Skip to content

Commit b3cfd46

Browse files
committed
[SharedCache] Fix loading DSC BNDB from a local project crashing
Also fixes a BinaryViewRef leak
1 parent 4bda0ac commit b3cfd46

File tree

3 files changed

+41
-26
lines changed

3 files changed

+41
-26
lines changed

view/sharedcache/core/SharedCache.cpp

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -317,19 +317,16 @@ uint64_t SharedCache::FastGetBackingCacheCount(BinaryNinja::Ref<BinaryNinja::Bin
317317
}
318318
case LargeCacheFormat:
319319
{
320-
auto mainFileName = baseFile->Path();
321320
auto subCacheCount = header.subCacheArrayCount;
322321
return subCacheCount + 1;
323322
}
324323
case SplitCacheFormat:
325324
{
326-
auto mainFileName = baseFile->Path();
327325
auto subCacheCount = header.subCacheArrayCount;
328326
return subCacheCount + 2;
329327
}
330328
case iOS16CacheFormat:
331329
{
332-
auto mainFileName = baseFile->Path();
333330
auto subCacheCount = header.subCacheArrayCount;
334331
return subCacheCount + 2;
335332
}
@@ -640,7 +637,7 @@ void SharedCache::PerformInitialLoad(std::lock_guard<std::mutex>& lock)
640637
subCachePath = path + "." + entry.fileExtension;
641638
subCacheFilename = mainFileName + "." + entry.fileExtension;
642639
}
643-
auto subCacheFile = MapFileWithoutApplyingSlide(subCachePath);
640+
auto subCacheFile = MapFileWithoutApplyingSlide(ResolveFilePath(m_dscView, subCachePath));
644641

645642
dyld_cache_header subCacheHeader {};
646643
uint64_t headerSize = subCacheFile->ReadUInt32(16);
@@ -727,7 +724,7 @@ void SharedCache::PerformInitialLoad(std::lock_guard<std::mutex>& lock)
727724
{
728725
auto subCachePath = path + "." + std::to_string(i);
729726
auto subCacheFilename = mainFileName + "." + std::to_string(i);
730-
auto subCacheFile = MapFileWithoutApplyingSlide(subCachePath);
727+
auto subCacheFile = MapFileWithoutApplyingSlide(ResolveFilePath(m_dscView, subCachePath));
731728

732729
dyld_cache_header subCacheHeader {};
733730
uint64_t headerSize = subCacheFile->ReadUInt32(16);
@@ -773,7 +770,7 @@ void SharedCache::PerformInitialLoad(std::lock_guard<std::mutex>& lock)
773770
// Load .symbols subcache
774771
try {
775772
auto subCachePath = path + ".symbols";
776-
auto subCacheFile = MapFileWithoutApplyingSlide(subCachePath);
773+
auto subCacheFile = MapFileWithoutApplyingSlide(ResolveFilePath(m_dscView, subCachePath));
777774

778775
dyld_cache_header subCacheHeader {};
779776
uint64_t headerSize = subCacheFile->ReadUInt32(16);
@@ -870,7 +867,7 @@ void SharedCache::PerformInitialLoad(std::lock_guard<std::mutex>& lock)
870867
subCacheFilename = mainFileName + "." + entry.fileExtension;
871868
}
872869

873-
auto subCacheFile = MapFileWithoutApplyingSlide(subCachePath);
870+
auto subCacheFile = MapFileWithoutApplyingSlide(ResolveFilePath(m_dscView, subCachePath));
874871

875872
dyld_cache_header subCacheHeader {};
876873
uint64_t headerSize = subCacheFile->ReadUInt32(16);
@@ -931,7 +928,7 @@ void SharedCache::PerformInitialLoad(std::lock_guard<std::mutex>& lock)
931928
try
932929
{
933930
auto subCachePath = path + ".symbols";
934-
auto subCacheFile = MapFileWithoutApplyingSlide(subCachePath);
931+
auto subCacheFile = MapFileWithoutApplyingSlide(ResolveFilePath(m_dscView, subCachePath));
935932
dyld_cache_header subCacheHeader {};
936933
uint64_t headerSize = subCacheFile->ReadUInt32(16);
937934
if (subCacheFile->ReadUInt32(16) > sizeof(dyld_cache_header))
@@ -3564,7 +3561,7 @@ uint64_t SharedCache::GetObjCRelativeMethodBaseAddress(const VMReader& reader) c
35643561
std::shared_ptr<MMappedFileAccessor> SharedCache::MapFile(const std::string& path)
35653562
{
35663563
uint64_t baseAddress = m_cacheInfo->BaseAddress();
3567-
return MMappedFileAccessor::Open(m_dscView, m_dscView->GetFile()->GetSessionId(), path,
3564+
return MMappedFileAccessor::Open(m_dscView->GetFile()->GetSessionId(), path,
35683565
[baseAddress, logger = m_logger](std::shared_ptr<MMappedFileAccessor> mmap) {
35693566
ParseAndApplySlideInfoForFile(mmap, baseAddress, logger);
35703567
})

view/sharedcache/core/VM.cpp

Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,13 @@ void VMShutdown() {}
6363
std::string ResolveFilePath(BinaryNinja::Ref<BinaryNinja::BinaryView> dscView, const std::string& path)
6464
{
6565
auto dscProjectFile = dscView->GetFile()->GetProjectFile();
66+
BinaryNinja::LogDebugF(
67+
"ResolveFilePath:\n of: {}\n path: {}\n pfn: {}\n pfp: {}",
68+
dscView->GetFile()->GetOriginalFilename(),
69+
path,
70+
dscProjectFile ? dscProjectFile->GetName() : "",
71+
dscProjectFile ? dscProjectFile->GetPathOnDisk() : ""
72+
);
6673

6774
// If we're not in a project, just return the path we were given
6875
if (!dscProjectFile)
@@ -73,8 +80,22 @@ std::string ResolveFilePath(BinaryNinja::Ref<BinaryNinja::BinaryView> dscView, c
7380
// TODO: do we need to support looking in subfolders?
7481
// Replace project file path on disk with project file name for resolution
7582
std::string projectFilePathOnDisk = dscProjectFile->GetPathOnDisk();
83+
std::string originalFilePathOnDisk = dscView->GetFile()->GetOriginalFilename();
7684
std::string cleanPath = path;
77-
cleanPath.replace(cleanPath.find(projectFilePathOnDisk), projectFilePathOnDisk.size(), dscProjectFile->GetName());
85+
if (auto pindex = cleanPath.find(projectFilePathOnDisk); pindex != std::string::npos)
86+
{
87+
cleanPath.replace(pindex, projectFilePathOnDisk.size(), dscProjectFile->GetName());
88+
}
89+
else if (auto oindex = cleanPath.find(originalFilePathOnDisk); oindex != std::string::npos)
90+
{
91+
BinaryNinja::Ref<BinaryNinja::ProjectFile> originalProjectFile = dscProjectFile->GetProject()->GetFileByPathOnDisk(originalFilePathOnDisk);
92+
if (!originalProjectFile)
93+
{
94+
BinaryNinja::LogErrorF("Failed to resolve file path for {}: original file {} not found", path, originalFilePathOnDisk);
95+
return path;
96+
}
97+
cleanPath.replace(oindex, originalFilePathOnDisk.size(), originalProjectFile->GetName());
98+
}
7899

79100
size_t lastSlashPos = cleanPath.find_last_of("/\\");
80101
std::string fileName;
@@ -108,10 +129,7 @@ std::string ResolveFilePath(BinaryNinja::Ref<BinaryNinja::BinaryView> dscView, c
108129
}
109130
}
110131

111-
if (dscView->GetFile()->GetProjectFile())
112-
{
113-
BinaryNinja::LogError("Failed to resolve file path for %s", path.c_str());
114-
}
132+
BinaryNinja::LogErrorF("Failed to resolve file path for {}", path);
115133

116134
// If we couldn't find a sibling filename, just return the path we were given
117135
return path;
@@ -235,7 +253,7 @@ void FileAccessorCache::EvictFromCacheIfNeeded()
235253
}
236254
}
237255

238-
std::shared_ptr<LazyMappedFileAccessor> FileAccessorCache::OpenLazily(BinaryNinja::Ref<BinaryNinja::BinaryView> dscView,
256+
std::shared_ptr<LazyMappedFileAccessor> FileAccessorCache::OpenLazily(
239257
const uint64_t sessionID, const std::string& path,
240258
std::function<void(std::shared_ptr<MMappedFileAccessor>)> postAllocationRoutine)
241259
{
@@ -247,9 +265,9 @@ std::shared_ptr<LazyMappedFileAccessor> FileAccessorCache::OpenLazily(BinaryNinj
247265
}
248266

249267
auto accessor = std::make_shared<LazyMappedFileAccessor>(path,
250-
[=, dscView = std::move(dscView), postAllocationRoutine = std::move(postAllocationRoutine)](
268+
[=, postAllocationRoutine = std::move(postAllocationRoutine)](
251269
const std::string& path) {
252-
auto accessor = Open(dscView, sessionID, path);
270+
auto accessor = Open(sessionID, path);
253271
if (postAllocationRoutine)
254272
{
255273
postAllocationRoutine(accessor);
@@ -262,12 +280,12 @@ std::shared_ptr<LazyMappedFileAccessor> FileAccessorCache::OpenLazily(BinaryNinj
262280
}
263281

264282
std::shared_ptr<MMappedFileAccessor> FileAccessorCache::Open(
265-
BinaryNinja::Ref<BinaryNinja::BinaryView> dscView, const uint64_t sessionID, const std::string& path)
283+
const uint64_t sessionID, const std::string& path)
266284
{
267285
EvictFromCacheIfNeeded();
268286

269287
mmapCount++;
270-
auto accessor = std::shared_ptr<MMappedFileAccessor>(new MMappedFileAccessor(ResolveFilePath(dscView, path)),
288+
auto accessor = std::shared_ptr<MMappedFileAccessor>(new MMappedFileAccessor(path),
271289
[this](MMappedFileAccessor* accessor) { Close(accessor); });
272290

273291
std::lock_guard lock(m_mutex);
@@ -291,11 +309,11 @@ void FileAccessorCache::Close(MMappedFileAccessor* accessor)
291309
delete accessor;
292310
}
293311

294-
std::shared_ptr<LazyMappedFileAccessor> MMappedFileAccessor::Open(BinaryNinja::Ref<BinaryNinja::BinaryView> dscView,
312+
std::shared_ptr<LazyMappedFileAccessor> MMappedFileAccessor::Open(
295313
const uint64_t sessionID, const std::string& path,
296314
std::function<void(std::shared_ptr<MMappedFileAccessor>)> postAllocationRoutine)
297315
{
298-
return FileAccessorCache::Shared().OpenLazily(dscView, sessionID, path, std::move(postAllocationRoutine));
316+
return FileAccessorCache::Shared().OpenLazily(sessionID, path, std::move(postAllocationRoutine));
299317
}
300318

301319
void MMappedFileAccessor::InitialVMSetup()
@@ -537,7 +555,7 @@ void VM::MapPages(BinaryNinja::Ref<BinaryNinja::BinaryView> dscView, uint64_t se
537555
}
538556

539557
auto accessor =
540-
MMappedFileAccessor::Open(std::move(dscView), sessionID, filePath, std::move(postAllocationRoutine));
558+
MMappedFileAccessor::Open(sessionID, ResolveFilePath(dscView, filePath), std::move(postAllocationRoutine));
541559
auto [it, inserted] = m_map.insert_or_assign({vm_address, vm_address + size}, PageMapping(std::move(accessor), fileoff));
542560
if (m_safe && !inserted)
543561
{

view/sharedcache/core/VM.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ class LazyMappedFileAccessor : public SelfAllocatingWeakPtr<MMappedFileAccessor>
7979
std::string_view filePath() const { return m_filePath; }
8080

8181
private:
82-
std::string m_filePath;
82+
std::string m_filePath;
8383
};
8484

8585
uint64_t MMapCount();
@@ -93,7 +93,7 @@ class MMappedFileAccessor {
9393
MMappedFileAccessor(const std::string &path);
9494
~MMappedFileAccessor();
9595

96-
static std::shared_ptr<LazyMappedFileAccessor> Open(BinaryNinja::Ref<BinaryNinja::BinaryView> dscView, const uint64_t sessionID, const std::string &path, std::function<void(std::shared_ptr<MMappedFileAccessor>)> postAllocationRoutine = nullptr);
96+
static std::shared_ptr<LazyMappedFileAccessor> Open(const uint64_t sessionID, const std::string &path, std::function<void(std::shared_ptr<MMappedFileAccessor>)> postAllocationRoutine = nullptr);
9797

9898
static void CloseAll(const uint64_t sessionID);
9999

@@ -163,7 +163,7 @@ class FileAccessorCache
163163
public:
164164
static FileAccessorCache& Shared();
165165

166-
std::shared_ptr<LazyMappedFileAccessor> OpenLazily(BinaryNinja::Ref<BinaryNinja::BinaryView> dscView,
166+
std::shared_ptr<LazyMappedFileAccessor> OpenLazily(
167167
const uint64_t sessionID, const std::string& path,
168168
std::function<void(std::shared_ptr<MMappedFileAccessor>)> postAllocationRoutine);
169169

@@ -173,7 +173,7 @@ class FileAccessorCache
173173
FileAccessorCache();
174174

175175
std::shared_ptr<MMappedFileAccessor> Open(
176-
BinaryNinja::Ref<BinaryNinja::BinaryView> dscView, const uint64_t sessionID, const std::string& path);
176+
const uint64_t sessionID, const std::string& path);
177177

178178
void Close(MMappedFileAccessor* accessor);
179179

0 commit comments

Comments
 (0)