Path: blob/main/contrib/llvm-project/lldb/source/API/SBPlatform.cpp
39587 views
//===-- SBPlatform.cpp ----------------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "lldb/API/SBPlatform.h"9#include "lldb/API/SBDebugger.h"10#include "lldb/API/SBEnvironment.h"11#include "lldb/API/SBError.h"12#include "lldb/API/SBFileSpec.h"13#include "lldb/API/SBLaunchInfo.h"14#include "lldb/API/SBModuleSpec.h"15#include "lldb/API/SBPlatform.h"16#include "lldb/API/SBProcessInfoList.h"17#include "lldb/API/SBTarget.h"18#include "lldb/API/SBUnixSignals.h"19#include "lldb/Host/File.h"20#include "lldb/Target/Platform.h"21#include "lldb/Target/Target.h"22#include "lldb/Utility/ArchSpec.h"23#include "lldb/Utility/Args.h"24#include "lldb/Utility/Instrumentation.h"25#include "lldb/Utility/Status.h"2627#include "llvm/Support/FileSystem.h"2829#include <functional>3031using namespace lldb;32using namespace lldb_private;3334// PlatformConnectOptions35struct PlatformConnectOptions {36PlatformConnectOptions(const char *url = nullptr) {37if (url && url[0])38m_url = url;39}4041~PlatformConnectOptions() = default;4243std::string m_url;44std::string m_rsync_options;45std::string m_rsync_remote_path_prefix;46bool m_rsync_enabled = false;47bool m_rsync_omit_hostname_from_remote_path = false;48ConstString m_local_cache_directory;49};5051// PlatformShellCommand52struct PlatformShellCommand {53PlatformShellCommand(llvm::StringRef shell_interpreter,54llvm::StringRef shell_command) {55if (!shell_interpreter.empty())56m_shell = shell_interpreter.str();5758if (!m_shell.empty() && !shell_command.empty())59m_command = shell_command.str();60}6162PlatformShellCommand(llvm::StringRef shell_command = llvm::StringRef()) {63if (!shell_command.empty())64m_command = shell_command.str();65}6667~PlatformShellCommand() = default;6869std::string m_shell;70std::string m_command;71std::string m_working_dir;72std::string m_output;73int m_status = 0;74int m_signo = 0;75Timeout<std::ratio<1>> m_timeout = std::nullopt;76};77// SBPlatformConnectOptions78SBPlatformConnectOptions::SBPlatformConnectOptions(const char *url)79: m_opaque_ptr(new PlatformConnectOptions(url)) {80LLDB_INSTRUMENT_VA(this, url);81}8283SBPlatformConnectOptions::SBPlatformConnectOptions(84const SBPlatformConnectOptions &rhs)85: m_opaque_ptr(new PlatformConnectOptions()) {86LLDB_INSTRUMENT_VA(this, rhs);8788*m_opaque_ptr = *rhs.m_opaque_ptr;89}9091SBPlatformConnectOptions::~SBPlatformConnectOptions() { delete m_opaque_ptr; }9293SBPlatformConnectOptions &94SBPlatformConnectOptions::operator=(const SBPlatformConnectOptions &rhs) {95LLDB_INSTRUMENT_VA(this, rhs);9697*m_opaque_ptr = *rhs.m_opaque_ptr;98return *this;99}100101const char *SBPlatformConnectOptions::GetURL() {102LLDB_INSTRUMENT_VA(this);103104if (m_opaque_ptr->m_url.empty())105return nullptr;106return ConstString(m_opaque_ptr->m_url.c_str()).GetCString();107}108109void SBPlatformConnectOptions::SetURL(const char *url) {110LLDB_INSTRUMENT_VA(this, url);111112if (url && url[0])113m_opaque_ptr->m_url = url;114else115m_opaque_ptr->m_url.clear();116}117118bool SBPlatformConnectOptions::GetRsyncEnabled() {119LLDB_INSTRUMENT_VA(this);120121return m_opaque_ptr->m_rsync_enabled;122}123124void SBPlatformConnectOptions::EnableRsync(125const char *options, const char *remote_path_prefix,126bool omit_hostname_from_remote_path) {127LLDB_INSTRUMENT_VA(this, options, remote_path_prefix,128omit_hostname_from_remote_path);129130m_opaque_ptr->m_rsync_enabled = true;131m_opaque_ptr->m_rsync_omit_hostname_from_remote_path =132omit_hostname_from_remote_path;133if (remote_path_prefix && remote_path_prefix[0])134m_opaque_ptr->m_rsync_remote_path_prefix = remote_path_prefix;135else136m_opaque_ptr->m_rsync_remote_path_prefix.clear();137138if (options && options[0])139m_opaque_ptr->m_rsync_options = options;140else141m_opaque_ptr->m_rsync_options.clear();142}143144void SBPlatformConnectOptions::DisableRsync() {145LLDB_INSTRUMENT_VA(this);146147m_opaque_ptr->m_rsync_enabled = false;148}149150const char *SBPlatformConnectOptions::GetLocalCacheDirectory() {151LLDB_INSTRUMENT_VA(this);152153return m_opaque_ptr->m_local_cache_directory.GetCString();154}155156void SBPlatformConnectOptions::SetLocalCacheDirectory(const char *path) {157LLDB_INSTRUMENT_VA(this, path);158159if (path && path[0])160m_opaque_ptr->m_local_cache_directory.SetCString(path);161else162m_opaque_ptr->m_local_cache_directory = ConstString();163}164165// SBPlatformShellCommand166SBPlatformShellCommand::SBPlatformShellCommand(const char *shell_interpreter,167const char *shell_command)168: m_opaque_ptr(new PlatformShellCommand(shell_interpreter, shell_command)) {169LLDB_INSTRUMENT_VA(this, shell_interpreter, shell_command);170}171172SBPlatformShellCommand::SBPlatformShellCommand(const char *shell_command)173: m_opaque_ptr(new PlatformShellCommand(shell_command)) {174LLDB_INSTRUMENT_VA(this, shell_command);175}176177SBPlatformShellCommand::SBPlatformShellCommand(178const SBPlatformShellCommand &rhs)179: m_opaque_ptr(new PlatformShellCommand()) {180LLDB_INSTRUMENT_VA(this, rhs);181182*m_opaque_ptr = *rhs.m_opaque_ptr;183}184185SBPlatformShellCommand &186SBPlatformShellCommand::operator=(const SBPlatformShellCommand &rhs) {187188LLDB_INSTRUMENT_VA(this, rhs);189190*m_opaque_ptr = *rhs.m_opaque_ptr;191return *this;192}193194SBPlatformShellCommand::~SBPlatformShellCommand() { delete m_opaque_ptr; }195196void SBPlatformShellCommand::Clear() {197LLDB_INSTRUMENT_VA(this);198199m_opaque_ptr->m_output = std::string();200m_opaque_ptr->m_status = 0;201m_opaque_ptr->m_signo = 0;202}203204const char *SBPlatformShellCommand::GetShell() {205LLDB_INSTRUMENT_VA(this);206207if (m_opaque_ptr->m_shell.empty())208return nullptr;209return ConstString(m_opaque_ptr->m_shell.c_str()).GetCString();210}211212void SBPlatformShellCommand::SetShell(const char *shell_interpreter) {213LLDB_INSTRUMENT_VA(this, shell_interpreter);214215if (shell_interpreter && shell_interpreter[0])216m_opaque_ptr->m_shell = shell_interpreter;217else218m_opaque_ptr->m_shell.clear();219}220221const char *SBPlatformShellCommand::GetCommand() {222LLDB_INSTRUMENT_VA(this);223224if (m_opaque_ptr->m_command.empty())225return nullptr;226return ConstString(m_opaque_ptr->m_command.c_str()).GetCString();227}228229void SBPlatformShellCommand::SetCommand(const char *shell_command) {230LLDB_INSTRUMENT_VA(this, shell_command);231232if (shell_command && shell_command[0])233m_opaque_ptr->m_command = shell_command;234else235m_opaque_ptr->m_command.clear();236}237238const char *SBPlatformShellCommand::GetWorkingDirectory() {239LLDB_INSTRUMENT_VA(this);240241if (m_opaque_ptr->m_working_dir.empty())242return nullptr;243return ConstString(m_opaque_ptr->m_working_dir.c_str()).GetCString();244}245246void SBPlatformShellCommand::SetWorkingDirectory(const char *path) {247LLDB_INSTRUMENT_VA(this, path);248249if (path && path[0])250m_opaque_ptr->m_working_dir = path;251else252m_opaque_ptr->m_working_dir.clear();253}254255uint32_t SBPlatformShellCommand::GetTimeoutSeconds() {256LLDB_INSTRUMENT_VA(this);257258if (m_opaque_ptr->m_timeout)259return m_opaque_ptr->m_timeout->count();260return UINT32_MAX;261}262263void SBPlatformShellCommand::SetTimeoutSeconds(uint32_t sec) {264LLDB_INSTRUMENT_VA(this, sec);265266if (sec == UINT32_MAX)267m_opaque_ptr->m_timeout = std::nullopt;268else269m_opaque_ptr->m_timeout = std::chrono::seconds(sec);270}271272int SBPlatformShellCommand::GetSignal() {273LLDB_INSTRUMENT_VA(this);274275return m_opaque_ptr->m_signo;276}277278int SBPlatformShellCommand::GetStatus() {279LLDB_INSTRUMENT_VA(this);280281return m_opaque_ptr->m_status;282}283284const char *SBPlatformShellCommand::GetOutput() {285LLDB_INSTRUMENT_VA(this);286287if (m_opaque_ptr->m_output.empty())288return nullptr;289return ConstString(m_opaque_ptr->m_output.c_str()).GetCString();290}291292// SBPlatform293SBPlatform::SBPlatform() { LLDB_INSTRUMENT_VA(this); }294295SBPlatform::SBPlatform(const char *platform_name) {296LLDB_INSTRUMENT_VA(this, platform_name);297298m_opaque_sp = Platform::Create(platform_name);299}300301SBPlatform::SBPlatform(const SBPlatform &rhs) {302LLDB_INSTRUMENT_VA(this, rhs);303304m_opaque_sp = rhs.m_opaque_sp;305}306307SBPlatform &SBPlatform::operator=(const SBPlatform &rhs) {308LLDB_INSTRUMENT_VA(this, rhs);309310m_opaque_sp = rhs.m_opaque_sp;311return *this;312}313314SBPlatform::~SBPlatform() = default;315316SBPlatform SBPlatform::GetHostPlatform() {317LLDB_INSTRUMENT();318319SBPlatform host_platform;320host_platform.m_opaque_sp = Platform::GetHostPlatform();321return host_platform;322}323324bool SBPlatform::IsValid() const {325LLDB_INSTRUMENT_VA(this);326return this->operator bool();327}328SBPlatform::operator bool() const {329LLDB_INSTRUMENT_VA(this);330331return m_opaque_sp.get() != nullptr;332}333334void SBPlatform::Clear() {335LLDB_INSTRUMENT_VA(this);336337m_opaque_sp.reset();338}339340const char *SBPlatform::GetName() {341LLDB_INSTRUMENT_VA(this);342343PlatformSP platform_sp(GetSP());344if (platform_sp)345return ConstString(platform_sp->GetName()).AsCString();346return nullptr;347}348349lldb::PlatformSP SBPlatform::GetSP() const { return m_opaque_sp; }350351void SBPlatform::SetSP(const lldb::PlatformSP &platform_sp) {352m_opaque_sp = platform_sp;353}354355const char *SBPlatform::GetWorkingDirectory() {356LLDB_INSTRUMENT_VA(this);357358PlatformSP platform_sp(GetSP());359if (platform_sp)360return platform_sp->GetWorkingDirectory().GetPathAsConstString().AsCString();361return nullptr;362}363364bool SBPlatform::SetWorkingDirectory(const char *path) {365LLDB_INSTRUMENT_VA(this, path);366367PlatformSP platform_sp(GetSP());368if (platform_sp) {369if (path)370platform_sp->SetWorkingDirectory(FileSpec(path));371else372platform_sp->SetWorkingDirectory(FileSpec());373return true;374}375return false;376}377378SBError SBPlatform::ConnectRemote(SBPlatformConnectOptions &connect_options) {379LLDB_INSTRUMENT_VA(this, connect_options);380381SBError sb_error;382PlatformSP platform_sp(GetSP());383if (platform_sp && connect_options.GetURL()) {384Args args;385args.AppendArgument(connect_options.GetURL());386sb_error.ref() = platform_sp->ConnectRemote(args);387} else {388sb_error.SetErrorString("invalid platform");389}390return sb_error;391}392393void SBPlatform::DisconnectRemote() {394LLDB_INSTRUMENT_VA(this);395396PlatformSP platform_sp(GetSP());397if (platform_sp)398platform_sp->DisconnectRemote();399}400401bool SBPlatform::IsConnected() {402LLDB_INSTRUMENT_VA(this);403404PlatformSP platform_sp(GetSP());405if (platform_sp)406return platform_sp->IsConnected();407return false;408}409410const char *SBPlatform::GetTriple() {411LLDB_INSTRUMENT_VA(this);412413PlatformSP platform_sp(GetSP());414if (platform_sp) {415ArchSpec arch(platform_sp->GetSystemArchitecture());416if (arch.IsValid()) {417// Const-ify the string so we don't need to worry about the lifetime of418// the string419return ConstString(arch.GetTriple().getTriple().c_str()).GetCString();420}421}422return nullptr;423}424425const char *SBPlatform::GetOSBuild() {426LLDB_INSTRUMENT_VA(this);427428PlatformSP platform_sp(GetSP());429if (platform_sp) {430std::string s = platform_sp->GetOSBuildString().value_or("");431if (!s.empty()) {432// Const-ify the string so we don't need to worry about the lifetime of433// the string434return ConstString(s).GetCString();435}436}437return nullptr;438}439440const char *SBPlatform::GetOSDescription() {441LLDB_INSTRUMENT_VA(this);442443PlatformSP platform_sp(GetSP());444if (platform_sp) {445std::string s = platform_sp->GetOSKernelDescription().value_or("");446if (!s.empty()) {447// Const-ify the string so we don't need to worry about the lifetime of448// the string449return ConstString(s.c_str()).GetCString();450}451}452return nullptr;453}454455const char *SBPlatform::GetHostname() {456LLDB_INSTRUMENT_VA(this);457458PlatformSP platform_sp(GetSP());459if (platform_sp)460return ConstString(platform_sp->GetHostname()).GetCString();461return nullptr;462}463464uint32_t SBPlatform::GetOSMajorVersion() {465LLDB_INSTRUMENT_VA(this);466467llvm::VersionTuple version;468if (PlatformSP platform_sp = GetSP())469version = platform_sp->GetOSVersion();470return version.empty() ? UINT32_MAX : version.getMajor();471}472473uint32_t SBPlatform::GetOSMinorVersion() {474LLDB_INSTRUMENT_VA(this);475476llvm::VersionTuple version;477if (PlatformSP platform_sp = GetSP())478version = platform_sp->GetOSVersion();479return version.getMinor().value_or(UINT32_MAX);480}481482uint32_t SBPlatform::GetOSUpdateVersion() {483LLDB_INSTRUMENT_VA(this);484485llvm::VersionTuple version;486if (PlatformSP platform_sp = GetSP())487version = platform_sp->GetOSVersion();488return version.getSubminor().value_or(UINT32_MAX);489}490491void SBPlatform::SetSDKRoot(const char *sysroot) {492LLDB_INSTRUMENT_VA(this, sysroot);493if (PlatformSP platform_sp = GetSP())494platform_sp->SetSDKRootDirectory(llvm::StringRef(sysroot).str());495}496497SBError SBPlatform::Get(SBFileSpec &src, SBFileSpec &dst) {498LLDB_INSTRUMENT_VA(this, src, dst);499500SBError sb_error;501PlatformSP platform_sp(GetSP());502if (platform_sp) {503sb_error.ref() = platform_sp->GetFile(src.ref(), dst.ref());504} else {505sb_error.SetErrorString("invalid platform");506}507return sb_error;508}509510SBError SBPlatform::Put(SBFileSpec &src, SBFileSpec &dst) {511LLDB_INSTRUMENT_VA(this, src, dst);512return ExecuteConnected([&](const lldb::PlatformSP &platform_sp) {513if (src.Exists()) {514uint32_t permissions = FileSystem::Instance().GetPermissions(src.ref());515if (permissions == 0) {516if (FileSystem::Instance().IsDirectory(src.ref()))517permissions = eFilePermissionsDirectoryDefault;518else519permissions = eFilePermissionsFileDefault;520}521522return platform_sp->PutFile(src.ref(), dst.ref(), permissions);523}524525Status error;526error.SetErrorStringWithFormat("'src' argument doesn't exist: '%s'",527src.ref().GetPath().c_str());528return error;529});530}531532SBError SBPlatform::Install(SBFileSpec &src, SBFileSpec &dst) {533LLDB_INSTRUMENT_VA(this, src, dst);534return ExecuteConnected([&](const lldb::PlatformSP &platform_sp) {535if (src.Exists())536return platform_sp->Install(src.ref(), dst.ref());537538Status error;539error.SetErrorStringWithFormat("'src' argument doesn't exist: '%s'",540src.ref().GetPath().c_str());541return error;542});543}544545SBError SBPlatform::Run(SBPlatformShellCommand &shell_command) {546LLDB_INSTRUMENT_VA(this, shell_command);547return ExecuteConnected(548[&](const lldb::PlatformSP &platform_sp) {549const char *command = shell_command.GetCommand();550if (!command)551return Status("invalid shell command (empty)");552553if (shell_command.GetWorkingDirectory() == nullptr) {554std::string platform_working_dir =555platform_sp->GetWorkingDirectory().GetPath();556if (!platform_working_dir.empty())557shell_command.SetWorkingDirectory(platform_working_dir.c_str());558}559return platform_sp->RunShellCommand(560shell_command.m_opaque_ptr->m_shell, command,561FileSpec(shell_command.GetWorkingDirectory()),562&shell_command.m_opaque_ptr->m_status,563&shell_command.m_opaque_ptr->m_signo,564&shell_command.m_opaque_ptr->m_output,565shell_command.m_opaque_ptr->m_timeout);566});567}568569SBError SBPlatform::Launch(SBLaunchInfo &launch_info) {570LLDB_INSTRUMENT_VA(this, launch_info);571return ExecuteConnected([&](const lldb::PlatformSP &platform_sp) {572ProcessLaunchInfo info = launch_info.ref();573Status error = platform_sp->LaunchProcess(info);574launch_info.set_ref(info);575return error;576});577}578579SBProcess SBPlatform::Attach(SBAttachInfo &attach_info,580const SBDebugger &debugger, SBTarget &target,581SBError &error) {582LLDB_INSTRUMENT_VA(this, attach_info, debugger, target, error);583584if (PlatformSP platform_sp = GetSP()) {585if (platform_sp->IsConnected()) {586ProcessAttachInfo &info = attach_info.ref();587Status status;588ProcessSP process_sp = platform_sp->Attach(info, debugger.ref(),589target.GetSP().get(), status);590error.SetError(status);591return SBProcess(process_sp);592}593594error.SetErrorString("not connected");595return {};596}597598error.SetErrorString("invalid platform");599return {};600}601602SBProcessInfoList SBPlatform::GetAllProcesses(SBError &error) {603if (PlatformSP platform_sp = GetSP()) {604if (platform_sp->IsConnected()) {605ProcessInstanceInfoList list = platform_sp->GetAllProcesses();606return SBProcessInfoList(list);607}608error.SetErrorString("not connected");609return {};610}611612error.SetErrorString("invalid platform");613return {};614}615616SBError SBPlatform::Kill(const lldb::pid_t pid) {617LLDB_INSTRUMENT_VA(this, pid);618return ExecuteConnected([&](const lldb::PlatformSP &platform_sp) {619return platform_sp->KillProcess(pid);620});621}622623SBError SBPlatform::ExecuteConnected(624const std::function<Status(const lldb::PlatformSP &)> &func) {625SBError sb_error;626const auto platform_sp(GetSP());627if (platform_sp) {628if (platform_sp->IsConnected())629sb_error.ref() = func(platform_sp);630else631sb_error.SetErrorString("not connected");632} else633sb_error.SetErrorString("invalid platform");634635return sb_error;636}637638SBError SBPlatform::MakeDirectory(const char *path, uint32_t file_permissions) {639LLDB_INSTRUMENT_VA(this, path, file_permissions);640641SBError sb_error;642PlatformSP platform_sp(GetSP());643if (platform_sp) {644sb_error.ref() =645platform_sp->MakeDirectory(FileSpec(path), file_permissions);646} else {647sb_error.SetErrorString("invalid platform");648}649return sb_error;650}651652uint32_t SBPlatform::GetFilePermissions(const char *path) {653LLDB_INSTRUMENT_VA(this, path);654655PlatformSP platform_sp(GetSP());656if (platform_sp) {657uint32_t file_permissions = 0;658platform_sp->GetFilePermissions(FileSpec(path), file_permissions);659return file_permissions;660}661return 0;662}663664SBError SBPlatform::SetFilePermissions(const char *path,665uint32_t file_permissions) {666LLDB_INSTRUMENT_VA(this, path, file_permissions);667668SBError sb_error;669PlatformSP platform_sp(GetSP());670if (platform_sp) {671sb_error.ref() =672platform_sp->SetFilePermissions(FileSpec(path), file_permissions);673} else {674sb_error.SetErrorString("invalid platform");675}676return sb_error;677}678679SBUnixSignals SBPlatform::GetUnixSignals() const {680LLDB_INSTRUMENT_VA(this);681682if (auto platform_sp = GetSP())683return SBUnixSignals{platform_sp};684685return SBUnixSignals();686}687688SBEnvironment SBPlatform::GetEnvironment() {689LLDB_INSTRUMENT_VA(this);690PlatformSP platform_sp(GetSP());691692if (platform_sp) {693return SBEnvironment(platform_sp->GetEnvironment());694}695696return SBEnvironment();697}698699SBError SBPlatform::SetLocateModuleCallback(700lldb::SBPlatformLocateModuleCallback callback, void *callback_baton) {701LLDB_INSTRUMENT_VA(this, callback, callback_baton);702PlatformSP platform_sp(GetSP());703if (!platform_sp)704return SBError("invalid platform");705706if (!callback) {707// Clear the callback.708platform_sp->SetLocateModuleCallback(nullptr);709return SBError();710}711712// Platform.h does not accept lldb::SBPlatformLocateModuleCallback directly713// because of the SBModuleSpec and SBFileSpec dependencies. Use a lambda to714// convert ModuleSpec/FileSpec <--> SBModuleSpec/SBFileSpec for the callback715// arguments.716platform_sp->SetLocateModuleCallback(717[callback, callback_baton](const ModuleSpec &module_spec,718FileSpec &module_file_spec,719FileSpec &symbol_file_spec) {720SBModuleSpec module_spec_sb(module_spec);721SBFileSpec module_file_spec_sb;722SBFileSpec symbol_file_spec_sb;723724SBError error = callback(callback_baton, module_spec_sb,725module_file_spec_sb, symbol_file_spec_sb);726727if (error.Success()) {728module_file_spec = module_file_spec_sb.ref();729symbol_file_spec = symbol_file_spec_sb.ref();730}731732return error.ref();733});734return SBError();735}736737738