1f678e45dSDimitry Andric //===--------------------- ModuleCache.cpp ----------------------*- C++ -*-===//
2f678e45dSDimitry Andric //
3f678e45dSDimitry Andric //                     The LLVM Compiler Infrastructure
4f678e45dSDimitry Andric //
5f678e45dSDimitry Andric // This file is distributed under the University of Illinois Open Source
6f678e45dSDimitry Andric // License. See LICENSE.TXT for details.
7f678e45dSDimitry Andric //
8f678e45dSDimitry Andric //===----------------------------------------------------------------------===//
9f678e45dSDimitry Andric 
10f678e45dSDimitry Andric #include "lldb/Target/ModuleCache.h"
11f678e45dSDimitry Andric 
12f678e45dSDimitry Andric #include "lldb/Core/Module.h"
13f678e45dSDimitry Andric #include "lldb/Core/ModuleList.h"
14f678e45dSDimitry Andric #include "lldb/Core/ModuleSpec.h"
15f678e45dSDimitry Andric #include "lldb/Host/File.h"
16f678e45dSDimitry Andric #include "lldb/Host/LockFile.h"
17f678e45dSDimitry Andric #include "lldb/Utility/Log.h"
18f678e45dSDimitry Andric #include "llvm/Support/FileSystem.h"
19f678e45dSDimitry Andric #include "llvm/Support/FileUtilities.h"
20f678e45dSDimitry Andric 
21f678e45dSDimitry Andric #include <assert.h>
22f678e45dSDimitry Andric 
23f678e45dSDimitry Andric #include <cstdio>
24f678e45dSDimitry Andric 
25f678e45dSDimitry Andric using namespace lldb;
26f678e45dSDimitry Andric using namespace lldb_private;
27f678e45dSDimitry Andric 
28f678e45dSDimitry Andric namespace {
29f678e45dSDimitry Andric 
30f678e45dSDimitry Andric const char *kModulesSubdir = ".cache";
31f678e45dSDimitry Andric const char *kLockDirName = ".lock";
32f678e45dSDimitry Andric const char *kTempFileName = ".temp";
33f678e45dSDimitry Andric const char *kTempSymFileName = ".symtemp";
34f678e45dSDimitry Andric const char *kSymFileExtension = ".sym";
35f678e45dSDimitry Andric const char *kFSIllegalChars = "\\/:*?\"<>|";
36f678e45dSDimitry Andric 
GetEscapedHostname(const char * hostname)37f678e45dSDimitry Andric std::string GetEscapedHostname(const char *hostname) {
38f678e45dSDimitry Andric   if (hostname == nullptr)
39f678e45dSDimitry Andric     hostname = "unknown";
40f678e45dSDimitry Andric   std::string result(hostname);
41f678e45dSDimitry Andric   size_t size = result.size();
42f678e45dSDimitry Andric   for (size_t i = 0; i < size; ++i) {
43f678e45dSDimitry Andric     if ((result[i] >= 1 && result[i] <= 31) ||
44f678e45dSDimitry Andric         strchr(kFSIllegalChars, result[i]) != nullptr)
45f678e45dSDimitry Andric       result[i] = '_';
46f678e45dSDimitry Andric   }
47f678e45dSDimitry Andric   return result;
48f678e45dSDimitry Andric }
49f678e45dSDimitry Andric 
50f678e45dSDimitry Andric class ModuleLock {
51f678e45dSDimitry Andric private:
52f678e45dSDimitry Andric   File m_file;
53f678e45dSDimitry Andric   std::unique_ptr<lldb_private::LockFile> m_lock;
54f678e45dSDimitry Andric   FileSpec m_file_spec;
55f678e45dSDimitry Andric 
56f678e45dSDimitry Andric public:
575517e702SDimitry Andric   ModuleLock(const FileSpec &root_dir_spec, const UUID &uuid, Status &error);
58f678e45dSDimitry Andric   void Delete();
59f678e45dSDimitry Andric };
60f678e45dSDimitry Andric 
JoinPath(const FileSpec & path1,const char * path2)61f678e45dSDimitry Andric static FileSpec JoinPath(const FileSpec &path1, const char *path2) {
62f678e45dSDimitry Andric   FileSpec result_spec(path1);
63f678e45dSDimitry Andric   result_spec.AppendPathComponent(path2);
64f678e45dSDimitry Andric   return result_spec;
65f678e45dSDimitry Andric }
66f678e45dSDimitry Andric 
MakeDirectory(const FileSpec & dir_path)675517e702SDimitry Andric static Status MakeDirectory(const FileSpec &dir_path) {
68f678e45dSDimitry Andric   namespace fs = llvm::sys::fs;
69f678e45dSDimitry Andric 
70f678e45dSDimitry Andric   return fs::create_directories(dir_path.GetPath(), true, fs::perms::owner_all);
71f678e45dSDimitry Andric }
72f678e45dSDimitry Andric 
GetModuleDirectory(const FileSpec & root_dir_spec,const UUID & uuid)73f678e45dSDimitry Andric FileSpec GetModuleDirectory(const FileSpec &root_dir_spec, const UUID &uuid) {
74f678e45dSDimitry Andric   const auto modules_dir_spec = JoinPath(root_dir_spec, kModulesSubdir);
75f678e45dSDimitry Andric   return JoinPath(modules_dir_spec, uuid.GetAsString().c_str());
76f678e45dSDimitry Andric }
77f678e45dSDimitry Andric 
GetSymbolFileSpec(const FileSpec & module_file_spec)78f678e45dSDimitry Andric FileSpec GetSymbolFileSpec(const FileSpec &module_file_spec) {
79*b5893f02SDimitry Andric   return FileSpec(module_file_spec.GetPath() + kSymFileExtension);
80f678e45dSDimitry Andric }
81f678e45dSDimitry Andric 
DeleteExistingModule(const FileSpec & root_dir_spec,const FileSpec & sysroot_module_path_spec)82f678e45dSDimitry Andric void DeleteExistingModule(const FileSpec &root_dir_spec,
83f678e45dSDimitry Andric                           const FileSpec &sysroot_module_path_spec) {
84f678e45dSDimitry Andric   Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_MODULES));
85f678e45dSDimitry Andric   UUID module_uuid;
86f678e45dSDimitry Andric   {
87f678e45dSDimitry Andric     auto module_sp =
88f678e45dSDimitry Andric         std::make_shared<Module>(ModuleSpec(sysroot_module_path_spec));
89f678e45dSDimitry Andric     module_uuid = module_sp->GetUUID();
90f678e45dSDimitry Andric   }
91f678e45dSDimitry Andric 
92f678e45dSDimitry Andric   if (!module_uuid.IsValid())
93f678e45dSDimitry Andric     return;
94f678e45dSDimitry Andric 
955517e702SDimitry Andric   Status error;
96f678e45dSDimitry Andric   ModuleLock lock(root_dir_spec, module_uuid, error);
97f678e45dSDimitry Andric   if (error.Fail()) {
98f678e45dSDimitry Andric     if (log)
99f678e45dSDimitry Andric       log->Printf("Failed to lock module %s: %s",
100f678e45dSDimitry Andric                   module_uuid.GetAsString().c_str(), error.AsCString());
101f678e45dSDimitry Andric   }
102f678e45dSDimitry Andric 
103f678e45dSDimitry Andric   namespace fs = llvm::sys::fs;
104f678e45dSDimitry Andric   fs::file_status st;
105f678e45dSDimitry Andric   if (status(sysroot_module_path_spec.GetPath(), st))
106f678e45dSDimitry Andric     return;
107f678e45dSDimitry Andric 
108f678e45dSDimitry Andric   if (st.getLinkCount() > 2) // module is referred by other hosts.
109f678e45dSDimitry Andric     return;
110f678e45dSDimitry Andric 
111f678e45dSDimitry Andric   const auto module_spec_dir = GetModuleDirectory(root_dir_spec, module_uuid);
112f678e45dSDimitry Andric   llvm::sys::fs::remove_directories(module_spec_dir.GetPath());
113f678e45dSDimitry Andric   lock.Delete();
114f678e45dSDimitry Andric }
115f678e45dSDimitry Andric 
DecrementRefExistingModule(const FileSpec & root_dir_spec,const FileSpec & sysroot_module_path_spec)116f678e45dSDimitry Andric void DecrementRefExistingModule(const FileSpec &root_dir_spec,
117f678e45dSDimitry Andric                                 const FileSpec &sysroot_module_path_spec) {
118f678e45dSDimitry Andric   // Remove $platform/.cache/$uuid folder if nobody else references it.
119f678e45dSDimitry Andric   DeleteExistingModule(root_dir_spec, sysroot_module_path_spec);
120f678e45dSDimitry Andric 
121f678e45dSDimitry Andric   // Remove sysroot link.
122f678e45dSDimitry Andric   llvm::sys::fs::remove(sysroot_module_path_spec.GetPath());
123f678e45dSDimitry Andric 
124f678e45dSDimitry Andric   FileSpec symfile_spec = GetSymbolFileSpec(sysroot_module_path_spec);
125f678e45dSDimitry Andric   llvm::sys::fs::remove(symfile_spec.GetPath());
126f678e45dSDimitry Andric }
127f678e45dSDimitry Andric 
CreateHostSysRootModuleLink(const FileSpec & root_dir_spec,const char * hostname,const FileSpec & platform_module_spec,const FileSpec & local_module_spec,bool delete_existing)1285517e702SDimitry Andric Status CreateHostSysRootModuleLink(const FileSpec &root_dir_spec,
129f678e45dSDimitry Andric                                    const char *hostname,
130f678e45dSDimitry Andric                                    const FileSpec &platform_module_spec,
131f678e45dSDimitry Andric                                    const FileSpec &local_module_spec,
132f678e45dSDimitry Andric                                    bool delete_existing) {
133f678e45dSDimitry Andric   const auto sysroot_module_path_spec =
134f678e45dSDimitry Andric       JoinPath(JoinPath(root_dir_spec, hostname),
135f678e45dSDimitry Andric                platform_module_spec.GetPath().c_str());
136*b5893f02SDimitry Andric   if (FileSystem::Instance().Exists(sysroot_module_path_spec)) {
137f678e45dSDimitry Andric     if (!delete_existing)
1385517e702SDimitry Andric       return Status();
139f678e45dSDimitry Andric 
140f678e45dSDimitry Andric     DecrementRefExistingModule(root_dir_spec, sysroot_module_path_spec);
141f678e45dSDimitry Andric   }
142f678e45dSDimitry Andric 
143f678e45dSDimitry Andric   const auto error = MakeDirectory(
144*b5893f02SDimitry Andric       FileSpec(sysroot_module_path_spec.GetDirectory().AsCString()));
145f678e45dSDimitry Andric   if (error.Fail())
146f678e45dSDimitry Andric     return error;
147f678e45dSDimitry Andric 
148f678e45dSDimitry Andric   return llvm::sys::fs::create_hard_link(local_module_spec.GetPath(),
149f678e45dSDimitry Andric                                          sysroot_module_path_spec.GetPath());
150f678e45dSDimitry Andric }
151f678e45dSDimitry Andric 
152f678e45dSDimitry Andric } // namespace
153f678e45dSDimitry Andric 
ModuleLock(const FileSpec & root_dir_spec,const UUID & uuid,Status & error)154f678e45dSDimitry Andric ModuleLock::ModuleLock(const FileSpec &root_dir_spec, const UUID &uuid,
1555517e702SDimitry Andric                        Status &error) {
156f678e45dSDimitry Andric   const auto lock_dir_spec = JoinPath(root_dir_spec, kLockDirName);
157f678e45dSDimitry Andric   error = MakeDirectory(lock_dir_spec);
158f678e45dSDimitry Andric   if (error.Fail())
159f678e45dSDimitry Andric     return;
160f678e45dSDimitry Andric 
161f678e45dSDimitry Andric   m_file_spec = JoinPath(lock_dir_spec, uuid.GetAsString().c_str());
162*b5893f02SDimitry Andric   FileSystem::Instance().Open(m_file, m_file_spec,
163*b5893f02SDimitry Andric                               File::eOpenOptionWrite |
164f678e45dSDimitry Andric                                   File::eOpenOptionCanCreate |
165f678e45dSDimitry Andric                                   File::eOpenOptionCloseOnExec);
166f678e45dSDimitry Andric   if (!m_file) {
167f678e45dSDimitry Andric     error.SetErrorToErrno();
168f678e45dSDimitry Andric     return;
169f678e45dSDimitry Andric   }
170f678e45dSDimitry Andric 
171f678e45dSDimitry Andric   m_lock.reset(new lldb_private::LockFile(m_file.GetDescriptor()));
172f678e45dSDimitry Andric   error = m_lock->WriteLock(0, 1);
173f678e45dSDimitry Andric   if (error.Fail())
174f678e45dSDimitry Andric     error.SetErrorStringWithFormat("Failed to lock file: %s",
175f678e45dSDimitry Andric                                    error.AsCString());
176f678e45dSDimitry Andric }
177f678e45dSDimitry Andric 
Delete()178f678e45dSDimitry Andric void ModuleLock::Delete() {
179f678e45dSDimitry Andric   if (!m_file)
180f678e45dSDimitry Andric     return;
181f678e45dSDimitry Andric 
182f678e45dSDimitry Andric   m_file.Close();
183f678e45dSDimitry Andric   llvm::sys::fs::remove(m_file_spec.GetPath());
184f678e45dSDimitry Andric }
185f678e45dSDimitry Andric 
186f678e45dSDimitry Andric /////////////////////////////////////////////////////////////////////////
187f678e45dSDimitry Andric 
Put(const FileSpec & root_dir_spec,const char * hostname,const ModuleSpec & module_spec,const FileSpec & tmp_file,const FileSpec & target_file)1885517e702SDimitry Andric Status ModuleCache::Put(const FileSpec &root_dir_spec, const char *hostname,
189f678e45dSDimitry Andric                         const ModuleSpec &module_spec, const FileSpec &tmp_file,
190f678e45dSDimitry Andric                         const FileSpec &target_file) {
191f678e45dSDimitry Andric   const auto module_spec_dir =
192f678e45dSDimitry Andric       GetModuleDirectory(root_dir_spec, module_spec.GetUUID());
193f678e45dSDimitry Andric   const auto module_file_path =
194f678e45dSDimitry Andric       JoinPath(module_spec_dir, target_file.GetFilename().AsCString());
195f678e45dSDimitry Andric 
196f678e45dSDimitry Andric   const auto tmp_file_path = tmp_file.GetPath();
197f678e45dSDimitry Andric   const auto err_code =
198f678e45dSDimitry Andric       llvm::sys::fs::rename(tmp_file_path, module_file_path.GetPath());
199f678e45dSDimitry Andric   if (err_code)
2005517e702SDimitry Andric     return Status("Failed to rename file %s to %s: %s", tmp_file_path.c_str(),
201f678e45dSDimitry Andric                   module_file_path.GetPath().c_str(),
202f678e45dSDimitry Andric                   err_code.message().c_str());
203f678e45dSDimitry Andric 
204f678e45dSDimitry Andric   const auto error = CreateHostSysRootModuleLink(
205f678e45dSDimitry Andric       root_dir_spec, hostname, target_file, module_file_path, true);
206f678e45dSDimitry Andric   if (error.Fail())
2075517e702SDimitry Andric     return Status("Failed to create link to %s: %s",
208f678e45dSDimitry Andric                   module_file_path.GetPath().c_str(), error.AsCString());
2095517e702SDimitry Andric   return Status();
210f678e45dSDimitry Andric }
211f678e45dSDimitry Andric 
Get(const FileSpec & root_dir_spec,const char * hostname,const ModuleSpec & module_spec,ModuleSP & cached_module_sp,bool * did_create_ptr)2125517e702SDimitry Andric Status ModuleCache::Get(const FileSpec &root_dir_spec, const char *hostname,
213f678e45dSDimitry Andric                         const ModuleSpec &module_spec,
214f678e45dSDimitry Andric                         ModuleSP &cached_module_sp, bool *did_create_ptr) {
215f678e45dSDimitry Andric   const auto find_it =
216f678e45dSDimitry Andric       m_loaded_modules.find(module_spec.GetUUID().GetAsString());
217f678e45dSDimitry Andric   if (find_it != m_loaded_modules.end()) {
218f678e45dSDimitry Andric     cached_module_sp = (*find_it).second.lock();
219f678e45dSDimitry Andric     if (cached_module_sp)
2205517e702SDimitry Andric       return Status();
221f678e45dSDimitry Andric     m_loaded_modules.erase(find_it);
222f678e45dSDimitry Andric   }
223f678e45dSDimitry Andric 
224f678e45dSDimitry Andric   const auto module_spec_dir =
225f678e45dSDimitry Andric       GetModuleDirectory(root_dir_spec, module_spec.GetUUID());
226f678e45dSDimitry Andric   const auto module_file_path = JoinPath(
227f678e45dSDimitry Andric       module_spec_dir, module_spec.GetFileSpec().GetFilename().AsCString());
228f678e45dSDimitry Andric 
229*b5893f02SDimitry Andric   if (!FileSystem::Instance().Exists(module_file_path))
2305517e702SDimitry Andric     return Status("Module %s not found", module_file_path.GetPath().c_str());
231*b5893f02SDimitry Andric   if (FileSystem::Instance().GetByteSize(module_file_path) !=
232*b5893f02SDimitry Andric       module_spec.GetObjectSize())
2335517e702SDimitry Andric     return Status("Module %s has invalid file size",
234f678e45dSDimitry Andric                   module_file_path.GetPath().c_str());
235f678e45dSDimitry Andric 
236f678e45dSDimitry Andric   // We may have already cached module but downloaded from an another host - in
237f678e45dSDimitry Andric   // this case let's create a link to it.
238f678e45dSDimitry Andric   auto error = CreateHostSysRootModuleLink(root_dir_spec, hostname,
239f678e45dSDimitry Andric                                            module_spec.GetFileSpec(),
240f678e45dSDimitry Andric                                            module_file_path, false);
241f678e45dSDimitry Andric   if (error.Fail())
2425517e702SDimitry Andric     return Status("Failed to create link to %s: %s",
243f678e45dSDimitry Andric                   module_file_path.GetPath().c_str(), error.AsCString());
244f678e45dSDimitry Andric 
245f678e45dSDimitry Andric   auto cached_module_spec(module_spec);
246f678e45dSDimitry Andric   cached_module_spec.GetUUID().Clear(); // Clear UUID since it may contain md5
247f678e45dSDimitry Andric                                         // content hash instead of real UUID.
248f678e45dSDimitry Andric   cached_module_spec.GetFileSpec() = module_file_path;
249f678e45dSDimitry Andric   cached_module_spec.GetPlatformFileSpec() = module_spec.GetFileSpec();
250f678e45dSDimitry Andric 
251f678e45dSDimitry Andric   error = ModuleList::GetSharedModule(cached_module_spec, cached_module_sp,
252f678e45dSDimitry Andric                                       nullptr, nullptr, did_create_ptr, false);
253f678e45dSDimitry Andric   if (error.Fail())
254f678e45dSDimitry Andric     return error;
255f678e45dSDimitry Andric 
256f678e45dSDimitry Andric   FileSpec symfile_spec = GetSymbolFileSpec(cached_module_sp->GetFileSpec());
257*b5893f02SDimitry Andric   if (FileSystem::Instance().Exists(symfile_spec))
258f678e45dSDimitry Andric     cached_module_sp->SetSymbolFileFileSpec(symfile_spec);
259f678e45dSDimitry Andric 
260f678e45dSDimitry Andric   m_loaded_modules.insert(
261f678e45dSDimitry Andric       std::make_pair(module_spec.GetUUID().GetAsString(), cached_module_sp));
262f678e45dSDimitry Andric 
2635517e702SDimitry Andric   return Status();
264f678e45dSDimitry Andric }
265f678e45dSDimitry Andric 
GetAndPut(const FileSpec & root_dir_spec,const char * hostname,const ModuleSpec & module_spec,const ModuleDownloader & module_downloader,const SymfileDownloader & symfile_downloader,lldb::ModuleSP & cached_module_sp,bool * did_create_ptr)2665517e702SDimitry Andric Status ModuleCache::GetAndPut(const FileSpec &root_dir_spec,
267f678e45dSDimitry Andric                               const char *hostname,
268f678e45dSDimitry Andric                               const ModuleSpec &module_spec,
269f678e45dSDimitry Andric                               const ModuleDownloader &module_downloader,
270f678e45dSDimitry Andric                               const SymfileDownloader &symfile_downloader,
271f678e45dSDimitry Andric                               lldb::ModuleSP &cached_module_sp,
272f678e45dSDimitry Andric                               bool *did_create_ptr) {
273f678e45dSDimitry Andric   const auto module_spec_dir =
274f678e45dSDimitry Andric       GetModuleDirectory(root_dir_spec, module_spec.GetUUID());
275f678e45dSDimitry Andric   auto error = MakeDirectory(module_spec_dir);
276f678e45dSDimitry Andric   if (error.Fail())
277f678e45dSDimitry Andric     return error;
278f678e45dSDimitry Andric 
279f678e45dSDimitry Andric   ModuleLock lock(root_dir_spec, module_spec.GetUUID(), error);
280f678e45dSDimitry Andric   if (error.Fail())
2815517e702SDimitry Andric     return Status("Failed to lock module %s: %s",
282f678e45dSDimitry Andric                   module_spec.GetUUID().GetAsString().c_str(),
283f678e45dSDimitry Andric                   error.AsCString());
284f678e45dSDimitry Andric 
285f678e45dSDimitry Andric   const auto escaped_hostname(GetEscapedHostname(hostname));
286f678e45dSDimitry Andric   // Check local cache for a module.
287f678e45dSDimitry Andric   error = Get(root_dir_spec, escaped_hostname.c_str(), module_spec,
288f678e45dSDimitry Andric               cached_module_sp, did_create_ptr);
289f678e45dSDimitry Andric   if (error.Success())
290f678e45dSDimitry Andric     return error;
291f678e45dSDimitry Andric 
292f678e45dSDimitry Andric   const auto tmp_download_file_spec = JoinPath(module_spec_dir, kTempFileName);
293f678e45dSDimitry Andric   error = module_downloader(module_spec, tmp_download_file_spec);
294f678e45dSDimitry Andric   llvm::FileRemover tmp_file_remover(tmp_download_file_spec.GetPath());
295f678e45dSDimitry Andric   if (error.Fail())
2965517e702SDimitry Andric     return Status("Failed to download module: %s", error.AsCString());
297f678e45dSDimitry Andric 
298f678e45dSDimitry Andric   // Put downloaded file into local module cache.
299f678e45dSDimitry Andric   error = Put(root_dir_spec, escaped_hostname.c_str(), module_spec,
300f678e45dSDimitry Andric               tmp_download_file_spec, module_spec.GetFileSpec());
301f678e45dSDimitry Andric   if (error.Fail())
3025517e702SDimitry Andric     return Status("Failed to put module into cache: %s", error.AsCString());
303f678e45dSDimitry Andric 
304f678e45dSDimitry Andric   tmp_file_remover.releaseFile();
305f678e45dSDimitry Andric   error = Get(root_dir_spec, escaped_hostname.c_str(), module_spec,
306f678e45dSDimitry Andric               cached_module_sp, did_create_ptr);
307f678e45dSDimitry Andric   if (error.Fail())
308f678e45dSDimitry Andric     return error;
309f678e45dSDimitry Andric 
310f678e45dSDimitry Andric   // Fetching a symbol file for the module
311f678e45dSDimitry Andric   const auto tmp_download_sym_file_spec =
312f678e45dSDimitry Andric       JoinPath(module_spec_dir, kTempSymFileName);
313f678e45dSDimitry Andric   error = symfile_downloader(cached_module_sp, tmp_download_sym_file_spec);
314f678e45dSDimitry Andric   llvm::FileRemover tmp_symfile_remover(tmp_download_sym_file_spec.GetPath());
315f678e45dSDimitry Andric   if (error.Fail())
316f678e45dSDimitry Andric     // Failed to download a symfile but fetching the module was successful. The
3174ba319b5SDimitry Andric     // module might contain the necessary symbols and the debugging is also
3184ba319b5SDimitry Andric     // possible without a symfile.
3195517e702SDimitry Andric     return Status();
320f678e45dSDimitry Andric 
321f678e45dSDimitry Andric   error = Put(root_dir_spec, escaped_hostname.c_str(), module_spec,
322f678e45dSDimitry Andric               tmp_download_sym_file_spec,
323f678e45dSDimitry Andric               GetSymbolFileSpec(module_spec.GetFileSpec()));
324f678e45dSDimitry Andric   if (error.Fail())
3255517e702SDimitry Andric     return Status("Failed to put symbol file into cache: %s",
3265517e702SDimitry Andric                   error.AsCString());
327f678e45dSDimitry Andric 
328f678e45dSDimitry Andric   tmp_symfile_remover.releaseFile();
329f678e45dSDimitry Andric 
330f678e45dSDimitry Andric   FileSpec symfile_spec = GetSymbolFileSpec(cached_module_sp->GetFileSpec());
331f678e45dSDimitry Andric   cached_module_sp->SetSymbolFileFileSpec(symfile_spec);
3325517e702SDimitry Andric   return Status();
333f678e45dSDimitry Andric }
334