Loading...
--- dyld/dyld-1284.13/cache-builder/AppCacheBuilder.cpp
+++ dyld/dyld-1125.5/cache-builder/AppCacheBuilder.cpp
@@ -36,10 +36,6 @@
#include <CommonCrypto/CommonDigest.h>
#include <CommonCrypto/CommonDigestSPI.h>
-#include "Header.h"
-
-using mach_o::Header;
-
AppCacheBuilder::AppCacheBuilder(const DyldSharedCache::CreateOptions& options,
const Options& appCacheOptions,
const dyld3::closure::FileSystem& fileSystem)
@@ -109,7 +105,7 @@
bool stop = false;
for (const AppCacheDylibInfo& dylib : sortedDylibs) {
for (const SegmentMappingInfo& loc : dylib.cacheLocation) {
- if ( loc.segName == "__TEXT" ) {
+ if (!strcmp(loc.segName, "__TEXT")) {
// Assume __TEXT contains the mach header
callback((const dyld3::MachOAnalyzer*)loc.dstSegment, dylib.dylibID, dylib.stripMode,
dylib.dependencies, *dylib.errors, stop);
@@ -163,45 +159,41 @@
// readOnlyTextRegion
callback(readOnlyTextRegion);
+ // readExecuteRegion
+ if ( readExecuteRegion.sizeInUse != 0 )
+ callback(readExecuteRegion);
+
+ // branchStubsRegion
+ if ( branchStubsRegion.bufferSize != 0 )
+ callback(branchStubsRegion);
+
+ // textBootExecRegion
+ if ( textBootExecRegion.sizeInUse != 0 )
+ callback(textBootExecRegion);
+
+ // dataConstRegion
+ if ( dataConstRegion.sizeInUse != 0 )
+ callback(dataConstRegion);
+
+ // dataSptmRegion
+ if ( dataSptmRegion.sizeInUse != 0 )
+ callback(dataSptmRegion);
+
+ // branchGOTsRegion
+ if ( branchGOTsRegion.bufferSize != 0 )
+ callback(branchGOTsRegion);
+
+ // readWriteRegion
+ if ( readWriteRegion.sizeInUse != 0 )
+ callback(readWriteRegion);
+
+ // hibernateRegion
+ if ( hibernateRegion.sizeInUse != 0 )
+ callback(hibernateRegion);
+
// -sectcreate
for (const Region& region : customDataRegions)
callback(region);
-
- // readExecuteRegion
- if ( readExecuteRegion.sizeInUse != 0 )
- callback(readExecuteRegion);
-
- // branchStubsRegion
- if ( branchStubsRegion.bufferSize != 0 )
- callback(branchStubsRegion);
-
- // textBootExecRegion
- if ( textBootExecRegion.sizeInUse != 0 )
- callback(textBootExecRegion);
-
- // dataConstRegion
- if ( dataConstRegion.sizeInUse != 0 )
- callback(dataConstRegion);
-
- // lateConstRegion
- if ( lateConstRegion.sizeInUse != 0 )
- callback(lateConstRegion);
-
- // dataSptmRegion
- if ( dataSptmRegion.sizeInUse != 0 )
- callback(dataSptmRegion);
-
- // branchGOTsRegion
- if ( branchGOTsRegion.bufferSize != 0 )
- callback(branchGOTsRegion);
-
- // readWriteRegion
- if ( readWriteRegion.sizeInUse != 0 )
- callback(readWriteRegion);
-
- // hibernateRegion
- if ( hibernateRegion.sizeInUse != 0 )
- callback(hibernateRegion);
// prelinkInfoRegion
if ( prelinkInfoDict != nullptr )
@@ -346,13 +338,13 @@
// Find __TEXT_EXEC __auth_stubs, and remove it if we have it
__block bool lastSectionWasAuthStubs = false;
- ((const Header*)ma)->forEachSection(^(const Header::SectionInfo& sectInfo, bool& stop) {
- if ( sectInfo.segmentName != "__TEXT_EXEC" )
+ ma->forEachSection(^(const dyld3::MachOAnalyzer::SectionInfo& sectInfo, bool malformedSectionRange, bool& stop) {
+ if ( strcmp(sectInfo.segInfo.segName, "__TEXT_EXEC") != 0 )
return;
lastSectionWasAuthStubs = false;
- if ( sectInfo.sectionName == "__auth_stubs" ) {
+ if ( strcmp(sectInfo.sectName, "__auth_stubs") == 0 ) {
// The auth stubs are only valid if the sections is 16-byte stubs
- if ( ((sectInfo.flags & SECTION_TYPE) == S_SYMBOL_STUBS) && (sectInfo.reserved2 == 16) )
+ if ( ((sectInfo.sectFlags & SECTION_TYPE) == S_SYMBOL_STUBS) && (sectInfo.reserved2 == 16) )
lastSectionWasAuthStubs = true;
}
});
@@ -368,25 +360,25 @@
// so first make space for all the cache location objects so that we get the order the same
// as the LC_SEGMENTs
for (DylibInfo& dylib : sortedDylibs) {
- ((const Header*)dylib.input->mappedFile.mh)->forEachSegment(^(const Header::SegmentInfo& segInfo, bool& stop) {
+ dylib.input->mappedFile.mh->forEachSegment(^(const dyld3::MachOFile::SegmentInfo& segInfo, bool& stop) {
dylib.cacheLocation.push_back({});
});
}
// If we are building the kernel collection, then inherit the base address of the statically linked kernel
- const Header* kernelHdr = nullptr;
+ const dyld3::MachOAnalyzer* kernelMA = nullptr;
if ( appCacheOptions.cacheKind == Options::AppCacheKind::kernel ) {
for (DylibInfo& dylib : sortedDylibs) {
if ( dylib.input->mappedFile.mh->isStaticExecutable() ) {
- kernelHdr = (const Header*)dylib.input->mappedFile.mh;
+ kernelMA = dylib.input->mappedFile.mh;
break;
}
}
- if ( kernelHdr == nullptr ) {
+ if ( kernelMA == nullptr ) {
_diagnostics.error("Could not find kernel image");
return;
}
- cacheBaseAddress = kernelHdr->preferredLoadAddress();
+ cacheBaseAddress = kernelMA->preferredLoadAddress();
}
// x86_64 doesn't have stubs for kext branches. So work out how many potential targets
@@ -398,10 +390,10 @@
minimumSegmentAlignmentP2 = 12;
}
- auto getMinAlignment = ^(const Header* hdr) {
+ auto getMinAlignment = ^(const dyld3::MachOAnalyzer* ma) {
// The kernel wants to be able to unmap its own segments so always align it.
// And align the pageable KC as each kext can be mapped individually
- if ( hdr == kernelHdr )
+ if ( ma == kernelMA )
return minimumSegmentAlignmentP2;
if ( fixupsArePerKext() )
return minimumSegmentAlignmentP2;
@@ -417,27 +409,26 @@
continue;
__block uint64_t textSegVmAddr = 0;
- ((const Header*)dylib.input->mappedFile.mh)->forEachSegment(^(const Header::SegmentInfo& segInfo, uint64_t sizeOfSections, uint32_t maxAlignOfSections, bool& stop) {
- if ( segInfo.segmentName == "__TEXT" )
- textSegVmAddr = segInfo.vmaddr;
- if ( segInfo.initProt != (VM_PROT_READ) )
+ dylib.input->mappedFile.mh->forEachSegment(^(const dyld3::MachOFile::SegmentInfo& segInfo, bool& stop) {
+ if ( strcmp(segInfo.segName, "__TEXT") == 0 )
+ textSegVmAddr = segInfo.vmAddr;
+ if ( segInfo.protections != (VM_PROT_READ) )
return;
- if ( ( segInfo.segmentName == "__DATA_CONST" )
- || ( segInfo.segmentName == "__PPLDATA_CONST" )
- || ( segInfo.segmentName == "__LASTDATA_CONST" )
- || ( segInfo.segmentName == "__LATE_CONST" ) )
+ if ( (strcmp(segInfo.segName, "__DATA_CONST") == 0)
+ || (strcmp(segInfo.segName, "__PPLDATA_CONST") == 0)
+ || (strcmp(segInfo.segName, "__LASTDATA_CONST") == 0) )
return;
- if ( segInfo.segmentName == "__LINKEDIT" )
+ if ( strcmp(segInfo.segName, "__LINKEDIT") == 0 )
return;
- if ( segInfo.segmentName == "__LINKINFO" )
+ if ( strcmp(segInfo.segName, "__LINKINFO") == 0 )
return;
- uint32_t minAlignmentP2 = getMinAlignment((const Header*)dylib.input->mappedFile.mh);
- size_t copySize = std::min((size_t)segInfo.fileSize, (size_t)sizeOfSections);
- uint64_t dstCacheSegmentSize = align(sizeOfSections, minAlignmentP2);
+ uint32_t minAlignmentP2 = getMinAlignment(dylib.input->mappedFile.mh);
+ size_t copySize = std::min((size_t)segInfo.fileSize, (size_t)segInfo.sizeOfSections);
+ uint64_t dstCacheSegmentSize = align(segInfo.sizeOfSections, minAlignmentP2);
// __CTF is not mapped in to the kernel, so remove it from the final binary.
- if ( segInfo.segmentName == "__CTF" ) {
+ if ( strcmp(segInfo.segName, "__CTF") == 0 ) {
copySize = 0;
dstCacheSegmentSize = 0;
}
@@ -445,20 +436,20 @@
// kxld packs __TEXT so we will do
// Note we align to at least 16-bytes as LDR's can scale up to 16 from their address
// and aligning them less than 16 would break that
- offsetInRegion = align(offsetInRegion, std::max(maxAlignOfSections, 4U));
+ offsetInRegion = align(offsetInRegion, std::max(segInfo.p2align, 4U));
offsetInRegion = align(offsetInRegion, minAlignmentP2);
SegmentMappingInfo loc;
- loc.srcSegment = (uint8_t*)dylib.input->mappedFile.mh + segInfo.vmaddr - textSegVmAddr;
- loc.segName = segInfo.segmentName;
+ loc.srcSegment = (uint8_t*)dylib.input->mappedFile.mh + segInfo.vmAddr - textSegVmAddr;
+ loc.segName = segInfo.segName;
loc.dstSegment = nullptr;
loc.dstCacheUnslidAddress = offsetInRegion; // This will be updated later once we've assigned addresses
loc.dstCacheFileOffset = (uint32_t)offsetInRegion;
loc.dstCacheSegmentSize = (uint32_t)dstCacheSegmentSize;
loc.dstCacheFileSize = (uint32_t)copySize;
loc.copySegmentSize = (uint32_t)copySize;
- loc.srcSegmentIndex = segInfo.segmentIndex;
+ loc.srcSegmentIndex = segInfo.segIndex;
loc.parentRegion = &readOnlyTextRegion;
- dylib.cacheLocation[segInfo.segmentIndex] = loc;
+ dylib.cacheLocation[segInfo.segIndex] = loc;
offsetInRegion += dstCacheSegmentSize;
});
}
@@ -481,51 +472,51 @@
continue;
__block uint64_t textSegVmAddr = 0;
- ((const Header*)dylib.input->mappedFile.mh)->forEachSegment(^(const Header::SegmentInfo& segInfo, uint64_t segSizeOfSections, uint32_t maxAlignOfSections, bool& stop) {
- if ( segInfo.segmentName == "__TEXT" )
- textSegVmAddr = segInfo.vmaddr;
- if ( segInfo.segmentName == "__HIB" )
+ dylib.input->mappedFile.mh->forEachSegment(^(const dyld3::MachOFile::SegmentInfo& segInfo, bool& stop) {
+ if ( strcmp(segInfo.segName, "__TEXT") == 0 )
+ textSegVmAddr = segInfo.vmAddr;
+ if ( strcmp(segInfo.segName, "__HIB") == 0 )
return;
- if ( (segInfo.segmentName == "__TEXT_BOOT_EXEC" ) && dylib.input->mappedFile.mh->isStaticExecutable() )
+ if ( (strcmp(segInfo.segName, "__TEXT_BOOT_EXEC") == 0) && dylib.input->mappedFile.mh->isStaticExecutable() )
return;
- if ( segInfo.initProt != (VM_PROT_READ | VM_PROT_EXECUTE) )
+ if ( segInfo.protections != (VM_PROT_READ | VM_PROT_EXECUTE) )
return;
// We may have coalesced the sections at the end of this segment. In that case, shrink the segment to remove them.
__block size_t sizeOfSections = 0;
__block bool foundRemovedSection = false;
- ((const Header*)dylib.input->mappedFile.mh)->forEachSection(^(const Header::SectionInfo §Info, bool &stopSection) {
- if ( sectInfo.segmentName != segInfo.segmentName )
+ dylib.input->mappedFile.mh->forEachSection(^(const dyld3::MachOAnalyzer::SectionInfo §Info, bool malformedSectionRange, bool &stopSection) {
+ if (strcmp(sectInfo.segInfo.segName, segInfo.segName) != 0)
return;
- if ( dylib._coalescer.sectionWasObliterated(segInfo.segmentName, sectInfo.sectionName) ) {
+ if ( dylib._coalescer.sectionWasObliterated(segInfo.segName, sectInfo.sectName)) {
foundRemovedSection = true;
} else {
- sizeOfSections = sectInfo.address + sectInfo.size - segInfo.vmaddr;
+ sizeOfSections = sectInfo.sectAddr + sectInfo.sectSize - segInfo.vmAddr;
}
});
if ( !foundRemovedSection )
- sizeOfSections = segSizeOfSections;
+ sizeOfSections = segInfo.sizeOfSections;
// kxld packs __TEXT_EXEC so we will do
// Note we align to at least 16-bytes as LDR's can scale up to 16 from their address
// and aligning them less than 16 would break that
- uint32_t minAlignmentP2 = getMinAlignment((const Header*)dylib.input->mappedFile.mh);
- offsetInRegion = align(offsetInRegion, std::max(maxAlignOfSections, 4U));
+ uint32_t minAlignmentP2 = getMinAlignment(dylib.input->mappedFile.mh);
+ offsetInRegion = align(offsetInRegion, std::max(segInfo.p2align, 4U));
offsetInRegion = align(offsetInRegion, minAlignmentP2);
size_t copySize = std::min((size_t)segInfo.fileSize, (size_t)sizeOfSections);
uint64_t dstCacheSegmentSize = align(sizeOfSections, minAlignmentP2);
SegmentMappingInfo loc;
- loc.srcSegment = (uint8_t*)dylib.input->mappedFile.mh + segInfo.vmaddr - textSegVmAddr;
- loc.segName = segInfo.segmentName;
+ loc.srcSegment = (uint8_t*)dylib.input->mappedFile.mh + segInfo.vmAddr - textSegVmAddr;
+ loc.segName = segInfo.segName;
loc.dstSegment = nullptr;
loc.dstCacheUnslidAddress = offsetInRegion; // This will be updated later once we've assigned addresses
loc.dstCacheFileOffset = (uint32_t)offsetInRegion;
loc.dstCacheSegmentSize = (uint32_t)dstCacheSegmentSize;
loc.dstCacheFileSize = (uint32_t)copySize;
loc.copySegmentSize = (uint32_t)copySize;
- loc.srcSegmentIndex = segInfo.segmentIndex;
+ loc.srcSegmentIndex = segInfo.segIndex;
loc.parentRegion = &readExecuteRegion;
- dylib.cacheLocation[segInfo.segmentIndex] = loc;
+ dylib.cacheLocation[segInfo.segIndex] = loc;
offsetInRegion += loc.dstCacheSegmentSize;
});
}
@@ -560,49 +551,49 @@
continue;
__block uint64_t textSegVmAddr = 0;
- ((const Header*)dylib.input->mappedFile.mh)->forEachSegment(^(const Header::SegmentInfo& segInfo, uint64_t segSizeOfSections, uint32_t maxAlignOfSections, bool& stop) {
- if ( segInfo.segmentName == "__TEXT" )
- textSegVmAddr = segInfo.vmaddr;
- if ( segInfo.segmentName != "__TEXT_BOOT_EXEC" )
+ dylib.input->mappedFile.mh->forEachSegment(^(const dyld3::MachOFile::SegmentInfo& segInfo, bool& stop) {
+ if ( strcmp(segInfo.segName, "__TEXT") == 0 )
+ textSegVmAddr = segInfo.vmAddr;
+ if ( strcmp(segInfo.segName, "__TEXT_BOOT_EXEC") != 0 )
return;
- if ( segInfo.initProt != (VM_PROT_READ | VM_PROT_EXECUTE) )
+ if ( segInfo.protections != (VM_PROT_READ | VM_PROT_EXECUTE) )
return;
// We may have coalesced the sections at the end of this segment. In that case, shrink the segment to remove them.
__block size_t sizeOfSections = 0;
__block bool foundRemovedSection = false;
- ((const Header*)dylib.input->mappedFile.mh)->forEachSection(^(const Header::SectionInfo §Info, bool &stopSection) {
- if ( sectInfo.segmentName != segInfo.segmentName )
+ dylib.input->mappedFile.mh->forEachSection(^(const dyld3::MachOAnalyzer::SectionInfo §Info, bool malformedSectionRange, bool &stopSection) {
+ if (strcmp(sectInfo.segInfo.segName, segInfo.segName) != 0)
return;
- if ( dylib._coalescer.sectionWasObliterated(segInfo.segmentName, sectInfo.sectionName)) {
+ if ( dylib._coalescer.sectionWasObliterated(segInfo.segName, sectInfo.sectName)) {
foundRemovedSection = true;
} else {
- sizeOfSections = sectInfo.address + sectInfo.size - segInfo.vmaddr;
+ sizeOfSections = sectInfo.sectAddr + sectInfo.sectSize - segInfo.vmAddr;
}
});
if ( !foundRemovedSection )
- sizeOfSections = segSizeOfSections;
+ sizeOfSections = segInfo.sizeOfSections;
// kxld packs __TEXT_EXEC so we will do
// Note we align to at least 16-bytes as LDR's can scale up to 16 from their address
// and aligning them less than 16 would break that
- uint32_t minAlignmentP2 = getMinAlignment((const Header*)dylib.input->mappedFile.mh);
- offsetInRegion = align(offsetInRegion, std::max(maxAlignOfSections, 4U));
+ uint32_t minAlignmentP2 = getMinAlignment(dylib.input->mappedFile.mh);
+ offsetInRegion = align(offsetInRegion, std::max(segInfo.p2align, 4U));
offsetInRegion = align(offsetInRegion, minAlignmentP2);
size_t copySize = std::min((size_t)segInfo.fileSize, (size_t)sizeOfSections);
uint64_t dstCacheSegmentSize = align(sizeOfSections, minAlignmentP2);
SegmentMappingInfo loc;
- loc.srcSegment = (uint8_t*)dylib.input->mappedFile.mh + segInfo.vmaddr - textSegVmAddr;
- loc.segName = segInfo.segmentName;
+ loc.srcSegment = (uint8_t*)dylib.input->mappedFile.mh + segInfo.vmAddr - textSegVmAddr;
+ loc.segName = segInfo.segName;
loc.dstSegment = nullptr;
loc.dstCacheUnslidAddress = offsetInRegion; // This will be updated later once we've assigned addresses
loc.dstCacheFileOffset = (uint32_t)offsetInRegion;
loc.dstCacheSegmentSize = (uint32_t)dstCacheSegmentSize;
loc.dstCacheFileSize = (uint32_t)copySize;
loc.copySegmentSize = (uint32_t)copySize;
- loc.srcSegmentIndex = segInfo.segmentIndex;
+ loc.srcSegmentIndex = segInfo.segIndex;
loc.parentRegion = &textBootExecRegion;
- dylib.cacheLocation[segInfo.segmentIndex] = loc;
+ dylib.cacheLocation[segInfo.segIndex] = loc;
offsetInRegion += loc.dstCacheSegmentSize;
});
}
@@ -623,35 +614,33 @@
continue;
__block uint64_t textSegVmAddr = 0;
- ((const Header*)dylib.input->mappedFile.mh)->forEachSegment(^(const Header::SegmentInfo& segInfo, uint64_t sizeOfSections, uint32_t maxAlignOfSections, bool& stop) {
- if ( segInfo.segmentName == "__TEXT" )
- textSegVmAddr = segInfo.vmaddr;
- if ( (segInfo.initProt & VM_PROT_EXECUTE) != 0 )
+ dylib.input->mappedFile.mh->forEachSegment(^(const dyld3::MachOFile::SegmentInfo& segInfo, bool& stop) {
+ if ( strcmp(segInfo.segName, "__TEXT") == 0 )
+ textSegVmAddr = segInfo.vmAddr;
+ if ( (segInfo.protections & VM_PROT_EXECUTE) != 0 )
return;
- if ( ( segInfo.segmentName != "__DATA_CONST" )
- && ( segInfo.segmentName != "__PPLDATA_CONST" )
- && ( segInfo.segmentName != "__LASTDATA_CONST") )
- return;
- if ( segInfo.segmentName == "__LATE_CONST" )
+ if ( (strcmp(segInfo.segName, "__DATA_CONST") != 0)
+ && (strcmp(segInfo.segName, "__PPLDATA_CONST") != 0)
+ && (strcmp(segInfo.segName, "__LASTDATA_CONST") != 0) )
return;
// kxld packs __DATA_CONST so we will do
- uint32_t minAlignmentP2 = getMinAlignment((const Header*)dylib.input->mappedFile.mh);
- offsetInRegion = align(offsetInRegion, maxAlignOfSections);
+ uint32_t minAlignmentP2 = getMinAlignment(dylib.input->mappedFile.mh);
+ offsetInRegion = align(offsetInRegion, segInfo.p2align);
offsetInRegion = align(offsetInRegion, minAlignmentP2);
- size_t copySize = std::min((size_t)segInfo.fileSize, (size_t)sizeOfSections);
- uint64_t dstCacheSegmentSize = align(sizeOfSections, minAlignmentP2);
+ size_t copySize = std::min((size_t)segInfo.fileSize, (size_t)segInfo.sizeOfSections);
+ uint64_t dstCacheSegmentSize = align(segInfo.sizeOfSections, minAlignmentP2);
SegmentMappingInfo loc;
- loc.srcSegment = (uint8_t*)dylib.input->mappedFile.mh + segInfo.vmaddr - textSegVmAddr;
- loc.segName = segInfo.segmentName;
+ loc.srcSegment = (uint8_t*)dylib.input->mappedFile.mh + segInfo.vmAddr - textSegVmAddr;
+ loc.segName = segInfo.segName;
loc.dstSegment = nullptr;
loc.dstCacheUnslidAddress = offsetInRegion; // This will be updated later once we've assigned addresses
loc.dstCacheFileOffset = (uint32_t)offsetInRegion;
loc.dstCacheSegmentSize = (uint32_t)dstCacheSegmentSize;
loc.dstCacheFileSize = (uint32_t)copySize;
loc.copySegmentSize = (uint32_t)copySize;
- loc.srcSegmentIndex = segInfo.segmentIndex;
+ loc.srcSegmentIndex = segInfo.segIndex;
loc.parentRegion = &dataConstRegion;
- dylib.cacheLocation[segInfo.segmentIndex] = loc;
+ dylib.cacheLocation[segInfo.segIndex] = loc;
offsetInRegion += loc.dstCacheSegmentSize;
});
}
@@ -664,7 +653,7 @@
dataConstRegion.name = "__DATA_CONST";
}
- // __LATE_CONST segments
+ // __DATA_SPTM segments
{
__block uint64_t offsetInRegion = 0;
for (DylibInfo& dylib : sortedDylibs) {
@@ -672,75 +661,30 @@
continue;
__block uint64_t textSegVmAddr = 0;
- ((const Header*)dylib.input->mappedFile.mh)->forEachSegment(^(const Header::SegmentInfo& segInfo, uint64_t sizeOfSections, uint32_t maxAlignOfSections, bool& stop) {
- if ( segInfo.segmentName == "__TEXT" )
- textSegVmAddr = segInfo.vmaddr;
- if ( (segInfo.initProt & VM_PROT_EXECUTE) != 0 )
+ dylib.input->mappedFile.mh->forEachSegment(^(const dyld3::MachOFile::SegmentInfo& segInfo, bool& stop) {
+ if ( strcmp(segInfo.segName, "__TEXT") == 0 )
+ textSegVmAddr = segInfo.vmAddr;
+ if ( (segInfo.protections & VM_PROT_EXECUTE) != 0 )
return;
- if ( segInfo.segmentName != "__LATE_CONST" )
+ if ( (strcmp(segInfo.segName, "__DATA_SPTM") != 0) )
return;
- // pack __LATE_CONST
- uint32_t minAlignmentP2 = getMinAlignment((const Header*)dylib.input->mappedFile.mh);
- offsetInRegion = align(offsetInRegion, maxAlignOfSections);
+ uint32_t minAlignmentP2 = getMinAlignment(dylib.input->mappedFile.mh);
+ offsetInRegion = align(offsetInRegion, segInfo.p2align);
offsetInRegion = align(offsetInRegion, minAlignmentP2);
- size_t copySize = std::min((size_t)segInfo.fileSize, (size_t)sizeOfSections);
- uint64_t dstCacheSegmentSize = align(sizeOfSections, minAlignmentP2);
+ size_t copySize = std::min((size_t)segInfo.fileSize, (size_t)segInfo.sizeOfSections);
+ uint64_t dstCacheSegmentSize = align(segInfo.sizeOfSections, minAlignmentP2);
SegmentMappingInfo loc;
- loc.srcSegment = (uint8_t*)dylib.input->mappedFile.mh + segInfo.vmaddr - textSegVmAddr;
- loc.segName = segInfo.segmentName;
+ loc.srcSegment = (uint8_t*)dylib.input->mappedFile.mh + segInfo.vmAddr - textSegVmAddr;
+ loc.segName = segInfo.segName;
loc.dstSegment = nullptr;
loc.dstCacheUnslidAddress = offsetInRegion; // This will be updated later once we've assigned addresses
loc.dstCacheFileOffset = (uint32_t)offsetInRegion;
loc.dstCacheSegmentSize = (uint32_t)dstCacheSegmentSize;
loc.dstCacheFileSize = (uint32_t)copySize;
loc.copySegmentSize = (uint32_t)copySize;
- loc.srcSegmentIndex = segInfo.segmentIndex;
- loc.parentRegion = &lateConstRegion;
- dylib.cacheLocation[segInfo.segmentIndex] = loc;
- offsetInRegion += loc.dstCacheSegmentSize;
- });
- }
-
- // align r/o region end
- lateConstRegion.bufferSize = align(offsetInRegion, 14);
- lateConstRegion.sizeInUse = lateConstRegion.bufferSize;
- lateConstRegion.initProt = VM_PROT_READ;
- lateConstRegion.maxProt = VM_PROT_READ;
- lateConstRegion.name = "__LATE_CONST";
- }
-
- // __DATA_SPTM segments
- {
- __block uint64_t offsetInRegion = 0;
- for (DylibInfo& dylib : sortedDylibs) {
- if (!dylib.input->mappedFile.mh->hasSplitSeg())
- continue;
-
- __block uint64_t textSegVmAddr = 0;
- ((const Header*)dylib.input->mappedFile.mh)->forEachSegment(^(const Header::SegmentInfo& segInfo, uint64_t sizeOfSections, uint32_t maxAlignOfSections, bool& stop) {
- if ( segInfo.segmentName == "__TEXT" )
- textSegVmAddr = segInfo.vmaddr;
- if ( (segInfo.initProt & VM_PROT_EXECUTE) != 0 )
- return;
- if ( segInfo.segmentName != "__DATA_SPTM" )
- return;
- uint32_t minAlignmentP2 = getMinAlignment((const Header*)dylib.input->mappedFile.mh);
- offsetInRegion = align(offsetInRegion, maxAlignOfSections);
- offsetInRegion = align(offsetInRegion, minAlignmentP2);
- size_t copySize = std::min((size_t)segInfo.fileSize, (size_t)sizeOfSections);
- uint64_t dstCacheSegmentSize = align(sizeOfSections, minAlignmentP2);
- SegmentMappingInfo loc;
- loc.srcSegment = (uint8_t*)dylib.input->mappedFile.mh + segInfo.vmaddr - textSegVmAddr;
- loc.segName = segInfo.segmentName;
- loc.dstSegment = nullptr;
- loc.dstCacheUnslidAddress = offsetInRegion; // This will be updated later once we've assigned addresses
- loc.dstCacheFileOffset = (uint32_t)offsetInRegion;
- loc.dstCacheSegmentSize = (uint32_t)dstCacheSegmentSize;
- loc.dstCacheFileSize = (uint32_t)copySize;
- loc.copySegmentSize = (uint32_t)copySize;
- loc.srcSegmentIndex = segInfo.segmentIndex;
+ loc.srcSegmentIndex = segInfo.segIndex;
loc.parentRegion = &dataSptmRegion;
- dylib.cacheLocation[segInfo.segmentIndex] = loc;
+ dylib.cacheLocation[segInfo.segIndex] = loc;
offsetInRegion += loc.dstCacheSegmentSize;
});
}
@@ -772,36 +716,35 @@
continue;
__block uint64_t textSegVmAddr = 0;
- ((const Header*)dylib.input->mappedFile.mh)->forEachSegment(^(const Header::SegmentInfo& segInfo, uint64_t sizeOfSections, uint32_t maxAlignOfSections, bool& stop) {
- if ( segInfo.segmentName == "__TEXT" )
- textSegVmAddr = segInfo.vmaddr;
- if ( segInfo.segmentName == "__HIB" )
+ dylib.input->mappedFile.mh->forEachSegment(^(const dyld3::MachOFile::SegmentInfo& segInfo, bool& stop) {
+ if ( strcmp(segInfo.segName, "__TEXT") == 0 )
+ textSegVmAddr = segInfo.vmAddr;
+ if ( strcmp(segInfo.segName, "__HIB") == 0 )
return;
- if ( ( segInfo.segmentName == "__DATA_CONST" )
- || ( segInfo.segmentName == "__PPLDATA_CONST" )
- || ( segInfo.segmentName == "__LASTDATA_CONST" )
- || ( segInfo.segmentName == "__LATE_CONST" ) )
+ if ( (strcmp(segInfo.segName, "__DATA_CONST") == 0)
+ || (strcmp(segInfo.segName, "__PPLDATA_CONST") == 0)
+ || (strcmp(segInfo.segName, "__LASTDATA_CONST") == 0) )
return;
- if ( segInfo.initProt != (VM_PROT_READ | VM_PROT_WRITE) )
+ if ( segInfo.protections != (VM_PROT_READ | VM_PROT_WRITE) )
return;
// kxld packs __DATA so we will do
- uint32_t minAlignmentP2 = getMinAlignment((const Header*)dylib.input->mappedFile.mh);
- offsetInRegion = align(offsetInRegion, maxAlignOfSections);
+ uint32_t minAlignmentP2 = getMinAlignment(dylib.input->mappedFile.mh);
+ offsetInRegion = align(offsetInRegion, segInfo.p2align);
offsetInRegion = align(offsetInRegion, minAlignmentP2);
- size_t copySize = std::min((size_t)segInfo.fileSize, (size_t)sizeOfSections);
- uint64_t dstCacheSegmentSize = align(sizeOfSections, minAlignmentP2);
+ size_t copySize = std::min((size_t)segInfo.fileSize, (size_t)segInfo.sizeOfSections);
+ uint64_t dstCacheSegmentSize = align(segInfo.sizeOfSections, minAlignmentP2);
SegmentMappingInfo loc;
- loc.srcSegment = (uint8_t*)dylib.input->mappedFile.mh + segInfo.vmaddr - textSegVmAddr;
- loc.segName = segInfo.segmentName;
+ loc.srcSegment = (uint8_t*)dylib.input->mappedFile.mh + segInfo.vmAddr - textSegVmAddr;
+ loc.segName = segInfo.segName;
loc.dstSegment = nullptr;
loc.dstCacheUnslidAddress = offsetInRegion; // This will be updated later once we've assigned addresses
loc.dstCacheFileOffset = (uint32_t)offsetInRegion;
loc.dstCacheSegmentSize = (uint32_t)dstCacheSegmentSize;
loc.dstCacheFileSize = (uint32_t)copySize;
loc.copySegmentSize = (uint32_t)copySize;
- loc.srcSegmentIndex = segInfo.segmentIndex;
+ loc.srcSegmentIndex = segInfo.segIndex;
loc.parentRegion = &readWriteRegion;
- dylib.cacheLocation[segInfo.segmentIndex] = loc;
+ dylib.cacheLocation[segInfo.segIndex] = loc;
offsetInRegion += loc.dstCacheSegmentSize;
});
}
@@ -823,27 +766,27 @@
__block uint64_t textSegVmAddr = 0;
__block uint64_t hibernateAddress = 0;
- ((const Header*)dylib.input->mappedFile.mh)->forEachSegment(^(const Header::SegmentInfo& segInfo, uint64_t sizeOfSections, uint32_t maxAlignOfSections, bool& stop) {
- if ( segInfo.segmentName == "__TEXT" )
- textSegVmAddr = segInfo.vmaddr;
- if ( segInfo.segmentName != "__HIB" )
+ dylib.input->mappedFile.mh->forEachSegment(^(const dyld3::MachOFile::SegmentInfo& segInfo, bool& stop) {
+ if ( strcmp(segInfo.segName, "__TEXT") == 0 )
+ textSegVmAddr = segInfo.vmAddr;
+ if ( strcmp(segInfo.segName, "__HIB") != 0 )
return;
- size_t copySize = std::min((size_t)segInfo.fileSize, (size_t)sizeOfSections);
+ size_t copySize = std::min((size_t)segInfo.fileSize, (size_t)segInfo.sizeOfSections);
SegmentMappingInfo loc;
- loc.srcSegment = (uint8_t*)dylib.input->mappedFile.mh + segInfo.vmaddr - textSegVmAddr;
- loc.segName = segInfo.segmentName;
+ loc.srcSegment = (uint8_t*)dylib.input->mappedFile.mh + segInfo.vmAddr - textSegVmAddr;
+ loc.segName = segInfo.segName;
loc.dstSegment = nullptr;
loc.dstCacheUnslidAddress = offsetInRegion; // This will be updated later once we've assigned addresses
loc.dstCacheFileOffset = (uint32_t)offsetInRegion;
- loc.dstCacheSegmentSize = (uint32_t)segInfo.vmsize;
+ loc.dstCacheSegmentSize = (uint32_t)segInfo.vmSize;
loc.dstCacheFileSize = (uint32_t)copySize;
loc.copySegmentSize = (uint32_t)copySize;
- loc.srcSegmentIndex = segInfo.segmentIndex;
+ loc.srcSegmentIndex = segInfo.segIndex;
loc.parentRegion = &hibernateRegion;
- dylib.cacheLocation[segInfo.segmentIndex] = loc;
+ dylib.cacheLocation[segInfo.segIndex] = loc;
offsetInRegion += loc.dstCacheSegmentSize;
- hibernateAddress = segInfo.vmaddr;
+ hibernateAddress = segInfo.vmAddr;
});
if ( offsetInRegion != 0 ) {
@@ -880,31 +823,31 @@
continue;
__block uint64_t textSegVmAddr = 0;
- ((const Header*)dylib.input->mappedFile.mh)->forEachSegment(^(const Header::SegmentInfo& segInfo, bool& stop) {
- if ( segInfo.segmentName == "__TEXT" )
- textSegVmAddr = segInfo.vmaddr;
- if ( segInfo.segmentName == "__LINKEDIT" )
+ dylib.input->mappedFile.mh->forEachSegment(^(const dyld3::MachOFile::SegmentInfo& segInfo, bool& stop) {
+ if ( strcmp(segInfo.segName, "__TEXT") == 0 )
+ textSegVmAddr = segInfo.vmAddr;
+ if ( strcmp(segInfo.segName, "__LINKEDIT") == 0 )
return;
nonSplitSegRegions.emplace_back();
- nonSplitSegRegions.back().initProt = segInfo.initProt;
- nonSplitSegRegions.back().maxProt = segInfo.maxProt;
+ nonSplitSegRegions.back().initProt = segInfo.protections;
+ nonSplitSegRegions.back().maxProt = segInfo.protections;
nonSplitSegRegions.back().name = "__REGION" + std::to_string(nonSplitSegRegions.size() - 1);
// Note we don't align the region offset as we have no split seg
uint64_t offsetInRegion = 0;
SegmentMappingInfo loc;
- loc.srcSegment = (uint8_t*)dylib.input->mappedFile.mh + segInfo.vmaddr - textSegVmAddr;
- loc.segName = segInfo.segmentName;
+ loc.srcSegment = (uint8_t*)dylib.input->mappedFile.mh + segInfo.vmAddr - textSegVmAddr;
+ loc.segName = segInfo.segName;
loc.dstSegment = nullptr;
loc.dstCacheUnslidAddress = offsetInRegion; // This will be updated later once we've assigned addresses
loc.dstCacheFileOffset = (uint32_t)offsetInRegion;
- loc.dstCacheSegmentSize = (uint32_t)segInfo.vmsize;
+ loc.dstCacheSegmentSize = (uint32_t)segInfo.vmSize;
loc.dstCacheFileSize = (uint32_t)segInfo.fileSize;
loc.copySegmentSize = (uint32_t)segInfo.fileSize;
- loc.srcSegmentIndex = segInfo.segmentIndex;
+ loc.srcSegmentIndex = segInfo.segIndex;
loc.parentRegion = &nonSplitSegRegions.back();
- dylib.cacheLocation[segInfo.segmentIndex] = loc;
+ dylib.cacheLocation[segInfo.segIndex] = loc;
offsetInRegion += loc.dstCacheSegmentSize;
// record non-split seg region end
@@ -996,9 +939,9 @@
// Use the size of the TEXT sections in the cache. This is required as we pack segments
__block uint64_t textSegSize = 0;
if ( info.ma != nullptr ) {
- ((const Header*)info.ma)->forEachSegment(^(const Header::SegmentInfo& segInfo, uint64_t sizeOfSections, uint32_t maxAlignOfSections, bool& stop) {
- if ( segInfo.segmentName == "__TEXT" )
- textSegSize = sizeOfSections == 0 ? segInfo.fileSize : sizeOfSections;
+ info.ma->forEachSegment(^(const dyld3::MachOFile::SegmentInfo& segInfo, bool& stop) {
+ if ( strcmp(segInfo.segName, "__TEXT") == 0 )
+ textSegSize = segInfo.sizeOfSections == 0 ? segInfo.fileSize : segInfo.sizeOfSections;
});
}
if (textSegSize != 0) {
@@ -1072,7 +1015,7 @@
// The pageable/aux KCs should embed the UUID of the base kernel collection
if ( existingKernelCollection != nullptr ) {
uuid_t uuid = {};
- bool foundUUID = ((mach_o::Header*)existingKernelCollection)->getUuid(uuid);
+ bool foundUUID = existingKernelCollection->getUuid(uuid);
if ( !foundUUID ) {
_diagnostics.error("Could not find UUID in base kernel collection");
return;
@@ -1085,7 +1028,7 @@
// The aux KC should embed the UUID of the pageable kernel collection if we have one
if ( pageableKernelCollection != nullptr ) {
uuid_t uuid = {};
- bool foundUUID = ((mach_o::Header*)pageableKernelCollection)->getUuid(uuid);
+ bool foundUUID = pageableKernelCollection->getUuid(uuid);
if ( !foundUUID ) {
_diagnostics.error("Could not find UUID in pageable kernel collection");
return;
@@ -1123,28 +1066,28 @@
__block uint64_t offsetInRegion = 0;
for (DylibInfo& dylib : sortedDylibs) {
__block uint64_t textSegVmAddr = 0;
- ((const Header*)dylib.input->mappedFile.mh)->forEachSegment(^(const Header::SegmentInfo& segInfo, uint64_t sizeOfSections, uint32_t maxAlignOfSections, bool& stop) {
- if ( segInfo.segmentName == "__TEXT" )
- textSegVmAddr = segInfo.vmaddr;
- if ( segInfo.initProt != VM_PROT_READ )
+ dylib.input->mappedFile.mh->forEachSegment(^(const dyld3::MachOFile::SegmentInfo& segInfo, bool& stop) {
+ if ( strcmp(segInfo.segName, "__TEXT") == 0 )
+ textSegVmAddr = segInfo.vmAddr;
+ if ( segInfo.protections != VM_PROT_READ )
return;
- if ( segInfo.segmentName != "__LINKINFO" )
+ if ( strcmp(segInfo.segName, "__LINKINFO") != 0 )
return;
// Keep segments 4K or more aligned
- offsetInRegion = align(offsetInRegion, std::max(maxAlignOfSections, 12U));
- size_t copySize = std::min((size_t)segInfo.fileSize, (size_t)sizeOfSections);
+ offsetInRegion = align(offsetInRegion, std::max((int)segInfo.p2align, (int)12));
+ size_t copySize = std::min((size_t)segInfo.fileSize, (size_t)segInfo.sizeOfSections);
SegmentMappingInfo loc;
- loc.srcSegment = (uint8_t*)dylib.input->mappedFile.mh + segInfo.vmaddr - textSegVmAddr;
- loc.segName = segInfo.segmentName;
+ loc.srcSegment = (uint8_t*)dylib.input->mappedFile.mh + segInfo.vmAddr - textSegVmAddr;
+ loc.segName = segInfo.segName;
loc.dstSegment = nullptr;
loc.dstCacheUnslidAddress = offsetInRegion; // This will be updated later once we've assigned addresses
loc.dstCacheFileOffset = (uint32_t)offsetInRegion;
- loc.dstCacheSegmentSize = (uint32_t)align(sizeOfSections, 12);
+ loc.dstCacheSegmentSize = (uint32_t)align(segInfo.sizeOfSections, 12);
loc.dstCacheFileSize = (uint32_t)copySize;
loc.copySegmentSize = (uint32_t)copySize;
- loc.srcSegmentIndex = segInfo.segmentIndex;
+ loc.srcSegmentIndex = segInfo.segIndex;
loc.parentRegion = &_readOnlyRegion;
- dylib.cacheLocation[segInfo.segmentIndex] = loc;
+ dylib.cacheLocation[segInfo.segIndex] = loc;
offsetInRegion += loc.dstCacheSegmentSize;
});
}
@@ -1156,15 +1099,15 @@
// Do all __LINKEDIT, regardless of split seg
for (DylibInfo& dylib : sortedDylibs) {
__block uint64_t textSegVmAddr = 0;
- ((const Header*)dylib.input->mappedFile.mh)->forEachSegment(^(const Header::SegmentInfo& segInfo, uint64_t sizeOfSections, uint32_t maxAlignOfSections, bool& stop) {
- if ( segInfo.segmentName == "__TEXT" )
- textSegVmAddr = segInfo.vmaddr;
- if ( segInfo.initProt != VM_PROT_READ )
+ dylib.input->mappedFile.mh->forEachSegment(^(const dyld3::MachOFile::SegmentInfo& segInfo, bool& stop) {
+ if ( strcmp(segInfo.segName, "__TEXT") == 0 )
+ textSegVmAddr = segInfo.vmAddr;
+ if ( segInfo.protections != VM_PROT_READ )
return;
- if ( segInfo.segmentName != "__LINKEDIT" )
+ if ( strcmp(segInfo.segName, "__LINKEDIT") != 0 )
return;
// Keep segments 4K or more aligned
- offsetInRegion = align(offsetInRegion, std::max(maxAlignOfSections, 12U));
+ offsetInRegion = align(offsetInRegion, std::max((int)segInfo.p2align, (int)12));
size_t copySize = segInfo.fileSize;
// HACK: When we adjust LINKEDIT, we may grow function starts. This is because the kernel and kexts
@@ -1175,17 +1118,17 @@
const uint32_t extraLinkeditSpace = 16;
SegmentMappingInfo loc;
- loc.srcSegment = (uint8_t*)dylib.input->mappedFile.mh + segInfo.vmaddr - textSegVmAddr;
- loc.segName = segInfo.segmentName;
+ loc.srcSegment = (uint8_t*)dylib.input->mappedFile.mh + segInfo.vmAddr - textSegVmAddr;
+ loc.segName = segInfo.segName;
loc.dstSegment = nullptr;
loc.dstCacheUnslidAddress = offsetInRegion; // This will be updated later once we've assigned addresses
loc.dstCacheFileOffset = (uint32_t)offsetInRegion;
loc.dstCacheSegmentSize = (uint32_t)align(copySize + extraLinkeditSpace, 12);
loc.dstCacheFileSize = (uint32_t)copySize + extraLinkeditSpace;
loc.copySegmentSize = (uint32_t)copySize;
- loc.srcSegmentIndex = segInfo.segmentIndex;
+ loc.srcSegmentIndex = segInfo.segIndex;
loc.parentRegion = &_readOnlyRegion;
- dylib.cacheLocation[segInfo.segmentIndex] = loc;
+ dylib.cacheLocation[segInfo.segIndex] = loc;
offsetInRegion += loc.dstCacheSegmentSize;
});
}
@@ -1203,11 +1146,13 @@
// The pageableKC (and sometimes auxKC) has 1 LC_DYLD_CHAINED_FIXUPS per kext
// while other KCs have 1 for the whole KC.
// It also tracks each segment in each kext for chained fixups, not the segments on the KC itself
- uint64_t numSegmentsForChainedFixups = 0;
+ __block uint64_t numSegmentsForChainedFixups = 0;
uint64_t numChainedFixupHeaders = 0;
if ( fixupsArePerKext() ) {
for (DylibInfo& dylib : sortedDylibs) {
- numSegmentsForChainedFixups += ((const Header*)dylib.input->mappedFile.mh)->segmentCount();
+ dylib.input->mappedFile.mh->forEachSegment(^(const dyld3::MachOFile::SegmentInfo& segInfo, bool& stop) {
+ ++numSegmentsForChainedFixups;
+ });
}
numChainedFixupHeaders = sortedDylibs.size();
@@ -1223,8 +1168,6 @@
uint64_t numBytesForPageStarts = 0;
if ( dataConstRegion.sizeInUse != 0 )
numBytesForPageStarts += sizeof(dyld_chained_starts_in_segment) + (sizeof(uint16_t) * numWritablePagesToFixup(dataConstRegion.bufferSize));
- if ( lateConstRegion.sizeInUse != 0 )
- numBytesForPageStarts += sizeof(dyld_chained_starts_in_segment) + (sizeof(uint16_t) * numWritablePagesToFixup(lateConstRegion.bufferSize));
if ( dataSptmRegion.sizeInUse != 0 )
numBytesForPageStarts += sizeof(dyld_chained_starts_in_segment) + (sizeof(uint16_t) * numWritablePagesToFixup(dataSptmRegion.bufferSize));
if ( branchGOTsRegion.bufferSize != 0 )
@@ -1600,7 +1543,7 @@
DylibSymbols& kernelDylibSymbols = dylibsToSymbols[kernelID];
SymbolLocation symbolLocation = findVTablePatchingSymbol("__ZTV11OSMetaClass", kernelDylibSymbols);
if ( symbolLocation.found() ) {
- baseMetaClassVTableLoc = (uint8_t*)kernelMA + (symbolLocation.vmAddr - ((const Header*)kernelMA)->preferredLoadAddress());
+ baseMetaClassVTableLoc = (uint8_t*)kernelMA + (symbolLocation.vmAddr - kernelMA->preferredLoadAddress());
VTable& vtable = vtables[baseMetaClassVTableLoc];
vtable.ma = kernelMA;
@@ -1642,10 +1585,10 @@
// And add classic if we have them
existingKernelCollection->forEachRebase(diags, ^(const char *opcodeName, const dyld3::MachOAnalyzer::LinkEditInfo &leInfo,
- const Header::SegmentInfo *segments,
+ const dyld3::MachOAnalyzer::SegmentInfo *segments,
bool segIndexSet, uint32_t ptrSize, uint8_t segmentIndex,
uint64_t segmentOffset, dyld3::MachOAnalyzer::Rebase kind, bool &stop) {
- uint64_t rebaseVmAddr = segments[segmentIndex].vmaddr + segmentOffset;
+ uint64_t rebaseVmAddr = segments[segmentIndex].vmAddr + segmentOffset;
uint64_t runtimeOffset = rebaseVmAddr - kernelBaseAddress;
const uint8_t* fixupLoc = kernelBasePointer + runtimeOffset;
uint64_t targetVMAddr = 0;
@@ -1711,7 +1654,7 @@
bool kernelUsesClassicRelocs = existingKernelCollection->usesClassicRelocationsInKernelCollection();
existingKernelCollection->forEachDylib(diags, ^(const dyld3::MachOAnalyzer *ma, const char *dylibID, bool &stop) {
- uint64_t loadAddress = ((const Header*)ma)->preferredLoadAddress();
+ uint64_t loadAddress = ma->preferredLoadAddress();
auto visitBaseKernelCollectionSymbols = ^(const char *symbolName, uint64_t n_value) {
if ( strstr(symbolName, superMetaclassPointerToken) == nullptr )
@@ -1932,7 +1875,7 @@
}
pageableKernelCollection->forEachDylib(diags, ^(const dyld3::MachOAnalyzer *ma, const char *dylibID, bool &stop) {
- uint64_t loadAddress = ((const Header*)ma)->preferredLoadAddress();
+ uint64_t loadAddress = ma->preferredLoadAddress();
auto visitPageableKernelCollectionSymbols = ^(const char *symbolName, uint64_t n_value) {
if ( strstr(symbolName, superMetaclassPointerToken) == nullptr )
return;
@@ -2165,7 +2108,7 @@
Diagnostics& dylibDiags = *dylib.diags;
const std::vector<std::string>& dependencies = dylib.dependencies;
- uint64_t loadAddress = ((const Header*)ma)->preferredLoadAddress();
+ uint64_t loadAddress = ma->preferredLoadAddress();
bool alreadyPatched = (ma == kernelMA);
auto visitSymbols = ^(const char *symbolName, uint64_t n_value) {
if ( strstr(symbolName, superMetaclassPointerToken) == nullptr )
@@ -2861,6 +2804,8 @@
return;
}
}
+
+ // uint64_t baseAddress = ma->preferredLoadAddress();
ma->withChainStarts(dylibDiag, 0, ^(const dyld_chained_starts_in_image* starts) {
ma->forEachFixupInAllChains(dylibDiag, starts, false, ^(dyld3::MachOLoaded::ChainedFixupPointerOnDisk* fixupLoc, const dyld_chained_starts_in_segment* segInfo, bool& stop) {
@@ -2972,7 +2917,7 @@
__block bool foundUseOfMagicSymbol = false;
__block bool foundMissingWeakImport = false;
- const uint64_t loadAddress = ((const Header*)ma)->preferredLoadAddress();
+ const uint64_t loadAddress = ma->preferredLoadAddress();
ma->forEachBind(dylibDiag, ^(uint64_t runtimeOffset, int libOrdinal, uint8_t bindType,
const char *symbolName, bool weakImport, bool lazyBind, uint64_t addend, bool &stop) {
// printf("Bind at 0x%llx to '%s'\n", runtimeOffset, symbolName);
@@ -3251,7 +3196,7 @@
std::map<const uint8_t*, const VTableBindSymbol>& missingBindLocations)
{
// We only patch vtables on macOS. Luckily the platform is in the kernel binary
- if ( !((mach_o::Header*)kernelMA)->builtForPlatform(mach_o::Platform::macOS) )
+ if ( !kernelMA->builtForPlatform(dyld3::Platform::macOS) )
return;
auto vtablePatcherOwner = std::make_unique<VTablePatcher>(numFixupLevels);
@@ -3265,13 +3210,13 @@
// The kernel base address is still __TEXT, even if __DATA or __HIB is mapped prior to that.
// The loader may have loaded something before __TEXT, but the existingKernelCollection pointer still corresponds to __TEXT
__block uint64_t baseAddress = ~0ULL;
- ((const Header*)existingKernelCollection)->forEachSegment(^(const Header::SegmentInfo& info, bool& stop) {
- baseAddress = std::min(baseAddress, info.vmaddr);
+ existingKernelCollection->forEachSegment(^(const dyld3::MachOAnalyzer::SegmentInfo& info, bool& stop) {
+ baseAddress = std::min(baseAddress, info.vmAddr);
});
// The existing collection is a pointer to the mach_header for the baseKC, but __HIB and other segments may be before that
// Offset those here
- uint64_t basePointerOffset = ((const Header*)existingKernelCollection)->preferredLoadAddress() - baseAddress;
+ uint64_t basePointerOffset = existingKernelCollection->preferredLoadAddress() - baseAddress;
const uint8_t* basePointer = (uint8_t*)existingKernelCollection - basePointerOffset;
vtablePatcher.addKernelCollection(existingKernelCollection, Options::AppCacheKind::kernel,
@@ -3283,13 +3228,13 @@
// The kernel base address is still __TEXT, even if __DATA or __HIB is mapped prior to that.
// The loader may have loaded something before __TEXT, but the existingKernelCollection pointer still corresponds to __TEXT
__block uint64_t baseAddress = ~0ULL;
- ((const Header*)pageableKernelCollection)->forEachSegment(^(const Header::SegmentInfo& info, bool& stop) {
- baseAddress = std::min(baseAddress, info.vmaddr);
+ pageableKernelCollection->forEachSegment(^(const dyld3::MachOAnalyzer::SegmentInfo& info, bool& stop) {
+ baseAddress = std::min(baseAddress, info.vmAddr);
});
// The existing collection is a pointer to the mach_header for the baseKC, but __HIB and other segments may be before that
// Offset those here
- uint64_t basePointerOffset = ((const Header*)pageableKernelCollection)->preferredLoadAddress() - baseAddress;
+ uint64_t basePointerOffset = pageableKernelCollection->preferredLoadAddress() - baseAddress;
const uint8_t* basePointer = (uint8_t*)pageableKernelCollection - basePointerOffset;
vtablePatcher.addKernelCollection(pageableKernelCollection, Options::AppCacheKind::pageableKC,
@@ -3829,7 +3774,7 @@
}
// Emit branch stubs
- const uint64_t loadAddress = ((const Header*)dylibFixup.ma)->preferredLoadAddress();
+ const uint64_t loadAddress = dylibFixup.ma->preferredLoadAddress();
for (const DylibFixups::BranchStubData& branchData : dylibFixup.branchStubs) {
// Branching from the auxKC to baseKC. ld64 doesn't emit a stub in x86_64 kexts
// so we need to synthesize one now
@@ -3900,20 +3845,20 @@
forEachCacheDylib(^(const dyld3::MachOAnalyzer *ma, const std::string &dylibID, DylibStripMode stripMode,
const std::vector<std::string> &dependencies, Diagnostics& dylibDiag, bool &stopDylib) {
intptr_t slide = ma->getSlide();
- ((const Header*)ma)->forEachSection(^(const Header::SectionInfo §Info,
- bool &stopSection) {
- const uint8_t* content = (uint8_t*)(sectInfo.address + slide);
+ ma->forEachSection(^(const dyld3::MachOAnalyzer::SectionInfo §Info,
+ bool malformedSectionRange, bool &stopSection) {
+ const uint8_t* content = (uint8_t*)(sectInfo.sectAddr + slide);
const uint8_t* start = (uint8_t*)content;
- const uint8_t* end = start + sectInfo.size;
+ const uint8_t* end = start + sectInfo.sectSize;
if ( (missingBindLoc >= start) && (missingBindLoc < end) ) {
+ std::string segmentName = sectInfo.segInfo.segName;
+ std::string sectionName = sectInfo.sectName;
uint64_t sectionOffset = (missingBindLoc - start);
-
- dylibDiag.error("Failed to bind '%s' in '%s' (at offset 0x%llx in %.*s, %.*s) as "
+
+ dylibDiag.error("Failed to bind '%s' in '%s' (at offset 0x%llx in %s, %s) as "
"could not find a kext which exports this symbol",
missingBind.symbolName.c_str(), missingBind.binaryID.data(),
- sectionOffset,
- (int)sectInfo.segmentName.size(), sectInfo.segmentName.data(),
- (int)sectInfo.sectionName.size(), sectInfo.sectionName.data());
+ sectionOffset, segmentName.c_str(), sectionName.c_str());
reportedError = true;
stopSection = true;
@@ -3989,23 +3934,23 @@
if ( header.dynSymbolTable != nullptr ) {
classicRelocsBufferStart = byteBuffer.begin();
- const Header* cacheMH = (const Header*)header.header;
+ dyld3::MachOAnalyzer* cacheMA = (dyld3::MachOAnalyzer*)header.header;
__block uint64_t localRelocBaseAddress = 0;
- cacheMH->forEachSegment(^(const Header::SegmentInfo &info, bool &stop) {
- if ( info.initProt & VM_PROT_WRITE ) {
- localRelocBaseAddress = info.vmaddr;
+ cacheMA->forEachSegment(^(const dyld3::MachOAnalyzer::SegmentInfo &info, bool &stop) {
+ if ( info.protections & VM_PROT_WRITE ) {
+ localRelocBaseAddress = info.vmAddr;
stop = true;
}
});
const std::vector<void*> allRebaseTargets = _aslrTracker.getRebaseTargets();
- const Header* kernelMH = (const Header*)getKernelStaticExecutableFromCache();
- kernelMH->forEachSegment(^(const Header::SegmentInfo &info, bool &stop) {
+ const dyld3::MachOAnalyzer* kernelMA = getKernelStaticExecutableFromCache();
+ kernelMA->forEachSegment(^(const dyld3::MachOAnalyzer::SegmentInfo &info, bool &stop) {
std::vector<void*> segmentRebaseTargets;
- uint64_t segmentVMOffset = info.vmaddr - cacheBaseAddress;
+ uint64_t segmentVMOffset = info.vmAddr - cacheBaseAddress;
const uint8_t* segmentStartAddr = (const uint8_t*)(_fullAllocatedBuffer + segmentVMOffset);
- const uint8_t* segmentEndAddr = (const uint8_t*)(segmentStartAddr + info.vmsize);
+ const uint8_t* segmentEndAddr = (const uint8_t*)(segmentStartAddr + info.vmSize);
for (void* target : allRebaseTargets) {
if ( (target >= segmentStartAddr) && (target < segmentEndAddr) ) {
segmentRebaseTargets.push_back(target);
@@ -4017,7 +3962,7 @@
uint64_t targetSegmentOffset = (uint64_t)target - (uint64_t)segmentStartAddr;
//printf("Target: %s + 0x%llx: %p\n", info.segName, targetSegmentOffset, target);
- uint64_t offsetFromBaseAddress = (info.vmaddr + targetSegmentOffset) - localRelocBaseAddress;
+ uint64_t offsetFromBaseAddress = (info.vmAddr + targetSegmentOffset) - localRelocBaseAddress;
relocation_info* reloc = (relocation_info*)byteBuffer.makeSpace(sizeof(relocation_info));
reloc->r_address = (uint32_t)offsetFromBaseAddress;
reloc->r_symbolnum = 0;
@@ -4060,8 +4005,8 @@
assert(existingKernelCollection != nullptr);
// The auxKC is mapped with __DATA first, so we need to get either the __DATA or __TEXT depending on what is earliest
__block uint64_t baseAddress = ~0ULL;
- ((const Header*)existingKernelCollection)->forEachSegment(^(const Header::SegmentInfo& info, bool& stop) {
- baseAddress = std::min(baseAddress, info.vmaddr);
+ existingKernelCollection->forEachSegment(^(const dyld3::MachOAnalyzer::SegmentInfo& info, bool& stop) {
+ baseAddress = std::min(baseAddress, info.vmAddr);
});
levelBaseAddresses[0] = baseAddress;
}
@@ -4069,8 +4014,8 @@
if ( pageableKernelCollection != nullptr ) {
// We may have __DATA first, so we need to get either the __DATA or __TEXT depending on what is earliest
__block uint64_t baseAddress = ~0ULL;
- ((const Header *)pageableKernelCollection)->forEachSegment(^(const Header::SegmentInfo& info, bool& stop) {
- baseAddress = std::min(baseAddress, info.vmaddr);
+ pageableKernelCollection->forEachSegment(^(const dyld3::MachOAnalyzer::SegmentInfo& info, bool& stop) {
+ baseAddress = std::min(baseAddress, info.vmAddr);
});
uint8_t fixupLevel = getFixupLevel(Options::AppCacheKind::pageableKC);
levelBaseAddresses[fixupLevel] = baseAddress;
@@ -4217,30 +4162,30 @@
forEachCacheDylib(^(const dyld3::MachOAnalyzer *ma, const std::string &dylibID,
DylibStripMode stripMode, const std::vector<std::string> &dependencies,
Diagnostics& dylibDiag, bool &stop) {
- uint64_t loadAddress = ((const Header*)ma)->preferredLoadAddress();
+ uint64_t loadAddress = ma->preferredLoadAddress();
__block uint64_t numSegments = 0;
__block std::vector<SegmentFixups> segmentFixups;
- ((const Header*)ma)->forEachSegment(^(const Header::SegmentInfo &info, bool &stopSegments) {
+ ma->forEachSegment(^(const dyld3::MachOAnalyzer::SegmentInfo &info, bool &stopSegments) {
// Third party kexts have writable __TEXT, so we need to add starts for all segments
// other than LINKEDIT
bool segmentCanHaveFixups = false;
if ( appCacheOptions.cacheKind == Options::AppCacheKind::pageableKC ) {
- segmentCanHaveFixups = (info.initProt & VM_PROT_WRITE) != 0;
+ segmentCanHaveFixups = (info.protections & VM_PROT_WRITE) != 0;
} else {
// auxKC
- segmentCanHaveFixups = info.segmentName != "__LINKEDIT";
+ segmentCanHaveFixups = (strcmp(info.segName, "__LINKEDIT") != 0);
}
if ( segmentCanHaveFixups) {
SegmentFixups segmentToFixup;
- segmentToFixup.segmentBuffer = (uint8_t*)ma + (info.vmaddr - loadAddress);
- segmentToFixup.segmentIndex = info.segmentIndex;
- segmentToFixup.unslidLoadAddress = info.vmaddr;
- segmentToFixup.sizeInUse = info.vmsize;
+ segmentToFixup.segmentBuffer = (uint8_t*)ma + (info.vmAddr - loadAddress);
+ segmentToFixup.segmentIndex = info.segIndex;
+ segmentToFixup.unslidLoadAddress = info.vmAddr;
+ segmentToFixup.sizeInUse = info.vmSize;
segmentToFixup.starts = nullptr;
segmentToFixup.startsByteSize = 0;
- segmentToFixup.numPagesToFixup = numWritablePagesToFixup(info.vmsize);
+ segmentToFixup.numPagesToFixup = numWritablePagesToFixup(info.vmSize);
segmentFixups.push_back(segmentToFixup);
}
@@ -4263,7 +4208,7 @@
assert(_is64);
typedef Pointer64<LittleEndian> P;
- uint32_t freeSpace = ((const Header*)ma)->loadCommandsFreeSpace();
+ uint32_t freeSpace = ma->loadCommandsFreeSpace();
assert(freeSpace >= sizeof(macho_linkedit_data_command<P>));
uint8_t* endOfLoadCommands = (uint8_t*)ma + sizeof(macho_header<P>) + ma->sizeofcmds;
@@ -4329,8 +4274,6 @@
if ( dataConstRegion.sizeInUse != 0 )
addSegmentStarts(dataConstRegion);
- if ( lateConstRegion.sizeInUse != 0 )
- addSegmentStarts(lateConstRegion);
if ( dataSptmRegion.sizeInUse != 0 )
addSegmentStarts(dataSptmRegion);
if ( branchGOTsRegion.sizeInUse != 0 )
@@ -4423,6 +4366,42 @@
sectionsToAddToRegions[&readOnlyTextRegion] = 1;
}
+ // __DATA_CONST
+ if ( dataConstRegion.sizeInUse != 0 ) {
+ vmOrder.emplace_back(&dataConstRegion, 14, 14);
+ fileOrder.emplace_back(&dataConstRegion, 14, 14);
+ }
+
+ // __DATA_SPTM
+ if ( dataSptmRegion.sizeInUse != 0 ) {
+ vmOrder.emplace_back(&dataSptmRegion, 14, 14);
+ fileOrder.emplace_back(&dataSptmRegion, 14, 14);
+ }
+
+ // Split seg __TEXT_EXEC
+ if ( readExecuteRegion.sizeInUse != 0 ) {
+ vmOrder.emplace_back(&readExecuteRegion, 14, 14);
+ fileOrder.emplace_back(&readExecuteRegion, 14, 14);
+ }
+
+ // __BRANCH_STUBS
+ if ( branchStubsRegion.bufferSize != 0 ) {
+ vmOrder.emplace_back(&branchStubsRegion, 14, 14);
+ fileOrder.emplace_back(&branchStubsRegion, 14, 14);
+ }
+
+ // __TEXT_BOOT_EXEC
+ if ( textBootExecRegion.sizeInUse != 0 ) {
+ vmOrder.emplace_back(&textBootExecRegion, 14, 14);
+ fileOrder.emplace_back(&textBootExecRegion, 14, 14);
+ }
+
+ // __BRANCH_GOTS
+ if ( branchGOTsRegion.bufferSize != 0 ) {
+ vmOrder.emplace_back(&branchGOTsRegion, 14, 14);
+ fileOrder.emplace_back(&branchGOTsRegion, 14, 14);
+ }
+
// -sectcreate
// Align to 16k before we lay out all contiguous regions
if ( !customSegments.empty() ) {
@@ -4448,48 +4427,6 @@
// Align the last region after
vmOrder.back().alignmentAfter = 14;
fileOrder.back().alignmentAfter = 14;
- }
-
- // __DATA_CONST
- if ( dataConstRegion.sizeInUse != 0 ) {
- vmOrder.emplace_back(&dataConstRegion, 14, 14);
- fileOrder.emplace_back(&dataConstRegion, 14, 14);
- }
-
- // __LATE_CONST
- if ( lateConstRegion.sizeInUse != 0 ) {
- vmOrder.emplace_back(&lateConstRegion, 14, 14);
- fileOrder.emplace_back(&lateConstRegion, 14, 14);
- }
-
- // __DATA_SPTM
- if ( dataSptmRegion.sizeInUse != 0 ) {
- vmOrder.emplace_back(&dataSptmRegion, 14, 14);
- fileOrder.emplace_back(&dataSptmRegion, 14, 14);
- }
-
- // Split seg __TEXT_EXEC
- if ( readExecuteRegion.sizeInUse != 0 ) {
- vmOrder.emplace_back(&readExecuteRegion, 14, 14);
- fileOrder.emplace_back(&readExecuteRegion, 14, 14);
- }
-
- // __BRANCH_STUBS
- if ( branchStubsRegion.bufferSize != 0 ) {
- vmOrder.emplace_back(&branchStubsRegion, 14, 14);
- fileOrder.emplace_back(&branchStubsRegion, 14, 14);
- }
-
- // __TEXT_BOOT_EXEC
- if ( textBootExecRegion.sizeInUse != 0 ) {
- vmOrder.emplace_back(&textBootExecRegion, 14, 14);
- fileOrder.emplace_back(&textBootExecRegion, 14, 14);
- }
-
- // __BRANCH_GOTS
- if ( branchGOTsRegion.bufferSize != 0 ) {
- vmOrder.emplace_back(&branchGOTsRegion, 14, 14);
- fileOrder.emplace_back(&branchGOTsRegion, 14, 14);
}
// __PRELINK_INFO
@@ -4575,7 +4512,7 @@
const thread_command* unixThread = nullptr;
if (const DylibInfo* dylib = getKernelStaticExecutableInputFile()) {
- unixThread = ((const Header*)dylib->input->mappedFile.mh)->unixThreadLoadCommand();
+ unixThread = dylib->input->mappedFile.mh->unixThreadLoadCommand();
}
if (_is64) {
@@ -4820,7 +4757,7 @@
macho_build_version_command<P>* cmd = (macho_build_version_command<P>*)header.buildVersion;
cmd->set_cmd(LC_BUILD_VERSION);
cmd->set_cmdsize(sizeof(build_version_command));
- cmd->set_platform(_options.platform.value());
+ cmd->set_platform((uint32_t)_options.platform);
cmd->set_minos(0);
cmd->set_sdk(0);
cmd->set_ntools(0);
@@ -4832,12 +4769,12 @@
if ( header.unixThread != nullptr ) {
const DylibInfo* dylib = getKernelStaticExecutableInputFile();
const dyld3::MachOAnalyzer* ma = dylib->input->mappedFile.mh;
- ((const Header*)ma)->forEachSegment(^(const Header::SegmentInfo &info, bool &stop) {
+ ma->forEachSegment(^(const dyld3::MachOAnalyzer::SegmentInfo &info, bool &stop) {
uint64_t startAddress = dylib->input->mappedFile.mh->entryAddrFromThreadCmd(header.unixThread);
- if ( (startAddress < info.vmaddr) || (startAddress >= (info.vmaddr + info.vmsize)) )
+ if ( (startAddress < info.vmAddr) || (startAddress >= (info.vmAddr + info.vmSize)) )
return;
- uint64_t segSlide = dylib->cacheLocation[info.segmentIndex].dstCacheUnslidAddress - info.vmaddr;
+ uint64_t segSlide = dylib->cacheLocation[info.segIndex].dstCacheUnslidAddress - info.vmAddr;
startAddress += segSlide;
macho_thread_command<P>* cmd = (macho_thread_command<P>*)header.unixThread;
@@ -5100,7 +5037,7 @@
// Skip codeless kext's
if ( ma == nullptr )
continue;
- uint64_t loadAddress = ((const Header*)ma)->preferredLoadAddress();
+ uint64_t loadAddress = ma->preferredLoadAddress();
// _PrelinkExecutableLoadAddr
CFNumberRef loadAddrRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberLongLongType, &loadAddress);
@@ -5152,10 +5089,10 @@
}
__block uint64_t textSegmnentVMAddr = 0;
__block uint64_t textSegmnentVMSize = 0;
- ((const Header*)ma)->forEachSegment(^(const Header::SegmentInfo &info, bool &stop) {
- if ( info.segmentName == "__TEXT" ) {
- textSegmnentVMAddr = info.vmaddr;
- textSegmnentVMSize = info.vmsize;
+ ma->forEachSegment(^(const dyld3::MachOAnalyzer::SegmentInfo &info, bool &stop) {
+ if ( !strcmp(info.segName, "__TEXT") ) {
+ textSegmnentVMAddr = info.vmAddr;
+ textSegmnentVMSize = info.vmSize;
stop = true;
}
});
@@ -5329,13 +5266,6 @@
firstDataRegion = &dataConstRegion;
if ( (lastDataRegion == nullptr) || (dataConstRegion.buffer > lastDataRegion->buffer) )
lastDataRegion = &dataConstRegion;
- }
-
- if ( lateConstRegion.sizeInUse != 0 ) {
- if ( firstDataRegion == nullptr )
- firstDataRegion = &lateConstRegion;
- if ( (lastDataRegion == nullptr) || (lateConstRegion.buffer > lastDataRegion->buffer) )
- lastDataRegion = &lateConstRegion;
}
if ( dataSptmRegion.sizeInUse != 0 ) {
@@ -5543,15 +5473,15 @@
uint32_t& authStubSectionIndex)
{
// section index 0 refers to mach_header
- sectionAddresses.push_back(((const Header*)ma)->preferredLoadAddress());
+ sectionAddresses.push_back(ma->preferredLoadAddress());
sectionBuffers.push_back(nullptr);
intptr_t slide = ma->getSlide();
- ((const Header*)ma)->forEachSection(^(const Header::SectionInfo& sectInfo, bool& stop) {
- if ( (sectInfo.segmentName == "__TEXT_EXEC") && (sectInfo.sectionName == "__auth_stubs") )
+ ma->forEachSection(^(const dyld3::MachOAnalyzer::SectionInfo& sectInfo, bool malformedSectionRange, bool& stop) {
+ if ( !strcmp(sectInfo.segInfo.segName, "__TEXT_EXEC") && !strcmp(sectInfo.sectName, "__auth_stubs") )
authStubSectionIndex = (uint32_t)sectionAddresses.size();
- sectionAddresses.push_back(sectInfo.address);
- sectionBuffers.push_back((uint8_t*)sectInfo.address + slide);
+ sectionAddresses.push_back(sectInfo.sectAddr);
+ sectionBuffers.push_back((uint8_t*)sectInfo.sectAddr + slide);
});
}
@@ -5715,7 +5645,7 @@
const dyld3::MachOAnalyzer* ma = nullptr;
for (const SegmentMappingInfo& loc : dylib.cacheLocation) {
- if ( loc.segName == "__TEXT" ) {
+ if ( !strcmp(loc.segName, "__TEXT") ) {
// Assume __TEXT contains the mach header
ma = (const dyld3::MachOAnalyzer*)loc.dstSegment;
break;