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-exception 6 // 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 28 using namespace lldb; 29 using namespace lldb_private; 30 31 PlatformRemoteDarwinDevice::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 Constructor 41 PlatformRemoteDarwinDevice::PlatformRemoteDarwinDevice() 42 : PlatformDarwinDevice(false) {} // This is a remote platform 43 44 /// Destructor. 45 /// 46 /// The destructor is virtual since this class is designed to be 47 /// inherited from by the plug-in instance. 48 PlatformRemoteDarwinDevice::~PlatformRemoteDarwinDevice() = default; 49 50 void 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 else 56 strm.PutCString(" SDK Path: error: 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 66 bool 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/" between 77 // the 78 // 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 99 Status 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 159 Status PlatformRemoteDarwinDevice::GetSharedModule( 160 const ModuleSpec &module_spec, Process *process, ModuleSP &module_sp, 161 const FileSpecList *module_search_paths_ptr, 162 llvm::SmallVectorImpl<ModuleSP> *old_modules, bool *did_create_ptr) { 163 // For iOS, the SDK files are all cached locally on the host system. So first 164 // we ask for the file in the cached SDK, then we attempt to get a shared 165 // module for the right architecture with the right UUID. 166 const FileSpec &platform_file = module_spec.GetFileSpec(); 167 Log *log = GetLog(LLDBLog::Host); 168 169 Status error; 170 char platform_file_path[PATH_MAX]; 171 172 if (platform_file.GetPath(platform_file_path, sizeof(platform_file_path))) { 173 ModuleSpec platform_module_spec(module_spec); 174 175 UpdateSDKDirectoryInfosIfNeeded(); 176 177 const uint32_t num_sdk_infos = m_sdk_directory_infos.size(); 178 179 // If we are connected we migth be able to correctly deduce the SDK 180 // directory using the OS build. 181 const uint32_t connected_sdk_idx = GetConnectedSDKIndex(); 182 if (connected_sdk_idx < num_sdk_infos) { 183 LLDB_LOGV(log, "Searching for {0} in sdk path {1}", platform_file, 184 m_sdk_directory_infos[connected_sdk_idx].directory); 185 if (GetFileInSDK(platform_file_path, connected_sdk_idx, 186 platform_module_spec.GetFileSpec())) { 187 module_sp.reset(); 188 error = ResolveExecutable(platform_module_spec, module_sp, nullptr); 189 if (module_sp) { 190 m_last_module_sdk_idx = connected_sdk_idx; 191 error.Clear(); 192 return error; 193 } 194 } 195 } 196 197 // Try the last SDK index if it is set as most files from an SDK will tend 198 // to be valid in that same SDK. 199 if (m_last_module_sdk_idx < num_sdk_infos) { 200 LLDB_LOGV(log, "Searching for {0} in sdk path {1}", platform_file, 201 m_sdk_directory_infos[m_last_module_sdk_idx].directory); 202 if (GetFileInSDK(platform_file_path, m_last_module_sdk_idx, 203 platform_module_spec.GetFileSpec())) { 204 module_sp.reset(); 205 error = ResolveExecutable(platform_module_spec, module_sp, nullptr); 206 if (module_sp) { 207 error.Clear(); 208 return error; 209 } 210 } 211 } 212 213 // First try for an exact match of major, minor and update: If a particalar 214 // SDK version was specified via --version or --build, look for a match on 215 // disk. 216 const SDKDirectoryInfo *current_sdk_info = 217 GetSDKDirectoryForCurrentOSVersion(); 218 const uint32_t current_sdk_idx = 219 GetSDKIndexBySDKDirectoryInfo(current_sdk_info); 220 if (current_sdk_idx < num_sdk_infos && 221 current_sdk_idx != m_last_module_sdk_idx) { 222 LLDB_LOGV(log, "Searching for {0} in sdk path {1}", platform_file, 223 m_sdk_directory_infos[current_sdk_idx].directory); 224 if (GetFileInSDK(platform_file_path, current_sdk_idx, 225 platform_module_spec.GetFileSpec())) { 226 module_sp.reset(); 227 error = ResolveExecutable(platform_module_spec, module_sp, nullptr); 228 if (module_sp) { 229 m_last_module_sdk_idx = current_sdk_idx; 230 error.Clear(); 231 return error; 232 } 233 } 234 } 235 236 // Second try all SDKs that were found. 237 for (uint32_t sdk_idx = 0; sdk_idx < num_sdk_infos; ++sdk_idx) { 238 if (m_last_module_sdk_idx == sdk_idx) { 239 // Skip the last module SDK index if we already searched it above 240 continue; 241 } 242 LLDB_LOGV(log, "Searching for {0} in sdk path {1}", platform_file, 243 m_sdk_directory_infos[sdk_idx].directory); 244 if (GetFileInSDK(platform_file_path, sdk_idx, 245 platform_module_spec.GetFileSpec())) { 246 // printf ("sdk[%u]: '%s'\n", sdk_idx, local_file.GetPath().c_str()); 247 248 error = ResolveExecutable(platform_module_spec, module_sp, nullptr); 249 if (module_sp) { 250 // Remember the index of the last SDK that we found a file in in case 251 // the wrong SDK was selected. 252 m_last_module_sdk_idx = sdk_idx; 253 error.Clear(); 254 return error; 255 } 256 } 257 } 258 } 259 // Not the module we are looking for... Nothing to see here... 260 module_sp.reset(); 261 262 // This may not be an SDK-related module. Try whether we can bring in the 263 // thing to our local cache. 264 error = GetSharedModuleWithLocalCache(module_spec, module_sp, 265 module_search_paths_ptr, old_modules, 266 did_create_ptr); 267 if (error.Success()) 268 return error; 269 270 // See if the file is present in any of the module_search_paths_ptr 271 // directories. 272 if (!module_sp) 273 error = PlatformDarwin::FindBundleBinaryInExecSearchPaths( 274 module_spec, process, module_sp, module_search_paths_ptr, old_modules, 275 did_create_ptr); 276 277 if (error.Success()) 278 return error; 279 280 const bool always_create = false; 281 error = ModuleList::GetSharedModule(module_spec, module_sp, 282 module_search_paths_ptr, old_modules, 283 did_create_ptr, always_create); 284 285 if (module_sp) 286 module_sp->SetPlatformFileSpec(platform_file); 287 288 return error; 289 } 290 291 uint32_t PlatformRemoteDarwinDevice::GetConnectedSDKIndex() { 292 if (IsConnected()) { 293 if (m_connected_module_sdk_idx == UINT32_MAX) { 294 if (std::optional<std::string> build = GetRemoteOSBuildString()) { 295 const uint32_t num_sdk_infos = m_sdk_directory_infos.size(); 296 for (uint32_t i = 0; i < num_sdk_infos; ++i) { 297 const SDKDirectoryInfo &sdk_dir_info = m_sdk_directory_infos[i]; 298 if (strstr(sdk_dir_info.directory.GetFilename().AsCString(""), 299 build->c_str())) { 300 m_connected_module_sdk_idx = i; 301 } 302 } 303 } 304 } 305 } else { 306 m_connected_module_sdk_idx = UINT32_MAX; 307 } 308 return m_connected_module_sdk_idx; 309 } 310 311 uint32_t PlatformRemoteDarwinDevice::GetSDKIndexBySDKDirectoryInfo( 312 const SDKDirectoryInfo *sdk_info) { 313 if (sdk_info == nullptr) { 314 return UINT32_MAX; 315 } 316 317 return sdk_info - &m_sdk_directory_infos[0]; 318 } 319