Loading...
src/dyld.cpp dyld-195.5 dyld-210.2.3
--- dyld/dyld-195.5/src/dyld.cpp
+++ dyld/dyld-210.2.3/src/dyld.cpp
@@ -37,6 +37,7 @@
 #include <mach-o/loader.h> 
 #include <mach-o/ldsyms.h> 
 #include <libkern/OSByteOrder.h> 
+#include <libkern/OSAtomic.h>
 #include <mach/mach.h>
 #include <sys/sysctl.h>
 #include <sys/mman.h>
@@ -54,6 +55,15 @@
 #endif
 #ifndef CPU_SUBTYPE_ARM_V7
 	#define CPU_SUBTYPE_ARM_V7			((cpu_subtype_t) 9)
+#endif
+#ifndef CPU_SUBTYPE_ARM_V7F
+	#define CPU_SUBTYPE_ARM_V7F			((cpu_subtype_t) 10)
+#endif
+#ifndef CPU_SUBTYPE_ARM_V7S
+	#define CPU_SUBTYPE_ARM_V7S			((cpu_subtype_t) 11)
+#endif
+#ifndef CPU_SUBTYPE_ARM_V7K
+	#define CPU_SUBTYPE_ARM_V7K			((cpu_subtype_t) 12)
 #endif
 #ifndef LC_DYLD_ENVIRONMENT
 	#define LC_DYLD_ENVIRONMENT			0x27
@@ -90,8 +100,8 @@
 
 
 
-// 32-bit ppc and ARM are the only architecture that use cpu-sub-types
-#define CPU_SUBTYPES_SUPPORTED __ppc__ || __arm__
+// ARM is the only architecture that use cpu-sub-types
+#define CPU_SUBTYPES_SUPPORTED  __arm__
 
 
 
@@ -112,6 +122,8 @@
 // implemented in dyldStartup.s for CrashReporter
 extern "C" void dyld_fatal_error(const char* errString) __attribute__((noreturn));
 
+// magic linker symbol for start of dyld binary
+extern "C" void* __dso_handle;
 
 
 //
@@ -174,6 +186,8 @@
 struct RegisteredDOF { const mach_header* mh; int registrationID; };
 struct DylibOverride { const char* installName; const char* override; };
 
+enum RestrictedReason { restrictedNot, restrictedBySetGUid, restrictedBySegment, restrictedByEntitlements };
+	
 // all global state
 static const char*					sExecPath = NULL;
 static const macho_header*			sMainExecutableMachHeader = NULL;
@@ -183,6 +197,7 @@
 #endif
 static ImageLoader*					sMainExecutable = NULL;
 static bool							sProcessIsRestricted = false;
+static RestrictedReason			sRestrictedReason = restrictedNot;
 static unsigned int					sInsertedDylibCount = 0;
 static std::vector<ImageLoader*>	sAllImages;
 static std::vector<ImageLoader*>	sImageRoots;
@@ -333,6 +348,7 @@
 
 
 //#define ALTERNATIVE_LOGFILE "/dev/console"
+
 static int sLogfile = STDERR_FILENO;
 
 #if LOG_BINDINGS
@@ -380,6 +396,29 @@
 	_simple_vdprintf(sLogfile, format, list);
 	va_end(list);
 }
+
+
+// <rdar://problem/8867781> control access to sAllImages through a lock 
+// because global dyld lock is not held during initialization phase of dlopen()
+static long sAllImagesLock = 0;
+
+static void allImagesLock()
+{
+    //dyld::log("allImagesLock()\n");
+	while ( ! OSAtomicCompareAndSwapPtrBarrier((void*)0, (void*)1, (void**)&sAllImagesLock) ) {
+        // spin
+    }
+}
+
+static void allImagesUnlock()
+{
+    //dyld::log("allImagesUnlock()\n");
+	while ( ! OSAtomicCompareAndSwapPtrBarrier((void*)1, (void*)0, (void**)&sAllImagesLock) ) {
+        // spin
+   }
+}
+
+
 
 
 // utility class to assure files are closed when an exception is thrown
@@ -405,19 +444,8 @@
 }
 
 
-// forward declaration
-#if __ppc__ || __i386__
-bool isRosetta();
-#endif
-
-
 static void	registerDOFs(const std::vector<ImageLoader::DOFInfo>& dofs)
 {
-#if __ppc__
-	// can't dtrace a program running emulated under rosetta rdar://problem/5179640
-	if ( isRosetta() )
-		return;
-#endif
 	const unsigned int dofSectionCount = dofs.size();
 	if ( !sEnv.DYLD_DISABLE_DOFS && (dofSectionCount != 0) ) {
 		int fd = open("/dev/" DTRACEMNR_HELPER, O_RDWR);
@@ -536,7 +564,7 @@
 	if ( handlers != NULL ) {
 		dyld_image_info info;
 		info.imageLoadAddress	= image->machHeader();
-		info.imageFilePath		= image->getPath();
+		info.imageFilePath		= image->getRealPath();
 		info.imageFileModDate	= image->lastModified();
 		for (std::vector<dyld_image_state_change_handler>::iterator it = handlers->begin(); it != handlers->end(); ++it) {
 			const char* result = (*it)(state, 1, &info);
@@ -592,7 +620,7 @@
 		dyld_image_info info;
 		ImageLoader* image = *it;
 		info.imageLoadAddress = image->machHeader();
-		info.imageFilePath = image->getPath();
+		info.imageFilePath = image->getRealPath();
 		info.imageFileModDate = image->lastModified();
 		// add to all_image_infos if not already there
 		bool found = false;
@@ -627,18 +655,20 @@
 	std::vector<dyld_image_state_change_handler>* handlers = stateToHandlers(state, sBatchHandlers);
 	if ( handlers != NULL ) {
 		// don't use a vector because it will use malloc/free and we want notifcation to be low cost
-		ImageLoader* images[sAllImages.size()+1];
-		ImageLoader** end = images;
-		for (std::vector<ImageLoader*>::iterator it=sAllImages.begin(); it != sAllImages.end(); it++) {
-			dyld_image_states imageState = (*it)->getState();
-			if ( (imageState == state) || (orLater && (imageState > state)) )
-				*end++ = *it;
-		}
+        allImagesLock();
+        ImageLoader* images[sAllImages.size()+1];
+        ImageLoader** end = images;
+        for (std::vector<ImageLoader*>::iterator it=sAllImages.begin(); it != sAllImages.end(); it++) {
+            dyld_image_states imageState = (*it)->getState();
+            if ( (imageState == state) || (orLater && (imageState > state)) )
+                *end++ = *it;
+        }
 		if ( sBundleBeingLoaded != NULL ) {
 			dyld_image_states imageState = sBundleBeingLoaded->getState();
 			if ( (imageState == state) || (orLater && (imageState > state)) )
 				*end++ = sBundleBeingLoaded;
 		}
+        const char* dontLoadReason = NULL;
 		unsigned int count = end-images;
 		if ( end != images ) {
 			// sort bottom up
@@ -650,7 +680,7 @@
 				ImageLoader* image = images[i];
 				//dyld::log("  state=%d, name=%s\n", state, image->getPath());
 				p->imageLoadAddress = image->machHeader();
-				p->imageFilePath = image->getPath();
+				p->imageFilePath = image->getRealPath();
 				p->imageFileModDate = image->lastModified();
 				// special case for add_image hook
 				if ( state == dyld_image_state_bound )
@@ -662,8 +692,7 @@
 				if ( (result != NULL) && (state == dyld_image_state_dependents_mapped) ) {
 					//fprintf(stderr, "  images rejected by handler=%p\n", onlyHandler);
 					// make copy of thrown string so that later catch clauses can free it
-					const char* str = strdup(result);
-					throw str;
+					dontLoadReason = strdup(result);
 				}
 			}
 			else {
@@ -673,12 +702,15 @@
 					if ( (result != NULL) && (state == dyld_image_state_dependents_mapped) ) {
 						//fprintf(stderr, "  images rejected by handler=%p\n", *it);
 						// make copy of thrown string so that later catch clauses can free it
-						const char* str = strdup(result);
-						throw str;
+						dontLoadReason = strdup(result);
+						break;
 					}
 				}
 			}
 		}
+        allImagesUnlock();
+        if ( dontLoadReason != NULL )
+            throw dontLoadReason;
 	}
 #if CORESYMBOLICATION_SUPPORT
 	if ( state == dyld_image_state_rebased ) {
@@ -730,6 +762,13 @@
 		(*it)->clearDepth();
 }
 
+static void printAllDepths()
+{
+	for (std::vector<ImageLoader*>::iterator it=sAllImages.begin(); it != sAllImages.end(); it++)
+		dyld::log("%03d %s\n",  (*it)->getDepth(), (*it)->getShortName());
+}
+
+
 static unsigned int imageCount()
 {
 	return sAllImages.size();
@@ -758,7 +797,9 @@
 static void addImage(ImageLoader* image)
 {
 	// add to master list
-	sAllImages.push_back(image);
+    allImagesLock();
+        sAllImages.push_back(image);
+    allImagesUnlock();
 	
 	// update mapped ranges
 	uintptr_t lastSegStart = 0;
@@ -832,12 +873,14 @@
 	removedMappedRanges(image);
 
 	// remove from master list
-	for (std::vector<ImageLoader*>::iterator it=sAllImages.begin(); it != sAllImages.end(); it++) {
-		if ( *it == image ) {
-			sAllImages.erase(it);
-			break;
-		}
-	}
+    allImagesLock();
+        for (std::vector<ImageLoader*>::iterator it=sAllImages.begin(); it != sAllImages.end(); it++) {
+            if ( *it == image ) {
+                sAllImages.erase(it);
+                break;
+            }
+        }
+    allImagesUnlock();
 	
 	// flush find-by-address cache (do this after removed from master list, so there is no chance it can come back)
 	if ( sLastImageByAddressCache == image )
@@ -917,15 +960,22 @@
 
 void runTerminators(void* extra)
 {
-	const unsigned int imageCount = sImageFilesNeedingTermination.size();
-	for(unsigned int i=imageCount; i > 0; --i){
-		ImageLoader* image = sImageFilesNeedingTermination[i-1];
-		image->doTermination(gLinkContext);
-	}
-	sImageFilesNeedingTermination.clear();
-	notifyBatch(dyld_image_state_terminated);
-}
-
+	try {
+		const unsigned int imageCount = sImageFilesNeedingTermination.size();
+		for(unsigned int i=imageCount; i > 0; --i){
+			ImageLoader* image = sImageFilesNeedingTermination[i-1];
+			image->doTermination(gLinkContext);
+		}
+		sImageFilesNeedingTermination.clear();
+		notifyBatch(dyld_image_state_terminated);
+	}
+	catch (const char* msg) {
+		halt(msg);
+	}
+}
+
+
+#if SUPPORT_VERSIONED_PATHS
 
 // forward reference
 static bool getDylibVersionAndInstallname(const char* dylibPath, uint32_t* version, char* installName);
@@ -1036,6 +1086,8 @@
 		closedir(dirp);
 	}
 }
+#endif // SUPPORT_VERSIONED_PATHS
+
 
 //
 // Turns a colon separated list of strings into a NULL terminated array 
@@ -1448,6 +1500,22 @@
 		}
 	}
 	*d++ = NULL;
+	if ( removedCount != 0 ) {
+		dyld::log("dyld: DYLD_ environment variables being ignored because ");
+		switch (sRestrictedReason) {
+			case restrictedNot:
+				break;
+			case restrictedBySetGUid:
+				dyld::log("main executable (%s) is setuid or setgid\n", sExecPath);
+				break;
+			case restrictedBySegment:
+				dyld::log("main executable (%s) has __RESTRICT/__restrict section\n", sExecPath);
+				break;
+			case restrictedByEntitlements:
+				dyld::log("main executable (%s) is code signed with entitlements\n", sExecPath);
+				break;
+		}
+	}
 	
 	// slide apple parameters
 	if ( removedCount > 0 ) {
@@ -1530,6 +1598,15 @@
 #elif __ARM_ARCH_6K__
 	sHostCPU		= CPU_TYPE_ARM;
 	sHostCPUsubtype = CPU_SUBTYPE_ARM_V6;
+#elif __ARM_ARCH_7F__
+	sHostCPU		= CPU_TYPE_ARM;
+	sHostCPUsubtype = CPU_SUBTYPE_ARM_V7F;
+#elif __ARM_ARCH_7S__
+	sHostCPU		= CPU_TYPE_ARM;
+	sHostCPUsubtype = CPU_SUBTYPE_ARM_V7S;
+#elif __ARM_ARCH_7K__
+	sHostCPU		= CPU_TYPE_ARM;
+	sHostCPUsubtype = CPU_SUBTYPE_ARM_V7K;
 #else
 	struct host_basic_info info;
 	mach_msg_type_number_t count = HOST_BASIC_INFO_COUNT;
@@ -1559,12 +1636,12 @@
 
 bool validImage(const ImageLoader* possibleImage)
 {
-	const unsigned int imageCount = sAllImages.size();
-	for(unsigned int i=0; i < imageCount; ++i) {
-		if ( possibleImage == sAllImages[i] ) {
-			return true;
-		}
-	}
+    const unsigned int imageCount = sAllImages.size();
+    for(unsigned int i=0; i < imageCount; ++i) {
+        if ( possibleImage == sAllImages[i] ) {
+            return true;
+        }
+    }
 	return false;
 }
 
@@ -1710,31 +1787,19 @@
 //
 
 
-#if __ppc__
-//	 
-//	32-bit PowerPC sub-type lists
-//
-const int kPPC_RowCount = 4;
-static const cpu_subtype_t kPPC32[kPPC_RowCount][6] = { 
-	// G5 can run any code
-	{  CPU_SUBTYPE_POWERPC_970, CPU_SUBTYPE_POWERPC_7450,  CPU_SUBTYPE_POWERPC_7400, CPU_SUBTYPE_POWERPC_750, CPU_SUBTYPE_POWERPC_ALL, CPU_SUBTYPE_END_OF_LIST },
-	
-	// G4 can run all but G5 code
-	{  CPU_SUBTYPE_POWERPC_7450,  CPU_SUBTYPE_POWERPC_7400,  CPU_SUBTYPE_POWERPC_750, CPU_SUBTYPE_POWERPC_ALL, CPU_SUBTYPE_END_OF_LIST, CPU_SUBTYPE_END_OF_LIST },
-	{  CPU_SUBTYPE_POWERPC_7400,  CPU_SUBTYPE_POWERPC_7450,  CPU_SUBTYPE_POWERPC_750, CPU_SUBTYPE_POWERPC_ALL, CPU_SUBTYPE_END_OF_LIST, CPU_SUBTYPE_END_OF_LIST },
-
-	// G3 cannot run G4 or G5 code
-	{ CPU_SUBTYPE_POWERPC_750,  CPU_SUBTYPE_POWERPC_ALL, CPU_SUBTYPE_END_OF_LIST,  CPU_SUBTYPE_END_OF_LIST, CPU_SUBTYPE_END_OF_LIST, CPU_SUBTYPE_END_OF_LIST }
-};
-#endif
-
-
 #if __arm__
 //      
 //     ARM sub-type lists
 //
-const int kARM_RowCount = 5;
-static const cpu_subtype_t kARM[kARM_RowCount][6] = { 
+const int kARM_RowCount = 8;
+static const cpu_subtype_t kARM[kARM_RowCount][9] = { 
+
+	// armv7f can run: v7f, v7, v6, v5, and v4
+	{  CPU_SUBTYPE_ARM_V7F, CPU_SUBTYPE_ARM_V7, CPU_SUBTYPE_ARM_V6, CPU_SUBTYPE_ARM_V5TEJ, CPU_SUBTYPE_ARM_V4T, CPU_SUBTYPE_ARM_ALL, CPU_SUBTYPE_END_OF_LIST },
+
+	// armv7k can run: v7k, v6, v5, and v4
+	{  CPU_SUBTYPE_ARM_V7K, CPU_SUBTYPE_ARM_V6, CPU_SUBTYPE_ARM_V5TEJ, CPU_SUBTYPE_ARM_V4T, CPU_SUBTYPE_ARM_ALL, CPU_SUBTYPE_END_OF_LIST },
+
 	// armv7 can run: v7, v6, v5, and v4
 	{  CPU_SUBTYPE_ARM_V7, CPU_SUBTYPE_ARM_V6, CPU_SUBTYPE_ARM_V5TEJ, CPU_SUBTYPE_ARM_V4T, CPU_SUBTYPE_ARM_ALL, CPU_SUBTYPE_END_OF_LIST },
 	
@@ -1757,14 +1822,6 @@
 static const cpu_subtype_t* findCPUSubtypeList(cpu_type_t cpu, cpu_subtype_t subtype)
 {
 	switch (cpu) {
-#if __ppc__
-		case CPU_TYPE_POWERPC:
-			for (int i=0; i < kPPC_RowCount ; ++i) {
-				if ( kPPC32[i][0] == subtype )
-					return kPPC32[i];
-			}
-			break;
-#endif
 #if __arm__
 		case CPU_TYPE_ARM:
 			for (int i=0; i < kARM_RowCount ; ++i) {
@@ -1819,15 +1876,6 @@
 	for(uint32_t i=0; i < OSSwapBigToHostInt32(fh->nfat_arch); ++i) {
 		if ( (cpu_type_t)OSSwapBigToHostInt32(archs[i].cputype) == cpu) {
 			switch (cpu) {
-#if __ppc__
-				case CPU_TYPE_POWERPC:
-					if ( (cpu_subtype_t)OSSwapBigToHostInt32(archs[i].cpusubtype) == CPU_SUBTYPE_POWERPC_ALL ) {
-						*offset = OSSwapBigToHostInt32(archs[i].offset);
-						*len = OSSwapBigToHostInt32(archs[i].size);
-						return true;
-					}
-					break;
-#endif
 #if __arm__
 				case CPU_TYPE_ARM:
 					if ( (cpu_subtype_t)OSSwapBigToHostInt32(archs[i].cpusubtype) == CPU_SUBTYPE_ARM_ALL ) {
@@ -1920,12 +1968,6 @@
 			
 			// cpu type has no ordered list of subtypes
 			switch (mh->cputype) {
-				case CPU_TYPE_POWERPC:
-					// allow _ALL to be used by any client
-					if ( mh->cpusubtype == CPU_SUBTYPE_POWERPC_ALL ) 
-						return true;
-					break;
-				case CPU_TYPE_POWERPC64:
 				case CPU_TYPE_I386:
 				case CPU_TYPE_X86_64:
 					// subtypes are not used or these architectures
@@ -2225,6 +2267,7 @@
 {
 	ImageLoader* image = NULL;
 	*imageFound = false;
+	*statErrNo = 0;
 	if ( stat(path, stat_buf) == 0 ) {
 		// in case image was renamed or found via symlinks, check for inode match
 		image = findLoadedImage(*stat_buf);
@@ -2272,7 +2315,7 @@
 		// see if this image in the cache was already loaded via a different path
 		for (std::vector<ImageLoader*>::iterator it=sAllImages.begin(); it != sAllImages.end(); ++it) {
 			ImageLoader* anImage = *it;
-			if ( anImage->machHeader() == mhInCache )
+			if ( (const macho_header*)anImage->machHeader() == mhInCache )
 				return anImage;
 		}
 		// do nothing if not already loaded and if RTLD_NOLOAD 
@@ -2297,7 +2340,7 @@
 		return image;
 #endif
 	// just return NULL if file not found, but record any other errors
-	if ( statErrNo != ENOENT ) {
+	if ( (statErrNo != ENOENT) && (statErrNo != 0) ) {
 		exceptions->push_back(dyld::mkstringf("%s: stat() failed with errno=%d", path, statErrNo));
 	}
 	return NULL;
@@ -2679,20 +2722,11 @@
 
 
 
-
 #if DYLD_SHARED_CACHE_SUPPORT
 
 
 
-
-#if __ppc__
-	#define ARCH_NAME			"ppc"
-	#define ARCH_NAME_ROSETTA	"rosetta"
-	#define ARCH_CACHE_MAGIC	"dyld_v1     ppc"
-#elif __ppc64__
-	#define ARCH_NAME			"ppc64"
-	#define ARCH_CACHE_MAGIC	"dyld_v1   ppc64"
-#elif __i386__
+#if __i386__
 	#define ARCH_NAME			"i386"
 	#define ARCH_CACHE_MAGIC	"dyld_v1    i386"
 #elif __x86_64__
@@ -2709,6 +2743,14 @@
 #elif __ARM_ARCH_6K__
 	#define ARCH_NAME			"armv6"
 	#define ARCH_CACHE_MAGIC	"dyld_v1   armv6"
+#elif __ARM_ARCH_7F__
+	#define ARCH_NAME			"armv7f"
+	#define ARCH_CACHE_MAGIC	"dyld_v1  armv7f"
+	#define SHARED_REGION_READ_ONLY_START   0x30000000
+	#define SHARED_REGION_READ_ONLY_END     0x3E000000
+	#define SHARED_REGION_WRITABLE_START    0x3E000000
+	#define SHARED_REGION_WRITABLE_END      0x40000000
+	#define SLIDEABLE_CACHE_SUPPORT		    1
 #elif __ARM_ARCH_7A__
 	#define ARCH_NAME			"armv7"
 	#define ARCH_CACHE_MAGIC	"dyld_v1   armv7"
@@ -2717,12 +2759,20 @@
 	#define SHARED_REGION_WRITABLE_START    0x3E000000
 	#define SHARED_REGION_WRITABLE_END      0x40000000
 	#define SLIDEABLE_CACHE_SUPPORT		    1
+#elif __ARM_ARCH_7K__
+	#define ARCH_NAME			"armv7k"
+	#define ARCH_CACHE_MAGIC	"dyld_v1  armv7k"
+	#define SHARED_REGION_READ_ONLY_START   0x30000000
+	#define SHARED_REGION_READ_ONLY_END     0x3E000000
+	#define SHARED_REGION_WRITABLE_START    0x3E000000
+	#define SHARED_REGION_WRITABLE_END      0x40000000
+	#define SLIDEABLE_CACHE_SUPPORT		    1
 #endif
 
 
 static int __attribute__((noinline)) _shared_region_check_np(uint64_t* start_address)
 {
-	if ( (gLinkContext.sharedRegionMode == ImageLoader::kUseSharedRegion) ) 
+	if ( gLinkContext.sharedRegionMode == ImageLoader::kUseSharedRegion ) 
 		return syscall(294, start_address);
 	return -1;
 }
@@ -2743,7 +2793,7 @@
 			dyld::log("dyld: code signature for shared cache failed with errno=%d\n", errno);
 	}
 #endif
-	if ( (gLinkContext.sharedRegionMode == ImageLoader::kUseSharedRegion) ) {
+	if ( gLinkContext.sharedRegionMode == ImageLoader::kUseSharedRegion ) {
 		return syscall(438, fd, count, mappings, slide, slideInfo, slideInfoSize);
 	}
 
@@ -2829,13 +2879,7 @@
 	char path[1024];
 	strcpy(path, sSharedCacheDir);
 	strcat(path, "/");
-#if __ppc__
-	// rosetta cannot handle optimized _ppc cache, so it use _rosetta cache instead, rdar://problem/5495438
-    if ( isRosetta() )
-		strcat(path, DYLD_SHARED_CACHE_BASE_NAME ARCH_NAME_ROSETTA);
-    else
-#endif
-		strcat(path, DYLD_SHARED_CACHE_BASE_NAME ARCH_NAME);
+	strcat(path, DYLD_SHARED_CACHE_BASE_NAME ARCH_NAME);
 	return ::open(path, O_RDONLY);
 }
 
@@ -3126,8 +3170,7 @@
 		// check for file that enables dyld shared cache dylibs to be overridden
 		struct stat enableStatBuf;
 		sDylibsOverrideCache = ( ::stat(IPHONE_DYLD_SHARED_CACHE_DIR "enable-dylibs-to-override-cache", &enableStatBuf) == 0 );
-#endif		
-
+#endif	
 	}
 }
 #endif // #if DYLD_SHARED_CACHE_SUPPORT
@@ -3443,14 +3486,19 @@
 	// add to list of handlers
 	std::vector<dyld_image_state_change_handler>* handlers = stateToHandlers(state, sSingleHandlers);
 	if ( handlers != NULL ) {
-		handlers->push_back(handler);
+        // <rdar://problem/10332417> need updateAllImages() to be last in dyld_image_state_mapped list
+        // so that if ObjC adds a handler that prevents a load, it happens before the gdb list is updated
+        if ( state == dyld_image_state_mapped )
+            handlers->insert(handlers->begin(), handler);
+        else
+            handlers->push_back(handler);
 
 		// call callback with all existing images
 		for (std::vector<ImageLoader*>::iterator it=sAllImages.begin(); it != sAllImages.end(); it++) {
 			ImageLoader* image = *it;
 			dyld_image_info	 info;
 			info.imageLoadAddress	= image->machHeader();
-			info.imageFilePath		= image->getPath();
+			info.imageFilePath		= image->getRealPath();
 			info.imageFileModDate	= image->lastModified();
 			// should only call handler if state == image->state
 			if ( image->getState() == state )
@@ -3525,6 +3573,7 @@
 	gLinkContext.removeImage			= &removeImage;
 	gLinkContext.registerDOFs			= &registerDOFs;
 	gLinkContext.clearAllDepths			= &clearAllDepths;
+	gLinkContext.printAllDepths			= &printAllDepths;
 	gLinkContext.imageCount				= &imageCount;
 	gLinkContext.setNewProgramVars		= &setNewProgramVars;
 #if DYLD_SHARED_CACHE_SUPPORT
@@ -3550,21 +3599,6 @@
 	gLinkContext.prebindUsage			= ImageLoader::kUseAllPrebinding;
 	gLinkContext.sharedRegionMode		= ImageLoader::kUseSharedRegion;
 }
-
-#if __ppc__ || __i386__
-bool isRosetta()
-{
-	int mib[] = { CTL_KERN, KERN_CLASSIC, getpid() };
-	int is_classic = 0;
-	size_t len = sizeof(int);
-	int ret = sysctl(mib, 3, &is_classic, &len, NULL, 0);
-	if ((ret != -1) && is_classic) {
-		// we're running under Rosetta 
-		return true;
-	}
-	return false;
-}
-#endif
 
 
 #if __LP64__
@@ -3612,7 +3646,7 @@
 	return false;
 }
 
-
+#if SUPPORT_VERSIONED_PATHS
 //
 // Peeks at a dylib file and returns its current_version and install_name.
 // Returns false on error.
@@ -3674,7 +3708,8 @@
 	
 	return false;
 }
-								
+#endif // SUPPORT_VERSIONED_PATHS
+						
 #if 0
 static void printAllImages()
 {
@@ -3726,8 +3761,14 @@
 		for (std::vector<ImageLoader*>::iterator it=sAllImages.begin(); it != sAllImages.end(); it++) {
 			ImageLoader* image = *it;
 			if ( (image->referenceCount() == 0) && !image->neverUnload() && !image->isBeingRemoved() ) {
+				if ( image->isReferencedUpward() ) {
+					// temp hack for rdar://problem/10973109
+					// if an image is upwardly referenced, we really need to scan all images 
+					// to see if any are still using it.
+					continue;
+				}
 				try {
-					//dyld::log("garbageCollectImages: deleting %s\n", image->getPath());
+					//dyld::log("garbageCollectImages: deleting %p %s\n", image, image->getPath());
 					image->setBeingRemoved();
 					removeImage(image);
 					ImageLoader::deleteImage(image);
@@ -3796,14 +3837,18 @@
 static bool processRestricted(const macho_header* mainExecutableMH)
 {
     // all processes with setuid or setgid bit set are restricted
-    if ( issetugid() )
-        return true;
-        
-	if ( hasRestrictedSegment(mainExecutableMH) && (geteuid() != 0) ) {
+    if ( issetugid() ) {
+		sRestrictedReason = restrictedBySetGUid;
+		return true;
+	}
+		
+	const uid_t euid = geteuid();
+	if ( (euid != 0) && hasRestrictedSegment(mainExecutableMH) ) {
 		// existence of __RESTRICT/__restrict section make process restricted
+		sRestrictedReason = restrictedBySegment;
 		return true;
 	}
-    
+	
 #if __MAC_OS_X_VERSION_MIN_REQUIRED    
     // ask kernel if code signature of program makes it restricted
     uint32_t flags;
@@ -3812,12 +3857,40 @@
                 CS_OPS_STATUS,
                 &flags,
                 sizeof(flags)) != -1) {
-        if (flags & CS_RESTRICT)
-            return true;
+        if (flags & CS_RESTRICT) {
+			sRestrictedReason = restrictedByEntitlements;
+			return true;
+		}
     }
 #endif
     return false;
 }
+
+
+
+
+// <rdar://problem/10583252> Add dyld to uuidArray to enable symbolication of stackshots
+static void addDyldImageToUUIDList()
+{
+	const struct macho_header* mh = (macho_header*)&__dso_handle;
+	const uint32_t cmd_count = mh->ncmds;
+	const struct load_command* const cmds = (struct load_command*)((char*)mh + sizeof(macho_header));
+	const struct load_command* cmd = cmds;
+	for (uint32_t i = 0; i < cmd_count; ++i) {
+		switch (cmd->cmd) {
+			case LC_UUID: {
+				uuid_command* uc = (uuid_command*)cmd;
+				dyld_uuid_info info;
+				info.imageLoadAddress = (mach_header*)mh;
+				memcpy(info.imageUUID, uc->uuid, 16);
+				addNonSharedCacheImageUUID(info);
+				return;
+			}
+		}
+		cmd = (const struct load_command*)(((char*)cmd)+cmd->cmdsize);
+	}
+}
+
 
 
 //
@@ -3827,8 +3900,11 @@
 // Returns address of main() in target program which __dyld_start jumps to
 //
 uintptr_t
-_main(const macho_header* mainExecutableMH, uintptr_t mainExecutableSlide, int argc, const char* argv[], const char* envp[], const char* apple[])
+_main(const macho_header* mainExecutableMH, uintptr_t mainExecutableSlide, 
+		int argc, const char* argv[], const char* envp[], const char* apple[], 
+		uintptr_t* startGlue)
 {	
+	uintptr_t result = 0;
 	CRSetCrashLogMessage("dyld: launch started");
 #ifdef ALTERNATIVE_LOGFILE
 	sLogfile = open(ALTERNATIVE_LOGFILE, O_WRONLY | O_CREAT | O_APPEND);
@@ -3862,16 +3938,6 @@
 	// Pickup the pointer to the exec path.
 	sExecPath = apple[0];
 	bool ignoreEnvironmentVariables = false;
-#if __i386__
-	if ( isRosetta() ) {
-		// under Rosetta (x86 side)
-		// When a 32-bit ppc program is run under emulation on an Intel processor,
-		// we want any i386 dylibs (e.g. any used by Rosetta) to not load in the shared region
-		// because the shared region is being used by ppc dylibs
-		gLinkContext.sharedRegionMode = ImageLoader::kDontUseSharedRegion;
-		ignoreEnvironmentVariables = true;
-	}
-#endif
 	if ( sExecPath[0] != '/' ) {
 		// have relative path, use cwd to make absolute
 		char cwdbuff[MAXPATHLEN];
@@ -3884,7 +3950,6 @@
 			sExecPath = s;
 		}
 	}
-	uintptr_t result = 0;
 	sMainExecutableMachHeader = mainExecutableMH;
     sProcessIsRestricted = processRestricted(mainExecutableMH);
     if ( sProcessIsRestricted ) {
@@ -3922,6 +3987,8 @@
 #endif
 	
 	try {
+		// add dyld itself to UUID list
+		addDyldImageToUUIDList();
 		CRSetCrashLogMessage("dyld: launch, loading dependent libraries");
 		// instantiate ImageLoader for main executable
 		sMainExecutable = instantiateFromLoadedImage(mainExecutableMH, mainExecutableSlide, sExecPath);
@@ -3951,7 +4018,6 @@
 			gLinkContext.bindFlat = true;
 			gLinkContext.prebindUsage = ImageLoader::kUseNoPrebinding;
 		}
-		result = (uintptr_t)sMainExecutable->getMain();
 
 		// link any inserted libraries
 		// do this after linking main executable so that any dylibs pulled in by inserted 
@@ -3969,8 +4035,25 @@
 	#if SUPPORT_OLD_CRT_INITIALIZATION
 		// Old way is to run initializers via a callback from crt1.o
 		if ( ! gRunInitializersOldWay ) 
+			initializeMainExecutable(); 
+	#else
+		// run all initializers
+		initializeMainExecutable(); 
 	#endif
-		initializeMainExecutable(); // run all initializers
+		// find entry point for main executable
+		result = (uintptr_t)sMainExecutable->getThreadPC();
+		if ( result != 0 ) {
+			// main executable uses LC_MAIN, needs to return to glue in libdyld.dylib
+			if ( (gLibSystemHelpers != NULL) && (gLibSystemHelpers->version >= 9) )
+				*startGlue = (uintptr_t)gLibSystemHelpers->startGlueToCallExit;
+			else
+				halt("libdyld.dylib support not present for LC_MAIN");
+		}
+		else {
+			// main executable uses LC_UNIXTHREAD, dyld needs to let "start" in program set up for main()
+			result = (uintptr_t)sMainExecutable->getMain();
+			*startGlue = NULL;
+		}
 	}
 	catch(const char* message) {
 		syncAllImages();