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