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