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