315 lines · cpp
1//===-- PlatformRemoteDarwinDevice.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 "PlatformRemoteDarwinDevice.h"10 11#include "lldb/Breakpoint/BreakpointLocation.h"12#include "lldb/Core/Module.h"13#include "lldb/Core/ModuleList.h"14#include "lldb/Core/ModuleSpec.h"15#include "lldb/Core/PluginManager.h"16#include "lldb/Host/FileSystem.h"17#include "lldb/Host/Host.h"18#include "lldb/Host/HostInfo.h"19#include "lldb/Target/Process.h"20#include "lldb/Target/Target.h"21#include "lldb/Utility/FileSpec.h"22#include "lldb/Utility/LLDBLog.h"23#include "lldb/Utility/Log.h"24#include "lldb/Utility/Status.h"25#include "lldb/Utility/StreamString.h"26#include <optional>27 28using namespace lldb;29using namespace lldb_private;30 31PlatformRemoteDarwinDevice::SDKDirectoryInfo::SDKDirectoryInfo(32 const lldb_private::FileSpec &sdk_dir)33 : directory(sdk_dir), build(), user_cached(false) {34 llvm::StringRef dirname_str = sdk_dir.GetFilename().GetStringRef();35 llvm::StringRef build_str;36 std::tie(version, build_str) = ParseVersionBuildDir(dirname_str);37 build.SetString(build_str);38}39 40/// Default Constructor41PlatformRemoteDarwinDevice::PlatformRemoteDarwinDevice()42 : PlatformDarwinDevice(false) {} // This is a remote platform43 44/// Destructor.45///46/// The destructor is virtual since this class is designed to be47/// inherited from by the plug-in instance.48PlatformRemoteDarwinDevice::~PlatformRemoteDarwinDevice() = default;49 50void PlatformRemoteDarwinDevice::GetStatus(Stream &strm) {51 Platform::GetStatus(strm);52 const char *sdk_directory = GetDeviceSupportDirectoryForOSVersion();53 if (sdk_directory)54 strm.Printf(" SDK Path: \"%s\"\n", sdk_directory);55 else56 strm.PutCString(" SDK Path: <unable to locate SDK>\n");57 58 const uint32_t num_sdk_infos = m_sdk_directory_infos.size();59 for (uint32_t i = 0; i < num_sdk_infos; ++i) {60 const SDKDirectoryInfo &sdk_dir_info = m_sdk_directory_infos[i];61 strm.Printf(" SDK Roots: [%2u] \"%s\"\n", i,62 sdk_dir_info.directory.GetPath().c_str());63 }64}65 66bool PlatformRemoteDarwinDevice::GetFileInSDK(const char *platform_file_path,67 uint32_t sdk_idx,68 lldb_private::FileSpec &local_file) {69 Log *log = GetLog(LLDBLog::Host);70 if (sdk_idx < m_sdk_directory_infos.size()) {71 std::string sdkroot_path =72 m_sdk_directory_infos[sdk_idx].directory.GetPath();73 local_file.Clear();74 75 if (!sdkroot_path.empty() && platform_file_path && platform_file_path[0]) {76 // We may need to interpose "/Symbols/" or "/Symbols.Internal/" between77 // the78 // SDK root directory and the file path.79 80 const char *paths_to_try[] = {"Symbols", "", "Symbols.Internal", nullptr};81 for (size_t i = 0; paths_to_try[i] != nullptr; i++) {82 local_file.SetFile(sdkroot_path, FileSpec::Style::native);83 if (paths_to_try[i][0] != '\0')84 local_file.AppendPathComponent(paths_to_try[i]);85 local_file.AppendPathComponent(platform_file_path);86 FileSystem::Instance().Resolve(local_file);87 if (FileSystem::Instance().Exists(local_file)) {88 LLDB_LOGF(log, "Found a copy of %s in the SDK dir %s/%s",89 platform_file_path, sdkroot_path.c_str(), paths_to_try[i]);90 return true;91 }92 local_file.Clear();93 }94 }95 }96 return false;97}98 99Status PlatformRemoteDarwinDevice::GetSymbolFile(const FileSpec &platform_file,100 const UUID *uuid_ptr,101 FileSpec &local_file) {102 Log *log = GetLog(LLDBLog::Host);103 Status error;104 char platform_file_path[PATH_MAX];105 if (platform_file.GetPath(platform_file_path, sizeof(platform_file_path))) {106 const char *os_version_dir = GetDeviceSupportDirectoryForOSVersion();107 if (os_version_dir) {108 std::string resolved_path =109 (llvm::Twine(os_version_dir) + "/" + platform_file_path).str();110 111 local_file.SetFile(resolved_path, FileSpec::Style::native);112 FileSystem::Instance().Resolve(local_file);113 if (FileSystem::Instance().Exists(local_file)) {114 if (log) {115 LLDB_LOGF(log, "Found a copy of %s in the DeviceSupport dir %s",116 platform_file_path, os_version_dir);117 }118 return error;119 }120 121 resolved_path = (llvm::Twine(os_version_dir) + "/Symbols.Internal/" +122 platform_file_path)123 .str();124 125 local_file.SetFile(resolved_path, FileSpec::Style::native);126 FileSystem::Instance().Resolve(local_file);127 if (FileSystem::Instance().Exists(local_file)) {128 LLDB_LOGF(129 log,130 "Found a copy of %s in the DeviceSupport dir %s/Symbols.Internal",131 platform_file_path, os_version_dir);132 return error;133 }134 resolved_path =135 (llvm::Twine(os_version_dir) + "/Symbols/" + platform_file_path)136 .str();137 138 local_file.SetFile(resolved_path, FileSpec::Style::native);139 FileSystem::Instance().Resolve(local_file);140 if (FileSystem::Instance().Exists(local_file)) {141 LLDB_LOGF(log, "Found a copy of %s in the DeviceSupport dir %s/Symbols",142 platform_file_path, os_version_dir);143 return error;144 }145 }146 local_file = platform_file;147 if (FileSystem::Instance().Exists(local_file))148 return error;149 150 error = Status::FromErrorStringWithFormatv(151 "unable to locate a platform file for '{0}' in platform '{1}'",152 platform_file_path, GetPluginName());153 } else {154 error = Status::FromErrorString("invalid platform file argument");155 }156 return error;157}158 159Status PlatformRemoteDarwinDevice::GetSharedModule(160 const ModuleSpec &module_spec, Process *process, ModuleSP &module_sp,161 llvm::SmallVectorImpl<ModuleSP> *old_modules, bool *did_create_ptr) {162 // For iOS, the SDK files are all cached locally on the host system. So first163 // we ask for the file in the cached SDK, then we attempt to get a shared164 // module for the right architecture with the right UUID.165 const FileSpec &platform_file = module_spec.GetFileSpec();166 Log *log = GetLog(LLDBLog::Host);167 168 Status error;169 char platform_file_path[PATH_MAX];170 171 if (platform_file.GetPath(platform_file_path, sizeof(platform_file_path))) {172 ModuleSpec platform_module_spec(module_spec);173 174 UpdateSDKDirectoryInfosIfNeeded();175 176 const uint32_t num_sdk_infos = m_sdk_directory_infos.size();177 178 // If we are connected we migth be able to correctly deduce the SDK179 // directory using the OS build.180 const uint32_t connected_sdk_idx = GetConnectedSDKIndex();181 if (connected_sdk_idx < num_sdk_infos) {182 LLDB_LOGV(log, "Searching for {0} in sdk path {1}", platform_file,183 m_sdk_directory_infos[connected_sdk_idx].directory);184 if (GetFileInSDK(platform_file_path, connected_sdk_idx,185 platform_module_spec.GetFileSpec())) {186 module_sp.reset();187 error = ResolveExecutable(platform_module_spec, module_sp);188 if (module_sp) {189 m_last_module_sdk_idx = connected_sdk_idx;190 error.Clear();191 return error;192 }193 }194 }195 196 // Try the last SDK index if it is set as most files from an SDK will tend197 // to be valid in that same SDK.198 if (m_last_module_sdk_idx < num_sdk_infos) {199 LLDB_LOGV(log, "Searching for {0} in sdk path {1}", platform_file,200 m_sdk_directory_infos[m_last_module_sdk_idx].directory);201 if (GetFileInSDK(platform_file_path, m_last_module_sdk_idx,202 platform_module_spec.GetFileSpec())) {203 module_sp.reset();204 error = ResolveExecutable(platform_module_spec, module_sp);205 if (module_sp) {206 error.Clear();207 return error;208 }209 }210 }211 212 // First try for an exact match of major, minor and update: If a particalar213 // SDK version was specified via --version or --build, look for a match on214 // disk.215 const SDKDirectoryInfo *current_sdk_info =216 GetSDKDirectoryForCurrentOSVersion();217 const uint32_t current_sdk_idx =218 GetSDKIndexBySDKDirectoryInfo(current_sdk_info);219 if (current_sdk_idx < num_sdk_infos &&220 current_sdk_idx != m_last_module_sdk_idx) {221 LLDB_LOGV(log, "Searching for {0} in sdk path {1}", platform_file,222 m_sdk_directory_infos[current_sdk_idx].directory);223 if (GetFileInSDK(platform_file_path, current_sdk_idx,224 platform_module_spec.GetFileSpec())) {225 module_sp.reset();226 error = ResolveExecutable(platform_module_spec, module_sp);227 if (module_sp) {228 m_last_module_sdk_idx = current_sdk_idx;229 error.Clear();230 return error;231 }232 }233 }234 235 // Second try all SDKs that were found.236 for (uint32_t sdk_idx = 0; sdk_idx < num_sdk_infos; ++sdk_idx) {237 if (m_last_module_sdk_idx == sdk_idx) {238 // Skip the last module SDK index if we already searched it above239 continue;240 }241 LLDB_LOGV(log, "Searching for {0} in sdk path {1}", platform_file,242 m_sdk_directory_infos[sdk_idx].directory);243 if (GetFileInSDK(platform_file_path, sdk_idx,244 platform_module_spec.GetFileSpec())) {245 // printf ("sdk[%u]: '%s'\n", sdk_idx, local_file.GetPath().c_str());246 247 error = ResolveExecutable(platform_module_spec, module_sp);248 if (module_sp) {249 // Remember the index of the last SDK that we found a file in in case250 // the wrong SDK was selected.251 m_last_module_sdk_idx = sdk_idx;252 error.Clear();253 return error;254 }255 }256 }257 }258 // Not the module we are looking for... Nothing to see here...259 module_sp.reset();260 261 // This may not be an SDK-related module. Try whether we can bring in the262 // thing to our local cache.263 error = GetSharedModuleWithLocalCache(module_spec, module_sp, old_modules,264 did_create_ptr);265 if (error.Success())266 return error;267 268 // See if the file is present in any of the module_search_paths_ptr269 // directories.270 if (!module_sp)271 error = PlatformDarwin::FindBundleBinaryInExecSearchPaths(272 module_spec, process, module_sp, old_modules, did_create_ptr);273 274 if (error.Success())275 return error;276 277 const bool always_create = false;278 error = ModuleList::GetSharedModule(module_spec, module_sp, old_modules,279 did_create_ptr, always_create);280 281 if (module_sp)282 module_sp->SetPlatformFileSpec(platform_file);283 284 return error;285}286 287uint32_t PlatformRemoteDarwinDevice::GetConnectedSDKIndex() {288 if (IsConnected()) {289 if (m_connected_module_sdk_idx == UINT32_MAX) {290 if (std::optional<std::string> build = GetRemoteOSBuildString()) {291 const uint32_t num_sdk_infos = m_sdk_directory_infos.size();292 for (uint32_t i = 0; i < num_sdk_infos; ++i) {293 const SDKDirectoryInfo &sdk_dir_info = m_sdk_directory_infos[i];294 if (strstr(sdk_dir_info.directory.GetFilename().AsCString(""),295 build->c_str())) {296 m_connected_module_sdk_idx = i;297 }298 }299 }300 }301 } else {302 m_connected_module_sdk_idx = UINT32_MAX;303 }304 return m_connected_module_sdk_idx;305}306 307uint32_t PlatformRemoteDarwinDevice::GetSDKIndexBySDKDirectoryInfo(308 const SDKDirectoryInfo *sdk_info) {309 if (sdk_info == nullptr) {310 return UINT32_MAX;311 }312 313 return sdk_info - &m_sdk_directory_infos[0];314}315