diff options
| author | Mark Rowe <mrowe@bdash.net.nz> | 2024-11-24 22:34:40 -0800 |
|---|---|---|
| committer | Mark Rowe <mrowe@bdash.net.nz> | 2025-01-10 11:52:37 -0800 |
| commit | a44b78355031ed429ac07f20a6439f07f9f47d9d (patch) | |
| tree | 88460c41150d37321b4ae63d0a82ad8a5837cb30 /view/sharedcache/core/SharedCache.cpp | |
| parent | 1f0be2385be2c796152e12ffebc229f10e3ffc28 (diff) | |
[SharedCache] Track whether non-image regions are data vs code
`BackingCache` now tracks the `dyld_cache_mapping_info` for its mappings
so it has access to the memory protections for the region. This means it
can avoid marking some regions as containing code when they don't,
reducing the amount of analysis work that has to be done.
Using `dyld_cache_mapping_info` also makes references to mappings easier
to understand due to its named fields vs the nested `std::pair`s that
were previously in use.
Diffstat (limited to 'view/sharedcache/core/SharedCache.cpp')
| -rw-r--r-- | view/sharedcache/core/SharedCache.cpp | 152 |
1 files changed, 80 insertions, 72 deletions
diff --git a/view/sharedcache/core/SharedCache.cpp b/view/sharedcache/core/SharedCache.cpp index b734a6b1..0f61da63 100644 --- a/view/sharedcache/core/SharedCache.cpp +++ b/view/sharedcache/core/SharedCache.cpp @@ -133,6 +133,24 @@ std::string base_name(std::string const& path) return path.substr(path.find_last_of("/\\") + 1); } +BNSegmentFlag SegmentFlagsFromMachOProtections(int initProt, int maxProt) { + + uint32_t flags = 0; + if (initProt & MACHO_VM_PROT_READ) + flags |= SegmentReadable; + if (initProt & MACHO_VM_PROT_WRITE) + flags |= SegmentWritable; + if (initProt & MACHO_VM_PROT_EXECUTE) + flags |= SegmentExecutable; + if (((initProt & MACHO_VM_PROT_WRITE) == 0) && + ((maxProt & MACHO_VM_PROT_WRITE) == 0)) + flags |= SegmentDenyWrite; + if (((initProt & MACHO_VM_PROT_EXECUTE) == 0) && + ((maxProt & MACHO_VM_PROT_EXECUTE) == 0)) + flags |= SegmentDenyExecute; + return (BNSegmentFlag)flags; +} + #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wunused-function" @@ -305,11 +323,7 @@ void SharedCache::PerformInitialLoad() for (size_t i = 0; i < primaryCacheHeader.mappingCount; i++) { baseFile->Read(&mapping, primaryCacheHeader.mappingOffset + (i * sizeof(mapping)), sizeof(mapping)); - std::pair<uint64_t, std::pair<uint64_t, uint64_t>> mapRawToAddrAndSize; - mapRawToAddrAndSize.first = mapping.fileOffset; - mapRawToAddrAndSize.second.first = mapping.address; - mapRawToAddrAndSize.second.second = mapping.size; - cache.mappings.push_back(mapRawToAddrAndSize); + cache.mappings.push_back(mapping); } MutableState().backingCaches.push_back(std::move(cache)); @@ -373,11 +387,7 @@ void SharedCache::PerformInitialLoad() for (size_t i = 0; i < primaryCacheHeader.mappingCount; i++) { baseFile->Read(&mapping, primaryCacheHeader.mappingOffset + (i * sizeof(mapping)), sizeof(mapping)); - std::pair<uint64_t, std::pair<uint64_t, uint64_t>> mapRawToAddrAndSize; - mapRawToAddrAndSize.first = mapping.fileOffset; - mapRawToAddrAndSize.second.first = mapping.address; - mapRawToAddrAndSize.second.second = mapping.size; - cache.mappings.push_back(std::move(mapRawToAddrAndSize)); + cache.mappings.push_back(mapping); } MutableState().backingCaches.push_back(std::move(cache)); @@ -449,11 +459,7 @@ void SharedCache::PerformInitialLoad() { subCacheFile->Read(&subCacheMapping, subCacheHeader.mappingOffset + (j * sizeof(subCacheMapping)), sizeof(subCacheMapping)); - std::pair<uint64_t, std::pair<uint64_t, uint64_t>> mapRawToAddrAndSize; - mapRawToAddrAndSize.first = subCacheMapping.fileOffset; - mapRawToAddrAndSize.second.first = subCacheMapping.address; - mapRawToAddrAndSize.second.second = subCacheMapping.size; - subCache.mappings.push_back(std::move(mapRawToAddrAndSize)); + subCache.mappings.push_back(subCacheMapping); } if (subCacheHeader.mappingCount == 1 && subCacheHeader.imagesCountOld == 0 && subCacheHeader.imagesCount == 0 @@ -485,11 +491,7 @@ void SharedCache::PerformInitialLoad() for (size_t i = 0; i < primaryCacheHeader.mappingCount; i++) { baseFile->Read(&mapping, primaryCacheHeader.mappingOffset + (i * sizeof(mapping)), sizeof(mapping)); - std::pair<uint64_t, std::pair<uint64_t, uint64_t>> mapRawToAddrAndSize; - mapRawToAddrAndSize.first = mapping.fileOffset; - mapRawToAddrAndSize.second.first = mapping.address; - mapRawToAddrAndSize.second.second = mapping.size; - cache.mappings.push_back(std::move(mapRawToAddrAndSize)); + cache.mappings.push_back(mapping); } MutableState().backingCaches.push_back(std::move(cache)); @@ -545,11 +547,7 @@ void SharedCache::PerformInitialLoad() { subCacheFile->Read(&subCacheMapping, subCacheHeader.mappingOffset + (j * sizeof(subCacheMapping)), sizeof(subCacheMapping)); - std::pair<uint64_t, std::pair<uint64_t, uint64_t>> mapRawToAddrAndSize; - mapRawToAddrAndSize.first = subCacheMapping.fileOffset; - mapRawToAddrAndSize.second.first = subCacheMapping.address; - mapRawToAddrAndSize.second.second = subCacheMapping.size; - subCache.mappings.push_back(std::move(mapRawToAddrAndSize)); + subCache.mappings.push_back(subCacheMapping); } MutableState().backingCaches.push_back(std::move(subCache)); @@ -591,11 +589,7 @@ void SharedCache::PerformInitialLoad() { subCacheFile->Read(&subCacheMapping, subCacheHeader.mappingOffset + (j * sizeof(subCacheMapping)), sizeof(subCacheMapping)); - std::pair<uint64_t, std::pair<uint64_t, uint64_t>> mapRawToAddrAndSize; - mapRawToAddrAndSize.first = subCacheMapping.fileOffset; - mapRawToAddrAndSize.second.first = subCacheMapping.address; - mapRawToAddrAndSize.second.second = subCacheMapping.size; - subCache.mappings.push_back(std::move(mapRawToAddrAndSize)); + subCache.mappings.push_back(subCacheMapping); } MutableState().backingCaches.push_back(std::move(subCache)); @@ -612,11 +606,7 @@ void SharedCache::PerformInitialLoad() for (size_t i = 0; i < primaryCacheHeader.mappingCount; i++) { baseFile->Read(&mapping, primaryCacheHeader.mappingOffset + (i * sizeof(mapping)), sizeof(mapping)); - std::pair<uint64_t, std::pair<uint64_t, uint64_t>> mapRawToAddrAndSize; - mapRawToAddrAndSize.first = mapping.fileOffset; - mapRawToAddrAndSize.second.first = mapping.address; - mapRawToAddrAndSize.second.second = mapping.size; - cache.mappings.push_back(std::move(mapRawToAddrAndSize)); + cache.mappings.push_back(mapping); } MutableState().backingCaches.push_back(std::move(cache)); @@ -694,12 +684,7 @@ void SharedCache::PerformInitialLoad() { subCacheFile->Read(&subCacheMapping, subCacheHeader.mappingOffset + (j * sizeof(subCacheMapping)), sizeof(subCacheMapping)); - - std::pair<uint64_t, std::pair<uint64_t, uint64_t>> mapRawToAddrAndSize; - mapRawToAddrAndSize.first = subCacheMapping.fileOffset; - mapRawToAddrAndSize.second.first = subCacheMapping.address; - mapRawToAddrAndSize.second.second = subCacheMapping.size; - subCache.mappings.push_back(std::move(mapRawToAddrAndSize)); + subCache.mappings.push_back(subCacheMapping); if (subCachePath.find(".dylddata") != std::string::npos) { @@ -756,11 +741,7 @@ void SharedCache::PerformInitialLoad() { subCacheFile->Read(&subCacheMapping, subCacheHeader.mappingOffset + (j * sizeof(subCacheMapping)), sizeof(subCacheMapping)); - std::pair<uint64_t, std::pair<uint64_t, uint64_t>> mapRawToAddrAndSize; - mapRawToAddrAndSize.first = subCacheMapping.fileOffset; - mapRawToAddrAndSize.second.first = subCacheMapping.address; - mapRawToAddrAndSize.second.second = subCacheMapping.size; - subCache.mappings.push_back(std::move(mapRawToAddrAndSize)); + subCache.mappings.push_back(subCacheMapping); } MutableState().backingCaches.push_back(std::move(subCache)); @@ -806,19 +787,7 @@ void SharedCache::PerformInitialLoad() sectionRegion.prettyName = imageHeader.value().identifierPrefix + "::" + std::string(segName); sectionRegion.start = segment.vmaddr; sectionRegion.size = segment.vmsize; - uint32_t flags = 0; - if (segment.initprot & MACHO_VM_PROT_READ) - flags |= SegmentReadable; - if (segment.initprot & MACHO_VM_PROT_WRITE) - flags |= SegmentWritable; - if (segment.initprot & MACHO_VM_PROT_EXECUTE) - flags |= SegmentExecutable; - if (((segment.initprot & MACHO_VM_PROT_WRITE) == 0) && - ((segment.maxprot & MACHO_VM_PROT_WRITE) == 0)) - flags |= SegmentDenyWrite; - if (((segment.initprot & MACHO_VM_PROT_EXECUTE) == 0) && - ((segment.maxprot & MACHO_VM_PROT_EXECUTE) == 0)) - flags |= SegmentDenyExecute; + uint32_t flags = SegmentFlagsFromMachOProtections(segment.initprot, segment.maxprot); // if we're positive we have an entry point for some reason, force the segment // executable. this helps with kernel images. @@ -850,11 +819,10 @@ void SharedCache::PerformInitialLoad() for (const auto& mapping : cache.mappings) { MemoryRegion region; - region.start = mapping.second.first; - region.size = mapping.second.second; + region.start = mapping.address; + region.size = mapping.size; region.prettyName = base_name(cache.path) + "::" + std::to_string(i); - // FIXME flags!!! BackingCache.mapping needs refactored to store this information! - region.flags = (BNSegmentFlag)(BNSegmentFlag::SegmentReadable | BNSegmentFlag::SegmentExecutable); + region.flags = SegmentFlagsFromMachOProtections(mapping.initProt, mapping.maxProt); MutableState().nonImageRegions.push_back(std::move(region)); i++; } @@ -998,7 +966,7 @@ std::shared_ptr<VM> SharedCache::GetVMMap(bool mapPages) { for (const auto& mapping : cache.mappings) { - vm->MapPages(m_dscView, m_dscView->GetFile()->GetSessionId(), mapping.second.first, mapping.first, mapping.second.second, cache.path, + vm->MapPages(m_dscView, m_dscView->GetFile()->GetSessionId(), mapping.address, mapping.fileOffset, mapping.size, cache.path, [this, vm=vm](std::shared_ptr<MMappedFileAccessor> mmap){ ParseAndApplySlideInfoForFile(mmap); }); @@ -1065,9 +1033,9 @@ void SharedCache::ParseAndApplySlideInfoForFile(std::shared_ptr<MMappedFileAcces { for (const auto& mapping : backingCache.mappings) { - if (mapping.second.first < base) + if (mapping.address < base) { - base = mapping.second.first; + base = mapping.address; break; } } @@ -1696,7 +1664,7 @@ bool SharedCache::LoadSectionAtAddress(uint64_t address) m_dscView->GetParentView()->WriteBuffer(rawViewEnd, buff); m_dscView->GetParentView()->AddAutoSegment(rawViewEnd, region.size, rawViewEnd, region.size, region.flags); m_dscView->AddUserSegment(region.start, region.size, rawViewEnd, region.size, region.flags); - m_dscView->AddUserSection(name, region.start, region.size, ReadOnlyCodeSectionSemantics); + m_dscView->AddUserSection(name, region.start, region.size, region.flags & SegmentDenyExecute ? ReadOnlyDataSectionSemantics : ReadOnlyCodeSectionSemantics); m_dscView->WriteBuffer(region.start, buff); region.loaded = true; @@ -3298,11 +3266,11 @@ extern "C" mappings = (BNDSCBackingCacheMapping*)malloc(sizeof(BNDSCBackingCacheMapping) * viewCaches[i].mappings.size()); size_t j = 0; - for (const auto& [fileOffset, mapping] : viewCaches[i].mappings) + for (const auto& mapping : viewCaches[i].mappings) { - mappings[j].vmAddress = mapping.first; - mappings[j].size = mapping.second; - mappings[j].fileOffset = fileOffset; + mappings[j].vmAddress = mapping.address; + mappings[j].size = mapping.size; + mappings[j].fileOffset = mapping.fileOffset; j++; } caches[i].mappings = mappings; @@ -3445,6 +3413,34 @@ void InitDSCViewType() namespace SharedCacheCore { +void Serialize(SerializationContext& context, const dyld_cache_mapping_info& value) +{ + context.writer.StartArray(); + Serialize(context, value.address); + Serialize(context, value.size); + Serialize(context, value.fileOffset); + Serialize(context, value.maxProt); + Serialize(context, value.initProt); + context.writer.EndArray(); +} + +void Deserialize(DeserializationContext& context, std::string_view name, std::vector<dyld_cache_mapping_info>& b) +{ + + auto bArr = context.doc[name.data()].GetArray(); + for (auto& s : bArr) + { + dyld_cache_mapping_info mapping; + auto s2 = s.GetArray(); + mapping.address = s2[0].GetUint64(); + mapping.size = s2[1].GetUint64(); + mapping.fileOffset = s2[2].GetUint64(); + mapping.maxProt = s2[3].GetUint(); + mapping.initProt = s2[4].GetUint(); + b.push_back(mapping); + } +} + void SharedCache::Store(SerializationContext& context) const { Serialize(context, "metadataVersion", METADATA_VERSION); @@ -3616,6 +3612,19 @@ void SharedCache::Load(DeserializationContext& context) m_metadataValid = true; } +void BackingCache::Store(SerializationContext& context) const +{ + MSS(path); + MSS(isPrimary); + MSS(mappings); +} +void BackingCache::Load(DeserializationContext& context) +{ + MSL(path); + MSL(isPrimary); + MSL(mappings); +} + #if defined(__GNUC__) || defined(__clang__) __attribute__((always_inline)) void SharedCache::AssertMutable() const #elif defined(_MSC_VER) @@ -3664,5 +3673,4 @@ const std::unordered_map<uint64_t, SharedCacheMachOHeader>& SharedCache::AllImag { return State().headers; } - } // namespace SharedCacheCore |
