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 "Examples: \n\ 1071 \n\ 1072 platform get-file /the/remote/file/path /the/local/file/path\n\ 1073 # Transfer a file from the remote end with file path /the/remote/file/path to the local host.\n"); 1074 1075 CommandArgumentEntry arg1, arg2; 1076 CommandArgumentData file_arg_remote, file_arg_host; 1077 1078 // Define the first (and only) variant of this arg. 1079 file_arg_remote.arg_type = eArgTypeFilename; 1080 file_arg_remote.arg_repetition = eArgRepeatPlain; 1081 // There is only one variant this argument could be; put it into the argument entry. 1082 arg1.push_back (file_arg_remote); 1083 1084 // Define the second (and only) variant of this arg. 1085 file_arg_host.arg_type = eArgTypeFilename; 1086 file_arg_host.arg_repetition = eArgRepeatPlain; 1087 // There is only one variant this argument could be; put it into the argument entry. 1088 arg2.push_back (file_arg_host); 1089 1090 // Push the data for the first and the second arguments into the m_arguments vector. 1091 m_arguments.push_back (arg1); 1092 m_arguments.push_back (arg2); 1093 } 1094 1095 virtual 1096 ~CommandObjectPlatformGetFile () 1097 { 1098 } 1099 1100 virtual bool 1101 DoExecute (Args& args, CommandReturnObject &result) 1102 { 1103 // If the number of arguments is incorrect, issue an error message. 1104 if (args.GetArgumentCount() != 2) 1105 { 1106 result.GetErrorStream().Printf("error: required arguments missing; specify both the source and destination file paths\n"); 1107 result.SetStatus(eReturnStatusFailed); 1108 return false; 1109 } 1110 1111 PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); 1112 if (platform_sp) 1113 { 1114 const char *remote_file_path = args.GetArgumentAtIndex(0); 1115 const char *local_file_path = args.GetArgumentAtIndex(1); 1116 Error error = platform_sp->GetFile(FileSpec(remote_file_path, false), 1117 FileSpec(local_file_path, false)); 1118 if (error.Success()) 1119 { 1120 result.AppendMessageWithFormat("successfully get-file from %s (remote) to %s (host)\n", 1121 remote_file_path, local_file_path); 1122 result.SetStatus (eReturnStatusSuccessFinishResult); 1123 } 1124 else 1125 { 1126 result.AppendMessageWithFormat("get-file failed: %s\n", error.AsCString()); 1127 result.SetStatus (eReturnStatusFailed); 1128 } 1129 } 1130 else 1131 { 1132 result.AppendError ("no platform currently selected\n"); 1133 result.SetStatus (eReturnStatusFailed); 1134 } 1135 return result.Succeeded(); 1136 } 1137 }; 1138 1139 //---------------------------------------------------------------------- 1140 // "platform get-size remote-file-path" 1141 //---------------------------------------------------------------------- 1142 class CommandObjectPlatformGetSize : public CommandObjectParsed 1143 { 1144 public: 1145 CommandObjectPlatformGetSize (CommandInterpreter &interpreter) : 1146 CommandObjectParsed (interpreter, 1147 "platform get-size", 1148 "Get the file size from the remote end.", 1149 "platform get-size <remote-file-spec>", 1150 0) 1151 { 1152 SetHelpLong( 1153 "Examples: \n\ 1154 \n\ 1155 platform get-size /the/remote/file/path\n\ 1156 # Get the file size from the remote end with path /the/remote/file/path.\n"); 1157 1158 CommandArgumentEntry arg1; 1159 CommandArgumentData file_arg_remote; 1160 1161 // Define the first (and only) variant of this arg. 1162 file_arg_remote.arg_type = eArgTypeFilename; 1163 file_arg_remote.arg_repetition = eArgRepeatPlain; 1164 // There is only one variant this argument could be; put it into the argument entry. 1165 arg1.push_back (file_arg_remote); 1166 1167 // Push the data for the first argument into the m_arguments vector. 1168 m_arguments.push_back (arg1); 1169 } 1170 1171 virtual 1172 ~CommandObjectPlatformGetSize () 1173 { 1174 } 1175 1176 virtual bool 1177 DoExecute (Args& args, CommandReturnObject &result) 1178 { 1179 // If the number of arguments is incorrect, issue an error message. 1180 if (args.GetArgumentCount() != 1) 1181 { 1182 result.GetErrorStream().Printf("error: required argument missing; specify the source file path as the only argument\n"); 1183 result.SetStatus(eReturnStatusFailed); 1184 return false; 1185 } 1186 1187 PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); 1188 if (platform_sp) 1189 { 1190 std::string remote_file_path(args.GetArgumentAtIndex(0)); 1191 user_id_t size = platform_sp->GetFileSize(FileSpec(remote_file_path.c_str(), false)); 1192 if (size != UINT64_MAX) 1193 { 1194 result.AppendMessageWithFormat("File size of %s (remote): %" PRIu64 "\n", remote_file_path.c_str(), size); 1195 result.SetStatus (eReturnStatusSuccessFinishResult); 1196 } 1197 else 1198 { 1199 result.AppendMessageWithFormat("Error getting file size of %s (remote)\n", remote_file_path.c_str()); 1200 result.SetStatus (eReturnStatusFailed); 1201 } 1202 } 1203 else 1204 { 1205 result.AppendError ("no platform currently selected\n"); 1206 result.SetStatus (eReturnStatusFailed); 1207 } 1208 return result.Succeeded(); 1209 } 1210 }; 1211 1212 //---------------------------------------------------------------------- 1213 // "platform put-file" 1214 //---------------------------------------------------------------------- 1215 class CommandObjectPlatformPutFile : public CommandObjectParsed 1216 { 1217 public: 1218 CommandObjectPlatformPutFile (CommandInterpreter &interpreter) : 1219 CommandObjectParsed (interpreter, 1220 "platform put-file", 1221 "Transfer a file from this system to the remote end.", 1222 NULL, 1223 0) 1224 { 1225 } 1226 1227 virtual 1228 ~CommandObjectPlatformPutFile () 1229 { 1230 } 1231 1232 virtual bool 1233 DoExecute (Args& args, CommandReturnObject &result) 1234 { 1235 const char* src = args.GetArgumentAtIndex(0); 1236 const char* dst = args.GetArgumentAtIndex(1); 1237 1238 FileSpec src_fs(src, true); 1239 FileSpec dst_fs(dst ? dst : src_fs.GetFilename().GetCString(), false); 1240 1241 PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); 1242 if (platform_sp) 1243 { 1244 Error error (platform_sp->PutFile(src_fs, dst_fs)); 1245 if (error.Success()) 1246 { 1247 result.SetStatus (eReturnStatusSuccessFinishNoResult); 1248 } 1249 else 1250 { 1251 result.AppendError (error.AsCString()); 1252 result.SetStatus (eReturnStatusFailed); 1253 } 1254 } 1255 else 1256 { 1257 result.AppendError ("no platform currently selected\n"); 1258 result.SetStatus (eReturnStatusFailed); 1259 } 1260 return result.Succeeded(); 1261 } 1262 }; 1263 1264 //---------------------------------------------------------------------- 1265 // "platform process launch" 1266 //---------------------------------------------------------------------- 1267 class CommandObjectPlatformProcessLaunch : public CommandObjectParsed 1268 { 1269 public: 1270 CommandObjectPlatformProcessLaunch (CommandInterpreter &interpreter) : 1271 CommandObjectParsed (interpreter, 1272 "platform process launch", 1273 "Launch a new process on a remote platform.", 1274 "platform process launch program", 1275 eCommandRequiresTarget | eCommandTryTargetAPILock), 1276 m_options (interpreter) 1277 { 1278 } 1279 1280 virtual 1281 ~CommandObjectPlatformProcessLaunch () 1282 { 1283 } 1284 1285 virtual Options * 1286 GetOptions () 1287 { 1288 return &m_options; 1289 } 1290 1291 protected: 1292 virtual bool 1293 DoExecute (Args& args, CommandReturnObject &result) 1294 { 1295 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 1296 PlatformSP platform_sp; 1297 if (target) 1298 { 1299 platform_sp = target->GetPlatform(); 1300 } 1301 if (!platform_sp) 1302 { 1303 platform_sp = m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform(); 1304 } 1305 1306 if (platform_sp) 1307 { 1308 Error error; 1309 const size_t argc = args.GetArgumentCount(); 1310 Target *target = m_exe_ctx.GetTargetPtr(); 1311 Module *exe_module = target->GetExecutableModulePointer(); 1312 if (exe_module) 1313 { 1314 m_options.launch_info.GetExecutableFile () = exe_module->GetFileSpec(); 1315 char exe_path[PATH_MAX]; 1316 if (m_options.launch_info.GetExecutableFile ().GetPath (exe_path, sizeof(exe_path))) 1317 m_options.launch_info.GetArguments().AppendArgument (exe_path); 1318 m_options.launch_info.GetArchitecture() = exe_module->GetArchitecture(); 1319 } 1320 1321 if (argc > 0) 1322 { 1323 if (m_options.launch_info.GetExecutableFile ()) 1324 { 1325 // We already have an executable file, so we will use this 1326 // and all arguments to this function are extra arguments 1327 m_options.launch_info.GetArguments().AppendArguments (args); 1328 } 1329 else 1330 { 1331 // We don't have any file yet, so the first argument is our 1332 // executable, and the rest are program arguments 1333 const bool first_arg_is_executable = true; 1334 m_options.launch_info.SetArguments (args, first_arg_is_executable); 1335 } 1336 } 1337 1338 if (m_options.launch_info.GetExecutableFile ()) 1339 { 1340 Debugger &debugger = m_interpreter.GetDebugger(); 1341 1342 if (argc == 0) 1343 target->GetRunArguments(m_options.launch_info.GetArguments()); 1344 1345 ProcessSP process_sp (platform_sp->DebugProcess (m_options.launch_info, 1346 debugger, 1347 target, 1348 error)); 1349 if (process_sp && process_sp->IsAlive()) 1350 { 1351 result.SetStatus (eReturnStatusSuccessFinishNoResult); 1352 return true; 1353 } 1354 1355 if (error.Success()) 1356 result.AppendError ("process launch failed"); 1357 else 1358 result.AppendError (error.AsCString()); 1359 result.SetStatus (eReturnStatusFailed); 1360 } 1361 else 1362 { 1363 result.AppendError ("'platform process launch' uses the current target file and arguments, or the executable and its arguments can be specified in this command"); 1364 result.SetStatus (eReturnStatusFailed); 1365 return false; 1366 } 1367 } 1368 else 1369 { 1370 result.AppendError ("no platform is selected\n"); 1371 } 1372 return result.Succeeded(); 1373 } 1374 1375 protected: 1376 ProcessLaunchCommandOptions m_options; 1377 }; 1378 1379 1380 1381 //---------------------------------------------------------------------- 1382 // "platform process list" 1383 //---------------------------------------------------------------------- 1384 class CommandObjectPlatformProcessList : public CommandObjectParsed 1385 { 1386 public: 1387 CommandObjectPlatformProcessList (CommandInterpreter &interpreter) : 1388 CommandObjectParsed (interpreter, 1389 "platform process list", 1390 "List processes on a remote platform by name, pid, or many other matching attributes.", 1391 "platform process list", 1392 0), 1393 m_options (interpreter) 1394 { 1395 } 1396 1397 virtual 1398 ~CommandObjectPlatformProcessList () 1399 { 1400 } 1401 1402 virtual Options * 1403 GetOptions () 1404 { 1405 return &m_options; 1406 } 1407 1408 protected: 1409 virtual bool 1410 DoExecute (Args& args, CommandReturnObject &result) 1411 { 1412 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 1413 PlatformSP platform_sp; 1414 if (target) 1415 { 1416 platform_sp = target->GetPlatform(); 1417 } 1418 if (!platform_sp) 1419 { 1420 platform_sp = m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform(); 1421 } 1422 1423 if (platform_sp) 1424 { 1425 Error error; 1426 if (args.GetArgumentCount() == 0) 1427 { 1428 1429 if (platform_sp) 1430 { 1431 Stream &ostrm = result.GetOutputStream(); 1432 1433 lldb::pid_t pid = m_options.match_info.GetProcessInfo().GetProcessID(); 1434 if (pid != LLDB_INVALID_PROCESS_ID) 1435 { 1436 ProcessInstanceInfo proc_info; 1437 if (platform_sp->GetProcessInfo (pid, proc_info)) 1438 { 1439 ProcessInstanceInfo::DumpTableHeader (ostrm, platform_sp.get(), m_options.show_args, m_options.verbose); 1440 proc_info.DumpAsTableRow(ostrm, platform_sp.get(), m_options.show_args, m_options.verbose); 1441 result.SetStatus (eReturnStatusSuccessFinishResult); 1442 } 1443 else 1444 { 1445 result.AppendErrorWithFormat ("no process found with pid = %" PRIu64 "\n", pid); 1446 result.SetStatus (eReturnStatusFailed); 1447 } 1448 } 1449 else 1450 { 1451 ProcessInstanceInfoList proc_infos; 1452 const uint32_t matches = platform_sp->FindProcesses (m_options.match_info, proc_infos); 1453 const char *match_desc = NULL; 1454 const char *match_name = m_options.match_info.GetProcessInfo().GetName(); 1455 if (match_name && match_name[0]) 1456 { 1457 switch (m_options.match_info.GetNameMatchType()) 1458 { 1459 case eNameMatchIgnore: break; 1460 case eNameMatchEquals: match_desc = "matched"; break; 1461 case eNameMatchContains: match_desc = "contained"; break; 1462 case eNameMatchStartsWith: match_desc = "started with"; break; 1463 case eNameMatchEndsWith: match_desc = "ended with"; break; 1464 case eNameMatchRegularExpression: match_desc = "matched the regular expression"; break; 1465 } 1466 } 1467 1468 if (matches == 0) 1469 { 1470 if (match_desc) 1471 result.AppendErrorWithFormat ("no processes were found that %s \"%s\" on the \"%s\" platform\n", 1472 match_desc, 1473 match_name, 1474 platform_sp->GetPluginName().GetCString()); 1475 else 1476 result.AppendErrorWithFormat ("no processes were found on the \"%s\" platform\n", platform_sp->GetPluginName().GetCString()); 1477 result.SetStatus (eReturnStatusFailed); 1478 } 1479 else 1480 { 1481 result.AppendMessageWithFormat ("%u matching process%s found on \"%s\"", 1482 matches, 1483 matches > 1 ? "es were" : " was", 1484 platform_sp->GetName().GetCString()); 1485 if (match_desc) 1486 result.AppendMessageWithFormat (" whose name %s \"%s\"", 1487 match_desc, 1488 match_name); 1489 result.AppendMessageWithFormat ("\n"); 1490 ProcessInstanceInfo::DumpTableHeader (ostrm, platform_sp.get(), m_options.show_args, m_options.verbose); 1491 for (uint32_t i=0; i<matches; ++i) 1492 { 1493 proc_infos.GetProcessInfoAtIndex(i).DumpAsTableRow(ostrm, platform_sp.get(), m_options.show_args, m_options.verbose); 1494 } 1495 } 1496 } 1497 } 1498 } 1499 else 1500 { 1501 result.AppendError ("invalid args: process list takes only options\n"); 1502 result.SetStatus (eReturnStatusFailed); 1503 } 1504 } 1505 else 1506 { 1507 result.AppendError ("no platform is selected\n"); 1508 result.SetStatus (eReturnStatusFailed); 1509 } 1510 return result.Succeeded(); 1511 } 1512 1513 class CommandOptions : public Options 1514 { 1515 public: 1516 1517 CommandOptions (CommandInterpreter &interpreter) : 1518 Options (interpreter), 1519 match_info () 1520 { 1521 } 1522 1523 virtual 1524 ~CommandOptions () 1525 { 1526 } 1527 1528 virtual Error 1529 SetOptionValue (uint32_t option_idx, const char *option_arg) 1530 { 1531 Error error; 1532 const int short_option = m_getopt_table[option_idx].val; 1533 bool success = false; 1534 1535 switch (short_option) 1536 { 1537 case 'p': 1538 match_info.GetProcessInfo().SetProcessID (StringConvert::ToUInt32 (option_arg, LLDB_INVALID_PROCESS_ID, 0, &success)); 1539 if (!success) 1540 error.SetErrorStringWithFormat("invalid process ID string: '%s'", option_arg); 1541 break; 1542 1543 case 'P': 1544 match_info.GetProcessInfo().SetParentProcessID (StringConvert::ToUInt32 (option_arg, LLDB_INVALID_PROCESS_ID, 0, &success)); 1545 if (!success) 1546 error.SetErrorStringWithFormat("invalid parent process ID string: '%s'", option_arg); 1547 break; 1548 1549 case 'u': 1550 match_info.GetProcessInfo().SetUserID (StringConvert::ToUInt32 (option_arg, UINT32_MAX, 0, &success)); 1551 if (!success) 1552 error.SetErrorStringWithFormat("invalid user ID string: '%s'", option_arg); 1553 break; 1554 1555 case 'U': 1556 match_info.GetProcessInfo().SetEffectiveUserID (StringConvert::ToUInt32 (option_arg, UINT32_MAX, 0, &success)); 1557 if (!success) 1558 error.SetErrorStringWithFormat("invalid effective user ID string: '%s'", option_arg); 1559 break; 1560 1561 case 'g': 1562 match_info.GetProcessInfo().SetGroupID (StringConvert::ToUInt32 (option_arg, UINT32_MAX, 0, &success)); 1563 if (!success) 1564 error.SetErrorStringWithFormat("invalid group ID string: '%s'", option_arg); 1565 break; 1566 1567 case 'G': 1568 match_info.GetProcessInfo().SetEffectiveGroupID (StringConvert::ToUInt32 (option_arg, UINT32_MAX, 0, &success)); 1569 if (!success) 1570 error.SetErrorStringWithFormat("invalid effective group ID string: '%s'", option_arg); 1571 break; 1572 1573 case 'a': 1574 match_info.GetProcessInfo().GetArchitecture().SetTriple (option_arg, m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform().get()); 1575 break; 1576 1577 case 'n': 1578 match_info.GetProcessInfo().GetExecutableFile().SetFile (option_arg, false); 1579 match_info.SetNameMatchType (eNameMatchEquals); 1580 break; 1581 1582 case 'e': 1583 match_info.GetProcessInfo().GetExecutableFile().SetFile (option_arg, false); 1584 match_info.SetNameMatchType (eNameMatchEndsWith); 1585 break; 1586 1587 case 's': 1588 match_info.GetProcessInfo().GetExecutableFile().SetFile (option_arg, false); 1589 match_info.SetNameMatchType (eNameMatchStartsWith); 1590 break; 1591 1592 case 'c': 1593 match_info.GetProcessInfo().GetExecutableFile().SetFile (option_arg, false); 1594 match_info.SetNameMatchType (eNameMatchContains); 1595 break; 1596 1597 case 'r': 1598 match_info.GetProcessInfo().GetExecutableFile().SetFile (option_arg, false); 1599 match_info.SetNameMatchType (eNameMatchRegularExpression); 1600 break; 1601 1602 case 'A': 1603 show_args = true; 1604 break; 1605 1606 case 'v': 1607 verbose = true; 1608 break; 1609 1610 default: 1611 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 1612 break; 1613 } 1614 1615 return error; 1616 } 1617 1618 void 1619 OptionParsingStarting () 1620 { 1621 match_info.Clear(); 1622 show_args = false; 1623 verbose = false; 1624 } 1625 1626 const OptionDefinition* 1627 GetDefinitions () 1628 { 1629 return g_option_table; 1630 } 1631 1632 // Options table: Required for subclasses of Options. 1633 1634 static OptionDefinition g_option_table[]; 1635 1636 // Instance variables to hold the values for command options. 1637 1638 ProcessInstanceInfoMatch match_info; 1639 bool show_args; 1640 bool verbose; 1641 }; 1642 CommandOptions m_options; 1643 }; 1644 1645 namespace 1646 { 1647 PosixPlatformCommandOptionValidator g_posix_validator; 1648 } 1649 1650 OptionDefinition 1651 CommandObjectPlatformProcessList::CommandOptions::g_option_table[] = 1652 { 1653 { LLDB_OPT_SET_1 , false, "pid" , 'p', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypePid , "List the process info for a specific process ID." }, 1654 { LLDB_OPT_SET_2 , true , "name" , 'n', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeProcessName , "Find processes with executable basenames that match a string." }, 1655 { LLDB_OPT_SET_3 , true , "ends-with" , 'e', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeProcessName , "Find processes with executable basenames that end with a string." }, 1656 { LLDB_OPT_SET_4 , true , "starts-with", 's', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeProcessName , "Find processes with executable basenames that start with a string." }, 1657 { LLDB_OPT_SET_5 , true , "contains" , 'c', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeProcessName , "Find processes with executable basenames that contain a string." }, 1658 { LLDB_OPT_SET_6 , true , "regex" , 'r', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeRegularExpression, "Find processes with executable basenames that match a regular expression." }, 1659 { 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." }, 1660 { 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." }, 1661 { 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." }, 1662 { 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." }, 1663 { 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." }, 1664 { LLDB_OPT_SET_FROM_TO(2, 6), false, "arch" , 'a', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeArchitecture , "Find processes that have a matching architecture." }, 1665 { 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." }, 1666 { LLDB_OPT_SET_FROM_TO(1, 6), false, "verbose" , 'v', OptionParser::eNoArgument , NULL, NULL, 0, eArgTypeNone , "Enable verbose output." }, 1667 { 0 , false, NULL , 0 , 0 , NULL, NULL, 0, eArgTypeNone , NULL } 1668 }; 1669 1670 //---------------------------------------------------------------------- 1671 // "platform process info" 1672 //---------------------------------------------------------------------- 1673 class CommandObjectPlatformProcessInfo : public CommandObjectParsed 1674 { 1675 public: 1676 CommandObjectPlatformProcessInfo (CommandInterpreter &interpreter) : 1677 CommandObjectParsed (interpreter, 1678 "platform process info", 1679 "Get detailed information for one or more process by process ID.", 1680 "platform process info <pid> [<pid> <pid> ...]", 1681 0) 1682 { 1683 CommandArgumentEntry arg; 1684 CommandArgumentData pid_args; 1685 1686 // Define the first (and only) variant of this arg. 1687 pid_args.arg_type = eArgTypePid; 1688 pid_args.arg_repetition = eArgRepeatStar; 1689 1690 // There is only one variant this argument could be; put it into the argument entry. 1691 arg.push_back (pid_args); 1692 1693 // Push the data for the first argument into the m_arguments vector. 1694 m_arguments.push_back (arg); 1695 } 1696 1697 virtual 1698 ~CommandObjectPlatformProcessInfo () 1699 { 1700 } 1701 1702 protected: 1703 virtual bool 1704 DoExecute (Args& args, CommandReturnObject &result) 1705 { 1706 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 1707 PlatformSP platform_sp; 1708 if (target) 1709 { 1710 platform_sp = target->GetPlatform(); 1711 } 1712 if (!platform_sp) 1713 { 1714 platform_sp = m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform(); 1715 } 1716 1717 if (platform_sp) 1718 { 1719 const size_t argc = args.GetArgumentCount(); 1720 if (argc > 0) 1721 { 1722 Error error; 1723 1724 if (platform_sp->IsConnected()) 1725 { 1726 Stream &ostrm = result.GetOutputStream(); 1727 bool success; 1728 for (size_t i=0; i<argc; ++ i) 1729 { 1730 const char *arg = args.GetArgumentAtIndex(i); 1731 lldb::pid_t pid = StringConvert::ToUInt32 (arg, LLDB_INVALID_PROCESS_ID, 0, &success); 1732 if (success) 1733 { 1734 ProcessInstanceInfo proc_info; 1735 if (platform_sp->GetProcessInfo (pid, proc_info)) 1736 { 1737 ostrm.Printf ("Process information for process %" PRIu64 ":\n", pid); 1738 proc_info.Dump (ostrm, platform_sp.get()); 1739 } 1740 else 1741 { 1742 ostrm.Printf ("error: no process information is available for process %" PRIu64 "\n", pid); 1743 } 1744 ostrm.EOL(); 1745 } 1746 else 1747 { 1748 result.AppendErrorWithFormat ("invalid process ID argument '%s'", arg); 1749 result.SetStatus (eReturnStatusFailed); 1750 break; 1751 } 1752 } 1753 } 1754 else 1755 { 1756 // Not connected... 1757 result.AppendErrorWithFormat ("not connected to '%s'", platform_sp->GetPluginName().GetCString()); 1758 result.SetStatus (eReturnStatusFailed); 1759 } 1760 } 1761 else 1762 { 1763 // No args 1764 result.AppendError ("one or more process id(s) must be specified"); 1765 result.SetStatus (eReturnStatusFailed); 1766 } 1767 } 1768 else 1769 { 1770 result.AppendError ("no platform is currently selected"); 1771 result.SetStatus (eReturnStatusFailed); 1772 } 1773 return result.Succeeded(); 1774 } 1775 }; 1776 1777 class CommandObjectPlatformProcessAttach : public CommandObjectParsed 1778 { 1779 public: 1780 1781 class CommandOptions : public Options 1782 { 1783 public: 1784 1785 CommandOptions (CommandInterpreter &interpreter) : 1786 Options(interpreter) 1787 { 1788 // Keep default values of all options in one place: OptionParsingStarting () 1789 OptionParsingStarting (); 1790 } 1791 1792 ~CommandOptions () 1793 { 1794 } 1795 1796 Error 1797 SetOptionValue (uint32_t option_idx, const char *option_arg) 1798 { 1799 Error error; 1800 char short_option = (char) m_getopt_table[option_idx].val; 1801 bool success = false; 1802 switch (short_option) 1803 { 1804 case 'p': 1805 { 1806 lldb::pid_t pid = StringConvert::ToUInt32 (option_arg, LLDB_INVALID_PROCESS_ID, 0, &success); 1807 if (!success || pid == LLDB_INVALID_PROCESS_ID) 1808 { 1809 error.SetErrorStringWithFormat("invalid process ID '%s'", option_arg); 1810 } 1811 else 1812 { 1813 attach_info.SetProcessID (pid); 1814 } 1815 } 1816 break; 1817 1818 case 'P': 1819 attach_info.SetProcessPluginName (option_arg); 1820 break; 1821 1822 case 'n': 1823 attach_info.GetExecutableFile().SetFile(option_arg, false); 1824 break; 1825 1826 case 'w': 1827 attach_info.SetWaitForLaunch(true); 1828 break; 1829 1830 default: 1831 error.SetErrorStringWithFormat("invalid short option character '%c'", short_option); 1832 break; 1833 } 1834 return error; 1835 } 1836 1837 void 1838 OptionParsingStarting () 1839 { 1840 attach_info.Clear(); 1841 } 1842 1843 const OptionDefinition* 1844 GetDefinitions () 1845 { 1846 return g_option_table; 1847 } 1848 1849 virtual bool 1850 HandleOptionArgumentCompletion (Args &input, 1851 int cursor_index, 1852 int char_pos, 1853 OptionElementVector &opt_element_vector, 1854 int opt_element_index, 1855 int match_start_point, 1856 int max_return_elements, 1857 bool &word_complete, 1858 StringList &matches) 1859 { 1860 int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos; 1861 int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index; 1862 1863 // We are only completing the name option for now... 1864 1865 const OptionDefinition *opt_defs = GetDefinitions(); 1866 if (opt_defs[opt_defs_index].short_option == 'n') 1867 { 1868 // Are we in the name? 1869 1870 // Look to see if there is a -P argument provided, and if so use that plugin, otherwise 1871 // use the default plugin. 1872 1873 const char *partial_name = NULL; 1874 partial_name = input.GetArgumentAtIndex(opt_arg_pos); 1875 1876 PlatformSP platform_sp (m_interpreter.GetPlatform (true)); 1877 if (platform_sp) 1878 { 1879 ProcessInstanceInfoList process_infos; 1880 ProcessInstanceInfoMatch match_info; 1881 if (partial_name) 1882 { 1883 match_info.GetProcessInfo().GetExecutableFile().SetFile(partial_name, false); 1884 match_info.SetNameMatchType(eNameMatchStartsWith); 1885 } 1886 platform_sp->FindProcesses (match_info, process_infos); 1887 const uint32_t num_matches = process_infos.GetSize(); 1888 if (num_matches > 0) 1889 { 1890 for (uint32_t i=0; i<num_matches; ++i) 1891 { 1892 matches.AppendString (process_infos.GetProcessNameAtIndex(i), 1893 process_infos.GetProcessNameLengthAtIndex(i)); 1894 } 1895 } 1896 } 1897 } 1898 1899 return false; 1900 } 1901 1902 // Options table: Required for subclasses of Options. 1903 1904 static OptionDefinition g_option_table[]; 1905 1906 // Instance variables to hold the values for command options. 1907 1908 ProcessAttachInfo attach_info; 1909 }; 1910 1911 CommandObjectPlatformProcessAttach (CommandInterpreter &interpreter) : 1912 CommandObjectParsed (interpreter, 1913 "platform process attach", 1914 "Attach to a process.", 1915 "platform process attach <cmd-options>"), 1916 m_options (interpreter) 1917 { 1918 } 1919 1920 ~CommandObjectPlatformProcessAttach () 1921 { 1922 } 1923 1924 bool 1925 DoExecute (Args& command, 1926 CommandReturnObject &result) 1927 { 1928 PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); 1929 if (platform_sp) 1930 { 1931 Error err; 1932 ProcessSP remote_process_sp = 1933 platform_sp->Attach(m_options.attach_info, m_interpreter.GetDebugger(), NULL, err); 1934 if (err.Fail()) 1935 { 1936 result.AppendError(err.AsCString()); 1937 result.SetStatus (eReturnStatusFailed); 1938 } 1939 else if (remote_process_sp.get() == NULL) 1940 { 1941 result.AppendError("could not attach: unknown reason"); 1942 result.SetStatus (eReturnStatusFailed); 1943 } 1944 else 1945 result.SetStatus (eReturnStatusSuccessFinishResult); 1946 } 1947 else 1948 { 1949 result.AppendError ("no platform is currently selected"); 1950 result.SetStatus (eReturnStatusFailed); 1951 } 1952 return result.Succeeded(); 1953 } 1954 1955 Options * 1956 GetOptions () 1957 { 1958 return &m_options; 1959 } 1960 1961 protected: 1962 1963 CommandOptions m_options; 1964 }; 1965 1966 1967 OptionDefinition 1968 CommandObjectPlatformProcessAttach::CommandOptions::g_option_table[] = 1969 { 1970 { LLDB_OPT_SET_ALL, false, "plugin", 'P' , OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypePlugin, "Name of the process plugin you want to use."}, 1971 { LLDB_OPT_SET_1, false, "pid", 'p' , OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypePid, "The process ID of an existing process to attach to."}, 1972 { LLDB_OPT_SET_2, false, "name", 'n' , OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeProcessName, "The name of the process to attach to."}, 1973 { LLDB_OPT_SET_2, false, "waitfor", 'w' , OptionParser::eNoArgument , NULL, NULL, 0, eArgTypeNone, "Wait for the process with <process-name> to launch."}, 1974 { 0, false, NULL , 0 , 0 , NULL, NULL, 0, eArgTypeNone, NULL } 1975 }; 1976 1977 1978 class CommandObjectPlatformProcess : public CommandObjectMultiword 1979 { 1980 public: 1981 //------------------------------------------------------------------ 1982 // Constructors and Destructors 1983 //------------------------------------------------------------------ 1984 CommandObjectPlatformProcess (CommandInterpreter &interpreter) : 1985 CommandObjectMultiword (interpreter, 1986 "platform process", 1987 "A set of commands to query, launch and attach to platform processes", 1988 "platform process [attach|launch|list] ...") 1989 { 1990 LoadSubCommand ("attach", CommandObjectSP (new CommandObjectPlatformProcessAttach (interpreter))); 1991 LoadSubCommand ("launch", CommandObjectSP (new CommandObjectPlatformProcessLaunch (interpreter))); 1992 LoadSubCommand ("info" , CommandObjectSP (new CommandObjectPlatformProcessInfo (interpreter))); 1993 LoadSubCommand ("list" , CommandObjectSP (new CommandObjectPlatformProcessList (interpreter))); 1994 1995 } 1996 1997 virtual 1998 ~CommandObjectPlatformProcess () 1999 { 2000 } 2001 2002 private: 2003 //------------------------------------------------------------------ 2004 // For CommandObjectPlatform only 2005 //------------------------------------------------------------------ 2006 DISALLOW_COPY_AND_ASSIGN (CommandObjectPlatformProcess); 2007 }; 2008 2009 //---------------------------------------------------------------------- 2010 // "platform shell" 2011 //---------------------------------------------------------------------- 2012 class CommandObjectPlatformShell : public CommandObjectRaw 2013 { 2014 public: 2015 2016 class CommandOptions : public Options 2017 { 2018 public: 2019 2020 CommandOptions (CommandInterpreter &interpreter) : 2021 Options(interpreter), 2022 timeout(10) 2023 { 2024 } 2025 2026 virtual 2027 ~CommandOptions () 2028 { 2029 } 2030 2031 virtual uint32_t 2032 GetNumDefinitions () 2033 { 2034 return 1; 2035 } 2036 2037 virtual const OptionDefinition* 2038 GetDefinitions () 2039 { 2040 return g_option_table; 2041 } 2042 2043 virtual Error 2044 SetOptionValue (uint32_t option_idx, 2045 const char *option_value) 2046 { 2047 Error error; 2048 2049 const char short_option = (char) g_option_table[option_idx].short_option; 2050 2051 switch (short_option) 2052 { 2053 case 't': 2054 { 2055 bool success; 2056 timeout = StringConvert::ToUInt32(option_value, 10, 10, &success); 2057 if (!success) 2058 error.SetErrorStringWithFormat("could not convert \"%s\" to a numeric value.", option_value); 2059 break; 2060 } 2061 default: 2062 error.SetErrorStringWithFormat("invalid short option character '%c'", short_option); 2063 break; 2064 } 2065 2066 return error; 2067 } 2068 2069 virtual void 2070 OptionParsingStarting () 2071 { 2072 } 2073 2074 // Options table: Required for subclasses of Options. 2075 2076 static OptionDefinition g_option_table[]; 2077 uint32_t timeout; 2078 }; 2079 2080 CommandObjectPlatformShell (CommandInterpreter &interpreter) : 2081 CommandObjectRaw (interpreter, 2082 "platform shell", 2083 "Run a shell command on the selected platform.", 2084 "platform shell <shell-command>", 2085 0), 2086 m_options(interpreter) 2087 { 2088 } 2089 2090 virtual 2091 ~CommandObjectPlatformShell () 2092 { 2093 } 2094 2095 virtual 2096 Options * 2097 GetOptions () 2098 { 2099 return &m_options; 2100 } 2101 2102 virtual bool 2103 DoExecute (const char *raw_command_line, CommandReturnObject &result) 2104 { 2105 m_options.NotifyOptionParsingStarting(); 2106 2107 const char* expr = NULL; 2108 2109 // Print out an usage syntax on an empty command line. 2110 if (raw_command_line[0] == '\0') 2111 { 2112 result.GetOutputStream().Printf("%s\n", this->GetSyntax()); 2113 return true; 2114 } 2115 2116 if (raw_command_line[0] == '-') 2117 { 2118 // We have some options and these options MUST end with --. 2119 const char *end_options = NULL; 2120 const char *s = raw_command_line; 2121 while (s && s[0]) 2122 { 2123 end_options = ::strstr (s, "--"); 2124 if (end_options) 2125 { 2126 end_options += 2; // Get past the "--" 2127 if (::isspace (end_options[0])) 2128 { 2129 expr = end_options; 2130 while (::isspace (*expr)) 2131 ++expr; 2132 break; 2133 } 2134 } 2135 s = end_options; 2136 } 2137 2138 if (end_options) 2139 { 2140 Args args (llvm::StringRef(raw_command_line, end_options - raw_command_line)); 2141 if (!ParseOptions (args, result)) 2142 return false; 2143 } 2144 } 2145 2146 if (expr == NULL) 2147 expr = raw_command_line; 2148 2149 PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); 2150 Error error; 2151 if (platform_sp) 2152 { 2153 FileSpec working_dir{}; 2154 std::string output; 2155 int status = -1; 2156 int signo = -1; 2157 error = (platform_sp->RunShellCommand (expr, working_dir, &status, &signo, &output, m_options.timeout)); 2158 if (!output.empty()) 2159 result.GetOutputStream().PutCString(output.c_str()); 2160 if (status > 0) 2161 { 2162 if (signo > 0) 2163 { 2164 const char *signo_cstr = Host::GetSignalAsCString(signo); 2165 if (signo_cstr) 2166 result.GetOutputStream().Printf("error: command returned with status %i and signal %s\n", status, signo_cstr); 2167 else 2168 result.GetOutputStream().Printf("error: command returned with status %i and signal %i\n", status, signo); 2169 } 2170 else 2171 result.GetOutputStream().Printf("error: command returned with status %i\n", status); 2172 } 2173 } 2174 else 2175 { 2176 result.GetOutputStream().Printf("error: cannot run remote shell commands without a platform\n"); 2177 error.SetErrorString("error: cannot run remote shell commands without a platform"); 2178 } 2179 2180 if (error.Fail()) 2181 { 2182 result.AppendError(error.AsCString()); 2183 result.SetStatus (eReturnStatusFailed); 2184 } 2185 else 2186 { 2187 result.SetStatus (eReturnStatusSuccessFinishResult); 2188 } 2189 return true; 2190 } 2191 CommandOptions m_options; 2192 }; 2193 2194 OptionDefinition 2195 CommandObjectPlatformShell::CommandOptions::g_option_table[] = 2196 { 2197 { 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."}, 2198 { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } 2199 }; 2200 2201 2202 //---------------------------------------------------------------------- 2203 // "platform install" - install a target to a remote end 2204 //---------------------------------------------------------------------- 2205 class CommandObjectPlatformInstall : public CommandObjectParsed 2206 { 2207 public: 2208 CommandObjectPlatformInstall (CommandInterpreter &interpreter) : 2209 CommandObjectParsed (interpreter, 2210 "platform target-install", 2211 "Install a target (bundle or executable file) to the remote end.", 2212 "platform target-install <local-thing> <remote-sandbox>", 2213 0) 2214 { 2215 } 2216 2217 virtual 2218 ~CommandObjectPlatformInstall () 2219 { 2220 } 2221 2222 virtual bool 2223 DoExecute (Args& args, CommandReturnObject &result) 2224 { 2225 if (args.GetArgumentCount() != 2) 2226 { 2227 result.AppendError("platform target-install takes two arguments"); 2228 result.SetStatus(eReturnStatusFailed); 2229 return false; 2230 } 2231 // TODO: move the bulk of this code over to the platform itself 2232 FileSpec src(args.GetArgumentAtIndex(0), true); 2233 FileSpec dst(args.GetArgumentAtIndex(1), false); 2234 if (src.Exists() == false) 2235 { 2236 result.AppendError("source location does not exist or is not accessible"); 2237 result.SetStatus(eReturnStatusFailed); 2238 return false; 2239 } 2240 PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform()); 2241 if (!platform_sp) 2242 { 2243 result.AppendError ("no platform currently selected"); 2244 result.SetStatus (eReturnStatusFailed); 2245 return false; 2246 } 2247 2248 Error error = platform_sp->Install(src, dst); 2249 if (error.Success()) 2250 { 2251 result.SetStatus(eReturnStatusSuccessFinishNoResult); 2252 } 2253 else 2254 { 2255 result.AppendErrorWithFormat("install failed: %s", error.AsCString()); 2256 result.SetStatus(eReturnStatusFailed); 2257 } 2258 return result.Succeeded(); 2259 } 2260 private: 2261 2262 }; 2263 2264 //---------------------------------------------------------------------- 2265 // CommandObjectPlatform constructor 2266 //---------------------------------------------------------------------- 2267 CommandObjectPlatform::CommandObjectPlatform(CommandInterpreter &interpreter) : 2268 CommandObjectMultiword (interpreter, 2269 "platform", 2270 "A set of commands to manage and create platforms.", 2271 "platform [connect|disconnect|info|list|status|select] ...") 2272 { 2273 LoadSubCommand ("select", CommandObjectSP (new CommandObjectPlatformSelect (interpreter))); 2274 LoadSubCommand ("list" , CommandObjectSP (new CommandObjectPlatformList (interpreter))); 2275 LoadSubCommand ("status", CommandObjectSP (new CommandObjectPlatformStatus (interpreter))); 2276 LoadSubCommand ("connect", CommandObjectSP (new CommandObjectPlatformConnect (interpreter))); 2277 LoadSubCommand ("disconnect", CommandObjectSP (new CommandObjectPlatformDisconnect (interpreter))); 2278 LoadSubCommand ("settings", CommandObjectSP (new CommandObjectPlatformSettings (interpreter))); 2279 LoadSubCommand ("mkdir", CommandObjectSP (new CommandObjectPlatformMkDir (interpreter))); 2280 LoadSubCommand ("file", CommandObjectSP (new CommandObjectPlatformFile (interpreter))); 2281 LoadSubCommand ("get-file", CommandObjectSP (new CommandObjectPlatformGetFile (interpreter))); 2282 LoadSubCommand ("get-size", CommandObjectSP (new CommandObjectPlatformGetSize (interpreter))); 2283 LoadSubCommand ("put-file", CommandObjectSP (new CommandObjectPlatformPutFile (interpreter))); 2284 LoadSubCommand ("process", CommandObjectSP (new CommandObjectPlatformProcess (interpreter))); 2285 LoadSubCommand ("shell", CommandObjectSP (new CommandObjectPlatformShell (interpreter))); 2286 LoadSubCommand ("target-install", CommandObjectSP (new CommandObjectPlatformInstall (interpreter))); 2287 } 2288 2289 //---------------------------------------------------------------------- 2290 // Destructor 2291 //---------------------------------------------------------------------- 2292 CommandObjectPlatform::~CommandObjectPlatform() 2293 { 2294 } 2295