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 27 using namespace lldb; 28 using namespace lldb_private; 29 30 PlatformRemoteDarwinDevice::SDKDirectoryInfo::SDKDirectoryInfo( 31 const lldb_private::FileSpec &sdk_dir) 32 : directory(sdk_dir), build(), user_cached(false) { 33 llvm::StringRef dirname_str = sdk_dir.GetFilename().GetStringRef(); 34 llvm::StringRef build_str; 35 std::tie(version, build_str) = ParseVersionBuildDir(dirname_str); 36 build.SetString(build_str); 37 } 38 39 /// Default Constructor 40 PlatformRemoteDarwinDevice::PlatformRemoteDarwinDevice() 41 : PlatformDarwinDevice(false) {} // This is a remote platform 42 43 /// Destructor. 44 /// 45 /// The destructor is virtual since this class is designed to be 46 /// inherited from by the plug-in instance. 47 PlatformRemoteDarwinDevice::~PlatformRemoteDarwinDevice() = default; 48 49 void PlatformRemoteDarwinDevice::GetStatus(Stream &strm) { 50 Platform::GetStatus(strm); 51 const char *sdk_directory = GetDeviceSupportDirectoryForOSVersion(); 52 if (sdk_directory) 53 strm.Printf(" SDK Path: \"%s\"\n", sdk_directory); 54 else 55 strm.PutCString(" SDK Path: error: unable to locate SDK\n"); 56 57 const uint32_t num_sdk_infos = m_sdk_directory_infos.size(); 58 for (uint32_t i = 0; i < num_sdk_infos; ++i) { 59 const SDKDirectoryInfo &sdk_dir_info = m_sdk_directory_infos[i]; 60 strm.Printf(" SDK Roots: [%2u] \"%s\"\n", i, 61 sdk_dir_info.directory.GetPath().c_str()); 62 } 63 } 64 65 Status PlatformRemoteDarwinDevice::ResolveExecutable( 66 const ModuleSpec &ms, lldb::ModuleSP &exe_module_sp, 67 const FileSpecList *module_search_paths_ptr) { 68 Status error; 69 // Nothing special to do here, just use the actual file and architecture 70 71 ModuleSpec resolved_module_spec(ms); 72 73 // Resolve any executable within a bundle on MacOSX 74 // TODO: verify that this handles shallow bundles, if not then implement one 75 // ourselves 76 Host::ResolveExecutableInBundle(resolved_module_spec.GetFileSpec()); 77 78 if (FileSystem::Instance().Exists(resolved_module_spec.GetFileSpec())) { 79 if (resolved_module_spec.GetArchitecture().IsValid() || 80 resolved_module_spec.GetUUID().IsValid()) { 81 error = ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp, 82 nullptr, nullptr, nullptr); 83 84 if (exe_module_sp && exe_module_sp->GetObjectFile()) 85 return error; 86 exe_module_sp.reset(); 87 } 88 // No valid architecture was specified or the exact ARM slice wasn't found 89 // so ask the platform for the architectures that we should be using (in 90 // the correct order) and see if we can find a match that way 91 StreamString arch_names; 92 llvm::ListSeparator LS; 93 ArchSpec process_host_arch; 94 for (const ArchSpec &arch : GetSupportedArchitectures(process_host_arch)) { 95 resolved_module_spec.GetArchitecture() = arch; 96 error = ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp, 97 nullptr, nullptr, nullptr); 98 // Did we find an executable using one of the 99 if (error.Success()) { 100 if (exe_module_sp && exe_module_sp->GetObjectFile()) 101 break; 102 else 103 error.SetErrorToGenericError(); 104 } 105 106 arch_names << LS << arch.GetArchitectureName(); 107 } 108 109 if (error.Fail() || !exe_module_sp) { 110 if (FileSystem::Instance().Readable(resolved_module_spec.GetFileSpec())) { 111 error.SetErrorStringWithFormatv( 112 "'{0}' doesn't contain any '{1}' platform architectures: {2}", 113 resolved_module_spec.GetFileSpec(), GetPluginName(), 114 arch_names.GetData()); 115 } else { 116 error.SetErrorStringWithFormat( 117 "'%s' is not readable", 118 resolved_module_spec.GetFileSpec().GetPath().c_str()); 119 } 120 } 121 } else { 122 error.SetErrorStringWithFormat( 123 "'%s' does not exist", 124 resolved_module_spec.GetFileSpec().GetPath().c_str()); 125 } 126 127 return error; 128 } 129 130 bool PlatformRemoteDarwinDevice::GetFileInSDK(const char *platform_file_path, 131 uint32_t sdk_idx, 132 lldb_private::FileSpec &local_file) { 133 Log *log = GetLog(LLDBLog::Host); 134 if (sdk_idx < m_sdk_directory_infos.size()) { 135 std::string sdkroot_path = 136 m_sdk_directory_infos[sdk_idx].directory.GetPath(); 137 local_file.Clear(); 138 139 if (!sdkroot_path.empty() && platform_file_path && platform_file_path[0]) { 140 // We may need to interpose "/Symbols/" or "/Symbols.Internal/" between 141 // the 142 // SDK root directory and the file path. 143 144 const char *paths_to_try[] = {"Symbols", "", "Symbols.Internal", nullptr}; 145 for (size_t i = 0; paths_to_try[i] != nullptr; i++) { 146 local_file.SetFile(sdkroot_path, FileSpec::Style::native); 147 if (paths_to_try[i][0] != '\0') 148 local_file.AppendPathComponent(paths_to_try[i]); 149 local_file.AppendPathComponent(platform_file_path); 150 FileSystem::Instance().Resolve(local_file); 151 if (FileSystem::Instance().Exists(local_file)) { 152 LLDB_LOGF(log, "Found a copy of %s in the SDK dir %s/%s", 153 platform_file_path, sdkroot_path.c_str(), paths_to_try[i]); 154 return true; 155 } 156 local_file.Clear(); 157 } 158 } 159 } 160 return false; 161 } 162 163 Status PlatformRemoteDarwinDevice::GetSymbolFile(const FileSpec &platform_file, 164 const UUID *uuid_ptr, 165 FileSpec &local_file) { 166 Log *log = GetLog(LLDBLog::Host); 167 Status error; 168 char platform_file_path[PATH_MAX]; 169 if (platform_file.GetPath(platform_file_path, sizeof(platform_file_path))) { 170 const char *os_version_dir = GetDeviceSupportDirectoryForOSVersion(); 171 if (os_version_dir) { 172 std::string resolved_path = 173 (llvm::Twine(os_version_dir) + "/" + platform_file_path).str(); 174 175 local_file.SetFile(resolved_path, FileSpec::Style::native); 176 FileSystem::Instance().Resolve(local_file); 177 if (FileSystem::Instance().Exists(local_file)) { 178 if (log) { 179 LLDB_LOGF(log, "Found a copy of %s in the DeviceSupport dir %s", 180 platform_file_path, os_version_dir); 181 } 182 return error; 183 } 184 185 resolved_path = (llvm::Twine(os_version_dir) + "/Symbols.Internal/" + 186 platform_file_path) 187 .str(); 188 189 local_file.SetFile(resolved_path, FileSpec::Style::native); 190 FileSystem::Instance().Resolve(local_file); 191 if (FileSystem::Instance().Exists(local_file)) { 192 LLDB_LOGF( 193 log, 194 "Found a copy of %s in the DeviceSupport dir %s/Symbols.Internal", 195 platform_file_path, os_version_dir); 196 return error; 197 } 198 resolved_path = 199 (llvm::Twine(os_version_dir) + "/Symbols/" + platform_file_path) 200 .str(); 201 202 local_file.SetFile(resolved_path, FileSpec::Style::native); 203 FileSystem::Instance().Resolve(local_file); 204 if (FileSystem::Instance().Exists(local_file)) { 205 LLDB_LOGF(log, "Found a copy of %s in the DeviceSupport dir %s/Symbols", 206 platform_file_path, os_version_dir); 207 return error; 208 } 209 } 210 local_file = platform_file; 211 if (FileSystem::Instance().Exists(local_file)) 212 return error; 213 214 error.SetErrorStringWithFormatv( 215 "unable to locate a platform file for '{0}' in platform '{1}'", 216 platform_file_path, GetPluginName()); 217 } else { 218 error.SetErrorString("invalid platform file argument"); 219 } 220 return error; 221 } 222 223 Status PlatformRemoteDarwinDevice::GetSharedModule( 224 const ModuleSpec &module_spec, Process *process, ModuleSP &module_sp, 225 const FileSpecList *module_search_paths_ptr, 226 llvm::SmallVectorImpl<ModuleSP> *old_modules, bool *did_create_ptr) { 227 // For iOS, the SDK files are all cached locally on the host system. So first 228 // we ask for the file in the cached SDK, then we attempt to get a shared 229 // module for the right architecture with the right UUID. 230 const FileSpec &platform_file = module_spec.GetFileSpec(); 231 Log *log = GetLog(LLDBLog::Host); 232 233 Status error; 234 char platform_file_path[PATH_MAX]; 235 236 if (platform_file.GetPath(platform_file_path, sizeof(platform_file_path))) { 237 ModuleSpec platform_module_spec(module_spec); 238 239 UpdateSDKDirectoryInfosIfNeeded(); 240 241 const uint32_t num_sdk_infos = m_sdk_directory_infos.size(); 242 243 // If we are connected we migth be able to correctly deduce the SDK 244 // directory using the OS build. 245 const uint32_t connected_sdk_idx = GetConnectedSDKIndex(); 246 if (connected_sdk_idx < num_sdk_infos) { 247 LLDB_LOGV(log, "Searching for {0} in sdk path {1}", platform_file, 248 m_sdk_directory_infos[connected_sdk_idx].directory); 249 if (GetFileInSDK(platform_file_path, connected_sdk_idx, 250 platform_module_spec.GetFileSpec())) { 251 module_sp.reset(); 252 error = ResolveExecutable(platform_module_spec, module_sp, nullptr); 253 if (module_sp) { 254 m_last_module_sdk_idx = connected_sdk_idx; 255 error.Clear(); 256 return error; 257 } 258 } 259 } 260 261 // Try the last SDK index if it is set as most files from an SDK will tend 262 // to be valid in that same SDK. 263 if (m_last_module_sdk_idx < num_sdk_infos) { 264 LLDB_LOGV(log, "Searching for {0} in sdk path {1}", platform_file, 265 m_sdk_directory_infos[m_last_module_sdk_idx].directory); 266 if (GetFileInSDK(platform_file_path, m_last_module_sdk_idx, 267 platform_module_spec.GetFileSpec())) { 268 module_sp.reset(); 269 error = ResolveExecutable(platform_module_spec, module_sp, nullptr); 270 if (module_sp) { 271 error.Clear(); 272 return error; 273 } 274 } 275 } 276 277 // First try for an exact match of major, minor and update: If a particalar 278 // SDK version was specified via --version or --build, look for a match on 279 // disk. 280 const SDKDirectoryInfo *current_sdk_info = 281 GetSDKDirectoryForCurrentOSVersion(); 282 const uint32_t current_sdk_idx = 283 GetSDKIndexBySDKDirectoryInfo(current_sdk_info); 284 if (current_sdk_idx < num_sdk_infos && 285 current_sdk_idx != m_last_module_sdk_idx) { 286 LLDB_LOGV(log, "Searching for {0} in sdk path {1}", platform_file, 287 m_sdk_directory_infos[current_sdk_idx].directory); 288 if (GetFileInSDK(platform_file_path, current_sdk_idx, 289 platform_module_spec.GetFileSpec())) { 290 module_sp.reset(); 291 error = ResolveExecutable(platform_module_spec, module_sp, nullptr); 292 if (module_sp) { 293 m_last_module_sdk_idx = current_sdk_idx; 294 error.Clear(); 295 return error; 296 } 297 } 298 } 299 300 // Second try all SDKs that were found. 301 for (uint32_t sdk_idx = 0; sdk_idx < num_sdk_infos; ++sdk_idx) { 302 if (m_last_module_sdk_idx == sdk_idx) { 303 // Skip the last module SDK index if we already searched it above 304 continue; 305 } 306 LLDB_LOGV(log, "Searching for {0} in sdk path {1}", platform_file, 307 m_sdk_directory_infos[sdk_idx].directory); 308 if (GetFileInSDK(platform_file_path, sdk_idx, 309 platform_module_spec.GetFileSpec())) { 310 // printf ("sdk[%u]: '%s'\n", sdk_idx, local_file.GetPath().c_str()); 311 312 error = ResolveExecutable(platform_module_spec, module_sp, nullptr); 313 if (module_sp) { 314 // Remember the index of the last SDK that we found a file in in case 315 // the wrong SDK was selected. 316 m_last_module_sdk_idx = sdk_idx; 317 error.Clear(); 318 return error; 319 } 320 } 321 } 322 } 323 // Not the module we are looking for... Nothing to see here... 324 module_sp.reset(); 325 326 // This may not be an SDK-related module. Try whether we can bring in the 327 // thing to our local cache. 328 error = GetSharedModuleWithLocalCache(module_spec, module_sp, 329 module_search_paths_ptr, old_modules, 330 did_create_ptr); 331 if (error.Success()) 332 return error; 333 334 // See if the file is present in any of the module_search_paths_ptr 335 // directories. 336 if (!module_sp) 337 error = PlatformDarwin::FindBundleBinaryInExecSearchPaths( 338 module_spec, process, module_sp, module_search_paths_ptr, old_modules, 339 did_create_ptr); 340 341 if (error.Success()) 342 return error; 343 344 const bool always_create = false; 345 error = ModuleList::GetSharedModule(module_spec, module_sp, 346 module_search_paths_ptr, old_modules, 347 did_create_ptr, always_create); 348 349 if (module_sp) 350 module_sp->SetPlatformFileSpec(platform_file); 351 352 return error; 353 } 354 355 uint32_t PlatformRemoteDarwinDevice::GetConnectedSDKIndex() { 356 if (IsConnected()) { 357 if (m_connected_module_sdk_idx == UINT32_MAX) { 358 if (llvm::Optional<std::string> build = GetRemoteOSBuildString()) { 359 const uint32_t num_sdk_infos = m_sdk_directory_infos.size(); 360 for (uint32_t i = 0; i < num_sdk_infos; ++i) { 361 const SDKDirectoryInfo &sdk_dir_info = m_sdk_directory_infos[i]; 362 if (strstr(sdk_dir_info.directory.GetFilename().AsCString(""), 363 build->c_str())) { 364 m_connected_module_sdk_idx = i; 365 } 366 } 367 } 368 } 369 } else { 370 m_connected_module_sdk_idx = UINT32_MAX; 371 } 372 return m_connected_module_sdk_idx; 373 } 374 375 uint32_t PlatformRemoteDarwinDevice::GetSDKIndexBySDKDirectoryInfo( 376 const SDKDirectoryInfo *sdk_info) { 377 if (sdk_info == nullptr) { 378 return UINT32_MAX; 379 } 380 381 return sdk_info - &m_sdk_directory_infos[0]; 382 } 383