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