Loading...
--- dyld/dyld-360.18/src/dyld.cpp
+++ dyld/dyld-239.4/src/dyld.cpp
@@ -1,6 +1,6 @@
/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
*
- * Copyright (c) 2004-2013 Apple Inc. All rights reserved.
+ * Copyright (c) 2004-2010 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
@@ -50,9 +50,7 @@
#include <libkern/OSAtomic.h>
#include <Availability.h>
#include <System/sys/codesign.h>
-#include <System/sys/csr.h>
#include <_simple.h>
-#include <os/lock_private.h>
#ifndef CPU_SUBTYPE_ARM_V5TEJ
@@ -76,10 +74,6 @@
#ifndef LC_DYLD_ENVIRONMENT
#define LC_DYLD_ENVIRONMENT 0x27
#endif
-
-#ifndef CPU_SUBTYPE_X86_64_H
- #define CPU_SUBTYPE_X86_64_H ((cpu_subtype_t) 8)
-#endif
#ifndef VM_PROT_SLIDE
#define VM_PROT_SLIDE 0x20
@@ -98,32 +92,16 @@
#if DYLD_SHARED_CACHE_SUPPORT
#include "dyld_cache_format.h"
#endif
-#include <coreSymbolicationDyldSupport.h>
-#if TARGET_IPHONE_SIMULATOR
- extern "C" void xcoresymbolication_load_notifier(void *connection, uint64_t load_timestamp, const char *image_path, const struct mach_header *mach_header);
- extern "C" void xcoresymbolication_unload_notifier(void *connection, uint64_t unload_timestamp, const char *image_path, const struct mach_header *mach_header);
- #define coresymbolication_load_notifier(c, t, p, h) xcoresymbolication_load_notifier(c, t, p, h)
- #define coresymbolication_unload_notifier(c, t, p, h) xcoresymbolication_unload_notifier(c, t, p, h)
+#if CORESYMBOLICATION_SUPPORT
+#include "coreSymbolicationDyldSupport.hpp"
#endif
// not libc header for send() syscall interface
extern "C" ssize_t __sendto(int, const void *, size_t, int, const struct sockaddr *, socklen_t);
-// ARM and x86_64 are the only architecture that use cpu-sub-types
-#define CPU_SUBTYPES_SUPPORTED ((__arm__ || __x86_64__) && !TARGET_IPHONE_SIMULATOR)
-
-#if __LP64__
- #define LC_SEGMENT_COMMAND LC_SEGMENT_64
- #define LC_SEGMENT_COMMAND_WRONG LC_SEGMENT
- #define macho_segment_command segment_command_64
- #define macho_section section_64
-#else
- #define LC_SEGMENT_COMMAND LC_SEGMENT
- #define LC_SEGMENT_COMMAND_WRONG LC_SEGMENT_64
- #define macho_segment_command segment_command
- #define macho_section section
-#endif
+// ARM is the only architecture that use cpu-sub-types
+#define CPU_SUBTYPES_SUPPORTED __arm__
@@ -145,7 +123,7 @@
extern "C" void dyld_fatal_error(const char* errString) __attribute__((noreturn));
// magic linker symbol for start of dyld binary
-extern "C" const macho_header __dso_handle;
+extern "C" void* __dso_handle;
//
@@ -233,38 +211,30 @@
#endif
static ImageLoader* sMainExecutable = NULL;
static bool sProcessIsRestricted = false;
-static bool sProcessRequiresLibraryValidation = false;
static RestrictedReason sRestrictedReason = restrictedNot;
-static size_t sInsertedDylibCount = 0;
+static unsigned int sInsertedDylibCount = 0;
static std::vector<ImageLoader*> sAllImages;
static std::vector<ImageLoader*> sImageRoots;
static std::vector<ImageLoader*> sImageFilesNeedingTermination;
static std::vector<RegisteredDOF> sImageFilesNeedingDOFUnregistration;
static std::vector<ImageCallback> sAddImageCallbacks;
static std::vector<ImageCallback> sRemoveImageCallbacks;
-static bool sRemoveImageCallbacksInUse = false;
static void* sSingleHandlers[7][3];
static void* sBatchHandlers[7][3];
static ImageLoader* sLastImageByAddressCache;
static EnvironmentVariables sEnv;
-#if __MAC_OS_X_VERSION_MIN_REQUIRED
static const char* sFrameworkFallbackPaths[] = { "$HOME/Library/Frameworks", "/Library/Frameworks", "/Network/Library/Frameworks", "/System/Library/Frameworks", NULL };
static const char* sLibraryFallbackPaths[] = { "$HOME/lib", "/usr/local/lib", "/usr/lib", NULL };
-#else
-static const char* sFrameworkFallbackPaths[] = { "/System/Library/Frameworks", NULL };
-static const char* sLibraryFallbackPaths[] = { "/usr/local/lib", "/usr/lib", NULL };
-#endif
static UndefinedHandler sUndefinedHandler = NULL;
static ImageLoader* sBundleBeingLoaded = NULL; // hack until OFI is reworked
#if DYLD_SHARED_CACHE_SUPPORT
static const dyld_cache_header* sSharedCache = NULL;
static long sSharedCacheSlide = 0;
static bool sSharedCacheIgnoreInodeAndTimeStamp = false;
- bool gSharedCacheOverridden = false;
-#if __IPHONE_OS_VERSION_MIN_REQUIRED
+#if __IPHONE_OS_VERSION_MIN_REQUIRED && DYLD_SHARED_CACHE_SUPPORT
+ bool gSharedCacheOverridden = false;
static const char* sSharedCacheDir = IPHONE_DYLD_SHARED_CACHE_DIR;
static bool sDylibsOverrideCache = false;
- #define ENABLE_DYLIBS_TO_OVERRIDE_CACHE_SIZE 1024
#else
static const char* sSharedCacheDir = MACOSX_DYLD_SHARED_CACHE_DIR;
#endif
@@ -280,13 +250,9 @@
static int sLogSocket = -1;
#endif
static bool sFrameworksFoundAsDylibs = false;
-#if __x86_64__
-static bool sHaswell = false;
-#endif
+
static std::vector<ImageLoader::DynamicReference> sDynamicReferences;
-static OSSpinLock sDynamicReferencesLock = 0;
-static bool sLogToFile = false;
-static char sLoadingCrashMessage[1024] = "dyld: launch, loading dependent libraries";
+
//
// The MappedRanges structure is used for fast address->image lookups.
@@ -402,6 +368,7 @@
}
+//#define ALTERNATIVE_LOGFILE "/dev/console"
#if !TARGET_IPHONE_SIMULATOR
static int sLogfile = STDERR_FILENO;
#endif
@@ -489,11 +456,10 @@
void vlog(const char* format, va_list list)
{
- if ( !sLogToFile && useSyslog() )
+ if ( useSyslog() )
socket_syslogv(LOG_ERR, format, list);
- else {
+ else
_simple_vdprintf(sLogfile, format, list);
- }
}
void log(const char* format, ...)
@@ -525,18 +491,25 @@
// <rdar://problem/8867781> control access to sAllImages through a lock
// because global dyld lock is not held during initialization phase of dlopen()
-// <rdar://problem/16145518> Use OSSpinLockLock to allow yielding
-static OSSpinLock sAllImagesLock = 0;
+static long sAllImagesLock = 0;
static void allImagesLock()
{
- OSSpinLockLock(&sAllImagesLock);
+ //dyld::log("allImagesLock()\n");
+ while ( ! OSAtomicCompareAndSwapPtrBarrier((void*)0, (void*)1, (void**)&sAllImagesLock) ) {
+ // spin
+ }
}
static void allImagesUnlock()
{
- OSSpinLockUnlock(&sAllImagesLock);
-}
+ //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
@@ -564,7 +537,7 @@
static void registerDOFs(const std::vector<ImageLoader::DOFInfo>& dofs)
{
- const size_t dofSectionCount = dofs.size();
+ const unsigned int dofSectionCount = dofs.size();
if ( !sEnv.DYLD_DISABLE_DOFS && (dofSectionCount != 0) ) {
int fd = open("/dev/" DTRACEMNR_HELPER, O_RDWR);
if ( fd < 0 ) {
@@ -600,7 +573,7 @@
}
}
else {
- //dyld::log( "dyld: ioctl to register dtrace DOF section failed\n");
+ dyld::log( "dyld: ioctl to register dtrace DOF section failed\n");
}
close(fd);
}
@@ -703,17 +676,20 @@
}
}
}
- // mach message csdlc about dynamically unloaded images
+#if CORESYMBOLICATION_SUPPORT
+ // mach message csdlc about dynamically loaded images
if ( image->addFuncNotified() && (state == dyld_image_state_terminated) ) {
- uint64_t loadTimestamp = mach_absolute_time();
if ( sEnv.DYLD_PRINT_CS_NOTIFICATIONS ) {
- dyld::log("dyld: coresymbolication_unload_notifier(%p, 0x%016llX, %p, %s)\n",
- dyld::gProcessInfo->coreSymbolicationShmPage, loadTimestamp, image->machHeader(), image->getPath());
+ dyld::log("dyld core symbolication unload notification: %p %s\n", image->machHeader(), image->getPath());
}
if ( dyld::gProcessInfo->coreSymbolicationShmPage != NULL) {
- coresymbolication_unload_notifier(dyld::gProcessInfo->coreSymbolicationShmPage, loadTimestamp, image->getPath(), image->machHeader());
- }
- }
+ CSCppDyldSharedMemoryPage* connection = (CSCppDyldSharedMemoryPage*)dyld::gProcessInfo->coreSymbolicationShmPage;
+ if ( connection->is_valid_version() ) {
+ coresymbolication_unload_image(connection, image);
+ }
+ }
+ }
+#endif
}
@@ -783,7 +759,7 @@
*end++ = sBundleBeingLoaded;
}
const char* dontLoadReason = NULL;
- uint32_t count = (uint32_t)(end-images);
+ unsigned int count = end-images;
if ( end != images ) {
// sort bottom up
qsort(images, count, sizeof(ImageLoader*), &imageSorter);
@@ -821,22 +797,34 @@
}
}
}
- if ( (state == dyld_image_state_dependents_mapped) && ((dyld::gProcessInfo->coreSymbolicationShmPage != NULL) || sEnv.DYLD_PRINT_CS_NOTIFICATIONS) ) {
- // mach message csdlc about loaded images
- uint64_t loadTimestamp = mach_absolute_time();
- for (unsigned j=0; j < count; ++j) {
- if ( sEnv.DYLD_PRINT_CS_NOTIFICATIONS ) {
- dyld::log("dyld: coresymbolication_load_notifier(%p, 0x%016llX, %p, %s)\n",
- dyld::gProcessInfo->coreSymbolicationShmPage, loadTimestamp, infos[j].imageLoadAddress, infos[j].imageFilePath);
- }
- coresymbolication_load_notifier(dyld::gProcessInfo->coreSymbolicationShmPage, loadTimestamp, infos[j].imageFilePath, infos[j].imageLoadAddress);
- }
- }
}
allImagesUnlock();
if ( dontLoadReason != NULL )
throw dontLoadReason;
}
+#if CORESYMBOLICATION_SUPPORT
+ if ( state == dyld_image_state_rebased ) {
+ if ( sEnv.DYLD_PRINT_CS_NOTIFICATIONS ) {
+ for (std::vector<ImageLoader*>::iterator it=sAllImages.begin(); it != sAllImages.end(); it++) {
+ dyld_image_states imageState = (*it)->getState();
+ if ( (imageState == dyld_image_state_rebased) || (orLater && (imageState > dyld_image_state_rebased)) )
+ dyld::log("dyld core symbolication load notification: %p %s\n", (*it)->machHeader(), (*it)->getPath());
+ }
+ }
+ if ( dyld::gProcessInfo->coreSymbolicationShmPage != NULL) {
+ CSCppDyldSharedMemoryPage* connection = (CSCppDyldSharedMemoryPage*)dyld::gProcessInfo->coreSymbolicationShmPage;
+ if ( connection->is_valid_version() ) {
+ // This needs to be captured now
+ uint64_t load_timestamp = mach_absolute_time();
+ for (std::vector<ImageLoader*>::iterator it=sAllImages.begin(); it != sAllImages.end(); it++) {
+ dyld_image_states imageState = (*it)->getState();
+ if ( (imageState == state) || (orLater && (imageState > state)) )
+ coresymbolication_load_image(connection, *it, load_timestamp);
+ }
+ }
+ }
+ }
+#endif
}
@@ -873,7 +861,7 @@
static unsigned int imageCount()
{
- return (unsigned int)sAllImages.size();
+ return sAllImages.size();
}
@@ -908,22 +896,17 @@
return;
// don't add if this combination already exists
- OSSpinLockLock(&sDynamicReferencesLock);
for (std::vector<ImageLoader::DynamicReference>::iterator it=sDynamicReferences.begin(); it != sDynamicReferences.end(); ++it) {
- if ( (it->from == from) && (it->to == to) ) {
- OSSpinLockUnlock(&sDynamicReferencesLock);
+ if ( (it->from == from) && (it->to == to) )
return;
- }
- }
-
+ }
//dyld::log("addDynamicReference(%s, %s\n", from->getShortName(), to->getShortName());
ImageLoader::DynamicReference t;
t.from = from;
t.to = to;
sDynamicReferences.push_back(t);
- OSSpinLockUnlock(&sDynamicReferencesLock);
-}
-
+}
+
static void addImage(ImageLoader* image)
{
// add to master list
@@ -993,11 +976,9 @@
// tell all registered remove image handlers about this
// do this before removing image from internal data structures so that the callback can query dyld about the image
if ( image->getState() >= dyld_image_state_bound ) {
- sRemoveImageCallbacksInUse = true; // This only runs inside dyld's global lock, so ok to use a global for the in-use flag.
for (std::vector<ImageCallback>::iterator it=sRemoveImageCallbacks.begin(); it != sRemoveImageCallbacks.end(); it++) {
(*it)(image->machHeader(), image->getSlide());
}
- sRemoveImageCallbacksInUse = false;
}
// notify
@@ -1017,9 +998,7 @@
allImagesUnlock();
// remove from sDynamicReferences
- OSSpinLockLock(&sDynamicReferencesLock);
- sDynamicReferences.erase(std::remove_if(sDynamicReferences.begin(), sDynamicReferences.end(), RefUsesImage(image)), sDynamicReferences.end());
- OSSpinLockUnlock(&sDynamicReferencesLock);
+ sDynamicReferences.erase(std::remove_if(sDynamicReferences.begin(), sDynamicReferences.end(), RefUsesImage(image)), sDynamicReferences.end());
// flush find-by-address cache (do this after removed from master list, so there is no chance it can come back)
if ( sLastImageByAddressCache == image )
@@ -1043,7 +1022,7 @@
}
-void runImageStaticTerminators(ImageLoader* image)
+void runImageTerminators(ImageLoader* image)
{
// if in termination list, pull it out and run terminator
bool mightBeMore;
@@ -1052,13 +1031,17 @@
for (std::vector<ImageLoader*>::iterator it=sImageFilesNeedingTermination.begin(); it != sImageFilesNeedingTermination.end(); it++) {
if ( *it == image ) {
sImageFilesNeedingTermination.erase(it);
- if (gLogAPIs) dyld::log("dlclose(), running static terminators for %p %s\n", image, image->getShortName());
image->doTermination(gLinkContext);
mightBeMore = true;
break;
}
}
} while ( mightBeMore );
+
+ // <rdar://problem/7740779> dyld should directly call __cxa_finalize()
+ if ( (gLibSystemHelpers != NULL) && (gLibSystemHelpers->version >= 8) )
+ (*gLibSystemHelpers->cxa_finalize)(image->machHeader());
+
}
static void terminationRecorder(ImageLoader* image)
@@ -1071,11 +1054,51 @@
return sExecPath;
}
-static void runAllStaticTerminators(void* extra)
+
+void initializeMainExecutable()
+{
+ // record that we've reached this step
+ gLinkContext.startedInitializingMainExecutable = true;
+
+ // run initialzers for any inserted dylibs
+ ImageLoader::InitializerTimingList initializerTimes[sAllImages.size()];
+ const int rootCount = sImageRoots.size();
+ if ( rootCount > 1 ) {
+ for(int i=1; i < rootCount; ++i) {
+ initializerTimes[0].count = 0;
+ sImageRoots[i]->runInitializers(gLinkContext, initializerTimes[0]);
+ }
+ }
+
+ // run initializers for main executable and everything it brings up
+ initializerTimes[0].count = 0;
+ sMainExecutable->runInitializers(gLinkContext, initializerTimes[0]);
+
+ // register atexit() handler to run terminators in all loaded images when this process exits
+ if ( gLibSystemHelpers != NULL )
+ (*gLibSystemHelpers->cxa_atexit)(&runTerminators, NULL, NULL);
+
+ // dump info if requested
+ if ( sEnv.DYLD_PRINT_STATISTICS )
+ ImageLoaderMachO::printStatistics(sAllImages.size(), initializerTimes[0]);
+}
+
+bool mainExecutablePrebound()
+{
+ return sMainExecutable->usablePrebinding(gLinkContext);
+}
+
+ImageLoader* mainExecutable()
+{
+ return sMainExecutable;
+}
+
+
+void runTerminators(void* extra)
{
try {
- const size_t imageCount = sImageFilesNeedingTermination.size();
- for(size_t i=imageCount; i > 0; --i){
+ const unsigned int imageCount = sImageFilesNeedingTermination.size();
+ for(unsigned int i=imageCount; i > 0; --i){
ImageLoader* image = sImageFilesNeedingTermination[i-1];
image->doTermination(gLinkContext);
}
@@ -1086,45 +1109,6 @@
halt(msg);
}
}
-
-void initializeMainExecutable()
-{
- // record that we've reached this step
- gLinkContext.startedInitializingMainExecutable = true;
-
- // run initialzers for any inserted dylibs
- ImageLoader::InitializerTimingList initializerTimes[sAllImages.size()];
- initializerTimes[0].count = 0;
- const size_t rootCount = sImageRoots.size();
- if ( rootCount > 1 ) {
- for(size_t i=1; i < rootCount; ++i) {
- sImageRoots[i]->runInitializers(gLinkContext, initializerTimes[0]);
- }
- }
-
- // run initializers for main executable and everything it brings up
- sMainExecutable->runInitializers(gLinkContext, initializerTimes[0]);
-
- // register cxa_atexit() handler to run static terminators in all loaded images when this process exits
- if ( gLibSystemHelpers != NULL )
- (*gLibSystemHelpers->cxa_atexit)(&runAllStaticTerminators, NULL, NULL);
-
- // dump info if requested
- if ( sEnv.DYLD_PRINT_STATISTICS )
- ImageLoaderMachO::printStatistics((unsigned int)sAllImages.size(), initializerTimes[0]);
-}
-
-bool mainExecutablePrebound()
-{
- return sMainExecutable->usablePrebinding(gLinkContext);
-}
-
-ImageLoader* mainExecutable()
-{
- return sMainExecutable;
-}
-
-
#if SUPPORT_VERSIONED_PATHS
@@ -1142,7 +1126,7 @@
//dyld::log("checkDylibOverride('%s')\n", dylibFile);
uint32_t altVersion;
char sysInstallName[PATH_MAX];
- if ( getDylibVersionAndInstallname(dylibFile, &altVersion, sysInstallName) && (sysInstallName[0] =='/') ) {
+ if ( getDylibVersionAndInstallname(dylibFile, &altVersion, sysInstallName) ) {
//dyld::log("%s has version 0x%08X and install name %s\n", dylibFile, altVersion, sysInstallName);
uint32_t sysVersion;
if ( getDylibVersionAndInstallname(sysInstallName, &sysVersion, NULL) ) {
@@ -1190,8 +1174,8 @@
{
//dyld::log("checkDylibOverridesInDir('%s')\n", dirPath);
char dylibPath[PATH_MAX];
- if ( strlcpy(dylibPath, dirPath, PATH_MAX) >= PATH_MAX )
- return;
+ int dirPathLen = strlen(dirPath);
+ strlcpy(dylibPath, dirPath, PATH_MAX);
DIR* dirp = opendir(dirPath);
if ( dirp != NULL) {
dirent entry;
@@ -1201,9 +1185,9 @@
break;
if ( entp->d_type != DT_REG )
continue;
- if ( strlcat(dylibPath, "/", PATH_MAX) >= PATH_MAX )
- continue;
- if ( strlcat(dylibPath, entp->d_name, PATH_MAX) >= PATH_MAX )
+ dylibPath[dirPathLen] = '/';
+ dylibPath[dirPathLen+1] = '\0';
+ if ( strlcat(dylibPath, entp->d_name, PATH_MAX) > PATH_MAX )
continue;
checkDylibOverride(dylibPath);
}
@@ -1216,8 +1200,8 @@
{
//dyld::log("checkFrameworkOverridesInDir('%s')\n", dirPath);
char frameworkPath[PATH_MAX];
- if ( strlcpy(frameworkPath, dirPath, PATH_MAX) >= PATH_MAX )
- return;
+ int dirPathLen = strlen(dirPath);
+ strlcpy(frameworkPath, dirPath, PATH_MAX);
DIR* dirp = opendir(dirPath);
if ( dirp != NULL) {
dirent entry;
@@ -1227,18 +1211,18 @@
break;
if ( entp->d_type != DT_DIR )
continue;
- if ( strlcat(frameworkPath, "/", PATH_MAX) >= PATH_MAX )
- continue;
+ frameworkPath[dirPathLen] = '/';
+ frameworkPath[dirPathLen+1] = '\0';
int dirNameLen = strlen(entp->d_name);
if ( dirNameLen < 11 )
continue;
if ( strcmp(&entp->d_name[dirNameLen-10], ".framework") != 0 )
continue;
- if ( strlcat(frameworkPath, entp->d_name, PATH_MAX) >= PATH_MAX )
+ if ( strlcat(frameworkPath, entp->d_name, PATH_MAX) > PATH_MAX )
continue;
- if ( strlcat(frameworkPath, "/", PATH_MAX) >= PATH_MAX )
+ if ( strlcat(frameworkPath, "/", PATH_MAX) > PATH_MAX )
continue;
- if ( strlcat(frameworkPath, entp->d_name, PATH_MAX) >= PATH_MAX )
+ if ( strlcat(frameworkPath, entp->d_name, PATH_MAX) > PATH_MAX )
continue;
frameworkPath[strlen(frameworkPath)-10] = '\0';
checkDylibOverride(frameworkPath);
@@ -1272,9 +1256,9 @@
char** result = new char*[colonCount+2];
for(const char* s=list; *s != '\0'; ++s) {
if (*s == ':') {
- size_t len = s-start;
+ int len = s-start;
if ( (mainExecutableDir != NULL) && (strncmp(start, "@loader_path/", 13) == 0) ) {
- size_t mainExecDirLen = strlen(mainExecutableDir);
+ int mainExecDirLen = strlen(mainExecutableDir);
char* str = new char[mainExecDirLen+len+1];
strcpy(str, mainExecutableDir);
strlcat(str, &start[13], mainExecDirLen+len+1);
@@ -1283,7 +1267,7 @@
result[index++] = str;
}
else if ( (mainExecutableDir != NULL) && (strncmp(start, "@executable_path/", 17) == 0) ) {
- size_t mainExecDirLen = strlen(mainExecutableDir);
+ int mainExecDirLen = strlen(mainExecutableDir);
char* str = new char[mainExecDirLen+len+1];
strcpy(str, mainExecutableDir);
strlcat(str, &start[17], mainExecDirLen+len+1);
@@ -1300,9 +1284,9 @@
}
}
}
- size_t len = strlen(start);
+ int len = strlen(start);
if ( (mainExecutableDir != NULL) && (strncmp(start, "@loader_path/", 13) == 0) ) {
- size_t mainExecDirLen = strlen(mainExecutableDir);
+ int mainExecDirLen = strlen(mainExecutableDir);
char* str = new char[mainExecDirLen+len+1];
strcpy(str, mainExecutableDir);
strlcat(str, &start[13], mainExecDirLen+len+1);
@@ -1310,7 +1294,7 @@
result[index++] = str;
}
else if ( (mainExecutableDir != NULL) && (strncmp(start, "@executable_path/", 17) == 0) ) {
- size_t mainExecDirLen = strlen(mainExecutableDir);
+ int mainExecDirLen = strlen(mainExecutableDir);
char* str = new char[mainExecDirLen+len+1];
strcpy(str, mainExecutableDir);
strlcat(str, &start[17], mainExecDirLen+len+1);
@@ -1575,18 +1559,6 @@
appendParsedColonList(value, mainExecutableDir, &sEnv.DYLD_VERSIONED_FRAMEWORK_PATH);
}
#endif
-#if !TARGET_IPHONE_SIMULATOR
- else if ( (strcmp(key, "DYLD_PRINT_TO_FILE") == 0) && (mainExecutableDir == NULL) ) {
- int fd = open(value, O_WRONLY | O_CREAT | O_APPEND, 0644);
- if ( fd != -1 ) {
- sLogfile = fd;
- sLogToFile = true;
- }
- else {
- dyld::log("dyld: could not open DYLD_PRINT_TO_FILE='%s', errno=%d\n", value, errno);
- }
- }
-#endif
else {
dyld::warn("unknown environment variable: %s\n", key);
}
@@ -1606,7 +1578,7 @@
{
const struct dylinker_command* envcmd = (struct dylinker_command*)cmd;
const char* keyEqualsValue = (char*)envcmd + envcmd->name.offset;
- char mainExecutableDir[strlen(sExecPath)+2];
+ char mainExecutableDir[strlen(sExecPath)];
strcpy(mainExecutableDir, sExecPath);
char* lastSlash = strrchr(mainExecutableDir, '/');
if ( lastSlash != NULL)
@@ -1617,16 +1589,13 @@
if ( equals != NULL ) {
if ( strncmp(&equals[-5], "_PATH", 5) == 0 ) {
const char* value = &equals[1];
- const size_t keyLen = equals-keyEqualsValue;
- // <rdar://problem/22799635> don't let malformed load command overflow stack
- if ( keyLen < 40 ) {
- char key[keyLen+1];
- strncpy(key, keyEqualsValue, keyLen);
- key[keyLen] = '\0';
- //dyld::log("processing: %s\n", keyEqualsValue);
- //dyld::log("mainExecutableDir: %s\n", mainExecutableDir);
- processDyldEnvironmentVariable(key, value, mainExecutableDir);
- }
+ const int keyLen = equals-keyEqualsValue;
+ char key[keyLen+1];
+ strncpy(key, keyEqualsValue, keyLen);
+ key[keyLen] = '\0';
+ //dyld::log("processing: %s\n", keyEqualsValue);
+ //dyld::log("mainExecutableDir: %s\n", mainExecutableDir);
+ processDyldEnvironmentVariable(key, value, mainExecutableDir);
}
}
}
@@ -1724,62 +1693,29 @@
// disable framework and library fallback paths for setuid binaries rdar://problem/4589305
sEnv.DYLD_FALLBACK_FRAMEWORK_PATH = NULL;
sEnv.DYLD_FALLBACK_LIBRARY_PATH = NULL;
-
- if ( removedCount > 0 )
- strlcat(sLoadingCrashMessage, ", ignoring DYLD_* env vars", sizeof(sLoadingCrashMessage));
-}
-
-static void defaultUninitializedFallbackPaths(const char* envp[])
-{
-#if __MAC_OS_X_VERSION_MIN_REQUIRED
- // default value for DYLD_FALLBACK_FRAMEWORK_PATH, if not set in environment
- const char* home = _simple_getenv(envp, "HOME");;
- if ( sEnv.DYLD_FALLBACK_FRAMEWORK_PATH == NULL ) {
- const char** fpaths = sFrameworkFallbackPaths;
- if ( home == NULL )
- removePathWithPrefix(fpaths, "$HOME");
- else
- paths_expand_roots(fpaths, "$HOME", home);
- sEnv.DYLD_FALLBACK_FRAMEWORK_PATH = fpaths;
- }
-
- // default value for DYLD_FALLBACK_LIBRARY_PATH, if not set in environment
- if ( sEnv.DYLD_FALLBACK_LIBRARY_PATH == NULL ) {
- const char** lpaths = sLibraryFallbackPaths;
- if ( home == NULL )
- removePathWithPrefix(lpaths, "$HOME");
- else
- paths_expand_roots(lpaths, "$HOME", home);
- sEnv.DYLD_FALLBACK_LIBRARY_PATH = lpaths;
- }
-#else
- if ( sEnv.DYLD_FALLBACK_FRAMEWORK_PATH == NULL )
- sEnv.DYLD_FALLBACK_FRAMEWORK_PATH = sFrameworkFallbackPaths;
-
- if ( sEnv.DYLD_FALLBACK_LIBRARY_PATH == NULL )
- sEnv.DYLD_FALLBACK_LIBRARY_PATH = sLibraryFallbackPaths;
-#endif
-}
-
-
-static void checkEnvironmentVariables(const char* envp[])
-{
+}
+
+
+static void checkEnvironmentVariables(const char* envp[], bool ignoreEnviron)
+{
+ const char* home = NULL;
const char** p;
for(p = envp; *p != NULL; p++) {
const char* keyEqualsValue = *p;
if ( strncmp(keyEqualsValue, "DYLD_", 5) == 0 ) {
const char* equals = strchr(keyEqualsValue, '=');
- if ( equals != NULL ) {
- strlcat(sLoadingCrashMessage, "\n", sizeof(sLoadingCrashMessage));
- strlcat(sLoadingCrashMessage, keyEqualsValue, sizeof(sLoadingCrashMessage));
+ if ( (equals != NULL) && !ignoreEnviron ) {
const char* value = &equals[1];
- const size_t keyLen = equals-keyEqualsValue;
+ const int keyLen = equals-keyEqualsValue;
char key[keyLen+1];
strncpy(key, keyEqualsValue, keyLen);
key[keyLen] = '\0';
processDyldEnvironmentVariable(key, value, NULL);
}
}
+ else if ( strncmp(keyEqualsValue, "HOME=", 5) == 0 ) {
+ home = &keyEqualsValue[5];
+ }
else if ( strncmp(keyEqualsValue, "LD_LIBRARY_PATH=", 16) == 0 ) {
const char* path = &keyEqualsValue[16];
sEnv.LD_LIBRARY_PATH = parseColonList(path, NULL);
@@ -1789,50 +1725,43 @@
#if SUPPORT_LC_DYLD_ENVIRONMENT
checkLoadCommandEnvironmentVariables();
#endif // SUPPORT_LC_DYLD_ENVIRONMENT
+
+ // default value for DYLD_FALLBACK_FRAMEWORK_PATH, if not set in environment
+ if ( sEnv.DYLD_FALLBACK_FRAMEWORK_PATH == NULL ) {
+ const char** paths = sFrameworkFallbackPaths;
+ if ( home == NULL )
+ removePathWithPrefix(paths, "$HOME");
+ else
+ paths_expand_roots(paths, "$HOME", home);
+ sEnv.DYLD_FALLBACK_FRAMEWORK_PATH = paths;
+ }
+
+ // default value for DYLD_FALLBACK_LIBRARY_PATH, if not set in environment
+ if ( sEnv.DYLD_FALLBACK_LIBRARY_PATH == NULL ) {
+ const char** paths = sLibraryFallbackPaths;
+ if ( home == NULL )
+ removePathWithPrefix(paths, "$HOME");
+ else
+ paths_expand_roots(paths, "$HOME", home);
+ sEnv.DYLD_FALLBACK_LIBRARY_PATH = paths;
+ }
// <rdar://problem/11281064> DYLD_IMAGE_SUFFIX and DYLD_ROOT_PATH cannot be used together
if ( (gLinkContext.imageSuffix != NULL) && (gLinkContext.rootPaths != NULL) ) {
dyld::warn("Ignoring DYLD_IMAGE_SUFFIX because DYLD_ROOT_PATH is used.\n");
gLinkContext.imageSuffix = NULL;
}
-}
-
-#if __x86_64__
-static bool isGCProgram(const macho_header* mh, uintptr_t slide)
-{
- 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_SEGMENT_COMMAND:
- {
- const struct macho_segment_command* seg = (struct macho_segment_command*)cmd;
- if (strcmp(seg->segname, "__DATA") == 0) {
- const struct macho_section* const sectionsStart = (struct macho_section*)((char*)seg + sizeof(struct macho_segment_command));
- const struct macho_section* const sectionsEnd = §ionsStart[seg->nsects];
- for (const struct macho_section* sect=sectionsStart; sect < sectionsEnd; ++sect) {
- if (strncmp(sect->sectname, "__objc_imageinfo", 16) == 0) {
- const uint32_t* objcInfo = (uint32_t*)(sect->addr + slide);
- return (objcInfo[1] & 6); // 6 = (OBJC_IMAGE_SUPPORTS_GC | OBJC_IMAGE_REQUIRES_GC)
- }
- }
- }
- }
- break;
- }
- cmd = (const struct load_command*)(((char*)cmd)+cmd->cmdsize);
- }
- return false;
-}
-#endif
-static void getHostInfo(const macho_header* mainExecutableMH, uintptr_t mainExecutableSlide)
+
+#if SUPPORT_VERSIONED_PATHS
+ checkVersionedPaths();
+#endif
+}
+
+
+static void getHostInfo()
{
#if CPU_SUBTYPES_SUPPORTED
-#if __ARM_ARCH_7K__
- sHostCPU = CPU_TYPE_ARM;
- sHostCPUsubtype = CPU_SUBTYPE_ARM_V7K;
-#elif __ARM_ARCH_7A__
+#if __ARM_ARCH_7A__
sHostCPU = CPU_TYPE_ARM;
sHostCPUsubtype = CPU_SUBTYPE_ARM_V7;
#elif __ARM_ARCH_6K__
@@ -1844,6 +1773,9 @@
#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;
@@ -1853,23 +1785,6 @@
throw "host_info() failed";
sHostCPU = info.cpu_type;
sHostCPUsubtype = info.cpu_subtype;
- mach_port_deallocate(mach_task_self(), hostPort);
- #if __x86_64__
- #if TARGET_IPHONE_SIMULATOR
- sHaswell = false;
- #else
- sHaswell = (sHostCPUsubtype == CPU_SUBTYPE_X86_64_H);
- // <rdar://problem/18528074> x86_64h: Fall back to the x86_64 slice if an app requires GC.
- if ( sHaswell ) {
- if ( isGCProgram(mainExecutableMH, mainExecutableSlide) ) {
- // When running a GC program on a haswell machine, don't use and 'h slices
- sHostCPUsubtype = CPU_SUBTYPE_X86_64_ALL;
- sHaswell = false;
- gLinkContext.sharedRegionMode = ImageLoader::kDontUseSharedRegion;
- }
- }
- #endif
- #endif
#endif
#endif
}
@@ -1884,20 +1799,14 @@
if ( gLinkContext.verboseMapping )
dyld::warn("disabling shared region because main executable overlaps\n");
}
-#if __i386__
- if ( sProcessIsRestricted ) {
- // <rdar://problem/15280847> use private or no shared region for suid processes
- gLinkContext.sharedRegionMode = ImageLoader::kUsePrivateSharedRegion;
- }
-#endif
#endif
// iPhoneOS cannot run without shared region
}
bool validImage(const ImageLoader* possibleImage)
{
- const size_t imageCount = sAllImages.size();
- for(size_t i=0; i < imageCount; ++i) {
+ const unsigned int imageCount = sAllImages.size();
+ for(unsigned int i=0; i < imageCount; ++i) {
if ( possibleImage == sAllImages[i] ) {
return true;
}
@@ -1907,7 +1816,7 @@
uint32_t getImageCount()
{
- return (uint32_t)sAllImages.size();
+ return sAllImages.size();
}
ImageLoader* getIndexedImage(unsigned int index)
@@ -1943,8 +1852,8 @@
void forEachImageDo( void (*callback)(ImageLoader*, void* userData), void* userData)
{
- const size_t imageCount = sAllImages.size();
- for(size_t i=0; i < imageCount; ++i) {
+ const unsigned int imageCount = sAllImages.size();
+ for(unsigned int i=0; i < imageCount; ++i) {
ImageLoader* anImage = sAllImages[i];
(*callback)(anImage, userData);
}
@@ -1952,8 +1861,8 @@
ImageLoader* findLoadedImage(const struct stat& stat_buf)
{
- const size_t imageCount = sAllImages.size();
- for(size_t i=0; i < imageCount; ++i){
+ const unsigned int imageCount = sAllImages.size();
+ for(unsigned int i=0; i < imageCount; ++i){
ImageLoader* anImage = sAllImages[i];
if ( anImage->statMatch(stat_buf) )
return anImage;
@@ -1964,7 +1873,7 @@
// based on ANSI-C strstr()
static const char* strrstr(const char* str, const char* sub)
{
- const size_t sublen = strlen(sub);
+ const int sublen = strlen(sub);
for(const char* p = &str[strlen(str)]; p != str; --p) {
if ( strncmp(p, sub, sublen) == 0 )
return p;
@@ -1994,7 +1903,7 @@
const char* frameworkStart = &dirStart[1];
if ( dirStart == path )
--frameworkStart;
- size_t len = dirDot - frameworkStart;
+ int len = dirDot - frameworkStart;
char framework[len+1];
strncpy(framework, frameworkStart, len);
framework[len] = '\0';
@@ -2057,11 +1966,11 @@
// 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
- { CPU_SUBTYPE_ARM_V7K, 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 },
// armv7s can run: v7s, v7, v7f, v7k, v6, v5, and v4
- { CPU_SUBTYPE_ARM_V7S, CPU_SUBTYPE_ARM_V7, CPU_SUBTYPE_ARM_V7F, CPU_SUBTYPE_ARM_V6, CPU_SUBTYPE_ARM_V5TEJ, CPU_SUBTYPE_ARM_V4T, CPU_SUBTYPE_ARM_ALL, CPU_SUBTYPE_END_OF_LIST },
+ { CPU_SUBTYPE_ARM_V7S, CPU_SUBTYPE_ARM_V7, CPU_SUBTYPE_ARM_V7F, 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 },
@@ -2077,22 +1986,6 @@
// armv4 can run: v4
{ CPU_SUBTYPE_ARM_V4T, CPU_SUBTYPE_ARM_ALL, CPU_SUBTYPE_END_OF_LIST, CPU_SUBTYPE_END_OF_LIST, CPU_SUBTYPE_END_OF_LIST, CPU_SUBTYPE_END_OF_LIST },
-};
-#endif
-
-#if __x86_64__
-//
-// x86_64 sub-type lists
-//
-const int kX86_64_RowCount = 2;
-static const cpu_subtype_t kX86_64[kX86_64_RowCount][5] = {
-
- // x86_64h can run: x86_64h, x86_64h(lib), x86_64(lib), and x86_64
- { CPU_SUBTYPE_X86_64_H, CPU_SUBTYPE_LIB64|CPU_SUBTYPE_X86_64_H, CPU_SUBTYPE_LIB64|CPU_SUBTYPE_X86_64_ALL, CPU_SUBTYPE_X86_64_ALL, CPU_SUBTYPE_END_OF_LIST },
-
- // x86_64 can run: x86_64(lib) and x86_64
- { CPU_SUBTYPE_X86_64_ALL, CPU_SUBTYPE_LIB64|CPU_SUBTYPE_X86_64_ALL, CPU_SUBTYPE_END_OF_LIST },
-
};
#endif
@@ -2106,14 +1999,6 @@
for (int i=0; i < kARM_RowCount ; ++i) {
if ( kARM[i][0] == subtype )
return kARM[i];
- }
- break;
-#endif
-#if __x86_64__
- case CPU_TYPE_X86_64:
- for (int i=0; i < kX86_64_RowCount ; ++i) {
- if ( kX86_64[i][0] == subtype )
- return kX86_64[i];
}
break;
#endif
@@ -2166,15 +2051,6 @@
#if __arm__
case CPU_TYPE_ARM:
if ( (cpu_subtype_t)OSSwapBigToHostInt32(archs[i].cpusubtype) == CPU_SUBTYPE_ARM_ALL ) {
- *offset = OSSwapBigToHostInt32(archs[i].offset);
- *len = OSSwapBigToHostInt32(archs[i].size);
- return true;
- }
- break;
-#endif
-#if __x86_64__
- case CPU_TYPE_X86_64:
- if ( (cpu_subtype_t)OSSwapBigToHostInt32(archs[i].cpusubtype) == CPU_SUBTYPE_X86_64_ALL ) {
*offset = OSSwapBigToHostInt32(archs[i].offset);
*len = OSSwapBigToHostInt32(archs[i].size);
return true;
@@ -2303,7 +2179,7 @@
#if DYLD_SHARED_CACHE_SUPPORT
-static bool findInSharedCacheImage(const char* path, bool searchByPath, const struct stat* stat_buf, const macho_header** mh, const char** pathInCache, long* slide)
+static bool findInSharedCacheImage(const char* path, const struct stat* stat_buf, const macho_header** mh, const char** pathInCache, long* slide)
{
if ( sSharedCache != NULL ) {
#if __MAC_OS_X_VERSION_MIN_REQUIRED
@@ -2316,24 +2192,13 @@
stat_buf = &statb;
}
#endif
-#if __IPHONE_OS_VERSION_MIN_REQUIRED
- uint64_t hash = 0;
- for (const char* s=path; *s != '\0'; ++s)
- hash += hash*4 + *s;
-#endif
-
// walk shared cache to see if there is a cached image that matches the inode/mtime/path desired
const dyld_cache_image_info* const start = (dyld_cache_image_info*)((uint8_t*)sSharedCache + sSharedCache->imagesOffset);
const dyld_cache_image_info* const end = &start[sSharedCache->imagesCount];
-#if __IPHONE_OS_VERSION_MIN_REQUIRED
- const bool cacheHasHashInfo = (start->modTime == 0);
-#endif
for( const dyld_cache_image_info* p = start; p != end; ++p) {
#if __IPHONE_OS_VERSION_MIN_REQUIRED
// just check path
const char* aPath = (char*)sSharedCache + p->pathFileOffset;
- if ( cacheHasHashInfo && (p->inode != hash) )
- continue;
if ( strcmp(path, aPath) == 0 ) {
// found image in cache
*mh = (macho_header*)(p->address+sSharedCacheSlide);
@@ -2343,12 +2208,12 @@
}
#elif __MAC_OS_X_VERSION_MIN_REQUIRED
// check mtime and inode first because it is fast
- bool inodeMatch = ( ((time_t)p->modTime == stat_buf->st_mtime) && ((ino_t)p->inode == stat_buf->st_ino) );
- if ( searchByPath || sSharedCacheIgnoreInodeAndTimeStamp || inodeMatch ) {
+ if ( sSharedCacheIgnoreInodeAndTimeStamp
+ || ( ((time_t)p->modTime == stat_buf->st_mtime) && ((ino_t)p->inode == stat_buf->st_ino) ) ) {
// mod-time and inode match an image in the shared cache, now check path
const char* aPath = (char*)sSharedCache + p->pathFileOffset;
bool cacheHit = (strcmp(path, aPath) == 0);
- if ( inodeMatch && !cacheHit ) {
+ if ( ! cacheHit ) {
// path does not match install name of dylib in cache, but inode and mtime does match
// perhaps path is a symlink to the cached dylib
struct stat pathInCacheStatBuf;
@@ -2376,7 +2241,7 @@
const macho_header* mhInCache;
const char* pathInCache;
long slide;
- return findInSharedCacheImage(path, true, NULL, &mhInCache, &pathInCache, &slide);
+ return findInSharedCacheImage(path, NULL, &mhInCache, &pathInCache, &slide);
}
#endif
@@ -2419,34 +2284,6 @@
return image;
}
-#if TARGET_IPHONE_SIMULATOR
-static bool isSimulatorBinary(const uint8_t* firstPage, const char* path)
-{
- const macho_header* mh = (macho_header*)firstPage;
- 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* const cmdsReadEnd = (struct load_command*)(((char*)mh)+4096);
- const struct load_command* cmd = cmds;
- for (uint32_t i = 0; i < cmd_count; ++i) {
- switch (cmd->cmd) {
- case LC_VERSION_MIN_IPHONEOS:
- case LC_VERSION_MIN_TVOS:
- case LC_VERSION_MIN_WATCHOS:
- return true;
- case LC_VERSION_MIN_MACOSX:
- // grandfather in a few libSystem dylibs
- if (strstr(path, "/usr/lib/system") || strstr(path, "/usr/lib/libSystem"))
- return true;
- return false;
- }
- cmd = (const struct load_command*)(((char*)cmd)+cmd->cmdsize);
- if ( cmd > cmdsReadEnd )
- return true;
- }
- return false;
-}
-#endif
-
// map in file and instantiate an ImageLoader
static ImageLoader* loadPhase6(int fd, const struct stat& stat_buf, const char* path, const LoadContext& context)
{
@@ -2500,18 +2337,7 @@
default:
throw "mach-o, but wrong filetype";
}
-
-#if TARGET_IPHONE_SIMULATOR
- #if TARGET_OS_WATCH || TARGET_OS_TV
- // disable error during bring up of these simulators
- #else
- // <rdar://problem/14168872> dyld_sim should restrict loading osx binaries
- if ( !isSimulatorBinary(firstPage, path) ) {
- throw "mach-o, but not built for iOS simulator";
- }
- #endif
-#endif
-
+
// instantiate an image
ImageLoader* image = ImageLoaderMachO::instantiateFromFile(path, fd, firstPage, fileOffset, fileLength, stat_buf, gLinkContext);
@@ -2595,7 +2421,7 @@
const macho_header* mhInCache;
const char* pathInCache;
long slideInCache;
- if ( findInSharedCacheImage(path, false, &stat_buf, &mhInCache, &pathInCache, &slideInCache) ) {
+ if ( findInSharedCacheImage(path, &stat_buf, &mhInCache, &pathInCache, &slideInCache) ) {
image = ImageLoaderMachO::instantiateFromCache(mhInCache, pathInCache, slideInCache, stat_buf, gLinkContext);
return checkandAddImage(image, context);
}
@@ -2657,7 +2483,7 @@
const macho_header* mhInCache;
const char* pathInCache;
long slideInCache;
- if ( findInSharedCacheImage(path, true, NULL, &mhInCache, &pathInCache, &slideInCache) ) {
+ if ( findInSharedCacheImage(path, NULL, &mhInCache, &pathInCache, &slideInCache) ) {
// 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;
@@ -2785,7 +2611,7 @@
ImageLoader* image = NULL;
if ( strncmp(path, "@executable_path/", 17) == 0 ) {
// executable_path cannot be in used in any binary in a setuid process rdar://problem/4589305
- if ( sProcessIsRestricted && !sProcessRequiresLibraryValidation )
+ if ( sProcessIsRestricted )
throwf("unsafe use of @executable_path in %s with restricted binary", context.origin);
// handle @executable_path path prefix
const char* executablePath = sExecPath;
@@ -2817,7 +2643,7 @@
}
else if ( (strncmp(path, "@loader_path/", 13) == 0) && (context.origin != NULL) ) {
// @loader_path cannot be used from the main executable of a setuid process rdar://problem/4589305
- if ( sProcessIsRestricted && (strcmp(context.origin, sExecPath) == 0) && !sProcessRequiresLibraryValidation )
+ if ( sProcessIsRestricted && (strcmp(context.origin, sExecPath) == 0) )
throwf("unsafe use of @loader_path in %s with restricted binary", context.origin);
// handle @loader_path path prefix
char newPath[strlen(context.origin) + strlen(path)];
@@ -2881,7 +2707,7 @@
if ( (exceptions != NULL) && (trailingPath != path) )
return NULL;
}
- else if (sProcessIsRestricted && (path[0] != '/' ) && !sProcessRequiresLibraryValidation) {
+ else if (sProcessIsRestricted && (path[0] != '/' )) {
throwf("unsafe use of relative rpath %s in %s with restricted binary", path, context.origin);
}
@@ -2899,7 +2725,7 @@
const char* frameworkPartialPath = getFrameworkPartialPath(path);
if ( frameworkPaths != NULL ) {
if ( frameworkPartialPath != NULL ) {
- const size_t frameworkPartialPathLen = strlen(frameworkPartialPath);
+ const int frameworkPartialPathLen = strlen(frameworkPartialPath);
for(const char* const* fp = frameworkPaths; *fp != NULL; ++fp) {
char npath[strlen(*fp)+frameworkPartialPathLen+8];
strcpy(npath, *fp);
@@ -2916,7 +2742,7 @@
// <rdar://problem/14160846> Some apps depend on frameworks being found via library paths
if ( (libraryPaths != NULL) && ((frameworkPartialPath == NULL) || sFrameworksFoundAsDylibs) ) {
const char* libraryLeafName = getLibraryLeafName(path);
- const size_t libraryLeafNameLen = strlen(libraryLeafName);
+ const int libraryLeafNameLen = strlen(libraryLeafName);
for(const char* const* lp = libraryPaths; *lp != NULL; ++lp) {
char libpath[strlen(*lp)+libraryLeafNameLen+8];
strcpy(libpath, *lp);
@@ -2989,16 +2815,6 @@
// try raw path
return loadPhase1(path, orgPath, context, exceptions);
}
-
-#if DYLD_SHARED_CACHE_SUPPORT
- static bool cacheablePath(const char* path) {
- if (strncmp(path, "/usr/lib/", 9) == 0)
- return true;
- if (strncmp(path, "/System/Library/", 16) == 0)
- return true;
- return false;
- }
-#endif
//
// Given all the DYLD_ environment variables, the general case for loading libraries
@@ -3037,44 +2853,19 @@
// try all path permutations and try open() until first success
std::vector<const char*> exceptions;
image = loadPhase0(path, orgPath, context, &exceptions);
-#if __IPHONE_OS_VERSION_MIN_REQUIRED && DYLD_SHARED_CACHE_SUPPORT && !TARGET_IPHONE_SIMULATOR
- // <rdar://problem/16704628> support symlinks on disk to a path in dyld shared cache
- if ( (image == NULL) && cacheablePath(path) && !context.dontLoad ) {
- char resolvedPath[PATH_MAX];
- realpath(path, resolvedPath);
- int myerr = errno;
- // If realpath() resolves to a path which does not exist on disk, errno is set to ENOENT
- if ( (myerr == ENOENT) || (myerr == 0) )
- {
- // see if this image is in shared cache
- const macho_header* mhInCache;
- const char* pathInCache;
- long slideInCache;
- if ( findInSharedCacheImage(resolvedPath, false, NULL, &mhInCache, &pathInCache, &slideInCache) ) {
- struct stat stat_buf;
- bzero(&stat_buf, sizeof(stat_buf));
- try {
- image = ImageLoaderMachO::instantiateFromCache(mhInCache, pathInCache, slideInCache, stat_buf, gLinkContext);
- image = checkandAddImage(image, context);
- }
- catch (...) {
- image = NULL;
- }
- }
- }
- }
-#endif
CRSetCrashLogMessage2(NULL);
if ( image != NULL ) {
// <rdar://problem/6916014> leak in dyld during dlopen when using DYLD_ variables
for (std::vector<const char*>::iterator it = exceptions.begin(); it != exceptions.end(); ++it) {
free((void*)(*it));
}
-#if DYLD_SHARED_CACHE_SUPPORT
+#if __IPHONE_OS_VERSION_MIN_REQUIRED && DYLD_SHARED_CACHE_SUPPORT
// if loaded image is not from cache, but original path is in cache
// set gSharedCacheOverridden flag to disable some ObjC optimizations
- if ( !gSharedCacheOverridden && !image->inSharedCache() && image->isDylib() && cacheablePath(path) && inSharedCache(path) ) {
- gSharedCacheOverridden = true;
+ if ( !gSharedCacheOverridden ) {
+ if ( !image->inSharedCache() && inSharedCache(path) ) {
+ gSharedCacheOverridden = true;
+ }
}
#endif
return image;
@@ -3090,11 +2881,11 @@
const char* msgStart = "no suitable image found. Did find:";
const char* delim = "\n\t";
size_t allsizes = strlen(msgStart)+8;
- for (size_t i=0; i < exceptions.size(); ++i)
+ for (unsigned int i=0; i < exceptions.size(); ++i)
allsizes += (strlen(exceptions[i]) + strlen(delim));
char* fullMsg = new char[allsizes];
strcpy(fullMsg, msgStart);
- for (size_t i=0; i < exceptions.size(); ++i) {
+ for (unsigned int i=0; i < exceptions.size(); ++i) {
strcat(fullMsg, delim);
strcat(fullMsg, exceptions[i]);
free((void*)exceptions[i]);
@@ -3115,8 +2906,6 @@
#elif __x86_64__
#define ARCH_NAME "x86_64"
#define ARCH_CACHE_MAGIC "dyld_v1 x86_64"
- #define ARCH_NAME_H "x86_64h"
- #define ARCH_CACHE_MAGIC_H "dyld_v1 x86_64h"
#elif __ARM_ARCH_5TEJ__
#define ARCH_NAME "armv5"
#define ARCH_CACHE_MAGIC "dyld_v1 armv5"
@@ -3126,18 +2915,15 @@
#elif __ARM_ARCH_7F__
#define ARCH_NAME "armv7f"
#define ARCH_CACHE_MAGIC "dyld_v1 armv7f"
-#elif __ARM_ARCH_7K__
- #define ARCH_NAME "armv7k"
- #define ARCH_CACHE_MAGIC "dyld_v1 armv7k"
#elif __ARM_ARCH_7A__
#define ARCH_NAME "armv7"
#define ARCH_CACHE_MAGIC "dyld_v1 armv7"
#elif __ARM_ARCH_7S__
#define ARCH_NAME "armv7s"
#define ARCH_CACHE_MAGIC "dyld_v1 armv7s"
-#elif __arm64__
- #define ARCH_NAME "arm64"
- #define ARCH_CACHE_MAGIC "dyld_v1 arm64"
+#elif __ARM_ARCH_7K__
+ #define ARCH_NAME "armv7k"
+ #define ARCH_CACHE_MAGIC "dyld_v1 armv7k"
#endif
@@ -3150,7 +2936,7 @@
static int __attribute__((noinline)) _shared_region_map_and_slide_np(int fd, uint32_t count, const shared_file_mapping_np mappings[],
- int codeSignatureMappingIndex, long slide, void* slideInfo, unsigned long slideInfoSize)
+ int codeSignatureMappingIndex, int slide, void* slideInfo, uint32_t slideInfoSize)
{
// register code signature blob for whole dyld cache
if ( codeSignatureMappingIndex != -1 ) {
@@ -3243,63 +3029,13 @@
return sSharedCache;
}
-const char* getStandardSharedCacheFilePath()
-{
-#if __IPHONE_OS_VERSION_MIN_REQUIRED
- return IPHONE_DYLD_SHARED_CACHE_DIR DYLD_SHARED_CACHE_BASE_NAME ARCH_NAME;
-#else
- #if __x86_64__
- if ( sHaswell ) {
- const char* path2 = MACOSX_DYLD_SHARED_CACHE_DIR DYLD_SHARED_CACHE_BASE_NAME ARCH_NAME_H;
- struct stat statBuf;
- if ( my_stat(path2, &statBuf) == 0 )
- return path2;
- }
- #endif
- return MACOSX_DYLD_SHARED_CACHE_DIR DYLD_SHARED_CACHE_BASE_NAME ARCH_NAME;
-#endif
-}
-
int openSharedCacheFile()
{
char path[MAXPATHLEN];
strlcpy(path, sSharedCacheDir, MAXPATHLEN);
strlcat(path, "/", MAXPATHLEN);
-#if __x86_64__
- if ( sHaswell ) {
- strlcat(path, DYLD_SHARED_CACHE_BASE_NAME ARCH_NAME_H, MAXPATHLEN);
- int fd = my_open(path, O_RDONLY, 0);
- if ( fd != -1 ) {
- if ( gLinkContext.verboseMapping )
- dyld::log("dyld: Mapping%s shared cache from %s\n", (gLinkContext.sharedRegionMode == ImageLoader::kUsePrivateSharedRegion) ? " private": "", path);
- return fd;
- }
- strlcpy(path, sSharedCacheDir, MAXPATHLEN);
- }
-#endif
strlcat(path, DYLD_SHARED_CACHE_BASE_NAME ARCH_NAME, MAXPATHLEN);
- if ( gLinkContext.verboseMapping )
- dyld::log("dyld: Mapping%s shared cache from %s\n", (gLinkContext.sharedRegionMode == ImageLoader::kUsePrivateSharedRegion) ? " private": "", path);
return my_open(path, O_RDONLY, 0);
-}
-
-
-static void getCacheBounds(uint32_t mappingsCount, const shared_file_mapping_np mappings[], uint64_t& lowAddress, uint64_t& highAddress)
-{
- lowAddress = 0;
- highAddress = 0;
- for(uint32_t i=0; i < mappingsCount; ++i) {
- if ( lowAddress == 0 ) {
- lowAddress = mappings[i].sfm_address;
- highAddress = mappings[i].sfm_address + mappings[i].sfm_size;
- }
- else {
- if ( mappings[i].sfm_address < lowAddress )
- lowAddress = mappings[i].sfm_address;
- if ( (mappings[i].sfm_address + mappings[i].sfm_size) > highAddress )
- highAddress = mappings[i].sfm_address + mappings[i].sfm_size;
- }
- }
}
static long pickCacheSlide(uint32_t mappingsCount, shared_file_mapping_np mappings[])
@@ -3332,15 +3068,26 @@
// else fall through to handle old style cache
#endif
// get bounds of cache
- uint64_t lowAddress;
- uint64_t highAddress;
- getCacheBounds(mappingsCount, mappings, lowAddress, highAddress);
+ uint64_t lowAddress = 0;
+ uint64_t highAddress = 0;
+ for(uint32_t i=0; i < mappingsCount; ++i) {
+ if ( lowAddress == 0 ) {
+ lowAddress = mappings[i].sfm_address;
+ highAddress = mappings[i].sfm_address + mappings[i].sfm_size;
+ }
+ else {
+ if ( mappings[i].sfm_address < lowAddress )
+ lowAddress = mappings[i].sfm_address;
+ if ( (mappings[i].sfm_address + mappings[i].sfm_size) > highAddress )
+ highAddress = mappings[i].sfm_address + mappings[i].sfm_size;
+ }
+ }
// find slop space
const uint64_t space = (SHARED_REGION_BASE + SHARED_REGION_SIZE) - highAddress;
// choose new random slide
- long slide = dyld_page_trunc(arc4random() % space);
+ long slide = (arc4random() % space) & (-4096);
//dyld::log("slideSpace=0x%0llX\n", space);
//dyld::log("slide=0x%0lX\n", slide);
@@ -3355,16 +3102,11 @@
static void mapSharedCache()
{
uint64_t cacheBaseAddress = 0;
- // quick check if a cache is already mapped into shared region
+ // quick check if a cache is alreay mapped into shared region
if ( _shared_region_check_np(&cacheBaseAddress) == 0 ) {
sSharedCache = (dyld_cache_header*)cacheBaseAddress;
// if we don't understand the currently mapped shared cache, then ignore
-#if __x86_64__
- const char* magic = (sHaswell ? ARCH_CACHE_MAGIC_H : ARCH_CACHE_MAGIC);
-#else
- const char* magic = ARCH_CACHE_MAGIC;
-#endif
- if ( strcmp(sSharedCache->magic, magic) != 0 ) {
+ if ( strcmp(sSharedCache->magic, ARCH_CACHE_MAGIC) != 0 ) {
sSharedCache = NULL;
if ( gLinkContext.verboseMapping ) {
dyld::log("dyld: existing shared cached in memory is not compatible\n");
@@ -3385,10 +3127,6 @@
// if cache has a uuid, copy it
if ( header->mappingOffset >= 0x68 ) {
memcpy(dyld::gProcessInfo->sharedCacheUUID, header->uuid, 16);
- }
- // verbose logging
- if ( gLinkContext.verboseMapping ) {
- dyld::log("dyld: re-using existing shared cache mapping\n");
}
}
else {
@@ -3422,12 +3160,7 @@
uint8_t firstPages[8192];
if ( ::read(fd, firstPages, 8192) == 8192 ) {
dyld_cache_header* header = (dyld_cache_header*)firstPages;
- #if __x86_64__
- const char* magic = (sHaswell ? ARCH_CACHE_MAGIC_H : ARCH_CACHE_MAGIC);
- #else
- const char* magic = ARCH_CACHE_MAGIC;
- #endif
- if ( strcmp(header->magic, magic) == 0 ) {
+ if ( strcmp(header->magic, ARCH_CACHE_MAGIC) == 0 ) {
const dyld_cache_mapping_info* const fileMappingsStart = (dyld_cache_mapping_info*)&firstPages[header->mappingOffset];
const dyld_cache_mapping_info* const fileMappingsEnd = &fileMappingsStart[header->mappingCount];
shared_file_mapping_np mappings[header->mappingCount+1]; // add room for code-sig
@@ -3461,7 +3194,7 @@
}
}
// if shared cache is code signed, add a mapping for the code signature
- uint64_t signatureSize = header->codeSignatureSize;
+ uint32_t signatureSize = header->codeSignatureSize;
// zero size in header means signature runs to end-of-file
if ( signatureSize == 0 )
signatureSize = stat_buf.st_size - header->codeSignatureOffset;
@@ -3469,11 +3202,7 @@
int linkeditMapping = mappingCount-1;
codeSignatureMappingIndex = mappingCount++;
mappings[codeSignatureMappingIndex].sfm_address = mappings[linkeditMapping].sfm_address + mappings[linkeditMapping].sfm_size;
-#if __arm__ || __arm64__
- mappings[codeSignatureMappingIndex].sfm_size = (signatureSize+16383) & (-16384);
-#else
mappings[codeSignatureMappingIndex].sfm_size = (signatureSize+4095) & (-4096);
-#endif
mappings[codeSignatureMappingIndex].sfm_file_offset = header->codeSignatureOffset;
mappings[codeSignatureMappingIndex].sfm_max_prot = VM_PROT_READ;
mappings[codeSignatureMappingIndex].sfm_init_prot = VM_PROT_READ;
@@ -3499,17 +3228,7 @@
goodCache = false;
}
}
-#endif
-#if __IPHONE_OS_VERSION_MIN_REQUIRED
- {
- uint64_t lowAddress;
- uint64_t highAddress;
- getCacheBounds(mappingCount, mappings, lowAddress, highAddress);
- if ( (highAddress-lowAddress) > SHARED_REGION_SIZE )
- throw "dyld shared cache is too big to fit in shared region";
- }
-#endif
-
+#endif
if ( goodCache && (readWriteMappingIndex == -1) ) {
dyld::log("dyld: shared cached file is missing read/write mapping: %s" DYLD_SHARED_CACHE_BASE_NAME ARCH_NAME "\n", sSharedCacheDir);
goodCache = false;
@@ -3521,7 +3240,7 @@
if ( goodCache ) {
long cacheSlide = 0;
void* slideInfo = NULL;
- uint64_t slideInfoSize = 0;
+ uint32_t slideInfoSize = 0;
// check if shared cache contains slid info
if ( header->slideInfoSize != 0 ) {
// <rdar://problem/8611968> don't slide shared cache if ASLR disabled (main executable didn't slide)
@@ -3537,12 +3256,6 @@
mappings[readWriteMappingIndex].sfm_init_prot |= VM_PROT_SLIDE;
}
}
- if ( gLinkContext.verboseMapping ) {
- dyld::log("dyld: calling _shared_region_map_and_slide_np() with regions:\n");
- for (int i=0; i < mappingCount; ++i) {
- dyld::log(" address=0x%08llX, size=0x%08llX, fileOffset=0x%08llX\n", mappings[i].sfm_address, mappings[i].sfm_size, mappings[i].sfm_file_offset);
- }
- }
if (_shared_region_map_and_slide_np(fd, mappingCount, mappings, codeSignatureMappingIndex, cacheSlide, slideInfo, slideInfoSize) == 0) {
// successfully mapped cache into shared region
sSharedCache = (dyld_cache_header*)mappings[0].sfm_address;
@@ -3555,9 +3268,6 @@
}
}
else {
-#if __IPHONE_OS_VERSION_MIN_REQUIRED
- throw "dyld shared cache could not be mapped";
-#endif
if ( gLinkContext.verboseMapping )
dyld::log("dyld: shared cached file could not be mapped\n");
}
@@ -3592,6 +3302,12 @@
// only room to tell gdb about first four regions
if ( dyld_shared_cache_ranges.sharedRegionsCount > 4 )
dyld_shared_cache_ranges.sharedRegionsCount = 4;
+ if ( gLinkContext.verboseMapping ) {
+ if ( gLinkContext.sharedRegionMode == ImageLoader::kUseSharedRegion )
+ dyld::log("dyld: Mapping shared cache from %s/" DYLD_SHARED_CACHE_BASE_NAME ARCH_NAME "\n", sSharedCacheDir);
+ else if ( gLinkContext.sharedRegionMode == ImageLoader::kUsePrivateSharedRegion )
+ dyld::log("dyld: Mapping private shared cache from %s/" DYLD_SHARED_CACHE_BASE_NAME ARCH_NAME "\n", sSharedCacheDir);
+ }
const dyld_cache_mapping_info* const end = &start[dyld_shared_cache_ranges.sharedRegionsCount];
int index = 0;
for (const dyld_cache_mapping_info* p = start; p < end; ++p, ++index ) {
@@ -3623,12 +3339,11 @@
if ( gLinkContext.verboseMapping ) {
// list the code blob
dyld_cache_header* header = (dyld_cache_header*)sSharedCache;
- uint64_t signatureSize = header->codeSignatureSize;
+ uint32_t signatureSize = header->codeSignatureSize;
// zero size in header means signature runs to end-of-file
if ( signatureSize == 0 ) {
struct stat stat_buf;
- // FIXME: need size of cache file actually used
- if ( my_stat(IPHONE_DYLD_SHARED_CACHE_DIR DYLD_SHARED_CACHE_BASE_NAME ARCH_NAME, &stat_buf) == 0 )
+ if ( my_stat(IPHONE_DYLD_SHARED_CACHE_DIR DYLD_SHARED_CACHE_BASE_NAME ARCH_NAME, &stat_buf) == 0 )
signatureSize = stat_buf.st_size - header->codeSignatureOffset;
}
if ( signatureSize != 0 ) {
@@ -3640,10 +3355,7 @@
#if __IPHONE_OS_VERSION_MIN_REQUIRED
// check for file that enables dyld shared cache dylibs to be overridden
struct stat enableStatBuf;
- // check file size to determine if correct file is in place.
- // See <rdar://problem/13591370> Need a way to disable roots without removing /S/L/C/com.apple.dyld/enable...
- sDylibsOverrideCache = ( (my_stat(IPHONE_DYLD_SHARED_CACHE_DIR "enable-dylibs-to-override-cache", &enableStatBuf) == 0)
- && (enableStatBuf.st_size < ENABLE_DYLIBS_TO_OVERRIDE_CACHE_SIZE) );
+ sDylibsOverrideCache = ( my_stat(IPHONE_DYLD_SHARED_CACHE_DIR "enable-dylibs-to-override-cache", &enableStatBuf) == 0 );
#endif
}
}
@@ -3733,9 +3445,6 @@
void registerRemoveCallback(ImageCallback func)
{
- // <rdar://problem/15025198> ignore calls to register a notification during a notification
- if ( sRemoveImageCallbacksInUse )
- return;
sRemoveImageCallbacks.push_back(func);
}
@@ -3832,7 +3541,7 @@
// bind lazy pointer and return it
try {
- result = (*imageLoaderCache)->doBindFastLazySymbol((uint32_t)lazyBindingInfoOffset, gLinkContext,
+ result = (*imageLoaderCache)->doBindFastLazySymbol(lazyBindingInfoOffset, gLinkContext,
(dyld::gLibSystemHelpers != NULL) ? dyld::gLibSystemHelpers->acquireGlobalDyldLock : NULL,
(dyld::gLibSystemHelpers != NULL) ? dyld::gLibSystemHelpers->releaseGlobalDyldLock : NULL);
}
@@ -3864,8 +3573,8 @@
// search all images in order
const ImageLoader* firstWeakImage = NULL;
const ImageLoader::Symbol* firstWeakSym = NULL;
- const size_t imageCount = sAllImages.size();
- for(size_t i=0; i < imageCount; ++i) {
+ const unsigned int imageCount = sAllImages.size();
+ for(unsigned int i=0; i < imageCount; ++i) {
ImageLoader* anImage = sAllImages[i];
// the use of inserted libraries alters search order
// so that inserted libraries are found before the main executable
@@ -3916,8 +3625,8 @@
bool flatFindExportedSymbolWithHint(const char* name, const char* librarySubstring, const ImageLoader::Symbol** sym, const ImageLoader** image)
{
// search all images in order
- const size_t imageCount = sAllImages.size();
- for(size_t i=0; i < imageCount; ++i){
+ const unsigned int imageCount = sAllImages.size();
+ for(unsigned int i=0; i < imageCount; ++i){
ImageLoader* anImage = sAllImages[i];
// only look at images whose paths contain the hint string (NULL hint string is wildcard)
if ( ! anImage->isBundle() && ((librarySubstring==NULL) || (strstr(anImage->getPath(), librarySubstring) != NULL)) ) {
@@ -4075,16 +3784,20 @@
gLinkContext.programVars.__prognamePtr=&gLinkContext.progname;
gLinkContext.mainExecutable = NULL;
gLinkContext.imageSuffix = NULL;
- gLinkContext.dynamicInterposeArray = NULL;
- gLinkContext.dynamicInterposeCount = 0;
gLinkContext.prebindUsage = ImageLoader::kUseAllPrebinding;
-#if TARGET_IPHONE_SIMULATOR
- gLinkContext.sharedRegionMode = ImageLoader::kDontUseSharedRegion;
+ gLinkContext.sharedRegionMode = ImageLoader::kUseSharedRegion;
+}
+
+
+#if __LP64__
+ #define LC_SEGMENT_COMMAND LC_SEGMENT_64
+ #define macho_segment_command segment_command_64
+ #define macho_section section_64
#else
- gLinkContext.sharedRegionMode = ImageLoader::kUseSharedRegion;
-#endif
-}
-
+ #define LC_SEGMENT_COMMAND LC_SEGMENT
+ #define macho_segment_command segment_command
+ #define macho_section section
+#endif
//
@@ -4121,18 +3834,20 @@
return false;
}
-
#if SUPPORT_VERSIONED_PATHS
-
-static bool readFirstPage(const char* dylibPath, uint8_t firstPage[4096])
-{
- firstPage[0] = 0;
+//
+// Peeks at a dylib file and returns its current_version and install_name.
+// Returns false on error.
+//
+static bool getDylibVersionAndInstallname(const char* dylibPath, uint32_t* version, char* installName)
+{
// open file (automagically closed when this function exits)
FileOpener file(dylibPath);
-
+
if ( file.getFileDescriptor() == -1 )
return false;
+ uint8_t firstPage[4096];
if ( pread(file.getFileDescriptor(), firstPage, 4096, 0) != 4096 )
return false;
@@ -4149,33 +3864,9 @@
return false;
}
}
-
- return true;
-}
-
-//
-// Peeks at a dylib file and returns its current_version and install_name.
-// Returns false on error.
-//
-static bool getDylibVersionAndInstallname(const char* dylibPath, uint32_t* version, char* installName)
-{
- uint8_t firstPage[4096];
- const macho_header* mh = (macho_header*)firstPage;
- if ( !readFirstPage(dylibPath, firstPage) ) {
- #if DYLD_SHARED_CACHE_SUPPORT
- // If file cannot be read, check to see if path is in shared cache
- const macho_header* mhInCache;
- const char* pathInCache;
- long slideInCache;
- if ( !findInSharedCacheImage(dylibPath, true, NULL, &mhInCache, &pathInCache, &slideInCache) )
- return false;
- mh = mhInCache;
- #else
- return false;
- #endif
- }
// check mach-o header
+ const mach_header* mh = (mach_header*)firstPage;
if ( mh->magic != sMainExecutableMachHeader->magic )
return false;
if ( mh->cputype != sMainExecutableMachHeader->cputype )
@@ -4207,7 +3898,6 @@
}
#endif // SUPPORT_VERSIONED_PATHS
-
#if 0
static void printAllImages()
{
@@ -4289,16 +3979,13 @@
for (std::vector<ImageLoader*>::iterator it=sAllImages.begin(); it != sAllImages.end(); it++) {
ImageLoader* image = *it;
if ( (image->dlopenCount() != 0) || image->neverUnload() ) {
- OSSpinLockLock(&sDynamicReferencesLock);
- image->markedUsedRecursive(sDynamicReferences);
- OSSpinLockUnlock(&sDynamicReferencesLock);
+ image->markedUsedRecursive(sDynamicReferences);
}
}
// collect phase: build array of images not marked in-use
ImageLoader* deadImages[sAllImages.size()];
unsigned deadCount = 0;
- int maxRangeCount = 0;
unsigned i = 0;
for (std::vector<ImageLoader*>::iterator it=sAllImages.begin(); it != sAllImages.end(); it++) {
ImageLoader* image = *it;
@@ -4306,35 +3993,21 @@
deadImages[i++] = image;
if (gLogAPIs) dyld::log("dlclose(), found unused image %p %s\n", image, image->getShortName());
++deadCount;
- maxRangeCount += image->segmentCount();
}
}
// collect phase: run termination routines for images not marked in-use
- __cxa_range_t ranges[maxRangeCount];
- int rangeCount = 0;
+ // TO DO: When libc has cxa_finalize() that takes array of images, pass deadImages[] instead of the for loop here
for (unsigned i=0; i < deadCount; ++i) {
ImageLoader* image = deadImages[i];
- for (unsigned int j=0; j < image->segmentCount(); ++j) {
- if ( !image->segExecutable(j) )
- continue;
- if ( rangeCount < maxRangeCount ) {
- ranges[rangeCount].addr = (const void*)image->segActualLoadAddress(j);
- ranges[rangeCount].length = image->segSize(j);
- ++rangeCount;
- }
- }
try {
- runImageStaticTerminators(image);
+ if (gLogAPIs) dyld::log("dlclose(), running terminators for %p %s\n", image, image->getShortName());
+ runImageTerminators(image);
}
catch (const char* msg) {
dyld::warn("problem running terminators for image: %s\n", msg);
}
}
-
- // <rdar://problem/14718598> dyld should call __cxa_finalize_ranges()
- if ( (rangeCount > 0) && (gLibSystemHelpers != NULL) && (gLibSystemHelpers->version >= 13) )
- (*gLibSystemHelpers->cxa_finalize_ranges)(ranges, rangeCount);
// collect phase: delete all images which are not marked in-use
bool mightBeMore;
@@ -4408,45 +4081,31 @@
image = load(path, context);
}
catch (const char* msg) {
-#if TARGET_IPHONE_SIMULATOR
- dyld::log("dyld: warning: could not load inserted library '%s' because %s\n", path, msg);
-#else
halt(dyld::mkstringf("could not load inserted library '%s' because %s\n", path, msg));
-#endif
}
catch (...) {
halt(dyld::mkstringf("could not load inserted library '%s'\n", path));
}
}
-static bool processRestricted(const macho_header* mainExecutableMH, bool* ignoreEnvVars, bool* processRequiresLibraryValidation)
+static bool processRestricted(const macho_header* mainExecutableMH)
{
-#if TARGET_IPHONE_SIMULATOR
- gLinkContext.codeSigningEnforced = true;
-#else
+#if __MAC_OS_X_VERSION_MIN_REQUIRED
// ask kernel if code signature of program makes it restricted
uint32_t flags;
if ( csops(0, CS_OPS_STATUS, &flags, sizeof(flags)) != -1 ) {
- if (flags & CS_REQUIRE_LV)
- *processRequiresLibraryValidation = true;
-
- #if __MAC_OS_X_VERSION_MIN_REQUIRED
if ( flags & CS_ENFORCEMENT ) {
gLinkContext.codeSigningEnforced = true;
}
- if ( ((flags & CS_RESTRICT) == CS_RESTRICT) && (csr_check(CSR_ALLOW_TASK_FOR_PID) != 0) ) {
- sRestrictedReason = restrictedByEntitlements;
- return true;
- }
- #else
- if ((flags & CS_ENFORCEMENT) && !(flags & CS_GET_TASK_ALLOW)) {
- *ignoreEnvVars = true;
- }
- gLinkContext.codeSigningEnforced = true;
- #endif
- }
-#endif
-
+ }
+ if (flags & CS_RESTRICT) {
+ sRestrictedReason = restrictedByEntitlements;
+ return true;
+ }
+#else
+ gLinkContext.codeSigningEnforced = true;
+#endif
+
// all processes with setuid or setgid bit set are restricted
if ( issetugid() ) {
sRestrictedReason = restrictedBySetGUid;
@@ -4497,8 +4156,7 @@
typedef int (*ioctl_proc_t)(int, unsigned long, void*);
static void* getProcessInfo() { return dyld::gProcessInfo; }
static SyscallHelpers sSysCalls = {
- 4,
- // added in version 1
+ 1,
(open_proc_t)&open,
&close,
&pread,
@@ -4527,16 +4185,7 @@
&OSMemoryBarrier,
&getProcessInfo,
&__error,
- &mach_absolute_time,
- // added in version 2
- &thread_switch,
- // added in version 3
- &opendir,
- &readdir_r,
- &closedir,
- // added in version 4
- &coresymbolication_load_notifier,
- &coresymbolication_unload_notifier
+ &mach_absolute_time
};
__attribute__((noinline))
@@ -4548,6 +4197,8 @@
// verify simulator dyld file is owned by root
struct stat sb;
if ( fstat(fd, &sb) == -1 )
+ return 0;
+ if ( sb.st_uid != 0 )
return 0;
// read first page of dyld file
@@ -4572,73 +4223,32 @@
// calculate total size of dyld segments
const macho_header* mh = (const macho_header*)firstPage;
- struct macho_segment_command* lastSeg = NULL;
- struct macho_segment_command* firstSeg = NULL;
uintptr_t mappingSize = 0;
uintptr_t preferredLoadAddress = 0;
const uint32_t cmd_count = mh->ncmds;
- if ( (sizeof(macho_header) + mh->sizeofcmds) > 4096 )
- return 0;
const struct load_command* const cmds = (struct load_command*)(((char*)mh)+sizeof(macho_header));
- const struct load_command* const endCmds = (struct load_command*)(((char*)mh) + sizeof(macho_header) + mh->sizeofcmds);
const struct load_command* cmd = cmds;
for (uint32_t i = 0; i < cmd_count; ++i) {
- uint32_t cmdLength = cmd->cmdsize;
- if ( cmdLength < 8 )
- return 0;
- const struct load_command* const nextCmd = (const struct load_command*)(((char*)cmd)+cmdLength);
- if ( (nextCmd > endCmds) || (nextCmd < cmd) )
- return 0;
switch (cmd->cmd) {
case LC_SEGMENT_COMMAND:
{
struct macho_segment_command* seg = (struct macho_segment_command*)cmd;
- if ( seg->vmaddr + seg->vmsize < seg->vmaddr )
- return 0;
- if ( seg->vmsize < seg->filesize )
- return 0;
- if ( lastSeg == NULL ) {
- // first segment must be __TEXT and start at beginning of file/slice
- firstSeg = seg;
- if ( strcmp(seg->segname, "__TEXT") != 0 )
- return 0;
- if ( seg->fileoff != 0 )
- return 0;
- if ( seg->filesize < (sizeof(macho_header) + mh->sizeofcmds) )
- return 0;
+ mappingSize += seg->vmsize;
+ if ( seg->fileoff == 0 )
preferredLoadAddress = seg->vmaddr;
- }
- else {
- // other sements must be continguous with previous segment and not executable
- if ( lastSeg->fileoff + lastSeg->filesize != seg->fileoff )
- return 0;
- if ( lastSeg->vmaddr + lastSeg->vmsize != seg->vmaddr )
- return 0;
- if ( (seg->initprot & VM_PROT_EXECUTE) != 0 )
- return 0;
- }
- mappingSize += seg->vmsize;
- lastSeg = seg;
}
break;
- case LC_SEGMENT_COMMAND_WRONG:
- return 0;
- }
- cmd = nextCmd;
- }
- // last segment must be named __LINKEDIT and not writable
- if ( strcmp(lastSeg->segname, "__LINKEDIT") != 0 )
- return 0;
- if ( lastSeg->initprot & VM_PROT_WRITE )
- return 0;
+ }
+ cmd = (const struct load_command*)(((char*)cmd)+cmd->cmdsize);
+ }
// reserve space, then mmap each segment
vm_address_t loadAddress = 0;
+ uintptr_t entry = 0;
if ( ::vm_allocate(mach_task_self(), &loadAddress, mappingSize, VM_FLAGS_ANYWHERE) != 0 )
return 0;
cmd = cmds;
struct linkedit_data_command* codeSigCmd = NULL;
- struct source_version_command* dyldVersionCmd = NULL;
for (uint32_t i = 0; i < cmd_count; ++i) {
switch (cmd->cmd) {
case LC_SEGMENT_COMMAND:
@@ -4651,64 +4261,36 @@
return 0;
}
break;
+ case LC_UNIXTHREAD:
+ {
+ #if __i386__
+ const i386_thread_state_t* registers = (i386_thread_state_t*)(((char*)cmd) + 16);
+ entry = (registers->__eip + loadAddress - preferredLoadAddress);
+ #elif __x86_64__
+ const x86_thread_state64_t* registers = (x86_thread_state64_t*)(((char*)cmd) + 16);
+ entry = (registers->__rip + loadAddress - preferredLoadAddress);
+ #endif
+ }
+ break;
case LC_CODE_SIGNATURE:
codeSigCmd = (struct linkedit_data_command*)cmd;
break;
- case LC_SOURCE_VERSION:
- dyldVersionCmd = (struct source_version_command*)cmd;
- break;
}
cmd = (const struct load_command*)(((char*)cmd)+cmd->cmdsize);
}
-
- // must have code signature which is contained within LINKEDIT segment
- if ( codeSigCmd == NULL )
- return 0;
- if ( codeSigCmd->dataoff < lastSeg->fileoff )
- return 0;
- if ( (codeSigCmd->dataoff + codeSigCmd->datasize) > (lastSeg->fileoff + lastSeg->filesize) )
- return 0;
-
- fsignatures_t siginfo;
- siginfo.fs_file_start=fileOffset; // start of mach-o slice in fat file
- siginfo.fs_blob_start=(void*)(long)(codeSigCmd->dataoff); // start of code-signature in mach-o file
- siginfo.fs_blob_size=codeSigCmd->datasize; // size of code-signature
- int result = fcntl(fd, F_ADDFILESIGS_FOR_DYLD_SIM, &siginfo);
- if ( result == -1 ) {
- dyld::log("fcntl(F_ADDFILESIGS_FOR_DYLD_SIM) failed with errno=%d\n", errno);
- return 0;
+
+ if ( codeSigCmd != NULL ) {
+ fsignatures_t siginfo;
+ siginfo.fs_file_start=fileOffset; // start of mach-o slice in fat file
+ siginfo.fs_blob_start=(void*)(long)(codeSigCmd->dataoff); // start of code-signature in mach-o file
+ siginfo.fs_blob_size=codeSigCmd->datasize; // size of code-signature
+ int result = fcntl(fd, F_ADDFILESIGS, &siginfo);
+ if ( result == -1 ) {
+ if ( (errno == EPERM) || (errno == EBADEXEC) )
+ return 0;
+ }
}
close(fd);
- // file range covered by code signature must extend up to code signature itself
- if ( siginfo.fs_file_start < codeSigCmd->dataoff )
- return 0;
-
- // walk newly mapped dyld_sim __TEXT load commands to find entry point
- uintptr_t entry = 0;
- cmd = (struct load_command*)(((char*)loadAddress)+sizeof(macho_header));
- const uint32_t count = ((macho_header*)(loadAddress))->ncmds;
- for (uint32_t i = 0; i < count; ++i) {
- if (cmd->cmd == LC_UNIXTHREAD) {
- #if __i386__
- const i386_thread_state_t* registers = (i386_thread_state_t*)(((char*)cmd) + 16);
- // entry point must be in first segment
- if ( registers->__eip < firstSeg->vmaddr )
- return 0;
- if ( registers->__eip > (firstSeg->vmaddr + firstSeg->vmsize) )
- return 0;
- entry = (registers->__eip + loadAddress - preferredLoadAddress);
- #elif __x86_64__
- const x86_thread_state64_t* registers = (x86_thread_state64_t*)(((char*)cmd) + 16);
- // entry point must be in first segment
- if ( registers->__rip < firstSeg->vmaddr )
- return 0;
- if ( registers->__rip > (firstSeg->vmaddr + firstSeg->vmsize) )
- return 0;
- entry = (registers->__rip + loadAddress - preferredLoadAddress);
- #endif
- }
- cmd = (const struct load_command*)(((char*)cmd)+cmd->cmdsize);
- }
// notify debugger that dyld_sim is loaded
dyld_image_info info;
@@ -4717,14 +4299,13 @@
info.imageFileModDate = sb.st_mtime;
addImagesToAllImages(1, &info);
dyld::gProcessInfo->notification(dyld_image_adding, 1, &info);
-
- const char** appleParams = apple;
+
// jump into new simulator dyld
typedef uintptr_t (*sim_entry_proc_t)(int argc, const char* argv[], const char* envp[], const char* apple[],
const macho_header* mainExecutableMH, const macho_header* dyldMH, uintptr_t dyldSlide,
const dyld::SyscallHelpers* vtable, uintptr_t* startGlue);
sim_entry_proc_t newDyld = (sim_entry_proc_t)entry;
- return (*newDyld)(argc, argv, envp, appleParams, mainExecutableMH, (macho_header*)loadAddress,
+ return (*newDyld)(argc, argv, envp, apple, mainExecutableMH, (macho_header*)loadAddress,
loadAddress - preferredLoadAddress,
&sSysCalls, startGlue);
}
@@ -4763,6 +4344,13 @@
#endif
CRSetCrashLogMessage("dyld: launch started");
+#ifdef ALTERNATIVE_LOGFILE
+ sLogfile = open(ALTERNATIVE_LOGFILE, O_WRONLY | O_CREAT | O_APPEND);
+ if ( sLogfile == -1 ) {
+ sLogfile = STDERR_FILENO;
+ dyld::log("error opening alternate log file %s, errno = %d\n", ALTERNATIVE_LOGFILE, errno);
+ }
+#endif
#if LOG_BINDINGS
char bindingsLogPath[256];
@@ -4791,6 +4379,7 @@
// <rdar://problem/13868260> Remove interim apple[0] transition code from dyld
if (!sExecPath) sExecPath = apple[0];
+ sExecPath = apple[0];
bool ignoreEnvironmentVariables = false;
if ( sExecPath[0] != '/' ) {
// have relative path, use cwd to make absolute
@@ -4810,25 +4399,25 @@
++sExecShortName;
else
sExecShortName = sExecPath;
- sProcessIsRestricted = processRestricted(mainExecutableMH, &ignoreEnvironmentVariables, &sProcessRequiresLibraryValidation);
+ sProcessIsRestricted = processRestricted(mainExecutableMH);
if ( sProcessIsRestricted ) {
#if SUPPORT_LC_DYLD_ENVIRONMENT
checkLoadCommandEnvironmentVariables();
+#if SUPPORT_VERSIONED_PATHS
+ checkVersionedPaths();
+#endif
#endif
pruneEnvironmentVariables(envp, &apple);
// set again because envp and apple may have changed or moved
setContext(mainExecutableMH, argc, argv, envp, apple);
}
- else {
- if ( !ignoreEnvironmentVariables )
- checkEnvironmentVariables(envp);
- defaultUninitializedFallbackPaths(envp);
- }
- if ( sEnv.DYLD_PRINT_OPTS )
+ else
+ checkEnvironmentVariables(envp, ignoreEnvironmentVariables);
+ if ( sEnv.DYLD_PRINT_OPTS )
printOptions(argv);
if ( sEnv.DYLD_PRINT_ENV )
printEnvironmentVariables(envp);
- getHostInfo(mainExecutableMH, mainExecutableSlide);
+ getHostInfo();
// install gdb notifier
stateToHandlers(dyld_image_state_dependents_mapped, sBatchHandlers)->push_back(notifyGDB);
stateToHandlers(dyld_image_state_mapped, sSingleHandlers)->push_back(updateAllImages);
@@ -4849,48 +4438,21 @@
try {
// add dyld itself to UUID list
addDyldImageToUUIDList();
- CRSetCrashLogMessage(sLoadingCrashMessage);
+ if ( sProcessIsRestricted )
+ CRSetCrashLogMessage("dyld: launch, loading dependent libraries, ignoring DYLD_* env vars");
+ else
+ CRSetCrashLogMessage("dyld: launch, loading dependent libraries");
// instantiate ImageLoader for main executable
sMainExecutable = instantiateFromLoadedImage(mainExecutableMH, mainExecutableSlide, sExecPath);
gLinkContext.mainExecutable = sMainExecutable;
gLinkContext.processIsRestricted = sProcessIsRestricted;
- gLinkContext.processRequiresLibraryValidation = sProcessRequiresLibraryValidation;
gLinkContext.mainExecutableCodeSigned = hasCodeSignatureLoadCommand(mainExecutableMH);
-
-#if TARGET_IPHONE_SIMULATOR
- #if TARGET_OS_WATCH || TARGET_OS_TV
- // disable error during bring up of these simulators
- #else
- // check main executable is not too new for this OS
- {
- if ( ! isSimulatorBinary((uint8_t*)mainExecutableMH, sExecPath) ) {
- throwf("program was built for Mac OS X and cannot be run in simulator");
- }
- uint32_t mainMinOS = sMainExecutable->minOSVersion();
- // dyld is always built for the current OS, so we can get the current OS version
- // from the load command in dyld itself.
- uint32_t dyldMinOS = ImageLoaderMachO::minOSVersion((const mach_header*)&__dso_handle);
- if ( mainMinOS > dyldMinOS ) {
- throwf("app was built for iOS %d.%d which is newer than this simulator %d.%d",
- mainMinOS >> 16, ((mainMinOS >> 8) & 0xFF),
- dyldMinOS >> 16, ((dyldMinOS >> 8) & 0xFF));
- }
- }
- #endif
-#endif
-
// load shared cache
checkSharedRegionDisable();
#if DYLD_SHARED_CACHE_SUPPORT
if ( gLinkContext.sharedRegionMode != ImageLoader::kDontUseSharedRegion )
mapSharedCache();
#endif
-
- // Now that shared cache is loaded, setup an versioned dylib overrides
- #if SUPPORT_VERSIONED_PATHS
- checkVersionedPaths();
- #endif
-
// load any inserted libraries
if ( sEnv.DYLD_INSERT_LIBRARIES != NULL ) {
for (const char* const* lib = sEnv.DYLD_INSERT_LIBRARIES; *lib != NULL; ++lib)
@@ -4917,23 +4479,10 @@
ImageLoader* image = sAllImages[i+1];
link(image, sEnv.DYLD_BIND_AT_LAUNCH, true, ImageLoader::RPathChain(NULL, NULL));
image->setNeverUnloadRecursive();
- }
- // only INSERTED libraries can interpose
- // register interposing info after all inserted libraries are bound so chaining works
- for(unsigned int i=0; i < sInsertedDylibCount; ++i) {
- ImageLoader* image = sAllImages[i+1];
+ // only INSERTED libraries can interpose
image->registerInterposing();
}
}
-
- // <rdar://problem/19315404> dyld should support interposition even without DYLD_INSERT_LIBRARIES
- for (int i=sInsertedDylibCount+1; i < sAllImages.size(); ++i) {
- ImageLoader* image = sAllImages[i];
- if ( image->inSharedCache() )
- continue;
- image->registerInterposing();
- }
-
// apply interposing to initial set of images
for(int i=0; i < sImageRoots.size(); ++i) {
sImageRoots[i]->applyInterposing(gLinkContext);
@@ -4975,6 +4524,13 @@
dyld::log("dyld: launch failed\n");
}
+#ifdef ALTERNATIVE_LOGFILE
+ // only use alternate log during launch, otherwise file is open forever
+ if ( sLogfile != STDERR_FILENO ) {
+ close(sLogfile);
+ sLogfile = STDERR_FILENO;
+ }
+#endif
CRSetCrashLogMessage(NULL);
return result;