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