brintos

brintos / llvm-project-archived public Read only

0
0
Text · 77.7 KiB · 5b0930c Raw
2253 lines · cpp
1//===-- Platform.cpp ------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include <algorithm>10#include <csignal>11#include <fstream>12#include <memory>13#include <optional>14#include <vector>15 16#include "lldb/Breakpoint/BreakpointIDList.h"17#include "lldb/Breakpoint/BreakpointLocation.h"18#include "lldb/Core/Debugger.h"19#include "lldb/Core/Module.h"20#include "lldb/Core/ModuleSpec.h"21#include "lldb/Core/PluginManager.h"22#include "lldb/Host/FileCache.h"23#include "lldb/Host/FileSystem.h"24#include "lldb/Host/Host.h"25#include "lldb/Host/HostInfo.h"26#include "lldb/Host/OptionParser.h"27#include "lldb/Interpreter/OptionValueFileSpec.h"28#include "lldb/Interpreter/OptionValueProperties.h"29#include "lldb/Interpreter/Property.h"30#include "lldb/Symbol/ObjectFile.h"31#include "lldb/Target/ModuleCache.h"32#include "lldb/Target/Platform.h"33#include "lldb/Target/Process.h"34#include "lldb/Target/Target.h"35#include "lldb/Target/UnixSignals.h"36#include "lldb/Utility/DataBufferHeap.h"37#include "lldb/Utility/FileSpec.h"38#include "lldb/Utility/LLDBLog.h"39#include "lldb/Utility/Log.h"40#include "lldb/Utility/Status.h"41#include "lldb/Utility/StructuredData.h"42#include "llvm/ADT/STLExtras.h"43#include "llvm/Support/FileSystem.h"44#include "llvm/Support/Path.h"45 46// Define these constants from POSIX mman.h rather than include the file so47// that they will be correct even when compiled on Linux.48#define MAP_PRIVATE 249#define MAP_ANON 0x100050 51using namespace lldb;52using namespace lldb_private;53 54// Use a singleton function for g_local_platform_sp to avoid init constructors55// since LLDB is often part of a shared library56static PlatformSP &GetHostPlatformSP() {57  static PlatformSP g_platform_sp;58  return g_platform_sp;59}60 61const char *Platform::GetHostPlatformName() { return "host"; }62 63namespace {64 65#define LLDB_PROPERTIES_platform66#include "TargetProperties.inc"67 68enum {69#define LLDB_PROPERTIES_platform70#include "TargetPropertiesEnum.inc"71};72 73} // namespace74 75llvm::StringRef PlatformProperties::GetSettingName() {76  static constexpr llvm::StringLiteral g_setting_name("platform");77  return g_setting_name;78}79 80PlatformProperties::PlatformProperties() {81  m_collection_sp = std::make_shared<OptionValueProperties>(GetSettingName());82  m_collection_sp->Initialize(g_platform_properties);83 84  auto module_cache_dir = GetModuleCacheDirectory();85  if (module_cache_dir)86    return;87 88  llvm::SmallString<64> user_home_dir;89  if (!FileSystem::Instance().GetHomeDirectory(user_home_dir))90    return;91 92  module_cache_dir = FileSpec(user_home_dir.c_str());93  module_cache_dir.AppendPathComponent(".lldb");94  module_cache_dir.AppendPathComponent("module_cache");95  SetDefaultModuleCacheDirectory(module_cache_dir);96  SetModuleCacheDirectory(module_cache_dir);97}98 99bool PlatformProperties::GetUseModuleCache() const {100  const auto idx = ePropertyUseModuleCache;101  return GetPropertyAtIndexAs<bool>(102      idx, g_platform_properties[idx].default_uint_value != 0);103}104 105bool PlatformProperties::SetUseModuleCache(bool use_module_cache) {106  return SetPropertyAtIndex(ePropertyUseModuleCache, use_module_cache);107}108 109FileSpec PlatformProperties::GetModuleCacheDirectory() const {110  return GetPropertyAtIndexAs<FileSpec>(ePropertyModuleCacheDirectory, {});111}112 113bool PlatformProperties::SetModuleCacheDirectory(const FileSpec &dir_spec) {114  return m_collection_sp->SetPropertyAtIndex(ePropertyModuleCacheDirectory,115                                             dir_spec);116}117 118void PlatformProperties::SetDefaultModuleCacheDirectory(119    const FileSpec &dir_spec) {120  auto f_spec_opt = m_collection_sp->GetPropertyAtIndexAsOptionValueFileSpec(121      ePropertyModuleCacheDirectory);122  assert(f_spec_opt);123  f_spec_opt->SetDefaultValue(dir_spec);124}125 126/// Get the native host platform plug-in.127///128/// There should only be one of these for each host that LLDB runs129/// upon that should be statically compiled in and registered using130/// preprocessor macros or other similar build mechanisms.131///132/// This platform will be used as the default platform when launching133/// or attaching to processes unless another platform is specified.134PlatformSP Platform::GetHostPlatform() { return GetHostPlatformSP(); }135 136void Platform::Initialize() {}137 138void Platform::Terminate() {}139 140PlatformProperties &Platform::GetGlobalPlatformProperties() {141  static PlatformProperties g_settings;142  return g_settings;143}144 145void Platform::SetHostPlatform(const lldb::PlatformSP &platform_sp) {146  // The native platform should use its static void Platform::Initialize()147  // function to register itself as the native platform.148  GetHostPlatformSP() = platform_sp;149}150 151Status Platform::GetFileWithUUID(const FileSpec &platform_file,152                                 const UUID *uuid_ptr, FileSpec &local_file) {153  // Default to the local case154  local_file = platform_file;155  return Status();156}157 158FileSpecList159Platform::LocateExecutableScriptingResources(Target *target, Module &module,160                                             Stream &feedback_stream) {161  return FileSpecList();162}163 164Status Platform::GetSharedModule(165    const ModuleSpec &module_spec, Process *process, ModuleSP &module_sp,166    llvm::SmallVectorImpl<lldb::ModuleSP> *old_modules, bool *did_create_ptr) {167  if (IsHost())168    // Note: module_search_paths_ptr functionality is now handled internally169    // by getting target from module_spec and calling170    // target->GetExecutableSearchPaths()171    return ModuleList::GetSharedModule(module_spec, module_sp, old_modules,172                                       did_create_ptr, false);173 174  // Module resolver lambda.175  auto resolver = [&](const ModuleSpec &spec) {176    Status error(eErrorTypeGeneric);177    ModuleSpec resolved_spec;178    // Check if we have sysroot set.179    if (!m_sdk_sysroot.empty()) {180      // Prepend sysroot to module spec.181      resolved_spec = spec;182      resolved_spec.GetFileSpec().PrependPathComponent(m_sdk_sysroot);183      // Try to get shared module with resolved spec.184      error = ModuleList::GetSharedModule(resolved_spec, module_sp, old_modules,185                                          did_create_ptr, false);186    }187    // If we don't have sysroot or it didn't work then188    // try original module spec.189    if (!error.Success()) {190      resolved_spec = spec;191      error = ModuleList::GetSharedModule(resolved_spec, module_sp, old_modules,192                                          did_create_ptr, false);193    }194    if (error.Success() && module_sp)195      module_sp->SetPlatformFileSpec(resolved_spec.GetFileSpec());196    return error;197  };198 199  return GetRemoteSharedModule(module_spec, process, module_sp, resolver,200                               did_create_ptr);201}202 203bool Platform::GetModuleSpec(const FileSpec &module_file_spec,204                             const ArchSpec &arch, ModuleSpec &module_spec) {205  ModuleSpecList module_specs;206  if (ObjectFile::GetModuleSpecifications(module_file_spec, 0, 0,207                                          module_specs) == 0)208    return false;209 210  ModuleSpec matched_module_spec;211  return module_specs.FindMatchingModuleSpec(ModuleSpec(module_file_spec, arch),212                                             module_spec);213}214 215PlatformSP Platform::Create(llvm::StringRef name) {216  lldb::PlatformSP platform_sp;217  if (name == GetHostPlatformName())218    return GetHostPlatform();219 220  if (PlatformCreateInstance create_callback =221          PluginManager::GetPlatformCreateCallbackForPluginName(name))222    return create_callback(true, nullptr);223  return nullptr;224}225 226ArchSpec Platform::GetAugmentedArchSpec(Platform *platform, llvm::StringRef triple) {227  if (platform)228    return platform->GetAugmentedArchSpec(triple);229  return HostInfo::GetAugmentedArchSpec(triple);230}231 232/// Default Constructor233Platform::Platform(bool is_host)234    : m_is_host(is_host), m_os_version_set_while_connected(false),235      m_system_arch_set_while_connected(false), m_max_uid_name_len(0),236      m_max_gid_name_len(0), m_supports_rsync(false), m_rsync_opts(),237      m_rsync_prefix(), m_supports_ssh(false), m_ssh_opts(),238      m_ignores_remote_hostname(false), m_trap_handlers(),239      m_calculated_trap_handlers(false),240      m_module_cache(std::make_unique<ModuleCache>()) {241  Log *log = GetLog(LLDBLog::Object);242  LLDB_LOGF(log, "%p Platform::Platform()", static_cast<void *>(this));243}244 245Platform::~Platform() = default;246 247void Platform::GetStatus(Stream &strm) {248  strm.Format("  Platform: {0}\n", GetPluginName());249 250  ArchSpec arch(GetSystemArchitecture());251  if (arch.IsValid()) {252    if (!arch.GetTriple().str().empty()) {253      strm.Printf("    Triple: ");254      arch.DumpTriple(strm.AsRawOstream());255      strm.EOL();256    }257  }258 259  llvm::VersionTuple os_version = GetOSVersion();260  if (!os_version.empty()) {261    strm.Format("OS Version: {0}", os_version.getAsString());262 263    if (std::optional<std::string> s = GetOSBuildString())264      strm.Format(" ({0})", *s);265 266    strm.EOL();267  }268 269  if (IsHost()) {270    strm.Printf("  Hostname: %s\n", GetHostname());271  } else {272    const bool is_connected = IsConnected();273    if (is_connected)274      strm.Printf("  Hostname: %s\n", GetHostname());275    strm.Printf(" Connected: %s\n", is_connected ? "yes" : "no");276  }277 278  if (const std::string &sdk_root = GetSDKRootDirectory(); !sdk_root.empty())279    strm.Format("   Sysroot: {0}\n", sdk_root);280 281  if (GetWorkingDirectory()) {282    strm.Printf("WorkingDir: %s\n", GetWorkingDirectory().GetPath().c_str());283  }284  if (!IsConnected())285    return;286 287  std::string specific_info(GetPlatformSpecificConnectionInformation());288 289  if (!specific_info.empty())290    strm.Printf("Platform-specific connection: %s\n", specific_info.c_str());291 292  if (std::optional<std::string> s = GetOSKernelDescription())293    strm.Format("    Kernel: {0}\n", *s);294}295 296llvm::VersionTuple Platform::GetOSVersion(Process *process) {297  std::lock_guard<std::mutex> guard(m_mutex);298 299  if (IsHost()) {300    if (m_os_version.empty()) {301      // We have a local host platform302      m_os_version = HostInfo::GetOSVersion();303      m_os_version_set_while_connected = !m_os_version.empty();304    }305  } else {306    // We have a remote platform. We can only fetch the remote307    // OS version if we are connected, and we don't want to do it308    // more than once.309 310    const bool is_connected = IsConnected();311 312    bool fetch = false;313    if (!m_os_version.empty()) {314      // We have valid OS version info, check to make sure it wasn't manually315      // set prior to connecting. If it was manually set prior to connecting,316      // then lets fetch the actual OS version info if we are now connected.317      if (is_connected && !m_os_version_set_while_connected)318        fetch = true;319    } else {320      // We don't have valid OS version info, fetch it if we are connected321      fetch = is_connected;322    }323 324    if (fetch)325      m_os_version_set_while_connected = GetRemoteOSVersion();326  }327 328  if (!m_os_version.empty())329    return m_os_version;330  if (process) {331    // Check with the process in case it can answer the question if a process332    // was provided333    return process->GetHostOSVersion();334  }335  return llvm::VersionTuple();336}337 338std::optional<std::string> Platform::GetOSBuildString() {339  if (IsHost())340    return HostInfo::GetOSBuildString();341  return GetRemoteOSBuildString();342}343 344std::optional<std::string> Platform::GetOSKernelDescription() {345  if (IsHost())346    return HostInfo::GetOSKernelDescription();347  return GetRemoteOSKernelDescription();348}349 350void Platform::AddClangModuleCompilationOptions(351    Target *target, std::vector<std::string> &options) {352  std::vector<std::string> default_compilation_options = {353      "-x", "c++", "-Xclang", "-nostdsysteminc", "-Xclang", "-nostdsysteminc"};354 355  options.insert(options.end(), default_compilation_options.begin(),356                 default_compilation_options.end());357}358 359FileSpec Platform::GetWorkingDirectory() {360  if (IsHost()) {361    llvm::SmallString<64> cwd;362    if (llvm::sys::fs::current_path(cwd))363      return {};364    else {365      FileSpec file_spec(cwd);366      FileSystem::Instance().Resolve(file_spec);367      return file_spec;368    }369  } else {370    if (!m_working_dir)371      m_working_dir = GetRemoteWorkingDirectory();372    return m_working_dir;373  }374}375 376struct RecurseCopyBaton {377  const FileSpec &dst;378  Platform *platform_ptr;379  Status error;380};381 382static FileSystem::EnumerateDirectoryResult383RecurseCopy_Callback(void *baton, llvm::sys::fs::file_type ft,384                     llvm::StringRef path) {385  RecurseCopyBaton *rc_baton = (RecurseCopyBaton *)baton;386  FileSpec src(path);387  namespace fs = llvm::sys::fs;388  switch (ft) {389  case fs::file_type::fifo_file:390  case fs::file_type::socket_file:391    // we have no way to copy pipes and sockets - ignore them and continue392    return FileSystem::eEnumerateDirectoryResultNext;393    break;394 395  case fs::file_type::directory_file: {396    // make the new directory and get in there397    FileSpec dst_dir = rc_baton->dst;398    if (!dst_dir.GetFilename())399      dst_dir.SetFilename(src.GetFilename());400    Status error = rc_baton->platform_ptr->MakeDirectory(401        dst_dir, lldb::eFilePermissionsDirectoryDefault);402    if (error.Fail()) {403      rc_baton->error = Status::FromErrorStringWithFormatv(404          "unable to setup directory {0} on remote end", dst_dir.GetPath());405      return FileSystem::eEnumerateDirectoryResultQuit; // got an error, bail out406    }407 408    // now recurse409    std::string src_dir_path(src.GetPath());410 411    // Make a filespec that only fills in the directory of a FileSpec so when412    // we enumerate we can quickly fill in the filename for dst copies413    FileSpec recurse_dst;414    recurse_dst.SetDirectory(dst_dir.GetPathAsConstString());415    RecurseCopyBaton rc_baton2 = {recurse_dst, rc_baton->platform_ptr,416                                  Status()};417    FileSystem::Instance().EnumerateDirectory(src_dir_path, true, true, true,418                                              RecurseCopy_Callback, &rc_baton2);419    if (rc_baton2.error.Fail()) {420      rc_baton->error = Status::FromErrorString(rc_baton2.error.AsCString());421      return FileSystem::eEnumerateDirectoryResultQuit; // got an error, bail out422    }423    return FileSystem::eEnumerateDirectoryResultNext;424  } break;425 426  case fs::file_type::symlink_file: {427    // copy the file and keep going428    FileSpec dst_file = rc_baton->dst;429    if (!dst_file.GetFilename())430      dst_file.SetFilename(src.GetFilename());431 432    FileSpec src_resolved;433 434    rc_baton->error = FileSystem::Instance().Readlink(src, src_resolved);435 436    if (rc_baton->error.Fail())437      return FileSystem::eEnumerateDirectoryResultQuit; // got an error, bail out438 439    rc_baton->error =440        rc_baton->platform_ptr->CreateSymlink(dst_file, src_resolved);441 442    if (rc_baton->error.Fail())443      return FileSystem::eEnumerateDirectoryResultQuit; // got an error, bail out444 445    return FileSystem::eEnumerateDirectoryResultNext;446  } break;447 448  case fs::file_type::regular_file: {449    // copy the file and keep going450    FileSpec dst_file = rc_baton->dst;451    if (!dst_file.GetFilename())452      dst_file.SetFilename(src.GetFilename());453    Status err = rc_baton->platform_ptr->PutFile(src, dst_file);454    if (err.Fail()) {455      rc_baton->error = Status::FromErrorString(err.AsCString());456      return FileSystem::eEnumerateDirectoryResultQuit; // got an error, bail out457    }458    return FileSystem::eEnumerateDirectoryResultNext;459  } break;460 461  default:462    rc_baton->error = Status::FromErrorStringWithFormat(463        "invalid file detected during copy: %s", src.GetPath().c_str());464    return FileSystem::eEnumerateDirectoryResultQuit; // got an error, bail out465    break;466  }467  llvm_unreachable("Unhandled file_type!");468}469 470Status Platform::Install(const FileSpec &src, const FileSpec &dst) {471  Status error;472 473  Log *log = GetLog(LLDBLog::Platform);474  LLDB_LOGF(log, "Platform::Install (src='%s', dst='%s')",475            src.GetPath().c_str(), dst.GetPath().c_str());476  FileSpec fixed_dst(dst);477 478  if (!fixed_dst.GetFilename())479    fixed_dst.SetFilename(src.GetFilename());480 481  FileSpec working_dir = GetWorkingDirectory();482 483  if (dst) {484    if (dst.GetDirectory()) {485      const char first_dst_dir_char = dst.GetDirectory().GetCString()[0];486      if (first_dst_dir_char == '/' || first_dst_dir_char == '\\') {487        fixed_dst.SetDirectory(dst.GetDirectory());488      }489      // If the fixed destination file doesn't have a directory yet, then we490      // must have a relative path. We will resolve this relative path against491      // the platform's working directory492      if (!fixed_dst.GetDirectory()) {493        FileSpec relative_spec;494        if (working_dir) {495          relative_spec = working_dir;496          relative_spec.AppendPathComponent(dst.GetPath());497          fixed_dst.SetDirectory(relative_spec.GetDirectory());498        } else {499          error = Status::FromErrorStringWithFormat(500              "platform working directory must be valid for relative path '%s'",501              dst.GetPath().c_str());502          return error;503        }504      }505    } else {506      if (working_dir) {507        fixed_dst.SetDirectory(working_dir.GetPathAsConstString());508      } else {509        error = Status::FromErrorStringWithFormat(510            "platform working directory must be valid for relative path '%s'",511            dst.GetPath().c_str());512        return error;513      }514    }515  } else {516    if (working_dir) {517      fixed_dst.SetDirectory(working_dir.GetPathAsConstString());518    } else {519      error =520          Status::FromErrorString("platform working directory must be valid "521                                  "when destination directory is empty");522      return error;523    }524  }525 526  LLDB_LOGF(log, "Platform::Install (src='%s', dst='%s') fixed_dst='%s'",527            src.GetPath().c_str(), dst.GetPath().c_str(),528            fixed_dst.GetPath().c_str());529 530  if (GetSupportsRSync()) {531    error = PutFile(src, dst);532  } else {533    namespace fs = llvm::sys::fs;534    switch (fs::get_file_type(src.GetPath(), false)) {535    case fs::file_type::directory_file: {536      llvm::sys::fs::remove(fixed_dst.GetPath());537      uint32_t permissions = FileSystem::Instance().GetPermissions(src);538      if (permissions == 0)539        permissions = eFilePermissionsDirectoryDefault;540      error = MakeDirectory(fixed_dst, permissions);541      if (error.Success()) {542        // Make a filespec that only fills in the directory of a FileSpec so543        // when we enumerate we can quickly fill in the filename for dst copies544        FileSpec recurse_dst;545        recurse_dst.SetDirectory(fixed_dst.GetPathAsConstString());546        std::string src_dir_path(src.GetPath());547        RecurseCopyBaton baton = {recurse_dst, this, Status()};548        FileSystem::Instance().EnumerateDirectory(549            src_dir_path, true, true, true, RecurseCopy_Callback, &baton);550        return std::move(baton.error);551      }552    } break;553 554    case fs::file_type::regular_file:555      llvm::sys::fs::remove(fixed_dst.GetPath());556      error = PutFile(src, fixed_dst);557      break;558 559    case fs::file_type::symlink_file: {560      llvm::sys::fs::remove(fixed_dst.GetPath());561      FileSpec src_resolved;562      error = FileSystem::Instance().Readlink(src, src_resolved);563      if (error.Success())564        error = CreateSymlink(dst, src_resolved);565    } break;566    case fs::file_type::fifo_file:567      error = Status::FromErrorString("platform install doesn't handle pipes");568      break;569    case fs::file_type::socket_file:570      error =571          Status::FromErrorString("platform install doesn't handle sockets");572      break;573    default:574      error = Status::FromErrorString(575          "platform install doesn't handle non file or directory items");576      break;577    }578  }579  return error;580}581 582bool Platform::SetWorkingDirectory(const FileSpec &file_spec) {583  if (IsHost()) {584    Log *log = GetLog(LLDBLog::Platform);585    LLDB_LOG(log, "{0}", file_spec);586    if (std::error_code ec = llvm::sys::fs::set_current_path(file_spec.GetPath())) {587      LLDB_LOG(log, "error: {0}", ec.message());588      return false;589    }590    return true;591  } else {592    m_working_dir.Clear();593    return SetRemoteWorkingDirectory(file_spec);594  }595}596 597Status Platform::MakeDirectory(const FileSpec &file_spec,598                               uint32_t permissions) {599  if (IsHost())600    return llvm::sys::fs::create_directory(file_spec.GetPath(), permissions);601  else {602    Status error;603    return Status::FromErrorStringWithFormatv(604        "remote platform {0} doesn't support {1}", GetPluginName(),605        LLVM_PRETTY_FUNCTION);606    return error;607  }608}609 610Status Platform::GetFilePermissions(const FileSpec &file_spec,611                                    uint32_t &file_permissions) {612  if (IsHost()) {613    auto Value = llvm::sys::fs::getPermissions(file_spec.GetPath());614    if (Value)615      file_permissions = Value.get();616    return Status(Value.getError());617  } else {618    Status error;619    return Status::FromErrorStringWithFormatv(620        "remote platform {0} doesn't support {1}", GetPluginName(),621        LLVM_PRETTY_FUNCTION);622    return error;623  }624}625 626Status Platform::SetFilePermissions(const FileSpec &file_spec,627                                    uint32_t file_permissions) {628  if (IsHost()) {629    auto Perms = static_cast<llvm::sys::fs::perms>(file_permissions);630    return llvm::sys::fs::setPermissions(file_spec.GetPath(), Perms);631  } else {632    Status error;633    return Status::FromErrorStringWithFormatv(634        "remote platform {0} doesn't support {1}", GetPluginName(),635        LLVM_PRETTY_FUNCTION);636    return error;637  }638}639 640user_id_t Platform::OpenFile(const FileSpec &file_spec,641                                   File::OpenOptions flags, uint32_t mode,642                                   Status &error) {643  if (IsHost())644    return FileCache::GetInstance().OpenFile(file_spec, flags, mode, error);645  return UINT64_MAX;646}647 648bool Platform::CloseFile(user_id_t fd, Status &error) {649  if (IsHost())650    return FileCache::GetInstance().CloseFile(fd, error);651  return false;652}653 654user_id_t Platform::GetFileSize(const FileSpec &file_spec) {655  if (!IsHost())656    return UINT64_MAX;657 658  uint64_t Size;659  if (llvm::sys::fs::file_size(file_spec.GetPath(), Size))660    return 0;661  return Size;662}663 664uint64_t Platform::ReadFile(lldb::user_id_t fd, uint64_t offset, void *dst,665                            uint64_t dst_len, Status &error) {666  if (IsHost())667    return FileCache::GetInstance().ReadFile(fd, offset, dst, dst_len, error);668  error = Status::FromErrorStringWithFormatv(669      "Platform::ReadFile() is not supported in the {0} platform",670      GetPluginName());671  return -1;672}673 674uint64_t Platform::WriteFile(lldb::user_id_t fd, uint64_t offset,675                             const void *src, uint64_t src_len, Status &error) {676  if (IsHost())677    return FileCache::GetInstance().WriteFile(fd, offset, src, src_len, error);678  error = Status::FromErrorStringWithFormatv(679      "Platform::WriteFile() is not supported in the {0} platform",680      GetPluginName());681  return -1;682}683 684UserIDResolver &Platform::GetUserIDResolver() {685  if (IsHost())686    return HostInfo::GetUserIDResolver();687  return UserIDResolver::GetNoopResolver();688}689 690const char *Platform::GetHostname() {691  if (IsHost())692    return "127.0.0.1";693 694  if (m_hostname.empty())695    return nullptr;696  return m_hostname.c_str();697}698 699ConstString Platform::GetFullNameForDylib(ConstString basename) {700  return basename;701}702 703bool Platform::SetRemoteWorkingDirectory(const FileSpec &working_dir) {704  Log *log = GetLog(LLDBLog::Platform);705  LLDB_LOGF(log, "Platform::SetRemoteWorkingDirectory('%s')",706            working_dir.GetPath().c_str());707  m_working_dir = working_dir;708  return true;709}710 711bool Platform::SetOSVersion(llvm::VersionTuple version) {712  if (IsHost()) {713    // We don't need anyone setting the OS version for the host platform, we714    // should be able to figure it out by calling HostInfo::GetOSVersion(...).715    return false;716  } else {717    // We have a remote platform, allow setting the target OS version if we718    // aren't connected, since if we are connected, we should be able to719    // request the remote OS version from the connected platform.720    if (IsConnected())721      return false;722    else {723      // We aren't connected and we might want to set the OS version ahead of724      // time before we connect so we can peruse files and use a local SDK or725      // PDK cache of support files to disassemble or do other things.726      m_os_version = version;727      return true;728    }729  }730  return false;731}732 733Status Platform::ResolveExecutable(const ModuleSpec &module_spec,734                                   lldb::ModuleSP &exe_module_sp) {735 736  // We may connect to a process and use the provided executable (Don't use737  // local $PATH).738  ModuleSpec resolved_module_spec(module_spec);739 740  // Resolve any executable within a bundle on MacOSX741  Host::ResolveExecutableInBundle(resolved_module_spec.GetFileSpec());742 743  if (!FileSystem::Instance().Exists(resolved_module_spec.GetFileSpec()) &&744      !module_spec.GetUUID().IsValid())745    return Status::FromErrorStringWithFormatv(746        "'{0}' does not exist", resolved_module_spec.GetFileSpec());747 748  if (resolved_module_spec.GetArchitecture().IsValid() ||749      resolved_module_spec.GetUUID().IsValid()) {750    Status error = ModuleList::GetSharedModule(resolved_module_spec,751                                               exe_module_sp, nullptr, nullptr);752 753    if (exe_module_sp && exe_module_sp->GetObjectFile())754      return error;755    exe_module_sp.reset();756  }757  // No valid architecture was specified or the exact arch wasn't found.758  // Ask the platform for the architectures that we should be using (in the759  // correct order) and see if we can find a match that way.760  StreamString arch_names;761  llvm::ListSeparator LS;762  ArchSpec process_host_arch;763  Status error;764  for (const ArchSpec &arch : GetSupportedArchitectures(process_host_arch)) {765    resolved_module_spec.GetArchitecture() = arch;766 767    error = ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp,768                                        nullptr, nullptr);769    if (error.Success()) {770      if (exe_module_sp && exe_module_sp->GetObjectFile())771        break;772      error = Status::FromErrorString("no exe object file");773    }774 775    arch_names << LS << arch.GetArchitectureName();776  }777 778  if (exe_module_sp && error.Success())779    return {};780 781  if (!FileSystem::Instance().Readable(resolved_module_spec.GetFileSpec()))782    return Status::FromErrorStringWithFormatv(783        "'{0}' is not readable", resolved_module_spec.GetFileSpec());784 785  if (!ObjectFile::IsObjectFile(resolved_module_spec.GetFileSpec()))786    return Status::FromErrorStringWithFormatv(787        "'{0}' is not a valid executable", resolved_module_spec.GetFileSpec());788 789  return Status::FromErrorStringWithFormatv(790      "'{0}' doesn't contain any '{1}' platform architectures: {2}",791      resolved_module_spec.GetFileSpec(), GetPluginName(),792      arch_names.GetData());793}794 795Status Platform::ResolveSymbolFile(Target &target, const ModuleSpec &sym_spec,796                                   FileSpec &sym_file) {797  Status error;798  if (FileSystem::Instance().Exists(sym_spec.GetSymbolFileSpec()))799    sym_file = sym_spec.GetSymbolFileSpec();800  else801    error = Status::FromErrorString("unable to resolve symbol file");802  return error;803}804 805bool Platform::ResolveRemotePath(const FileSpec &platform_path,806                                 FileSpec &resolved_platform_path) {807  resolved_platform_path = platform_path;808  FileSystem::Instance().Resolve(resolved_platform_path);809  return true;810}811 812const ArchSpec &Platform::GetSystemArchitecture() {813  if (IsHost()) {814    if (!m_system_arch.IsValid()) {815      // We have a local host platform816      m_system_arch = HostInfo::GetArchitecture();817      m_system_arch_set_while_connected = m_system_arch.IsValid();818    }819  } else {820    // We have a remote platform. We can only fetch the remote system821    // architecture if we are connected, and we don't want to do it more than822    // once.823 824    const bool is_connected = IsConnected();825 826    bool fetch = false;827    if (m_system_arch.IsValid()) {828      // We have valid OS version info, check to make sure it wasn't manually829      // set prior to connecting. If it was manually set prior to connecting,830      // then lets fetch the actual OS version info if we are now connected.831      if (is_connected && !m_system_arch_set_while_connected)832        fetch = true;833    } else {834      // We don't have valid OS version info, fetch it if we are connected835      fetch = is_connected;836    }837 838    if (fetch) {839      m_system_arch = GetRemoteSystemArchitecture();840      m_system_arch_set_while_connected = m_system_arch.IsValid();841    }842  }843  return m_system_arch;844}845 846ArchSpec Platform::GetAugmentedArchSpec(llvm::StringRef triple) {847  if (triple.empty())848    return ArchSpec();849  llvm::Triple normalized_triple(llvm::Triple::normalize(triple));850  if (!ArchSpec::ContainsOnlyArch(normalized_triple))851    return ArchSpec(triple);852 853  if (auto kind = HostInfo::ParseArchitectureKind(triple))854    return HostInfo::GetArchitecture(*kind);855 856  ArchSpec compatible_arch;857  ArchSpec raw_arch(triple);858  if (!IsCompatibleArchitecture(raw_arch, {}, ArchSpec::CompatibleMatch,859                                &compatible_arch))860    return raw_arch;861 862  if (!compatible_arch.IsValid())863    return ArchSpec(normalized_triple);864 865  const llvm::Triple &compatible_triple = compatible_arch.GetTriple();866  if (normalized_triple.getVendorName().empty())867    normalized_triple.setVendor(compatible_triple.getVendor());868  if (normalized_triple.getOSName().empty())869    normalized_triple.setOS(compatible_triple.getOS());870  if (normalized_triple.getEnvironmentName().empty())871    normalized_triple.setEnvironment(compatible_triple.getEnvironment());872  return ArchSpec(normalized_triple);873}874 875Status Platform::ConnectRemote(Args &args) {876  Status error;877  if (IsHost())878    return Status::FromErrorStringWithFormatv(879        "The currently selected platform ({0}) is "880        "the host platform and is always connected.",881        GetPluginName());882  else883    return Status::FromErrorStringWithFormatv(884        "Platform::ConnectRemote() is not supported by {0}", GetPluginName());885  return error;886}887 888Status Platform::DisconnectRemote() {889  Status error;890  if (IsHost())891    return Status::FromErrorStringWithFormatv(892        "The currently selected platform ({0}) is "893        "the host platform and is always connected.",894        GetPluginName());895  else896    return Status::FromErrorStringWithFormatv(897        "Platform::DisconnectRemote() is not supported by {0}",898        GetPluginName());899  return error;900}901 902bool Platform::GetProcessInfo(lldb::pid_t pid,903                              ProcessInstanceInfo &process_info) {904  // Take care of the host case so that each subclass can just call this905  // function to get the host functionality.906  if (IsHost())907    return Host::GetProcessInfo(pid, process_info);908  return false;909}910 911uint32_t Platform::FindProcesses(const ProcessInstanceInfoMatch &match_info,912                                 ProcessInstanceInfoList &process_infos) {913  // Take care of the host case so that each subclass can just call this914  // function to get the host functionality.915  uint32_t match_count = 0;916  if (IsHost())917    match_count = Host::FindProcesses(match_info, process_infos);918  return match_count;919}920 921ProcessInstanceInfoList Platform::GetAllProcesses() {922  ProcessInstanceInfoList processes;923  ProcessInstanceInfoMatch match;924  assert(match.MatchAllProcesses());925  FindProcesses(match, processes);926  return processes;927}928 929Status Platform::LaunchProcess(ProcessLaunchInfo &launch_info) {930  Status error;931  Log *log = GetLog(LLDBLog::Platform);932  LLDB_LOGF(log, "Platform::%s()", __FUNCTION__);933 934  // Take care of the host case so that each subclass can just call this935  // function to get the host functionality.936  if (IsHost()) {937    if (::getenv("LLDB_LAUNCH_FLAG_LAUNCH_IN_TTY"))938      launch_info.GetFlags().Set(eLaunchFlagLaunchInTTY);939 940    if (launch_info.GetFlags().Test(eLaunchFlagLaunchInShell)) {941      const bool will_debug = launch_info.GetFlags().Test(eLaunchFlagDebug);942      const bool first_arg_is_full_shell_command = false;943      uint32_t num_resumes = GetResumeCountForLaunchInfo(launch_info);944      if (log) {945        const FileSpec &shell = launch_info.GetShell();946        std::string shell_str = (shell) ? shell.GetPath() : "<null>";947        LLDB_LOGF(log,948                  "Platform::%s GetResumeCountForLaunchInfo() returned %" PRIu32949                  ", shell is '%s'",950                  __FUNCTION__, num_resumes, shell_str.c_str());951      }952 953      if (!launch_info.ConvertArgumentsForLaunchingInShell(954              error, will_debug, first_arg_is_full_shell_command, num_resumes))955        return error;956    } else if (launch_info.GetFlags().Test(eLaunchFlagShellExpandArguments)) {957      error = ShellExpandArguments(launch_info);958      if (error.Fail()) {959        error = Status::FromErrorStringWithFormat(960            "shell expansion failed (reason: %s). "961            "consider launching with 'process "962            "launch'.",963            error.AsCString("unknown"));964        return error;965      }966    }967 968    LLDB_LOGF(log, "Platform::%s final launch_info resume count: %" PRIu32,969              __FUNCTION__, launch_info.GetResumeCount());970 971    error = Host::LaunchProcess(launch_info);972  } else973    error = Status::FromErrorString(974        "base lldb_private::Platform class can't launch remote processes");975  return error;976}977 978Status Platform::ShellExpandArguments(ProcessLaunchInfo &launch_info) {979  if (IsHost())980    return Host::ShellExpandArguments(launch_info);981  return Status::FromErrorString(982      "base lldb_private::Platform class can't expand arguments");983}984 985Status Platform::KillProcess(const lldb::pid_t pid) {986  Log *log = GetLog(LLDBLog::Platform);987  LLDB_LOGF(log, "Platform::%s, pid %" PRIu64, __FUNCTION__, pid);988 989  if (!IsHost()) {990    return Status::FromErrorString(991        "base lldb_private::Platform class can't kill remote processes");992  }993  Host::Kill(pid, SIGKILL);994  return Status();995}996 997lldb::ProcessSP Platform::DebugProcess(ProcessLaunchInfo &launch_info,998                                       Debugger &debugger, Target &target,999                                       Status &error) {1000  Log *log = GetLog(LLDBLog::Platform);1001  LLDB_LOG(log, "target = {0}", &target);1002 1003  ProcessSP process_sp;1004  // Make sure we stop at the entry point1005  launch_info.GetFlags().Set(eLaunchFlagDebug);1006  // We always launch the process we are going to debug in a separate process1007  // group, since then we can handle ^C interrupts ourselves w/o having to1008  // worry about the target getting them as well.1009  launch_info.SetLaunchInSeparateProcessGroup(true);1010 1011  // Allow any StructuredData process-bound plugins to adjust the launch info1012  // if needed1013  size_t i = 0;1014  bool iteration_complete = false;1015  // Note iteration can't simply go until a nullptr callback is returned, as it1016  // is valid for a plugin to not supply a filter.1017  auto get_filter_func = PluginManager::GetStructuredDataFilterCallbackAtIndex;1018  for (auto filter_callback = get_filter_func(i, iteration_complete);1019       !iteration_complete;1020       filter_callback = get_filter_func(++i, iteration_complete)) {1021    if (filter_callback) {1022      // Give this ProcessLaunchInfo filter a chance to adjust the launch info.1023      error = (*filter_callback)(launch_info, &target);1024      if (!error.Success()) {1025        LLDB_LOGF(log,1026                  "Platform::%s() StructuredDataPlugin launch "1027                  "filter failed.",1028                  __FUNCTION__);1029        return process_sp;1030      }1031    }1032  }1033 1034  error = LaunchProcess(launch_info);1035  if (error.Success()) {1036    LLDB_LOGF(log,1037              "Platform::%s LaunchProcess() call succeeded (pid=%" PRIu64 ")",1038              __FUNCTION__, launch_info.GetProcessID());1039    if (launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID) {1040      ProcessAttachInfo attach_info(launch_info);1041      process_sp = Attach(attach_info, debugger, &target, error);1042      if (process_sp) {1043        LLDB_LOG(log, "Attach() succeeded, Process plugin: {0}",1044                 process_sp->GetPluginName());1045        launch_info.SetHijackListener(attach_info.GetHijackListener());1046 1047        // Since we attached to the process, it will think it needs to detach1048        // if the process object just goes away without an explicit call to1049        // Process::Kill() or Process::Detach(), so let it know to kill the1050        // process if this happens.1051        process_sp->SetShouldDetach(false);1052 1053        // If we didn't have any file actions, the pseudo terminal might have1054        // been used where the secondary side was given as the file to open for1055        // stdin/out/err after we have already opened the primary so we can1056        // read/write stdin/out/err.1057        int pty_fd = launch_info.GetPTY().ReleasePrimaryFileDescriptor();1058        if (pty_fd != PseudoTerminal::invalid_fd) {1059          process_sp->SetSTDIOFileDescriptor(pty_fd);1060        }1061      } else {1062        LLDB_LOGF(log, "Platform::%s Attach() failed: %s", __FUNCTION__,1063                  error.AsCString());1064      }1065    } else {1066      LLDB_LOGF(log,1067                "Platform::%s LaunchProcess() returned launch_info with "1068                "invalid process id",1069                __FUNCTION__);1070    }1071  } else {1072    LLDB_LOGF(log, "Platform::%s LaunchProcess() failed: %s", __FUNCTION__,1073              error.AsCString());1074  }1075 1076  return process_sp;1077}1078 1079std::vector<ArchSpec>1080Platform::CreateArchList(llvm::ArrayRef<llvm::Triple::ArchType> archs,1081                         llvm::Triple::OSType os) {1082  std::vector<ArchSpec> list;1083  for(auto arch : archs) {1084    llvm::Triple triple;1085    triple.setArch(arch);1086    triple.setOS(os);1087    list.push_back(ArchSpec(triple));1088  }1089  return list;1090}1091 1092/// Lets a platform answer if it is compatible with a given1093/// architecture and the target triple contained within.1094bool Platform::IsCompatibleArchitecture(const ArchSpec &arch,1095                                        const ArchSpec &process_host_arch,1096                                        ArchSpec::MatchType match,1097                                        ArchSpec *compatible_arch_ptr) {1098  // If the architecture is invalid, we must answer true...1099  if (arch.IsValid()) {1100    ArchSpec platform_arch;1101    for (const ArchSpec &platform_arch :1102         GetSupportedArchitectures(process_host_arch)) {1103      if (arch.IsMatch(platform_arch, match)) {1104        if (compatible_arch_ptr)1105          *compatible_arch_ptr = platform_arch;1106        return true;1107      }1108    }1109  }1110  if (compatible_arch_ptr)1111    compatible_arch_ptr->Clear();1112  return false;1113}1114 1115Status Platform::PutFile(const FileSpec &source, const FileSpec &destination,1116                         uint32_t uid, uint32_t gid) {1117  Log *log = GetLog(LLDBLog::Platform);1118  LLDB_LOGF(log, "[PutFile] Using block by block transfer....\n");1119 1120  auto source_open_options =1121      File::eOpenOptionReadOnly | File::eOpenOptionCloseOnExec;1122  namespace fs = llvm::sys::fs;1123  if (fs::is_symlink_file(source.GetPath()))1124    source_open_options |= File::eOpenOptionDontFollowSymlinks;1125 1126  auto source_file = FileSystem::Instance().Open(source, source_open_options,1127                                                 lldb::eFilePermissionsUserRW);1128  if (!source_file)1129    return Status::FromError(source_file.takeError());1130  Status error;1131 1132  bool requires_upload = true;1133  llvm::ErrorOr<llvm::MD5::MD5Result> remote_md5 = CalculateMD5(destination);1134  if (std::error_code ec = remote_md5.getError()) {1135    LLDB_LOG(log, "[PutFile] couldn't get md5 sum of destination: {0}",1136             ec.message());1137  } else {1138    llvm::ErrorOr<llvm::MD5::MD5Result> local_md5 =1139        llvm::sys::fs::md5_contents(source.GetPath());1140    if (std::error_code ec = local_md5.getError()) {1141      LLDB_LOG(log, "[PutFile] couldn't get md5 sum of source: {0}",1142               ec.message());1143    } else {1144      LLDB_LOGF(log, "[PutFile] destination md5: %016" PRIx64 "%016" PRIx64,1145                remote_md5->high(), remote_md5->low());1146      LLDB_LOGF(log, "[PutFile]       local md5: %016" PRIx64 "%016" PRIx64,1147                local_md5->high(), local_md5->low());1148      requires_upload = *remote_md5 != *local_md5;1149    }1150  }1151 1152  if (!requires_upload) {1153    LLDB_LOGF(log, "[PutFile] skipping PutFile because md5sums match");1154    return error;1155  }1156 1157  uint32_t permissions = source_file.get()->GetPermissions(error);1158  if (permissions == 0)1159    permissions = lldb::eFilePermissionsUserRWX;1160 1161  lldb::user_id_t dest_file = OpenFile(1162      destination, File::eOpenOptionCanCreate | File::eOpenOptionWriteOnly |1163                       File::eOpenOptionTruncate | File::eOpenOptionCloseOnExec,1164      permissions, error);1165  LLDB_LOGF(log, "dest_file = %" PRIu64 "\n", dest_file);1166 1167  if (error.Fail())1168    return error;1169  if (dest_file == UINT64_MAX)1170    return Status::FromErrorString("unable to open target file");1171  lldb::WritableDataBufferSP buffer_sp(new DataBufferHeap(1024 * 16, 0));1172  uint64_t offset = 0;1173  for (;;) {1174    size_t bytes_read = buffer_sp->GetByteSize();1175    error = source_file.get()->Read(buffer_sp->GetBytes(), bytes_read);1176    if (error.Fail() || bytes_read == 0)1177      break;1178 1179    const uint64_t bytes_written =1180        WriteFile(dest_file, offset, buffer_sp->GetBytes(), bytes_read, error);1181    if (error.Fail())1182      break;1183 1184    offset += bytes_written;1185    if (bytes_written != bytes_read) {1186      // We didn't write the correct number of bytes, so adjust the file1187      // position in the source file we are reading from...1188      source_file.get()->SeekFromStart(offset);1189    }1190  }1191  CloseFile(dest_file, error);1192 1193  if (uid == UINT32_MAX && gid == UINT32_MAX)1194    return error;1195 1196  // TODO: ChownFile?1197 1198  return error;1199}1200 1201Status Platform::GetFile(const FileSpec &source, const FileSpec &destination) {1202  return Status::FromErrorString("unimplemented");1203}1204 1205Status1206Platform::CreateSymlink(const FileSpec &src, // The name of the link is in src1207                        const FileSpec &dst) // The symlink points to dst1208{1209  if (IsHost())1210    return FileSystem::Instance().Symlink(src, dst);1211  return Status::FromErrorString("unimplemented");1212}1213 1214bool Platform::GetFileExists(const lldb_private::FileSpec &file_spec) {1215  if (IsHost())1216    return FileSystem::Instance().Exists(file_spec);1217  return false;1218}1219 1220Status Platform::Unlink(const FileSpec &path) {1221  if (IsHost())1222    return llvm::sys::fs::remove(path.GetPath());1223  return Status::FromErrorString("unimplemented");1224}1225 1226MmapArgList Platform::GetMmapArgumentList(const ArchSpec &arch, addr_t addr,1227                                          addr_t length, unsigned prot,1228                                          unsigned flags, addr_t fd,1229                                          addr_t offset) {1230  uint64_t flags_platform = 0;1231  if (flags & eMmapFlagsPrivate)1232    flags_platform |= MAP_PRIVATE;1233  if (flags & eMmapFlagsAnon)1234    flags_platform |= MAP_ANON;1235 1236  MmapArgList args({addr, length, prot, flags_platform, fd, offset});1237  return args;1238}1239 1240lldb_private::Status Platform::RunShellCommand(1241    llvm::StringRef command,1242    const FileSpec &1243        working_dir, // Pass empty FileSpec to use the current working directory1244    int *status_ptr, // Pass nullptr if you don't want the process exit status1245    int *signo_ptr, // Pass nullptr if you don't want the signal that caused the1246                    // process to exit1247    std::string1248        *command_output, // Pass nullptr if you don't want the command output1249    const Timeout<std::micro> &timeout) {1250  return RunShellCommand(llvm::StringRef(), command, working_dir, status_ptr,1251                         signo_ptr, command_output, timeout);1252}1253 1254lldb_private::Status Platform::RunShellCommand(1255    llvm::StringRef shell,   // Pass empty if you want to use the default1256                             // shell interpreter1257    llvm::StringRef command, // Shouldn't be empty1258    const FileSpec &1259        working_dir, // Pass empty FileSpec to use the current working directory1260    int *status_ptr, // Pass nullptr if you don't want the process exit status1261    int *signo_ptr, // Pass nullptr if you don't want the signal that caused the1262                    // process to exit1263    std::string1264        *command_output, // Pass nullptr if you don't want the command output1265    const Timeout<std::micro> &timeout) {1266  if (IsHost())1267    return Host::RunShellCommand(shell, command, working_dir, status_ptr,1268                                 signo_ptr, command_output, timeout);1269  return Status::FromErrorString(1270      "unable to run a remote command without a platform");1271}1272 1273llvm::ErrorOr<llvm::MD5::MD5Result>1274Platform::CalculateMD5(const FileSpec &file_spec) {1275  if (!IsHost())1276    return std::make_error_code(std::errc::not_supported);1277  return llvm::sys::fs::md5_contents(file_spec.GetPath());1278}1279 1280void Platform::SetLocalCacheDirectory(const char *local) {1281  m_local_cache_directory.assign(local);1282}1283 1284const char *Platform::GetLocalCacheDirectory() {1285  return m_local_cache_directory.c_str();1286}1287 1288static constexpr OptionDefinition g_rsync_option_table[] = {1289    {LLDB_OPT_SET_ALL, false, "rsync", 'r', OptionParser::eNoArgument, nullptr,1290     {}, 0, eArgTypeNone, "Enable rsync."},1291    {LLDB_OPT_SET_ALL, false, "rsync-opts", 'R',1292     OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeCommandName,1293     "Platform-specific options required for rsync to work."},1294    {LLDB_OPT_SET_ALL, false, "rsync-prefix", 'P',1295     OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeCommandName,1296     "Platform-specific rsync prefix put before the remote path."},1297    {LLDB_OPT_SET_ALL, false, "ignore-remote-hostname", 'i',1298     OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone,1299     "Do not automatically fill in the remote hostname when composing the "1300     "rsync command."},1301};1302 1303static constexpr OptionDefinition g_ssh_option_table[] = {1304    {LLDB_OPT_SET_ALL, false, "ssh", 's', OptionParser::eNoArgument, nullptr,1305     {}, 0, eArgTypeNone, "Enable SSH."},1306    {LLDB_OPT_SET_ALL, false, "ssh-opts", 'S', OptionParser::eRequiredArgument,1307     nullptr, {}, 0, eArgTypeCommandName,1308     "Platform-specific options required for SSH to work."},1309};1310 1311static constexpr OptionDefinition g_caching_option_table[] = {1312    {LLDB_OPT_SET_ALL, false, "local-cache-dir", 'c',1313     OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePath,1314     "Path in which to store local copies of files."},1315};1316 1317llvm::ArrayRef<OptionDefinition> OptionGroupPlatformRSync::GetDefinitions() {1318  return llvm::ArrayRef(g_rsync_option_table);1319}1320 1321void OptionGroupPlatformRSync::OptionParsingStarting(1322    ExecutionContext *execution_context) {1323  m_rsync = false;1324  m_rsync_opts.clear();1325  m_rsync_prefix.clear();1326  m_ignores_remote_hostname = false;1327}1328 1329lldb_private::Status1330OptionGroupPlatformRSync::SetOptionValue(uint32_t option_idx,1331                                         llvm::StringRef option_arg,1332                                         ExecutionContext *execution_context) {1333  Status error;1334  char short_option = (char)GetDefinitions()[option_idx].short_option;1335  switch (short_option) {1336  case 'r':1337    m_rsync = true;1338    break;1339 1340  case 'R':1341    m_rsync_opts.assign(std::string(option_arg));1342    break;1343 1344  case 'P':1345    m_rsync_prefix.assign(std::string(option_arg));1346    break;1347 1348  case 'i':1349    m_ignores_remote_hostname = true;1350    break;1351 1352  default:1353    error = Status::FromErrorStringWithFormat("unrecognized option '%c'",1354                                              short_option);1355    break;1356  }1357 1358  return error;1359}1360 1361lldb::BreakpointSP1362Platform::SetThreadCreationBreakpoint(lldb_private::Target &target) {1363  return lldb::BreakpointSP();1364}1365 1366llvm::ArrayRef<OptionDefinition> OptionGroupPlatformSSH::GetDefinitions() {1367  return llvm::ArrayRef(g_ssh_option_table);1368}1369 1370void OptionGroupPlatformSSH::OptionParsingStarting(1371    ExecutionContext *execution_context) {1372  m_ssh = false;1373  m_ssh_opts.clear();1374}1375 1376lldb_private::Status1377OptionGroupPlatformSSH::SetOptionValue(uint32_t option_idx,1378                                       llvm::StringRef option_arg,1379                                       ExecutionContext *execution_context) {1380  Status error;1381  char short_option = (char)GetDefinitions()[option_idx].short_option;1382  switch (short_option) {1383  case 's':1384    m_ssh = true;1385    break;1386 1387  case 'S':1388    m_ssh_opts.assign(std::string(option_arg));1389    break;1390 1391  default:1392    error = Status::FromErrorStringWithFormat("unrecognized option '%c'",1393                                              short_option);1394    break;1395  }1396 1397  return error;1398}1399 1400llvm::ArrayRef<OptionDefinition> OptionGroupPlatformCaching::GetDefinitions() {1401  return llvm::ArrayRef(g_caching_option_table);1402}1403 1404void OptionGroupPlatformCaching::OptionParsingStarting(1405    ExecutionContext *execution_context) {1406  m_cache_dir.clear();1407}1408 1409lldb_private::Status OptionGroupPlatformCaching::SetOptionValue(1410    uint32_t option_idx, llvm::StringRef option_arg,1411    ExecutionContext *execution_context) {1412  Status error;1413  char short_option = (char)GetDefinitions()[option_idx].short_option;1414  switch (short_option) {1415  case 'c':1416    m_cache_dir.assign(std::string(option_arg));1417    break;1418 1419  default:1420    error = Status::FromErrorStringWithFormat("unrecognized option '%c'",1421                                              short_option);1422    break;1423  }1424 1425  return error;1426}1427 1428Environment Platform::GetEnvironment() {1429  if (IsHost())1430    return Host::GetEnvironment();1431  return Environment();1432}1433 1434const std::vector<ConstString> &Platform::GetTrapHandlerSymbolNames() {1435  if (!m_calculated_trap_handlers) {1436    std::lock_guard<std::mutex> guard(m_mutex);1437    if (!m_calculated_trap_handlers) {1438      CalculateTrapHandlerSymbolNames();1439      m_calculated_trap_handlers = true;1440    }1441  }1442  return m_trap_handlers;1443}1444 1445Status Platform::GetCachedExecutable(ModuleSpec &module_spec,1446                                     lldb::ModuleSP &module_sp) {1447  FileSpec platform_spec = module_spec.GetFileSpec();1448  Status error = GetRemoteSharedModule(1449      module_spec, nullptr, module_sp,1450      [&](const ModuleSpec &spec) {1451        return Platform::ResolveExecutable(spec, module_sp);1452      },1453      nullptr);1454  if (error.Success()) {1455    module_spec.GetFileSpec() = module_sp->GetFileSpec();1456    module_spec.GetPlatformFileSpec() = platform_spec;1457  }1458 1459  return error;1460}1461 1462Status Platform::GetRemoteSharedModule(const ModuleSpec &module_spec,1463                                       Process *process,1464                                       lldb::ModuleSP &module_sp,1465                                       const ModuleResolver &module_resolver,1466                                       bool *did_create_ptr) {1467  // Get module information from a target.1468  ModuleSpec resolved_module_spec;1469  ArchSpec process_host_arch;1470  bool got_module_spec = false;1471  if (process) {1472    process_host_arch = process->GetSystemArchitecture();1473    // Try to get module information from the process1474    if (process->GetModuleSpec(module_spec.GetFileSpec(),1475                               module_spec.GetArchitecture(),1476                               resolved_module_spec)) {1477      if (!module_spec.GetUUID().IsValid() ||1478          module_spec.GetUUID() == resolved_module_spec.GetUUID()) {1479        got_module_spec = true;1480      }1481    }1482  }1483 1484  if (!module_spec.GetArchitecture().IsValid()) {1485    Status error;1486    // No valid architecture was specified, ask the platform for the1487    // architectures that we should be using (in the correct order) and see if1488    // we can find a match that way1489    ModuleSpec arch_module_spec(module_spec);1490    for (const ArchSpec &arch : GetSupportedArchitectures(process_host_arch)) {1491      arch_module_spec.GetArchitecture() = arch;1492      error = ModuleList::GetSharedModule(arch_module_spec, module_sp, nullptr,1493                                          nullptr);1494      // Did we find an executable using one of the1495      if (error.Success() && module_sp)1496        break;1497    }1498    if (module_sp) {1499      resolved_module_spec = arch_module_spec;1500      got_module_spec = true;1501    }1502  }1503 1504  if (!got_module_spec) {1505    // Get module information from a target.1506    if (GetModuleSpec(module_spec.GetFileSpec(), module_spec.GetArchitecture(),1507                      resolved_module_spec)) {1508      if (!module_spec.GetUUID().IsValid() ||1509          module_spec.GetUUID() == resolved_module_spec.GetUUID()) {1510        got_module_spec = true;1511      }1512    }1513  }1514 1515  if (!got_module_spec) {1516    // Fall back to the given module resolver, which may have its own1517    // search logic.1518    return module_resolver(module_spec);1519  }1520 1521  // If we are looking for a specific UUID, make sure resolved_module_spec has1522  // the same one before we search.1523  if (module_spec.GetUUID().IsValid()) {1524    resolved_module_spec.GetUUID() = module_spec.GetUUID();1525  }1526 1527  // Call locate module callback if set. This allows users to implement their1528  // own module cache system. For example, to leverage build system artifacts,1529  // to bypass pulling files from remote platform, or to search symbol files1530  // from symbol servers.1531  FileSpec symbol_file_spec;1532  CallLocateModuleCallbackIfSet(resolved_module_spec, module_sp,1533                                symbol_file_spec, did_create_ptr);1534  if (module_sp) {1535    // The module is loaded.1536    if (symbol_file_spec) {1537      // 1. module_sp:loaded, symbol_file_spec:set1538      //      The callback found a module file and a symbol file for this1539      //      resolved_module_spec. Set the symbol file to the module.1540      module_sp->SetSymbolFileFileSpec(symbol_file_spec);1541    } else {1542      // 2. module_sp:loaded, symbol_file_spec:empty1543      //      The callback only found a module file for this1544      //      resolved_module_spec.1545    }1546    return Status();1547  }1548 1549  // The module is not loaded by CallLocateModuleCallbackIfSet.1550  // 3. module_sp:empty, symbol_file_spec:set1551  //      The callback only found a symbol file for the module. We continue to1552  //      find a module file for this resolved_module_spec. and we will call1553  //      module_sp->SetSymbolFileFileSpec with the symbol_file_spec later.1554  // 4. module_sp:empty, symbol_file_spec:empty1555  //      The callback is not set. Or the callback did not find any module1556  //      files nor any symbol files. Or the callback failed, or something1557  //      went wrong. We continue to find a module file for this1558  //      resolved_module_spec.1559 1560  // Trying to find a module by UUID on local file system.1561  Status error = module_resolver(resolved_module_spec);1562  if (error.Success()) {1563    if (module_sp && symbol_file_spec) {1564      // Set the symbol file to the module if the locate modudle callback was1565      // called and returned only a symbol file.1566      module_sp->SetSymbolFileFileSpec(symbol_file_spec);1567    }1568    return error;1569  }1570 1571  // Fallback to call GetCachedSharedModule on failure.1572  if (GetCachedSharedModule(resolved_module_spec, module_sp, did_create_ptr)) {1573    if (module_sp && symbol_file_spec) {1574      // Set the symbol file to the module if the locate modudle callback was1575      // called and returned only a symbol file.1576      module_sp->SetSymbolFileFileSpec(symbol_file_spec);1577    }1578    return Status();1579  }1580 1581  return Status::FromErrorStringWithFormat(1582      "Failed to call GetCachedSharedModule");1583}1584 1585void Platform::CallLocateModuleCallbackIfSet(const ModuleSpec &module_spec,1586                                             lldb::ModuleSP &module_sp,1587                                             FileSpec &symbol_file_spec,1588                                             bool *did_create_ptr) {1589  if (!m_locate_module_callback) {1590    // Locate module callback is not set.1591    return;1592  }1593 1594  FileSpec module_file_spec;1595  Status error =1596      m_locate_module_callback(module_spec, module_file_spec, symbol_file_spec);1597 1598  // Locate module callback is set and called. Check the error.1599  Log *log = GetLog(LLDBLog::Platform);1600  if (error.Fail()) {1601    LLDB_LOGF(log, "%s: locate module callback failed: %s",1602              LLVM_PRETTY_FUNCTION, error.AsCString());1603    return;1604  }1605 1606  // The locate module callback was succeeded.1607  // Check the module_file_spec and symbol_file_spec values.1608  // 1. module:empty  symbol:empty  -> Failure1609  //    - The callback did not return any files.1610  // 2. module:exists symbol:exists -> Success1611  //    - The callback returned a module file and a symbol file.1612  // 3. module:exists symbol:empty  -> Success1613  //    - The callback returned only a module file.1614  // 4. module:empty  symbol:exists -> Success1615  //    - The callback returned only a symbol file.1616  //      For example, a breakpad symbol text file.1617  if (!module_file_spec && !symbol_file_spec) {1618    // This is '1. module:empty  symbol:empty  -> Failure'1619    // The callback did not return any files.1620    LLDB_LOGF(log,1621              "%s: locate module callback did not set both "1622              "module_file_spec and symbol_file_spec",1623              LLVM_PRETTY_FUNCTION);1624    return;1625  }1626 1627  // If the callback returned a module file, it should exist.1628  if (module_file_spec && !FileSystem::Instance().Exists(module_file_spec)) {1629    LLDB_LOGF(log,1630              "%s: locate module callback set a non-existent file to "1631              "module_file_spec: %s",1632              LLVM_PRETTY_FUNCTION, module_file_spec.GetPath().c_str());1633    // Clear symbol_file_spec for the error.1634    symbol_file_spec.Clear();1635    return;1636  }1637 1638  // If the callback returned a symbol file, it should exist.1639  if (symbol_file_spec && !FileSystem::Instance().Exists(symbol_file_spec)) {1640    LLDB_LOGF(log,1641              "%s: locate module callback set a non-existent file to "1642              "symbol_file_spec: %s",1643              LLVM_PRETTY_FUNCTION, symbol_file_spec.GetPath().c_str());1644    // Clear symbol_file_spec for the error.1645    symbol_file_spec.Clear();1646    return;1647  }1648 1649  if (!module_file_spec && symbol_file_spec) {1650    // This is '4. module:empty  symbol:exists -> Success'1651    // The locate module callback returned only a symbol file. For example,1652    // a breakpad symbol text file. GetRemoteSharedModule will use this returned1653    // symbol_file_spec.1654    LLDB_LOGF(log, "%s: locate module callback succeeded: symbol=%s",1655              LLVM_PRETTY_FUNCTION, symbol_file_spec.GetPath().c_str());1656    return;1657  }1658 1659  // This is one of the following.1660  // - 2. module:exists symbol:exists -> Success1661  //    - The callback returned a module file and a symbol file.1662  // - 3. module:exists symbol:empty  -> Success1663  //    - The callback returned Only a module file.1664  // Load the module file.1665  auto cached_module_spec(module_spec);1666  cached_module_spec.GetUUID().Clear(); // Clear UUID since it may contain md51667                                        // content hash instead of real UUID.1668  cached_module_spec.GetFileSpec() = module_file_spec;1669  cached_module_spec.GetSymbolFileSpec() = symbol_file_spec;1670  cached_module_spec.GetPlatformFileSpec() = module_spec.GetFileSpec();1671  cached_module_spec.SetObjectOffset(0);1672 1673  error = ModuleList::GetSharedModule(cached_module_spec, module_sp, nullptr,1674                                      did_create_ptr, false, false);1675  if (error.Success() && module_sp) {1676    // Succeeded to load the module file.1677    LLDB_LOGF(log, "%s: locate module callback succeeded: module=%s symbol=%s",1678              LLVM_PRETTY_FUNCTION, module_file_spec.GetPath().c_str(),1679              symbol_file_spec.GetPath().c_str());1680  } else {1681    LLDB_LOGF(log,1682              "%s: locate module callback succeeded but failed to load: "1683              "module=%s symbol=%s",1684              LLVM_PRETTY_FUNCTION, module_file_spec.GetPath().c_str(),1685              symbol_file_spec.GetPath().c_str());1686    // Clear module_sp and symbol_file_spec for the error.1687    module_sp.reset();1688    symbol_file_spec.Clear();1689  }1690}1691 1692bool Platform::GetCachedSharedModule(const ModuleSpec &module_spec,1693                                     lldb::ModuleSP &module_sp,1694                                     bool *did_create_ptr) {1695  if (IsHost() || !GetGlobalPlatformProperties().GetUseModuleCache() ||1696      !GetGlobalPlatformProperties().GetModuleCacheDirectory())1697    return false;1698 1699  Log *log = GetLog(LLDBLog::Platform);1700 1701  // Check local cache for a module.1702  auto error = m_module_cache->GetAndPut(1703      GetModuleCacheRoot(), GetCacheHostname(), module_spec,1704      [this](const ModuleSpec &module_spec,1705             const FileSpec &tmp_download_file_spec) {1706        return DownloadModuleSlice(1707            module_spec.GetFileSpec(), module_spec.GetObjectOffset(),1708            module_spec.GetObjectSize(), tmp_download_file_spec);1709 1710      },1711      [this](const ModuleSP &module_sp,1712             const FileSpec &tmp_download_file_spec) {1713        return DownloadSymbolFile(module_sp, tmp_download_file_spec);1714      },1715      module_sp, did_create_ptr);1716  if (error.Success())1717    return true;1718 1719  LLDB_LOGF(log, "Platform::%s - module %s not found in local cache: %s",1720            __FUNCTION__, module_spec.GetUUID().GetAsString().c_str(),1721            error.AsCString());1722  return false;1723}1724 1725Status Platform::DownloadModuleSlice(const FileSpec &src_file_spec,1726                                     const uint64_t src_offset,1727                                     const uint64_t src_size,1728                                     const FileSpec &dst_file_spec) {1729  Status error;1730 1731  std::error_code EC;1732  llvm::raw_fd_ostream dst(dst_file_spec.GetPath(), EC, llvm::sys::fs::OF_None);1733  if (EC) {1734    error = Status::FromErrorStringWithFormat(1735        "unable to open destination file: %s", dst_file_spec.GetPath().c_str());1736    return error;1737  }1738 1739  auto src_fd = OpenFile(src_file_spec, File::eOpenOptionReadOnly,1740                         lldb::eFilePermissionsFileDefault, error);1741 1742  if (error.Fail()) {1743    error = Status::FromErrorStringWithFormat("unable to open source file: %s",1744                                              error.AsCString());1745    return error;1746  }1747 1748  std::vector<char> buffer(512 * 1024);1749  auto offset = src_offset;1750  uint64_t total_bytes_read = 0;1751  while (total_bytes_read < src_size) {1752    const auto to_read = std::min(static_cast<uint64_t>(buffer.size()),1753                                  src_size - total_bytes_read);1754    const uint64_t n_read =1755        ReadFile(src_fd, offset, &buffer[0], to_read, error);1756    if (error.Fail())1757      break;1758    if (n_read == 0) {1759      error = Status::FromErrorString("read 0 bytes");1760      break;1761    }1762    offset += n_read;1763    total_bytes_read += n_read;1764    dst.write(&buffer[0], n_read);1765  }1766 1767  Status close_error;1768  CloseFile(src_fd, close_error); // Ignoring close error.1769 1770  return error;1771}1772 1773Status Platform::DownloadSymbolFile(const lldb::ModuleSP &module_sp,1774                                    const FileSpec &dst_file_spec) {1775  return Status::FromErrorString(1776      "Symbol file downloading not supported by the default platform.");1777}1778 1779FileSpec Platform::GetModuleCacheRoot() {1780  auto dir_spec = GetGlobalPlatformProperties().GetModuleCacheDirectory();1781  dir_spec.AppendPathComponent(GetPluginName());1782  return dir_spec;1783}1784 1785const char *Platform::GetCacheHostname() { return GetHostname(); }1786 1787const UnixSignalsSP &Platform::GetRemoteUnixSignals() {1788  static const auto s_default_unix_signals_sp = std::make_shared<UnixSignals>();1789  return s_default_unix_signals_sp;1790}1791 1792UnixSignalsSP Platform::GetUnixSignals() {1793  if (IsHost())1794    return UnixSignals::CreateForHost();1795  return GetRemoteUnixSignals();1796}1797 1798uint32_t Platform::LoadImage(lldb_private::Process *process,1799                             const lldb_private::FileSpec &local_file,1800                             const lldb_private::FileSpec &remote_file,1801                             lldb_private::Status &error) {1802  if (local_file && remote_file) {1803    // Both local and remote file was specified. Install the local file to the1804    // given location.1805    if (IsRemote() || local_file != remote_file) {1806      error = Install(local_file, remote_file);1807      if (error.Fail())1808        return LLDB_INVALID_IMAGE_TOKEN;1809    }1810    return DoLoadImage(process, remote_file, nullptr, error);1811  }1812 1813  if (local_file) {1814    // Only local file was specified. Install it to the current working1815    // directory.1816    FileSpec target_file = GetWorkingDirectory();1817    target_file.AppendPathComponent(local_file.GetFilename().AsCString());1818    if (IsRemote() || local_file != target_file) {1819      error = Install(local_file, target_file);1820      if (error.Fail())1821        return LLDB_INVALID_IMAGE_TOKEN;1822    }1823    return DoLoadImage(process, target_file, nullptr, error);1824  }1825 1826  if (remote_file) {1827    // Only remote file was specified so we don't have to do any copying1828    return DoLoadImage(process, remote_file, nullptr, error);1829  }1830 1831  error =1832      Status::FromErrorString("Neither local nor remote file was specified");1833  return LLDB_INVALID_IMAGE_TOKEN;1834}1835 1836uint32_t Platform::DoLoadImage(lldb_private::Process *process,1837                               const lldb_private::FileSpec &remote_file,1838                               const std::vector<std::string> *paths,1839                               lldb_private::Status &error,1840                               lldb_private::FileSpec *loaded_image) {1841  error = Status::FromErrorString(1842      "LoadImage is not supported on the current platform");1843  return LLDB_INVALID_IMAGE_TOKEN;1844}1845 1846uint32_t Platform::LoadImageUsingPaths(lldb_private::Process *process,1847                               const lldb_private::FileSpec &remote_filename,1848                               const std::vector<std::string> &paths,1849                               lldb_private::Status &error,1850                               lldb_private::FileSpec *loaded_path)1851{1852  FileSpec file_to_use;1853  if (remote_filename.IsAbsolute())1854    file_to_use = FileSpec(remote_filename.GetFilename().GetStringRef(),1855 1856                           remote_filename.GetPathStyle());1857  else1858    file_to_use = remote_filename;1859 1860  return DoLoadImage(process, file_to_use, &paths, error, loaded_path);1861}1862 1863Status Platform::UnloadImage(lldb_private::Process *process,1864                             uint32_t image_token) {1865  return Status::FromErrorString(1866      "UnloadImage is not supported on the current platform");1867}1868 1869lldb::ProcessSP Platform::ConnectProcess(llvm::StringRef connect_url,1870                                         llvm::StringRef plugin_name,1871                                         Debugger &debugger, Target *target,1872                                         Status &error) {1873  return DoConnectProcess(connect_url, plugin_name, debugger, nullptr, target,1874                          error);1875}1876 1877lldb::ProcessSP Platform::ConnectProcessSynchronous(1878    llvm::StringRef connect_url, llvm::StringRef plugin_name,1879    Debugger &debugger, Stream &stream, Target *target, Status &error) {1880  return DoConnectProcess(connect_url, plugin_name, debugger, &stream, target,1881                          error);1882}1883 1884lldb::ProcessSP Platform::DoConnectProcess(llvm::StringRef connect_url,1885                                           llvm::StringRef plugin_name,1886                                           Debugger &debugger, Stream *stream,1887                                           Target *target, Status &error) {1888  error.Clear();1889 1890  if (!target) {1891    ArchSpec arch = Target::GetDefaultArchitecture();1892 1893    const char *triple =1894        arch.IsValid() ? arch.GetTriple().getTriple().c_str() : "";1895 1896    TargetSP new_target_sp;1897    error = debugger.GetTargetList().CreateTarget(1898        debugger, "", triple, eLoadDependentsNo, nullptr, new_target_sp);1899 1900    target = new_target_sp.get();1901    if (!target || error.Fail()) {1902      return nullptr;1903    }1904  }1905 1906  lldb::ProcessSP process_sp =1907      target->CreateProcess(debugger.GetListener(), plugin_name, nullptr, true);1908 1909  if (!process_sp)1910    return nullptr;1911 1912  // If this private method is called with a stream we are synchronous.1913  const bool synchronous = stream != nullptr;1914 1915  ListenerSP listener_sp(1916      Listener::MakeListener("lldb.Process.ConnectProcess.hijack"));1917  if (synchronous)1918    process_sp->HijackProcessEvents(listener_sp);1919 1920  error = process_sp->ConnectRemote(connect_url);1921  if (error.Fail()) {1922    if (synchronous)1923      process_sp->RestoreProcessEvents();1924    return nullptr;1925  }1926 1927  if (synchronous) {1928    EventSP event_sp;1929    process_sp->WaitForProcessToStop(std::nullopt, &event_sp, true, listener_sp,1930                                     nullptr);1931    process_sp->RestoreProcessEvents();1932    bool pop_process_io_handler = false;1933    // This is a user-level stop, so we allow recognizers to select frames.1934    Process::HandleProcessStateChangedEvent(1935        event_sp, stream, SelectMostRelevantFrame, pop_process_io_handler);1936  }1937 1938  return process_sp;1939}1940 1941size_t Platform::ConnectToWaitingProcesses(lldb_private::Debugger &debugger,1942                                           lldb_private::Status &error) {1943  error.Clear();1944  return 0;1945}1946 1947size_t Platform::GetSoftwareBreakpointTrapOpcode(Target &target,1948                                                 BreakpointSite *bp_site) {1949  ArchSpec arch = target.GetArchitecture();1950  assert(arch.IsValid());1951  const uint8_t *trap_opcode = nullptr;1952  size_t trap_opcode_size = 0;1953 1954  switch (arch.GetMachine()) {1955  case llvm::Triple::aarch64_32:1956  case llvm::Triple::aarch64: {1957    static const uint8_t g_aarch64_opcode[] = {0x00, 0x00, 0x20, 0xd4};1958    trap_opcode = g_aarch64_opcode;1959    trap_opcode_size = sizeof(g_aarch64_opcode);1960  } break;1961 1962  case llvm::Triple::arc: {1963    static const uint8_t g_hex_opcode[] = { 0xff, 0x7f };1964    trap_opcode = g_hex_opcode;1965    trap_opcode_size = sizeof(g_hex_opcode);1966  } break;1967 1968  // TODO: support big-endian arm and thumb trap codes.1969  case llvm::Triple::arm: {1970    // The ARM reference recommends the use of 0xe7fddefe and 0xdefe but the1971    // linux kernel does otherwise.1972    static const uint8_t g_arm_breakpoint_opcode[] = {0xf0, 0x01, 0xf0, 0xe7};1973    static const uint8_t g_thumb_breakpoint_opcode[] = {0x01, 0xde};1974 1975    lldb::BreakpointLocationSP bp_loc_sp(bp_site->GetConstituentAtIndex(0));1976    AddressClass addr_class = AddressClass::eUnknown;1977 1978    if (bp_loc_sp) {1979      addr_class = bp_loc_sp->GetAddress().GetAddressClass();1980      if (addr_class == AddressClass::eUnknown &&1981          (bp_loc_sp->GetAddress().GetFileAddress() & 1))1982        addr_class = AddressClass::eCodeAlternateISA;1983    }1984 1985    if (addr_class == AddressClass::eCodeAlternateISA) {1986      trap_opcode = g_thumb_breakpoint_opcode;1987      trap_opcode_size = sizeof(g_thumb_breakpoint_opcode);1988    } else {1989      trap_opcode = g_arm_breakpoint_opcode;1990      trap_opcode_size = sizeof(g_arm_breakpoint_opcode);1991    }1992  } break;1993 1994  case llvm::Triple::avr: {1995    static const uint8_t g_hex_opcode[] = {0x98, 0x95};1996    trap_opcode = g_hex_opcode;1997    trap_opcode_size = sizeof(g_hex_opcode);1998  } break;1999 2000  case llvm::Triple::mips:2001  case llvm::Triple::mips64: {2002    static const uint8_t g_hex_opcode[] = {0x00, 0x00, 0x00, 0x0d};2003    trap_opcode = g_hex_opcode;2004    trap_opcode_size = sizeof(g_hex_opcode);2005  } break;2006 2007  case llvm::Triple::mipsel:2008  case llvm::Triple::mips64el: {2009    static const uint8_t g_hex_opcode[] = {0x0d, 0x00, 0x00, 0x00};2010    trap_opcode = g_hex_opcode;2011    trap_opcode_size = sizeof(g_hex_opcode);2012  } break;2013 2014  case llvm::Triple::msp430: {2015    static const uint8_t g_msp430_opcode[] = {0x43, 0x43};2016    trap_opcode = g_msp430_opcode;2017    trap_opcode_size = sizeof(g_msp430_opcode);2018  } break;2019 2020  case llvm::Triple::systemz: {2021    static const uint8_t g_hex_opcode[] = {0x00, 0x01};2022    trap_opcode = g_hex_opcode;2023    trap_opcode_size = sizeof(g_hex_opcode);2024  } break;2025 2026  case llvm::Triple::hexagon: {2027    static const uint8_t g_hex_opcode[] = {0x0c, 0xdb, 0x00, 0x54};2028    trap_opcode = g_hex_opcode;2029    trap_opcode_size = sizeof(g_hex_opcode);2030  } break;2031 2032  case llvm::Triple::ppc:2033  case llvm::Triple::ppc64: {2034    static const uint8_t g_ppc_opcode[] = {0x7f, 0xe0, 0x00, 0x08};2035    trap_opcode = g_ppc_opcode;2036    trap_opcode_size = sizeof(g_ppc_opcode);2037  } break;2038 2039  case llvm::Triple::ppc64le: {2040    static const uint8_t g_ppc64le_opcode[] = {0x08, 0x00, 0xe0, 0x7f}; // trap2041    trap_opcode = g_ppc64le_opcode;2042    trap_opcode_size = sizeof(g_ppc64le_opcode);2043  } break;2044 2045  case llvm::Triple::x86:2046  case llvm::Triple::x86_64: {2047    static const uint8_t g_i386_opcode[] = {0xCC};2048    trap_opcode = g_i386_opcode;2049    trap_opcode_size = sizeof(g_i386_opcode);2050  } break;2051 2052  case llvm::Triple::riscv32:2053  case llvm::Triple::riscv64: {2054    static const uint8_t g_riscv_opcode[] = {0x73, 0x00, 0x10, 0x00}; // ebreak2055    static const uint8_t g_riscv_opcode_c[] = {0x02, 0x90}; // c.ebreak2056    if (arch.GetFlags() & ArchSpec::eRISCV_rvc) {2057      trap_opcode = g_riscv_opcode_c;2058      trap_opcode_size = sizeof(g_riscv_opcode_c);2059    } else {2060      trap_opcode = g_riscv_opcode;2061      trap_opcode_size = sizeof(g_riscv_opcode);2062    }2063  } break;2064 2065  case llvm::Triple::loongarch32:2066  case llvm::Triple::loongarch64: {2067    static const uint8_t g_loongarch_opcode[] = {0x05, 0x00, 0x2a,2068                                                 0x00}; // break 0x52069    trap_opcode = g_loongarch_opcode;2070    trap_opcode_size = sizeof(g_loongarch_opcode);2071  } break;2072 2073  case llvm::Triple::wasm32: {2074    // Unreachable (0x00) triggers an unconditional trap.2075    static const uint8_t g_wasm_opcode[] = {0x00};2076    trap_opcode = g_wasm_opcode;2077    trap_opcode_size = sizeof(g_wasm_opcode);2078  } break;2079 2080  default:2081    return 0;2082  }2083 2084  assert(bp_site);2085  if (bp_site->SetTrapOpcode(trap_opcode, trap_opcode_size))2086    return trap_opcode_size;2087 2088  return 0;2089}2090 2091CompilerType Platform::GetSiginfoType(const llvm::Triple& triple) {2092  return CompilerType();2093}2094 2095Args Platform::GetExtraStartupCommands() {2096  return {};2097}2098 2099void Platform::SetLocateModuleCallback(LocateModuleCallback callback) {2100  m_locate_module_callback = callback;2101}2102 2103Platform::LocateModuleCallback Platform::GetLocateModuleCallback() const {2104  return m_locate_module_callback;2105}2106 2107PlatformSP PlatformList::GetOrCreate(llvm::StringRef name) {2108  std::lock_guard<std::recursive_mutex> guard(m_mutex);2109  for (const PlatformSP &platform_sp : m_platforms) {2110    if (platform_sp->GetName() == name)2111      return platform_sp;2112  }2113  return Create(name);2114}2115 2116PlatformSP PlatformList::GetOrCreate(const ArchSpec &arch,2117                                     const ArchSpec &process_host_arch,2118                                     ArchSpec *platform_arch_ptr,2119                                     Status &error) {2120  std::lock_guard<std::recursive_mutex> guard(m_mutex);2121  // First try exact arch matches across all platforms already created2122  for (const auto &platform_sp : m_platforms) {2123    if (platform_sp->IsCompatibleArchitecture(2124            arch, process_host_arch, ArchSpec::ExactMatch, platform_arch_ptr))2125      return platform_sp;2126  }2127 2128  // Next try compatible arch matches across all platforms already created2129  for (const auto &platform_sp : m_platforms) {2130    if (platform_sp->IsCompatibleArchitecture(arch, process_host_arch,2131                                              ArchSpec::CompatibleMatch,2132                                              platform_arch_ptr))2133      return platform_sp;2134  }2135 2136  PlatformCreateInstance create_callback;2137  // First try exact arch matches across all platform plug-ins2138  uint32_t idx;2139  for (idx = 0;2140       (create_callback = PluginManager::GetPlatformCreateCallbackAtIndex(idx));2141       ++idx) {2142    PlatformSP platform_sp = create_callback(false, &arch);2143    if (platform_sp &&2144        platform_sp->IsCompatibleArchitecture(2145            arch, process_host_arch, ArchSpec::ExactMatch, platform_arch_ptr)) {2146      m_platforms.push_back(platform_sp);2147      return platform_sp;2148    }2149  }2150  // Next try compatible arch matches across all platform plug-ins2151  for (idx = 0;2152       (create_callback = PluginManager::GetPlatformCreateCallbackAtIndex(idx));2153       ++idx) {2154    PlatformSP platform_sp = create_callback(false, &arch);2155    if (platform_sp && platform_sp->IsCompatibleArchitecture(2156                           arch, process_host_arch, ArchSpec::CompatibleMatch,2157                           platform_arch_ptr)) {2158      m_platforms.push_back(platform_sp);2159      return platform_sp;2160    }2161  }2162  if (platform_arch_ptr)2163    platform_arch_ptr->Clear();2164  return nullptr;2165}2166 2167PlatformSP PlatformList::GetOrCreate(const ArchSpec &arch,2168                                     const ArchSpec &process_host_arch,2169                                     ArchSpec *platform_arch_ptr) {2170  Status error;2171  if (arch.IsValid())2172    return GetOrCreate(arch, process_host_arch, platform_arch_ptr, error);2173  return nullptr;2174}2175 2176PlatformSP PlatformList::GetOrCreate(llvm::ArrayRef<ArchSpec> archs,2177                                     const ArchSpec &process_host_arch,2178                                     std::vector<PlatformSP> &candidates) {2179  candidates.clear();2180  candidates.reserve(archs.size());2181 2182  if (archs.empty())2183    return nullptr;2184 2185  PlatformSP host_platform_sp = Platform::GetHostPlatform();2186 2187  // Prefer the selected platform if it matches at least one architecture.2188  if (m_selected_platform_sp) {2189    for (const ArchSpec &arch : archs) {2190      if (m_selected_platform_sp->IsCompatibleArchitecture(2191              arch, process_host_arch, ArchSpec::CompatibleMatch, nullptr))2192        return m_selected_platform_sp;2193    }2194  }2195 2196  // Prefer the host platform if it matches at least one architecture.2197  if (host_platform_sp) {2198    for (const ArchSpec &arch : archs) {2199      if (host_platform_sp->IsCompatibleArchitecture(2200              arch, process_host_arch, ArchSpec::CompatibleMatch, nullptr))2201        return host_platform_sp;2202    }2203  }2204 2205  // Collect a list of candidate platforms for the architectures.2206  for (const ArchSpec &arch : archs) {2207    if (PlatformSP platform = GetOrCreate(arch, process_host_arch, nullptr))2208      candidates.push_back(platform);2209  }2210 2211  // The selected or host platform didn't match any of the architectures. If2212  // the same platform supports all architectures then that's the obvious next2213  // best thing.2214  if (candidates.size() == archs.size()) {2215    if (llvm::all_of(candidates, [&](const PlatformSP &p) -> bool {2216          return p->GetName() == candidates.front()->GetName();2217        })) {2218      return candidates.front();2219    }2220  }2221 2222  // At this point we either have no platforms that match the given2223  // architectures or multiple platforms with no good way to disambiguate2224  // between them.2225  return nullptr;2226}2227 2228PlatformSP PlatformList::Create(llvm::StringRef name) {2229  std::lock_guard<std::recursive_mutex> guard(m_mutex);2230  PlatformSP platform_sp = Platform::Create(name);2231  if (platform_sp)2232    m_platforms.push_back(platform_sp);2233  return platform_sp;2234}2235 2236bool PlatformList::LoadPlatformBinaryAndSetup(Process *process,2237                                              lldb::addr_t addr, bool notify) {2238  std::lock_guard<std::recursive_mutex> guard(m_mutex);2239 2240  PlatformCreateInstance create_callback;2241  for (int idx = 0;2242       (create_callback = PluginManager::GetPlatformCreateCallbackAtIndex(idx));2243       ++idx) {2244    ArchSpec arch;2245    PlatformSP platform_sp = create_callback(true, &arch);2246    if (platform_sp) {2247      if (platform_sp->LoadPlatformBinaryAndSetup(process, addr, notify))2248        return true;2249    }2250  }2251  return false;2252}2253