summaryrefslogtreecommitdiff
path: root/view/sharedcache/core/SharedCache.cpp
diff options
context:
space:
mode:
authorMark Rowe <mrowe@bdash.net.nz>2024-11-24 22:34:40 -0800
committerMark Rowe <mrowe@bdash.net.nz>2025-01-10 11:52:37 -0800
commita44b78355031ed429ac07f20a6439f07f9f47d9d (patch)
tree88460c41150d37321b4ae63d0a82ad8a5837cb30 /view/sharedcache/core/SharedCache.cpp
parent1f0be2385be2c796152e12ffebc229f10e3ffc28 (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.cpp152
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