brintos

brintos / llvm-project-archived public Read only

0
0
Text · 19.4 KiB · a72d94e Raw
467 lines · cpp
1//===-- PlatformDarwinDevice.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 "PlatformDarwinDevice.h"10#include "lldb/Core/Module.h"11#include "lldb/Core/ModuleList.h"12#include "lldb/Core/ModuleSpec.h"13#include "lldb/Host/HostInfo.h"14#include "lldb/Utility/FileSpec.h"15#include "lldb/Utility/LLDBLog.h"16#include "lldb/Utility/Log.h"17#include <optional>18 19using namespace lldb;20using namespace lldb_private;21 22PlatformDarwinDevice::~PlatformDarwinDevice() = default;23 24FileSystem::EnumerateDirectoryResult25PlatformDarwinDevice::GetContainedFilesIntoVectorOfStringsCallback(26    void *baton, llvm::sys::fs::file_type ft, llvm::StringRef path) {27  ((PlatformDarwinDevice::SDKDirectoryInfoCollection *)baton)28      ->push_back(PlatformDarwinDevice::SDKDirectoryInfo(FileSpec(path)));29  return FileSystem::eEnumerateDirectoryResultNext;30}31 32bool PlatformDarwinDevice::UpdateSDKDirectoryInfosIfNeeded() {33  Log *log = GetLog(LLDBLog::Host);34  std::lock_guard<std::mutex> guard(m_sdk_dir_mutex);35  if (m_sdk_directory_infos.empty()) {36    // A --sysroot option was supplied - add it to our list of SDKs to check37    if (!m_sdk_sysroot.empty()) {38      FileSpec sdk_sysroot_fspec(m_sdk_sysroot.c_str());39      FileSystem::Instance().Resolve(sdk_sysroot_fspec);40      const SDKDirectoryInfo sdk_sysroot_directory_info(sdk_sysroot_fspec);41      m_sdk_directory_infos.push_back(sdk_sysroot_directory_info);42      if (log) {43        LLDB_LOGF(log,44                  "PlatformDarwinDevice::UpdateSDKDirectoryInfosIfNeeded added "45                  "--sysroot SDK directory %s",46                  m_sdk_sysroot.c_str());47      }48      return true;49    }50    const char *device_support_dir = GetDeviceSupportDirectory();51    if (log) {52      LLDB_LOGF(log,53                "PlatformDarwinDevice::UpdateSDKDirectoryInfosIfNeeded Got "54                "DeviceSupport directory %s",55                device_support_dir);56    }57    if (device_support_dir) {58      const bool find_directories = true;59      const bool find_files = false;60      const bool find_other = false;61 62      SDKDirectoryInfoCollection builtin_sdk_directory_infos;63      FileSystem::Instance().EnumerateDirectory(64          m_device_support_directory, find_directories, find_files, find_other,65          GetContainedFilesIntoVectorOfStringsCallback,66          &builtin_sdk_directory_infos);67 68      // Only add SDK directories that have symbols in them, some SDKs only69      // contain developer disk images and no symbols, so they aren't useful to70      // us.71      FileSpec sdk_symbols_symlink_fspec;72      for (const auto &sdk_directory_info : builtin_sdk_directory_infos) {73        sdk_symbols_symlink_fspec = sdk_directory_info.directory;74        sdk_symbols_symlink_fspec.AppendPathComponent("Symbols");75        if (FileSystem::Instance().Exists(sdk_symbols_symlink_fspec)) {76          m_sdk_directory_infos.push_back(sdk_directory_info);77          if (log) {78            LLDB_LOGF(log,79                      "PlatformDarwinDevice::UpdateSDKDirectoryInfosIfNeeded "80                      "added builtin SDK directory %s",81                      sdk_symbols_symlink_fspec.GetPath().c_str());82          }83        }84      }85 86      const uint32_t num_installed = m_sdk_directory_infos.size();87      llvm::StringRef dirname = GetDeviceSupportDirectoryName();88      std::string local_sdk_cache_str = "~/Library/Developer/Xcode/";89      local_sdk_cache_str += std::string(dirname);90      FileSpec local_sdk_cache(local_sdk_cache_str.c_str());91      FileSystem::Instance().Resolve(local_sdk_cache);92      if (FileSystem::Instance().Exists(local_sdk_cache)) {93        if (log) {94          LLDB_LOGF(log,95                    "PlatformDarwinDevice::UpdateSDKDirectoryInfosIfNeeded "96                    "searching %s for additional SDKs",97                    local_sdk_cache.GetPath().c_str());98        }99        char path[PATH_MAX];100        if (local_sdk_cache.GetPath(path, sizeof(path))) {101          FileSystem::Instance().EnumerateDirectory(102              path, find_directories, find_files, find_other,103              GetContainedFilesIntoVectorOfStringsCallback,104              &m_sdk_directory_infos);105          const uint32_t num_sdk_infos = m_sdk_directory_infos.size();106          // First try for an exact match of major, minor and update107          for (uint32_t i = num_installed; i < num_sdk_infos; ++i) {108            m_sdk_directory_infos[i].user_cached = true;109            if (log) {110              LLDB_LOGF(log,111                        "PlatformDarwinDevice::"112                        "UpdateSDKDirectoryInfosIfNeeded "113                        "user SDK directory %s",114                        m_sdk_directory_infos[i].directory.GetPath().c_str());115            }116          }117        }118      }119 120      const char *addtional_platform_dirs = getenv("PLATFORM_SDK_DIRECTORY");121      if (addtional_platform_dirs) {122        SDKDirectoryInfoCollection env_var_sdk_directory_infos;123        FileSystem::Instance().EnumerateDirectory(124            addtional_platform_dirs, find_directories, find_files, find_other,125            GetContainedFilesIntoVectorOfStringsCallback,126            &env_var_sdk_directory_infos);127        FileSpec sdk_symbols_symlink_fspec;128        for (const auto &sdk_directory_info : env_var_sdk_directory_infos) {129          sdk_symbols_symlink_fspec = sdk_directory_info.directory;130          sdk_symbols_symlink_fspec.AppendPathComponent("Symbols");131          if (FileSystem::Instance().Exists(sdk_symbols_symlink_fspec)) {132            m_sdk_directory_infos.push_back(sdk_directory_info);133            if (log) {134              LLDB_LOGF(log,135                        "PlatformDarwinDevice::UpdateSDKDirectoryInfosIfNeeded "136                        "added env var SDK directory %s",137                        sdk_symbols_symlink_fspec.GetPath().c_str());138            }139          }140        }141      }142    }143  }144  return !m_sdk_directory_infos.empty();145}146 147const PlatformDarwinDevice::SDKDirectoryInfo *148PlatformDarwinDevice::GetSDKDirectoryForCurrentOSVersion() {149  uint32_t i;150  if (UpdateSDKDirectoryInfosIfNeeded()) {151    const uint32_t num_sdk_infos = m_sdk_directory_infos.size();152    std::vector<bool> check_sdk_info(num_sdk_infos, true);153 154    // Prefer the user SDK build string.155    std::string build = GetSDKBuild();156 157    // Fall back to the platform's build string.158    if (build.empty()) {159      if (std::optional<std::string> os_build_str = GetOSBuildString())160        build.assign(*os_build_str);161    }162 163    // If we have a build string, only check platforms for which the build164    // string matches.165    if (!build.empty()) {166      for (i = 0; i < num_sdk_infos; ++i)167        check_sdk_info[i] = m_sdk_directory_infos[i].build.GetStringRef() ==168                            llvm::StringRef(build);169    }170 171    // If we are connected we can find the version of the OS the platform us172    // running on and select the right SDK173    llvm::VersionTuple version = GetOSVersion();174    if (!version.empty()) {175      if (UpdateSDKDirectoryInfosIfNeeded()) {176        // First try for an exact match of major, minor and update.177        for (i = 0; i < num_sdk_infos; ++i) {178          if (check_sdk_info[i]) {179            if (m_sdk_directory_infos[i].version == version)180              return &m_sdk_directory_infos[i];181          }182        }183        // Try for an exact match of major and minor.184        for (i = 0; i < num_sdk_infos; ++i) {185          if (check_sdk_info[i]) {186            if (m_sdk_directory_infos[i].version.getMajor() ==187                    version.getMajor() &&188                m_sdk_directory_infos[i].version.getMinor() ==189                    version.getMinor()) {190              return &m_sdk_directory_infos[i];191            }192          }193        }194        // Lastly try to match of major version only.195        for (i = 0; i < num_sdk_infos; ++i) {196          if (check_sdk_info[i]) {197            if (m_sdk_directory_infos[i].version.getMajor() ==198                version.getMajor()) {199              return &m_sdk_directory_infos[i];200            }201          }202        }203      }204    } else if (!build.empty()) {205      // No version, just a build number, return the first one that matches.206      for (i = 0; i < num_sdk_infos; ++i)207        if (check_sdk_info[i])208          return &m_sdk_directory_infos[i];209    }210  }211  return nullptr;212}213 214const PlatformDarwinDevice::SDKDirectoryInfo *215PlatformDarwinDevice::GetSDKDirectoryForLatestOSVersion() {216  const PlatformDarwinDevice::SDKDirectoryInfo *result = nullptr;217  if (UpdateSDKDirectoryInfosIfNeeded()) {218    auto max = std::max_element(219        m_sdk_directory_infos.begin(), m_sdk_directory_infos.end(),220        [](const SDKDirectoryInfo &a, const SDKDirectoryInfo &b) {221          return a.version < b.version;222        });223    if (max != m_sdk_directory_infos.end())224      result = &*max;225  }226  return result;227}228 229const char *PlatformDarwinDevice::GetDeviceSupportDirectory() {230  std::string platform_dir =231      ("/Platforms/" + GetPlatformName() + "/DeviceSupport").str();232  if (m_device_support_directory.empty()) {233    if (FileSpec fspec = HostInfo::GetXcodeDeveloperDirectory()) {234      m_device_support_directory = fspec.GetPath();235      m_device_support_directory.append(platform_dir.c_str());236    } else {237      // Assign a single NULL character so we know we tried to find the device238      // support directory and we don't keep trying to find it over and over.239      m_device_support_directory.assign(1, '\0');240    }241  }242  // We should have put a single NULL character into m_device_support_directory243  // or it should have a valid path if the code gets here244  assert(m_device_support_directory.empty() == false);245  if (m_device_support_directory[0])246    return m_device_support_directory.c_str();247  return nullptr;248}249 250const char *PlatformDarwinDevice::GetDeviceSupportDirectoryForOSVersion() {251  if (!m_sdk_sysroot.empty())252    return m_sdk_sysroot.c_str();253 254  if (m_device_support_directory_for_os_version.empty()) {255    const PlatformDarwinDevice::SDKDirectoryInfo *sdk_dir_info =256        GetSDKDirectoryForCurrentOSVersion();257    if (sdk_dir_info == nullptr)258      sdk_dir_info = GetSDKDirectoryForLatestOSVersion();259    if (sdk_dir_info) {260      char path[PATH_MAX];261      if (sdk_dir_info->directory.GetPath(path, sizeof(path))) {262        m_device_support_directory_for_os_version = path;263        return m_device_support_directory_for_os_version.c_str();264      }265    } else {266      // Assign a single NULL character so we know we tried to find the device267      // support directory and we don't keep trying to find it over and over.268      m_device_support_directory_for_os_version.assign(1, '\0');269    }270  }271  // We should have put a single NULL character into272  // m_device_support_directory_for_os_version or it should have a valid path273  // if the code gets here274  assert(m_device_support_directory_for_os_version.empty() == false);275  if (m_device_support_directory_for_os_version[0])276    return m_device_support_directory_for_os_version.c_str();277  return nullptr;278}279 280static lldb_private::Status281MakeCacheFolderForFile(const FileSpec &module_cache_spec) {282  FileSpec module_cache_folder =283      module_cache_spec.CopyByRemovingLastPathComponent();284  return llvm::sys::fs::create_directory(module_cache_folder.GetPath());285}286 287static lldb_private::Status288BringInRemoteFile(Platform *platform,289                  const lldb_private::ModuleSpec &module_spec,290                  const FileSpec &module_cache_spec) {291  MakeCacheFolderForFile(module_cache_spec);292  Status err = platform->GetFile(module_spec.GetFileSpec(), module_cache_spec);293  return err;294}295 296lldb_private::Status PlatformDarwinDevice::GetSharedModuleWithLocalCache(297    const lldb_private::ModuleSpec &module_spec, lldb::ModuleSP &module_sp,298    llvm::SmallVectorImpl<lldb::ModuleSP> *old_modules, bool *did_create_ptr) {299 300  Log *log = GetLog(LLDBLog::Platform);301  LLDB_LOGF(log,302            "[%s] Trying to find module %s/%s - platform path %s/%s symbol "303            "path %s/%s",304            (IsHost() ? "host" : "remote"),305            module_spec.GetFileSpec().GetDirectory().AsCString(),306            module_spec.GetFileSpec().GetFilename().AsCString(),307            module_spec.GetPlatformFileSpec().GetDirectory().AsCString(),308            module_spec.GetPlatformFileSpec().GetFilename().AsCString(),309            module_spec.GetSymbolFileSpec().GetDirectory().AsCString(),310            module_spec.GetSymbolFileSpec().GetFilename().AsCString());311 312  Status err;313 314  if (CheckLocalSharedCache()) {315    // When debugging on the host, we are most likely using the same shared316    // cache as our inferior. The dylibs from the shared cache might not317    // exist on the filesystem, so let's use the images in our own memory318    // to create the modules.319 320    // Check if the requested image is in our shared cache.321    SharedCacheImageInfo image_info =322        HostInfo::GetSharedCacheImageInfo(module_spec.GetFileSpec().GetPath());323 324    // If we found it and it has the correct UUID, let's proceed with325    // creating a module from the memory contents.326    if (image_info.uuid &&327        (!module_spec.GetUUID() || module_spec.GetUUID() == image_info.uuid)) {328      ModuleSpec shared_cache_spec(module_spec.GetFileSpec(), image_info.uuid,329                                   image_info.data_sp);330      err = ModuleList::GetSharedModule(shared_cache_spec, module_sp,331                                        old_modules, did_create_ptr);332      if (module_sp) {333        LLDB_LOGF(log, "[%s] module %s was found in the in-memory shared cache",334                  (IsHost() ? "host" : "remote"),335                  module_spec.GetFileSpec().GetPath().c_str());336        return err;337      }338    }339 340    // We failed to find the module in our shared cache. Let's see if we have a341    // copy in our device support directory.342    FileSpec device_support_spec(GetDeviceSupportDirectoryForOSVersion());343    device_support_spec.AppendPathComponent("Symbols");344    device_support_spec.AppendPathComponent(345        module_spec.GetFileSpec().GetPath());346    FileSystem::Instance().Resolve(device_support_spec);347    if (FileSystem::Instance().Exists(device_support_spec)) {348      ModuleSpec local_spec(device_support_spec, module_spec.GetUUID());349      err = ModuleList::GetSharedModule(local_spec, module_sp, old_modules,350                                        did_create_ptr);351      if (module_sp) {352        LLDB_LOGF(log,353                  "[%s] module %s was found in Device Support "354                  "directory: %s",355                  (IsHost() ? "host" : "remote"),356                  module_spec.GetFileSpec().GetPath().c_str(),357                  local_spec.GetFileSpec().GetPath().c_str());358        return err;359      }360    }361  }362 363  err = ModuleList::GetSharedModule(module_spec, module_sp, old_modules,364                                    did_create_ptr);365  if (module_sp)366    return err;367 368  if (!IsHost()) {369    std::string cache_path(GetLocalCacheDirectory());370    // Only search for a locally cached file if we have a valid cache path371    if (!cache_path.empty()) {372      std::string module_path(module_spec.GetFileSpec().GetPath());373      cache_path.append(module_path);374      FileSpec module_cache_spec(cache_path);375 376      // if rsync is supported, always bring in the file - rsync will be very377      // efficient when files are the same on the local and remote end of the378      // connection379      if (this->GetSupportsRSync()) {380        err = BringInRemoteFile(this, module_spec, module_cache_spec);381        if (err.Fail())382          return err;383        if (FileSystem::Instance().Exists(module_cache_spec)) {384          Log *log = GetLog(LLDBLog::Platform);385          LLDB_LOGF(log, "[%s] module %s/%s was rsynced and is now there",386                    (IsHost() ? "host" : "remote"),387                    module_spec.GetFileSpec().GetDirectory().AsCString(),388                    module_spec.GetFileSpec().GetFilename().AsCString());389          ModuleSpec local_spec(module_cache_spec,390                                module_spec.GetArchitecture());391          module_sp = std::make_shared<Module>(local_spec);392          module_sp->SetPlatformFileSpec(module_spec.GetFileSpec());393          return Status();394        }395      }396 397      // try to find the module in the cache398      if (FileSystem::Instance().Exists(module_cache_spec)) {399        // get the local and remote MD5 and compare400        if (m_remote_platform_sp) {401          // when going over the *slow* GDB remote transfer mechanism we first402          // check the hashes of the files - and only do the actual transfer if403          // they differ404          auto MD5 = llvm::sys::fs::md5_contents(module_cache_spec.GetPath());405          if (!MD5)406            return Status(MD5.getError());407 408          Log *log = GetLog(LLDBLog::Platform);409          bool requires_transfer = true;410          llvm::ErrorOr<llvm::MD5::MD5Result> remote_md5 =411              m_remote_platform_sp->CalculateMD5(module_spec.GetFileSpec());412          if (std::error_code ec = remote_md5.getError())413            LLDB_LOG(log, "couldn't get md5 sum from remote: {0}",414                     ec.message());415          else416            requires_transfer = *MD5 != *remote_md5;417          if (requires_transfer) {418            // bring in the remote file419            LLDB_LOGF(log,420                      "[%s] module %s/%s needs to be replaced from remote copy",421                      (IsHost() ? "host" : "remote"),422                      module_spec.GetFileSpec().GetDirectory().AsCString(),423                      module_spec.GetFileSpec().GetFilename().AsCString());424            Status err =425                BringInRemoteFile(this, module_spec, module_cache_spec);426            if (err.Fail())427              return err;428          }429        }430 431        ModuleSpec local_spec(module_cache_spec, module_spec.GetArchitecture());432        module_sp = std::make_shared<Module>(local_spec);433        module_sp->SetPlatformFileSpec(module_spec.GetFileSpec());434        Log *log = GetLog(LLDBLog::Platform);435        LLDB_LOGF(log, "[%s] module %s/%s was found in the cache",436                  (IsHost() ? "host" : "remote"),437                  module_spec.GetFileSpec().GetDirectory().AsCString(),438                  module_spec.GetFileSpec().GetFilename().AsCString());439        return Status();440      }441 442      // bring in the remote module file443      LLDB_LOGF(log, "[%s] module %s/%s needs to come in remotely",444                (IsHost() ? "host" : "remote"),445                module_spec.GetFileSpec().GetDirectory().AsCString(),446                module_spec.GetFileSpec().GetFilename().AsCString());447      Status err = BringInRemoteFile(this, module_spec, module_cache_spec);448      if (err.Fail())449        return err;450      if (FileSystem::Instance().Exists(module_cache_spec)) {451        Log *log = GetLog(LLDBLog::Platform);452        LLDB_LOGF(log, "[%s] module %s/%s is now cached and fine",453                  (IsHost() ? "host" : "remote"),454                  module_spec.GetFileSpec().GetDirectory().AsCString(),455                  module_spec.GetFileSpec().GetFilename().AsCString());456        ModuleSpec local_spec(module_cache_spec, module_spec.GetArchitecture());457        module_sp = std::make_shared<Module>(local_spec);458        module_sp->SetPlatformFileSpec(module_spec.GetFileSpec());459        return Status();460      } else461        return Status::FromErrorString("unable to obtain valid module file");462    } else463      return Status::FromErrorString("no cache path");464  } else465    return Status::FromErrorString("unable to resolve module");466}467