summaryrefslogtreecommitdiff
path: root/view/sharedcache/core/SharedCache.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'view/sharedcache/core/SharedCache.cpp')
-rw-r--r--view/sharedcache/core/SharedCache.cpp69
1 files changed, 19 insertions, 50 deletions
diff --git a/view/sharedcache/core/SharedCache.cpp b/view/sharedcache/core/SharedCache.cpp
index 09093ba5..f9761968 100644
--- a/view/sharedcache/core/SharedCache.cpp
+++ b/view/sharedcache/core/SharedCache.cpp
@@ -33,7 +33,8 @@ std::vector<std::string> CacheImage::GetDependencies() const
}
CacheEntry::CacheEntry(std::string filePath, std::string fileName, CacheEntryType type, dyld_cache_header header,
- std::vector<dyld_cache_mapping_info>&& mappings, std::vector<std::pair<std::string, dyld_cache_image_info>>&& images)
+ std::vector<dyld_cache_mapping_info> mappings, std::vector<std::pair<std::string, dyld_cache_image_info>> images,
+ std::shared_ptr<MappedFileRegion> file)
{
m_filePath = std::move(filePath);
m_fileName = std::move(fileName);
@@ -41,21 +42,24 @@ CacheEntry::CacheEntry(std::string filePath, std::string fileName, CacheEntryTyp
m_header = header;
m_mappings = std::move(mappings);
m_images = std::move(images);
+ m_file = std::move(file);
}
CacheEntry CacheEntry::FromFile(const std::string& filePath, const std::string& fileName, CacheEntryType type)
{
- auto file = FileAccessorCache::Global().Open(filePath).lock();
+ auto file = MappedFileRegion::Open(filePath);
+ if (!file)
+ throw std::runtime_error(fmt::format("Failed to open cache file: '{}'", filePath));
// TODO: Pull this out into another function so we can do IsValidDSCFile or something.
// We first want to make sure that the base file is dyld.
// All entries must start with "dyld".
+ if (file->Length() < 4)
+ throw std::runtime_error(fmt::format("File too small to be a shared cache: '{}'", filePath));
DataBuffer sig = file->ReadBuffer(0, 4);
- if (sig.GetLength() != 4)
- throw std::runtime_error("File is empty!");
const char* magic = static_cast<char*>(sig.GetData());
if (strncmp(magic, "dyld", 4) != 0)
- throw std::runtime_error("File does not start with `dyld`!");
+ throw std::runtime_error(fmt::format("File does not start with 'dyld': '{}'", filePath));
// Read the header, this _should_ be compatible with all known DSC formats.
// Mason: the above is not true! https://github.com/Vector35/binaryninja-api/issues/6073
@@ -74,7 +78,7 @@ CacheEntry CacheEntry::FromFile(const std::string& filePath, const std::string&
// Cancel adding the entry if we have an invalid mapping.
if (currentMapping.fileOffset + currentMapping.size > file->Length())
- throw std::runtime_error("Invalid mapping in shared cache entry");
+ throw std::runtime_error(fmt::format("Invalid mapping in shared cache entry: '{}'", filePath));
// TODO: Check initProt to make sure its in the range of expected values.
@@ -139,12 +143,7 @@ CacheEntry CacheEntry::FromFile(const std::string& filePath, const std::string&
images.emplace_back(imageName, branchIslandImg);
}
- return {filePath, fileName, type, header, std::move(mappings), std::move(images)};
-}
-
-WeakFileAccessor CacheEntry::GetAccessor() const
-{
- return FileAccessorCache::Global().Open(m_filePath);
+ return CacheEntry{filePath, fileName, type, header, std::move(mappings), std::move(images), std::move(file)};
}
std::optional<uint64_t> CacheEntry::GetHeaderAddress() const
@@ -226,8 +225,7 @@ void SharedCache::AddSymbols(std::vector<CacheSymbol>&& symbols)
void SharedCache::AddEntry(CacheEntry entry)
{
- // Get the file accessor to associate with the virtual memory region.
- auto fileAccessor = FileAccessorCache::Global().Open(entry.GetFilePath());
+ const auto& file = entry.GetFile();
if (entry.GetType() == CacheEntryType::Symbols)
{
@@ -236,7 +234,7 @@ void SharedCache::AddEntry(CacheEntry entry)
// This is necessary due to code that processes symbols being written in terms of a `VirtualMemory`
// rather than something more generic.
m_localSymbolsVM = std::make_shared<VirtualMemory>(m_vm->GetAddressSize());
- m_localSymbolsVM->MapRegion(fileAccessor, {0, fileAccessor.lock()->Length()}, 0);
+ m_localSymbolsVM->MapRegion(m_localSymbolsEntry->GetFile(), {0, m_localSymbolsEntry->GetFile()->Length()}, 0);
return;
}
@@ -245,7 +243,7 @@ void SharedCache::AddEntry(CacheEntry entry)
const auto& mappings = entry.GetMappings();
for (const auto& mapping : mappings)
{
- m_vm->MapRegion(fileAccessor, {mapping.address, mapping.address + mapping.size}, mapping.fileOffset);
+ m_vm->MapRegion(file, {mapping.address, mapping.address + mapping.size}, mapping.fileOffset);
// Recalculate the base address.
if (mapping.address < m_baseAddress || m_baseAddress == 0)
@@ -421,40 +419,11 @@ void SharedCache::ProcessEntryRegions(const CacheEntry& entry)
void SharedCache::ProcessEntrySlideInfo(const CacheEntry& entry) const
{
- auto slideInfoProcessor = SlideInfoProcessor(GetBaseAddress());
-
- // This will be set for every associated `VirtualMemoryRegion` so that any accesses though the VM will be always be slid.
- // NOTE: This MUST be called on the CacheEntry object owned by SharedCache, otherwise persistence through the `SharedCacheController` will not occur.
- // NOTE: This will keep a copy of a processor in the `WeakFileAccessor` until that object is destroyed (likely view destruction).
- // NOTE: This will keep a copy of the cache entry in the `WeakFileAccessor` until that object is destroyed (likely view destruction).
- auto reviveCallback = [slideInfoProcessor, entry](MappedFileAccessor& revivedAccessor) {
- slideInfoProcessor.ProcessEntry(revivedAccessor, entry);
- };
-
- // Use the current entry accessor, don't register the callback for this one as we want calls through the VM to be slid only.
- // Actually process the slide info for this entry, everything else besides this is to support revived file accessors.
- auto slideMappings = slideInfoProcessor.ProcessEntry(*entry.GetAccessor().lock(), entry);
-
- // Register the revive callback for all virtual memory regions that have been slid.
- // The reason we don't just set this on the entry accessor is that accessor is not consulted for anything really after
- // this point, everything else will be going through the virtual memory, and because the callback is on the weak accessor
- // reference and not the file accessor cache itself this matters.
- auto vm = GetVirtualMemory();
- for (const auto& mapping : slideMappings)
- {
- // Because the mapping address is a file offset for us to consult the virtual memory we must first call `GetMappedAddress`.
- if (auto mappedMappingAddr = entry.GetMappedAddress(mapping.address))
- {
- if (auto vmRegion = vm->GetRegionAtAddress(*mappedMappingAddr))
- {
- // Ok we have the virtual memory region, lets register the callback on its accessor.
- vmRegion->fileAccessor.RegisterReviveCallback(reviveCallback);
- continue;
- }
- }
-
- LogWarnF("Failed to register revive callback for slide mapping {:#x} in entry {:?}", mapping.address, entry.GetFileName().c_str());
- }
+ const auto& file = entry.GetFile();
+ file->SlideOnce([&] {
+ SlideInfoProcessor processor(GetBaseAddress());
+ processor.ProcessEntry(*file, entry);
+ });
}
void SharedCache::ProcessSymbols()