Loading...
--- dyld/dyld-750.5/dyld3/Loading.cpp
+++ dyld/dyld-635.2/dyld3/Loading.cpp
@@ -39,23 +39,21 @@
#include <System/sys/mman.h>
#include <System/sys/csr.h>
#include <System/machine/cpu_capabilities.h>
-#if !TARGET_OS_SIMULATOR && !TARGET_OS_DRIVERKIT
+#include <bootstrap.h>
+#include <CommonCrypto/CommonDigest.h>
#include <sandbox.h>
#include <sandbox/private.h>
-#endif
-//#include <dispatch/dispatch.h>
+#include <dispatch/dispatch.h>
#include <mach/vm_page_size.h>
#include "MachOFile.h"
#include "MachOLoaded.h"
-#include "MachOAnalyzer.h"
#include "Logging.h"
#include "Loading.h"
#include "Tracing.h"
-#include "dyld2.h"
+#include "dyld.h"
#include "dyld_cache_format.h"
-#include "objc-shared-cache.h"
namespace dyld {
void log(const char* m, ...);
@@ -100,57 +98,24 @@
namespace dyld3 {
-Loader::Loader(const Array<LoadedImage>& existingImages, Array<LoadedImage>& newImagesStorage,
- const void* cacheAddress, const Array<const dyld3::closure::ImageArray*>& imagesArrays,
- const closure::ObjCSelectorOpt* selOpt, const Array<closure::Image::ObjCSelectorImage>& selImages,
+Loader::Loader(Array<LoadedImage>& storage, const void* cacheAddress, const Array<const dyld3::closure::ImageArray*>& imagesArrays,
LogFunc logLoads, LogFunc logSegments, LogFunc logFixups, LogFunc logDofs)
- : _existingImages(existingImages), _newImages(newImagesStorage),
- _imagesArrays(imagesArrays), _dyldCacheAddress(cacheAddress), _dyldCacheSelectorOpt(nullptr),
- _closureSelectorOpt(selOpt), _closureSelectorImages(selImages),
+ : _allImages(storage), _imagesArrays(imagesArrays), _dyldCacheAddress(cacheAddress),
_logLoads(logLoads), _logSegments(logSegments), _logFixups(logFixups), _logDofs(logDofs)
{
-#if BUILDING_DYLD
- // This is only needed for dyld and the launch closure, not the dlopen closures
- if ( _dyldCacheAddress != nullptr ) {
- _dyldCacheSelectorOpt = ((const DyldSharedCache*)_dyldCacheAddress)->objcOpt()->selopt();
- }
-#endif
}
void Loader::addImage(const LoadedImage& li)
{
- _newImages.push_back(li);
+ _allImages.push_back(li);
}
LoadedImage* Loader::findImage(closure::ImageNum targetImageNum)
{
-#if BUILDING_DYLD
- // The launch images are different in dyld vs libdyld. In dyld, the new images are
- // the launch images, while in libdyld, the existing images are the launch images
- if (LoadedImage* info = _launchImagesCache.findImage(targetImageNum, _newImages)) {
- return info;
- }
-
- for (uint64_t index = 0; index != _newImages.count(); ++index) {
- LoadedImage& info = _newImages[index];
- if ( info.image()->representsImageNum(targetImageNum) ) {
- // Try cache this entry for next time
- _launchImagesCache.tryAddImage(targetImageNum, index);
- return &info;
- }
- }
-#elif BUILDING_LIBDYLD
- for (const LoadedImage& info : _existingImages) {
- if ( info.image()->representsImageNum(targetImageNum) )
- return (LoadedImage*)&info;
- }
- for (LoadedImage& info : _newImages) {
+ for (LoadedImage& info : _allImages) {
if ( info.image()->representsImageNum(targetImageNum) )
return &info;
}
-#else
-#error Must be building dyld or libdyld
-#endif
return nullptr;
}
@@ -178,10 +143,10 @@
}
-void Loader::completeAllDependents(Diagnostics& diag, bool& someCacheImageOverridden)
+void Loader::completeAllDependents(Diagnostics& diag, uintptr_t topIndex)
{
// accumulate all image overrides
- STACK_ALLOC_ARRAY(ImageOverride, overrides, _existingImages.maxCount() + _newImages.maxCount());
+ STACK_ALLOC_ARRAY(ImageOverride, overrides, _allImages.maxCount());
for (const auto anArray : _imagesArrays) {
// ignore prebuilt Image* in dyld cache
if ( anArray->startImageNum() < dyld3::closure::kFirstLaunchClosureImageNum )
@@ -189,7 +154,6 @@
anArray->forEachImage(^(const dyld3::closure::Image* image, bool& stop) {
ImageOverride overrideEntry;
if ( image->isOverrideOfDyldCacheImage(overrideEntry.inCache) ) {
- someCacheImageOverridden = true;
overrideEntry.replacement = image->imageNum();
overrides.push_back(overrideEntry);
}
@@ -198,15 +162,14 @@
// make cache for fast lookup of already loaded images
__block ImageNumSet alreadyLoaded;
- for (const LoadedImage& info : _existingImages) {
- alreadyLoaded.add(info.image()->imageNum());
- }
- alreadyLoaded.add(_newImages.begin()->image()->imageNum());
-
- // for each image in _newImages, starting at the top image, make sure its dependents are in _allImages
- uintptr_t index = 0;
- while ( (index < _newImages.count()) && diag.noError() ) {
- const closure::Image* image = _newImages[index].image();
+ for (int i=0; i <= topIndex; ++i) {
+ alreadyLoaded.add(_allImages[i].image()->imageNum());
+ }
+
+ // for each image in _allImages, starting at topIndex, make sure its depenents are in _allImages
+ uintptr_t index = topIndex;
+ while ( (index < _allImages.count()) && diag.noError() ) {
+ const closure::Image* image = _allImages[index].image();
//fprintf(stderr, "completeAllDependents(): looking at dependents of %s\n", image->path());
image->forEachDependentImage(^(uint32_t depIndex, closure::Image::LinkKind kind, closure::ImageNum depImageNum, bool& stop) {
// check if imageNum needs to be changed to an override
@@ -222,12 +185,12 @@
const closure::Image* depImage = closure::ImageArray::findImage(_imagesArrays, depImageNum);
if ( depImage != nullptr ) {
//dyld::log(" load imageNum=0x%05X, image path=%s\n", depImageNum, depImage->path());
- if ( _newImages.freeCount() == 0 ) {
+ if ( _allImages.freeCount() == 0 ) {
diag.error("too many initial images");
stop = true;
}
else {
- _newImages.push_back(LoadedImage::make(depImage));
+ _allImages.push_back(LoadedImage::make(depImage));
}
alreadyLoaded.add(depImageNum);
}
@@ -241,15 +204,16 @@
}
}
-void Loader::mapAndFixupAllImages(Diagnostics& diag, bool processDOFs, bool fromOFI)
+void Loader::mapAndFixupAllImages(Diagnostics& diag, bool processDOFs, bool fromOFI, uintptr_t topIndex)
{
// scan array and map images not already loaded
- for (LoadedImage& info : _newImages) {
+ for (uintptr_t i=topIndex; i < _allImages.count(); ++i) {
+ LoadedImage& info = _allImages[i];
if ( info.loadedAddress() != nullptr ) {
// log main executable's segments
if ( (info.loadedAddress()->filetype == MH_EXECUTE) && (info.state() == LoadedImage::State::mapped) ) {
if ( _logSegments("dyld: mapped by kernel %s\n", info.image()->path()) ) {
- info.image()->forEachDiskSegment(^(uint32_t segIndex, uint32_t fileOffset, uint32_t fileSize, int64_t vmOffset, uint64_t vmSize, uint8_t permissions, bool laterReadOnly, bool& stop) {
+ info.image()->forEachDiskSegment(^(uint32_t segIndex, uint32_t fileOffset, uint32_t fileSize, int64_t vmOffset, uint64_t vmSize, uint8_t permissions, bool& stop) {
uint64_t start = (long)info.loadedAddress() + vmOffset;
uint64_t end = start+vmSize-1;
if ( (segIndex == 0) && (permissions == 0) ) {
@@ -305,7 +269,7 @@
}
if ( diag.hasError() ) {
// bummer, need to clean up by unmapping any images just mapped
- for (LoadedImage& info : _newImages) {
+ for (LoadedImage& info : _allImages) {
if ( (info.state() == LoadedImage::State::mapped) && !info.image()->inDyldCache() && !info.leaveMapped() ) {
_logSegments("dyld: unmapping %s\n", info.image()->path());
unmapImage(info);
@@ -315,7 +279,8 @@
}
// apply fixups
- for (LoadedImage& info : _newImages) {
+ for (uintptr_t i=topIndex; i < _allImages.count(); ++i) {
+ LoadedImage& info = _allImages[i];
// images in shared cache do not need fixups applied
if ( info.image()->inDyldCache() )
continue;
@@ -330,8 +295,9 @@
// find and register dtrace DOFs
if ( processDOFs ) {
- STACK_ALLOC_OVERFLOW_SAFE_ARRAY(DOFInfo, dofImages, _newImages.count());
- for (LoadedImage& info : _newImages) {
+ STACK_ALLOC_OVERFLOW_SAFE_ARRAY(DOFInfo, dofImages, _allImages.count());
+ for (uintptr_t i=topIndex; i < _allImages.count(); ++i) {
+ LoadedImage& info = _allImages[i];
info.image()->forEachDOF(info.loadedAddress(), ^(const void* section) {
DOFInfo dofInfo;
dofInfo.dof = section;
@@ -346,7 +312,7 @@
bool Loader::sandboxBlocked(const char* path, const char* kind)
{
-#if TARGET_OS_SIMULATOR || TARGET_OS_DRIVERKIT
+#if TARGET_IPHONE_SIMULATOR
// sandbox calls not yet supported in dyld_sim
return false;
#else
@@ -382,11 +348,7 @@
bool isCodeSigned = image->hasCodeSignature(codeSignFileOffset, codeSignFileSize);
// open file
-#if BUILDING_DYLD
- int fd = dyld::my_open(info.image()->path(), O_RDONLY, 0);
-#else
int fd = ::open(info.image()->path(), O_RDONLY, 0);
-#endif
if ( fd == -1 ) {
int openErr = errno;
if ( (openErr == EPERM) && sandboxBlockedOpen(image->path()) )
@@ -398,7 +360,7 @@
// get file info
struct stat statBuf;
-#if TARGET_OS_SIMULATOR
+#if TARGET_IPHONE_SIMULATOR
if ( stat(image->path(), &statBuf) != 0 ) {
#else
if ( fstat(fd, &statBuf) != 0 ) {
@@ -495,12 +457,11 @@
_logSegments("dyld: Mapping %s\n", image->path());
// map each segment
- __block bool mmapFailure = false;
+ __block bool mmapFailure = false;
__block const uint8_t* codeSignatureStartAddress = nullptr;
__block const uint8_t* linkeditEndAddress = nullptr;
- __block bool mappedFirstSegment = false;
- __block uint64_t maxFileOffset = 0;
- image->forEachDiskSegment(^(uint32_t segIndex, uint32_t fileOffset, uint32_t fileSize, int64_t vmOffset, uint64_t vmSize, uint8_t permissions, bool laterReadOnly, bool& stop) {
+ __block bool mappedFirstSegment = false;
+ image->forEachDiskSegment(^(uint32_t segIndex, uint32_t fileOffset, uint32_t fileSize, int64_t vmOffset, uint64_t vmSize, uint8_t permissions, bool& stop) {
// <rdar://problem/32363581> Mapping zero filled segments fails with mmap of size 0
if ( fileSize == 0 )
return;
@@ -538,7 +499,6 @@
(permissions & PROT_READ) ? 'r' : '.', (permissions & PROT_WRITE) ? 'w' : '.', (permissions & PROT_EXEC) ? 'x' : '.' ,
(long)segAddress, (long)segAddress+(long)vmSize-1);
}
- maxFileOffset = fileOffset + fileSize;
});
if ( mmapFailure ) {
::vm_deallocate(mach_task_self(), loadAddress, (vm_size_t)totalVMSize);
@@ -546,60 +506,28 @@
return;
}
- // <rdar://problem/47163421> speculatively read whole slice
- fspecread_t specread = {} ;
- specread.fsr_offset = sliceOffset;
- specread.fsr_length = maxFileOffset;
- specread.fsr_flags = 0;
- fcntl(fd, F_SPECULATIVE_READ, &specread);
- _logSegments("dyld: Speculatively read offset=0x%08llX, len=0x%08llX, path=%s\n", sliceOffset, maxFileOffset, image->path());
-
// close file
close(fd);
#if BUILDING_LIBDYLD
// verify file has not changed since closure was built by checking code signature has not changed
- struct CDHashWrapper {
- uint8_t cdHash[20];
- };
-
- // Get all the hashes for the image
- STACK_ALLOC_OVERFLOW_SAFE_ARRAY(CDHashWrapper, expectedCDHashes, 1);
- image->forEachCDHash(^(const uint8_t *cdHash, bool &stop) {
- CDHashWrapper cdHashWrapper;
- memcpy(cdHashWrapper.cdHash, cdHash, sizeof(CDHashWrapper::cdHash));
- expectedCDHashes.push_back(cdHashWrapper);
- });
-
- if (!expectedCDHashes.empty()) {
- if (expectedCDHashes.count() != 1) {
- // We should only see a single hash for dylibs
- diag.error("code signature count invalid");
- } else if ( codeSignatureStartAddress == nullptr ) {
+ uint8_t cdHashExpected[20];
+ if ( image->hasCdHash(cdHashExpected) ) {
+ if ( codeSignatureStartAddress == nullptr ) {
diag.error("code signature missing");
}
else if ( codeSignatureStartAddress+codeSignFileSize > linkeditEndAddress ) {
diag.error("code signature extends beyond end of __LINKEDIT");
}
else {
- // Get all the cd hashes for the macho
- STACK_ALLOC_OVERFLOW_SAFE_ARRAY(CDHashWrapper, foundCDHashes, 1);
+ uint8_t cdHashFound[20];
const MachOLoaded* lmo = (MachOLoaded*)loadAddress;
- lmo->forEachCDHashOfCodeSignature(codeSignatureStartAddress, codeSignFileSize,
- ^(const uint8_t *cdHash) {
- CDHashWrapper cdHashWrapper;
- memcpy(cdHashWrapper.cdHash, cdHash, sizeof(CDHashWrapper::cdHash));
- foundCDHashes.push_back(cdHashWrapper);
- });
-
- if (foundCDHashes.empty()) {
+ if ( lmo->cdHashOfCodeSignature(codeSignatureStartAddress, codeSignFileSize, cdHashFound) ) {
+ if ( ::memcmp(cdHashFound, cdHashExpected, 20) != 0 )
+ diag.error("code signature changed since closure was built");
+ }
+ else {
diag.error("code signature format invalid");
- } else if (expectedCDHashes.count() != foundCDHashes.count()) {
- diag.error("code signature count invalid");
- } else {
- // We found a hash, so make sure its equal.
- if ( ::memcmp(foundCDHashes[0].cdHash, expectedCDHashes[0].cdHash, 20) != 0 )
- diag.error("code signature changed since closure was built");
}
}
if ( diag.hasError() ) {
@@ -607,10 +535,9 @@
return;
}
}
-
-#endif
-
-#if __IPHONE_OS_VERSION_MIN_REQUIRED && !TARGET_OS_SIMULATOR
+#endif
+
+#if __IPHONE_OS_VERSION_MIN_REQUIRED && !TARGET_IPHONE_SIMULATOR
// tell kernel about fairplay encrypted regions
uint32_t fpTextOffset;
uint32_t fpSize;
@@ -682,8 +609,17 @@
bool Loader::dtraceUserProbesEnabled()
{
- uint8_t dofEnabled = *((uint8_t*)_COMM_PAGE_DTRACE_DOF_ENABLED);
- return ( (dofEnabled & 1) );
+#if __IPHONE_OS_VERSION_MIN_REQUIRED && !TARGET_IPHONE_SIMULATOR
+ int dof_mode;
+ size_t dof_mode_size = sizeof(dof_mode);
+ if ( sysctlbyname("kern.dtrace.dof_mode", &dof_mode, &dof_mode_size, nullptr, 0) == 0 ) {
+ return ( dof_mode != 0 );
+ }
+ return false;
+#else
+ // dtrace is always available for macOS and simulators
+ return true;
+#endif
}
@@ -709,79 +645,61 @@
const uint8_t* imageLoadAddress = (uint8_t*)info.loadedAddress();
uintptr_t slide = info.loadedAddress()->getSlide();
bool overrideOfCache = info.image()->isOverrideOfDyldCacheImage(cacheImageNum);
-
if ( overrideOfCache )
vmAccountingSetSuspended(true, _logFixups);
- image->forEachFixup(^(uint64_t imageOffsetToRebase, bool& stop) {
- // this is a rebase, add slide
+ image->forEachFixup(^(uint64_t imageOffsetToRebase, bool &stop) {
uintptr_t* fixUpLoc = (uintptr_t*)(imageLoadAddress + imageOffsetToRebase);
*fixUpLoc += slide;
_logFixups("dyld: fixup: %s:%p += %p\n", leafName, fixUpLoc, (void*)slide);
},
- ^(uint64_t imageOffsetToBind, closure::Image::ResolvedSymbolTarget bindTarget, bool& stop) {
- // this is a bind, set to target
+ ^(uint64_t imageOffsetToBind, closure::Image::ResolvedSymbolTarget bindTarget, bool &stop) {
uintptr_t* fixUpLoc = (uintptr_t*)(imageLoadAddress + imageOffsetToBind);
uintptr_t value = resolveTarget(bindTarget);
_logFixups("dyld: fixup: %s:%p = %p\n", leafName, fixUpLoc, (void*)value);
*fixUpLoc = value;
},
- ^(uint64_t imageOffsetToStartsInfo, const Array<closure::Image::ResolvedSymbolTarget>& targets, bool& stop) {
- // this is a chain of fixups, fix up all
- STACK_ALLOC_OVERFLOW_SAFE_ARRAY(const void*, targetAddrs, 128);
- targetAddrs.reserve(targets.count());
- for (uint32_t i=0; i < targets.count(); ++i)
- targetAddrs.push_back((void*)resolveTarget(targets[i]));
- ((dyld3::MachOAnalyzer*)(info.loadedAddress()))->withChainStarts(diag, imageOffsetToStartsInfo, ^(const dyld_chained_starts_in_image* starts) {
- info.loadedAddress()->fixupAllChainedFixups(diag, starts, slide, targetAddrs, ^(void* loc, void* newValue) {
- _logFixups("dyld: fixup: %s:%p = %p\n", leafName, loc, newValue);
- });
+ ^(uint64_t imageOffsetStart, const Array<closure::Image::ResolvedSymbolTarget>& targets, bool& stop) {
+ // walk each fixup in the chain
+ image->forEachChainedFixup((void*)imageLoadAddress, imageOffsetStart, ^(uint64_t* fixupLoc, MachOLoaded::ChainedFixupPointerOnDisk fixupInfo, bool& stopChain) {
+ if ( fixupInfo.authRebase.auth ) {
+ #if __has_feature(ptrauth_calls)
+ if ( fixupInfo.authBind.bind ) {
+ closure::Image::ResolvedSymbolTarget bindTarget = targets[fixupInfo.authBind.ordinal];
+ uint64_t targetAddr = resolveTarget(bindTarget);
+ // Don't sign missing weak imports.
+ if (targetAddr != 0)
+ targetAddr = fixupInfo.signPointer(fixupLoc, targetAddr);
+ _logFixups("dyld: fixup: *%p = %p (JOP: diversity 0x%04X, addr-div=%d, key=%s)\n",
+ fixupLoc, (void*)targetAddr, fixupInfo.authBind.diversity, fixupInfo.authBind.addrDiv, fixupInfo.authBind.keyName());
+ *fixupLoc = targetAddr;
+ }
+ else {
+ uint64_t targetAddr = (uint64_t)imageLoadAddress + fixupInfo.authRebase.target;
+ targetAddr = fixupInfo.signPointer(fixupLoc, targetAddr);
+ _logFixups("dyld: fixup: *%p = %p (JOP: diversity 0x%04X, addr-div=%d, key=%s)\n",
+ fixupLoc, (void*)targetAddr, fixupInfo.authRebase.diversity, fixupInfo.authRebase.addrDiv, fixupInfo.authRebase.keyName());
+ *fixupLoc = targetAddr;
+ }
+ #else
+ diag.error("malformed chained pointer");
+ stop = true;
+ stopChain = true;
+ #endif
+ }
+ else {
+ if ( fixupInfo.plainRebase.bind ) {
+ closure::Image::ResolvedSymbolTarget bindTarget = targets[fixupInfo.plainBind.ordinal];
+ uint64_t targetAddr = resolveTarget(bindTarget) + fixupInfo.plainBind.signExtendedAddend();
+ _logFixups("dyld: fixup: %s:%p = %p\n", leafName, fixupLoc, (void*)targetAddr);
+ *fixupLoc = targetAddr;
+ }
+ else {
+ uint64_t targetAddr = fixupInfo.plainRebase.signExtendedTarget() + slide;
+ _logFixups("dyld: fixup: %s:%p += %p\n", leafName, fixupLoc, (void*)slide);
+ *fixupLoc = targetAddr;
+ }
+ }
});
- },
- ^(uint64_t imageOffsetToFixup) {
- uintptr_t* fixUpLoc = (uintptr_t*)(imageLoadAddress + imageOffsetToFixup);
- _logFixups("dyld: fixup objc image info: %s Setting objc image info for precomputed objc\n", leafName);
-
- MachOAnalyzer::ObjCImageInfo *imageInfo = (MachOAnalyzer::ObjCImageInfo *)fixUpLoc;
- ((MachOAnalyzer::ObjCImageInfo *)imageInfo)->flags |= MachOAnalyzer::ObjCImageInfo::dyldPreoptimized;
- },
- ^(uint64_t imageOffsetToBind, closure::Image::ResolvedSymbolTarget bindTarget, bool& stop) {
- // this is a bind, set to target
- uintptr_t* fixUpLoc = (uintptr_t*)(imageLoadAddress + imageOffsetToBind);
- uintptr_t value = resolveTarget(bindTarget);
- _logFixups("dyld: fixup objc protocol: %s:%p = %p\n", leafName, fixUpLoc, (void*)value);
- *fixUpLoc = value;
- },
- ^(uint64_t imageOffsetToFixup, uint32_t selectorIndex, bool inSharedCache, bool &stop) {
- // fixupObjCSelRefs
- closure::Image::ResolvedSymbolTarget fixupTarget;
- if ( inSharedCache ) {
- const char* selectorString = _dyldCacheSelectorOpt->getEntryForIndex(selectorIndex);
- fixupTarget.sharedCache.kind = closure::Image::ResolvedSymbolTarget::kindSharedCache;
- fixupTarget.sharedCache.offset = (uint64_t)selectorString - (uint64_t)_dyldCacheAddress;
- } else {
- closure::ImageNum imageNum;
- uint64_t vmOffset;
- bool gotLocation = _closureSelectorOpt->getStringLocation(selectorIndex, _closureSelectorImages, imageNum, vmOffset);
- assert(gotLocation);
- fixupTarget.image.kind = closure::Image::ResolvedSymbolTarget::kindImage;
- fixupTarget.image.imageNum = imageNum;
- fixupTarget.image.offset = vmOffset;
- }
-
- uintptr_t* fixUpLoc = (uintptr_t*)(imageLoadAddress + imageOffsetToFixup);
- uintptr_t value = resolveTarget(fixupTarget);
- _logFixups("dyld: fixup objc selector: %s:%p(was '%s') = %p(now '%s')\n", leafName, fixUpLoc, (const char*)*fixUpLoc, (void*)value, (const char*)value);
- *fixUpLoc = value;
- }, ^(uint64_t imageOffsetToFixup, bool &stop) {
- // fixupObjCStableSwift
- // Class really is stable Swift, pretending to be pre-stable.
- // Fix its lie.
- uintptr_t* fixUpLoc = (uintptr_t*)(imageLoadAddress + imageOffsetToFixup);
- uintptr_t value = ((*fixUpLoc) | MachOAnalyzer::ObjCClassInfo::FAST_IS_SWIFT_STABLE) & ~MachOAnalyzer::ObjCClassInfo::FAST_IS_SWIFT_LEGACY;
- _logFixups("dyld: fixup objc stable Swift: %s:%p = %p\n", leafName, fixUpLoc, (void*)value);
- *fixUpLoc = value;
- }, ^(uint64_t imageOffsetToFixup, bool &stop) {
- // TODO: Implement this
});
#if __i386__
@@ -800,15 +718,6 @@
setSegmentProtects(info, false);
#endif
- // make any read-only data segments read-only
- if ( image->hasReadOnlyData() && !image->inDyldCache() ) {
- image->forEachDiskSegment(^(uint32_t segIndex, uint32_t fileOffset, uint32_t fileSize, int64_t vmOffset, uint64_t vmSize, uint8_t permissions, bool laterReadOnly, bool& segStop) {
- if ( laterReadOnly ) {
- ::mprotect((void*)(imageLoadAddress+vmOffset), (size_t)vmSize, VM_PROT_READ);
- }
- });
- }
-
if ( overrideOfCache )
vmAccountingSetSuspended(false, _logFixups);
}
@@ -816,7 +725,7 @@
#if __i386__
void Loader::setSegmentProtects(const LoadedImage& info, bool write)
{
- info.image()->forEachDiskSegment(^(uint32_t segIndex, uint32_t fileOffset, uint32_t fileSize, int64_t vmOffset, uint64_t vmSize, uint8_t protections, bool laterReadOnly, bool& segStop) {
+ info.image()->forEachDiskSegment(^(uint32_t segIndex, uint32_t fileOffset, uint32_t fileSize, int64_t vmOffset, uint64_t vmSize, uint8_t protections, bool& segStop) {
if ( protections & VM_PROT_WRITE )
return;
uint32_t regionProt = protections;
@@ -829,31 +738,6 @@
#endif
#if BUILDING_DYLD
-LoadedImage* Loader::LaunchImagesCache::findImage(closure::ImageNum imageNum,
- Array<LoadedImage>& images) const {
- if ( (imageNum < _firstImageNum) || (imageNum >= _lastImageNum) )
- return nullptr;
-
- uint64_t cacheIndex = imageNum - _firstImageNum;
- uint32_t imagesIndex = _imageIndices[cacheIndex];
- if ( imagesIndex == 0 )
- return nullptr;
-
- // Note the index is offset by 1 so that 0's are not yet set
- return &images[imagesIndex - 1];
-}
-
-void Loader::LaunchImagesCache::tryAddImage(closure::ImageNum imageNum,
- uint64_t allImagesIndex) {
- if ( (imageNum < _firstImageNum) || (imageNum >= _lastImageNum) )
- return;
-
- uint64_t cacheIndex = imageNum - _firstImageNum;
-
- // Note the index is offset by 1 so that 0's are not yet set
- _imageIndices[cacheIndex] = (uint32_t)allImagesIndex + 1;
-}
-
void forEachLineInFile(const char* buffer, size_t bufferLen, void (^lineHandler)(const char* line, bool& stop))
{
bool stop = false;
@@ -890,20 +774,88 @@
}
}
-#endif
-
-#if (BUILDING_LIBDYLD || BUILDING_DYLD)
- bool internalInstall()
- {
-#if TARGET_OS_SIMULATOR
+
+bool internalInstall()
+{
+#if TARGET_IPHONE_SIMULATOR
+ return false;
+#elif __IPHONE_OS_VERSION_MIN_REQUIRED
+ uint32_t devFlags = *((uint32_t*)_COMM_PAGE_DEV_FIRM);
+ return ( (devFlags & 1) == 1 );
+#else
+ return ( csr_check(CSR_ALLOW_APPLE_INTERNAL) == 0 );
+#endif
+}
+
+/* Checks to see if there are any args that impact dyld. These args
+ * can be set sevaral ways. These will only be honored on development
+ * and Apple Internal builds.
+ *
+ * First the existence of a file is checked for:
+ * /S/L/C/com.apple.dyld/dyld-bootargs
+ * If it exists it will be mapped and scanned line by line. If the executable
+ * exists in the file then the arguments on its line will be applied. "*" may
+ * be used a wildcard to represent all apps. First matching line will be used,
+ * the wild card must be one the last line. Additionally, lines must end with
+ * a "\n"
+ *
+ *
+ * SAMPLE FILE:
+
+ /bin/ls:force_dyld2=1
+ /usr/bin/sw_vers:force_dyld2=1
+*:force_dyld3=1
+EOL
+
+ If no file exists then the kernel boot-args will be scanned.
+ */
+bool bootArgsContains(const char* arg)
+{
+ //FIXME: Use strnstr(). Unfortunately we are missing an imp libc.
+#if TARGET_IPHONE_SIMULATOR
+ return false;
+#else
+ // don't check for boot-args on customer installs
+ if ( !internalInstall() )
return false;
-#elif __IPHONE_OS_VERSION_MIN_REQUIRED
- uint32_t devFlags = *((uint32_t*)_COMM_PAGE_DEV_FIRM);
- return ( (devFlags & 1) == 1 );
+
+ char pathBuffer[MAXPATHLEN+1];
+#if __IPHONE_OS_VERSION_MIN_REQUIRED
+ strlcpy(pathBuffer, IPHONE_DYLD_SHARED_CACHE_DIR, sizeof(IPHONE_DYLD_SHARED_CACHE_DIR));
#else
- return ( csr_check(CSR_ALLOW_APPLE_INTERNAL) == 0 );
-#endif
- }
+ strlcpy(pathBuffer, MACOSX_DYLD_SHARED_CACHE_DIR, sizeof(MACOSX_DYLD_SHARED_CACHE_DIR));
+#endif
+ strlcat(pathBuffer, "dyld-bootargs", MAXPATHLEN+1);
+ __block bool result = false;
+ forEachLineInFile(pathBuffer, ^(const char* line, bool& stop) {
+ const char* delim = strchr(line, ':');
+ if ( delim == nullptr )
+ return;
+ char binary[MAXPATHLEN];
+ char options[MAXPATHLEN];
+ strlcpy(binary, line, MAXPATHLEN);
+ binary[delim-line] = '\0';
+ strlcpy(options, delim+1, MAXPATHLEN);
+ if ( (strcmp(dyld::getExecutablePath(), binary) == 0) || (strcmp("*", binary) == 0) ) {
+ result = (strstr(options, arg) != nullptr);
+ return;
+ }
+ });
+
+ // get length of full boot-args string
+ size_t len;
+ if ( sysctlbyname("kern.bootargs", NULL, &len, NULL, 0) != 0 )
+ return false;
+
+ // get copy of boot-args string
+ char bootArgsBuffer[len];
+ if ( sysctlbyname("kern.bootargs", bootArgsBuffer, &len, NULL, 0) != 0 )
+ return false;
+
+ // return true if 'arg' is a sub-string of boot-args
+ return (strstr(bootArgsBuffer, arg) != nullptr);
+#endif
+}
#endif
#if BUILDING_LIBDYLD