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/Host/StringConvert.h" 23 #include "lldb/Interpreter/Args.h" 24 #include "lldb/Interpreter/CommandInterpreter.h" 25 #include "lldb/Interpreter/CommandOptionValidators.h" 26 #include "lldb/Interpreter/CommandReturnObject.h" 27 #include "lldb/Interpreter/OptionGroupFile.h" 28 #include "lldb/Interpreter/OptionGroupPlatform.h" 29 #include "lldb/Target/ExecutionContext.h" 30 #include "lldb/Target/Platform.h" 31 #include "lldb/Target/Process.h" 32 #include "lldb/Utility/Utils.h" 33 34 using namespace lldb; 35 using namespace lldb_private; 36 37 static mode_t 38 ParsePermissionString(const char* permissions) 39 { 40 if (strlen(permissions) != 9) 41 return (mode_t)(-1); 42 bool user_r,user_w,user_x, 43 group_r,group_w,group_x, 44 world_r,world_w,world_x; 45 46 user_r = (permissions[0] == 'r'); 47 user_w = (permissions[1] == 'w'); 48 user_x = (permissions[2] == 'x'); 49 50 group_r = (permissions[3] == 'r'); 51 group_w = (permissions[4] == 'w'); 52 group_x = (permissions[5] == 'x'); 53 54 world_r = (permissions[6] == 'r'); 55 world_w = (permissions[7] == 'w'); 56 world_x = (permissions[8] == 'x'); 57 58 mode_t user,group,world; 59 user = (user_r ? 4 : 0) | (user_w ? 2 : 0) | (user_x ? 1 : 0); 60 group = (group_r ? 4 : 0) | (group_w ? 2 : 0) | (group_x ? 1 : 0); 61 world = (world_r ? 4 : 0) | (world_w ? 2 : 0) | (world_x ? 1 : 0); 62 63 return user | group | world; 64 } 65 66 static OptionDefinition 67 g_permissions_options[] = 68 { 69 { LLDB_OPT_SET_ALL, false, "permissions-value", 'v', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypePermissionsNumber , "Give out the numeric value for permissions (e.g. 757)" }, 70 { LLDB_OPT_SET_ALL, false, "permissions-string", 's', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypePermissionsString , "Give out the string value for permissions (e.g. rwxr-xr--)." }, 71 { LLDB_OPT_SET_ALL, false, "user-read", 'r', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone , "Allow user to read." }, 72 { LLDB_OPT_SET_ALL, false, "user-write", 'w', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone , "Allow user to write." }, 73 { LLDB_OPT_SET_ALL, false, "user-exec", 'x', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone , "Allow user to execute." }, 74 75 { LLDB_OPT_SET_ALL, false, "group-read", 'R', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone , "Allow group to read." }, 76 { LLDB_OPT_SET_ALL, false, "group-write", 'W', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone , "Allow group to write." }, 77 { LLDB_OPT_SET_ALL, false, "group-exec", 'X', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone , "Allow group to execute." }, 78 79 { LLDB_OPT_SET_ALL, false, "world-read", 'd', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone , "Allow world to read." }, 80 { LLDB_OPT_SET_ALL, false, "world-write", 't', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone , "Allow world to write." }, 81 { LLDB_OPT_SET_ALL, false, "world-exec", 'e', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone , "Allow world to execute." }, 82 }; 83 84 class OptionPermissions : public lldb_private::OptionGroup 85 { 86 public: 87 OptionPermissions () 88 { 89 } 90 91 virtual 92 ~OptionPermissions () 93 { 94 } 95 96 virtual lldb_private::Error 97 SetOptionValue (CommandInterpreter &interpreter, 98 uint32_t option_idx, 99 const char *option_arg) 100 { 101 Error error; 102 char short_option = (char) GetDefinitions()[option_idx].short_option; 103 switch (short_option) 104 { 105 case 'v': 106 { 107 bool ok; 108 uint32_t perms = StringConvert::ToUInt32(option_arg, 777, 8, &ok); 109 if (!ok) 110 error.SetErrorStringWithFormat("invalid value for permissions: %s", option_arg); 111 else 112 m_permissions = perms; 113 } 114 break; 115 case 's': 116 { 117 mode_t perms = ParsePermissionString(option_arg); 118 if (perms == (mode_t)-1) 119 error.SetErrorStringWithFormat("invalid value for permissions: %s", option_arg); 120 else 121 m_permissions = perms; 122 } 123 case 'r': 124 m_permissions |= lldb::eFilePermissionsUserRead; 125 break; 126 case 'w': 127 m_permissions |= lldb::eFilePermissionsUserWrite; 128 break; 129 case 'x': 130 m_permissions |= lldb::eFilePermissionsUserExecute; 131 break; 132 case 'R': 133 m_permissions |= lldb::eFilePermissionsGroupRead; 134 break; 135 case 'W': 136 m_permissions |= lldb::eFilePermissionsGroupWrite; 137 break; 138 case 'X': 139 m_permissions |= lldb::eFilePermissionsGroupExecute; 140 break; 141 case 'd': 142 m_permissions |= lldb::eFilePermissionsWorldRead; 143 break; 144 case 't': 145 m_permissions |= lldb::eFilePermissionsWorldWrite; 146 break; 147 case 'e': 148 m_permissions |= lldb::eFilePermissionsWorldExecute; 149 break; 150 151 default: 152 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 153 break; 154 } 155 156 return error; 157 } 158 159 void 160 OptionParsingStarting (CommandInterpreter &interpreter) 161 { 162 m_permissions = 0; 163 } 164 165 virtual uint32_t 166 GetNumDefinitions () 167 { 168 return llvm::array_lengthof(g_permissions_options); 169 } 170 171 const lldb_private::OptionDefinition* 172 GetDefinitions () 173 { 174 return g_permissions_options; 175 } 176 177 // Instance variables to hold the values for command options. 178 179 uint32_t m_permissions; 180 private: 181 DISALLOW_COPY_AND_ASSIGN(OptionPermissions); 182 }; 183 184 //---------------------------------------------------------------------- 185 // "platform select <platform-name>" 186 //---------------------------------------------------------------------- 187 class CommandObjectPlatformSelect : public CommandObjectParsed 188 { 189 public: 190 CommandObjectPlatformSelect (CommandInterpreter &interpreter) : 191 CommandObjectParsed (interpreter, 192 "platform select", 193 "Create a platform if needed and select it as the current platform.", 194 "platform select <platform-name>", 195 0), 196 m_option_group (interpreter), 197 m_platform_options (false) // Don't include the "--platform" option by passing false 198 { 199 m_option_group.Append (&m_platform_options, LLDB_OPT_SET_ALL, 1); 200 m_option_group.Finalize(); 201 } 202 203 virtual 204 ~CommandObjectPlatformSelect () 205 { 206 } 207 208 virtual int 209 HandleCompletion (Args &input, 210 int &cursor_index, 211 int &cursor_char_position, 212 int match_start_point, 213 int max_return_elements, 214 bool &word_complete, 215 StringList &matches) 216 { 217 std::string completion_str (input.GetArgumentAtIndex(cursor_index)); 218 completion_str.erase (cursor_char_position); 219 220 CommandCompletions::PlatformPluginNames (m_interpreter, 221 completion_str.c_str(), 222 match_start_point, 223 max_return_elements, 224 NULL, 225 word_complete, 226 matches); 227 return matches.GetSize(); 228 } 229 230 virtual Options * 231 GetOptions () 232 { 233 return &m_option_group; 234 } 235 236 protected: 237 virtual bool 238 DoExecute (Args& args, CommandReturnObject &result) 239 { 240 if (args.GetArgumentCount() == 1) 241 { 242 const char *platform_name = args.GetArgumentAtIndex (0); 243 if (platform_name && platform_name[0]) 244 { 245 const bool select = true; 246 m_platform_options.SetPlatformName (platform_name); 247 Error error; 248 ArchSpec platform_arch; 249 PlatformSP platform_sp (m_platform_options.CreatePlatformWithOptions (m_interpreter, ArchSpec(), select, error, platform_arch)); 250 if (platform_sp) 251 { 252 m_interpreter.GetDebugger().GetPlatformList().SetSelectedPlatform(platform_sp); 253 254 platform_sp->GetStatus (result.GetOutputStream()); 255 result.SetStatus (eReturnStatusSuccessFinishResult); 256 } 257 else 258 { 259 result.AppendError(error.AsCString()); 260 result.SetStatus (eReturnStatusFailed); 261 } 262 } 263 else 264 { 265 result.AppendError ("invalid platform name"); 266 result.SetStatus (eReturnStatusFailed); 267 } 268 } 269 else 270 { 271 result.AppendError ("platform create takes a platform name as an argument\n"); 272 result.SetStatus (eReturnStatusFailed); 273 } 274 return result.Succeeded(); 275 } 276 277 OptionGroupOptions m_option_group; 278 OptionGroupPlatform m_platform_options; 279 }; 280 281 //---------------------------------------------------------------------- 282 // "platform list" 283 //---------------------------------------------------------------------- 284 class CommandObjectPlatformList : public CommandObjectParsed 285 { 286 public: 287 CommandObjectPlatformList (CommandInterpreter &interpreter) : 288 CommandObjectParsed (interpreter, 289 "platform list", 290 "List all platforms that are available.", 291 NULL, 292 0) 293 { 294 } 295 296 virtual 297 ~CommandObjectPlatformList () 298 { 299 } 300 301 protected: 302 virtual bool 303 DoExecute (Args& args, CommandReturnObject &result) 304 { 305 Stream &ostrm = result.GetOutputStream(); 306 ostrm.Printf("Available platforms:\n"); 307 308 PlatformSP host_platform_sp (Platform::GetHostPlatform()); 309 ostrm.Printf ("%s: %s\n", 310 host_platform_sp->GetPluginName().GetCString(), 311 host_platform_sp->GetDescription()); 312 313 uint32_t idx; 314 for (idx = 0; 1; ++idx) 315 { 316 const char *plugin_name = PluginManager::GetPlatformPluginNameAtIndex (idx); 317 if (plugin_name == NULL) 318 break; 319 const char *plugin_desc = PluginManager::GetPlatformPluginDescriptionAtIndex (idx); 320 if (plugin_desc == NULL) 321 break; 322 ostrm.Printf("%s: %s\n", plugin_name, plugin_desc); 323 } 324 325 if (idx == 0) 326 { 327 result.AppendError ("no platforms are available\n"); 328 result.SetStatus (eReturnStatusFailed); 329 } 330 else 331 result.SetStatus (eReturnStatusSuccessFinishResult); 332 return result.Succeeded(); 333 } 334 }; 335 336 //---------------------------------------------------------------------- 337 // "platform status" 338 //---------------------------------------------------------------------- 339 class CommandObjectPlatformStatus : public CommandObjectParsed 340 { 341 public: 342 CommandObjectPlatformStatus (CommandInterpreter &interpreter) : 343 CommandObjectParsed (interpreter, 344 "platform status", 345 "Display status for the currently selected platform.", 346 NULL, 347 0) 348 { 349 } 350 351 virtual 352 ~CommandObjectPlatformStatus () 353 { 354 } 355 356 protected: 357 virtual bool 358 DoExecute (Args& args, CommandReturnObject &result) 359 { 360 Stream &ostrm = result.GetOutputStream(); 361 362 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 363 PlatformSP platform_sp; 364 if (target) 365 { 366 platform_sp = target->GetPlatform(); 367 } 368 if (!platform_sp) 369 { 370 platform_sp = m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform(); 371 } 372 if (platform_sp) 373 { 374 platform_sp->GetStatus (ostrm); 375 result.SetStatus (eReturnStatusSuccessFinishResult); 376 } 377 else 378 { 379 result.AppendError ("no platform us currently selected\n"); 380 result.SetStatus (eReturnStatusFailed); 381 } 382 return result.Succeeded(); 383 } 384 }; 385 386 //---------------------------------------------------------------------- 387 // "platform connect <connect-url>" 388 //---------------------------------------------------------------------- 389 class CommandObjectPlatformConnect : public CommandObjectParsed 390 { 391 public: 392 CommandObjectPlatformConnect (CommandInterpreter &interpreter) : 393 CommandObjectParsed (interpreter, 394 "platform connect", 395 "Connect a platform by name to be the currently selected platform.", 396 "platform connect <connect-url>", 397 0) 398 { 399 } 400 401 virtual 402 ~CommandObjectPlatformConnect () 403 { 404 } 405 406 protected: 407 virtual bool 408 DoExecute (Args& args, CommandReturnObject &result) 409 { 410 Stream &ostrm = result.GetOutputStream(); 411 412 PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); 413 if (platform_sp) 414 { 415 Error error (platform_sp->ConnectRemote (args)); 416 if (error.Success()) 417 { 418 platform_sp->GetStatus (ostrm); 419 result.SetStatus (eReturnStatusSuccessFinishResult); 420 } 421 else 422 { 423 result.AppendErrorWithFormat ("%s\n", error.AsCString()); 424 result.SetStatus (eReturnStatusFailed); 425 } 426 } 427 else 428 { 429 result.AppendError ("no platform is currently selected\n"); 430 result.SetStatus (eReturnStatusFailed); 431 } 432 return result.Succeeded(); 433 } 434 435 virtual Options * 436 GetOptions () 437 { 438 PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); 439 OptionGroupOptions* m_platform_options = NULL; 440 if (platform_sp) 441 { 442 m_platform_options = platform_sp->GetConnectionOptions(m_interpreter); 443 if (m_platform_options != NULL && !m_platform_options->m_did_finalize) 444 m_platform_options->Finalize(); 445 } 446 return m_platform_options; 447 } 448 449 }; 450 451 //---------------------------------------------------------------------- 452 // "platform disconnect" 453 //---------------------------------------------------------------------- 454 class CommandObjectPlatformDisconnect : public CommandObjectParsed 455 { 456 public: 457 CommandObjectPlatformDisconnect (CommandInterpreter &interpreter) : 458 CommandObjectParsed (interpreter, 459 "platform disconnect", 460 "Disconnect a platform by name to be the currently selected platform.", 461 "platform disconnect", 462 0) 463 { 464 } 465 466 virtual 467 ~CommandObjectPlatformDisconnect () 468 { 469 } 470 471 protected: 472 virtual bool 473 DoExecute (Args& args, CommandReturnObject &result) 474 { 475 PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); 476 if (platform_sp) 477 { 478 if (args.GetArgumentCount() == 0) 479 { 480 Error error; 481 482 if (platform_sp->IsConnected()) 483 { 484 // Cache the instance name if there is one since we are 485 // about to disconnect and the name might go with it. 486 const char *hostname_cstr = platform_sp->GetHostname(); 487 std::string hostname; 488 if (hostname_cstr) 489 hostname.assign (hostname_cstr); 490 491 error = platform_sp->DisconnectRemote (); 492 if (error.Success()) 493 { 494 Stream &ostrm = result.GetOutputStream(); 495 if (hostname.empty()) 496 ostrm.Printf ("Disconnected from \"%s\"\n", platform_sp->GetPluginName().GetCString()); 497 else 498 ostrm.Printf ("Disconnected from \"%s\"\n", hostname.c_str()); 499 result.SetStatus (eReturnStatusSuccessFinishResult); 500 } 501 else 502 { 503 result.AppendErrorWithFormat ("%s", error.AsCString()); 504 result.SetStatus (eReturnStatusFailed); 505 } 506 } 507 else 508 { 509 // Not connected... 510 result.AppendErrorWithFormat ("not connected to '%s'", platform_sp->GetPluginName().GetCString()); 511 result.SetStatus (eReturnStatusFailed); 512 } 513 } 514 else 515 { 516 // Bad args 517 result.AppendError ("\"platform disconnect\" doesn't take any arguments"); 518 result.SetStatus (eReturnStatusFailed); 519 } 520 } 521 else 522 { 523 result.AppendError ("no platform is currently selected"); 524 result.SetStatus (eReturnStatusFailed); 525 } 526 return result.Succeeded(); 527 } 528 }; 529 530 //---------------------------------------------------------------------- 531 // "platform settings" 532 //---------------------------------------------------------------------- 533 class CommandObjectPlatformSettings : public CommandObjectParsed 534 { 535 public: 536 CommandObjectPlatformSettings (CommandInterpreter &interpreter) : 537 CommandObjectParsed (interpreter, 538 "platform settings", 539 "Set settings for the current target's platform, or for a platform by name.", 540 "platform settings", 541 0), 542 m_options (interpreter), 543 m_option_working_dir (LLDB_OPT_SET_1, false, "working-dir", 'w', 0, eArgTypePath, "The working directory for the platform.") 544 { 545 m_options.Append (&m_option_working_dir, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); 546 } 547 548 virtual 549 ~CommandObjectPlatformSettings () 550 { 551 } 552 553 protected: 554 virtual bool 555 DoExecute (Args& args, CommandReturnObject &result) 556 { 557 PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); 558 if (platform_sp) 559 { 560 if (m_option_working_dir.GetOptionValue().OptionWasSet()) 561 platform_sp->SetWorkingDirectory (ConstString(m_option_working_dir.GetOptionValue().GetCurrentValue().GetPath().c_str())); 562 } 563 else 564 { 565 result.AppendError ("no platform is currently selected"); 566 result.SetStatus (eReturnStatusFailed); 567 } 568 return result.Succeeded(); 569 } 570 571 virtual Options * 572 GetOptions () 573 { 574 if (m_options.DidFinalize() == false) 575 { 576 m_options.Append(new OptionPermissions()); 577 m_options.Finalize(); 578 } 579 return &m_options; 580 } 581 protected: 582 583 OptionGroupOptions m_options; 584 OptionGroupFile m_option_working_dir; 585 586 }; 587 588 589 //---------------------------------------------------------------------- 590 // "platform mkdir" 591 //---------------------------------------------------------------------- 592 class CommandObjectPlatformMkDir : public CommandObjectParsed 593 { 594 public: 595 CommandObjectPlatformMkDir (CommandInterpreter &interpreter) : 596 CommandObjectParsed (interpreter, 597 "platform mkdir", 598 "Make a new directory on the remote end.", 599 NULL, 600 0), 601 m_options(interpreter) 602 { 603 } 604 605 virtual 606 ~CommandObjectPlatformMkDir () 607 { 608 } 609 610 virtual bool 611 DoExecute (Args& args, CommandReturnObject &result) 612 { 613 PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); 614 if (platform_sp) 615 { 616 std::string cmd_line; 617 args.GetCommandString(cmd_line); 618 uint32_t mode; 619 const OptionPermissions* options_permissions = (const OptionPermissions*)m_options.GetGroupWithOption('r'); 620 if (options_permissions) 621 mode = options_permissions->m_permissions; 622 else 623 mode = lldb::eFilePermissionsUserRWX | lldb::eFilePermissionsGroupRWX | lldb::eFilePermissionsWorldRX; 624 Error error = platform_sp->MakeDirectory(cmd_line.c_str(), mode); 625 if (error.Success()) 626 { 627 result.SetStatus (eReturnStatusSuccessFinishResult); 628 } 629 else 630 { 631 result.AppendError(error.AsCString()); 632 result.SetStatus (eReturnStatusFailed); 633 } 634 } 635 else 636 { 637 result.AppendError ("no platform currently selected\n"); 638 result.SetStatus (eReturnStatusFailed); 639 } 640 return result.Succeeded(); 641 } 642 643 virtual Options * 644 GetOptions () 645 { 646 if (m_options.DidFinalize() == false) 647 { 648 m_options.Append(new OptionPermissions()); 649 m_options.Finalize(); 650 } 651 return &m_options; 652 } 653 OptionGroupOptions m_options; 654 655 }; 656 657 //---------------------------------------------------------------------- 658 // "platform fopen" 659 //---------------------------------------------------------------------- 660 class CommandObjectPlatformFOpen : public CommandObjectParsed 661 { 662 public: 663 CommandObjectPlatformFOpen (CommandInterpreter &interpreter) : 664 CommandObjectParsed (interpreter, 665 "platform file open", 666 "Open a file on the remote end.", 667 NULL, 668 0), 669 m_options(interpreter) 670 { 671 } 672 673 virtual 674 ~CommandObjectPlatformFOpen () 675 { 676 } 677 678 virtual bool 679 DoExecute (Args& args, CommandReturnObject &result) 680 { 681 PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); 682 if (platform_sp) 683 { 684 Error error; 685 std::string cmd_line; 686 args.GetCommandString(cmd_line); 687 mode_t perms; 688 const OptionPermissions* options_permissions = (const OptionPermissions*)m_options.GetGroupWithOption('r'); 689 if (options_permissions) 690 perms = options_permissions->m_permissions; 691 else 692 perms = lldb::eFilePermissionsUserRW | lldb::eFilePermissionsGroupRW | lldb::eFilePermissionsWorldRead; 693 lldb::user_id_t fd = platform_sp->OpenFile(FileSpec(cmd_line.c_str(),false), 694 File::eOpenOptionRead | File::eOpenOptionWrite | 695 File::eOpenOptionAppend | File::eOpenOptionCanCreate, 696 perms, 697 error); 698 if (error.Success()) 699 { 700 result.AppendMessageWithFormat("File Descriptor = %" PRIu64 "\n",fd); 701 result.SetStatus (eReturnStatusSuccessFinishResult); 702 } 703 else 704 { 705 result.AppendError(error.AsCString()); 706 result.SetStatus (eReturnStatusFailed); 707 } 708 } 709 else 710 { 711 result.AppendError ("no platform currently selected\n"); 712 result.SetStatus (eReturnStatusFailed); 713 } 714 return result.Succeeded(); 715 } 716 virtual Options * 717 GetOptions () 718 { 719 if (m_options.DidFinalize() == false) 720 { 721 m_options.Append(new OptionPermissions()); 722 m_options.Finalize(); 723 } 724 return &m_options; 725 } 726 OptionGroupOptions m_options; 727 }; 728 729 //---------------------------------------------------------------------- 730 // "platform fclose" 731 //---------------------------------------------------------------------- 732 class CommandObjectPlatformFClose : public CommandObjectParsed 733 { 734 public: 735 CommandObjectPlatformFClose (CommandInterpreter &interpreter) : 736 CommandObjectParsed (interpreter, 737 "platform file close", 738 "Close a file on the remote end.", 739 NULL, 740 0) 741 { 742 } 743 744 virtual 745 ~CommandObjectPlatformFClose () 746 { 747 } 748 749 virtual bool 750 DoExecute (Args& args, CommandReturnObject &result) 751 { 752 PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); 753 if (platform_sp) 754 { 755 std::string cmd_line; 756 args.GetCommandString(cmd_line); 757 const lldb::user_id_t fd = StringConvert::ToUInt64(cmd_line.c_str(), UINT64_MAX); 758 Error error; 759 bool success = platform_sp->CloseFile(fd, error); 760 if (success) 761 { 762 result.AppendMessageWithFormat("file %" PRIu64 " closed.\n", fd); 763 result.SetStatus (eReturnStatusSuccessFinishResult); 764 } 765 else 766 { 767 result.AppendError(error.AsCString()); 768 result.SetStatus (eReturnStatusFailed); 769 } 770 } 771 else 772 { 773 result.AppendError ("no platform currently selected\n"); 774 result.SetStatus (eReturnStatusFailed); 775 } 776 return result.Succeeded(); 777 } 778 }; 779 780 //---------------------------------------------------------------------- 781 // "platform fread" 782 //---------------------------------------------------------------------- 783 class CommandObjectPlatformFRead : public CommandObjectParsed 784 { 785 public: 786 CommandObjectPlatformFRead (CommandInterpreter &interpreter) : 787 CommandObjectParsed (interpreter, 788 "platform file read", 789 "Read data from a file on the remote end.", 790 NULL, 791 0), 792 m_options (interpreter) 793 { 794 } 795 796 virtual 797 ~CommandObjectPlatformFRead () 798 { 799 } 800 801 virtual bool 802 DoExecute (Args& args, CommandReturnObject &result) 803 { 804 PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); 805 if (platform_sp) 806 { 807 std::string cmd_line; 808 args.GetCommandString(cmd_line); 809 const lldb::user_id_t fd = StringConvert::ToUInt64(cmd_line.c_str(), UINT64_MAX); 810 std::string buffer(m_options.m_count,0); 811 Error error; 812 uint32_t retcode = platform_sp->ReadFile(fd, m_options.m_offset, &buffer[0], m_options.m_count, error); 813 result.AppendMessageWithFormat("Return = %d\n",retcode); 814 result.AppendMessageWithFormat("Data = \"%s\"\n",buffer.c_str()); 815 result.SetStatus (eReturnStatusSuccessFinishResult); 816 } 817 else 818 { 819 result.AppendError ("no platform currently selected\n"); 820 result.SetStatus (eReturnStatusFailed); 821 } 822 return result.Succeeded(); 823 } 824 virtual Options * 825 GetOptions () 826 { 827 return &m_options; 828 } 829 830 protected: 831 class CommandOptions : public Options 832 { 833 public: 834 835 CommandOptions (CommandInterpreter &interpreter) : 836 Options (interpreter) 837 { 838 } 839 840 virtual 841 ~CommandOptions () 842 { 843 } 844 845 virtual Error 846 SetOptionValue (uint32_t option_idx, const char *option_arg) 847 { 848 Error error; 849 char short_option = (char) m_getopt_table[option_idx].val; 850 bool success = false; 851 852 switch (short_option) 853 { 854 case 'o': 855 m_offset = StringConvert::ToUInt32(option_arg, 0, 0, &success); 856 if (!success) 857 error.SetErrorStringWithFormat("invalid offset: '%s'", option_arg); 858 break; 859 case 'c': 860 m_count = StringConvert::ToUInt32(option_arg, 0, 0, &success); 861 if (!success) 862 error.SetErrorStringWithFormat("invalid offset: '%s'", option_arg); 863 break; 864 865 default: 866 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 867 break; 868 } 869 870 return error; 871 } 872 873 void 874 OptionParsingStarting () 875 { 876 m_offset = 0; 877 m_count = 1; 878 } 879 880 const OptionDefinition* 881 GetDefinitions () 882 { 883 return g_option_table; 884 } 885 886 // Options table: Required for subclasses of Options. 887 888 static OptionDefinition g_option_table[]; 889 890 // Instance variables to hold the values for command options. 891 892 uint32_t m_offset; 893 uint32_t m_count; 894 }; 895 CommandOptions m_options; 896 }; 897 OptionDefinition 898 CommandObjectPlatformFRead::CommandOptions::g_option_table[] = 899 { 900 { LLDB_OPT_SET_1, false, "offset" , 'o', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeIndex , "Offset into the file at which to start reading." }, 901 { LLDB_OPT_SET_1, false, "count" , 'c', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeCount , "Number of bytes to read from the file." }, 902 { 0 , false, NULL , 0 , 0 , NULL, NULL, 0, eArgTypeNone , NULL } 903 }; 904 905 906 //---------------------------------------------------------------------- 907 // "platform fwrite" 908 //---------------------------------------------------------------------- 909 class CommandObjectPlatformFWrite : public CommandObjectParsed 910 { 911 public: 912 CommandObjectPlatformFWrite (CommandInterpreter &interpreter) : 913 CommandObjectParsed (interpreter, 914 "platform file write", 915 "Write data to a file on the remote end.", 916 NULL, 917 0), 918 m_options (interpreter) 919 { 920 } 921 922 virtual 923 ~CommandObjectPlatformFWrite () 924 { 925 } 926 927 virtual bool 928 DoExecute (Args& args, CommandReturnObject &result) 929 { 930 PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); 931 if (platform_sp) 932 { 933 std::string cmd_line; 934 args.GetCommandString(cmd_line); 935 Error error; 936 const lldb::user_id_t fd = StringConvert::ToUInt64(cmd_line.c_str(), UINT64_MAX); 937 uint32_t retcode = platform_sp->WriteFile (fd, 938 m_options.m_offset, 939 &m_options.m_data[0], 940 m_options.m_data.size(), 941 error); 942 result.AppendMessageWithFormat("Return = %d\n",retcode); 943 result.SetStatus (eReturnStatusSuccessFinishResult); 944 } 945 else 946 { 947 result.AppendError ("no platform currently selected\n"); 948 result.SetStatus (eReturnStatusFailed); 949 } 950 return result.Succeeded(); 951 } 952 virtual Options * 953 GetOptions () 954 { 955 return &m_options; 956 } 957 958 protected: 959 class CommandOptions : public Options 960 { 961 public: 962 963 CommandOptions (CommandInterpreter &interpreter) : 964 Options (interpreter) 965 { 966 } 967 968 virtual 969 ~CommandOptions () 970 { 971 } 972 973 virtual Error 974 SetOptionValue (uint32_t option_idx, const char *option_arg) 975 { 976 Error error; 977 char short_option = (char) m_getopt_table[option_idx].val; 978 bool success = false; 979 980 switch (short_option) 981 { 982 case 'o': 983 m_offset = StringConvert::ToUInt32(option_arg, 0, 0, &success); 984 if (!success) 985 error.SetErrorStringWithFormat("invalid offset: '%s'", option_arg); 986 break; 987 case 'd': 988 m_data.assign(option_arg); 989 break; 990 991 default: 992 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 993 break; 994 } 995 996 return error; 997 } 998 999 void 1000 OptionParsingStarting () 1001 { 1002 m_offset = 0; 1003 m_data.clear(); 1004 } 1005 1006 const OptionDefinition* 1007 GetDefinitions () 1008 { 1009 return g_option_table; 1010 } 1011 1012 // Options table: Required for subclasses of Options. 1013 1014 static OptionDefinition g_option_table[]; 1015 1016 // Instance variables to hold the values for command options. 1017 1018 uint32_t m_offset; 1019 std::string m_data; 1020 }; 1021 CommandOptions m_options; 1022 }; 1023 OptionDefinition 1024 CommandObjectPlatformFWrite::CommandOptions::g_option_table[] = 1025 { 1026 { LLDB_OPT_SET_1, false, "offset" , 'o', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeIndex , "Offset into the file at which to start reading." }, 1027 { LLDB_OPT_SET_1, false, "data" , 'd', OptionParser::eRequiredArgument , NULL, NULL, 0, eArgTypeValue , "Text to write to the file." }, 1028 { 0 , false, NULL , 0 , 0 , NULL, NULL, 0, eArgTypeNone , NULL } 1029 }; 1030 1031 class CommandObjectPlatformFile : public CommandObjectMultiword 1032 { 1033 public: 1034 //------------------------------------------------------------------ 1035 // Constructors and Destructors 1036 //------------------------------------------------------------------ 1037 CommandObjectPlatformFile (CommandInterpreter &interpreter) : 1038 CommandObjectMultiword (interpreter, 1039 "platform file", 1040 "A set of commands to manage file access through a platform", 1041 "platform file [open|close|read|write] ...") 1042 { 1043 LoadSubCommand ("open", CommandObjectSP (new CommandObjectPlatformFOpen (interpreter))); 1044 LoadSubCommand ("close", CommandObjectSP (new CommandObjectPlatformFClose (interpreter))); 1045 LoadSubCommand ("read", CommandObjectSP (new CommandObjectPlatformFRead (interpreter))); 1046 LoadSubCommand ("write", CommandObjectSP (new CommandObjectPlatformFWrite (interpreter))); 1047 } 1048 1049 virtual 1050 ~CommandObjectPlatformFile () 1051 { 1052 } 1053 1054 private: 1055 //------------------------------------------------------------------ 1056 // For CommandObjectPlatform only 1057 //------------------------------------------------------------------ 1058 DISALLOW_COPY_AND_ASSIGN (CommandObjectPlatformFile); 1059 }; 1060 1061 //---------------------------------------------------------------------- 1062 // "platform get-file remote-file-path host-file-path" 1063 //---------------------------------------------------------------------- 1064 class CommandObjectPlatformGetFile : public CommandObjectParsed 1065 { 1066 public: 1067 CommandObjectPlatformGetFile (CommandInterpreter &interpreter) : 1068 CommandObjectParsed (interpreter, 1069 "platform get-file", 1070 "Transfer a file from the remote end to the local host.", 1071 "platform get-file <remote-file-spec> <local-file-spec>", 1072 0) 1073 { 1074 SetHelpLong( 1075 "Examples: \n\ 1076 \n\ 1077 platform get-file /the/remote/file/path /the/local/file/path\n\ 1078 # Transfer a file from the remote end with file path /the/remote/file/path to the local host.\n"); 1079 1080 CommandArgumentEntry arg1, arg2; 1081 CommandArgumentData file_arg_remote, file_arg_host; 1082 1083 // Define the first (and only) variant of this arg. 1084 file_arg_remote.arg_type = eArgTypeFilename; 1085 file_arg_remote.arg_repetition = eArgRepeatPlain; 1086 // There is only one variant this argument could be; put it into the argument entry. 1087 arg1.push_back (file_arg_remote); 1088 1089 // Define the second (and only) variant of this arg. 1090 file_arg_host.arg_type = eArgTypeFilename; 1091 file_arg_host.arg_repetition = eArgRepeatPlain; 1092 // There is only one variant this argument could be; put it into the argument entry. 1093 arg2.push_back (file_arg_host); 1094 1095 // Push the data for the first and the second arguments into the m_arguments vector. 1096 m_arguments.push_back (arg1); 1097 m_arguments.push_back (arg2); 1098 } 1099 1100 virtual 1101 ~CommandObjectPlatformGetFile () 1102 { 1103 } 1104 1105 virtual bool 1106 DoExecute (Args& args, CommandReturnObject &result) 1107 { 1108 // If the number of arguments is incorrect, issue an error message. 1109 if (args.GetArgumentCount() != 2) 1110 { 1111 result.GetErrorStream().Printf("error: required arguments missing; specify both the source and destination file paths\n"); 1112 result.SetStatus(eReturnStatusFailed); 1113 return false; 1114 } 1115 1116 PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); 1117 if (platform_sp) 1118 { 1119 const char *remote_file_path = args.GetArgumentAtIndex(0); 1120 const char *local_file_path = args.GetArgumentAtIndex(1); 1121 Error error = platform_sp->GetFile(FileSpec(remote_file_path, false), 1122 FileSpec(local_file_path, false)); 1123 if (error.Success()) 1124 { 1125 result.AppendMessageWithFormat("successfully get-file from %s (remote) to %s (host)\n", 1126 remote_file_path, local_file_path); 1127 result.SetStatus (eReturnStatusSuccessFinishResult); 1128 } 1129 else 1130 { 1131 result.AppendMessageWithFormat("get-file failed: %s\n", error.AsCString()); 1132 result.SetStatus (eReturnStatusFailed); 1133 } 1134 } 1135 else 1136 { 1137 result.AppendError ("no platform currently selected\n"); 1138 result.SetStatus (eReturnStatusFailed); 1139 } 1140 return result.Succeeded(); 1141 } 1142 }; 1143 1144 //---------------------------------------------------------------------- 1145 // "platform get-size remote-file-path" 1146 //---------------------------------------------------------------------- 1147 class CommandObjectPlatformGetSize : public CommandObjectParsed 1148 { 1149 public: 1150 CommandObjectPlatformGetSize (CommandInterpreter &interpreter) : 1151 CommandObjectParsed (interpreter, 1152 "platform get-size", 1153 "Get the file size from the remote end.", 1154 "platform get-size <remote-file-spec>", 1155 0) 1156 { 1157 SetHelpLong( 1158 "Examples: \n\ 1159 \n\ 1160 platform get-size /the/remote/file/path\n\ 1161 # Get the file size from the remote end with path /the/remote/file/path.\n"); 1162 1163 CommandArgumentEntry arg1; 1164 CommandArgumentData file_arg_remote; 1165 1166 // Define the first (and only) variant of this arg. 1167 file_arg_remote.arg_type = eArgTypeFilename; 1168 file_arg_remote.arg_repetition = eArgRepeatPlain; 1169 // There is only one variant this argument could be; put it into the argument entry. 1170 arg1.push_back (file_arg_remote); 1171 1172 // Push the data for the first argument into the m_arguments vector. 1173 m_arguments.push_back (arg1); 1174 } 1175 1176 virtual 1177 ~CommandObjectPlatformGetSize () 1178 { 1179 } 1180 1181 virtual bool 1182 DoExecute (Args& args, CommandReturnObject &result) 1183 { 1184 // If the number of arguments is incorrect, issue an error message. 1185 if (args.GetArgumentCount() != 1) 1186 { 1187 result.GetErrorStream().Printf("error: required argument missing; specify the source file path as the only argument\n"); 1188 result.SetStatus(eReturnStatusFailed); 1189 return false; 1190 } 1191 1192 PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); 1193 if (platform_sp) 1194 { 1195 std::string remote_file_path(args.GetArgumentAtIndex(0)); 1196 user_id_t size = platform_sp->GetFileSize(FileSpec(remote_file_path.c_str(), false)); 1197 if (size != UINT64_MAX) 1198 { 1199 result.AppendMessageWithFormat("File size of %s (remote): %" PRIu64 "\n", remote_file_path.c_str(), size); 1200 result.SetStatus (eReturnStatusSuccessFinishResult); 1201 } 1202 else 1203 { 1204 result.AppendMessageWithFormat("Eroor getting file size of %s (remote)\n", remote_file_path.c_str()); 1205 result.SetStatus (eReturnStatusFailed); 1206 } 1207 } 1208 else 1209 { 1210 result.AppendError ("no platform currently selected\n"); 1211 result.SetStatus (eReturnStatusFailed); 1212 } 1213 return result.Succeeded(); 1214 } 1215 }; 1216 1217 //---------------------------------------------------------------------- 1218 // "platform put-file" 1219 //---------------------------------------------------------------------- 1220 class CommandObjectPlatformPutFile : public CommandObjectParsed 1221 { 1222 public: 1223 CommandObjectPlatformPutFile (CommandInterpreter &interpreter) : 1224 CommandObjectParsed (interpreter, 1225 "platform put-file", 1226 "Transfer a file from this system to the remote end.", 1227 NULL, 1228 0) 1229 { 1230 } 1231 1232 virtual 1233 ~CommandObjectPlatformPutFile () 1234 { 1235 } 1236 1237 virtual bool 1238 DoExecute (Args& args, CommandReturnObject &result) 1239 { 1240 const char* src = args.GetArgumentAtIndex(0); 1241 const char* dst = args.GetArgumentAtIndex(1); 1242 1243 FileSpec src_fs(src, true); 1244 FileSpec dst_fs(dst, false); 1245 1246 PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); 1247 if (platform_sp) 1248 { 1249 Error error (platform_sp->PutFile(src_fs, dst_fs)); 1250 if (error.Success()) 1251 { 1252 result.SetStatus (eReturnStatusSuccessFinishNoResult); 1253 } 1254 else 1255 { 1256 result.AppendError (error.AsCString()); 1257 result.SetStatus (eReturnStatusFailed); 1258 } 1259 } 1260 else 1261 { 1262 result.AppendError ("no platform currently selected\n"); 1263 result.SetStatus (eReturnStatusFailed); 1264 } 1265 return result.Succeeded(); 1266 } 1267 }; 1268 1269 //---------------------------------------------------------------------- 1270 // "platform process launch" 1271 //---------------------------------------------------------------------- 1272 class CommandObjectPlatformProcessLaunch : public CommandObjectParsed 1273 { 1274 public: 1275 CommandObjectPlatformProcessLaunch (CommandInterpreter &interpreter) : 1276 CommandObjectParsed (interpreter, 1277 "platform process launch", 1278 "Launch a new process on a remote platform.", 1279 "platform process launch program", 1280 eFlagRequiresTarget | eFlagTryTargetAPILock), 1281 m_options (interpreter) 1282 { 1283 } 1284 1285 virtual 1286 ~CommandObjectPlatformProcessLaunch () 1287 { 1288 } 1289 1290 virtual Options * 1291 GetOptions () 1292 { 1293 return &m_options; 1294 } 1295 1296 protected: 1297 virtual bool 1298 DoExecute (Args& args, CommandReturnObject &result) 1299 { 1300 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 1301 PlatformSP platform_sp; 1302 if (target) 1303 { 1304 platform_sp = target->GetPlatform(); 1305 } 1306 if (!platform_sp) 1307 { 1308 platform_sp = m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform(); 1309 } 1310 1311 if (platform_sp) 1312 { 1313 Error error; 1314 const size_t argc = args.GetArgumentCount(); 1315 Target *target = m_exe_ctx.GetTargetPtr(); 1316 Module *exe_module = target->GetExecutableModulePointer(); 1317 if (exe_module) 1318 { 1319 m_options.launch_info.GetExecutableFile () = exe_module->GetFileSpec(); 1320 char exe_path[PATH_MAX]; 1321 if (m_options.launch_info.GetExecutableFile ().GetPath (exe_path, sizeof(exe_path))) 1322 m_options.launch_info.GetArguments().AppendArgument (exe_path); 1323 m_options.launch_info.GetArchitecture() = exe_module->GetArchitecture(); 1324 } 1325 1326 if (argc > 0) 1327 { 1328 if (m_options.launch_info.GetExecutableFile ()) 1329 { 1330 // We already have an executable file, so we will use this 1331 // and all arguments to this function are extra arguments 1332 m_options.launch_info.GetArguments().AppendArguments (args); 1333 } 1334 else 1335 { 1336 // We don't have any file yet, so the first argument is our 1337 // executable, and the rest are program arguments 1338 const bool first_arg_is_executable = true; 1339 m_options.launch_info.SetArguments (args, first_arg_is_executable); 1340 } 1341 } 1342 1343 if (m_options.launch_info.GetExecutableFile ()) 1344 { 1345 Debugger &debugger = m_interpreter.GetDebugger(); 1346 1347 if (argc == 0) 1348 target->GetRunArguments(m_options.launch_info.GetArguments()); 1349 1350 ProcessSP process_sp (platform_sp->DebugProcess (m_options.launch_info, 1351 debugger, 1352 target, 1353 error)); 1354 if (process_sp && process_sp->IsAlive()) 1355 { 1356 result.SetStatus (eReturnStatusSuccessFinishNoResult); 1357 return true; 1358 } 1359 1360 if (error.Success()) 1361 result.AppendError ("process launch failed"); 1362 else 1363 result.AppendError (error.AsCString()); 1364 result.SetStatus (eReturnStatusFailed); 1365 } 1366 else 1367 { 1368 result.AppendError ("'platform process launch' uses the current target file and arguments, or the executable and its arguments can be specified in this command"); 1369 result.SetStatus (eReturnStatusFailed); 1370 return false; 1371 } 1372 } 1373 else 1374 { 1375 result.AppendError ("no platform is selected\n"); 1376 } 1377 return result.Succeeded(); 1378 } 1379 1380 protected: 1381 ProcessLaunchCommandOptions m_options; 1382 }; 1383 1384 1385 1386 //---------------------------------------------------------------------- 1387 // "platform process list" 1388 //---------------------------------------------------------------------- 1389 class CommandObjectPlatformProcessList : public CommandObjectParsed 1390 { 1391 public: 1392 CommandObjectPlatformProcessList (CommandInterpreter &interpreter) : 1393 CommandObjectParsed (interpreter, 1394 "platform process list", 1395 "List processes on a remote platform by name, pid, or many other matching attributes.", 1396 "platform process list", 1397 0), 1398 m_options (interpreter) 1399 { 1400 } 1401 1402 virtual 1403 ~CommandObjectPlatformProcessList () 1404 { 1405 } 1406 1407 virtual Options * 1408 GetOptions () 1409 { 1410 return &m_options; 1411 } 1412 1413 protected: 1414 virtual bool 1415 DoExecute (Args& args, CommandReturnObject &result) 1416 { 1417 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 1418 PlatformSP platform_sp; 1419 if (target) 1420 { 1421 platform_sp = target->GetPlatform(); 1422 } 1423 if (!platform_sp) 1424 { 1425 platform_sp = m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform(); 1426 } 1427 1428 if (platform_sp) 1429 { 1430 Error error; 1431 if (args.GetArgumentCount() == 0) 1432 { 1433 1434 if (platform_sp) 1435 { 1436 Stream &ostrm = result.GetOutputStream(); 1437 1438 lldb::pid_t pid = m_options.match_info.GetProcessInfo().GetProcessID(); 1439 if (pid != LLDB_INVALID_PROCESS_ID) 1440 { 1441 ProcessInstanceInfo proc_info; 1442 if (platform_sp->GetProcessInfo (pid, proc_info)) 1443 { 1444 ProcessInstanceInfo::DumpTableHeader (ostrm, platform_sp.get(), m_options.show_args, m_options.verbose); 1445 proc_info.DumpAsTableRow(ostrm, platform_sp.get(), m_options.show_args, m_options.verbose); 1446 result.SetStatus (eReturnStatusSuccessFinishResult); 1447 } 1448 else 1449 { 1450 result.AppendErrorWithFormat ("no process found with pid = %" PRIu64 "\n", pid); 1451 result.SetStatus (eReturnStatusFailed); 1452 } 1453 } 1454 else 1455 { 1456 ProcessInstanceInfoList proc_infos; 1457 const uint32_t matches = platform_sp->FindProcesses (m_options.match_info, proc_infos); 1458 const char *match_desc = NULL; 1459 const char *match_name = m_options.match_info.GetProcessInfo().GetName(); 1460 if (match_name && match_name[0]) 1461 { 1462 switch (m_options.match_info.GetNameMatchType()) 1463 { 1464 case eNameMatchIgnore: break; 1465 case eNameMatchEquals: match_desc = "matched"; break; 1466 case eNameMatchContains: match_desc = "contained"; break; 1467 case eNameMatchStartsWith: match_desc = "started with"; break; 1468 case eNameMatchEndsWith: match_desc = "ended with"; break; 1469 case eNameMatchRegularExpression: match_desc = "matched the regular expression"; break; 1470 } 1471 } 1472 1473 if (matches == 0) 1474 { 1475 if (match_desc) 1476 result.AppendErrorWithFormat ("no processes were found that %s \"%s\" on the \"%s\" platform\n", 1477 match_desc, 1478 match_name, 1479 platform_sp->GetPluginName().GetCString()); 1480 else 1481 result.AppendErrorWithFormat ("no processes were found on the \"%s\" platform\n", platform_sp->GetPluginName().GetCString()); 1482 result.SetStatus (eReturnStatusFailed); 1483 } 1484 else 1485 { 1486 result.AppendMessageWithFormat ("%u matching process%s found on \"%s\"", 1487 matches, 1488 matches > 1 ? "es were" : " was", 1489 platform_sp->GetName().GetCString()); 1490 if (match_desc) 1491 result.AppendMessageWithFormat (" whose name %s \"%s\"", 1492 match_desc, 1493 match_name); 1494 result.AppendMessageWithFormat ("\n"); 1495 ProcessInstanceInfo::DumpTableHeader (ostrm, platform_sp.get(), m_options.show_args, m_options.verbose); 1496 for (uint32_t i=0; i<matches; ++i) 1497 { 1498 proc_infos.GetProcessInfoAtIndex(i).DumpAsTableRow(ostrm, platform_sp.get(), m_options.show_args, m_options.verbose); 1499 } 1500 } 1501 } 1502 } 1503 } 1504 else 1505 { 1506 result.AppendError ("invalid args: process list takes only options\n"); 1507 result.SetStatus (eReturnStatusFailed); 1508 } 1509 } 1510 else 1511 { 1512 result.AppendError ("no platform is selected\n"); 1513 result.SetStatus (eReturnStatusFailed); 1514 } 1515 return result.Succeeded(); 1516 } 1517 1518 class CommandOptions : public Options 1519 { 1520 public: 1521 1522 CommandOptions (CommandInterpreter &interpreter) : 1523 Options (interpreter), 1524 match_info () 1525 { 1526 } 1527 1528 virtual 1529 ~CommandOptions () 1530 { 1531 } 1532 1533 virtual Error 1534 SetOptionValue (uint32_t option_idx, const char *option_arg) 1535 { 1536 Error error; 1537 const int short_option = m_getopt_table[option_idx].val; 1538 bool success = false; 1539 1540 switch (short_option) 1541 { 1542 case 'p': 1543 match_info.GetProcessInfo().SetProcessID (StringConvert::ToUInt32 (option_arg, LLDB_INVALID_PROCESS_ID, 0, &success)); 1544 if (!success) 1545 error.SetErrorStringWithFormat("invalid process ID string: '%s'", option_arg); 1546 break; 1547 1548 case 'P': 1549 match_info.GetProcessInfo().SetParentProcessID (StringConvert::ToUInt32 (option_arg, LLDB_INVALID_PROCESS_ID, 0, &success)); 1550 if (!success) 1551 error.SetErrorStringWithFormat("invalid parent process ID string: '%s'", option_arg); 1552 break; 1553 1554 case 'u': 1555 match_info.GetProcessInfo().SetUserID (StringConvert::ToUInt32 (option_arg, UINT32_MAX, 0, &success)); 1556 if (!success) 1557 error.SetErrorStringWithFormat("invalid user ID string: '%s'", option_arg); 1558 break; 1559 1560 case 'U': 1561 match_info.GetProcessInfo().SetEffectiveUserID (StringConvert::ToUInt32 (option_arg, UINT32_MAX, 0, &success)); 1562 if (!success) 1563 error.SetErrorStringWithFormat("invalid effective user ID string: '%s'", option_arg); 1564 break; 1565 1566 case 'g': 1567 match_info.GetProcessInfo().SetGroupID (StringConvert::ToUInt32 (option_arg, UINT32_MAX, 0, &success)); 1568 if (!success) 1569 error.SetErrorStringWithFormat("invalid group ID string: '%s'", option_arg); 1570 break; 1571 1572 case 'G': 1573 match_info.GetProcessInfo().SetEffectiveGroupID (StringConvert::ToUInt32 (option_arg, UINT32_MAX, 0, &success)); 1574 if (!success) 1575 error.SetErrorStringWithFormat("invalid effective group ID string: '%s'", option_arg); 1576 break; 1577 1578 case 'a': 1579 match_info.GetProcessInfo().GetArchitecture().SetTriple (option_arg, m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform().get()); 1580 break; 1581 1582 case 'n': 1583 match_info.GetProcessInfo().GetExecutableFile().SetFile (option_arg, false); 1584 match_info.SetNameMatchType (eNameMatchEquals); 1585 break; 1586 1587 case 'e': 1588 match_info.GetProcessInfo().GetExecutableFile().SetFile (option_arg, false); 1589 match_info.SetNameMatchType (eNameMatchEndsWith); 1590 break; 1591 1592 case 's': 1593 match_info.GetProcessInfo().GetExecutableFile().SetFile (option_arg, false); 1594 match_info.SetNameMatchType (eNameMatchStartsWith); 1595 break; 1596 1597 case 'c': 1598 match_info.GetProcessInfo().GetExecutableFile().SetFile (option_arg, false); 1599 match_info.SetNameMatchType (eNameMatchContains); 1600 break; 1601 1602 case 'r': 1603 match_info.GetProcessInfo().GetExecutableFile().SetFile (option_arg, false); 1604 match_info.SetNameMatchType (eNameMatchRegularExpression); 1605 break; 1606 1607 case 'A': 1608 show_args = true; 1609 break; 1610 1611 case 'v': 1612 verbose = true; 1613 break; 1614 1615 default: 1616 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 1617 break; 1618 } 1619 1620 return error; 1621 } 1622 1623 void 1624 OptionParsingStarting () 1625 { 1626 match_info.Clear(); 1627 show_args = false; 1628 verbose = false; 1629 } 1630 1631 const OptionDefinition* 1632 GetDefinitions () 1633 { 1634 return g_option_table; 1635 } 1636 1637 // Options table: Required for subclasses of Options. 1638 1639 static OptionDefinition g_option_table[]; 1640 1641 // Instance variables to hold the values for command options. 1642 1643 ProcessInstanceInfoMatch match_info; 1644 bool show_args; 1645 bool verbose; 1646 }; 1647 CommandOptions m_options; 1648 }; 1649 1650 namespace 1651 { 1652 PosixPlatformCommandOptionValidator g_posix_validator; 1653 } 1654 1655 OptionDefinition 1656 CommandObjectPlatformProcessList::CommandOptions::g_option_table[] = 1657 { 1658 { LLDB_OPT_SET_1 , false, "pid" , 'p', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypePid , "List the process info for a specific process ID." }, 1659 { LLDB_OPT_SET_2 , true , "name" , 'n', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeProcessName , "Find processes with executable basenames that match a string." }, 1660 { LLDB_OPT_SET_3 , true , "ends-with" , 'e', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeProcessName , "Find processes with executable basenames that end with a string." }, 1661 { LLDB_OPT_SET_4 , true , "starts-with", 's', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeProcessName , "Find processes with executable basenames that start with a string." }, 1662 { LLDB_OPT_SET_5 , true , "contains" , 'c', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeProcessName , "Find processes with executable basenames that contain a string." }, 1663 { LLDB_OPT_SET_6 , true , "regex" , 'r', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeRegularExpression, "Find processes with executable basenames that match a regular expression." }, 1664 { LLDB_OPT_SET_FROM_TO(2, 6), false, "parent" , 'P', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypePid , "Find processes that have a matching parent process ID." }, 1665 { LLDB_OPT_SET_FROM_TO(2, 6), false, "uid" , 'u', OptionParser::eRequiredArgument, &g_posix_validator, NULL, 0, eArgTypeUnsignedInteger , "Find processes that have a matching user ID." }, 1666 { LLDB_OPT_SET_FROM_TO(2, 6), false, "euid" , 'U', OptionParser::eRequiredArgument, &g_posix_validator, NULL, 0, eArgTypeUnsignedInteger , "Find processes that have a matching effective user ID." }, 1667 { LLDB_OPT_SET_FROM_TO(2, 6), false, "gid" , 'g', OptionParser::eRequiredArgument, &g_posix_validator, NULL, 0, eArgTypeUnsignedInteger , "Find processes that have a matching group ID." }, 1668 { LLDB_OPT_SET_FROM_TO(2, 6), false, "egid" , 'G', OptionParser::eRequiredArgument, &g_posix_validator, NULL, 0, eArgTypeUnsignedInteger , "Find processes that have a matching effective group ID." }, 1669 { LLDB_OPT_SET_FROM_TO(2, 6), false, "arch" , 'a', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeArchitecture , "Find processes that have a matching architecture." }, 1670 { LLDB_OPT_SET_FROM_TO(1, 6), false, "show-args" , 'A', OptionParser::eNoArgument , NULL, NULL, 0, eArgTypeNone , "Show process arguments instead of the process executable basename." }, 1671 { LLDB_OPT_SET_FROM_TO(1, 6), false, "verbose" , 'v', OptionParser::eNoArgument , NULL, NULL, 0, eArgTypeNone , "Enable verbose output." }, 1672 { 0 , false, NULL , 0 , 0 , NULL, NULL, 0, eArgTypeNone , NULL } 1673 }; 1674 1675 //---------------------------------------------------------------------- 1676 // "platform process info" 1677 //---------------------------------------------------------------------- 1678 class CommandObjectPlatformProcessInfo : public CommandObjectParsed 1679 { 1680 public: 1681 CommandObjectPlatformProcessInfo (CommandInterpreter &interpreter) : 1682 CommandObjectParsed (interpreter, 1683 "platform process info", 1684 "Get detailed information for one or more process by process ID.", 1685 "platform process info <pid> [<pid> <pid> ...]", 1686 0) 1687 { 1688 CommandArgumentEntry arg; 1689 CommandArgumentData pid_args; 1690 1691 // Define the first (and only) variant of this arg. 1692 pid_args.arg_type = eArgTypePid; 1693 pid_args.arg_repetition = eArgRepeatStar; 1694 1695 // There is only one variant this argument could be; put it into the argument entry. 1696 arg.push_back (pid_args); 1697 1698 // Push the data for the first argument into the m_arguments vector. 1699 m_arguments.push_back (arg); 1700 } 1701 1702 virtual 1703 ~CommandObjectPlatformProcessInfo () 1704 { 1705 } 1706 1707 protected: 1708 virtual bool 1709 DoExecute (Args& args, CommandReturnObject &result) 1710 { 1711 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 1712 PlatformSP platform_sp; 1713 if (target) 1714 { 1715 platform_sp = target->GetPlatform(); 1716 } 1717 if (!platform_sp) 1718 { 1719 platform_sp = m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform(); 1720 } 1721 1722 if (platform_sp) 1723 { 1724 const size_t argc = args.GetArgumentCount(); 1725 if (argc > 0) 1726 { 1727 Error error; 1728 1729 if (platform_sp->IsConnected()) 1730 { 1731 Stream &ostrm = result.GetOutputStream(); 1732 bool success; 1733 for (size_t i=0; i<argc; ++ i) 1734 { 1735 const char *arg = args.GetArgumentAtIndex(i); 1736 lldb::pid_t pid = StringConvert::ToUInt32 (arg, LLDB_INVALID_PROCESS_ID, 0, &success); 1737 if (success) 1738 { 1739 ProcessInstanceInfo proc_info; 1740 if (platform_sp->GetProcessInfo (pid, proc_info)) 1741 { 1742 ostrm.Printf ("Process information for process %" PRIu64 ":\n", pid); 1743 proc_info.Dump (ostrm, platform_sp.get()); 1744 } 1745 else 1746 { 1747 ostrm.Printf ("error: no process information is available for process %" PRIu64 "\n", pid); 1748 } 1749 ostrm.EOL(); 1750 } 1751 else 1752 { 1753 result.AppendErrorWithFormat ("invalid process ID argument '%s'", arg); 1754 result.SetStatus (eReturnStatusFailed); 1755 break; 1756 } 1757 } 1758 } 1759 else 1760 { 1761 // Not connected... 1762 result.AppendErrorWithFormat ("not connected to '%s'", platform_sp->GetPluginName().GetCString()); 1763 result.SetStatus (eReturnStatusFailed); 1764 } 1765 } 1766 else 1767 { 1768 // No args 1769 result.AppendError ("one or more process id(s) must be specified"); 1770 result.SetStatus (eReturnStatusFailed); 1771 } 1772 } 1773 else 1774 { 1775 result.AppendError ("no platform is currently selected"); 1776 result.SetStatus (eReturnStatusFailed); 1777 } 1778 return result.Succeeded(); 1779 } 1780 }; 1781 1782 class CommandObjectPlatformProcessAttach : public CommandObjectParsed 1783 { 1784 public: 1785 1786 class CommandOptions : public Options 1787 { 1788 public: 1789 1790 CommandOptions (CommandInterpreter &interpreter) : 1791 Options(interpreter) 1792 { 1793 // Keep default values of all options in one place: OptionParsingStarting () 1794 OptionParsingStarting (); 1795 } 1796 1797 ~CommandOptions () 1798 { 1799 } 1800 1801 Error 1802 SetOptionValue (uint32_t option_idx, const char *option_arg) 1803 { 1804 Error error; 1805 char short_option = (char) m_getopt_table[option_idx].val; 1806 bool success = false; 1807 switch (short_option) 1808 { 1809 case 'p': 1810 { 1811 lldb::pid_t pid = StringConvert::ToUInt32 (option_arg, LLDB_INVALID_PROCESS_ID, 0, &success); 1812 if (!success || pid == LLDB_INVALID_PROCESS_ID) 1813 { 1814 error.SetErrorStringWithFormat("invalid process ID '%s'", option_arg); 1815 } 1816 else 1817 { 1818 attach_info.SetProcessID (pid); 1819 } 1820 } 1821 break; 1822 1823 case 'P': 1824 attach_info.SetProcessPluginName (option_arg); 1825 break; 1826 1827 case 'n': 1828 attach_info.GetExecutableFile().SetFile(option_arg, false); 1829 break; 1830 1831 case 'w': 1832 attach_info.SetWaitForLaunch(true); 1833 break; 1834 1835 default: 1836 error.SetErrorStringWithFormat("invalid short option character '%c'", short_option); 1837 break; 1838 } 1839 return error; 1840 } 1841 1842 void 1843 OptionParsingStarting () 1844 { 1845 attach_info.Clear(); 1846 } 1847 1848 const OptionDefinition* 1849 GetDefinitions () 1850 { 1851 return g_option_table; 1852 } 1853 1854 virtual bool 1855 HandleOptionArgumentCompletion (Args &input, 1856 int cursor_index, 1857 int char_pos, 1858 OptionElementVector &opt_element_vector, 1859 int opt_element_index, 1860 int match_start_point, 1861 int max_return_elements, 1862 bool &word_complete, 1863 StringList &matches) 1864 { 1865 int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos; 1866 int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index; 1867 1868 // We are only completing the name option for now... 1869 1870 const OptionDefinition *opt_defs = GetDefinitions(); 1871 if (opt_defs[opt_defs_index].short_option == 'n') 1872 { 1873 // Are we in the name? 1874 1875 // Look to see if there is a -P argument provided, and if so use that plugin, otherwise 1876 // use the default plugin. 1877 1878 const char *partial_name = NULL; 1879 partial_name = input.GetArgumentAtIndex(opt_arg_pos); 1880 1881 PlatformSP platform_sp (m_interpreter.GetPlatform (true)); 1882 if (platform_sp) 1883 { 1884 ProcessInstanceInfoList process_infos; 1885 ProcessInstanceInfoMatch match_info; 1886 if (partial_name) 1887 { 1888 match_info.GetProcessInfo().GetExecutableFile().SetFile(partial_name, false); 1889 match_info.SetNameMatchType(eNameMatchStartsWith); 1890 } 1891 platform_sp->FindProcesses (match_info, process_infos); 1892 const uint32_t num_matches = process_infos.GetSize(); 1893 if (num_matches > 0) 1894 { 1895 for (uint32_t i=0; i<num_matches; ++i) 1896 { 1897 matches.AppendString (process_infos.GetProcessNameAtIndex(i), 1898 process_infos.GetProcessNameLengthAtIndex(i)); 1899 } 1900 } 1901 } 1902 } 1903 1904 return false; 1905 } 1906 1907 // Options table: Required for subclasses of Options. 1908 1909 static OptionDefinition g_option_table[]; 1910 1911 // Instance variables to hold the values for command options. 1912 1913 ProcessAttachInfo attach_info; 1914 }; 1915 1916 CommandObjectPlatformProcessAttach (CommandInterpreter &interpreter) : 1917 CommandObjectParsed (interpreter, 1918 "platform process attach", 1919 "Attach to a process.", 1920 "platform process attach <cmd-options>"), 1921 m_options (interpreter) 1922 { 1923 } 1924 1925 ~CommandObjectPlatformProcessAttach () 1926 { 1927 } 1928 1929 bool 1930 DoExecute (Args& command, 1931 CommandReturnObject &result) 1932 { 1933 PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); 1934 if (platform_sp) 1935 { 1936 Error err; 1937 ProcessSP remote_process_sp = 1938 platform_sp->Attach(m_options.attach_info, m_interpreter.GetDebugger(), NULL, err); 1939 if (err.Fail()) 1940 { 1941 result.AppendError(err.AsCString()); 1942 result.SetStatus (eReturnStatusFailed); 1943 } 1944 else if (remote_process_sp.get() == NULL) 1945 { 1946 result.AppendError("could not attach: unknown reason"); 1947 result.SetStatus (eReturnStatusFailed); 1948 } 1949 else 1950 result.SetStatus (eReturnStatusSuccessFinishResult); 1951 } 1952 else 1953 { 1954 result.AppendError ("no platform is currently selected"); 1955 result.SetStatus (eReturnStatusFailed); 1956 } 1957 return result.Succeeded(); 1958 } 1959 1960 Options * 1961 GetOptions () 1962 { 1963 return &m_options; 1964 } 1965 1966 protected: 1967 1968 CommandOptions m_options; 1969 }; 1970 1971 1972 OptionDefinition 1973 CommandObjectPlatformProcessAttach::CommandOptions::g_option_table[] = 1974 { 1975 { LLDB_OPT_SET_ALL, false, "plugin", 'P' , OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypePlugin, "Name of the process plugin you want to use."}, 1976 { LLDB_OPT_SET_1, false, "pid", 'p' , OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypePid, "The process ID of an existing process to attach to."}, 1977 { LLDB_OPT_SET_2, false, "name", 'n' , OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeProcessName, "The name of the process to attach to."}, 1978 { LLDB_OPT_SET_2, false, "waitfor", 'w' , OptionParser::eNoArgument , NULL, NULL, 0, eArgTypeNone, "Wait for the the process with <process-name> to launch."}, 1979 { 0, false, NULL , 0 , 0 , NULL, NULL, 0, eArgTypeNone, NULL } 1980 }; 1981 1982 1983 class CommandObjectPlatformProcess : public CommandObjectMultiword 1984 { 1985 public: 1986 //------------------------------------------------------------------ 1987 // Constructors and Destructors 1988 //------------------------------------------------------------------ 1989 CommandObjectPlatformProcess (CommandInterpreter &interpreter) : 1990 CommandObjectMultiword (interpreter, 1991 "platform process", 1992 "A set of commands to query, launch and attach to platform processes", 1993 "platform process [attach|launch|list] ...") 1994 { 1995 LoadSubCommand ("attach", CommandObjectSP (new CommandObjectPlatformProcessAttach (interpreter))); 1996 LoadSubCommand ("launch", CommandObjectSP (new CommandObjectPlatformProcessLaunch (interpreter))); 1997 LoadSubCommand ("info" , CommandObjectSP (new CommandObjectPlatformProcessInfo (interpreter))); 1998 LoadSubCommand ("list" , CommandObjectSP (new CommandObjectPlatformProcessList (interpreter))); 1999 2000 } 2001 2002 virtual 2003 ~CommandObjectPlatformProcess () 2004 { 2005 } 2006 2007 private: 2008 //------------------------------------------------------------------ 2009 // For CommandObjectPlatform only 2010 //------------------------------------------------------------------ 2011 DISALLOW_COPY_AND_ASSIGN (CommandObjectPlatformProcess); 2012 }; 2013 2014 //---------------------------------------------------------------------- 2015 // "platform shell" 2016 //---------------------------------------------------------------------- 2017 class CommandObjectPlatformShell : public CommandObjectRaw 2018 { 2019 public: 2020 2021 class CommandOptions : public Options 2022 { 2023 public: 2024 2025 CommandOptions (CommandInterpreter &interpreter) : 2026 Options(interpreter), 2027 timeout(10) 2028 { 2029 } 2030 2031 virtual 2032 ~CommandOptions () 2033 { 2034 } 2035 2036 virtual uint32_t 2037 GetNumDefinitions () 2038 { 2039 return 1; 2040 } 2041 2042 virtual const OptionDefinition* 2043 GetDefinitions () 2044 { 2045 return g_option_table; 2046 } 2047 2048 virtual Error 2049 SetOptionValue (uint32_t option_idx, 2050 const char *option_value) 2051 { 2052 Error error; 2053 2054 const char short_option = (char) g_option_table[option_idx].short_option; 2055 2056 switch (short_option) 2057 { 2058 case 't': 2059 { 2060 bool success; 2061 timeout = StringConvert::ToUInt32(option_value, 10, 10, &success); 2062 if (!success) 2063 error.SetErrorStringWithFormat("could not convert \"%s\" to a numeric value.", option_value); 2064 break; 2065 } 2066 default: 2067 error.SetErrorStringWithFormat("invalid short option character '%c'", short_option); 2068 break; 2069 } 2070 2071 return error; 2072 } 2073 2074 virtual void 2075 OptionParsingStarting () 2076 { 2077 } 2078 2079 // Options table: Required for subclasses of Options. 2080 2081 static OptionDefinition g_option_table[]; 2082 uint32_t timeout; 2083 }; 2084 2085 CommandObjectPlatformShell (CommandInterpreter &interpreter) : 2086 CommandObjectRaw (interpreter, 2087 "platform shell", 2088 "Run a shell command on a the selected platform.", 2089 "platform shell <shell-command>", 2090 0), 2091 m_options(interpreter) 2092 { 2093 } 2094 2095 virtual 2096 ~CommandObjectPlatformShell () 2097 { 2098 } 2099 2100 virtual 2101 Options * 2102 GetOptions () 2103 { 2104 return &m_options; 2105 } 2106 2107 virtual bool 2108 DoExecute (const char *raw_command_line, CommandReturnObject &result) 2109 { 2110 m_options.NotifyOptionParsingStarting(); 2111 2112 const char* expr = NULL; 2113 2114 // Print out an usage syntax on an empty command line. 2115 if (raw_command_line[0] == '\0') 2116 { 2117 result.GetOutputStream().Printf("%s\n", this->GetSyntax()); 2118 return true; 2119 } 2120 2121 if (raw_command_line[0] == '-') 2122 { 2123 // We have some options and these options MUST end with --. 2124 const char *end_options = NULL; 2125 const char *s = raw_command_line; 2126 while (s && s[0]) 2127 { 2128 end_options = ::strstr (s, "--"); 2129 if (end_options) 2130 { 2131 end_options += 2; // Get past the "--" 2132 if (::isspace (end_options[0])) 2133 { 2134 expr = end_options; 2135 while (::isspace (*expr)) 2136 ++expr; 2137 break; 2138 } 2139 } 2140 s = end_options; 2141 } 2142 2143 if (end_options) 2144 { 2145 Args args (raw_command_line, end_options - raw_command_line); 2146 if (!ParseOptions (args, result)) 2147 return false; 2148 } 2149 } 2150 2151 if (expr == NULL) 2152 expr = raw_command_line; 2153 2154 PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); 2155 Error error; 2156 if (platform_sp) 2157 { 2158 const char *working_dir = NULL; 2159 std::string output; 2160 int status = -1; 2161 int signo = -1; 2162 error = (platform_sp->RunShellCommand (expr, working_dir, &status, &signo, &output, m_options.timeout)); 2163 if (!output.empty()) 2164 result.GetOutputStream().PutCString(output.c_str()); 2165 if (status > 0) 2166 { 2167 if (signo > 0) 2168 { 2169 const char *signo_cstr = Host::GetSignalAsCString(signo); 2170 if (signo_cstr) 2171 result.GetOutputStream().Printf("error: command returned with status %i and signal %s\n", status, signo_cstr); 2172 else 2173 result.GetOutputStream().Printf("error: command returned with status %i and signal %i\n", status, signo); 2174 } 2175 else 2176 result.GetOutputStream().Printf("error: command returned with status %i\n", status); 2177 } 2178 } 2179 else 2180 { 2181 result.GetOutputStream().Printf("error: cannot run remote shell commands without a platform\n"); 2182 error.SetErrorString("error: cannot run remote shell commands without a platform"); 2183 } 2184 2185 if (error.Fail()) 2186 { 2187 result.AppendError(error.AsCString()); 2188 result.SetStatus (eReturnStatusFailed); 2189 } 2190 else 2191 { 2192 result.SetStatus (eReturnStatusSuccessFinishResult); 2193 } 2194 return true; 2195 } 2196 CommandOptions m_options; 2197 }; 2198 2199 OptionDefinition 2200 CommandObjectPlatformShell::CommandOptions::g_option_table[] = 2201 { 2202 { LLDB_OPT_SET_ALL, false, "timeout", 't', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeValue, "Seconds to wait for the remote host to finish running the command."}, 2203 { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } 2204 }; 2205 2206 2207 //---------------------------------------------------------------------- 2208 // "platform install" - install a target to a remote end 2209 //---------------------------------------------------------------------- 2210 class CommandObjectPlatformInstall : public CommandObjectParsed 2211 { 2212 public: 2213 CommandObjectPlatformInstall (CommandInterpreter &interpreter) : 2214 CommandObjectParsed (interpreter, 2215 "platform target-install", 2216 "Install a target (bundle or executable file) to the remote end.", 2217 "platform target-install <local-thing> <remote-sandbox>", 2218 0) 2219 { 2220 } 2221 2222 virtual 2223 ~CommandObjectPlatformInstall () 2224 { 2225 } 2226 2227 virtual bool 2228 DoExecute (Args& args, CommandReturnObject &result) 2229 { 2230 if (args.GetArgumentCount() != 2) 2231 { 2232 result.AppendError("platform target-install takes two arguments"); 2233 result.SetStatus(eReturnStatusFailed); 2234 return false; 2235 } 2236 // TODO: move the bulk of this code over to the platform itself 2237 FileSpec src(args.GetArgumentAtIndex(0), true); 2238 FileSpec dst(args.GetArgumentAtIndex(1), false); 2239 if (src.Exists() == false) 2240 { 2241 result.AppendError("source location does not exist or is not accessible"); 2242 result.SetStatus(eReturnStatusFailed); 2243 return false; 2244 } 2245 PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); 2246 if (!platform_sp) 2247 { 2248 result.AppendError ("no platform currently selected"); 2249 result.SetStatus (eReturnStatusFailed); 2250 return false; 2251 } 2252 2253 Error error = platform_sp->Install(src, dst); 2254 if (error.Success()) 2255 { 2256 result.SetStatus(eReturnStatusSuccessFinishNoResult); 2257 } 2258 else 2259 { 2260 result.AppendErrorWithFormat("install failed: %s", error.AsCString()); 2261 result.SetStatus(eReturnStatusFailed); 2262 } 2263 return result.Succeeded(); 2264 } 2265 private: 2266 2267 }; 2268 2269 //---------------------------------------------------------------------- 2270 // CommandObjectPlatform constructor 2271 //---------------------------------------------------------------------- 2272 CommandObjectPlatform::CommandObjectPlatform(CommandInterpreter &interpreter) : 2273 CommandObjectMultiword (interpreter, 2274 "platform", 2275 "A set of commands to manage and create platforms.", 2276 "platform [connect|disconnect|info|list|status|select] ...") 2277 { 2278 LoadSubCommand ("select", CommandObjectSP (new CommandObjectPlatformSelect (interpreter))); 2279 LoadSubCommand ("list" , CommandObjectSP (new CommandObjectPlatformList (interpreter))); 2280 LoadSubCommand ("status", CommandObjectSP (new CommandObjectPlatformStatus (interpreter))); 2281 LoadSubCommand ("connect", CommandObjectSP (new CommandObjectPlatformConnect (interpreter))); 2282 LoadSubCommand ("disconnect", CommandObjectSP (new CommandObjectPlatformDisconnect (interpreter))); 2283 LoadSubCommand ("settings", CommandObjectSP (new CommandObjectPlatformSettings (interpreter))); 2284 LoadSubCommand ("mkdir", CommandObjectSP (new CommandObjectPlatformMkDir (interpreter))); 2285 LoadSubCommand ("file", CommandObjectSP (new CommandObjectPlatformFile (interpreter))); 2286 LoadSubCommand ("get-file", CommandObjectSP (new CommandObjectPlatformGetFile (interpreter))); 2287 LoadSubCommand ("get-size", CommandObjectSP (new CommandObjectPlatformGetSize (interpreter))); 2288 LoadSubCommand ("put-file", CommandObjectSP (new CommandObjectPlatformPutFile (interpreter))); 2289 LoadSubCommand ("process", CommandObjectSP (new CommandObjectPlatformProcess (interpreter))); 2290 LoadSubCommand ("shell", CommandObjectSP (new CommandObjectPlatformShell (interpreter))); 2291 LoadSubCommand ("target-install", CommandObjectSP (new CommandObjectPlatformInstall (interpreter))); 2292 } 2293 2294 //---------------------------------------------------------------------- 2295 // Destructor 2296 //---------------------------------------------------------------------- 2297 CommandObjectPlatform::~CommandObjectPlatform() 2298 { 2299 } 2300