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