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