From b3cfd46356af3416d72bd6593bb2a397e72554b6 Mon Sep 17 00:00:00 2001 From: Glenn Smith Date: Tue, 18 Feb 2025 18:03:06 -0500 Subject: [SharedCache] Fix loading DSC BNDB from a local project crashing Also fixes a BinaryViewRef leak --- view/sharedcache/core/SharedCache.cpp | 15 +++++------- view/sharedcache/core/VM.cpp | 44 ++++++++++++++++++++++++----------- view/sharedcache/core/VM.h | 8 +++---- 3 files changed, 41 insertions(+), 26 deletions(-) (limited to 'view/sharedcache') diff --git a/view/sharedcache/core/SharedCache.cpp b/view/sharedcache/core/SharedCache.cpp index 2980c0e2..e3c115cd 100644 --- a/view/sharedcache/core/SharedCache.cpp +++ b/view/sharedcache/core/SharedCache.cpp @@ -317,19 +317,16 @@ uint64_t SharedCache::FastGetBackingCacheCount(BinaryNinja::RefPath(); auto subCacheCount = header.subCacheArrayCount; return subCacheCount + 1; } case SplitCacheFormat: { - auto mainFileName = baseFile->Path(); auto subCacheCount = header.subCacheArrayCount; return subCacheCount + 2; } case iOS16CacheFormat: { - auto mainFileName = baseFile->Path(); auto subCacheCount = header.subCacheArrayCount; return subCacheCount + 2; } @@ -640,7 +637,7 @@ void SharedCache::PerformInitialLoad(std::lock_guard& lock) subCachePath = path + "." + entry.fileExtension; subCacheFilename = mainFileName + "." + entry.fileExtension; } - auto subCacheFile = MapFileWithoutApplyingSlide(subCachePath); + auto subCacheFile = MapFileWithoutApplyingSlide(ResolveFilePath(m_dscView, subCachePath)); dyld_cache_header subCacheHeader {}; uint64_t headerSize = subCacheFile->ReadUInt32(16); @@ -727,7 +724,7 @@ void SharedCache::PerformInitialLoad(std::lock_guard& lock) { auto subCachePath = path + "." + std::to_string(i); auto subCacheFilename = mainFileName + "." + std::to_string(i); - auto subCacheFile = MapFileWithoutApplyingSlide(subCachePath); + auto subCacheFile = MapFileWithoutApplyingSlide(ResolveFilePath(m_dscView, subCachePath)); dyld_cache_header subCacheHeader {}; uint64_t headerSize = subCacheFile->ReadUInt32(16); @@ -773,7 +770,7 @@ void SharedCache::PerformInitialLoad(std::lock_guard& lock) // Load .symbols subcache try { auto subCachePath = path + ".symbols"; - auto subCacheFile = MapFileWithoutApplyingSlide(subCachePath); + auto subCacheFile = MapFileWithoutApplyingSlide(ResolveFilePath(m_dscView, subCachePath)); dyld_cache_header subCacheHeader {}; uint64_t headerSize = subCacheFile->ReadUInt32(16); @@ -870,7 +867,7 @@ void SharedCache::PerformInitialLoad(std::lock_guard& lock) subCacheFilename = mainFileName + "." + entry.fileExtension; } - auto subCacheFile = MapFileWithoutApplyingSlide(subCachePath); + auto subCacheFile = MapFileWithoutApplyingSlide(ResolveFilePath(m_dscView, subCachePath)); dyld_cache_header subCacheHeader {}; uint64_t headerSize = subCacheFile->ReadUInt32(16); @@ -931,7 +928,7 @@ void SharedCache::PerformInitialLoad(std::lock_guard& lock) try { auto subCachePath = path + ".symbols"; - auto subCacheFile = MapFileWithoutApplyingSlide(subCachePath); + auto subCacheFile = MapFileWithoutApplyingSlide(ResolveFilePath(m_dscView, subCachePath)); dyld_cache_header subCacheHeader {}; uint64_t headerSize = subCacheFile->ReadUInt32(16); if (subCacheFile->ReadUInt32(16) > sizeof(dyld_cache_header)) @@ -3564,7 +3561,7 @@ uint64_t SharedCache::GetObjCRelativeMethodBaseAddress(const VMReader& reader) c std::shared_ptr SharedCache::MapFile(const std::string& path) { uint64_t baseAddress = m_cacheInfo->BaseAddress(); - return MMappedFileAccessor::Open(m_dscView, m_dscView->GetFile()->GetSessionId(), path, + return MMappedFileAccessor::Open(m_dscView->GetFile()->GetSessionId(), path, [baseAddress, logger = m_logger](std::shared_ptr mmap) { ParseAndApplySlideInfoForFile(mmap, baseAddress, logger); }) diff --git a/view/sharedcache/core/VM.cpp b/view/sharedcache/core/VM.cpp index dcc87723..711c2a88 100644 --- a/view/sharedcache/core/VM.cpp +++ b/view/sharedcache/core/VM.cpp @@ -63,6 +63,13 @@ void VMShutdown() {} std::string ResolveFilePath(BinaryNinja::Ref dscView, const std::string& path) { auto dscProjectFile = dscView->GetFile()->GetProjectFile(); + BinaryNinja::LogDebugF( + "ResolveFilePath:\n of: {}\n path: {}\n pfn: {}\n pfp: {}", + dscView->GetFile()->GetOriginalFilename(), + path, + dscProjectFile ? dscProjectFile->GetName() : "", + dscProjectFile ? dscProjectFile->GetPathOnDisk() : "" + ); // If we're not in a project, just return the path we were given if (!dscProjectFile) @@ -73,8 +80,22 @@ std::string ResolveFilePath(BinaryNinja::Ref dscView, c // TODO: do we need to support looking in subfolders? // Replace project file path on disk with project file name for resolution std::string projectFilePathOnDisk = dscProjectFile->GetPathOnDisk(); + std::string originalFilePathOnDisk = dscView->GetFile()->GetOriginalFilename(); std::string cleanPath = path; - cleanPath.replace(cleanPath.find(projectFilePathOnDisk), projectFilePathOnDisk.size(), dscProjectFile->GetName()); + if (auto pindex = cleanPath.find(projectFilePathOnDisk); pindex != std::string::npos) + { + cleanPath.replace(pindex, projectFilePathOnDisk.size(), dscProjectFile->GetName()); + } + else if (auto oindex = cleanPath.find(originalFilePathOnDisk); oindex != std::string::npos) + { + BinaryNinja::Ref originalProjectFile = dscProjectFile->GetProject()->GetFileByPathOnDisk(originalFilePathOnDisk); + if (!originalProjectFile) + { + BinaryNinja::LogErrorF("Failed to resolve file path for {}: original file {} not found", path, originalFilePathOnDisk); + return path; + } + cleanPath.replace(oindex, originalFilePathOnDisk.size(), originalProjectFile->GetName()); + } size_t lastSlashPos = cleanPath.find_last_of("/\\"); std::string fileName; @@ -108,10 +129,7 @@ std::string ResolveFilePath(BinaryNinja::Ref dscView, c } } - if (dscView->GetFile()->GetProjectFile()) - { - BinaryNinja::LogError("Failed to resolve file path for %s", path.c_str()); - } + BinaryNinja::LogErrorF("Failed to resolve file path for {}", path); // If we couldn't find a sibling filename, just return the path we were given return path; @@ -235,7 +253,7 @@ void FileAccessorCache::EvictFromCacheIfNeeded() } } -std::shared_ptr FileAccessorCache::OpenLazily(BinaryNinja::Ref dscView, +std::shared_ptr FileAccessorCache::OpenLazily( const uint64_t sessionID, const std::string& path, std::function)> postAllocationRoutine) { @@ -247,9 +265,9 @@ std::shared_ptr FileAccessorCache::OpenLazily(BinaryNinj } auto accessor = std::make_shared(path, - [=, dscView = std::move(dscView), postAllocationRoutine = std::move(postAllocationRoutine)]( + [=, postAllocationRoutine = std::move(postAllocationRoutine)]( const std::string& path) { - auto accessor = Open(dscView, sessionID, path); + auto accessor = Open(sessionID, path); if (postAllocationRoutine) { postAllocationRoutine(accessor); @@ -262,12 +280,12 @@ std::shared_ptr FileAccessorCache::OpenLazily(BinaryNinj } std::shared_ptr FileAccessorCache::Open( - BinaryNinja::Ref dscView, const uint64_t sessionID, const std::string& path) + const uint64_t sessionID, const std::string& path) { EvictFromCacheIfNeeded(); mmapCount++; - auto accessor = std::shared_ptr(new MMappedFileAccessor(ResolveFilePath(dscView, path)), + auto accessor = std::shared_ptr(new MMappedFileAccessor(path), [this](MMappedFileAccessor* accessor) { Close(accessor); }); std::lock_guard lock(m_mutex); @@ -291,11 +309,11 @@ void FileAccessorCache::Close(MMappedFileAccessor* accessor) delete accessor; } -std::shared_ptr MMappedFileAccessor::Open(BinaryNinja::Ref dscView, +std::shared_ptr MMappedFileAccessor::Open( const uint64_t sessionID, const std::string& path, std::function)> postAllocationRoutine) { - return FileAccessorCache::Shared().OpenLazily(dscView, sessionID, path, std::move(postAllocationRoutine)); + return FileAccessorCache::Shared().OpenLazily(sessionID, path, std::move(postAllocationRoutine)); } void MMappedFileAccessor::InitialVMSetup() @@ -537,7 +555,7 @@ void VM::MapPages(BinaryNinja::Ref dscView, uint64_t se } auto accessor = - MMappedFileAccessor::Open(std::move(dscView), sessionID, filePath, std::move(postAllocationRoutine)); + MMappedFileAccessor::Open(sessionID, ResolveFilePath(dscView, filePath), std::move(postAllocationRoutine)); auto [it, inserted] = m_map.insert_or_assign({vm_address, vm_address + size}, PageMapping(std::move(accessor), fileoff)); if (m_safe && !inserted) { diff --git a/view/sharedcache/core/VM.h b/view/sharedcache/core/VM.h index 44bd5e63..e245751a 100644 --- a/view/sharedcache/core/VM.h +++ b/view/sharedcache/core/VM.h @@ -79,7 +79,7 @@ public: std::string_view filePath() const { return m_filePath; } private: - std::string m_filePath; + std::string m_filePath; }; uint64_t MMapCount(); @@ -93,7 +93,7 @@ public: MMappedFileAccessor(const std::string &path); ~MMappedFileAccessor(); - static std::shared_ptr Open(BinaryNinja::Ref dscView, const uint64_t sessionID, const std::string &path, std::function)> postAllocationRoutine = nullptr); + static std::shared_ptr Open(const uint64_t sessionID, const std::string &path, std::function)> postAllocationRoutine = nullptr); static void CloseAll(const uint64_t sessionID); @@ -163,7 +163,7 @@ class FileAccessorCache public: static FileAccessorCache& Shared(); - std::shared_ptr OpenLazily(BinaryNinja::Ref dscView, + std::shared_ptr OpenLazily( const uint64_t sessionID, const std::string& path, std::function)> postAllocationRoutine); @@ -173,7 +173,7 @@ private: FileAccessorCache(); std::shared_ptr Open( - BinaryNinja::Ref dscView, const uint64_t sessionID, const std::string& path); + const uint64_t sessionID, const std::string& path); void Close(MMappedFileAccessor* accessor); -- cgit v1.3.1