Loading...
--- dyld/dyld-360.21/src/dyld.cpp
+++ dyld/dyld-353.2.1/src/dyld.cpp
@@ -50,7 +50,6 @@
#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>
@@ -98,12 +97,11 @@
#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)
+ void coresymbolication_load_image(void*, const ImageLoader*, uint64_t);
+ void coresymbolication_unload_image(void*, const ImageLoader*);
+#else
+ #include "coreSymbolicationDyldSupport.hpp"
#endif
// not libc header for send() syscall interface
@@ -112,18 +110,6 @@
// 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
@@ -233,7 +219,6 @@
#endif
static ImageLoader* sMainExecutable = NULL;
static bool sProcessIsRestricted = false;
-static bool sProcessRequiresLibraryValidation = false;
static RestrictedReason sRestrictedReason = restrictedNot;
static size_t sInsertedDylibCount = 0;
static std::vector<ImageLoader*> sAllImages;
@@ -247,13 +232,8 @@
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
@@ -284,7 +264,6 @@
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";
@@ -530,13 +509,30 @@
static void allImagesLock()
{
+ //dyld::log("allImagesLock()\n");
+#if TARGET_IPHONE_SIMULATOR
+ // <rdar://problem/16154256> can't use OSSpinLockLock in simulator until thread_switch is provided by host dyld
+ while ( ! OSAtomicCompareAndSwapPtrBarrier((void*)0, (void*)1, (void**)&sAllImagesLock) ) {
+ // spin
+ }
+#else
OSSpinLockLock(&sAllImagesLock);
+#endif
}
static void allImagesUnlock()
{
+ //dyld::log("allImagesUnlock()\n");
+#if TARGET_IPHONE_SIMULATOR
+ while ( ! OSAtomicCompareAndSwapPtrBarrier((void*)1, (void*)0, (void**)&sAllImagesLock) ) {
+ // spin
+ }
+#else
OSSpinLockUnlock(&sAllImagesLock);
-}
+#endif
+}
+
+
// utility class to assure files are closed when an exception is thrown
@@ -703,15 +699,21 @@
}
}
}
- // mach message csdlc about dynamically unloaded images
+ // 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());
+#if TARGET_IPHONE_SIMULATOR
+ void* connection = dyld::gProcessInfo->coreSymbolicationShmPage;
+ if ( *((uint32_t*)connection) == 2 ) {
+#else
+ CSCppDyldSharedMemoryPage* connection = (CSCppDyldSharedMemoryPage*)dyld::gProcessInfo->coreSymbolicationShmPage;
+ if ( connection->is_valid_version() ) {
+#endif
+ coresymbolication_unload_image(connection, image);
+ }
}
}
}
@@ -821,21 +823,36 @@
}
}
}
- 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 ( 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) {
+#if TARGET_IPHONE_SIMULATOR
+ void* connection = dyld::gProcessInfo->coreSymbolicationShmPage;
+ if ( *((uint32_t*)connection) == 2 ) {
+#else
+ CSCppDyldSharedMemoryPage* connection = (CSCppDyldSharedMemoryPage*)dyld::gProcessInfo->coreSymbolicationShmPage;
+ if ( connection->is_valid_version() ) {
+#endif
+ // 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);
+ }
+ }
+ }
}
}
@@ -908,20 +925,15 @@
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)
@@ -1017,9 +1029,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 )
@@ -1142,7 +1152,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,9 +1200,8 @@
{
//dyld::log("checkDylibOverridesInDir('%s')\n", dirPath);
char dylibPath[PATH_MAX];
- int dirPathLen = strlcpy(dylibPath, dirPath, PATH_MAX-1);
- if ( dirPathLen >= PATH_MAX )
- return;
+ int dirPathLen = strlen(dirPath);
+ strlcpy(dylibPath, dirPath, PATH_MAX);
DIR* dirp = opendir(dirPath);
if ( dirp != NULL) {
dirent entry;
@@ -1202,9 +1211,9 @@
break;
if ( entp->d_type != DT_REG )
continue;
- dylibPath[dirPathLen] = '/';
- dylibPath[dirPathLen+1] = '\0';
- 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);
}
@@ -1217,9 +1226,8 @@
{
//dyld::log("checkFrameworkOverridesInDir('%s')\n", dirPath);
char frameworkPath[PATH_MAX];
- int dirPathLen = strlcpy(frameworkPath, dirPath, PATH_MAX-1);
- if ( dirPathLen >= PATH_MAX )
- return;
+ int dirPathLen = strlen(dirPath);
+ strlcpy(frameworkPath, dirPath, PATH_MAX);
DIR* dirp = opendir(dirPath);
if ( dirp != NULL) {
dirent entry;
@@ -1229,18 +1237,18 @@
break;
if ( entp->d_type != DT_DIR )
continue;
- frameworkPath[dirPathLen] = '/';
+ frameworkPath[dirPathLen] = '/';
frameworkPath[dirPathLen+1] = '\0';
- int dirNameLen = (int)strlen(entp->d_name);
+ 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);
@@ -1577,18 +1585,9 @@
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 if ( strcmp(key, "DYLD_PRINT_TO_FILE") == 0 ) {
+ // handled in _main()
+ }
else {
dyld::warn("unknown environment variable: %s\n", key);
}
@@ -1620,15 +1619,12 @@
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);
- }
+ 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);
}
}
}
@@ -1731,47 +1727,16 @@
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 ) {
+ if ( (equals != NULL) && !ignoreEnviron ) {
strlcat(sLoadingCrashMessage, "\n", sizeof(sLoadingCrashMessage));
strlcat(sLoadingCrashMessage, keyEqualsValue, sizeof(sLoadingCrashMessage));
const char* value = &equals[1];
@@ -1782,6 +1747,9 @@
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);
@@ -1791,44 +1759,40 @@
#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__
@@ -1856,22 +1820,6 @@
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
}
@@ -2432,13 +2380,11 @@
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;
+ if ( strncmp(path, "/usr/lib/system/libsystem_", 26) == 0 )
+ return true;
return false;
}
cmd = (const struct load_command*)(((char*)cmd)+cmd->cmdsize);
@@ -2502,16 +2448,12 @@
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
@@ -2787,7 +2729,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;
@@ -2819,7 +2761,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)];
@@ -2883,7 +2825,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);
}
@@ -3243,23 +3185,6 @@
const void* imMemorySharedCacheHeader()
{
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()
@@ -3629,8 +3554,7 @@
// 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 ) {
@@ -4088,6 +4012,16 @@
}
+#if __LP64__
+ #define LC_SEGMENT_COMMAND LC_SEGMENT_64
+ #define macho_segment_command segment_command_64
+ #define macho_section section_64
+#else
+ #define LC_SEGMENT_COMMAND LC_SEGMENT
+ #define macho_segment_command segment_command
+ #define macho_section section
+#endif
+
//
// Look for a special segment in the mach header.
@@ -4123,18 +4057,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;
@@ -4151,33 +4087,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 )
@@ -4291,16 +4203,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;
@@ -4308,11 +4217,11 @@
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
+ const int maxRangeCount = deadCount*2;
__cxa_range_t ranges[maxRangeCount];
int rangeCount = 0;
for (unsigned i=0; i < deadCount; ++i) {
@@ -4391,6 +4300,25 @@
preflight_finally(image);
}
+#if __x86_64__
+static bool isHaswell()
+{
+#if TARGET_IPHONE_SIMULATOR
+ return false;
+#else
+ // check system is capable of running x86_64h code
+ struct host_basic_info info;
+ mach_msg_type_number_t count = HOST_BASIC_INFO_COUNT;
+ mach_port_t hostPort = mach_host_self();
+ kern_return_t result = host_info(hostPort, HOST_BASIC_INFO, (host_info_t)&info, &count);
+ mach_port_deallocate(mach_task_self(), hostPort);
+ if ( result != KERN_SUCCESS )
+ return false;
+ return ( info.cpu_subtype == CPU_SUBTYPE_X86_64_H );
+#endif
+}
+#endif
+
static void loadInsertedDylib(const char* path)
{
ImageLoader* image = NULL;
@@ -4413,10 +4341,7 @@
#if TARGET_IPHONE_SIMULATOR
dyld::log("dyld: warning: could not load inserted library '%s' because %s\n", path, msg);
#else
- if ( sProcessRequiresLibraryValidation )
- dyld::log("dyld: warning: could not load inserted library '%s' into library validated process because %s\n", path, msg);
- else
- halt(dyld::mkstringf("could not load inserted library '%s' because %s\n", path, msg));
+ halt(dyld::mkstringf("could not load inserted library '%s' because %s\n", path, msg));
#endif
}
catch (...) {
@@ -4424,34 +4349,24 @@
}
}
-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;
@@ -4502,7 +4417,7 @@
typedef int (*ioctl_proc_t)(int, unsigned long, void*);
static void* getProcessInfo() { return dyld::gProcessInfo; }
static SyscallHelpers sSysCalls = {
- 4,
+ 3,
// added in version 1
(open_proc_t)&open,
&close,
@@ -4538,10 +4453,7 @@
// added in version 3
&opendir,
&readdir_r,
- &closedir,
- // added in version 4
- &coresymbolication_load_notifier,
- &coresymbolication_unload_notifier
+ &closedir
};
__attribute__((noinline))
@@ -4553,6 +4465,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
@@ -4577,73 +4491,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:
@@ -4654,68 +4527,38 @@
//dyld::log("dyld_sim %s mapped at %p\n", seg->segname, segAddress);
if ( segAddress == (void*)(-1) )
return 0;
- if ( ((uintptr_t)segAddress < loadAddress) || ((uintptr_t)segAddress+seg->filesize > loadAddress+mappingSize) )
- 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;
@@ -4724,14 +4567,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);
}
@@ -4751,6 +4593,19 @@
{
uintptr_t result = 0;
sMainExecutableMachHeader = mainExecutableMH;
+#if !TARGET_IPHONE_SIMULATOR
+ const char* loggingPath = _simple_getenv(envp, "DYLD_PRINT_TO_FILE");
+ if ( loggingPath != NULL ) {
+ int fd = open(loggingPath, 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", loggingPath, errno);
+ }
+ }
+#endif
#if __MAC_OS_X_VERSION_MIN_REQUIRED
// if this is host dyld, check to see if iOS simulator is being run
const char* rootPath = _simple_getenv(envp, "DYLD_ROOT_PATH");
@@ -4798,6 +4653,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
@@ -4817,25 +4673,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);
@@ -4861,13 +4717,9 @@
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) ) {
@@ -4883,21 +4735,17 @@
dyldMinOS >> 16, ((dyldMinOS >> 8) & 0xFF));
}
}
+#endif
+
+ // load shared cache
+ #if __x86_64__
+ sHaswell = isHaswell();
#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)
@@ -4932,15 +4780,6 @@
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);