Skip to content

Commit a44b783

Browse files
committed
[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.
1 parent 1f0be23 commit a44b783

File tree

2 files changed

+90
-93
lines changed

2 files changed

+90
-93
lines changed

view/sharedcache/core/SharedCache.cpp

Lines changed: 80 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,24 @@ std::string base_name(std::string const& path)
133133
return path.substr(path.find_last_of("/\\") + 1);
134134
}
135135

136+
BNSegmentFlag SegmentFlagsFromMachOProtections(int initProt, int maxProt) {
137+
138+
uint32_t flags = 0;
139+
if (initProt & MACHO_VM_PROT_READ)
140+
flags |= SegmentReadable;
141+
if (initProt & MACHO_VM_PROT_WRITE)
142+
flags |= SegmentWritable;
143+
if (initProt & MACHO_VM_PROT_EXECUTE)
144+
flags |= SegmentExecutable;
145+
if (((initProt & MACHO_VM_PROT_WRITE) == 0) &&
146+
((maxProt & MACHO_VM_PROT_WRITE) == 0))
147+
flags |= SegmentDenyWrite;
148+
if (((initProt & MACHO_VM_PROT_EXECUTE) == 0) &&
149+
((maxProt & MACHO_VM_PROT_EXECUTE) == 0))
150+
flags |= SegmentDenyExecute;
151+
return (BNSegmentFlag)flags;
152+
}
153+
136154

137155
#pragma clang diagnostic push
138156
#pragma clang diagnostic ignored "-Wunused-function"
@@ -305,11 +323,7 @@ void SharedCache::PerformInitialLoad()
305323
for (size_t i = 0; i < primaryCacheHeader.mappingCount; i++)
306324
{
307325
baseFile->Read(&mapping, primaryCacheHeader.mappingOffset + (i * sizeof(mapping)), sizeof(mapping));
308-
std::pair<uint64_t, std::pair<uint64_t, uint64_t>> mapRawToAddrAndSize;
309-
mapRawToAddrAndSize.first = mapping.fileOffset;
310-
mapRawToAddrAndSize.second.first = mapping.address;
311-
mapRawToAddrAndSize.second.second = mapping.size;
312-
cache.mappings.push_back(mapRawToAddrAndSize);
326+
cache.mappings.push_back(mapping);
313327
}
314328
MutableState().backingCaches.push_back(std::move(cache));
315329

@@ -373,11 +387,7 @@ void SharedCache::PerformInitialLoad()
373387
for (size_t i = 0; i < primaryCacheHeader.mappingCount; i++)
374388
{
375389
baseFile->Read(&mapping, primaryCacheHeader.mappingOffset + (i * sizeof(mapping)), sizeof(mapping));
376-
std::pair<uint64_t, std::pair<uint64_t, uint64_t>> mapRawToAddrAndSize;
377-
mapRawToAddrAndSize.first = mapping.fileOffset;
378-
mapRawToAddrAndSize.second.first = mapping.address;
379-
mapRawToAddrAndSize.second.second = mapping.size;
380-
cache.mappings.push_back(std::move(mapRawToAddrAndSize));
390+
cache.mappings.push_back(mapping);
381391
}
382392
MutableState().backingCaches.push_back(std::move(cache));
383393

@@ -449,11 +459,7 @@ void SharedCache::PerformInitialLoad()
449459
{
450460
subCacheFile->Read(&subCacheMapping, subCacheHeader.mappingOffset + (j * sizeof(subCacheMapping)),
451461
sizeof(subCacheMapping));
452-
std::pair<uint64_t, std::pair<uint64_t, uint64_t>> mapRawToAddrAndSize;
453-
mapRawToAddrAndSize.first = subCacheMapping.fileOffset;
454-
mapRawToAddrAndSize.second.first = subCacheMapping.address;
455-
mapRawToAddrAndSize.second.second = subCacheMapping.size;
456-
subCache.mappings.push_back(std::move(mapRawToAddrAndSize));
462+
subCache.mappings.push_back(subCacheMapping);
457463
}
458464

459465
if (subCacheHeader.mappingCount == 1 && subCacheHeader.imagesCountOld == 0 && subCacheHeader.imagesCount == 0
@@ -485,11 +491,7 @@ void SharedCache::PerformInitialLoad()
485491
for (size_t i = 0; i < primaryCacheHeader.mappingCount; i++)
486492
{
487493
baseFile->Read(&mapping, primaryCacheHeader.mappingOffset + (i * sizeof(mapping)), sizeof(mapping));
488-
std::pair<uint64_t, std::pair<uint64_t, uint64_t>> mapRawToAddrAndSize;
489-
mapRawToAddrAndSize.first = mapping.fileOffset;
490-
mapRawToAddrAndSize.second.first = mapping.address;
491-
mapRawToAddrAndSize.second.second = mapping.size;
492-
cache.mappings.push_back(std::move(mapRawToAddrAndSize));
494+
cache.mappings.push_back(mapping);
493495
}
494496
MutableState().backingCaches.push_back(std::move(cache));
495497

@@ -545,11 +547,7 @@ void SharedCache::PerformInitialLoad()
545547
{
546548
subCacheFile->Read(&subCacheMapping, subCacheHeader.mappingOffset + (j * sizeof(subCacheMapping)),
547549
sizeof(subCacheMapping));
548-
std::pair<uint64_t, std::pair<uint64_t, uint64_t>> mapRawToAddrAndSize;
549-
mapRawToAddrAndSize.first = subCacheMapping.fileOffset;
550-
mapRawToAddrAndSize.second.first = subCacheMapping.address;
551-
mapRawToAddrAndSize.second.second = subCacheMapping.size;
552-
subCache.mappings.push_back(std::move(mapRawToAddrAndSize));
550+
subCache.mappings.push_back(subCacheMapping);
553551
}
554552

555553
MutableState().backingCaches.push_back(std::move(subCache));
@@ -591,11 +589,7 @@ void SharedCache::PerformInitialLoad()
591589
{
592590
subCacheFile->Read(&subCacheMapping, subCacheHeader.mappingOffset + (j * sizeof(subCacheMapping)),
593591
sizeof(subCacheMapping));
594-
std::pair<uint64_t, std::pair<uint64_t, uint64_t>> mapRawToAddrAndSize;
595-
mapRawToAddrAndSize.first = subCacheMapping.fileOffset;
596-
mapRawToAddrAndSize.second.first = subCacheMapping.address;
597-
mapRawToAddrAndSize.second.second = subCacheMapping.size;
598-
subCache.mappings.push_back(std::move(mapRawToAddrAndSize));
592+
subCache.mappings.push_back(subCacheMapping);
599593
}
600594

601595
MutableState().backingCaches.push_back(std::move(subCache));
@@ -612,11 +606,7 @@ void SharedCache::PerformInitialLoad()
612606
for (size_t i = 0; i < primaryCacheHeader.mappingCount; i++)
613607
{
614608
baseFile->Read(&mapping, primaryCacheHeader.mappingOffset + (i * sizeof(mapping)), sizeof(mapping));
615-
std::pair<uint64_t, std::pair<uint64_t, uint64_t>> mapRawToAddrAndSize;
616-
mapRawToAddrAndSize.first = mapping.fileOffset;
617-
mapRawToAddrAndSize.second.first = mapping.address;
618-
mapRawToAddrAndSize.second.second = mapping.size;
619-
cache.mappings.push_back(std::move(mapRawToAddrAndSize));
609+
cache.mappings.push_back(mapping);
620610
}
621611

622612
MutableState().backingCaches.push_back(std::move(cache));
@@ -694,12 +684,7 @@ void SharedCache::PerformInitialLoad()
694684
{
695685
subCacheFile->Read(&subCacheMapping, subCacheHeader.mappingOffset + (j * sizeof(subCacheMapping)),
696686
sizeof(subCacheMapping));
697-
698-
std::pair<uint64_t, std::pair<uint64_t, uint64_t>> mapRawToAddrAndSize;
699-
mapRawToAddrAndSize.first = subCacheMapping.fileOffset;
700-
mapRawToAddrAndSize.second.first = subCacheMapping.address;
701-
mapRawToAddrAndSize.second.second = subCacheMapping.size;
702-
subCache.mappings.push_back(std::move(mapRawToAddrAndSize));
687+
subCache.mappings.push_back(subCacheMapping);
703688

704689
if (subCachePath.find(".dylddata") != std::string::npos)
705690
{
@@ -756,11 +741,7 @@ void SharedCache::PerformInitialLoad()
756741
{
757742
subCacheFile->Read(&subCacheMapping, subCacheHeader.mappingOffset + (j * sizeof(subCacheMapping)),
758743
sizeof(subCacheMapping));
759-
std::pair<uint64_t, std::pair<uint64_t, uint64_t>> mapRawToAddrAndSize;
760-
mapRawToAddrAndSize.first = subCacheMapping.fileOffset;
761-
mapRawToAddrAndSize.second.first = subCacheMapping.address;
762-
mapRawToAddrAndSize.second.second = subCacheMapping.size;
763-
subCache.mappings.push_back(std::move(mapRawToAddrAndSize));
744+
subCache.mappings.push_back(subCacheMapping);
764745
}
765746

766747
MutableState().backingCaches.push_back(std::move(subCache));
@@ -806,19 +787,7 @@ void SharedCache::PerformInitialLoad()
806787
sectionRegion.prettyName = imageHeader.value().identifierPrefix + "::" + std::string(segName);
807788
sectionRegion.start = segment.vmaddr;
808789
sectionRegion.size = segment.vmsize;
809-
uint32_t flags = 0;
810-
if (segment.initprot & MACHO_VM_PROT_READ)
811-
flags |= SegmentReadable;
812-
if (segment.initprot & MACHO_VM_PROT_WRITE)
813-
flags |= SegmentWritable;
814-
if (segment.initprot & MACHO_VM_PROT_EXECUTE)
815-
flags |= SegmentExecutable;
816-
if (((segment.initprot & MACHO_VM_PROT_WRITE) == 0) &&
817-
((segment.maxprot & MACHO_VM_PROT_WRITE) == 0))
818-
flags |= SegmentDenyWrite;
819-
if (((segment.initprot & MACHO_VM_PROT_EXECUTE) == 0) &&
820-
((segment.maxprot & MACHO_VM_PROT_EXECUTE) == 0))
821-
flags |= SegmentDenyExecute;
790+
uint32_t flags = SegmentFlagsFromMachOProtections(segment.initprot, segment.maxprot);
822791

823792
// if we're positive we have an entry point for some reason, force the segment
824793
// executable. this helps with kernel images.
@@ -850,11 +819,10 @@ void SharedCache::PerformInitialLoad()
850819
for (const auto& mapping : cache.mappings)
851820
{
852821
MemoryRegion region;
853-
region.start = mapping.second.first;
854-
region.size = mapping.second.second;
822+
region.start = mapping.address;
823+
region.size = mapping.size;
855824
region.prettyName = base_name(cache.path) + "::" + std::to_string(i);
856-
// FIXME flags!!! BackingCache.mapping needs refactored to store this information!
857-
region.flags = (BNSegmentFlag)(BNSegmentFlag::SegmentReadable | BNSegmentFlag::SegmentExecutable);
825+
region.flags = SegmentFlagsFromMachOProtections(mapping.initProt, mapping.maxProt);
858826
MutableState().nonImageRegions.push_back(std::move(region));
859827
i++;
860828
}
@@ -998,7 +966,7 @@ std::shared_ptr<VM> SharedCache::GetVMMap(bool mapPages)
998966
{
999967
for (const auto& mapping : cache.mappings)
1000968
{
1001-
vm->MapPages(m_dscView, m_dscView->GetFile()->GetSessionId(), mapping.second.first, mapping.first, mapping.second.second, cache.path,
969+
vm->MapPages(m_dscView, m_dscView->GetFile()->GetSessionId(), mapping.address, mapping.fileOffset, mapping.size, cache.path,
1002970
[this, vm=vm](std::shared_ptr<MMappedFileAccessor> mmap){
1003971
ParseAndApplySlideInfoForFile(mmap);
1004972
});
@@ -1065,9 +1033,9 @@ void SharedCache::ParseAndApplySlideInfoForFile(std::shared_ptr<MMappedFileAcces
10651033
{
10661034
for (const auto& mapping : backingCache.mappings)
10671035
{
1068-
if (mapping.second.first < base)
1036+
if (mapping.address < base)
10691037
{
1070-
base = mapping.second.first;
1038+
base = mapping.address;
10711039
break;
10721040
}
10731041
}
@@ -1696,7 +1664,7 @@ bool SharedCache::LoadSectionAtAddress(uint64_t address)
16961664
m_dscView->GetParentView()->WriteBuffer(rawViewEnd, buff);
16971665
m_dscView->GetParentView()->AddAutoSegment(rawViewEnd, region.size, rawViewEnd, region.size, region.flags);
16981666
m_dscView->AddUserSegment(region.start, region.size, rawViewEnd, region.size, region.flags);
1699-
m_dscView->AddUserSection(name, region.start, region.size, ReadOnlyCodeSectionSemantics);
1667+
m_dscView->AddUserSection(name, region.start, region.size, region.flags & SegmentDenyExecute ? ReadOnlyDataSectionSemantics : ReadOnlyCodeSectionSemantics);
17001668
m_dscView->WriteBuffer(region.start, buff);
17011669

17021670
region.loaded = true;
@@ -3298,11 +3266,11 @@ extern "C"
32983266
mappings = (BNDSCBackingCacheMapping*)malloc(sizeof(BNDSCBackingCacheMapping) * viewCaches[i].mappings.size());
32993267

33003268
size_t j = 0;
3301-
for (const auto& [fileOffset, mapping] : viewCaches[i].mappings)
3269+
for (const auto& mapping : viewCaches[i].mappings)
33023270
{
3303-
mappings[j].vmAddress = mapping.first;
3304-
mappings[j].size = mapping.second;
3305-
mappings[j].fileOffset = fileOffset;
3271+
mappings[j].vmAddress = mapping.address;
3272+
mappings[j].size = mapping.size;
3273+
mappings[j].fileOffset = mapping.fileOffset;
33063274
j++;
33073275
}
33083276
caches[i].mappings = mappings;
@@ -3445,6 +3413,34 @@ void InitDSCViewType()
34453413

34463414
namespace SharedCacheCore {
34473415

3416+
void Serialize(SerializationContext& context, const dyld_cache_mapping_info& value)
3417+
{
3418+
context.writer.StartArray();
3419+
Serialize(context, value.address);
3420+
Serialize(context, value.size);
3421+
Serialize(context, value.fileOffset);
3422+
Serialize(context, value.maxProt);
3423+
Serialize(context, value.initProt);
3424+
context.writer.EndArray();
3425+
}
3426+
3427+
void Deserialize(DeserializationContext& context, std::string_view name, std::vector<dyld_cache_mapping_info>& b)
3428+
{
3429+
3430+
auto bArr = context.doc[name.data()].GetArray();
3431+
for (auto& s : bArr)
3432+
{
3433+
dyld_cache_mapping_info mapping;
3434+
auto s2 = s.GetArray();
3435+
mapping.address = s2[0].GetUint64();
3436+
mapping.size = s2[1].GetUint64();
3437+
mapping.fileOffset = s2[2].GetUint64();
3438+
mapping.maxProt = s2[3].GetUint();
3439+
mapping.initProt = s2[4].GetUint();
3440+
b.push_back(mapping);
3441+
}
3442+
}
3443+
34483444
void SharedCache::Store(SerializationContext& context) const
34493445
{
34503446
Serialize(context, "metadataVersion", METADATA_VERSION);
@@ -3616,6 +3612,19 @@ void SharedCache::Load(DeserializationContext& context)
36163612
m_metadataValid = true;
36173613
}
36183614

3615+
void BackingCache::Store(SerializationContext& context) const
3616+
{
3617+
MSS(path);
3618+
MSS(isPrimary);
3619+
MSS(mappings);
3620+
}
3621+
void BackingCache::Load(DeserializationContext& context)
3622+
{
3623+
MSL(path);
3624+
MSL(isPrimary);
3625+
MSL(mappings);
3626+
}
3627+
36193628
#if defined(__GNUC__) || defined(__clang__)
36203629
__attribute__((always_inline)) void SharedCache::AssertMutable() const
36213630
#elif defined(_MSC_VER)
@@ -3664,5 +3673,4 @@ const std::unordered_map<uint64_t, SharedCacheMachOHeader>& SharedCache::AllImag
36643673
{
36653674
return State().headers;
36663675
}
3667-
36683676
} // namespace SharedCacheCore

view/sharedcache/core/SharedCache.h

Lines changed: 10 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ namespace SharedCacheCore {
2323
DSCViewStateLoadedWithImages,
2424
};
2525

26-
2726
const std::string SharedCacheMetadataTag = "SHAREDCACHE-SharedCacheData";
2827

2928
struct MemoryRegion : public MetadataSerializable<MemoryRegion>
@@ -91,26 +90,6 @@ namespace SharedCacheCore {
9190
}
9291
};
9392

94-
struct BackingCache : public MetadataSerializable<BackingCache>
95-
{
96-
std::string path;
97-
bool isPrimary = false;
98-
std::vector<std::pair<uint64_t, std::pair<uint64_t, uint64_t>>> mappings;
99-
100-
void Store(SerializationContext& context) const
101-
{
102-
MSS(path);
103-
MSS(isPrimary);
104-
MSS(mappings);
105-
}
106-
void Load(DeserializationContext& context)
107-
{
108-
MSL(path);
109-
MSL(isPrimary);
110-
MSL(mappings);
111-
}
112-
};
113-
11493
#if defined(__GNUC__) || defined(__clang__)
11594
#define PACKED_STRUCT __attribute__((packed))
11695
#else
@@ -132,6 +111,16 @@ namespace SharedCacheCore {
132111
uint32_t initProt;
133112
};
134113

114+
struct BackingCache : public MetadataSerializable<BackingCache>
115+
{
116+
std::string path;
117+
bool isPrimary = false;
118+
std::vector<dyld_cache_mapping_info> mappings;
119+
120+
void Store(SerializationContext& context) const;
121+
void Load(DeserializationContext& context);
122+
};
123+
135124
struct LoadedMapping
136125
{
137126
std::shared_ptr<MMappedFileAccessor> backingFile;

0 commit comments

Comments
 (0)