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