1254721Semaste//===-- CommandObjectPlatform.cpp -------------------------------*- C++ -*-===// 2254721Semaste// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6254721Semaste// 7254721Semaste//===----------------------------------------------------------------------===// 8254721Semaste 9309124Sdim#include "CommandObjectPlatform.h" 10254721Semaste#include "lldb/Core/Debugger.h" 11254721Semaste#include "lldb/Core/Module.h" 12254721Semaste#include "lldb/Core/PluginManager.h" 13321369Sdim#include "lldb/Host/OptionParser.h" 14288943Sdim#include "lldb/Host/StringConvert.h" 15254721Semaste#include "lldb/Interpreter/CommandInterpreter.h" 16276479Sdim#include "lldb/Interpreter/CommandOptionValidators.h" 17254721Semaste#include "lldb/Interpreter/CommandReturnObject.h" 18258884Semaste#include "lldb/Interpreter/OptionGroupFile.h" 19254721Semaste#include "lldb/Interpreter/OptionGroupPlatform.h" 20254721Semaste#include "lldb/Target/ExecutionContext.h" 21254721Semaste#include "lldb/Target/Platform.h" 22254721Semaste#include "lldb/Target/Process.h" 23341825Sdim#include "lldb/Utility/Args.h" 24254721Semaste 25314564Sdim#include "llvm/ADT/SmallString.h" 26314564Sdim 27254721Semasteusing namespace lldb; 28254721Semasteusing namespace lldb_private; 29254721Semaste 30314564Sdimstatic mode_t ParsePermissionString(const char *) = delete; 31254721Semaste 32314564Sdimstatic mode_t ParsePermissionString(llvm::StringRef permissions) { 33314564Sdim if (permissions.size() != 9) 34314564Sdim return (mode_t)(-1); 35314564Sdim bool user_r, user_w, user_x, group_r, group_w, group_x, world_r, world_w, 36314564Sdim world_x; 37258054Semaste 38314564Sdim user_r = (permissions[0] == 'r'); 39314564Sdim user_w = (permissions[1] == 'w'); 40314564Sdim user_x = (permissions[2] == 'x'); 41258054Semaste 42314564Sdim group_r = (permissions[3] == 'r'); 43314564Sdim group_w = (permissions[4] == 'w'); 44314564Sdim group_x = (permissions[5] == 'x'); 45314564Sdim 46314564Sdim world_r = (permissions[6] == 'r'); 47314564Sdim world_w = (permissions[7] == 'w'); 48314564Sdim world_x = (permissions[8] == 'x'); 49314564Sdim 50314564Sdim mode_t user, group, world; 51314564Sdim user = (user_r ? 4 : 0) | (user_w ? 2 : 0) | (user_x ? 1 : 0); 52314564Sdim group = (group_r ? 4 : 0) | (group_w ? 2 : 0) | (group_x ? 1 : 0); 53314564Sdim world = (world_r ? 4 : 0) | (world_w ? 2 : 0) | (world_x ? 1 : 0); 54314564Sdim 55314564Sdim return user | group | world; 56314564Sdim} 57314564Sdim 58360784Sdim#define LLDB_OPTIONS_permissions 59360784Sdim#include "CommandOptions.inc" 60258054Semaste 61314564Sdimclass OptionPermissions : public OptionGroup { 62258054Semastepublic: 63314564Sdim OptionPermissions() {} 64309124Sdim 65314564Sdim ~OptionPermissions() override = default; 66309124Sdim 67321369Sdim lldb_private::Status 68314564Sdim SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 69314564Sdim ExecutionContext *execution_context) override { 70321369Sdim Status error; 71314564Sdim char short_option = (char)GetDefinitions()[option_idx].short_option; 72314564Sdim switch (short_option) { 73314564Sdim case 'v': { 74314564Sdim if (option_arg.getAsInteger(8, m_permissions)) { 75314564Sdim m_permissions = 0777; 76314564Sdim error.SetErrorStringWithFormat("invalid value for permissions: %s", 77314564Sdim option_arg.str().c_str()); 78314564Sdim } 79314564Sdim 80314564Sdim } break; 81314564Sdim case 's': { 82314564Sdim mode_t perms = ParsePermissionString(option_arg); 83314564Sdim if (perms == (mode_t)-1) 84314564Sdim error.SetErrorStringWithFormat("invalid value for permissions: %s", 85314564Sdim option_arg.str().c_str()); 86314564Sdim else 87314564Sdim m_permissions = perms; 88314564Sdim } break; 89314564Sdim case 'r': 90314564Sdim m_permissions |= lldb::eFilePermissionsUserRead; 91314564Sdim break; 92314564Sdim case 'w': 93314564Sdim m_permissions |= lldb::eFilePermissionsUserWrite; 94314564Sdim break; 95314564Sdim case 'x': 96314564Sdim m_permissions |= lldb::eFilePermissionsUserExecute; 97314564Sdim break; 98314564Sdim case 'R': 99314564Sdim m_permissions |= lldb::eFilePermissionsGroupRead; 100314564Sdim break; 101314564Sdim case 'W': 102314564Sdim m_permissions |= lldb::eFilePermissionsGroupWrite; 103314564Sdim break; 104314564Sdim case 'X': 105314564Sdim m_permissions |= lldb::eFilePermissionsGroupExecute; 106314564Sdim break; 107314564Sdim case 'd': 108314564Sdim m_permissions |= lldb::eFilePermissionsWorldRead; 109314564Sdim break; 110314564Sdim case 't': 111314564Sdim m_permissions |= lldb::eFilePermissionsWorldWrite; 112314564Sdim break; 113314564Sdim case 'e': 114314564Sdim m_permissions |= lldb::eFilePermissionsWorldExecute; 115314564Sdim break; 116314564Sdim default: 117360784Sdim llvm_unreachable("Unimplemented option"); 118258054Semaste } 119309124Sdim 120314564Sdim return error; 121314564Sdim } 122314564Sdim 123314564Sdim void OptionParsingStarting(ExecutionContext *execution_context) override { 124314564Sdim m_permissions = 0; 125314564Sdim } 126314564Sdim 127314564Sdim llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 128314564Sdim return llvm::makeArrayRef(g_permissions_options); 129314564Sdim } 130314564Sdim 131314564Sdim // Instance variables to hold the values for command options. 132314564Sdim 133314564Sdim uint32_t m_permissions; 134314564Sdim 135258054Semasteprivate: 136314564Sdim DISALLOW_COPY_AND_ASSIGN(OptionPermissions); 137258054Semaste}; 138258054Semaste 139254721Semaste// "platform select <platform-name>" 140314564Sdimclass CommandObjectPlatformSelect : public CommandObjectParsed { 141254721Semastepublic: 142314564Sdim CommandObjectPlatformSelect(CommandInterpreter &interpreter) 143314564Sdim : CommandObjectParsed(interpreter, "platform select", 144314564Sdim "Create a platform if needed and select it as the " 145314564Sdim "current platform.", 146314564Sdim "platform select <platform-name>", 0), 147314564Sdim m_option_group(), 148314564Sdim m_platform_options( 149314564Sdim false) // Don't include the "--platform" option by passing false 150314564Sdim { 151314564Sdim m_option_group.Append(&m_platform_options, LLDB_OPT_SET_ALL, 1); 152314564Sdim m_option_group.Finalize(); 153314564Sdim } 154254721Semaste 155314564Sdim ~CommandObjectPlatformSelect() override = default; 156254721Semaste 157360784Sdim void HandleCompletion(CompletionRequest &request) override { 158341825Sdim CommandCompletions::PlatformPluginNames(GetCommandInterpreter(), request, 159341825Sdim nullptr); 160314564Sdim } 161254721Semaste 162314564Sdim Options *GetOptions() override { return &m_option_group; } 163314564Sdim 164254721Semasteprotected: 165314564Sdim bool DoExecute(Args &args, CommandReturnObject &result) override { 166314564Sdim if (args.GetArgumentCount() == 1) { 167314564Sdim const char *platform_name = args.GetArgumentAtIndex(0); 168314564Sdim if (platform_name && platform_name[0]) { 169314564Sdim const bool select = true; 170314564Sdim m_platform_options.SetPlatformName(platform_name); 171321369Sdim Status error; 172314564Sdim ArchSpec platform_arch; 173314564Sdim PlatformSP platform_sp(m_platform_options.CreatePlatformWithOptions( 174314564Sdim m_interpreter, ArchSpec(), select, error, platform_arch)); 175314564Sdim if (platform_sp) { 176353358Sdim GetDebugger().GetPlatformList().SetSelectedPlatform(platform_sp); 177288943Sdim 178314564Sdim platform_sp->GetStatus(result.GetOutputStream()); 179314564Sdim result.SetStatus(eReturnStatusSuccessFinishResult); 180314564Sdim } else { 181314564Sdim result.AppendError(error.AsCString()); 182314564Sdim result.SetStatus(eReturnStatusFailed); 183254721Semaste } 184314564Sdim } else { 185314564Sdim result.AppendError("invalid platform name"); 186314564Sdim result.SetStatus(eReturnStatusFailed); 187314564Sdim } 188314564Sdim } else { 189314564Sdim result.AppendError( 190314564Sdim "platform create takes a platform name as an argument\n"); 191314564Sdim result.SetStatus(eReturnStatusFailed); 192254721Semaste } 193314564Sdim return result.Succeeded(); 194314564Sdim } 195254721Semaste 196314564Sdim OptionGroupOptions m_option_group; 197314564Sdim OptionGroupPlatform m_platform_options; 198254721Semaste}; 199254721Semaste 200254721Semaste// "platform list" 201314564Sdimclass CommandObjectPlatformList : public CommandObjectParsed { 202254721Semastepublic: 203314564Sdim CommandObjectPlatformList(CommandInterpreter &interpreter) 204314564Sdim : CommandObjectParsed(interpreter, "platform list", 205314564Sdim "List all platforms that are available.", nullptr, 206314564Sdim 0) {} 207254721Semaste 208314564Sdim ~CommandObjectPlatformList() override = default; 209254721Semaste 210254721Semasteprotected: 211314564Sdim bool DoExecute(Args &args, CommandReturnObject &result) override { 212314564Sdim Stream &ostrm = result.GetOutputStream(); 213314564Sdim ostrm.Printf("Available platforms:\n"); 214254721Semaste 215314564Sdim PlatformSP host_platform_sp(Platform::GetHostPlatform()); 216314564Sdim ostrm.Printf("%s: %s\n", host_platform_sp->GetPluginName().GetCString(), 217314564Sdim host_platform_sp->GetDescription()); 218314564Sdim 219314564Sdim uint32_t idx; 220353358Sdim for (idx = 0; true; ++idx) { 221314564Sdim const char *plugin_name = 222314564Sdim PluginManager::GetPlatformPluginNameAtIndex(idx); 223314564Sdim if (plugin_name == nullptr) 224314564Sdim break; 225314564Sdim const char *plugin_desc = 226314564Sdim PluginManager::GetPlatformPluginDescriptionAtIndex(idx); 227314564Sdim if (plugin_desc == nullptr) 228314564Sdim break; 229314564Sdim ostrm.Printf("%s: %s\n", plugin_name, plugin_desc); 230254721Semaste } 231314564Sdim 232314564Sdim if (idx == 0) { 233314564Sdim result.AppendError("no platforms are available\n"); 234314564Sdim result.SetStatus(eReturnStatusFailed); 235314564Sdim } else 236314564Sdim result.SetStatus(eReturnStatusSuccessFinishResult); 237314564Sdim return result.Succeeded(); 238314564Sdim } 239254721Semaste}; 240254721Semaste 241254721Semaste// "platform status" 242314564Sdimclass CommandObjectPlatformStatus : public CommandObjectParsed { 243254721Semastepublic: 244314564Sdim CommandObjectPlatformStatus(CommandInterpreter &interpreter) 245314564Sdim : CommandObjectParsed(interpreter, "platform status", 246314564Sdim "Display status for the current platform.", nullptr, 247314564Sdim 0) {} 248254721Semaste 249314564Sdim ~CommandObjectPlatformStatus() override = default; 250254721Semaste 251254721Semasteprotected: 252314564Sdim bool DoExecute(Args &args, CommandReturnObject &result) override { 253314564Sdim Stream &ostrm = result.GetOutputStream(); 254314564Sdim 255353358Sdim Target *target = GetDebugger().GetSelectedTarget().get(); 256314564Sdim PlatformSP platform_sp; 257314564Sdim if (target) { 258314564Sdim platform_sp = target->GetPlatform(); 259254721Semaste } 260314564Sdim if (!platform_sp) { 261353358Sdim platform_sp = GetDebugger().GetPlatformList().GetSelectedPlatform(); 262314564Sdim } 263314564Sdim if (platform_sp) { 264314564Sdim platform_sp->GetStatus(ostrm); 265314564Sdim result.SetStatus(eReturnStatusSuccessFinishResult); 266314564Sdim } else { 267327952Sdim result.AppendError("no platform is currently selected\n"); 268314564Sdim result.SetStatus(eReturnStatusFailed); 269314564Sdim } 270314564Sdim return result.Succeeded(); 271314564Sdim } 272254721Semaste}; 273254721Semaste 274254721Semaste// "platform connect <connect-url>" 275314564Sdimclass CommandObjectPlatformConnect : public CommandObjectParsed { 276254721Semastepublic: 277314564Sdim CommandObjectPlatformConnect(CommandInterpreter &interpreter) 278314564Sdim : CommandObjectParsed( 279314564Sdim interpreter, "platform connect", 280314564Sdim "Select the current platform by providing a connection URL.", 281314564Sdim "platform connect <connect-url>", 0) {} 282254721Semaste 283314564Sdim ~CommandObjectPlatformConnect() override = default; 284254721Semaste 285254721Semasteprotected: 286314564Sdim bool DoExecute(Args &args, CommandReturnObject &result) override { 287314564Sdim Stream &ostrm = result.GetOutputStream(); 288296417Sdim 289314564Sdim PlatformSP platform_sp( 290353358Sdim GetDebugger().GetPlatformList().GetSelectedPlatform()); 291314564Sdim if (platform_sp) { 292321369Sdim Status error(platform_sp->ConnectRemote(args)); 293314564Sdim if (error.Success()) { 294314564Sdim platform_sp->GetStatus(ostrm); 295314564Sdim result.SetStatus(eReturnStatusSuccessFinishResult); 296314564Sdim 297353358Sdim platform_sp->ConnectToWaitingProcesses(GetDebugger(), error); 298314564Sdim if (error.Fail()) { 299314564Sdim result.AppendError(error.AsCString()); 300314564Sdim result.SetStatus(eReturnStatusFailed); 301254721Semaste } 302314564Sdim } else { 303314564Sdim result.AppendErrorWithFormat("%s\n", error.AsCString()); 304314564Sdim result.SetStatus(eReturnStatusFailed); 305314564Sdim } 306314564Sdim } else { 307314564Sdim result.AppendError("no platform is currently selected\n"); 308314564Sdim result.SetStatus(eReturnStatusFailed); 309254721Semaste } 310314564Sdim return result.Succeeded(); 311314564Sdim } 312314564Sdim 313314564Sdim Options *GetOptions() override { 314314564Sdim PlatformSP platform_sp( 315353358Sdim GetDebugger().GetPlatformList().GetSelectedPlatform()); 316314564Sdim OptionGroupOptions *m_platform_options = nullptr; 317314564Sdim if (platform_sp) { 318314564Sdim m_platform_options = platform_sp->GetConnectionOptions(m_interpreter); 319314564Sdim if (m_platform_options != nullptr && !m_platform_options->m_did_finalize) 320314564Sdim m_platform_options->Finalize(); 321258054Semaste } 322314564Sdim return m_platform_options; 323314564Sdim } 324254721Semaste}; 325254721Semaste 326254721Semaste// "platform disconnect" 327314564Sdimclass CommandObjectPlatformDisconnect : public CommandObjectParsed { 328254721Semastepublic: 329314564Sdim CommandObjectPlatformDisconnect(CommandInterpreter &interpreter) 330314564Sdim : CommandObjectParsed(interpreter, "platform disconnect", 331314564Sdim "Disconnect from the current platform.", 332314564Sdim "platform disconnect", 0) {} 333254721Semaste 334314564Sdim ~CommandObjectPlatformDisconnect() override = default; 335254721Semaste 336254721Semasteprotected: 337314564Sdim bool DoExecute(Args &args, CommandReturnObject &result) override { 338314564Sdim PlatformSP platform_sp( 339353358Sdim GetDebugger().GetPlatformList().GetSelectedPlatform()); 340314564Sdim if (platform_sp) { 341314564Sdim if (args.GetArgumentCount() == 0) { 342321369Sdim Status error; 343254721Semaste 344314564Sdim if (platform_sp->IsConnected()) { 345341825Sdim // Cache the instance name if there is one since we are about to 346341825Sdim // disconnect and the name might go with it. 347314564Sdim const char *hostname_cstr = platform_sp->GetHostname(); 348314564Sdim std::string hostname; 349314564Sdim if (hostname_cstr) 350314564Sdim hostname.assign(hostname_cstr); 351314564Sdim 352314564Sdim error = platform_sp->DisconnectRemote(); 353314564Sdim if (error.Success()) { 354314564Sdim Stream &ostrm = result.GetOutputStream(); 355314564Sdim if (hostname.empty()) 356314564Sdim ostrm.Printf("Disconnected from \"%s\"\n", 357314564Sdim platform_sp->GetPluginName().GetCString()); 358254721Semaste else 359314564Sdim ostrm.Printf("Disconnected from \"%s\"\n", hostname.c_str()); 360314564Sdim result.SetStatus(eReturnStatusSuccessFinishResult); 361314564Sdim } else { 362314564Sdim result.AppendErrorWithFormat("%s", error.AsCString()); 363314564Sdim result.SetStatus(eReturnStatusFailed); 364314564Sdim } 365314564Sdim } else { 366314564Sdim // Not connected... 367314564Sdim result.AppendErrorWithFormat( 368314564Sdim "not connected to '%s'", 369314564Sdim platform_sp->GetPluginName().GetCString()); 370314564Sdim result.SetStatus(eReturnStatusFailed); 371254721Semaste } 372314564Sdim } else { 373314564Sdim // Bad args 374314564Sdim result.AppendError( 375314564Sdim "\"platform disconnect\" doesn't take any arguments"); 376314564Sdim result.SetStatus(eReturnStatusFailed); 377314564Sdim } 378314564Sdim } else { 379314564Sdim result.AppendError("no platform is currently selected"); 380314564Sdim result.SetStatus(eReturnStatusFailed); 381254721Semaste } 382314564Sdim return result.Succeeded(); 383314564Sdim } 384254721Semaste}; 385258054Semaste 386258884Semaste// "platform settings" 387314564Sdimclass CommandObjectPlatformSettings : public CommandObjectParsed { 388258884Semastepublic: 389314564Sdim CommandObjectPlatformSettings(CommandInterpreter &interpreter) 390314564Sdim : CommandObjectParsed(interpreter, "platform settings", 391314564Sdim "Set settings for the current target's platform, " 392314564Sdim "or for a platform by name.", 393314564Sdim "platform settings", 0), 394314564Sdim m_options(), 395314564Sdim m_option_working_dir(LLDB_OPT_SET_1, false, "working-dir", 'w', 0, 396314564Sdim eArgTypePath, 397314564Sdim "The working directory for the platform.") { 398314564Sdim m_options.Append(&m_option_working_dir, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); 399314564Sdim } 400309124Sdim 401314564Sdim ~CommandObjectPlatformSettings() override = default; 402309124Sdim 403258884Semasteprotected: 404314564Sdim bool DoExecute(Args &args, CommandReturnObject &result) override { 405314564Sdim PlatformSP platform_sp( 406353358Sdim GetDebugger().GetPlatformList().GetSelectedPlatform()); 407314564Sdim if (platform_sp) { 408314564Sdim if (m_option_working_dir.GetOptionValue().OptionWasSet()) 409314564Sdim platform_sp->SetWorkingDirectory( 410314564Sdim m_option_working_dir.GetOptionValue().GetCurrentValue()); 411314564Sdim } else { 412314564Sdim result.AppendError("no platform is currently selected"); 413314564Sdim result.SetStatus(eReturnStatusFailed); 414258884Semaste } 415314564Sdim return result.Succeeded(); 416314564Sdim } 417309124Sdim 418314564Sdim Options *GetOptions() override { 419314564Sdim if (!m_options.DidFinalize()) 420314564Sdim m_options.Finalize(); 421314564Sdim return &m_options; 422314564Sdim } 423314564Sdim 424258884Semasteprotected: 425314564Sdim OptionGroupOptions m_options; 426314564Sdim OptionGroupFile m_option_working_dir; 427258884Semaste}; 428258884Semaste 429258054Semaste// "platform mkdir" 430314564Sdimclass CommandObjectPlatformMkDir : public CommandObjectParsed { 431258054Semastepublic: 432314564Sdim CommandObjectPlatformMkDir(CommandInterpreter &interpreter) 433314564Sdim : CommandObjectParsed(interpreter, "platform mkdir", 434314564Sdim "Make a new directory on the remote end.", nullptr, 435309124Sdim 0), 436314564Sdim m_options() {} 437309124Sdim 438314564Sdim ~CommandObjectPlatformMkDir() override = default; 439309124Sdim 440314564Sdim bool DoExecute(Args &args, CommandReturnObject &result) override { 441314564Sdim PlatformSP platform_sp( 442353358Sdim GetDebugger().GetPlatformList().GetSelectedPlatform()); 443314564Sdim if (platform_sp) { 444314564Sdim std::string cmd_line; 445314564Sdim args.GetCommandString(cmd_line); 446314564Sdim uint32_t mode; 447314564Sdim const OptionPermissions *options_permissions = 448314564Sdim (const OptionPermissions *)m_options.GetGroupWithOption('r'); 449314564Sdim if (options_permissions) 450314564Sdim mode = options_permissions->m_permissions; 451314564Sdim else 452314564Sdim mode = lldb::eFilePermissionsUserRWX | lldb::eFilePermissionsGroupRWX | 453314564Sdim lldb::eFilePermissionsWorldRX; 454344779Sdim Status error = platform_sp->MakeDirectory(FileSpec(cmd_line), mode); 455314564Sdim if (error.Success()) { 456314564Sdim result.SetStatus(eReturnStatusSuccessFinishResult); 457314564Sdim } else { 458314564Sdim result.AppendError(error.AsCString()); 459314564Sdim result.SetStatus(eReturnStatusFailed); 460314564Sdim } 461314564Sdim } else { 462314564Sdim result.AppendError("no platform currently selected\n"); 463314564Sdim result.SetStatus(eReturnStatusFailed); 464258054Semaste } 465314564Sdim return result.Succeeded(); 466314564Sdim } 467314564Sdim 468314564Sdim Options *GetOptions() override { 469314564Sdim if (!m_options.DidFinalize()) { 470314564Sdim m_options.Append(new OptionPermissions()); 471314564Sdim m_options.Finalize(); 472258054Semaste } 473314564Sdim return &m_options; 474314564Sdim } 475309124Sdim 476314564Sdim OptionGroupOptions m_options; 477258054Semaste}; 478258054Semaste 479258054Semaste// "platform fopen" 480314564Sdimclass CommandObjectPlatformFOpen : public CommandObjectParsed { 481258054Semastepublic: 482314564Sdim CommandObjectPlatformFOpen(CommandInterpreter &interpreter) 483314564Sdim : CommandObjectParsed(interpreter, "platform file open", 484314564Sdim "Open a file on the remote end.", nullptr, 0), 485314564Sdim m_options() {} 486309124Sdim 487314564Sdim ~CommandObjectPlatformFOpen() override = default; 488309124Sdim 489314564Sdim bool DoExecute(Args &args, CommandReturnObject &result) override { 490314564Sdim PlatformSP platform_sp( 491353358Sdim GetDebugger().GetPlatformList().GetSelectedPlatform()); 492314564Sdim if (platform_sp) { 493321369Sdim Status error; 494314564Sdim std::string cmd_line; 495314564Sdim args.GetCommandString(cmd_line); 496314564Sdim mode_t perms; 497314564Sdim const OptionPermissions *options_permissions = 498314564Sdim (const OptionPermissions *)m_options.GetGroupWithOption('r'); 499314564Sdim if (options_permissions) 500314564Sdim perms = options_permissions->m_permissions; 501314564Sdim else 502314564Sdim perms = lldb::eFilePermissionsUserRW | lldb::eFilePermissionsGroupRW | 503314564Sdim lldb::eFilePermissionsWorldRead; 504314564Sdim lldb::user_id_t fd = platform_sp->OpenFile( 505344779Sdim FileSpec(cmd_line), 506314564Sdim File::eOpenOptionRead | File::eOpenOptionWrite | 507314564Sdim File::eOpenOptionAppend | File::eOpenOptionCanCreate, 508314564Sdim perms, error); 509314564Sdim if (error.Success()) { 510314564Sdim result.AppendMessageWithFormat("File Descriptor = %" PRIu64 "\n", fd); 511314564Sdim result.SetStatus(eReturnStatusSuccessFinishResult); 512314564Sdim } else { 513314564Sdim result.AppendError(error.AsCString()); 514314564Sdim result.SetStatus(eReturnStatusFailed); 515314564Sdim } 516314564Sdim } else { 517314564Sdim result.AppendError("no platform currently selected\n"); 518314564Sdim result.SetStatus(eReturnStatusFailed); 519258054Semaste } 520314564Sdim return result.Succeeded(); 521314564Sdim } 522309124Sdim 523314564Sdim Options *GetOptions() override { 524314564Sdim if (!m_options.DidFinalize()) { 525314564Sdim m_options.Append(new OptionPermissions()); 526314564Sdim m_options.Finalize(); 527258054Semaste } 528314564Sdim return &m_options; 529314564Sdim } 530309124Sdim 531314564Sdim OptionGroupOptions m_options; 532258054Semaste}; 533258054Semaste 534258054Semaste// "platform fclose" 535314564Sdimclass CommandObjectPlatformFClose : public CommandObjectParsed { 536258054Semastepublic: 537314564Sdim CommandObjectPlatformFClose(CommandInterpreter &interpreter) 538314564Sdim : CommandObjectParsed(interpreter, "platform file close", 539314564Sdim "Close a file on the remote end.", nullptr, 0) {} 540309124Sdim 541314564Sdim ~CommandObjectPlatformFClose() override = default; 542309124Sdim 543314564Sdim bool DoExecute(Args &args, CommandReturnObject &result) override { 544314564Sdim PlatformSP platform_sp( 545353358Sdim GetDebugger().GetPlatformList().GetSelectedPlatform()); 546314564Sdim if (platform_sp) { 547314564Sdim std::string cmd_line; 548314564Sdim args.GetCommandString(cmd_line); 549314564Sdim const lldb::user_id_t fd = 550314564Sdim StringConvert::ToUInt64(cmd_line.c_str(), UINT64_MAX); 551321369Sdim Status error; 552314564Sdim bool success = platform_sp->CloseFile(fd, error); 553314564Sdim if (success) { 554314564Sdim result.AppendMessageWithFormat("file %" PRIu64 " closed.\n", fd); 555314564Sdim result.SetStatus(eReturnStatusSuccessFinishResult); 556314564Sdim } else { 557314564Sdim result.AppendError(error.AsCString()); 558314564Sdim result.SetStatus(eReturnStatusFailed); 559314564Sdim } 560314564Sdim } else { 561314564Sdim result.AppendError("no platform currently selected\n"); 562314564Sdim result.SetStatus(eReturnStatusFailed); 563258054Semaste } 564314564Sdim return result.Succeeded(); 565314564Sdim } 566258054Semaste}; 567258054Semaste 568258054Semaste// "platform fread" 569314564Sdim 570360784Sdim#define LLDB_OPTIONS_platform_fread 571360784Sdim#include "CommandOptions.inc" 572314564Sdim 573314564Sdimclass CommandObjectPlatformFRead : public CommandObjectParsed { 574258054Semastepublic: 575314564Sdim CommandObjectPlatformFRead(CommandInterpreter &interpreter) 576314564Sdim : CommandObjectParsed(interpreter, "platform file read", 577314564Sdim "Read data from a file on the remote end.", nullptr, 578309124Sdim 0), 579314564Sdim m_options() {} 580314564Sdim 581314564Sdim ~CommandObjectPlatformFRead() override = default; 582314564Sdim 583314564Sdim bool DoExecute(Args &args, CommandReturnObject &result) override { 584314564Sdim PlatformSP platform_sp( 585353358Sdim GetDebugger().GetPlatformList().GetSelectedPlatform()); 586314564Sdim if (platform_sp) { 587314564Sdim std::string cmd_line; 588314564Sdim args.GetCommandString(cmd_line); 589314564Sdim const lldb::user_id_t fd = 590314564Sdim StringConvert::ToUInt64(cmd_line.c_str(), UINT64_MAX); 591314564Sdim std::string buffer(m_options.m_count, 0); 592321369Sdim Status error; 593314564Sdim uint32_t retcode = platform_sp->ReadFile( 594314564Sdim fd, m_options.m_offset, &buffer[0], m_options.m_count, error); 595314564Sdim result.AppendMessageWithFormat("Return = %d\n", retcode); 596314564Sdim result.AppendMessageWithFormat("Data = \"%s\"\n", buffer.c_str()); 597314564Sdim result.SetStatus(eReturnStatusSuccessFinishResult); 598314564Sdim } else { 599314564Sdim result.AppendError("no platform currently selected\n"); 600314564Sdim result.SetStatus(eReturnStatusFailed); 601258054Semaste } 602314564Sdim return result.Succeeded(); 603314564Sdim } 604309124Sdim 605314564Sdim Options *GetOptions() override { return &m_options; } 606309124Sdim 607314564Sdimprotected: 608314564Sdim class CommandOptions : public Options { 609314564Sdim public: 610314564Sdim CommandOptions() : Options() {} 611314564Sdim 612314564Sdim ~CommandOptions() override = default; 613314564Sdim 614321369Sdim Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 615321369Sdim ExecutionContext *execution_context) override { 616321369Sdim Status error; 617314564Sdim char short_option = (char)m_getopt_table[option_idx].val; 618314564Sdim 619314564Sdim switch (short_option) { 620314564Sdim case 'o': 621314564Sdim if (option_arg.getAsInteger(0, m_offset)) 622314564Sdim error.SetErrorStringWithFormat("invalid offset: '%s'", 623314564Sdim option_arg.str().c_str()); 624314564Sdim break; 625314564Sdim case 'c': 626314564Sdim if (option_arg.getAsInteger(0, m_count)) 627314564Sdim error.SetErrorStringWithFormat("invalid offset: '%s'", 628314564Sdim option_arg.str().c_str()); 629314564Sdim break; 630314564Sdim default: 631360784Sdim llvm_unreachable("Unimplemented option"); 632314564Sdim } 633314564Sdim 634314564Sdim return error; 635258054Semaste } 636309124Sdim 637314564Sdim void OptionParsingStarting(ExecutionContext *execution_context) override { 638314564Sdim m_offset = 0; 639314564Sdim m_count = 1; 640258054Semaste } 641309124Sdim 642314564Sdim llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 643314564Sdim return llvm::makeArrayRef(g_platform_fread_options); 644314564Sdim } 645309124Sdim 646314564Sdim // Instance variables to hold the values for command options. 647309124Sdim 648314564Sdim uint32_t m_offset; 649314564Sdim uint32_t m_count; 650314564Sdim }; 651309124Sdim 652314564Sdim CommandOptions m_options; 653258054Semaste}; 654258054Semaste 655258054Semaste// "platform fwrite" 656314564Sdim 657360784Sdim#define LLDB_OPTIONS_platform_fwrite 658360784Sdim#include "CommandOptions.inc" 659314564Sdim 660314564Sdimclass CommandObjectPlatformFWrite : public CommandObjectParsed { 661258054Semastepublic: 662314564Sdim CommandObjectPlatformFWrite(CommandInterpreter &interpreter) 663314564Sdim : CommandObjectParsed(interpreter, "platform file write", 664314564Sdim "Write data to a file on the remote end.", nullptr, 665309124Sdim 0), 666314564Sdim m_options() {} 667314564Sdim 668314564Sdim ~CommandObjectPlatformFWrite() override = default; 669314564Sdim 670314564Sdim bool DoExecute(Args &args, CommandReturnObject &result) override { 671314564Sdim PlatformSP platform_sp( 672353358Sdim GetDebugger().GetPlatformList().GetSelectedPlatform()); 673314564Sdim if (platform_sp) { 674314564Sdim std::string cmd_line; 675314564Sdim args.GetCommandString(cmd_line); 676321369Sdim Status error; 677314564Sdim const lldb::user_id_t fd = 678314564Sdim StringConvert::ToUInt64(cmd_line.c_str(), UINT64_MAX); 679314564Sdim uint32_t retcode = 680314564Sdim platform_sp->WriteFile(fd, m_options.m_offset, &m_options.m_data[0], 681314564Sdim m_options.m_data.size(), error); 682314564Sdim result.AppendMessageWithFormat("Return = %d\n", retcode); 683314564Sdim result.SetStatus(eReturnStatusSuccessFinishResult); 684314564Sdim } else { 685314564Sdim result.AppendError("no platform currently selected\n"); 686314564Sdim result.SetStatus(eReturnStatusFailed); 687258054Semaste } 688314564Sdim return result.Succeeded(); 689314564Sdim } 690309124Sdim 691314564Sdim Options *GetOptions() override { return &m_options; } 692309124Sdim 693314564Sdimprotected: 694314564Sdim class CommandOptions : public Options { 695314564Sdim public: 696314564Sdim CommandOptions() : Options() {} 697314564Sdim 698314564Sdim ~CommandOptions() override = default; 699314564Sdim 700321369Sdim Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 701321369Sdim ExecutionContext *execution_context) override { 702321369Sdim Status error; 703314564Sdim char short_option = (char)m_getopt_table[option_idx].val; 704314564Sdim 705314564Sdim switch (short_option) { 706314564Sdim case 'o': 707314564Sdim if (option_arg.getAsInteger(0, m_offset)) 708314564Sdim error.SetErrorStringWithFormat("invalid offset: '%s'", 709314564Sdim option_arg.str().c_str()); 710314564Sdim break; 711314564Sdim case 'd': 712314564Sdim m_data.assign(option_arg); 713314564Sdim break; 714314564Sdim default: 715360784Sdim llvm_unreachable("Unimplemented option"); 716314564Sdim } 717314564Sdim 718314564Sdim return error; 719258054Semaste } 720309124Sdim 721314564Sdim void OptionParsingStarting(ExecutionContext *execution_context) override { 722314564Sdim m_offset = 0; 723314564Sdim m_data.clear(); 724258054Semaste } 725309124Sdim 726314564Sdim llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 727314564Sdim return llvm::makeArrayRef(g_platform_fwrite_options); 728314564Sdim } 729309124Sdim 730314564Sdim // Instance variables to hold the values for command options. 731309124Sdim 732314564Sdim uint32_t m_offset; 733314564Sdim std::string m_data; 734314564Sdim }; 735309124Sdim 736314564Sdim CommandOptions m_options; 737258054Semaste}; 738258054Semaste 739314564Sdimclass CommandObjectPlatformFile : public CommandObjectMultiword { 740258054Semastepublic: 741314564Sdim // Constructors and Destructors 742314564Sdim CommandObjectPlatformFile(CommandInterpreter &interpreter) 743314564Sdim : CommandObjectMultiword( 744314564Sdim interpreter, "platform file", 745314564Sdim "Commands to access files on the current platform.", 746314564Sdim "platform file [open|close|read|write] ...") { 747314564Sdim LoadSubCommand( 748314564Sdim "open", CommandObjectSP(new CommandObjectPlatformFOpen(interpreter))); 749314564Sdim LoadSubCommand( 750314564Sdim "close", CommandObjectSP(new CommandObjectPlatformFClose(interpreter))); 751314564Sdim LoadSubCommand( 752314564Sdim "read", CommandObjectSP(new CommandObjectPlatformFRead(interpreter))); 753314564Sdim LoadSubCommand( 754314564Sdim "write", CommandObjectSP(new CommandObjectPlatformFWrite(interpreter))); 755314564Sdim } 756309124Sdim 757314564Sdim ~CommandObjectPlatformFile() override = default; 758309124Sdim 759258054Semasteprivate: 760314564Sdim // For CommandObjectPlatform only 761314564Sdim DISALLOW_COPY_AND_ASSIGN(CommandObjectPlatformFile); 762258054Semaste}; 763258054Semaste 764258054Semaste// "platform get-file remote-file-path host-file-path" 765314564Sdimclass CommandObjectPlatformGetFile : public CommandObjectParsed { 766258054Semastepublic: 767314564Sdim CommandObjectPlatformGetFile(CommandInterpreter &interpreter) 768314564Sdim : CommandObjectParsed( 769314564Sdim interpreter, "platform get-file", 770314564Sdim "Transfer a file from the remote end to the local host.", 771314564Sdim "platform get-file <remote-file-spec> <local-file-spec>", 0) { 772314564Sdim SetHelpLong( 773314564Sdim R"(Examples: 774258054Semaste 775288943Sdim(lldb) platform get-file /the/remote/file/path /the/local/file/path 776288943Sdim 777314564Sdim Transfer a file from the remote end with file path /the/remote/file/path to the local host.)"); 778288943Sdim 779314564Sdim CommandArgumentEntry arg1, arg2; 780314564Sdim CommandArgumentData file_arg_remote, file_arg_host; 781258054Semaste 782314564Sdim // Define the first (and only) variant of this arg. 783314564Sdim file_arg_remote.arg_type = eArgTypeFilename; 784314564Sdim file_arg_remote.arg_repetition = eArgRepeatPlain; 785314564Sdim // There is only one variant this argument could be; put it into the 786314564Sdim // argument entry. 787314564Sdim arg1.push_back(file_arg_remote); 788309124Sdim 789314564Sdim // Define the second (and only) variant of this arg. 790314564Sdim file_arg_host.arg_type = eArgTypeFilename; 791314564Sdim file_arg_host.arg_repetition = eArgRepeatPlain; 792314564Sdim // There is only one variant this argument could be; put it into the 793314564Sdim // argument entry. 794314564Sdim arg2.push_back(file_arg_host); 795309124Sdim 796341825Sdim // Push the data for the first and the second arguments into the 797341825Sdim // m_arguments vector. 798314564Sdim m_arguments.push_back(arg1); 799314564Sdim m_arguments.push_back(arg2); 800314564Sdim } 801258054Semaste 802314564Sdim ~CommandObjectPlatformGetFile() override = default; 803314564Sdim 804314564Sdim bool DoExecute(Args &args, CommandReturnObject &result) override { 805314564Sdim // If the number of arguments is incorrect, issue an error message. 806314564Sdim if (args.GetArgumentCount() != 2) { 807314564Sdim result.GetErrorStream().Printf("error: required arguments missing; " 808314564Sdim "specify both the source and destination " 809314564Sdim "file paths\n"); 810314564Sdim result.SetStatus(eReturnStatusFailed); 811314564Sdim return false; 812258054Semaste } 813314564Sdim 814314564Sdim PlatformSP platform_sp( 815353358Sdim GetDebugger().GetPlatformList().GetSelectedPlatform()); 816314564Sdim if (platform_sp) { 817314564Sdim const char *remote_file_path = args.GetArgumentAtIndex(0); 818314564Sdim const char *local_file_path = args.GetArgumentAtIndex(1); 819344779Sdim Status error = platform_sp->GetFile(FileSpec(remote_file_path), 820344779Sdim FileSpec(local_file_path)); 821314564Sdim if (error.Success()) { 822314564Sdim result.AppendMessageWithFormat( 823314564Sdim "successfully get-file from %s (remote) to %s (host)\n", 824314564Sdim remote_file_path, local_file_path); 825314564Sdim result.SetStatus(eReturnStatusSuccessFinishResult); 826314564Sdim } else { 827314564Sdim result.AppendMessageWithFormat("get-file failed: %s\n", 828314564Sdim error.AsCString()); 829314564Sdim result.SetStatus(eReturnStatusFailed); 830314564Sdim } 831314564Sdim } else { 832314564Sdim result.AppendError("no platform currently selected\n"); 833314564Sdim result.SetStatus(eReturnStatusFailed); 834314564Sdim } 835314564Sdim return result.Succeeded(); 836314564Sdim } 837258054Semaste}; 838258054Semaste 839258054Semaste// "platform get-size remote-file-path" 840314564Sdimclass CommandObjectPlatformGetSize : public CommandObjectParsed { 841258054Semastepublic: 842314564Sdim CommandObjectPlatformGetSize(CommandInterpreter &interpreter) 843314564Sdim : CommandObjectParsed(interpreter, "platform get-size", 844314564Sdim "Get the file size from the remote end.", 845314564Sdim "platform get-size <remote-file-spec>", 0) { 846314564Sdim SetHelpLong( 847314564Sdim R"(Examples: 848258054Semaste 849288943Sdim(lldb) platform get-size /the/remote/file/path 850288943Sdim 851314564Sdim Get the file size from the remote end with path /the/remote/file/path.)"); 852288943Sdim 853314564Sdim CommandArgumentEntry arg1; 854314564Sdim CommandArgumentData file_arg_remote; 855309124Sdim 856314564Sdim // Define the first (and only) variant of this arg. 857314564Sdim file_arg_remote.arg_type = eArgTypeFilename; 858314564Sdim file_arg_remote.arg_repetition = eArgRepeatPlain; 859314564Sdim // There is only one variant this argument could be; put it into the 860314564Sdim // argument entry. 861314564Sdim arg1.push_back(file_arg_remote); 862309124Sdim 863314564Sdim // Push the data for the first argument into the m_arguments vector. 864314564Sdim m_arguments.push_back(arg1); 865314564Sdim } 866258054Semaste 867314564Sdim ~CommandObjectPlatformGetSize() override = default; 868314564Sdim 869314564Sdim bool DoExecute(Args &args, CommandReturnObject &result) override { 870314564Sdim // If the number of arguments is incorrect, issue an error message. 871314564Sdim if (args.GetArgumentCount() != 1) { 872314564Sdim result.GetErrorStream().Printf("error: required argument missing; " 873314564Sdim "specify the source file path as the only " 874314564Sdim "argument\n"); 875314564Sdim result.SetStatus(eReturnStatusFailed); 876314564Sdim return false; 877258054Semaste } 878314564Sdim 879314564Sdim PlatformSP platform_sp( 880353358Sdim GetDebugger().GetPlatformList().GetSelectedPlatform()); 881314564Sdim if (platform_sp) { 882314564Sdim std::string remote_file_path(args.GetArgumentAtIndex(0)); 883344779Sdim user_id_t size = platform_sp->GetFileSize(FileSpec(remote_file_path)); 884314564Sdim if (size != UINT64_MAX) { 885314564Sdim result.AppendMessageWithFormat("File size of %s (remote): %" PRIu64 886314564Sdim "\n", 887314564Sdim remote_file_path.c_str(), size); 888314564Sdim result.SetStatus(eReturnStatusSuccessFinishResult); 889314564Sdim } else { 890314564Sdim result.AppendMessageWithFormat( 891314564Sdim "Error getting file size of %s (remote)\n", 892314564Sdim remote_file_path.c_str()); 893314564Sdim result.SetStatus(eReturnStatusFailed); 894314564Sdim } 895314564Sdim } else { 896314564Sdim result.AppendError("no platform currently selected\n"); 897314564Sdim result.SetStatus(eReturnStatusFailed); 898314564Sdim } 899314564Sdim return result.Succeeded(); 900314564Sdim } 901258054Semaste}; 902258054Semaste 903258054Semaste// "platform put-file" 904314564Sdimclass CommandObjectPlatformPutFile : public CommandObjectParsed { 905258054Semastepublic: 906314564Sdim CommandObjectPlatformPutFile(CommandInterpreter &interpreter) 907314564Sdim : CommandObjectParsed( 908314564Sdim interpreter, "platform put-file", 909314564Sdim "Transfer a file from this system to the remote end.", nullptr, 0) { 910314564Sdim } 911309124Sdim 912314564Sdim ~CommandObjectPlatformPutFile() override = default; 913309124Sdim 914314564Sdim bool DoExecute(Args &args, CommandReturnObject &result) override { 915314564Sdim const char *src = args.GetArgumentAtIndex(0); 916314564Sdim const char *dst = args.GetArgumentAtIndex(1); 917258054Semaste 918344779Sdim FileSpec src_fs(src); 919344779Sdim FileSystem::Instance().Resolve(src_fs); 920344779Sdim FileSpec dst_fs(dst ? dst : src_fs.GetFilename().GetCString()); 921288943Sdim 922314564Sdim PlatformSP platform_sp( 923353358Sdim GetDebugger().GetPlatformList().GetSelectedPlatform()); 924314564Sdim if (platform_sp) { 925321369Sdim Status error(platform_sp->PutFile(src_fs, dst_fs)); 926314564Sdim if (error.Success()) { 927314564Sdim result.SetStatus(eReturnStatusSuccessFinishNoResult); 928314564Sdim } else { 929314564Sdim result.AppendError(error.AsCString()); 930314564Sdim result.SetStatus(eReturnStatusFailed); 931314564Sdim } 932314564Sdim } else { 933314564Sdim result.AppendError("no platform currently selected\n"); 934314564Sdim result.SetStatus(eReturnStatusFailed); 935258054Semaste } 936314564Sdim return result.Succeeded(); 937314564Sdim } 938258054Semaste}; 939258054Semaste 940254721Semaste// "platform process launch" 941314564Sdimclass CommandObjectPlatformProcessLaunch : public CommandObjectParsed { 942254721Semastepublic: 943314564Sdim CommandObjectPlatformProcessLaunch(CommandInterpreter &interpreter) 944314564Sdim : CommandObjectParsed(interpreter, "platform process launch", 945314564Sdim "Launch a new process on a remote platform.", 946314564Sdim "platform process launch program", 947314564Sdim eCommandRequiresTarget | eCommandTryTargetAPILock), 948314564Sdim m_options() {} 949309124Sdim 950314564Sdim ~CommandObjectPlatformProcessLaunch() override = default; 951309124Sdim 952314564Sdim Options *GetOptions() override { return &m_options; } 953314564Sdim 954314564Sdimprotected: 955314564Sdim bool DoExecute(Args &args, CommandReturnObject &result) override { 956353358Sdim Target *target = GetDebugger().GetSelectedTarget().get(); 957314564Sdim PlatformSP platform_sp; 958314564Sdim if (target) { 959314564Sdim platform_sp = target->GetPlatform(); 960254721Semaste } 961314564Sdim if (!platform_sp) { 962353358Sdim platform_sp = GetDebugger().GetPlatformList().GetSelectedPlatform(); 963314564Sdim } 964254721Semaste 965314564Sdim if (platform_sp) { 966321369Sdim Status error; 967314564Sdim const size_t argc = args.GetArgumentCount(); 968314564Sdim Target *target = m_exe_ctx.GetTargetPtr(); 969314564Sdim Module *exe_module = target->GetExecutableModulePointer(); 970314564Sdim if (exe_module) { 971314564Sdim m_options.launch_info.GetExecutableFile() = exe_module->GetFileSpec(); 972344779Sdim llvm::SmallString<128> exe_path; 973314564Sdim m_options.launch_info.GetExecutableFile().GetPath(exe_path); 974314564Sdim if (!exe_path.empty()) 975314564Sdim m_options.launch_info.GetArguments().AppendArgument(exe_path); 976314564Sdim m_options.launch_info.GetArchitecture() = exe_module->GetArchitecture(); 977314564Sdim } 978254721Semaste 979314564Sdim if (argc > 0) { 980314564Sdim if (m_options.launch_info.GetExecutableFile()) { 981341825Sdim // We already have an executable file, so we will use this and all 982341825Sdim // arguments to this function are extra arguments 983314564Sdim m_options.launch_info.GetArguments().AppendArguments(args); 984314564Sdim } else { 985314564Sdim // We don't have any file yet, so the first argument is our 986314564Sdim // executable, and the rest are program arguments 987314564Sdim const bool first_arg_is_executable = true; 988314564Sdim m_options.launch_info.SetArguments(args, first_arg_is_executable); 989314564Sdim } 990314564Sdim } 991254721Semaste 992314564Sdim if (m_options.launch_info.GetExecutableFile()) { 993353358Sdim Debugger &debugger = GetDebugger(); 994254721Semaste 995314564Sdim if (argc == 0) 996314564Sdim target->GetRunArguments(m_options.launch_info.GetArguments()); 997314564Sdim 998314564Sdim ProcessSP process_sp(platform_sp->DebugProcess( 999314564Sdim m_options.launch_info, debugger, target, error)); 1000314564Sdim if (process_sp && process_sp->IsAlive()) { 1001314564Sdim result.SetStatus(eReturnStatusSuccessFinishNoResult); 1002314564Sdim return true; 1003254721Semaste } 1004314564Sdim 1005314564Sdim if (error.Success()) 1006314564Sdim result.AppendError("process launch failed"); 1007254721Semaste else 1008314564Sdim result.AppendError(error.AsCString()); 1009314564Sdim result.SetStatus(eReturnStatusFailed); 1010314564Sdim } else { 1011314564Sdim result.AppendError("'platform process launch' uses the current target " 1012314564Sdim "file and arguments, or the executable and its " 1013314564Sdim "arguments can be specified in this command"); 1014314564Sdim result.SetStatus(eReturnStatusFailed); 1015314564Sdim return false; 1016314564Sdim } 1017314564Sdim } else { 1018314564Sdim result.AppendError("no platform is selected\n"); 1019254721Semaste } 1020314564Sdim return result.Succeeded(); 1021314564Sdim } 1022314564Sdim 1023254721Semasteprotected: 1024314564Sdim ProcessLaunchCommandOptions m_options; 1025254721Semaste}; 1026254721Semaste 1027254721Semaste// "platform process list" 1028314564Sdim 1029360784Sdimstatic PosixPlatformCommandOptionValidator posix_validator; 1030360784Sdim#define LLDB_OPTIONS_platform_process_list 1031360784Sdim#include "CommandOptions.inc" 1032314564Sdim 1033314564Sdimclass CommandObjectPlatformProcessList : public CommandObjectParsed { 1034254721Semastepublic: 1035314564Sdim CommandObjectPlatformProcessList(CommandInterpreter &interpreter) 1036314564Sdim : CommandObjectParsed(interpreter, "platform process list", 1037314564Sdim "List processes on a remote platform by name, pid, " 1038314564Sdim "or many other matching attributes.", 1039314564Sdim "platform process list", 0), 1040314564Sdim m_options() {} 1041309124Sdim 1042314564Sdim ~CommandObjectPlatformProcessList() override = default; 1043309124Sdim 1044314564Sdim Options *GetOptions() override { return &m_options; } 1045314564Sdim 1046314564Sdimprotected: 1047314564Sdim bool DoExecute(Args &args, CommandReturnObject &result) override { 1048353358Sdim Target *target = GetDebugger().GetSelectedTarget().get(); 1049314564Sdim PlatformSP platform_sp; 1050314564Sdim if (target) { 1051314564Sdim platform_sp = target->GetPlatform(); 1052254721Semaste } 1053314564Sdim if (!platform_sp) { 1054353358Sdim platform_sp = GetDebugger().GetPlatformList().GetSelectedPlatform(); 1055314564Sdim } 1056254721Semaste 1057314564Sdim if (platform_sp) { 1058321369Sdim Status error; 1059314564Sdim if (args.GetArgumentCount() == 0) { 1060314564Sdim if (platform_sp) { 1061314564Sdim Stream &ostrm = result.GetOutputStream(); 1062254721Semaste 1063314564Sdim lldb::pid_t pid = 1064314564Sdim m_options.match_info.GetProcessInfo().GetProcessID(); 1065314564Sdim if (pid != LLDB_INVALID_PROCESS_ID) { 1066314564Sdim ProcessInstanceInfo proc_info; 1067314564Sdim if (platform_sp->GetProcessInfo(pid, proc_info)) { 1068353358Sdim ProcessInstanceInfo::DumpTableHeader(ostrm, m_options.show_args, 1069314564Sdim m_options.verbose); 1070353358Sdim proc_info.DumpAsTableRow(ostrm, platform_sp->GetUserIDResolver(), 1071314564Sdim m_options.show_args, m_options.verbose); 1072314564Sdim result.SetStatus(eReturnStatusSuccessFinishResult); 1073314564Sdim } else { 1074314564Sdim result.AppendErrorWithFormat( 1075314564Sdim "no process found with pid = %" PRIu64 "\n", pid); 1076314564Sdim result.SetStatus(eReturnStatusFailed); 1077254721Semaste } 1078314564Sdim } else { 1079314564Sdim ProcessInstanceInfoList proc_infos; 1080314564Sdim const uint32_t matches = 1081314564Sdim platform_sp->FindProcesses(m_options.match_info, proc_infos); 1082314564Sdim const char *match_desc = nullptr; 1083314564Sdim const char *match_name = 1084314564Sdim m_options.match_info.GetProcessInfo().GetName(); 1085314564Sdim if (match_name && match_name[0]) { 1086314564Sdim switch (m_options.match_info.GetNameMatchType()) { 1087321369Sdim case NameMatch::Ignore: 1088314564Sdim break; 1089321369Sdim case NameMatch::Equals: 1090314564Sdim match_desc = "matched"; 1091314564Sdim break; 1092321369Sdim case NameMatch::Contains: 1093314564Sdim match_desc = "contained"; 1094314564Sdim break; 1095321369Sdim case NameMatch::StartsWith: 1096314564Sdim match_desc = "started with"; 1097314564Sdim break; 1098321369Sdim case NameMatch::EndsWith: 1099314564Sdim match_desc = "ended with"; 1100314564Sdim break; 1101321369Sdim case NameMatch::RegularExpression: 1102314564Sdim match_desc = "matched the regular expression"; 1103314564Sdim break; 1104314564Sdim } 1105254721Semaste } 1106314564Sdim 1107314564Sdim if (matches == 0) { 1108314564Sdim if (match_desc) 1109314564Sdim result.AppendErrorWithFormat( 1110314564Sdim "no processes were found that %s \"%s\" on the \"%s\" " 1111314564Sdim "platform\n", 1112314564Sdim match_desc, match_name, 1113314564Sdim platform_sp->GetPluginName().GetCString()); 1114314564Sdim else 1115314564Sdim result.AppendErrorWithFormat( 1116314564Sdim "no processes were found on the \"%s\" platform\n", 1117314564Sdim platform_sp->GetPluginName().GetCString()); 1118314564Sdim result.SetStatus(eReturnStatusFailed); 1119314564Sdim } else { 1120314564Sdim result.AppendMessageWithFormat( 1121314564Sdim "%u matching process%s found on \"%s\"", matches, 1122314564Sdim matches > 1 ? "es were" : " was", 1123314564Sdim platform_sp->GetName().GetCString()); 1124314564Sdim if (match_desc) 1125314564Sdim result.AppendMessageWithFormat(" whose name %s \"%s\"", 1126314564Sdim match_desc, match_name); 1127314564Sdim result.AppendMessageWithFormat("\n"); 1128353358Sdim ProcessInstanceInfo::DumpTableHeader(ostrm, m_options.show_args, 1129314564Sdim m_options.verbose); 1130314564Sdim for (uint32_t i = 0; i < matches; ++i) { 1131314564Sdim proc_infos.GetProcessInfoAtIndex(i).DumpAsTableRow( 1132353358Sdim ostrm, platform_sp->GetUserIDResolver(), 1133353358Sdim m_options.show_args, m_options.verbose); 1134314564Sdim } 1135314564Sdim } 1136314564Sdim } 1137254721Semaste } 1138314564Sdim } else { 1139314564Sdim result.AppendError("invalid args: process list takes only options\n"); 1140314564Sdim result.SetStatus(eReturnStatusFailed); 1141314564Sdim } 1142314564Sdim } else { 1143314564Sdim result.AppendError("no platform is selected\n"); 1144314564Sdim result.SetStatus(eReturnStatusFailed); 1145314564Sdim } 1146314564Sdim return result.Succeeded(); 1147314564Sdim } 1148314564Sdim 1149314564Sdim class CommandOptions : public Options { 1150314564Sdim public: 1151314564Sdim CommandOptions() 1152360784Sdim : Options(), match_info(), show_args(false), verbose(false) {} 1153309124Sdim 1154314564Sdim ~CommandOptions() override = default; 1155309124Sdim 1156321369Sdim Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1157321369Sdim ExecutionContext *execution_context) override { 1158321369Sdim Status error; 1159314564Sdim const int short_option = m_getopt_table[option_idx].val; 1160314564Sdim bool success = false; 1161254721Semaste 1162314564Sdim uint32_t id = LLDB_INVALID_PROCESS_ID; 1163314564Sdim success = !option_arg.getAsInteger(0, id); 1164314564Sdim switch (short_option) { 1165314564Sdim case 'p': { 1166314564Sdim match_info.GetProcessInfo().SetProcessID(id); 1167314564Sdim if (!success) 1168314564Sdim error.SetErrorStringWithFormat("invalid process ID string: '%s'", 1169314564Sdim option_arg.str().c_str()); 1170314564Sdim break; 1171314564Sdim } 1172314564Sdim case 'P': 1173314564Sdim match_info.GetProcessInfo().SetParentProcessID(id); 1174314564Sdim if (!success) 1175314564Sdim error.SetErrorStringWithFormat( 1176314564Sdim "invalid parent process ID string: '%s'", 1177314564Sdim option_arg.str().c_str()); 1178314564Sdim break; 1179254721Semaste 1180314564Sdim case 'u': 1181314564Sdim match_info.GetProcessInfo().SetUserID(success ? id : UINT32_MAX); 1182314564Sdim if (!success) 1183314564Sdim error.SetErrorStringWithFormat("invalid user ID string: '%s'", 1184314564Sdim option_arg.str().c_str()); 1185314564Sdim break; 1186254721Semaste 1187314564Sdim case 'U': 1188314564Sdim match_info.GetProcessInfo().SetEffectiveUserID(success ? id 1189314564Sdim : UINT32_MAX); 1190314564Sdim if (!success) 1191314564Sdim error.SetErrorStringWithFormat( 1192314564Sdim "invalid effective user ID string: '%s'", 1193314564Sdim option_arg.str().c_str()); 1194314564Sdim break; 1195254721Semaste 1196314564Sdim case 'g': 1197314564Sdim match_info.GetProcessInfo().SetGroupID(success ? id : UINT32_MAX); 1198314564Sdim if (!success) 1199314564Sdim error.SetErrorStringWithFormat("invalid group ID string: '%s'", 1200314564Sdim option_arg.str().c_str()); 1201314564Sdim break; 1202254721Semaste 1203314564Sdim case 'G': 1204314564Sdim match_info.GetProcessInfo().SetEffectiveGroupID(success ? id 1205314564Sdim : UINT32_MAX); 1206314564Sdim if (!success) 1207314564Sdim error.SetErrorStringWithFormat( 1208314564Sdim "invalid effective group ID string: '%s'", 1209314564Sdim option_arg.str().c_str()); 1210314564Sdim break; 1211254721Semaste 1212314564Sdim case 'a': { 1213314564Sdim TargetSP target_sp = 1214314564Sdim execution_context ? execution_context->GetTargetSP() : TargetSP(); 1215314564Sdim DebuggerSP debugger_sp = 1216314564Sdim target_sp ? target_sp->GetDebugger().shared_from_this() 1217314564Sdim : DebuggerSP(); 1218314564Sdim PlatformSP platform_sp = 1219314564Sdim debugger_sp ? debugger_sp->GetPlatformList().GetSelectedPlatform() 1220314564Sdim : PlatformSP(); 1221327952Sdim match_info.GetProcessInfo().GetArchitecture() = 1222327952Sdim Platform::GetAugmentedArchSpec(platform_sp.get(), option_arg); 1223314564Sdim } break; 1224254721Semaste 1225314564Sdim case 'n': 1226341825Sdim match_info.GetProcessInfo().GetExecutableFile().SetFile( 1227344779Sdim option_arg, FileSpec::Style::native); 1228321369Sdim match_info.SetNameMatchType(NameMatch::Equals); 1229314564Sdim break; 1230254721Semaste 1231314564Sdim case 'e': 1232341825Sdim match_info.GetProcessInfo().GetExecutableFile().SetFile( 1233344779Sdim option_arg, FileSpec::Style::native); 1234321369Sdim match_info.SetNameMatchType(NameMatch::EndsWith); 1235314564Sdim break; 1236254721Semaste 1237314564Sdim case 's': 1238341825Sdim match_info.GetProcessInfo().GetExecutableFile().SetFile( 1239344779Sdim option_arg, FileSpec::Style::native); 1240321369Sdim match_info.SetNameMatchType(NameMatch::StartsWith); 1241314564Sdim break; 1242254721Semaste 1243314564Sdim case 'c': 1244341825Sdim match_info.GetProcessInfo().GetExecutableFile().SetFile( 1245344779Sdim option_arg, FileSpec::Style::native); 1246321369Sdim match_info.SetNameMatchType(NameMatch::Contains); 1247314564Sdim break; 1248254721Semaste 1249314564Sdim case 'r': 1250341825Sdim match_info.GetProcessInfo().GetExecutableFile().SetFile( 1251344779Sdim option_arg, FileSpec::Style::native); 1252321369Sdim match_info.SetNameMatchType(NameMatch::RegularExpression); 1253314564Sdim break; 1254254721Semaste 1255314564Sdim case 'A': 1256314564Sdim show_args = true; 1257314564Sdim break; 1258309124Sdim 1259314564Sdim case 'v': 1260314564Sdim verbose = true; 1261314564Sdim break; 1262309124Sdim 1263360784Sdim case 'x': 1264360784Sdim match_info.SetMatchAllUsers(true); 1265360784Sdim break; 1266360784Sdim 1267314564Sdim default: 1268360784Sdim llvm_unreachable("Unimplemented option"); 1269314564Sdim } 1270254721Semaste 1271314564Sdim return error; 1272314564Sdim } 1273314564Sdim 1274314564Sdim void OptionParsingStarting(ExecutionContext *execution_context) override { 1275314564Sdim match_info.Clear(); 1276314564Sdim show_args = false; 1277314564Sdim verbose = false; 1278314564Sdim } 1279314564Sdim 1280314564Sdim llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1281314564Sdim return llvm::makeArrayRef(g_platform_process_list_options); 1282314564Sdim } 1283314564Sdim 1284314564Sdim // Instance variables to hold the values for command options. 1285314564Sdim 1286314564Sdim ProcessInstanceInfoMatch match_info; 1287314564Sdim bool show_args; 1288314564Sdim bool verbose; 1289314564Sdim }; 1290314564Sdim 1291314564Sdim CommandOptions m_options; 1292254721Semaste}; 1293254721Semaste 1294254721Semaste// "platform process info" 1295314564Sdimclass CommandObjectPlatformProcessInfo : public CommandObjectParsed { 1296254721Semastepublic: 1297314564Sdim CommandObjectPlatformProcessInfo(CommandInterpreter &interpreter) 1298314564Sdim : CommandObjectParsed( 1299314564Sdim interpreter, "platform process info", 1300314564Sdim "Get detailed information for one or more process by process ID.", 1301314564Sdim "platform process info <pid> [<pid> <pid> ...]", 0) { 1302314564Sdim CommandArgumentEntry arg; 1303314564Sdim CommandArgumentData pid_args; 1304309124Sdim 1305314564Sdim // Define the first (and only) variant of this arg. 1306314564Sdim pid_args.arg_type = eArgTypePid; 1307314564Sdim pid_args.arg_repetition = eArgRepeatStar; 1308309124Sdim 1309314564Sdim // There is only one variant this argument could be; put it into the 1310314564Sdim // argument entry. 1311314564Sdim arg.push_back(pid_args); 1312314564Sdim 1313314564Sdim // Push the data for the first argument into the m_arguments vector. 1314314564Sdim m_arguments.push_back(arg); 1315314564Sdim } 1316314564Sdim 1317314564Sdim ~CommandObjectPlatformProcessInfo() override = default; 1318314564Sdim 1319254721Semasteprotected: 1320314564Sdim bool DoExecute(Args &args, CommandReturnObject &result) override { 1321353358Sdim Target *target = GetDebugger().GetSelectedTarget().get(); 1322314564Sdim PlatformSP platform_sp; 1323314564Sdim if (target) { 1324314564Sdim platform_sp = target->GetPlatform(); 1325314564Sdim } 1326314564Sdim if (!platform_sp) { 1327353358Sdim platform_sp = GetDebugger().GetPlatformList().GetSelectedPlatform(); 1328314564Sdim } 1329254721Semaste 1330314564Sdim if (platform_sp) { 1331314564Sdim const size_t argc = args.GetArgumentCount(); 1332314564Sdim if (argc > 0) { 1333321369Sdim Status error; 1334314564Sdim 1335314564Sdim if (platform_sp->IsConnected()) { 1336314564Sdim Stream &ostrm = result.GetOutputStream(); 1337314564Sdim for (auto &entry : args.entries()) { 1338314564Sdim lldb::pid_t pid; 1339360784Sdim if (entry.ref().getAsInteger(0, pid)) { 1340314564Sdim result.AppendErrorWithFormat("invalid process ID argument '%s'", 1341360784Sdim entry.ref().str().c_str()); 1342314564Sdim result.SetStatus(eReturnStatusFailed); 1343314564Sdim break; 1344314564Sdim } else { 1345314564Sdim ProcessInstanceInfo proc_info; 1346314564Sdim if (platform_sp->GetProcessInfo(pid, proc_info)) { 1347314564Sdim ostrm.Printf("Process information for process %" PRIu64 ":\n", 1348314564Sdim pid); 1349353358Sdim proc_info.Dump(ostrm, platform_sp->GetUserIDResolver()); 1350314564Sdim } else { 1351314564Sdim ostrm.Printf("error: no process information is available for " 1352314564Sdim "process %" PRIu64 "\n", 1353314564Sdim pid); 1354314564Sdim } 1355314564Sdim ostrm.EOL(); 1356254721Semaste } 1357314564Sdim } 1358314564Sdim } else { 1359314564Sdim // Not connected... 1360314564Sdim result.AppendErrorWithFormat( 1361314564Sdim "not connected to '%s'", 1362314564Sdim platform_sp->GetPluginName().GetCString()); 1363314564Sdim result.SetStatus(eReturnStatusFailed); 1364254721Semaste } 1365314564Sdim } else { 1366314564Sdim // No args 1367314564Sdim result.AppendError("one or more process id(s) must be specified"); 1368314564Sdim result.SetStatus(eReturnStatusFailed); 1369314564Sdim } 1370314564Sdim } else { 1371314564Sdim result.AppendError("no platform is currently selected"); 1372314564Sdim result.SetStatus(eReturnStatusFailed); 1373254721Semaste } 1374314564Sdim return result.Succeeded(); 1375314564Sdim } 1376254721Semaste}; 1377254721Semaste 1378360784Sdim#define LLDB_OPTIONS_platform_process_attach 1379360784Sdim#include "CommandOptions.inc" 1380314564Sdim 1381314564Sdimclass CommandObjectPlatformProcessAttach : public CommandObjectParsed { 1382258054Semastepublic: 1383314564Sdim class CommandOptions : public Options { 1384314564Sdim public: 1385314564Sdim CommandOptions() : Options() { 1386314564Sdim // Keep default values of all options in one place: OptionParsingStarting 1387314564Sdim // () 1388314564Sdim OptionParsingStarting(nullptr); 1389314564Sdim } 1390314564Sdim 1391314564Sdim ~CommandOptions() override = default; 1392314564Sdim 1393321369Sdim Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1394321369Sdim ExecutionContext *execution_context) override { 1395321369Sdim Status error; 1396314564Sdim char short_option = (char)m_getopt_table[option_idx].val; 1397314564Sdim switch (short_option) { 1398314564Sdim case 'p': { 1399314564Sdim lldb::pid_t pid = LLDB_INVALID_PROCESS_ID; 1400314564Sdim if (option_arg.getAsInteger(0, pid)) { 1401314564Sdim error.SetErrorStringWithFormat("invalid process ID '%s'", 1402314564Sdim option_arg.str().c_str()); 1403314564Sdim } else { 1404314564Sdim attach_info.SetProcessID(pid); 1405258054Semaste } 1406314564Sdim } break; 1407309124Sdim 1408314564Sdim case 'P': 1409314564Sdim attach_info.SetProcessPluginName(option_arg); 1410314564Sdim break; 1411309124Sdim 1412314564Sdim case 'n': 1413344779Sdim attach_info.GetExecutableFile().SetFile(option_arg, 1414341825Sdim FileSpec::Style::native); 1415314564Sdim break; 1416314564Sdim 1417314564Sdim case 'w': 1418314564Sdim attach_info.SetWaitForLaunch(true); 1419314564Sdim break; 1420314564Sdim 1421314564Sdim default: 1422360784Sdim llvm_unreachable("Unimplemented option"); 1423314564Sdim } 1424314564Sdim return error; 1425258054Semaste } 1426309124Sdim 1427314564Sdim void OptionParsingStarting(ExecutionContext *execution_context) override { 1428314564Sdim attach_info.Clear(); 1429314564Sdim } 1430309124Sdim 1431314564Sdim llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1432314564Sdim return llvm::makeArrayRef(g_platform_process_attach_options); 1433314564Sdim } 1434314564Sdim 1435360784Sdim void HandleOptionArgumentCompletion( 1436341825Sdim CompletionRequest &request, OptionElementVector &opt_element_vector, 1437341825Sdim int opt_element_index, CommandInterpreter &interpreter) override { 1438314564Sdim int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos; 1439314564Sdim int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index; 1440314564Sdim 1441314564Sdim // We are only completing the name option for now... 1442314564Sdim 1443360784Sdim // Are we in the name? 1444360784Sdim if (GetDefinitions()[opt_defs_index].short_option != 'n') 1445360784Sdim return; 1446314564Sdim 1447360784Sdim // Look to see if there is a -P argument provided, and if so use that 1448360784Sdim // plugin, otherwise use the default plugin. 1449314564Sdim 1450360784Sdim const char *partial_name = nullptr; 1451360784Sdim partial_name = request.GetParsedLine().GetArgumentAtIndex(opt_arg_pos); 1452314564Sdim 1453360784Sdim PlatformSP platform_sp(interpreter.GetPlatform(true)); 1454360784Sdim if (!platform_sp) 1455360784Sdim return; 1456360784Sdim 1457360784Sdim ProcessInstanceInfoList process_infos; 1458360784Sdim ProcessInstanceInfoMatch match_info; 1459360784Sdim if (partial_name) { 1460360784Sdim match_info.GetProcessInfo().GetExecutableFile().SetFile( 1461360784Sdim partial_name, FileSpec::Style::native); 1462360784Sdim match_info.SetNameMatchType(NameMatch::StartsWith); 1463314564Sdim } 1464360784Sdim platform_sp->FindProcesses(match_info, process_infos); 1465360784Sdim const uint32_t num_matches = process_infos.GetSize(); 1466360784Sdim if (num_matches == 0) 1467360784Sdim return; 1468314564Sdim 1469360784Sdim for (uint32_t i = 0; i < num_matches; ++i) { 1470360784Sdim request.AddCompletion(process_infos.GetProcessNameAtIndex(i)); 1471360784Sdim } 1472360784Sdim return; 1473258054Semaste } 1474314564Sdim 1475314564Sdim // Options table: Required for subclasses of Options. 1476314564Sdim 1477314564Sdim static OptionDefinition g_option_table[]; 1478314564Sdim 1479314564Sdim // Instance variables to hold the values for command options. 1480314564Sdim 1481314564Sdim ProcessAttachInfo attach_info; 1482314564Sdim }; 1483314564Sdim 1484314564Sdim CommandObjectPlatformProcessAttach(CommandInterpreter &interpreter) 1485314564Sdim : CommandObjectParsed(interpreter, "platform process attach", 1486314564Sdim "Attach to a process.", 1487314564Sdim "platform process attach <cmd-options>"), 1488314564Sdim m_options() {} 1489314564Sdim 1490314564Sdim ~CommandObjectPlatformProcessAttach() override = default; 1491314564Sdim 1492314564Sdim bool DoExecute(Args &command, CommandReturnObject &result) override { 1493314564Sdim PlatformSP platform_sp( 1494353358Sdim GetDebugger().GetPlatformList().GetSelectedPlatform()); 1495314564Sdim if (platform_sp) { 1496321369Sdim Status err; 1497314564Sdim ProcessSP remote_process_sp = platform_sp->Attach( 1498353358Sdim m_options.attach_info, GetDebugger(), nullptr, err); 1499314564Sdim if (err.Fail()) { 1500314564Sdim result.AppendError(err.AsCString()); 1501314564Sdim result.SetStatus(eReturnStatusFailed); 1502314564Sdim } else if (!remote_process_sp) { 1503314564Sdim result.AppendError("could not attach: unknown reason"); 1504314564Sdim result.SetStatus(eReturnStatusFailed); 1505314564Sdim } else 1506314564Sdim result.SetStatus(eReturnStatusSuccessFinishResult); 1507314564Sdim } else { 1508314564Sdim result.AppendError("no platform is currently selected"); 1509314564Sdim result.SetStatus(eReturnStatusFailed); 1510258054Semaste } 1511314564Sdim return result.Succeeded(); 1512314564Sdim } 1513314564Sdim 1514314564Sdim Options *GetOptions() override { return &m_options; } 1515314564Sdim 1516258054Semasteprotected: 1517314564Sdim CommandOptions m_options; 1518258054Semaste}; 1519254721Semaste 1520314564Sdimclass CommandObjectPlatformProcess : public CommandObjectMultiword { 1521254721Semastepublic: 1522314564Sdim // Constructors and Destructors 1523314564Sdim CommandObjectPlatformProcess(CommandInterpreter &interpreter) 1524314564Sdim : CommandObjectMultiword(interpreter, "platform process", 1525314564Sdim "Commands to query, launch and attach to " 1526314564Sdim "processes on the current platform.", 1527314564Sdim "platform process [attach|launch|list] ...") { 1528314564Sdim LoadSubCommand( 1529314564Sdim "attach", 1530314564Sdim CommandObjectSP(new CommandObjectPlatformProcessAttach(interpreter))); 1531314564Sdim LoadSubCommand( 1532314564Sdim "launch", 1533314564Sdim CommandObjectSP(new CommandObjectPlatformProcessLaunch(interpreter))); 1534314564Sdim LoadSubCommand("info", CommandObjectSP(new CommandObjectPlatformProcessInfo( 1535314564Sdim interpreter))); 1536314564Sdim LoadSubCommand("list", CommandObjectSP(new CommandObjectPlatformProcessList( 1537314564Sdim interpreter))); 1538314564Sdim } 1539254721Semaste 1540314564Sdim ~CommandObjectPlatformProcess() override = default; 1541309124Sdim 1542254721Semasteprivate: 1543314564Sdim // For CommandObjectPlatform only 1544314564Sdim DISALLOW_COPY_AND_ASSIGN(CommandObjectPlatformProcess); 1545254721Semaste}; 1546254721Semaste 1547258054Semaste// "platform shell" 1548360784Sdim#define LLDB_OPTIONS_platform_shell 1549360784Sdim#include "CommandOptions.inc" 1550314564Sdim 1551314564Sdimclass CommandObjectPlatformShell : public CommandObjectRaw { 1552254721Semastepublic: 1553314564Sdim class CommandOptions : public Options { 1554314564Sdim public: 1555341825Sdim CommandOptions() : Options() {} 1556309124Sdim 1557314564Sdim ~CommandOptions() override = default; 1558309124Sdim 1559314564Sdim llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1560314564Sdim return llvm::makeArrayRef(g_platform_shell_options); 1561314564Sdim } 1562309124Sdim 1563321369Sdim Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1564321369Sdim ExecutionContext *execution_context) override { 1565321369Sdim Status error; 1566314564Sdim 1567314564Sdim const char short_option = (char)GetDefinitions()[option_idx].short_option; 1568314564Sdim 1569314564Sdim switch (short_option) { 1570314564Sdim case 't': 1571341825Sdim uint32_t timeout_sec; 1572341825Sdim if (option_arg.getAsInteger(10, timeout_sec)) 1573314564Sdim error.SetErrorStringWithFormat( 1574314564Sdim "could not convert \"%s\" to a numeric value.", 1575314564Sdim option_arg.str().c_str()); 1576341825Sdim else 1577341825Sdim timeout = std::chrono::seconds(timeout_sec); 1578314564Sdim break; 1579314564Sdim default: 1580360784Sdim llvm_unreachable("Unimplemented option"); 1581314564Sdim } 1582314564Sdim 1583314564Sdim return error; 1584254721Semaste } 1585309124Sdim 1586314564Sdim void OptionParsingStarting(ExecutionContext *execution_context) override {} 1587309124Sdim 1588341825Sdim Timeout<std::micro> timeout = std::chrono::seconds(10); 1589314564Sdim }; 1590314564Sdim 1591314564Sdim CommandObjectPlatformShell(CommandInterpreter &interpreter) 1592314564Sdim : CommandObjectRaw(interpreter, "platform shell", 1593314564Sdim "Run a shell command on the current platform.", 1594314564Sdim "platform shell <shell-command>", 0), 1595314564Sdim m_options() {} 1596314564Sdim 1597314564Sdim ~CommandObjectPlatformShell() override = default; 1598314564Sdim 1599314564Sdim Options *GetOptions() override { return &m_options; } 1600314564Sdim 1601341825Sdim bool DoExecute(llvm::StringRef raw_command_line, 1602314564Sdim CommandReturnObject &result) override { 1603314564Sdim ExecutionContext exe_ctx = GetCommandInterpreter().GetExecutionContext(); 1604314564Sdim m_options.NotifyOptionParsingStarting(&exe_ctx); 1605314564Sdim 1606314564Sdim // Print out an usage syntax on an empty command line. 1607341825Sdim if (raw_command_line.empty()) { 1608314564Sdim result.GetOutputStream().Printf("%s\n", this->GetSyntax().str().c_str()); 1609314564Sdim return true; 1610258054Semaste } 1611258054Semaste 1612341825Sdim OptionsWithRaw args(raw_command_line); 1613341825Sdim const char *expr = args.GetRawPart().c_str(); 1614258054Semaste 1615341825Sdim if (args.HasArgs()) 1616341825Sdim if (!ParseOptions(args.GetArgs(), result)) 1617341825Sdim return false; 1618254721Semaste 1619314564Sdim PlatformSP platform_sp( 1620353358Sdim GetDebugger().GetPlatformList().GetSelectedPlatform()); 1621321369Sdim Status error; 1622314564Sdim if (platform_sp) { 1623314564Sdim FileSpec working_dir{}; 1624314564Sdim std::string output; 1625314564Sdim int status = -1; 1626314564Sdim int signo = -1; 1627314564Sdim error = (platform_sp->RunShellCommand(expr, working_dir, &status, &signo, 1628314564Sdim &output, m_options.timeout)); 1629314564Sdim if (!output.empty()) 1630314564Sdim result.GetOutputStream().PutCString(output); 1631314564Sdim if (status > 0) { 1632314564Sdim if (signo > 0) { 1633314564Sdim const char *signo_cstr = Host::GetSignalAsCString(signo); 1634314564Sdim if (signo_cstr) 1635314564Sdim result.GetOutputStream().Printf( 1636314564Sdim "error: command returned with status %i and signal %s\n", 1637314564Sdim status, signo_cstr); 1638314564Sdim else 1639314564Sdim result.GetOutputStream().Printf( 1640314564Sdim "error: command returned with status %i and signal %i\n", 1641314564Sdim status, signo); 1642314564Sdim } else 1643314564Sdim result.GetOutputStream().Printf( 1644314564Sdim "error: command returned with status %i\n", status); 1645314564Sdim } 1646314564Sdim } else { 1647314564Sdim result.GetOutputStream().Printf( 1648314564Sdim "error: cannot run remote shell commands without a platform\n"); 1649314564Sdim error.SetErrorString( 1650314564Sdim "error: cannot run remote shell commands without a platform"); 1651254721Semaste } 1652309124Sdim 1653314564Sdim if (error.Fail()) { 1654314564Sdim result.AppendError(error.AsCString()); 1655314564Sdim result.SetStatus(eReturnStatusFailed); 1656314564Sdim } else { 1657314564Sdim result.SetStatus(eReturnStatusSuccessFinishResult); 1658314564Sdim } 1659314564Sdim return true; 1660314564Sdim } 1661254721Semaste 1662314564Sdim CommandOptions m_options; 1663258054Semaste}; 1664258054Semaste 1665258054Semaste// "platform install" - install a target to a remote end 1666314564Sdimclass CommandObjectPlatformInstall : public CommandObjectParsed { 1667258054Semastepublic: 1668314564Sdim CommandObjectPlatformInstall(CommandInterpreter &interpreter) 1669314564Sdim : CommandObjectParsed( 1670314564Sdim interpreter, "platform target-install", 1671314564Sdim "Install a target (bundle or executable file) to the remote end.", 1672314564Sdim "platform target-install <local-thing> <remote-sandbox>", 0) {} 1673309124Sdim 1674314564Sdim ~CommandObjectPlatformInstall() override = default; 1675309124Sdim 1676314564Sdim bool DoExecute(Args &args, CommandReturnObject &result) override { 1677314564Sdim if (args.GetArgumentCount() != 2) { 1678314564Sdim result.AppendError("platform target-install takes two arguments"); 1679314564Sdim result.SetStatus(eReturnStatusFailed); 1680314564Sdim return false; 1681258054Semaste } 1682314564Sdim // TODO: move the bulk of this code over to the platform itself 1683344779Sdim FileSpec src(args.GetArgumentAtIndex(0)); 1684344779Sdim FileSystem::Instance().Resolve(src); 1685344779Sdim FileSpec dst(args.GetArgumentAtIndex(1)); 1686344779Sdim if (!FileSystem::Instance().Exists(src)) { 1687314564Sdim result.AppendError("source location does not exist or is not accessible"); 1688314564Sdim result.SetStatus(eReturnStatusFailed); 1689314564Sdim return false; 1690314564Sdim } 1691314564Sdim PlatformSP platform_sp( 1692353358Sdim GetDebugger().GetPlatformList().GetSelectedPlatform()); 1693314564Sdim if (!platform_sp) { 1694314564Sdim result.AppendError("no platform currently selected"); 1695314564Sdim result.SetStatus(eReturnStatusFailed); 1696314564Sdim return false; 1697314564Sdim } 1698314564Sdim 1699321369Sdim Status error = platform_sp->Install(src, dst); 1700314564Sdim if (error.Success()) { 1701314564Sdim result.SetStatus(eReturnStatusSuccessFinishNoResult); 1702314564Sdim } else { 1703314564Sdim result.AppendErrorWithFormat("install failed: %s", error.AsCString()); 1704314564Sdim result.SetStatus(eReturnStatusFailed); 1705314564Sdim } 1706314564Sdim return result.Succeeded(); 1707314564Sdim } 1708258054Semaste}; 1709258054Semaste 1710309124SdimCommandObjectPlatform::CommandObjectPlatform(CommandInterpreter &interpreter) 1711314564Sdim : CommandObjectMultiword( 1712314564Sdim interpreter, "platform", "Commands to manage and create platforms.", 1713314564Sdim "platform [connect|disconnect|info|list|status|select] ...") { 1714314564Sdim LoadSubCommand("select", 1715314564Sdim CommandObjectSP(new CommandObjectPlatformSelect(interpreter))); 1716314564Sdim LoadSubCommand("list", 1717314564Sdim CommandObjectSP(new CommandObjectPlatformList(interpreter))); 1718314564Sdim LoadSubCommand("status", 1719314564Sdim CommandObjectSP(new CommandObjectPlatformStatus(interpreter))); 1720314564Sdim LoadSubCommand("connect", CommandObjectSP( 1721314564Sdim new CommandObjectPlatformConnect(interpreter))); 1722314564Sdim LoadSubCommand( 1723314564Sdim "disconnect", 1724314564Sdim CommandObjectSP(new CommandObjectPlatformDisconnect(interpreter))); 1725314564Sdim LoadSubCommand("settings", CommandObjectSP(new CommandObjectPlatformSettings( 1726314564Sdim interpreter))); 1727314564Sdim LoadSubCommand("mkdir", 1728314564Sdim CommandObjectSP(new CommandObjectPlatformMkDir(interpreter))); 1729314564Sdim LoadSubCommand("file", 1730314564Sdim CommandObjectSP(new CommandObjectPlatformFile(interpreter))); 1731314564Sdim LoadSubCommand("get-file", CommandObjectSP(new CommandObjectPlatformGetFile( 1732314564Sdim interpreter))); 1733314564Sdim LoadSubCommand("get-size", CommandObjectSP(new CommandObjectPlatformGetSize( 1734314564Sdim interpreter))); 1735314564Sdim LoadSubCommand("put-file", CommandObjectSP(new CommandObjectPlatformPutFile( 1736314564Sdim interpreter))); 1737314564Sdim LoadSubCommand("process", CommandObjectSP( 1738314564Sdim new CommandObjectPlatformProcess(interpreter))); 1739314564Sdim LoadSubCommand("shell", 1740314564Sdim CommandObjectSP(new CommandObjectPlatformShell(interpreter))); 1741314564Sdim LoadSubCommand( 1742314564Sdim "target-install", 1743314564Sdim CommandObjectSP(new CommandObjectPlatformInstall(interpreter))); 1744254721Semaste} 1745254721Semaste 1746309124SdimCommandObjectPlatform::~CommandObjectPlatform() = default; 1747