Loading...
--- dyld/dyld-1340/common/ProcessAtlas.cpp
+++ dyld/dyld-1165.3/common/ProcessAtlas.cpp
@@ -26,7 +26,6 @@
#if !TARGET_OS_EXCLAVEKIT
-#include <span>
#include <atomic>
#include <cstring>
#include <Block.h>
@@ -50,27 +49,24 @@
#include "dyld_process_info_internal.h" // For dyld_all_image_infos_{32,64}
#include "Defines.h"
-#include "Header.h"
#include "DyldSharedCache.h"
+#include "MachOFile.h"
#include "PVLEInt64.h"
+#include "MachOFile.h"
#include "MachOLoaded.h"
#include "ProcessAtlas.h"
-#include "Utilities.h"
-#include "SafeVMPrimitives.h"
+#include "Utils.h"
#include "CRC32c.h"
#include "UUID.h"
-#include "Bitmap.h"
using lsl::CRC32c;
using lsl::Allocator;
using lsl::emitPVLEUInt64;
using lsl::readPVLEUInt64;
-using lsl::Bitmap;
using dyld3::FatFile;
-
-using mach_o::Header;
+using dyld3::MachOFile;
// TODO: forEach shared cache needs to filter out subcaches and skip them
// The allocations made by a snapshot need to last for the life of a spanshot. In libdyld that is under the caller control
@@ -80,10 +76,8 @@
#if BUILDING_DYLD
#define _transactionalAllocator _ephemeralAllocator
#else
-#define _transactionalAllocator MemoryManager::memoryManager().defaultAllocator()
+#define _transactionalAllocator Allocator::defaultAllocator()
#endif
-
-#define BLEND_KERN_RETURN_LOCATION(kr, loc) (kr) = ((kr & 0x00ffffff) | loc<<24);
namespace {
static const size_t kCachePeekSize = 0x4000;
@@ -102,7 +96,7 @@
static void getCacheInfo(const dyld_cache_header *cache, uint64_t &headerSize, bool& splitCache) {
// If we have sub caches, then the cache header itself tells us how much space we need to cover all caches
- if ( cache->mappingOffset >= offsetof(dyld_cache_header, subCacheArrayCount) ) {
+ if ( cache->mappingOffset >= __offsetof(dyld_cache_header, subCacheArrayCount) ) {
// New style cache
headerSize = cache->subCacheArrayOffset + (sizeof(dyld_subcache_entry)*cache->subCacheArrayCount);
splitCache = true;
@@ -127,6 +121,56 @@
namespace dyld4 {
namespace Atlas {
+
+Bitmap::Bitmap(Allocator& allocator, size_t size)
+ : _size(size), _bitmap(UniquePtr<std::byte>((std::byte*)allocator.malloc((size+7)/8))) {}
+
+Bitmap::Bitmap(Allocator& allocator, std::span<std::byte>& data) {
+ _size = (size_t)readPVLEUInt64(data);
+ const size_t byteSize = (_size+7)/8;
+ _bitmap = UniquePtr<std::byte>((std::byte*)allocator.malloc(byteSize));
+ _bitmap.withUnsafe([&](std::byte* bitmap) {
+ std::copy(&data[0], &data[byteSize], &bitmap[0]);
+ });
+ data = data.last(data.size()-byteSize);
+}
+
+Bitmap::Bitmap(Bitmap&& other) {
+ swap(other);
+}
+
+Bitmap& Bitmap::operator=(Bitmap&& other) {
+ swap(other);
+ return *this;
+}
+
+void Bitmap::setBit(size_t bit) {
+ contract(bit < _size);
+ _bitmap.withUnsafe([&](std::byte* bitmap) {
+ std::byte* byte = &bitmap[bit/8];
+ (*byte) |= (std::byte)(1<<(bit%8));
+ });
+}
+
+void Bitmap::emit(Vector<std::byte>& data) const {
+ emitPVLEUInt64(_size, data);
+ const size_t byteSize = (_size+7)/8;
+ _bitmap.withUnsafe([&](std::byte* bitmap) {
+ std::copy(&bitmap[0], &bitmap[byteSize], std::back_inserter(data));
+ });
+}
+
+size_t Bitmap::size() const {
+ return _size;
+}
+
+bool Bitmap::checkBit(size_t bit) const {
+ contract(bit < _size);
+ return ((std::byte)0 != _bitmap.withUnsafe([&](std::byte* bitmap) {
+ std::byte* byte = &bitmap[bit/8];
+ return ((*byte) & (std::byte)(1<<(bit%8)));
+ }));
+}
#pragma mark -
#pragma mark Mappers
@@ -165,7 +209,7 @@
#endif
}
-SharedPtr<Mapper> Mapper::mapperForSharedCache(Allocator& _ephemeralAllocator, FileRecord& file, SafePointer baseAddress) {
+SharedPtr<Mapper> Mapper::mapperForSharedCache(Allocator& _ephemeralAllocator, FileRecord& file, const void* baseAddress) {
bool useLocalCache = false;
size_t length = 0;
uint64_t slide = 0;
@@ -203,7 +247,7 @@
}
if (!baseAddress) {
// No base address passed in, treat as unslid
- baseAddress = onDiskCacheHeader->sharedRegionStart;
+ baseAddress = (void*)onDiskCacheHeader->sharedRegionStart;
}
slide = (uint64_t)baseAddress-(uint64_t)onDiskCacheHeader->sharedRegionStart;
uint64_t headerSize = 0;
@@ -251,7 +295,7 @@
auto subCaches = (dyld_subcache_entry*)&onDiskHeaderBytes[onDiskCacheHeader->subCacheArrayOffset];
for (auto i = 0; i < onDiskCacheHeader->subCacheArrayCount; ++i) {
char subCachePath[PATH_MAX];
- if (onDiskCacheHeader->mappingOffset <= offsetof(dyld_cache_header, cacheSubType)) {
+ if (onDiskCacheHeader->mappingOffset <= __offsetof(dyld_cache_header, cacheSubType)) {
snprintf(&subCachePath[0], sizeof(subCachePath), "%s.%u", file.getPath(), i+1);
} else {
char basePath[PATH_MAX];
@@ -277,7 +321,7 @@
auto onDiskSubcacheUUID = UUID(subCache->uuid);
uint8_t uuidBuf[16];
- if (onDiskCacheHeader->mappingOffset <= offsetof(dyld_cache_header, cacheSubType)) {
+ if (onDiskCacheHeader->mappingOffset <= __offsetof(dyld_cache_header, cacheSubType)) {
auto subCacheArray = (dyld_subcache_entry_v1*)&onDiskHeaderBytes[onDiskCacheHeader->subCacheArrayOffset];
memcpy(uuidBuf, subCacheArray[i].uuid, 16);
} else {
@@ -361,7 +405,7 @@
return { _transactionalAllocator.makeShared<Mapper>(_transactionalAllocator, mappings), baseAddress };
}
-SharedPtr<Mapper> Mapper::mapperForMachO(Allocator& _ephemeralAllocator, FileRecord& file, const UUID& uuid, const SafePointer baseAddress) {
+SharedPtr<Mapper> Mapper::mapperForMachO(Allocator& _ephemeralAllocator, FileRecord& file, const UUID& uuid, const void* baseAddress) {
const char* filePath = file.getPath();
// open filePath
int fd = dyld3::open(filePath, O_RDONLY, 0);
@@ -377,21 +421,21 @@
}
// mmap whole file temporarily
- void* tempMapping = ::mmap(nullptr, (size_t)sb.st_size, PROT_READ, MAP_FILE | MAP_PRIVATE | MAP_RESILIENT_CODESIGN, fd, 0);
+ void* tempMapping = ::mmap(nullptr, (size_t)sb.st_size, PROT_READ, MAP_FILE | MAP_PRIVATE, fd, 0);
if ( tempMapping == MAP_FAILED ) {
::close(fd);
return nullptr;
}
// if fat file, pick matching slice
- __block const Header* mf = nullptr;
+ __block const MachOFile* mf = nullptr;
const FatFile* ff = FatFile::isFatFile(tempMapping);
__block uint64_t fileOffset = 0;
if (ff) {
uint64_t fileLength = sb.st_size;
Diagnostics diag;
ff->forEachSlice(diag, fileLength, ^(uint32_t sliceCpuType, uint32_t sliceCpuSubType, const void *sliceStart, uint64_t sliceSize, bool &stop) {
- auto slice = (Header*)sliceStart;
+ auto slice = (MachOFile*)sliceStart;
uuid_t sliceUUIDRaw;
slice->getUuid(sliceUUIDRaw);
auto sliceUUID = UUID(sliceUUIDRaw);
@@ -405,7 +449,7 @@
diag.clearError();
}
if (!mf) {
- auto slice = Header::isMachO({(uint8_t*)tempMapping, (size_t)sb.st_size});
+ auto slice = MachOFile::isMachO(tempMapping);
if (slice) {
uuid_t sliceUUID;
slice->getUuid(sliceUUID);
@@ -421,16 +465,16 @@
}
__block Vector<Mapper::Mapping> mappings(_transactionalAllocator);
__block uint64_t slide = 0;
- mf->forEachSegment(^(const Header::SegmentInfo &info, bool &stop) {
- if ( info.segmentName == "__TEXT" ) {
- slide = (uint64_t)baseAddress - info.vmaddr;
+ mf->forEachSegment(^(const MachOFile::SegmentInfo &info, bool &stop) {
+ if (strncmp(info.segName, "__TEXT", 16) == 0) {
+ slide = (uint64_t)baseAddress - info.vmAddr;
}
// fprintf(stderr, "Mapping\n");
// fprintf(stderr, "fd\tAddress\tFile Offset\tSize\n");
// fprintf(stderr, "%u\t0x%llx\t0x%llx\t%llu\n", fd, info.vmAddr + slide, info.fileOffset + fileOffset, info.vmSize);
mappings.emplace_back((Mapper::Mapping) {
- .address = info.vmaddr + slide,
- .size = info.vmsize,
+ .address = info.vmAddr + slide,
+ .size = info.vmSize,
.offset = info.fileOffset + fileOffset,
.fd = fd
});
@@ -458,46 +502,46 @@
}
}
-std::pair<SafePointer,bool> Mapper::map(const SafePointer addr, uint64_t size) const {
+std::pair<void*,bool> Mapper::map(const void* addr, uint64_t size) const {
if (_flatMapping) {
uint64_t offset = (uint64_t)addr-(uint64_t)baseAddress();
- return {(uint64_t)((uintptr_t)_flatMapping+offset),false};
+ return {(void*)((uintptr_t)_flatMapping+offset),false};
}
if (_mappings.size() == 0) {
// No mappings means we are an identity mapper
- return { addr, false };
+ return { (void*)addr, false };
}
for (const auto& mapping : _mappings) {
if (((uint64_t)addr >= mapping.address) && ((uint64_t)addr < (mapping.address + mapping.size))) {
if (mapping.fd == -1) {
- return {(((uint64_t)addr-mapping.address)+mapping.offset), false};
+ return {(void*)(((uint64_t)addr-mapping.address)+mapping.offset), false};
}
assert(((uint64_t)addr + size) <= mapping.address + mapping.size);
- uint64_t offset = (uint64_t)addr - mapping.address + mapping.offset;
+ off_t offset = (off_t)addr - mapping.address + mapping.offset;
// Handle unaligned mmap
void* newMapping = nullptr;
size_t extraBytes = 0;
- uint64_t roundedOffset = offset & (-1*PAGE_SIZE);
+ off_t roundedOffset = offset & (-1*PAGE_SIZE);
extraBytes = (size_t)offset - (size_t)roundedOffset;
newMapping = mmap(nullptr, (size_t)size+extraBytes, PROT_READ, MAP_FILE | MAP_PRIVATE, mapping.fd, roundedOffset);
- if (newMapping == MAP_FAILED) {
+ if (newMapping == (void*)-1) {
// fprintf(stderr, "mmap failed: %s (%d)\n", strerror(errno), errno);
- return { SafePointer(), false};
- }
- return {(uint64_t)((uintptr_t)newMapping+extraBytes),true};
- }
- }
- return {SafePointer(), false};
-}
-
-void Mapper::unmap(const SafePointer addr, uint64_t size) const {
- void* roundedAddr = (void*)((intptr_t)(uint64_t)addr & (-1*PAGE_SIZE));
- size_t extraBytes = (uintptr_t)(uint64_t)addr - (uintptr_t)roundedAddr;
+ return {(void*)1, false};
+ }
+ return {(void*)((uintptr_t)newMapping+extraBytes),true};
+ }
+ }
+ return {(void*)-1, false};
+}
+
+void Mapper::unmap(const void* addr, uint64_t size) const {
+ void* roundedAddr = (void*)((intptr_t)addr & (-1*PAGE_SIZE));
+ size_t extraBytes = (uintptr_t)addr - (uintptr_t)roundedAddr;
munmap(roundedAddr, (size_t)size+extraBytes);
}
-const SafePointer Mapper::baseAddress() const {
- return _mappings[0].address;
+const void* Mapper::baseAddress() const {
+ return (const void*)_mappings[0].address;
}
const uint64_t Mapper::size() const {
@@ -545,25 +589,25 @@
#if BUILDING_DYLD
Image::Image(RuntimeState* state, Allocator& ephemeralAllocator, SharedPtr<Mapper>& mapper, const Loader* ldr)
- : _ephemeralAllocator(ephemeralAllocator), _mapper(mapper), _rebasedAddress((uint64_t)ldr->loadAddress(*state)) {
+ : _ephemeralAllocator(ephemeralAllocator), _mapper(mapper), _rebasedAddress((void*)ldr->loadAddress(*state)) {
auto fileID = ldr->fileID(*state);
if (fileID.inode() && fileID.device()) {
_file = state->fileManager.fileRecordForFileID(ldr->fileID(*state));
if ( _file.volume().empty() ) {
- _file = state->fileManager.fileRecordForPath(ephemeralAllocator, ldr->path(*state));
+ _file = state->fileManager.fileRecordForPath(ephemeralAllocator, ldr->path());
}
} else {
- _file = state->fileManager.fileRecordForPath(ephemeralAllocator, ldr->path(*state));
+ _file = state->fileManager.fileRecordForPath(ephemeralAllocator, ldr->path());
}
}
#endif
-Image::Image(Allocator& ephemeralAllocator, FileRecord&& file, SharedPtr<Mapper>& mapper, const SafePointer mh)
- : _ephemeralAllocator(ephemeralAllocator), _file(std::move(file)), _mapper(mapper), _rebasedAddress(mh) {}
-Image::Image(Allocator& ephemeralAllocator, FileRecord&& file, SharedPtr<Mapper>& mapper, const SafePointer mh, const UUID& uuid)
- : _ephemeralAllocator(ephemeralAllocator), _file(std::move(file)), _mapper(mapper), _uuid(uuid), _rebasedAddress(mh) {}
-
-Image::Image(Allocator& ephemeralAllocator, SharedPtr<Mapper>& mapper, SafePointer baseAddress, uint64_t cacheSlide, SharedCache* sharedCache)
- : _ephemeralAllocator(ephemeralAllocator), _mapper(mapper), _sharedCacheSlide(cacheSlide), _rebasedAddress(((uint64_t)baseAddress+cacheSlide)), _sharedCache(sharedCache) {}
+Image::Image(Allocator& ephemeralAllocator, FileRecord&& file, SharedPtr<Mapper>& mapper, const struct mach_header* mh)
+ : _ephemeralAllocator(ephemeralAllocator), _file(std::move(file)), _mapper(mapper), _rebasedAddress((void*)mh) {}
+Image::Image(Allocator& ephemeralAllocator, FileRecord&& file, SharedPtr<Mapper>& mapper, const struct mach_header* mh, const UUID& uuid)
+ : _ephemeralAllocator(ephemeralAllocator), _file(std::move(file)), _mapper(mapper), _uuid(uuid), _rebasedAddress((void*)mh) {}
+
+Image::Image(Allocator& ephemeralAllocator, SharedPtr<Mapper>& mapper, void* baseAddress, uint64_t cacheSlide, SharedCache* sharedCache)
+ : _ephemeralAllocator(ephemeralAllocator), _mapper(mapper), _sharedCacheSlide(cacheSlide), _rebasedAddress((void*)((uint64_t)baseAddress+cacheSlide)), _sharedCache(sharedCache) {}
Image::Image(Image&& other) : _ephemeralAllocator(other._ephemeralAllocator) {
swap(other);
@@ -600,7 +644,7 @@
return nullptr;
}
if (!_ml) {
- SafePointer slidML = rebasedAddress();
+ void* slidML = (void*)rebasedAddress();
// Note, using 4k here as we might be an arm64e process inspecting an x86_64 image, which uses 4k pages
if (!_mapper && !_mapperFailed) {
_mapper = Mapper::mapperForMachO(_transactionalAllocator, _file, _uuid, _rebasedAddress);
@@ -610,10 +654,6 @@
return nullptr;
}
_ml = _mapper->map<MachOLoaded>(slidML, 4096);
- if (!_ml) {
- _mapperFailed = true;
- return nullptr;
- }
size_t size = _ml->sizeofcmds;
if ( _ml->magic == MH_MAGIC_64 ) {
size += sizeof(mach_header_64);
@@ -622,10 +662,6 @@
}
if (size > 4096) {
_ml = _mapper->map<MachOLoaded>(slidML, size);
- if (!_ml) {
- _mapperFailed = true;
- return nullptr;
- }
}
}
// This is a bit of a mess. With compact info this will be unified, but for now we use a lot of hacky abstactions here to deal with
@@ -636,7 +672,7 @@
const UUID& Image::uuid() const {
if (!_uuidLoaded) {
uuid_t fileUUID;
- const Header* mh = (Header*)ml();
+ const MachOLoaded* mh = ml();
if (mh && mh->hasMachOMagic()) {
if (mh->getUuid(fileUUID))
_uuid = UUID(fileUUID);
@@ -646,7 +682,7 @@
return _uuid;
}
-SafePointer Image::rebasedAddress() const {
+uint64_t Image::rebasedAddress() const {
return (uint64_t)_rebasedAddress;
}
@@ -654,7 +690,7 @@
const char* Image::installname() const {
if (!_installnameLoaded) {
if (ml()) {
- _installname = ((const Header*)ml())->installName();
+ _installname = ml()->installName();
}
_installnameLoaded = true;
}
@@ -674,7 +710,7 @@
}
uint64_t Image::sharedCacheVMOffset() const {
- return (uint64_t)_rebasedAddress - (uint64_t)sharedCache()->rebasedAddress();
+ return (uint64_t)_rebasedAddress - sharedCache()->rebasedAddress();
}
uint32_t Image::pointerSize() {
@@ -684,34 +720,34 @@
bool Image::forEachSegment(void (^block)(const char* segmentName, uint64_t vmAddr, uint64_t vmSize, int perm)) {
if (!ml()) { return false; }
- __block uint64_t slide = (uint64_t)_rebasedAddress - ((const Header*)ml())->preferredLoadAddress();
- ((const Header*)ml())->forEachSegment(^(const Header::SegmentInfo &info, bool &stop) {
+ __block uint64_t slide = (uint64_t)_rebasedAddress - ml()->preferredLoadAddress();
+ ml()->forEachSegment(^(const MachOLoaded::SegmentInfo &info, bool &stop) {
uint64_t vmAddr = 0x0;
if ( _sharedCacheSlide.has_value() ) {
- vmAddr = info.vmaddr + _sharedCacheSlide.value();
+ vmAddr = info.vmAddr + _sharedCacheSlide.value();
} else {
if ( ml()->isMainExecutable() ) {
- if ( info.segmentName.starts_with("__PAGEZERO") )
+ if ( strncmp(info.segName, "__PAGEZERO", 10) == 0 )
return;
}
- vmAddr = info.vmaddr + slide;
- }
- block(info.segmentName.data(), vmAddr, info.vmsize, info.initProt);
+ vmAddr = info.vmAddr + slide;
+ }
+ block(info.segName, vmAddr, info.vmSize, info.protections);
});
return true;
}
bool Image::forEachSection(void (^block)(const char* segmentName, const char* sectionName, uint64_t vmAddr, uint64_t vmSize)) {
if (!ml()) { return false; }
- __block uint64_t slide = (uint64_t)_rebasedAddress - ((const Header*)ml())->preferredLoadAddress();
- ((const Header*)ml())->forEachSection(^(const Header::SectionInfo &info, bool &stop) {
+ __block uint64_t slide = (uint64_t)_rebasedAddress - ml()->preferredLoadAddress();
+ ml()->forEachSection(^(const MachOLoaded::SectionInfo &info, bool malformedSectionRange, bool &stop) {
uint64_t sectAddr = 0x0;
if ( _sharedCacheSlide.has_value() ) {
- sectAddr = info.address + _sharedCacheSlide.value();
+ sectAddr = info.sectAddr + _sharedCacheSlide.value();
} else {
- sectAddr = info.address + slide;
- }
- block(info.segmentName.data(), info.sectionName.data(), sectAddr, info.size);
+ sectAddr = info.sectAddr + slide;
+ }
+ block(info.segInfo.segName, info.sectName, sectAddr, info.sectSize);
});
return true;
}
@@ -719,23 +755,23 @@
bool Image::contentForSegment(const char* segmentName, void (^contentReader)(const void* content, uint64_t vmAddr, uint64_t vmSize)) {
if (!ml()) { return false; }
__block bool result = false;
- __block uint64_t slide = (uint64_t)_rebasedAddress - ((const Header*)ml())->preferredLoadAddress();
- ((const Header*)ml())->forEachSegment(^(const Header::SegmentInfo &info, bool &stop) {
- if ( segmentName != info.segmentName ) { return; }
+ __block uint64_t slide = (uint64_t)_rebasedAddress - ml()->preferredLoadAddress();
+ ml()->forEachSegment(^(const MachOLoaded::SegmentInfo &info, bool &stop) {
+ if (strcmp(segmentName, info.segName) != 0) { return; }
uint64_t vmAddr = 0;
if ( _sharedCacheSlide.has_value() ) {
- vmAddr = info.vmaddr + _sharedCacheSlide.value();
+ vmAddr = info.vmAddr + _sharedCacheSlide.value();
} else {
if ( ml()->isMainExecutable() ) {
- if ( info.segmentName.starts_with("__PAGEZERO") )
+ if ( strncmp(info.segName, "__PAGEZERO", 10) == 0 )
return;
}
- vmAddr = info.vmaddr + slide;
- }
-
- if (info.vmsize) {
- auto content = _mapper->map<uint8_t>(vmAddr, info.vmsize);
- contentReader((void*)&*content, vmAddr, info.vmsize);
+ vmAddr = info.vmAddr + slide;
+ }
+
+ if (info.vmSize) {
+ auto content = _mapper->map<uint8_t>((void*)(vmAddr), info.vmSize);
+ contentReader((void*)&*content, vmAddr, info.vmSize);
} else {
contentReader(nullptr, vmAddr, 0);
}
@@ -748,19 +784,19 @@
bool Image::contentForSection(const char* segmentName, const char* sectionName,
void (^contentReader)(const void* content, uint64_t vmAddr, uint64_t vmSize)) {
__block bool result = false;
- __block uint64_t slide = (uint64_t)_rebasedAddress - ((const Header*)ml())->preferredLoadAddress();
- ((const Header*)ml())->forEachSection(^(const Header::SectionInfo &info, bool &stop) {
- if ( segmentName != info.segmentName ) { return; }
- if ( sectionName != info.sectionName ) { return; }
+ __block uint64_t slide = (uint64_t)_rebasedAddress - ml()->preferredLoadAddress();
+ ml()->forEachSection(^(const MachOLoaded::SectionInfo &info, bool malformedRange, bool &stop) {
+ if (strcmp(segmentName, info.segInfo.segName) != 0) { return; }
+ if (strcmp(sectionName, info.sectName) != 0) { return; }
uint64_t sectAddr = 0;
if ( _sharedCacheSlide.has_value() ) {
- sectAddr = info.address + _sharedCacheSlide.value();
+ sectAddr = info.sectAddr + _sharedCacheSlide.value();
} else {
- sectAddr = info.address + slide;
- }
- if (info.size) {
- auto content = _mapper->map<uint8_t>(sectAddr, info.size);
- contentReader((void*)&*content, sectAddr, info.size);
+ sectAddr = info.sectAddr + slide;
+ }
+ if (info.sectSize) {
+ auto content = _mapper->map<uint8_t>((void*)(sectAddr), info.sectSize);
+ contentReader((void*)&*content, sectAddr, info.sectSize);
} else {
contentReader(nullptr, sectAddr, 0);
}
@@ -775,12 +811,12 @@
SharedCacheLocals::SharedCacheLocals(SharedPtr<Mapper>& M, bool use64BitDylibOffsets)
: _mapper(M), _use64BitDylibOffsets(use64BitDylibOffsets) {
- auto header = _mapper->map<dyld_cache_header>(0ULL, sizeof(dyld_cache_header));
+ auto header = _mapper->map<dyld_cache_header>((void*)0, sizeof(dyld_cache_header));
// Map in the whole locals buffer.
// TODO: Once we have the symbols in their own file, simplify this to just map the whole file
// and not do the header and locals separately
- _locals = _mapper->map<uint8_t>(header->localSymbolsOffset, header->localSymbolsSize);
+ _locals = _mapper->map<uint8_t>((void*)header->localSymbolsOffset, header->localSymbolsSize);
}
const dyld_cache_local_symbols_info* SharedCacheLocals::localInfo() const {
@@ -799,7 +835,7 @@
uint64_t rebasedAddress, bool splitCache)
{
// If we have sub caches, then the cache header itself tells us how much space we need to cover all caches
- if (header->mappingOffset >= offsetof(dyld_cache_header, subCacheArrayCount) ) {
+ if (header->mappingOffset >= __offsetof(dyld_cache_header, subCacheArrayCount) ) {
return header->sharedRegionSize;
} else {
auto headerBytes = (uint8_t*)&*header;
@@ -813,19 +849,19 @@
if (splitCache) {
for (auto i = 0; i < header->subCacheArrayCount; ++i) {
uint64_t subCacheOffset = 0;
- if (header->mappingOffset <= offsetof(dyld_cache_header, cacheSubType) ) {
+ if (header->mappingOffset <= __offsetof(dyld_cache_header, cacheSubType) ) {
auto subCaches = (dyld_subcache_entry_v1*)&headerBytes[header->subCacheArrayOffset];
subCacheOffset = subCaches[i].cacheVMOffset;
} else {
auto subCaches = (dyld_subcache_entry*)&headerBytes[header->subCacheArrayOffset];
subCacheOffset = subCaches[i].cacheVMOffset;
}
- auto subCacheHeader = mapper->map<dyld_cache_header>(subCacheOffset + rebasedAddress, PAGE_SIZE);
+ auto subCacheHeader = mapper->map<dyld_cache_header>((void*)(subCacheOffset + rebasedAddress), PAGE_SIZE);
uint64_t subCacheHeaderSize = 0;
bool splitCacheUnused;
getCacheInfo(&*subCacheHeader, subCacheHeaderSize, splitCacheUnused);
if (subCacheHeaderSize > PAGE_SIZE) {
- subCacheHeader = mapper->map<dyld_cache_header>(subCacheOffset + rebasedAddress, subCacheHeaderSize);
+ subCacheHeader = mapper->map<dyld_cache_header>((void*)(subCacheOffset + rebasedAddress), subCacheHeaderSize);
}
auto subCacheHeaderBytes = (uint8_t*)&*subCacheHeader;
auto subCacheMappings = (dyld_cache_mapping_and_slide_info*)&subCacheHeaderBytes[subCacheHeader->mappingWithSlideOffset];
@@ -840,20 +876,20 @@
}
}
-SharedCache::SharedCache(Allocator& ephemeralAllocator, FileRecord&& file, SharedPtr<Mapper>& mapper, SafePointer rebasedAddress, bool P)
+SharedCache::SharedCache(Allocator& ephemeralAllocator, FileRecord&& file, SharedPtr<Mapper>& mapper, uint64_t rebasedAddress, bool P)
: _ephemeralAllocator(ephemeralAllocator), _file(std::move(file)), _mapper(mapper), _rebasedAddress(rebasedAddress), _private(P)
{
assert(_mapper);
- _header = _mapper->map<dyld_cache_header>(_rebasedAddress, PAGE_SIZE);
+ _header = _mapper->map<dyld_cache_header>((void*)_rebasedAddress, PAGE_SIZE);
uint64_t headerSize = 0;
bool splitCache = false;
getCacheInfo(&*_header, headerSize, splitCache);
if (headerSize > PAGE_SIZE) {
- _header = _mapper->map<dyld_cache_header>(_rebasedAddress, headerSize);
+ _header = _mapper->map<dyld_cache_header>((void*)_rebasedAddress, headerSize);
}
_uuid = UUID(&_header->uuid[0]);
- _slide = (uint64_t)_rebasedAddress - _header->sharedRegionStart;
- _size = cacheMappedSize(_header, _mapper, (uint64_t)rebasedAddress, splitCache);
+ _slide = _rebasedAddress - _header->sharedRegionStart;
+ _size = cacheMappedSize(_header, _mapper, rebasedAddress, splitCache);
}
@@ -867,7 +903,6 @@
"/private/preboot/Cryptexes/OS/System/DriverKit/System/Library/dyld/",
"/System/Cryptexes/OS/System/Library/Caches/com.apple.dyld/",
"/System/Cryptexes/OS/System/Library/dyld/",
- "/System/Cryptexes/ExclaveOS/System/ExclaveKit/System/Library/dyld/",
"/System/Volumes/Preboot/Cryptexes/Incoming/OS/System/Library/dyld/",
"/System/Volumes/Preboot/Cryptexes/Incoming/OS/System/DriverKit/System/Library/dyld/",
"/private/preboot/Cryptexes/Incoming/OS/System/Library/Caches/com.apple.dyld/",
@@ -876,7 +911,6 @@
"/System/Cryptexes/Incoming/OS/System/Library/dyld/",
"/System/Library/Caches/com.apple.dyld/",
"/System/DriverKit/System/Library/dyld/",
- "/System/ExclaveKit/System/Library/dyld/",
"/System/Library/dyld/"
};
@@ -943,7 +977,7 @@
UniquePtr<SharedCache> SharedCache::createForFileRecord(Allocator& _ephemeralAllocator, FileRecord&& file) {
auto uuid = UUID();
- auto fileMapper = Mapper::mapperForSharedCache(_ephemeralAllocator, file, 0ULL);
+ auto fileMapper = Mapper::mapperForSharedCache(_ephemeralAllocator, file, 0);
if (!fileMapper) { return nullptr; }
return _transactionalAllocator.makeUnique<SharedCache>(_ephemeralAllocator, std::move(file), fileMapper, (uint64_t)fileMapper->baseAddress(), true);
}
@@ -953,7 +987,7 @@
return _uuid;
}
-SafePointer SharedCache::rebasedAddress() const {
+uint64_t SharedCache::rebasedAddress() const {
return _rebasedAddress;
}
@@ -976,7 +1010,7 @@
if (splitCache) {
auto headerBytes = (std::byte*)&*_header;
char subCachePath[PATH_MAX];
- if (_header->mappingOffset <= offsetof(dyld_cache_header, cacheSubType)) {
+ if (_header->mappingOffset <= __offsetof(dyld_cache_header, cacheSubType)) {
for (auto i = 0; i < _header->subCacheArrayCount; ++i) {
snprintf(&subCachePath[0], sizeof(subCachePath), "%s.%u", _file.getPath(), i+1);
block(subCachePath);
@@ -988,7 +1022,7 @@
block(subCachePath);
}
}
- if ( (_header->mappingOffset >= offsetof(dyld_cache_header, symbolFileUUID)) && !uuid_is_null(_header->symbolFileUUID) ) {
+ if ( (_header->mappingOffset >= __offsetof(dyld_cache_header, symbolFileUUID)) && !uuid_is_null(_header->symbolFileUUID) ) {
strlcpy(&subCachePath[0], _file.getPath(), PATH_MAX);
// On new caches, the locals come from a new subCache file
if (strstr(subCachePath, ".development") != nullptr) {
@@ -1012,7 +1046,7 @@
auto headerBytes = (uint8_t*)&*_header;
auto images = std::span((const dyld_cache_image_text_info*)&headerBytes[_header->imagesTextOffset], (size_t)_header->imagesTextCount);
for (auto i : images) {
- auto image = Image(_ephemeralAllocator, _mapper, i.loadAddress, _slide, this);
+ auto image = Image(_ephemeralAllocator, _mapper, (void*)(i.loadAddress), _slide, this);
block(&image);
}
}
@@ -1020,7 +1054,7 @@
void SharedCache::withImageForIndex(uint32_t idx, void (^block)(Image* image)) {
auto headerBytes = (uint8_t*)&*_header;
auto images = std::span((const dyld_cache_image_text_info*)&headerBytes[_header->imagesTextOffset], (size_t)_header->imagesTextCount);
- auto image = Image(_ephemeralAllocator, _mapper, images[idx].loadAddress, _slide, this);
+ auto image = Image(_ephemeralAllocator, _mapper, (void*)(images[idx].loadAddress), _slide, this);
block(&image);
}
@@ -1031,7 +1065,7 @@
// Where it is depends on the cache header
char localSymbolsCachePath[PATH_MAX];
strlcpy(&localSymbolsCachePath[0], _file.getPath(), PATH_MAX);
- bool useSymbolsFile = (_header->mappingOffset >= offsetof(dyld_cache_header, symbolFileUUID));
+ bool useSymbolsFile = (_header->mappingOffset >= __offsetof(dyld_cache_header, symbolFileUUID));
if ( useSymbolsFile ) {
if ( uuid_is_null(_header->symbolFileUUID) )
return nullptr;
@@ -1082,7 +1116,7 @@
for(auto i = 0; i < _header->mappingCount; ++i) {
// _slide = _baseAddress - _header->sharedRegionStart;
auto mapping = (dyld_cache_mapping_info*)&subCacheHeaderBytes[subCacheHeader->mappingOffset+(i*sizeof(dyld_cache_mapping_info))];
- auto mappingBytes = _mapper->map<uint8_t>(mapping->address - _slide, mapping->size);
+ auto mappingBytes = _mapper->map<uint8_t>((void*)(mapping->address - _slide), mapping->size);
kern_return_t r = vm_copy(mach_task_self(), (vm_address_t)&*mappingBytes, (vm_size_t)mapping->size, (vm_address_t)(mappedSubCache+mapping->fileOffset));
if ( r != KERN_SUCCESS ) {
result = false;
@@ -1108,18 +1142,18 @@
if (splitCache) {
for (auto i = 0; i < _header->subCacheArrayCount; ++i) {
uint64_t subCacheOffset = 0;
- if (_header->mappingOffset <= offsetof(dyld_cache_header, cacheSubType) ) {
+ if (_header->mappingOffset <= __offsetof(dyld_cache_header, cacheSubType) ) {
auto subCaches = (dyld_subcache_entry_v1*)&headerBytes[_header->subCacheArrayOffset];
subCacheOffset = subCaches[i].cacheVMOffset;
} else {
auto subCaches = (dyld_subcache_entry*)&headerBytes[_header->subCacheArrayOffset];
subCacheOffset = subCaches[i].cacheVMOffset;
}
- auto subCacheHeader = _mapper->map<dyld_cache_header>((uint64_t)rebasedAddress() + subCacheOffset, PAGE_SIZE);
+ auto subCacheHeader = _mapper->map<dyld_cache_header>((void*)(rebasedAddress() + subCacheOffset), PAGE_SIZE);
uint64_t subCacheHeaderSize = subCacheHeader->mappingOffset+subCacheHeader->mappingCount*sizeof(dyld_cache_mapping_info);
getCacheInfo(&*_header, headerSize, splitCache);
if (subCacheHeaderSize > PAGE_SIZE) {
- subCacheHeader = _mapper->map<dyld_cache_header>((uint64_t)rebasedAddress() + subCacheOffset, subCacheHeaderSize);
+ subCacheHeader = _mapper->map<dyld_cache_header>((void*)(rebasedAddress() + subCacheOffset), subCacheHeaderSize);
}
// printf("Subcache Offset: %lx\n", (uintptr_t)&headerBytes[subCacheOffset]);
// printf("subCacheHeader: %lx\n", (uintptr_t)&*subCacheHeader);
@@ -1195,8 +1229,6 @@
pid_t pid;
*kr = pid_for_task(_task, &pid);
if ( *kr != KERN_SUCCESS ) {
- BLEND_KERN_RETURN_LOCATION(*kr, 0xea);
- *kr |= 0xeb000000UL;
return nullptr;
}
@@ -1204,7 +1236,6 @@
mach_msg_type_number_t count = MACH_TASK_BASIC_INFO_COUNT;
*kr = task_info(_task, MACH_TASK_BASIC_INFO, (task_info_t)&ti, &count);
if ( *kr != KERN_SUCCESS ) {
- BLEND_KERN_RETURN_LOCATION(*kr, 0xe9);
return nullptr;
}
@@ -1228,14 +1259,13 @@
mach_vm_size_t readSize = 0;
*kr = mach_vm_read_overwrite(_task, address, size, (mach_vm_address_t)&unsafeBytes[0], &readSize);
if ( *kr != KERN_SUCCESS ) {
- BLEND_KERN_RETURN_LOCATION(*kr, 0xe8);
return;
}
- auto mh = Header::isMachO({(const uint8_t*)unsafeBytes, (size_t)readSize});
- if (!mh) {
+ auto mf = MachOFile::isMachO((const void*)unsafeBytes);
+ if (!mf) {
return;
}
- if ( mh->isMainExecutable() ) {
+ if ( mf->filetype == MH_EXECUTE ) {
int len = proc_regionfilename(pid, address, executablePath, PATH_MAX);
if ( len != 0 ) {
executablePath[len] = '\0';
@@ -1243,11 +1273,11 @@
SharedPtr<Mapper> mapper = nullptr;
auto file = _fileManager.fileRecordForPath(_transactionalAllocator, executablePath);
uuid_t rawUUID;
- mh->getUuid(rawUUID);
+ mf->getUuid(rawUUID);
auto uuid = UUID(rawUUID);
- result->addImage(Image(_transactionalAllocator, std::move(file), mapper, (uint64_t)address, uuid));
+ result->addImage(Image(_transactionalAllocator, std::move(file), mapper, (const mach_header*)address, uuid));
foundMainExecutable = true;
- } else if ( mh->isDylinker() ) {
+ } else if ( mf->filetype == MH_DYLINKER ) {
int len = proc_regionfilename(pid, address, executablePath, PATH_MAX);
if ( len != 0 ) {
executablePath[len] = '\0';
@@ -1255,9 +1285,9 @@
SharedPtr<Mapper> mapper = nullptr;
auto file = _fileManager.fileRecordForPath(_transactionalAllocator, executablePath);
uuid_t rawUUID;
- mh->getUuid(rawUUID);
+ mf->getUuid(rawUUID);
auto uuid = UUID(rawUUID);
- result->addImage(Image(_transactionalAllocator, std::move(file), mapper, (uint64_t)address, uuid));
+ result->addImage(Image(_transactionalAllocator, std::move(file), mapper, (const mach_header*)address, uuid));
foundDyld = true;
}
});
@@ -1289,55 +1319,48 @@
task_dyld_info_data_t task_dyld_info;
*kr = task_info(_task, TASK_DYLD_INFO, (task_info_t)&task_dyld_info, &count);
if ( *kr != KERN_SUCCESS ) {
- BLEND_KERN_RETURN_LOCATION(*kr, 0xef);
return nullptr;
}
//The kernel will return MACH_VM_MIN_ADDRESS for an executable that has not had dyld loaded
if (task_dyld_info.all_image_info_addr == MACH_VM_MIN_ADDRESS) {
- BLEND_KERN_RETURN_LOCATION(*kr, 0xee);
return nullptr;
}
- uint64_t failedAddress = 0;
+ uint8_t remoteBuffer[16*1024];
+ mach_vm_size_t readSize = 0;
while (1) {
// Using mach_vm_read_overwrite because this is part of dyld. If the file is removed or the codesignature is invalid
// then the system is broken beyond recovery anyway
- auto taskInfoBuffer = SafeRemoteBuffer(_task, task_dyld_info.all_image_info_addr, task_dyld_info.all_image_info_size, kr);
+ *kr = mach_vm_read_overwrite(_task, task_dyld_info.all_image_info_addr, task_dyld_info.all_image_info_size,
+ (mach_vm_address_t)&remoteBuffer[0], &readSize);
if (*kr != KERN_SUCCESS) {
- BLEND_KERN_RETURN_LOCATION(*kr, 0xed);
// If we cannot read the all image info this is game over
return nullptr;
}
uint64_t compactInfoAddress;
uint64_t compactInfoSize;
if (task_dyld_info.all_image_info_format == TASK_DYLD_ALL_IMAGE_INFO_32 ) {
- const dyld_all_image_infos_32* info = (const dyld_all_image_infos_32*)&taskInfoBuffer.data()[0];
+ const dyld_all_image_infos_32* info = (const dyld_all_image_infos_32*)&remoteBuffer[0];
compactInfoAddress = info->compact_dyld_image_info_addr;
compactInfoSize = info->compact_dyld_image_info_size;
} else {
- const dyld_all_image_infos_64* info = (const dyld_all_image_infos_64*)&taskInfoBuffer.data()[0];
+ const dyld_all_image_infos_64* info = (const dyld_all_image_infos_64*)&remoteBuffer[0];
compactInfoAddress = info->compact_dyld_image_info_addr;
compactInfoSize = info->compact_dyld_image_info_size;
}
if (compactInfoSize == 0) {
return synthesizeSnapshot(kr);
}
-
- auto compactInfoBuffer = SafeRemoteBuffer(_task, compactInfoAddress,compactInfoSize, kr);
+ auto compactInfo = UniquePtr<std::byte>((std::byte*)_transactionalAllocator.malloc((size_t)compactInfoSize));
+ *kr = mach_vm_read_overwrite(_task, compactInfoAddress, compactInfoSize, (mach_vm_address_t)&*compactInfo, &readSize);
if (*kr != KERN_SUCCESS) {
- BLEND_KERN_RETURN_LOCATION(*kr, 0xec);
- if (compactInfoAddress == failedAddress) {
- // We tried the same address twice and it failed both times, this is not a simple mutation issue, give up and reutrn an error
- return nullptr;
- }
- failedAddress = compactInfoAddress;
// The read failed, chances are the process mutated the compact info, retry
continue;
}
- UniquePtr<ProcessSnapshot> result = _transactionalAllocator.makeUnique<ProcessSnapshot>(_ephemeralAllocator, _fileManager, false, compactInfoBuffer.data());
+ std::span<std::byte> data = std::span<std::byte>(&*compactInfo, (size_t)compactInfoSize);
+ UniquePtr<ProcessSnapshot> result = _transactionalAllocator.makeUnique<ProcessSnapshot>(_ephemeralAllocator, _fileManager, false, data);
if (!result->valid()) {
// Something blew up we don't know what
*kr = KERN_FAILURE;
- BLEND_KERN_RETURN_LOCATION(*kr, 0xeb);
return nullptr;
}
return result;
@@ -1575,46 +1598,14 @@
: _ephemeralAllocator(ephemeralAllocator), _fileManager(fileManager), _images(_transactionalAllocator),
_identityMapper(_transactionalAllocator.makeShared<Mapper>(_transactionalAllocator)), _useIdentityMapper(useIdentityMapper) {}
-#if BUILDING_LIBDYLD && !TARGET_OS_DRIVERKIT && !TARGET_OS_EXCLAVEKIT
-// This function is a private interface between libdyld and Dyld.framework and implemented in Swift
-// there is no header
-extern "C" const bool unwrapCompactInfo(void* _Nonnull buffer, uint64_t* _Nonnull size);
-#endif /* BUILDING_LIBDYLD && !TARGET_OS_DRIVERKIT && !TARGET_OS_EXCLAVEKIT */
-
ProcessSnapshot::ProcessSnapshot(Allocator& ephemeralAllocator, FileManager& fileManager, bool useIdentityMapper, const std::span<std::byte> data)
: _ephemeralAllocator(ephemeralAllocator), _fileManager(fileManager), _images(_transactionalAllocator),
_identityMapper(_transactionalAllocator.makeShared<Mapper>(_transactionalAllocator)), _useIdentityMapper(useIdentityMapper) {
Serializer serializer(*this);
- bool deserializedSucceeed = serializer.deserialize(data);
-#if BUILDING_LIBDYLD && !TARGET_OS_DRIVERKIT && !TARGET_OS_EXCLAVEKIT
- static dispatch_once_t onceToken;
- static __typeof__(unwrapCompactInfo) *unwrapCompactInfoPtr = nullptr;
- if (!deserializedSucceeed) {
- // If we failed we try to load the unwrap function
- dispatch_once(&onceToken, ^{
- // We attempt a dlopen() here since the unwrapCompactInfo is not in the build yet, and this is a temporary compatibility hack
- void* dyldFrameworkHandle = dlopen("/System/Library/PrivateFrameworks/Dyld.framework/Dyld", RTLD_NOW);
- unwrapCompactInfoPtr = (__typeof__(unwrapCompactInfo)*)dlsym(dyldFrameworkHandle, "unwrapCompactInfo");
- });
- }
- // Only try the fallback if we managed to load the unwrap function
- if (unwrapCompactInfoPtr && !deserializedSucceeed) {
- std::byte* unwrappedData = (std::byte*)_transactionalAllocator.malloc(data.size());
- std::copy(data.begin(), data.end(), unwrappedData);
- uint64_t unwrappedSize = data.size();
- if (unwrapCompactInfoPtr((void*)unwrappedData, &unwrappedSize)) {
- std::span<std::byte> unwrappedSpan = std::span<std::byte>(unwrappedData, (size_t)unwrappedSize);
- deserializedSucceeed = serializer.deserialize(unwrappedSpan);
- }
- free((void*)unwrappedData);
- }
-#endif /* BUILDING_LIBDYLD && !TARGET_OS_DRIVERKIT && !TARGET_OS_EXCLAVEKIT */
- if (!deserializedSucceeed) {
+ if (!serializer.deserialize(data)) {
// Deerialization failed, reset the snapshot and mark invalid
_images.clear();
- if (_bitmap) {
- _bitmap->clear();
- }
+ _bitmap = nullptr;
_sharedCache = nullptr;
_platform = 0;
_initialImageCount = 0;
@@ -1671,7 +1662,7 @@
uint64_t address = ~0ULL;
auto i = other._images.begin();
if (i != other._images.end()) {
- address = (uint64_t)(*i)->rebasedAddress();
+ address = (*i)->rebasedAddress();
}
for (auto& image : _images) {
@@ -1683,7 +1674,7 @@
address = ~0ULL;
break;
}
- address = (uint64_t)(*i)->rebasedAddress();
+ address = (*i)->rebasedAddress();
}
if (image->rebasedAddress() != address) {
block(&*image);
@@ -1700,7 +1691,7 @@
}
#if BUILDING_DYLD
-void ProcessSnapshot::addImages(RuntimeState* state, Vector<ConstAuthLoader>& loaders) {
+void ProcessSnapshot::addImages(RuntimeState* state, const std::span<const Loader*>& loaders) {
for (auto& ldr : loaders) {
if (_sharedCache && ldr->dylibInDyldCache) {
_bitmap->setBit(ldr->ref.index);
@@ -1730,7 +1721,7 @@
void ProcessSnapshot::addSharedCacheImage(const struct mach_header* mh) {
assert(mh->flags & MH_DYLIB_IN_CACHE);
- auto header = (dyld_cache_header*)(uint64_t)_sharedCache->rebasedAddress();
+ auto header = (dyld_cache_header*)_sharedCache->rebasedAddress();
auto headerBytes = (uint8_t*)header;
auto slide = (uint64_t)header - header->sharedRegionStart;
auto images = std::span((const dyld_cache_image_text_info*)&headerBytes[header->imagesTextOffset], (size_t)header->imagesTextCount);
@@ -1784,7 +1775,7 @@
if (!name) {
name = "<unknown>";
}
- fprintf(stderr, "0x%llx %s %s\n", (uint64_t)image->rebasedAddress(), uuidStr, name);
+ fprintf(stderr, "0x%llx %s %s\n", image->rebasedAddress(), uuidStr, name);
});
}
@@ -1898,33 +1889,23 @@
}
bool ProcessSnapshot::Serializer::readMappedFileInfo(std::span<std::byte>& data, uint64_t& rebasedAddress, UUID& uuid, FileRecord& file) {
- uint64_t flags = 0;
- if (!readPVLEUInt64(data, flags)
- || !readPVLEUInt64(data, rebasedAddress)) {
- return false;
- }
+ uint64_t flags = readPVLEUInt64(data);
+ rebasedAddress = readPVLEUInt64(data);
if (flags & kMappedFileFlagsHasUUID) {
- if (data.size() < 16) {
- return false;
- }
uuid = UUID(&data[0]);
data = data.last(data.size()-16);
}
if (flags & kMappedFileFlagsHasFileID) {
- uint64_t volumeIndex = 0;
- uint64_t objectID = 0;
- if (!readPVLEUInt64(data, volumeIndex)
- || !readPVLEUInt64(data, objectID)
- || volumeIndex >= _volumeUUIDs.size()) {
+ uint64_t volumeIndex = readPVLEUInt64(data);
+ uint64_t objectID = readPVLEUInt64(data);
+ if (volumeIndex >= _volumeUUIDs.size() )
return false;
- }
file = _fileManager.fileRecordForVolumeUUIDAndObjID(_volumeUUIDs[(size_t)volumeIndex], objectID);
}
if (flags & kMappedFileFlagsHasFilePath) {
- uint64_t pathOffset = 0;
- if (!readPVLEUInt64(data, pathOffset) || pathOffset >= _stringTableBuffer.size()) {
+ uint64_t pathOffset = readPVLEUInt64(data);
+ if ( pathOffset >= _stringTableBuffer.size() )
return false;
- }
file = _fileManager.fileRecordForPath(_ephemeralAllocator, &_stringTableBuffer[(size_t)pathOffset]);
}
return true;
@@ -1999,18 +1980,16 @@
emitPVLEUInt64(_stringTableBuffer.size(), result);
std::copy((std::byte*)_stringTableBuffer.begin(), (std::byte*)_stringTableBuffer.end(), std::back_inserter(result));
if (_processFlags & kProcessFlagsHasSharedCache) {
- uint64_t address = (uint64_t)_sharedCache->rebasedAddress()/((_processFlags & kProcessFlagsHas16kPages) ? 16384 : 4096);
+ uint64_t address = _sharedCache->rebasedAddress()/((_processFlags & kProcessFlagsHas16kPages) ? 16384 : 4096);
emitMappedFileInfo(address, _sharedCache->uuid(), _sharedCache->file(), result);
- emitPVLEUInt64(_bitmap->size(), result);
- if (_bitmap->size() > 0)
- emit(_bitmap->bytes(), result);
+ _bitmap->emit(result);
}
emitPVLEUInt64(_images.size(), result);
uint64_t lastAddress = 0;
for (const auto& image : _images) {
- uint64_t address = ((uint64_t)image->rebasedAddress()-lastAddress)/((_processFlags & kProcessFlagsHas16kPages) ? 16384 : 4096);
- lastAddress = (uint64_t)image->rebasedAddress();
+ uint64_t address = (image->rebasedAddress()-lastAddress)/((_processFlags & kProcessFlagsHas16kPages) ? 16384 : 4096);
+ lastAddress = image->rebasedAddress();
emitMappedFileInfo(address, image->uuid(), image->file(), result);
}
while(result.size()%16 != 0) {
@@ -2024,10 +2003,6 @@
bool ProcessSnapshot::Serializer::deserialize(const std::span<std::byte> data) {
auto i = data;
- if (i.size() < 36) {
- // Ensure data is at least large enough to read the header
- return false;
- }
// Confirm magic
_magic = read<uint32_t>(i);
_version = read<uint32_t>(i);
@@ -2049,27 +2024,17 @@
if (_crc32c != checksumer) {
return false;
}
- uint64_t volumeUUIDCount = 0;
- if (!readPVLEUInt64(i, _processFlags)
- || !readPVLEUInt64(i, _platform)
- || !readPVLEUInt64(i, _initialImageCount)
- || !readPVLEUInt64(i, _dyldState)
- || !readPVLEUInt64(i, volumeUUIDCount)) {
- return false;
- }
- if (i.size() < volumeUUIDCount*16) {
- return false;
- }
+ _processFlags = readPVLEUInt64(i);
+ _platform = readPVLEUInt64(i);
+ _initialImageCount = readPVLEUInt64(i);
+ _dyldState = readPVLEUInt64(i);
+ auto volumeUUIDCount = readPVLEUInt64(i);
for (auto j = 0; j < volumeUUIDCount; ++j) {
UUID volumeUUID(&i[j*16]);
_volumeUUIDs.push_back(volumeUUID);
}
i = i.last((size_t)(i.size()-(16*volumeUUIDCount)));
- uint64_t stringTableSize = 0;
- if (!readPVLEUInt64(i, stringTableSize)
- || i.size() < stringTableSize) {
- return false;
- }
+ auto stringTableSize = readPVLEUInt64(i);
_stringTableBuffer.reserve((size_t)stringTableSize);
std::copy((uint8_t*)&i[0], (uint8_t*)&i[(size_t)stringTableSize], std::back_inserter(_stringTableBuffer));
i = i.last((size_t)(i.size()-stringTableSize));
@@ -2080,7 +2045,7 @@
FileRecord file;
if ( !readMappedFileInfo(i, rebasedAddress, uuid, file) )
return false;
- rebasedAddress = rebasedAddress * ((_processFlags & kProcessFlagsHas16kPages) ? kPageSize16K : kPageSize4K);
+ rebasedAddress = rebasedAddress * ((_processFlags & kProcessFlagsHas16kPages) ? 16384 : 4096);
SharedPtr<Mapper> mapper = nullptr;
if (_processSnapshot._useIdentityMapper) {
mapper = _processSnapshot.identityMapper();
@@ -2088,27 +2053,18 @@
#if BUILDING_DYLD || BUILDING_UNIT_TESTS
mapper = _transactionalAllocator.makeShared<Mapper>(_transactionalAllocator);
#else
- mapper = Mapper::mapperForSharedCache(_transactionalAllocator, file, rebasedAddress);
+ mapper = Mapper::mapperForSharedCache(_transactionalAllocator, file, (void*)rebasedAddress);
#endif
}
if (!mapper) {
return false;
}
- _sharedCache = _transactionalAllocator.makeUnique<SharedCache>(_transactionalAllocator, std::move(file), mapper,
+
+ _sharedCache = _transactionalAllocator.makeUnique<SharedCache>(_ephemeralAllocator, std::move(file), mapper,
rebasedAddress, _processFlags & kProcessFlagsHasPrivateCache);
- uint64_t encodedSize = 0;
- if (!readPVLEUInt64(i, encodedSize)) {
- return false;
- }
- _bitmap = _transactionalAllocator.makeUnique<Bitmap>(_transactionalAllocator, (size_t)encodedSize, i);
- if (_bitmap->size() == 0) {
- return false;
- }
- }
- uint64_t imageCount = 0;
- if (!readPVLEUInt64(i, imageCount)) {
- return false;
- }
+ _bitmap = _transactionalAllocator.makeUnique<Bitmap>(_transactionalAllocator, i);
+ }
+ auto imageCount = readPVLEUInt64(i);
uint64_t lastAddress = 0;
for (auto j = 0; j < imageCount; ++j) {
uint64_t rebasedAddress;
@@ -2127,7 +2083,7 @@
mapper = _transactionalAllocator.makeShared<Mapper>(_transactionalAllocator);
}
#endif
- auto image = Image(_transactionalAllocator, std::move(file), mapper, (uint64_t)rebasedAddress, uuid);
+ auto image = Image(_ephemeralAllocator, std::move(file), mapper, (const struct mach_header*)rebasedAddress, uuid);
_images.insert(_transactionalAllocator.makeUnique<Image>(std::move(image)));
}
return true;
@@ -2136,4 +2092,3 @@
};
};
#endif // !TARGET_OS_EXCLAVEKIT
-