Loading...
--- dyld/dyld-852/src/dyld2.cpp
+++ dyld/dyld-750.5/src/dyld2.cpp
@@ -33,8 +33,7 @@
#include <libproc.h>
#include <sys/param.h>
#include <mach/mach_time.h> // mach_absolute_time()
-#include <mach/mach_init.h>
-#include <mach/mach_traps.h>
+#include <mach/mach_init.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/syscall.h>
@@ -42,13 +41,13 @@
#include <sys/un.h>
#include <sys/syslog.h>
#include <sys/uio.h>
-#include <sys/xattr.h>
#include <mach/mach.h>
#include <mach-o/fat.h>
#include <mach-o/loader.h>
#include <mach-o/ldsyms.h>
#include <libkern/OSByteOrder.h>
#include <libkern/OSAtomic.h>
+#include <mach/mach.h>
#include <sys/sysctl.h>
#include <sys/mman.h>
#include <sys/dtrace.h>
@@ -64,27 +63,6 @@
#include <sys/attr.h>
#include <sys/fsgetpath.h>
#include <System/sys/content_protection.h>
-
-#define SUPPORT_LOGGING_TO_CONSOLE !TARGET_OS_SIMULATOR
-#if SUPPORT_LOGGING_TO_CONSOLE
-#include <paths.h> // for logging to console
-#endif
-
-#if !TARGET_OS_SIMULATOR
-
-// The comm page is being renamed, so set our define to the new value if the old
-// value is missing
-#ifndef _COMM_PAGE_DYLD_SYSTEM_FLAGS
-
-#ifndef _COMM_PAGE_DYLD_FLAGS
-#error Must define _COMM_PAGE_DYLD_FLAGS or _COMM_PAGE_DYLD_SYSTEM_FLAGS
-#endif
-
-#define _COMM_PAGE_DYLD_SYSTEM_FLAGS _COMM_PAGE_DYLD_FLAGS
-
-#endif
-
-#endif
#if TARGET_OS_SIMULATOR
enum {
@@ -146,8 +124,6 @@
#include "ClosureFileSystemPhysical.h"
#include "FileUtils.h"
#include "BootArgs.h"
-#include "Defines.h"
-#include "RootsChecker.h"
#ifndef MH_HAS_OBJC
#define MH_HAS_OBJC 0x40000000
@@ -174,7 +150,7 @@
#define macho_section section
#endif
-#define DYLD_CLOSURE_XATTR_NAME "com.apple.dyld"
+
#define CPU_TYPE_MASK 0x00FFFFFF /* complement of CPU_ARCH_MASK */
@@ -182,7 +158,6 @@
/* implemented in dyld_gdb.cpp */
extern void resetAllImages();
extern void addImagesToAllImages(uint32_t infoCount, const dyld_image_info info[]);
-extern void addAotImagesToAllAotImages(uint32_t aotInfoCount, const dyld_aot_image_info aotInfo[]);
extern void removeImageFromAllImages(const mach_header* mh);
extern void addNonSharedCacheImageUUID(const dyld_uuid_info& info);
extern const char* notifyGDB(enum dyld_image_states state, uint32_t infoCount, const dyld_image_info info[]);
@@ -195,8 +170,6 @@
// magic linker symbol for start of dyld binary
extern "C" const macho_header __dso_handle;
-
-extern bool gEnableSharedCacheDataConst;
//
@@ -283,8 +256,7 @@
static cpu_type_t sHostCPU;
static cpu_subtype_t sHostCPUsubtype;
#endif
-typedef ImageLoaderMachO* __ptrauth_dyld_address_auth MainExecutablePointerType;
-static MainExecutablePointerType sMainExecutable = NULL;
+static ImageLoaderMachO* sMainExecutable = NULL;
static size_t sInsertedDylibCount = 0;
static std::vector<ImageLoader*> sAllImages;
static std::vector<ImageLoader*> sImageRoots;
@@ -299,7 +271,7 @@
static void* sBatchHandlers[7][3];
static ImageLoader* sLastImageByAddressCache;
static EnvironmentVariables sEnv;
-#if TARGET_OS_OSX
+#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 };
static const char* sRestrictedFrameworkFallbackPaths[] = { "/System/Library/Frameworks", NULL };
@@ -343,7 +315,7 @@
static _dyld_objc_notify_init sNotifyObjCInit;
static _dyld_objc_notify_unmapped sNotifyObjCUnmapped;
-#if TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR
+#if __IPHONE_OS_VERSION_MIN_REQUIRED && !TARGET_OS_SIMULATOR
static bool sForceStderr = false;
#endif
@@ -355,17 +327,10 @@
#endif
bool gUseDyld3 = false;
-static uint32_t sLaunchModeUsed = 0;
static bool sSkipMain = false;
-static void (*sEntryOverride)() = nullptr;
+static void (*sEntryOveride)() = nullptr;
static bool sJustBuildClosure = false;
-#if !TARGET_OS_SIMULATOR
static bool sLogClosureFailure = false;
-#endif
-static bool sKeysDisabled = false;
-static bool sOnlyPlatformArm64e = false; // arm64e binaries can only be loaded if they are part of the OS
-
-static dyld3::RootsChecker sRootsChecker;
enum class ClosureMode {
// Unset means we haven't provided an env variable or boot-arg to explicitly choose a mode
@@ -377,38 +342,12 @@
// -force_dyld2=1 env variable or an internal cache on iOS
Off,
// PreBuiltOnly means only use a shared cache closure and don't try build a new one
- PreBuiltOnly,
+ PreBuiltOnly
};
-enum class ClosureKind {
- unset,
- full,
- minimal,
-};
-
static ClosureMode sClosureMode = ClosureMode::Unset;
-static ClosureKind sClosureKind = ClosureKind::unset;
static bool sForceInvalidSharedCacheClosureFormat = false;
static uint64_t launchTraceID = 0;
-
-// These flags are the values in the 64-bit _COMM_PAGE_DYLD_SYSTEM_FLAGS entry
-// Note we own this and can write it from PID 1
-enum CommPageFlags : uint64_t {
- None = 0,
-
- // The boot args can set the low 32-bits of the comm page. We'll reserve the high 32-bits
- // for runtime (launchd) set values.
- CommPageBootArgMask = 0xFFFFFFFF,
-
- // Are the simulator support dylibs definitely roots when launchd scanned them
- libsystemKernelIsRoot = 1ULL << 32,
- libsystemPlatformIsRoot = 1ULL << 33,
- libsystemPThreadIsRoot = 1ULL << 34,
-
- // Is the file system writable, ie, could the simulator support dylibs be written
- // later, after PID 1
- fileSystemCanBeModified = 1ULL << 35
-};
//
// The MappedRanges structure is used for fast address->image lookups.
@@ -607,7 +546,7 @@
void vlog(const char* format, va_list list)
{
-#if TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR
+#if __IPHONE_OS_VERSION_MIN_REQUIRED && !TARGET_OS_SIMULATOR
// <rdar://problem/25965832> log to console when running iOS app from Xcode
if ( !sLogToFile && !sForceStderr && useSyslog() )
#else
@@ -640,21 +579,6 @@
va_start(list, format);
vwarn(format, list);
va_end(list);
-}
-
-void logToConsole(const char* format, ...) {
-#if SUPPORT_LOGGING_TO_CONSOLE
- int cfd = open(_PATH_CONSOLE, O_WRONLY|O_NOCTTY);
- if (cfd == -1)
- return;
-
- va_list list;
- va_start(list, format);
- _simple_vdprintf(cfd, format, list);
- va_end(list);
-
- close(cfd);
-#endif
}
#else
@@ -694,7 +618,7 @@
FileOpener::FileOpener(const char* path)
: fd(-1)
{
- fd = dyld3::open(path, O_RDONLY, 0);
+ fd = my_open(path, O_RDONLY, 0);
}
FileOpener::~FileOpener()
@@ -751,7 +675,7 @@
static void unregisterDOF(int registrationID)
{
- int fd = open("/dev/" DTRACEMNR_HELPER, O_RDWR, 0);
+ int fd = open("/dev/" DTRACEMNR_HELPER, O_RDWR);
if ( fd < 0 ) {
dyld::warn("can't open /dev/" DTRACEMNR_HELPER " to unregister dtrace DOF section\n");
}
@@ -869,188 +793,95 @@
#endif
#if !TARGET_OS_SIMULATOR
-#define DYLD_PROCESS_INFO_NOTIFY_MAGIC 0x49414E46
-
-struct RemoteNotificationResponder {
- RemoteNotificationResponder(const RemoteNotificationResponder&) = delete;
- RemoteNotificationResponder(RemoteNotificationResponder&&) = delete;
- RemoteNotificationResponder() {
- if (dyld::gProcessInfo->notifyPorts[0] != DYLD_PROCESS_INFO_NOTIFY_MAGIC) {
- // No notifier found, early out
- _namesCnt = 0;
- return;
- }
- kern_return_t kr = task_dyld_process_info_notify_get(_names, &_namesCnt);
- while (kr == KERN_NO_SPACE) {
- // In the future the SPI may return the size we need, but for now we just double the count. Since we don't want to depend on the
- // return value in _nameCnt we set it to have a minimm of 16, double the inline storage value
- _namesCnt = std::max<uint32_t>(16, 2*_namesCnt);
- _namesSize = _namesCnt*sizeof(mach_port_t);
- kr = vm_allocate(mach_task_self(), (vm_address_t*)&_names, _namesSize, VM_FLAGS_ANYWHERE);
- if (kr != KERN_SUCCESS) {
- // We could not allocate memory, time to error out
- break;
- }
- kr = task_dyld_process_info_notify_get(_names, &_namesCnt);
- if (kr != KERN_SUCCESS) {
- // We failed, so deallocate the memory. If the failures was KERN_NO_SPACE we will loop back and try again
- (void)vm_deallocate(mach_task_self(), (vm_address_t)_names, _namesSize);
- _namesSize = 0;
- }
- }
- if (kr != KERN_SUCCESS) {
- // We failed, set _namesCnt to 0 so nothing else will happen
- _namesCnt = 0;
- }
- }
- ~RemoteNotificationResponder() {
- if (_namesCnt) {
- for (auto i = 0; i < _namesCnt; ++i) {
- (void)mach_port_deallocate(mach_task_self(), _names[i]);
- }
- if (_namesSize != 0) {
- // We are not using inline memory, we need to free it
- (void)vm_deallocate(mach_task_self(), (vm_address_t)_names, _namesSize);
- }
- }
- }
- void sendMessage(mach_msg_id_t msgId, mach_msg_size_t sendSize, mach_msg_header_t* buffer) {
- if (_namesCnt == 0) { return; }
- // Allocate a port to listen on in this monitoring task
- mach_port_t replyPort = MACH_PORT_NULL;
- mach_port_options_t options = { .flags = MPO_CONTEXT_AS_GUARD | MPO_STRICT, .mpl = { 1 }};
- kern_return_t kr = mach_port_construct(mach_task_self(), &options, (mach_port_context_t)&replyPort, &replyPort);
- if (kr != KERN_SUCCESS) {
- return;
- }
- for (auto i = 0; i < _namesCnt; ++i) {
- if (_names[i] == MACH_PORT_NULL) { continue; }
- // Assemble a message
- uint8_t replyBuffer[sizeof(mach_msg_header_t) + MAX_TRAILER_SIZE];
- mach_msg_header_t* msg = buffer;
- msg->msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND,MACH_MSG_TYPE_MAKE_SEND_ONCE);
- msg->msgh_id = msgId;
- msg->msgh_local_port = replyPort;
- msg->msgh_remote_port = _names[i];
- msg->msgh_reserved = 0;
- msg->msgh_size = sendSize;
- kr = mach_msg_overwrite(msg, MACH_SEND_MSG | MACH_RCV_MSG, msg->msgh_size, sizeof(replyBuffer), replyPort, 0, MACH_PORT_NULL,
- (mach_msg_header_t*)&replyBuffer[0], 0);
- if (kr != KERN_SUCCESS) {
- // Send failed, we may have been psuedo recieved. destroy the message
- (void)mach_msg_destroy(msg);
- // Mark the port as null. It does not matter why we failed... if it is s single message we will not retry, if it
- // is a fragmented message then subsequent messages will not decode correctly
- _names[i] = MACH_PORT_NULL;
- }
- }
- (void)mach_port_destruct(mach_task_self(), replyPort, 0, (mach_port_context_t)&replyPort);
- }
-
- bool const active() const {
- for (auto i = 0; i < _namesCnt; ++i) {
- if (_names[i] != MACH_PORT_NULL) {
- return true;
- }
- }
- return false;
- }
-private:
- mach_port_t _namesArray[8] = {0};
- mach_port_name_array_t _names = (mach_port_name_array_t)&_namesArray[0];
- mach_msg_type_number_t _namesCnt = 8;
- vm_size_t _namesSize = 0;
-};
-
-//FIXME: Remove this once we drop support for iOS 11 simulators
-// This is an enormous hack to keep remote introspection of older simulators working
-// It works by interposing mach_msg, and redirecting message sent to a special port name. Messages to that portname will trigger a full set
-// of sends to all kernel registered notifiers. In this mode mach_msg_sim_interposed() must return KERN_SUCCESS or the older dyld_sim may
-// try to cleanup the notifer array.
-kern_return_t mach_msg_sim_interposed( mach_msg_header_t* msg, mach_msg_option_t option, mach_msg_size_t send_size, mach_msg_size_t rcv_size,
- mach_port_name_t rcv_name, mach_msg_timeout_t timeout, mach_port_name_t notify) {
- if (msg->msgh_remote_port != DYLD_PROCESS_INFO_NOTIFY_MAGIC) {
- // Not the magic port, so just pass through to the real mach_msg()
- return mach_msg(msg, option, send_size, rcv_size, rcv_name, timeout, notify);
- }
-
- // The magic port. We know dyld_sim is trying to message observers, so lets call into our messaging code directly.
- // This is kind of weird since we effectively built a buffer in dyld_sim, then pass it to mach_msg, which we interpose, unpack, and then
- // pass to send_message which then sends the buffer back out vis mach_message_overwrite(), but it should work at least as well as the old
- // way.
- RemoteNotificationResponder responder;
- responder.sendMessage(msg->msgh_id, send_size, msg);
-
- // We always return KERN_SUCCESS, otherwise old dyld_sims might clear the port
- return KERN_SUCCESS;
-}
-
-static void notifyMonitoringDyld(RemoteNotificationResponder& responder, bool unloading, unsigned imageCount,
- const struct mach_header* loadAddresses[], const char* imagePaths[])
-{
- // Make sure there is at least enough room to hold a the largest single file entry that can exist.
- static_assert((MAXPATHLEN + sizeof(dyld_process_info_image_entry) + 1 + MAX_TRAILER_SIZE) <= DYLD_PROCESS_INFO_NOTIFY_MAX_BUFFER_SIZE);
-
- unsigned entriesSize = imageCount*sizeof(dyld_process_info_image_entry);
- unsigned pathsSize = 0;
- for (unsigned j=0; j < imageCount; ++j) {
- pathsSize += (strlen(imagePaths[j]) + 1);
- }
-
- unsigned totalSize = (sizeof(struct dyld_process_info_notify_header) + entriesSize + pathsSize + 127) & -128; // align
- // The reciever has a fixed buffer of DYLD_PROCESS_INFO_NOTIFY_MAX_BUFFER_SIZE, whcih needs to hold both the message and a trailer.
- // If the total size exceeds that we need to fragment the message.
- if ( (totalSize + MAX_TRAILER_SIZE) > DYLD_PROCESS_INFO_NOTIFY_MAX_BUFFER_SIZE ) {
- // Putting all image paths into one message would make buffer too big.
- // Instead split into two messages. Recurse as needed until paths fit in buffer.
- unsigned imageHalfCount = imageCount/2;
- notifyMonitoringDyld(responder, unloading, imageHalfCount, loadAddresses, imagePaths);
- notifyMonitoringDyld(responder, unloading, imageCount - imageHalfCount, &loadAddresses[imageHalfCount], &imagePaths[imageHalfCount]);
+static void sendMessage(unsigned portSlot, mach_msg_id_t msgId, mach_msg_size_t sendSize, mach_msg_header_t* buffer, mach_msg_size_t bufferSize) {
+ // Allocate a port to listen on in this monitoring task
+ mach_port_t sendPort = dyld::gProcessInfo->notifyPorts[portSlot];
+ if (sendPort == MACH_PORT_NULL) {
return;
}
- uint8_t buffer[totalSize + MAX_TRAILER_SIZE];
- dyld_process_info_notify_header* header = (dyld_process_info_notify_header*)buffer;
- header->version = 1;
- header->imageCount = imageCount;
- header->imagesOffset = sizeof(dyld_process_info_notify_header);
- header->stringsOffset = sizeof(dyld_process_info_notify_header) + entriesSize;
- header->timestamp = dyld::gProcessInfo->infoArrayChangeTimestamp;
- dyld_process_info_image_entry* entries = (dyld_process_info_image_entry*)&buffer[header->imagesOffset];
- char* const pathPoolStart = (char*)&buffer[header->stringsOffset];
- char* pathPool = pathPoolStart;
- for (unsigned j=0; j < imageCount; ++j) {
- strcpy(pathPool, imagePaths[j]);
- uint32_t len = (uint32_t)strlen(pathPool);
- bzero(entries->uuid, 16);
- dyld3::MachOFile* mf = (dyld3::MachOFile*)loadAddresses[j];
- mf->getUuid(entries->uuid);
- entries->loadAddress = (uint64_t)loadAddresses[j];
- entries->pathStringOffset = (uint32_t)(pathPool - pathPoolStart);
- entries->pathLength = len;
- pathPool += (len +1);
- ++entries;
- }
- if (unloading) {
- responder.sendMessage(DYLD_PROCESS_INFO_NOTIFY_UNLOAD_ID, totalSize, (mach_msg_header_t*)buffer);
- } else {
- responder.sendMessage(DYLD_PROCESS_INFO_NOTIFY_LOAD_ID, totalSize, (mach_msg_header_t*)buffer);
- }
+ mach_port_t replyPort = MACH_PORT_NULL;
+ mach_port_options_t options = { .flags = MPO_CONTEXT_AS_GUARD | MPO_STRICT,
+ .mpl = { 1 }};
+ kern_return_t kr = mach_port_construct(mach_task_self(), &options, (mach_port_context_t)&replyPort, &replyPort);
+ if (kr != KERN_SUCCESS) {
+ return;
+ }
+ // Assemble a message
+ mach_msg_header_t* h = buffer;
+ h->msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND,MACH_MSG_TYPE_MAKE_SEND_ONCE);
+ h->msgh_id = msgId;
+ h->msgh_local_port = replyPort;
+ h->msgh_remote_port = sendPort;
+ h->msgh_reserved = 0;
+ h->msgh_size = sendSize;
+ kr = mach_msg(h, MACH_SEND_MSG | MACH_RCV_MSG, h->msgh_size, bufferSize, replyPort, 0, MACH_PORT_NULL);
+ mach_msg_destroy(h);
+ if ( kr == MACH_SEND_INVALID_DEST ) {
+ if (OSAtomicCompareAndSwap32(sendPort, 0, (volatile int32_t*)&dyld::gProcessInfo->notifyPorts[portSlot])) {
+ mach_port_deallocate(mach_task_self(), sendPort);
+ }
+ }
+ mach_port_destruct(mach_task_self(), replyPort, 0, (mach_port_context_t)&replyPort);
}
static void notifyMonitoringDyld(bool unloading, unsigned imageCount, const struct mach_header* loadAddresses[],
const char* imagePaths[])
{
dyld3::ScopedTimer(DBG_DYLD_REMOTE_IMAGE_NOTIFIER, 0, 0, 0);
- RemoteNotificationResponder responder;
- if (!responder.active()) { return; }
- notifyMonitoringDyld(responder, unloading, imageCount, loadAddresses, imagePaths);
-}
-
-static void notifyMonitoringDyldMain() {
+ for (int slot=0; slot < DYLD_MAX_PROCESS_INFO_NOTIFY_COUNT; ++slot) {
+ if ( dyld::gProcessInfo->notifyPorts[slot] == 0) continue;
+ unsigned entriesSize = imageCount*sizeof(dyld_process_info_image_entry);
+ unsigned pathsSize = 0;
+ for (unsigned j=0; j < imageCount; ++j) {
+ pathsSize += (strlen(imagePaths[j]) + 1);
+ }
+ unsigned totalSize = (sizeof(dyld_process_info_notify_header) + entriesSize + pathsSize + 127) & -128; // align
+ if ( totalSize > DYLD_PROCESS_INFO_NOTIFY_MAX_BUFFER_SIZE ) {
+ // Putting all image paths into one message would make buffer too big.
+ // Instead split into two messages. Recurse as needed until paths fit in buffer.
+ unsigned imageHalfCount = imageCount/2;
+ notifyMonitoringDyld(unloading, imageHalfCount, loadAddresses, imagePaths);
+ notifyMonitoringDyld(unloading, imageCount - imageHalfCount, &loadAddresses[imageHalfCount], &imagePaths[imageHalfCount]);
+ return;
+ }
+ uint8_t buffer[totalSize + MAX_TRAILER_SIZE];
+ dyld_process_info_notify_header* header = (dyld_process_info_notify_header*)buffer;
+ header->version = 1;
+ header->imageCount = imageCount;
+ header->imagesOffset = sizeof(dyld_process_info_notify_header);
+ header->stringsOffset = sizeof(dyld_process_info_notify_header) + entriesSize;
+ header->timestamp = dyld::gProcessInfo->infoArrayChangeTimestamp;
+ dyld_process_info_image_entry* entries = (dyld_process_info_image_entry*)&buffer[header->imagesOffset];
+ char* const pathPoolStart = (char*)&buffer[header->stringsOffset];
+ char* pathPool = pathPoolStart;
+ for (unsigned j=0; j < imageCount; ++j) {
+ strcpy(pathPool, imagePaths[j]);
+ uint32_t len = (uint32_t)strlen(pathPool);
+ bzero(entries->uuid, 16);
+ dyld3::MachOFile* mf = (dyld3::MachOFile*)loadAddresses[j];
+ mf->getUuid(entries->uuid);
+ entries->loadAddress = (uint64_t)loadAddresses[j];
+ entries->pathStringOffset = (uint32_t)(pathPool - pathPoolStart);
+ entries->pathLength = len;
+ pathPool += (len +1);
+ ++entries;
+ }
+ if (unloading) {
+ sendMessage(slot, DYLD_PROCESS_INFO_NOTIFY_UNLOAD_ID, totalSize, (mach_msg_header_t*)buffer, totalSize+MAX_TRAILER_SIZE);
+ } else {
+ sendMessage(slot, DYLD_PROCESS_INFO_NOTIFY_LOAD_ID, totalSize, (mach_msg_header_t*)buffer, totalSize+MAX_TRAILER_SIZE);
+ }
+ }
+}
+
+static void notifyMonitoringDyldMain()
+{
dyld3::ScopedTimer(DBG_DYLD_REMOTE_IMAGE_NOTIFIER, 0, 0, 0);
- RemoteNotificationResponder responder;
- uint8_t buffer[sizeof(mach_msg_header_t) + MAX_TRAILER_SIZE];
- responder.sendMessage(DYLD_PROCESS_INFO_NOTIFY_MAIN_ID, sizeof(mach_msg_header_t), (mach_msg_header_t*)buffer);
+ for (int slot=0; slot < DYLD_MAX_PROCESS_INFO_NOTIFY_COUNT; ++slot) {
+ if ( dyld::gProcessInfo->notifyPorts[slot] == 0) continue;
+ uint8_t buffer[sizeof(mach_msg_header_t) + MAX_TRAILER_SIZE];
+ sendMessage(slot, DYLD_PROCESS_INFO_NOTIFY_MAIN_ID, sizeof(mach_msg_header_t), (mach_msg_header_t*)buffer, sizeof(mach_msg_header_t) + MAX_TRAILER_SIZE);
+ }
}
#else
extern void notifyMonitoringDyldMain() VIS_HIDDEN;
@@ -1096,9 +927,7 @@
}
if ( state == dyld_image_state_mapped ) {
// <rdar://problem/7008875> Save load addr + UUID for images from outside the shared cache
- // <rdar://problem/50432671> Include UUIDs for shared cache dylibs in all image info when using private mapped shared caches
- if (!image->inSharedCache()
- || (gLinkContext.sharedRegionMode == ImageLoader::kUsePrivateSharedRegion)) {
+ if ( !image->inSharedCache() ) {
dyld_uuid_info info;
if ( image->getUUID(info.imageUUID) ) {
info.imageLoadAddress = image->machHeader();
@@ -1352,7 +1181,7 @@
notifyBatchPartial(state, false, NULL, preflightOnly, false);
}
-#if TARGET_OS_OSX
+#if __MAC_OS_X_VERSION_MIN_REQUIRED
static
void coresymbolication_load_notifier(void* connection, uint64_t timestamp, const char* path, const struct mach_header* mh)
{
@@ -1645,13 +1474,12 @@
}
// If this image is the potential canonical definition of any weak defs, then set them to a tombstone value
- if ( gLinkContext.weakDefMapInitialized && image->hasCoalescedExports() && (image->getState() >= dyld_image_state_bound) ) {
+ if ( gLinkContext.weakDefMapInitialized && image->hasCoalescedExports() ) {
Diagnostics diag;
const dyld3::MachOAnalyzer* ma = (const dyld3::MachOAnalyzer*)image->machHeader();
- ma->forEachWeakDef(diag, ^(const char *symbolName, uint64_t imageOffset, bool isFromExportTrie) {
+ ma->forEachWeakDef(diag, ^(const char *symbolName, uintptr_t imageOffset, bool isFromExportTrie) {
auto it = gLinkContext.weakDefMap.find(symbolName);
- if ( it == gLinkContext.weakDefMap.end() )
- return;
+ assert(it != gLinkContext.weakDefMap.end());
it->second = { nullptr, 0 };
if ( !isFromExportTrie ) {
// The string was already duplicated if we are an export trie
@@ -1703,15 +1531,7 @@
static void terminationRecorder(ImageLoader* image)
{
- bool add = true;
-#if __arm64e__
- // <rdar://problem/71820555> Don't run static terminator for arm64e
- const mach_header* mh = image->machHeader();
- if ( (mh->cputype == CPU_TYPE_ARM64) && ((mh->cpusubtype & ~CPU_SUBTYPE_MASK) == CPU_SUBTYPE_ARM64E) )
- add = false;
-#endif
- if ( add )
- sImageFilesNeedingTermination.push_back(image);
+ sImageFilesNeedingTermination.push_back(image);
}
const char* getExecutablePath()
@@ -2029,7 +1849,7 @@
}
}
-#if TARGET_OS_OSX
+#if __MAC_OS_X_VERSION_MIN_REQUIRED
static void paths_expand_roots(const char **paths, const char *key, const char *val)
{
// assert(val != NULL);
@@ -2178,13 +1998,13 @@
}
else if ( strcmp(key, "DYLD_PRINT_STATISTICS") == 0 ) {
sEnv.DYLD_PRINT_STATISTICS = true;
-#if TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR
+#if __IPHONE_OS_VERSION_MIN_REQUIRED && !TARGET_OS_SIMULATOR
// <rdar://problem/26614838> DYLD_PRINT_STATISTICS no longer logs to xcode console for device apps
sForceStderr = true;
#endif
}
else if ( strcmp(key, "DYLD_PRINT_TO_STDERR") == 0 ) {
-#if TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR
+#if __IPHONE_OS_VERSION_MIN_REQUIRED && !TARGET_OS_SIMULATOR
// <rdar://problem/26633440> DYLD_PRINT_STATISTICS no longer logs to xcode console for device apps
sForceStderr = true;
#endif
@@ -2245,9 +2065,6 @@
sSharedCacheOverrideDir = value;
}
else if ( strcmp(key, "DYLD_USE_CLOSURES") == 0 ) {
- // Handled elsewhere
- }
- else if ( strcmp(key, "DYLD_SHARED_REGION_DATA_CONST") == 0 ) {
// Handled elsewhere
}
else if ( strcmp(key, "DYLD_FORCE_INVALID_CACHE_CLOSURES") == 0 ) {
@@ -2290,7 +2107,7 @@
#endif
#if !TARGET_OS_SIMULATOR
else if ( (strcmp(key, "DYLD_PRINT_TO_FILE") == 0) && (mainExecutableDir == NULL) && gLinkContext.allowEnvVarsSharedCache ) {
- int fd = dyld3::open(value, O_WRONLY | O_CREAT | O_APPEND, 0644);
+ int fd = open(value, O_WRONLY | O_CREAT | O_APPEND, 0644);
if ( fd != -1 ) {
sLogfile = fd;
sLogToFile = true;
@@ -2403,7 +2220,7 @@
#endif
-#if TARGET_OS_OSX
+#if __MAC_OS_X_VERSION_MIN_REQUIRED
//
// For security, setuid programs ignore DYLD_* environment variables.
// Additionally, the DYLD_* enviroment variables are removed
@@ -2455,7 +2272,7 @@
static void defaultUninitializedFallbackPaths(const char* envp[])
{
-#if TARGET_OS_OSX
+#if __MAC_OS_X_VERSION_MIN_REQUIRED
if ( !gLinkContext.allowClassicFallbackPaths ) {
sEnv.DYLD_FALLBACK_FRAMEWORK_PATH = sRestrictedFrameworkFallbackPaths;
sEnv.DYLD_FALLBACK_LIBRARY_PATH = sRestrictedLibraryFallbackPaths;
@@ -2623,7 +2440,7 @@
static void checkSharedRegionDisable(const dyld3::MachOLoaded* mainExecutableMH, uintptr_t mainExecutableSlide)
{
-#if TARGET_OS_OSX
+#if __MAC_OS_X_VERSION_MIN_REQUIRED
// if main executable has segments that overlap the shared region,
// then disable using the shared region
if ( mainExecutableMH->intersectsRange(SHARED_REGION_BASE, SHARED_REGION_SIZE) ) {
@@ -2637,9 +2454,6 @@
gLinkContext.sharedRegionMode = ImageLoader::kUsePrivateSharedRegion;
}
#endif
-#endif
-#if TARGET_OS_SIMULATOR
- gLinkContext.sharedRegionMode = ImageLoader::kUsePrivateSharedRegion;
#endif
// iOS cannot run without shared region
}
@@ -2841,28 +2655,33 @@
};
#endif
+#if __arm64__
+//
+// ARM64 sub-type lists
+//
+const int kARM64_RowCount = 2;
+static const cpu_subtype_t kARM64[kARM64_RowCount][4] = {
+
+ // armv64e can run: 64e, 64
+ { CPU_SUBTYPE_ARM64E, CPU_SUBTYPE_ARM64_V8, CPU_SUBTYPE_ARM64_ALL, CPU_SUBTYPE_END_OF_LIST },
+
+ // armv64 can run: 64
+ { CPU_SUBTYPE_ARM64_V8, CPU_SUBTYPE_ARM64_ALL, CPU_SUBTYPE_END_OF_LIST },
+};
+
#if __ARM64_ARCH_8_32__
-//
-// arm64_32 sub-type lists
-//
- static const cpu_subtype_t kARM64_32[] = { CPU_SUBTYPE_ARM64_32_V8, CPU_SUBTYPE_END_OF_LIST };
-#endif
-
-#if __arm64__ && __LP64__
-//
-// arm64[e] sub-type handing
-//
- #if __arm64e__
- // arm64e with keys on
- static const cpu_subtype_t kARM64e[] = { CPU_SUBTYPE_ARM64E, CPU_SUBTYPE_END_OF_LIST };
- // arm64 or arm64e with keys off
- static const cpu_subtype_t kARM64eKeysOff[] = { CPU_SUBTYPE_ARM64E, CPU_SUBTYPE_ARM64_V8, CPU_SUBTYPE_ARM64_ALL, CPU_SUBTYPE_END_OF_LIST };
- #else
- // arm64 main binary
- static const cpu_subtype_t kARM64[] = { CPU_SUBTYPE_ARM64_V8, CPU_SUBTYPE_ARM64_ALL, CPU_SUBTYPE_END_OF_LIST };
- #endif // __arm64e__
-#endif
-
+const int kARM64_32_RowCount = 2;
+static const cpu_subtype_t kARM64_32[kARM64_32_RowCount][4] = {
+
+ // armv64_32 can run: v8
+ { CPU_SUBTYPE_ARM64_32_V8, CPU_SUBTYPE_END_OF_LIST },
+
+ // armv64 can run: 64
+ { CPU_SUBTYPE_ARM64_V8, CPU_SUBTYPE_ARM64_ALL, CPU_SUBTYPE_END_OF_LIST },
+};
+#endif
+
+#endif
#if __x86_64__
//
@@ -2894,20 +2713,21 @@
break;
#endif
#if __arm64__
- #if __LP64__
case CPU_TYPE_ARM64:
- #if __arm64e__
- return ( sKeysDisabled ? kARM64eKeysOff : kARM64e);
- #else
- return kARM64;
- #endif
+ for (int i=0; i < kARM64_RowCount ; ++i) {
+ if ( kARM64[i][0] == subtype )
+ return kARM64[i];
+ }
break;
- #endif
-
- #if !__LP64__
+
+#if __ARM64_ARCH_8_32__
case CPU_TYPE_ARM64_32:
- return kARM64_32;
- #endif
+ for (int i=0; i < kARM64_32_RowCount ; ++i) {
+ if ( kARM64_32[i][0] == subtype )
+ return kARM64_32[i];
+ }
+ break;
+#endif
#endif
#if __x86_64__
@@ -2923,26 +2743,18 @@
}
+
+
// scan fat table-of-contents for best most preferred subtype
-static bool fatFindBestFromOrderedList(cpu_type_t cpu, const cpu_subtype_t list[], const fat_header* fh, int fd, uint64_t* offset, uint64_t* len)
+static bool fatFindBestFromOrderedList(cpu_type_t cpu, const cpu_subtype_t list[], const fat_header* fh, uint64_t* offset, uint64_t* len)
{
const fat_arch* const archs = (fat_arch*)(((char*)fh)+sizeof(fat_header));
for (uint32_t subTypeIndex=0; list[subTypeIndex] != CPU_SUBTYPE_END_OF_LIST; ++subTypeIndex) {
for(uint32_t fatIndex=0; fatIndex < OSSwapBigToHostInt32(fh->nfat_arch); ++fatIndex) {
- cpu_type_t sliceCpuType = OSSwapBigToHostInt32(archs[fatIndex].cputype);
- cpu_subtype_t sliceCpuSubType = OSSwapBigToHostInt32(archs[fatIndex].cpusubtype) & ~CPU_SUBTYPE_MASK;
- uint64_t sliceOffset = OSSwapBigToHostInt32(archs[fatIndex].offset);
- uint64_t sliceLen = OSSwapBigToHostInt32(archs[fatIndex].size);
- if ( (sliceCpuType == cpu) && ((list[subTypeIndex] & ~CPU_SUBTYPE_MASK) == sliceCpuSubType) ) {
-#if TARGET_OS_OSX && __has_feature(ptrauth_calls)
- if ( sOnlyPlatformArm64e && (sliceCpuType == CPU_TYPE_ARM64) && (sliceCpuSubType == CPU_SUBTYPE_ARM64E) ) {
- // if we can only load arm64e slices that are platform binaries, skip over slices that are not
- if ( !dyld3::MachOAnalyzer::sliceIsOSBinary(fd, sliceOffset, sliceLen) )
- continue;
- }
-#endif
- *offset = sliceOffset;
- *len = sliceLen;
+ if ( ((cpu_type_t)OSSwapBigToHostInt32(archs[fatIndex].cputype) == cpu)
+ && (list[subTypeIndex] == (cpu_subtype_t)OSSwapBigToHostInt32(archs[fatIndex].cpusubtype)) ) {
+ *offset = OSSwapBigToHostInt32(archs[fatIndex].offset);
+ *len = OSSwapBigToHostInt32(archs[fatIndex].size);
return true;
}
}
@@ -2950,7 +2762,6 @@
return false;
}
-#if !TARGET_OS_OSX || !__has_feature(ptrauth_calls)
// scan fat table-of-contents for exact match of cpu and cpu-sub-type
static bool fatFindExactMatch(cpu_type_t cpu, cpu_subtype_t subtype, const fat_header* fh, uint64_t* offset, uint64_t* len)
{
@@ -2965,7 +2776,6 @@
}
return false;
}
-#endif
// scan fat table-of-contents for image with matching cpu-type and runs-on-all-sub-types
static bool fatFindRunsOnAllCPUs(cpu_type_t cpu, const fat_header* fh, uint64_t* offset, uint64_t* len)
@@ -3074,7 +2884,7 @@
// each optimized for a different cpu-sub-type (e.g G3 or G5).
// This routine picks the optimal sub-image.
//
-static bool fatFindBest(const fat_header* fh, uint64_t* offset, uint64_t* len, int fd=-1)
+static bool fatFindBest(const fat_header* fh, uint64_t* offset, uint64_t* len)
{
if ( !fatValidate(fh) )
return false;
@@ -3090,17 +2900,13 @@
// use ordered list to find best sub-image in fat file
if ( subTypePreferenceList != NULL ) {
- if ( fatFindBestFromOrderedList(cpu, subTypePreferenceList, fh, fd, offset, len) )
+ if ( fatFindBestFromOrderedList(cpu, subTypePreferenceList, fh, offset, len) )
return true;
}
-#if TARGET_OS_OSX && __has_feature(ptrauth_calls)
- // don't use fallbacks for macOS arm64e to ensure only compatible binaries are loaded
- return false;
-#else
+
// if running cpu is not in list, try for an exact match
if ( fatFindExactMatch(cpu, sHostCPUsubtype, fh, offset, len) )
return true;
-#endif
}
// running on an uknown cpu, can only load generic code
@@ -3119,21 +2925,12 @@
#endif
}
-#if defined(__x86_64__) && !TARGET_OS_SIMULATOR
-#ifndef kIsTranslated
- #define kIsTranslated 0x4000000000000000ULL
-#endif
-bool isTranslated()
-{
- return ((*(uint64_t*)_COMM_PAGE_CPU_CAPABILITIES64) & kIsTranslated);
-}
-#endif
//
// This is used to validate if a non-fat (aka thin or raw) mach-o file can be used
// on the current processor. //
-bool isCompatibleMachO(const uint8_t* firstPage, const char* path, int fd=-1, uint64_t sliceOffset=0, uint64_t sliceLen=-1)
+bool isCompatibleMachO(const uint8_t* firstPage, const char* path)
{
#if CPU_SUBTYPES_SUPPORTED
// It is deemed compatible if any of the following are true:
@@ -3144,31 +2941,22 @@
if ( mh->magic == sMainExecutableMachHeader->magic ) {
if ( mh->cputype == sMainExecutableMachHeader->cputype ) {
if ( mh->cputype == sHostCPU ) {
- const cpu_subtype_t mhCPUSubtype = mh->cpusubtype & ~CPU_SUBTYPE_MASK;
// get preference ordered list of subtypes that this machine can use
const cpu_subtype_t* subTypePreferenceList = findCPUSubtypeList(mh->cputype, sHostCPUsubtype);
if ( subTypePreferenceList != NULL ) {
// if image's subtype is in the list, it is compatible
for (const cpu_subtype_t* p = subTypePreferenceList; *p != CPU_SUBTYPE_END_OF_LIST; ++p) {
- if ( *p == mhCPUSubtype ) {
- #if TARGET_OS_OSX && __has_feature(ptrauth_calls)
- if ( mhCPUSubtype == CPU_SUBTYPE_ARM64E ) {
- if ( !sOnlyPlatformArm64e || dyld3::MachOAnalyzer::sliceIsOSBinary(fd, sliceOffset, sliceLen) )
- return true;
- }
- else
- #endif
+ if ( *p == mh->cpusubtype )
return true;
- }
}
// have list and not in list, so not compatible
- throwf("incompatible cpu-subtype: 0x%08X in %s", mhCPUSubtype, path);
+ throwf("incompatible cpu-subtype: 0x%08X in %s", mh->cpusubtype, path);
}
// unknown cpu sub-type, but if exact match for current subtype then ok to use
- if ( mhCPUSubtype == sHostCPUsubtype )
+ if ( mh->cpusubtype == sHostCPUsubtype )
return true;
}
-
+
// cpu type has no ordered list of subtypes
switch (mh->cputype) {
case CPU_TYPE_I386:
@@ -3199,13 +2987,13 @@
static ImageLoaderMachO* instantiateFromLoadedImage(const macho_header* mh, uintptr_t slide, const char* path)
{
// try mach-o loader
-// if ( isCompatibleMachO((const uint8_t*)mh, path) ) {
+ if ( isCompatibleMachO((const uint8_t*)mh, path) ) {
ImageLoader* image = ImageLoaderMachO::instantiateMainExecutable(mh, slide, path, gLinkContext);
addImage(image);
return (ImageLoaderMachO*)image;
-// }
+ }
-// throw "main executable not a known format";
+ throw "main executable not a known format";
}
#if SUPPORT_ACCELERATE_TABLES
@@ -3323,7 +3111,7 @@
(strcmp(path, "/usr/lib/system/libsystem_pthread_debug.dylib") == 0) ||
(strcmp(path, "/sbin/launchd_sim_trampoline") == 0) ||
(strcmp(path, "/usr/sbin/iokitsimd") == 0) ||
- (strcmp(path, "/usr/lib/system/host/liblaunch_sim.dylib") == 0))
+ (strcmp(path, "/usr/lib/system/host/liblaunch_sim.dylib") == 0))
return true;
return false;
case LC_BUILD_VERSION:
@@ -3336,6 +3124,10 @@
case PLATFORM_WATCHOSSIMULATOR:
case PLATFORM_WATCHOS:
return true;
+ #if TARGET_OS_IOSMAC
+ case 6:
+ return true;
+ #endif
case PLATFORM_MACOS:
if ((strcmp(path, "/usr/lib/system/libsystem_kernel.dylib") == 0) ||
(strcmp(path, "/usr/lib/system/libsystem_platform.dylib") == 0) ||
@@ -3357,6 +3149,31 @@
}
#endif
+#if __MAC_OS_X_VERSION_MIN_REQUIRED
+static bool iOSonMacDenied(const char* path)
+{
+ static char* blackListBuffer = nullptr;
+ static size_t blackListSize = 0;
+ static bool tried = false;
+ if ( !tried ) {
+ // only try to map file once
+ blackListBuffer = (char*)mapFileReadOnly("/System/iOSSupport/dyld/macOS-deny-list.txt", blackListSize);
+ tried = true;
+ }
+ __block bool result = false;
+ if ( blackListBuffer != nullptr ) {
+ dyld3::forEachLineInFile(blackListBuffer, blackListSize, ^(const char* line, bool& stop) {
+ // lines in the file are prefixes. Any path that starts with one of these lines is allowed to be unzippered
+ size_t lineLen = strlen(line);
+ if ( (*line == '/') && strncmp(line, path, lineLen) == 0 ) {
+ result = true;
+ stop = true;
+ }
+ });
+ }
+ return result;
+}
+#endif
// map in file and instantiate an ImageLoader
static ImageLoader* loadPhase6(int fd, const struct stat& stat_buf, const char* path, const LoadContext& context)
@@ -3370,6 +3187,7 @@
throw "not a file";
uint8_t firstPages[MAX_MACH_O_HEADER_AND_LOAD_COMMANDS_SIZE];
+ uint8_t *firstPagesPtr = firstPages;
bool shortPage = false;
// min mach-o file is 4K
@@ -3389,7 +3207,7 @@
if ( fileStartAsFat->magic == OSSwapBigToHostInt32(FAT_MAGIC) ) {
if ( OSSwapBigToHostInt32(fileStartAsFat->nfat_arch) > ((4096 - sizeof(fat_header)) / sizeof(fat_arch)) )
throwf("fat header too large: %u entries", OSSwapBigToHostInt32(fileStartAsFat->nfat_arch));
- if ( fatFindBest(fileStartAsFat, &fileOffset, &fileLength, fd) ) {
+ if ( fatFindBest(fileStartAsFat, &fileOffset, &fileLength) ) {
if ( (fileOffset+fileLength) > (uint64_t)(stat_buf.st_size) )
throwf("truncated fat file. file length=%llu, but needed slice goes to %llu", stat_buf.st_size, fileOffset+fileLength);
if (pread(fd, firstPages, 4096, fileOffset) != 4096)
@@ -3404,7 +3222,7 @@
if ( shortPage )
throw "file too short";
- if ( isCompatibleMachO(firstPages, path, fd, fileOffset, fileLength) ) {
+ if ( isCompatibleMachO(firstPages, path) ) {
// only MH_BUNDLE, MH_DYLIB, and some MH_EXECUTE can be dynamically loaded
const mach_header* mh = (mach_header*)firstPages;
@@ -3418,45 +3236,60 @@
}
uint32_t headerAndLoadCommandsSize = sizeof(macho_header) + mh->sizeofcmds;
+ if ( headerAndLoadCommandsSize > MAX_MACH_O_HEADER_AND_LOAD_COMMANDS_SIZE )
+ throwf("malformed mach-o: load commands size (%u) > %u", headerAndLoadCommandsSize, MAX_MACH_O_HEADER_AND_LOAD_COMMANDS_SIZE);
+
if ( headerAndLoadCommandsSize > fileLength )
dyld::throwf("malformed mach-o: load commands size (%u) > mach-o file size (%llu)", headerAndLoadCommandsSize, fileLength);
- vm_address_t vmAllocatedFirstPages = 0;
- if ( headerAndLoadCommandsSize > MAX_MACH_O_HEADER_AND_LOAD_COMMANDS_SIZE ) {
- if ( ::vm_allocate(mach_task_self(), &vmAllocatedFirstPages, headerAndLoadCommandsSize, VM_FLAGS_ANYWHERE) == 0 ) {
- if ( ::pread(fd, (void*)vmAllocatedFirstPages, headerAndLoadCommandsSize, fileOffset) != headerAndLoadCommandsSize )
- throwf("pread of all load commands failed: %d", errno);
- mh = (mach_header*)vmAllocatedFirstPages;
- }
- else {
- throwf("malformed mach-o: load commands size (%u) > %u", headerAndLoadCommandsSize, MAX_MACH_O_HEADER_AND_LOAD_COMMANDS_SIZE);
- }
- }
- else if ( headerAndLoadCommandsSize > 4096 ) {
+ if ( headerAndLoadCommandsSize > 4096 ) {
// read more pages
unsigned readAmount = headerAndLoadCommandsSize - 4096;
if ( pread(fd, &firstPages[4096], readAmount, fileOffset+4096) != readAmount )
throwf("pread of extra load commands past 4KB failed: %d", errno);
}
- if ( !((dyld3::MachOFile*)mh)->loadableIntoProcess((dyld3::Platform)gProcessInfo->platform, path) ) {
- throwf("mach-o, but not built for platform %s", dyld3::MachOFile::platformName((dyld3::Platform)gProcessInfo->platform));
- }
-
-#if __has_feature(ptrauth_calls)
- if ( !sKeysDisabled && ((sMainExecutableMachHeader->cpusubtype & ~CPU_SUBTYPE_MASK) == CPU_SUBTYPE_ARM64E) && ((mh->cpusubtype & ~CPU_SUBTYPE_MASK) != CPU_SUBTYPE_ARM64E) )
+#if TARGET_OS_SIMULATOR
+ // <rdar://problem/14168872> dyld_sim should restrict loading osx binaries
+ if ( !isSimulatorBinary(firstPages, path) ) {
+ #if TARGET_OS_WATCH
+ throw "mach-o, but not built for watchOS simulator";
+ #elif TARGET_OS_TV
+ throw "mach-o, but not built for tvOS simulator";
+ #else
+ throw "mach-o, but not built for iOS simulator";
+ #endif
+ }
+#endif
+
+#if __MAC_OS_X_VERSION_MIN_REQUIRED
+ if ( gLinkContext.iOSonMac ) {
+ const dyld3::MachOFile* mf = (dyld3::MachOFile*)firstPages;
+ bool supportsiOSMac = mf->supportsPlatform(dyld3::Platform::iOSMac);
+ if ( !supportsiOSMac && iOSonMacDenied(path) ) {
+ throw "mach-o, but not built for UIKitForMac";
+ }
+ }
+ else if ( gLinkContext.driverKit ) {
+ const dyld3::MachOFile* mf = (dyld3::MachOFile*)firstPages;
+ bool isDriverKitDylib = mf->supportsPlatform(dyld3::Platform::driverKit);
+ if ( !isDriverKitDylib ) {
+ throw "mach-o, but not built for driverkit";
+ }
+ }
+#endif
+
+#if __arm64e__
+ if ( (sMainExecutableMachHeader->cpusubtype == CPU_SUBTYPE_ARM64E) && (mh->cpusubtype != CPU_SUBTYPE_ARM64E) )
throw "arm64 dylibs cannot be loaded into arm64e processes";
#endif
ImageLoader* image = nullptr;
{
dyld3::ScopedTimer timer(DBG_DYLD_TIMING_MAP_IMAGE, path, 0, 0);
- image = ImageLoaderMachO::instantiateFromFile(path, fd, (uint8_t*)mh, headerAndLoadCommandsSize, fileOffset, fileLength, stat_buf, gLinkContext);
+ image = ImageLoaderMachO::instantiateFromFile(path, fd, firstPagesPtr, headerAndLoadCommandsSize, fileOffset, fileLength, stat_buf, gLinkContext);
timer.setData4((uint64_t)image->machHeader());
}
-
- if ( vmAllocatedFirstPages != 0 )
- ::vm_deallocate(mach_task_self(), (vm_address_t)vmAllocatedFirstPages, headerAndLoadCommandsSize);
-
+
// validate
return checkandAddImage(image, context);
}
@@ -3523,8 +3356,6 @@
return false;
}
-static ImageLoader* loadPhase5check(const char* path, const char* orgPath, const LoadContext& context);
-
// try to open file
static ImageLoader* loadPhase5load(const char* path, const char* orgPath, const LoadContext& context, unsigned& cacheIndex, std::vector<const char*>* exceptions)
@@ -3560,6 +3391,13 @@
#else
auto findSharedCacheImage = ^() {
+#if __MAC_OS_X_VERSION_MIN_REQUIRED
+ if ( gLinkContext.iOSonMac ) {
+ // On iOSMac, we are also running with DYLD_ROOT_PATH set, but want to look up the orgPath
+ if ( dyld3::findInSharedCacheImage(sSharedCacheLoadInfo, orgPath, &shareCacheResults) )
+ return true;
+ }
+#endif
return dyld3::findInSharedCacheImage(sSharedCacheLoadInfo, path, &shareCacheResults);
};
@@ -3575,7 +3413,7 @@
// if RTLD_NOLOAD, do nothing if not already loaded
if ( context.dontLoad ) {
// <rdar://33412890> possible that there is an override of cache
- if ( dyld3::stat(path, &statBuf) == 0 ) {
+ if ( my_stat(path, &statBuf) == 0 ) {
ImageLoader* imageLoader = findLoadedImage(statBuf);
if ( imageLoader != NULL )
return imageLoader;
@@ -3585,7 +3423,7 @@
bool useCache = false;
if ( shareCacheResults.image == nullptr ) {
// HACK to support old caches
- existsOnDisk = ( dyld3::stat(path, &statBuf) == 0 );
+ existsOnDisk = ( my_stat(path, &statBuf) == 0 );
didStat = true;
statErrNo = errno;
useCache = !existsOnDisk;
@@ -3594,58 +3432,44 @@
// <rdar://problem/7014995> zero out stat buffer so mtime, etc are zero for items from the shared cache
bzero(&statBuf, sizeof(statBuf));
if ( shareCacheResults.image->overridableDylib() ) {
- existsOnDisk = ( dyld3::stat(path, &statBuf) == 0 );
+ existsOnDisk = ( my_stat(path, &statBuf) == 0 );
+ didStat = true;
statErrNo = errno;
if ( sSharedCacheLoadInfo.loadAddress->header.dylibsExpectedOnDisk ) {
- // old style macOS with dylibs on disk
uint64_t expectedINode;
uint64_t expectedMtime;
if ( shareCacheResults.image->hasFileModTimeAndInode(expectedINode, expectedMtime) ) {
- // if dylib found has same inode/mtime as one in cache, use one in cache
if ( (expectedMtime == statBuf.st_mtime) && (expectedINode == statBuf.st_ino) )
useCache = true;
}
}
else {
- // MRM style where dylibs are not on disk
- if ( !existsOnDisk ) {
- // looking at path where dylib should be, and we expect it to not be there but rather in the cache
- // Its possible we are looking at a deleted symlink path. For example, we are trying to open .../AppKit but
- // there's already a loaded root of .../Versions/C/AppKit. That used to work when the symlink was on-disk as
- // we'd realpath to find the shared cache path. Now we record the aliases in the cache and delete the symlinks.
- const char* pathInSharedCache = shareCacheResults.image->path();
- if ( strcmp(path, pathInSharedCache) != 0 ) {
- ImageLoader* imageLoader = loadPhase5check(pathInSharedCache, orgPath, context);
- if ( imageLoader != NULL )
- return imageLoader;
- }
+ if ( !existsOnDisk )
useCache = true;
- }
- else if ( !sRootsChecker.onDiskFileIsRoot(path, sSharedCacheLoadInfo.loadAddress,
- shareCacheResults.image, nullptr, statBuf.st_ino, statBuf.st_mtime) ) {
- // we found a file on disk, at the same path as the dyld cache has a dylib and it is one of the magic three
- useCache = true;
- }
}
}
else {
- // we are trying to override a dylib in the cache that does not allow overrides, ignore override and use cache
useCache = true;
}
}
if ( useCache ) {
- const dyld3::MachOFile* cacheDylibMH = (dyld3::MachOFile*)shareCacheResults.mhInCache;
- if ( !cacheDylibMH->loadableIntoProcess((dyld3::Platform)gProcessInfo->platform, path) )
- throwf("mach-o, but not built for platform %s", dyld3::MachOFile::platformName((dyld3::Platform)gProcessInfo->platform));
-
- ImageLoader* imageLoader = ImageLoaderMachO::instantiateFromCache((macho_header*)cacheDylibMH, shareCacheResults.pathInCache, shareCacheResults.slideInCache, statBuf, gLinkContext);
+#if __MAC_OS_X_VERSION_MIN_REQUIRED
+ if ( gLinkContext.iOSonMac ) {
+ const dyld3::MachOFile* mf = (dyld3::MachOFile*)shareCacheResults.mhInCache;
+ bool supportsiOSMac = mf->supportsPlatform(dyld3::Platform::iOSMac);
+ if ( !supportsiOSMac && iOSonMacDenied(path) ) {
+ throw "mach-o, but not built for UIKitForMac";
+ }
+ }
+#endif
+ ImageLoader* imageLoader = ImageLoaderMachO::instantiateFromCache((macho_header*)shareCacheResults.mhInCache, shareCacheResults.pathInCache, shareCacheResults.slideInCache, statBuf, gLinkContext);
return checkandAddImage(imageLoader, context);
}
}
// not in cache or cache not usable
if ( !didStat ) {
- existsOnDisk = ( dyld3::stat(path, &statBuf) == 0 );
+ existsOnDisk = ( my_stat(path, &statBuf) == 0 );
statErrNo = errno;
}
if ( existsOnDisk ) {
@@ -3924,18 +3748,8 @@
if ( image != NULL ) {
// if original path is in the dyld cache, then mark this one found as an override
dyld3::SharedCacheFindDylibResults shareCacheResults;
- if ( dyld3::findInSharedCacheImage(sSharedCacheLoadInfo, path, &shareCacheResults) && (shareCacheResults.image != nullptr) ) {
+ if ( dyld3::findInSharedCacheImage(sSharedCacheLoadInfo, path, &shareCacheResults) && (shareCacheResults.image != nullptr) )
image->setOverridesCachedDylib(shareCacheResults.image->imageNum());
- }
-#if SUPPORT_ROOT_PATH
- else if ( (gLinkContext.rootPaths != nullptr)
- && dyld3::findInSharedCacheImage(sSharedCacheLoadInfo, orgPath, &shareCacheResults)
- && (shareCacheResults.image != nullptr) ) {
- // DYLD_ROOT_PATH, ie, iOSMac, also needs to check if the original path is overridden
- // as the root prefix has been applied to 'path', but the framework path searches without a root path prefix
- image->setOverridesCachedDylib(shareCacheResults.image->imageNum());
- }
-#endif
return image;
}
}
@@ -3958,21 +3772,11 @@
image = loadPhase2cache(libpath, orgPath, context, cacheIndex, exceptions);
if ( image != NULL ) {
// if original path is in the dyld cache, then mark this one found as an override
- dyld3::SharedCacheFindDylibResults shareCacheResults;
- if ( dyld3::findInSharedCacheImage(sSharedCacheLoadInfo, path, &shareCacheResults) && (shareCacheResults.image != nullptr) ) {
- image->setOverridesCachedDylib(shareCacheResults.image->imageNum());
- }
-#if SUPPORT_ROOT_PATH
- else if ( (gLinkContext.rootPaths != nullptr)
- && dyld3::findInSharedCacheImage(sSharedCacheLoadInfo, orgPath, &shareCacheResults)
- && (shareCacheResults.image != nullptr) ) {
- // DYLD_ROOT_PATH, ie, iOSMac, also needs to check if the original path is overridden
- // as the root prefix has been applied to 'path', but the library path searches without a root path prefix
- image->setOverridesCachedDylib(shareCacheResults.image->imageNum());
- }
-#endif
- return image;
- }
+ dyld3::SharedCacheFindDylibResults shareCacheResults;
+ if ( dyld3::findInSharedCacheImage(sSharedCacheLoadInfo, path, &shareCacheResults) && (shareCacheResults.image != nullptr) )
+ image->setOverridesCachedDylib(shareCacheResults.image->imageNum());
+ return image;
+ }
}
}
return NULL;
@@ -4047,7 +3851,7 @@
{
//dyld::log("%s(%s, %p)\n", __func__ , path, exceptions);
-#if TARGET_OS_OSX
+#if __MAC_OS_X_VERSION_MIN_REQUIRED
// handle macOS dylibs dlopen()ing versioned path which needs to map to flat path in mazipan simulator
if ( gLinkContext.iOSonMac && strstr(path, ".framework/Versions/")) {
uintptr_t sourceOffset = 0;
@@ -4145,11 +3949,6 @@
if ( !gSharedCacheOverridden && !image->inSharedCache() && image->isDylib() && dyld3::MachOFile::isSharedCacheEligiblePath(path) && inSharedCache(path) ) {
gSharedCacheOverridden = true;
}
- // <rdar://problem/59327556> if file loaded via symlink to a root of something in dyld cache, mark it as an override
- dyld3::SharedCacheFindDylibResults shareCacheResults;
- if ( !image->inSharedCache() && dyld3::findInSharedCacheImage(sSharedCacheLoadInfo, image->getRealPath(), &shareCacheResults) && (shareCacheResults.image != nullptr) )
- image->setOverridesCachedDylib(shareCacheResults.image->imageNum());
-
return image;
}
else if ( exceptions.size() == 0 ) {
@@ -4180,20 +3979,19 @@
-static void mapSharedCache(uintptr_t mainExecutableSlide)
+static void mapSharedCache()
{
dyld3::SharedCacheOptions opts;
opts.cacheDirOverride = sSharedCacheOverrideDir;
opts.forcePrivate = (gLinkContext.sharedRegionMode == ImageLoader::kUsePrivateSharedRegion);
+
+
#if __x86_64__ && !TARGET_OS_SIMULATOR
opts.useHaswell = sHaswell;
#else
opts.useHaswell = false;
#endif
opts.verbose = gLinkContext.verboseMapping;
- // <rdar://problem/32031197> respect -disable_aslr boot-arg
- // <rdar://problem/56299169> kern.bootargs is now blocked
- opts.disableASLR = (mainExecutableSlide == 0) && dyld3::internalInstall(); // infer ASLR is off if main executable is not slid
loadDyldCache(opts, &sSharedCacheLoadInfo);
// update global state
@@ -4206,7 +4004,7 @@
dyld3::kdebug_trace_dyld_image(DBG_DYLD_UUID_SHARED_CACHE_A, sSharedCacheLoadInfo.path, (const uuid_t *)&dyld::gProcessInfo->sharedCacheUUID[0], {0,0}, {{ 0, 0 }}, (const mach_header *)sSharedCacheLoadInfo.loadAddress);
}
-//#if TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR
+//#if __IPHONE_OS_VERSION_MIN_REQUIRED && !TARGET_OS_SIMULATOR
// RAM disk booting does not have shared cache yet
// Don't make lack of a shared cache fatal in that case
// if ( sSharedCacheLoadInfo.loadAddress == nullptr ) {
@@ -4390,24 +4188,6 @@
strlcat(error_string, sSharedCacheLoadInfo.errorMessage, sizeof(error_string));
strlcat(error_string, "\n", sizeof(error_string));
strlcat(error_string, message, sizeof(error_string));
- } else if ( dyld::gProcessInfo->errorKind == DYLD_EXIT_REASON_DYLIB_MISSING ) {
- // If a dylib is missing, but we have the cache, print the cache UUID to make it easier
- // to see what might have gone wrong
- if ( sSharedCacheLoadInfo.loadAddress == nullptr ) {
- strlcpy(error_string, "dyld: No shared cache present\n", sizeof(error_string));
- } else {
- uuid_t cacheUUID;
- sSharedCacheLoadInfo.loadAddress->getUUID(cacheUUID);
- uuid_string_t uuidStr;
- uuid_unparse_upper(cacheUUID, uuidStr);
-
- strlcpy(error_string, "dyld: Using shared cache: ", sizeof(error_string));
- strlcat(error_string, uuidStr, sizeof(error_string));
- strlcat(error_string, "\n", sizeof(error_string));
- }
-
- dyld::log("dyld: %s\n", message);
- strlcat(error_string, message, sizeof(error_string));
}
else {
dyld::log("dyld: %s\n", message);
@@ -4479,8 +4259,7 @@
#endif
if ( target == NULL )
throwf("image not found for lazy pointer at %p", lazyPointer);
- DyldSharedCache::DataConstLazyScopedWriter patcher(gLinkContext.dyldCache, mach_task_self(), gLinkContext.verboseMapping ? &dyld::log : nullptr);
- result = target->doBindLazySymbol(lazyPointer, gLinkContext, patcher);
+ result = target->doBindLazySymbol(lazyPointer, gLinkContext);
}
catch (const char* message) {
dyld::log("dyld: lazy symbol binding failed: %s\n", message);
@@ -4952,7 +4731,7 @@
// Its presences means that the binary wants to have DYLD ignore
// DYLD_ environment variables.
//
-#if TARGET_OS_OSX
+#if __MAC_OS_X_VERSION_MIN_REQUIRED
static bool hasRestrictedSegment(const macho_header* mh)
{
const uint32_t cmd_count = mh->ncmds;
@@ -4983,7 +4762,7 @@
}
#endif
-#if TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR
+#if __IPHONE_OS_VERSION_MIN_REQUIRED && !TARGET_OS_SIMULATOR
static bool isFairPlayEncrypted(const macho_header* mh)
{
const uint32_t cmd_count = mh->ncmds;
@@ -5003,9 +4782,7 @@
#if SUPPORT_VERSIONED_PATHS
-#define FIRST_PAGE_BUFFER_SIZE 16384
-
-static bool readFirstPage(const char* dylibPath, uint8_t firstPage[FIRST_PAGE_BUFFER_SIZE])
+static bool readFirstPage(const char* dylibPath, uint8_t firstPage[4096])
{
firstPage[0] = 0;
// open file (automagically closed when this function exits)
@@ -5014,7 +4791,7 @@
if ( file.getFileDescriptor() == -1 )
return false;
- if ( pread(file.getFileDescriptor(), firstPage, FIRST_PAGE_BUFFER_SIZE, 0) != FIRST_PAGE_BUFFER_SIZE )
+ if ( pread(file.getFileDescriptor(), firstPage, 4096, 0) != 4096 )
return false;
// if fat wrapper, find usable sub-file
@@ -5023,7 +4800,7 @@
uint64_t fileOffset;
uint64_t fileLength;
if ( fatFindBest(fileStartAsFat, &fileOffset, &fileLength) ) {
- if ( pread(file.getFileDescriptor(), firstPage, FIRST_PAGE_BUFFER_SIZE, fileOffset) != FIRST_PAGE_BUFFER_SIZE )
+ if ( pread(file.getFileDescriptor(), firstPage, 4096, fileOffset) != 4096 )
return false;
}
else {
@@ -5040,7 +4817,7 @@
//
static bool getDylibVersionAndInstallname(const char* dylibPath, uint32_t* version, char* installName)
{
- uint8_t firstPage[FIRST_PAGE_BUFFER_SIZE];
+ uint8_t firstPage[4096];
const macho_header* mh = (macho_header*)firstPage;
if ( !readFirstPage(dylibPath, firstPage) ) {
// If file cannot be read, check to see if path is in shared cache
@@ -5061,7 +4838,7 @@
// scan load commands for LC_ID_DYLIB
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)+FIRST_PAGE_BUFFER_SIZE);
+ 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) {
@@ -5314,21 +5091,18 @@
uint64_t amfiInputFlags = 0;
#if TARGET_OS_SIMULATOR
amfiInputFlags |= AMFI_DYLD_INPUT_PROC_IN_SIMULATOR;
-#elif TARGET_OS_OSX
+#elif __MAC_OS_X_VERSION_MIN_REQUIRED
if ( hasRestrictedSegment(mainExecutableMH) )
amfiInputFlags |= AMFI_DYLD_INPUT_PROC_HAS_RESTRICT_SEG;
-#elif TARGET_OS_IPHONE
+#elif __IPHONE_OS_VERSION_MIN_REQUIRED
if ( isFairPlayEncrypted(mainExecutableMH) )
amfiInputFlags |= AMFI_DYLD_INPUT_PROC_IS_ENCRYPTED;
#endif
uint64_t amfiOutputFlags = 0;
const char* amfiFake = nullptr;
- if constexpr(BUILD_FOR_TESTING == 1) {
+ if ( dyld3::internalInstall() && dyld3::BootArgs::enableDyldTestMode() ) {
amfiFake = _simple_getenv(envp, "DYLD_AMFI_FAKE");
- } else if ( dyld3::internalInstall() && dyld3::BootArgs::enableDyldTestMode() ) {
- amfiFake = _simple_getenv(envp, "DYLD_AMFI_FAKE");
- }
-
+ }
if ( amfiFake != nullptr ) {
amfiOutputFlags = hexToUInt64(amfiFake, nullptr);
}
@@ -5346,7 +5120,7 @@
#endif
}
else {
-#if TARGET_OS_OSX
+#if __MAC_OS_X_VERSION_MIN_REQUIRED
// support chrooting from old kernel
bool isRestricted = false;
bool libraryValidation = false;
@@ -5383,15 +5157,15 @@
// called by _dyld_register_driverkit_main()
void setMainEntry(void (*main)())
{
- if ( sEntryOverride == nullptr )
- sEntryOverride = main;
+ if ( sEntryOveride == nullptr )
+ sEntryOveride = main;
else
halt("_dyld_register_driverkit_main() may only be called once");
}
bool processIsRestricted()
{
-#if TARGET_OS_OSX
+#if __MAC_OS_X_VERSION_MIN_REQUIRED
return !gLinkContext.allowEnvVarsPath;
#else
return false;
@@ -5430,7 +5204,7 @@
fsobj_id_t fsobj_id = {0};
if (endptr != nullptr) {
fsobj_id_scalar = hexToUInt64(endptr+1, &endptr);
- fsobj_id = *reinterpret_cast<fsobj_id_t *>(&fsobj_id_scalar);
+ fsobj_id = *reinterpret_cast<fsobj_id_t *>(&tmp);
}
const uint32_t cmd_count = mh->ncmds;
const struct load_command* const cmds = (struct load_command*)((char*)mh + sizeof(macho_header));
@@ -5452,10 +5226,10 @@
}
}
-#if TARGET_OS_OSX
+#if __MAC_OS_X_VERSION_MIN_REQUIRED
static void* getProcessInfo() { return dyld::gProcessInfo; }
static const SyscallHelpers sSysCalls = {
- 14,
+ 12,
// added in version 1
&open,
&close,
@@ -5500,7 +5274,7 @@
&getpid,
&mach_port_insert_right,
&mach_port_allocate,
- &mach_msg_sim_interposed,
+ &mach_msg,
// Added in version 6
&abort_with_payload,
// Added in version 7
@@ -5525,12 +5299,7 @@
// Add in version 12
&mach_msg_destroy,
&mach_port_construct,
- &mach_port_destruct,
- // Added in version 13
- &fstat,
- &vm_copy,
- // Added in version 14
- &task_dyld_process_info_notify_get
+ &mach_port_destruct
};
__attribute__((noinline))
@@ -5573,7 +5342,7 @@
if ( pread(fd, firstPage, 4096, fileOffset) != 4096 )
return "pread(dyld_sim) failed";
}
- else if ( !isCompatibleMachO(firstPage, dyldPath, fd, fileOffset, fileLength) ) {
+ else if ( !isCompatibleMachO(firstPage, dyldPath) ) {
return "dyld_sim is not compatible with the loaded process, likely due to architecture mismatch";
}
@@ -5705,22 +5474,34 @@
}
close(fd);
- // Walk newly mapped dyld_sim load commands to find entry point
+ // walk newly mapped dyld_sim __TEXT load commands to find entry point
uintptr_t entry = 0;
- bool unusedUsesCRT = false;
- uint64_t entryOffset = 0;
- if ( !((dyld3::MachOAnalyzer*)loadAddress)->getEntry(entryOffset, unusedUsesCRT) ) {
+ 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 "dyld_sim entry point not in __TEXT segment";
+ if ( registers->__eip > (firstSeg->vmaddr + firstSeg->vmsize) )
+ return "dyld_sim entry point not in __TEXT segment";
+ 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 "dyld_sim entry point not in __TEXT segment";
+ if ( registers->__rip > (firstSeg->vmaddr + firstSeg->vmsize) )
+ return "dyld_sim entry point not in __TEXT segment";
+ entry = (registers->__rip + loadAddress - preferredLoadAddress);
+ #endif
+ }
+ cmd = (const struct load_command*)(((char*)cmd)+cmd->cmdsize);
+ }
+ if ( entry == 0 )
return "dyld_sim entry not found";
- }
-
- // Translate the load address by the entry offset in order to get the runtime address.
- entry = (uintptr_t)loadAddress;
- entry += entryOffset;
-
-#if __arm64e__
- // It's necessary to sign the entry pointer.
- entry = (uint64_t)__builtin_ptrauth_sign_unauthenticated((void*)entry, ptrauth_key_asia, 0);
-#endif
// notify debugger that dyld_sim is loaded
dyld_image_info info;
@@ -5736,7 +5517,7 @@
fsobj.fid_objno = (uint32_t)inode;
fsobj.fid_generation = (uint32_t)(inode>>32);
fsid.val[0] = sb.st_dev;
- dyld3::kdebug_trace_dyld_image(DBG_DYLD_UUID_MAP_A, dyldPath, (const uuid_t *)&uuidCmd->uuid[0], fsobj, fsid, (const mach_header *)loadAddress);
+ dyld3::kdebug_trace_dyld_image(DBG_DYLD_UUID_MAP_A, dyldPath, (const uuid_t *)&uuidCmd->uuid[0], fsobj, fsid, (const mach_header *)mh);
const char** appleParams = apple;
@@ -5873,6 +5654,33 @@
return false;
}
}
+#if __IPHONE_OS_VERSION_MIN_REQUIRED
+ // verify this closure is not from a previous reboot
+ const char* expectedBootUUID = mainClosure->bootUUID();
+ char actualBootSessionUUID[256] = { 0 };
+ size_t bootSize = sizeof(actualBootSessionUUID);
+ bool gotActualBootUUID = (sysctlbyname("kern.bootsessionuuid", actualBootSessionUUID, &bootSize, NULL, 0) == 0);
+ if ( gotActualBootUUID ) {
+ // If we got a boot UUID then we should have also recorded it in the closure
+ if ( expectedBootUUID == nullptr) {
+ // The closure didn't have a UUID but now we do. This isn't valid.
+ if ( gLinkContext.verboseWarnings )
+ dyld::log("dyld: closure %p missing boot-UUID\n", mainClosure);
+ return false;
+ } else if ( strcmp(expectedBootUUID, actualBootSessionUUID) != 0 ) {
+ if ( gLinkContext.verboseWarnings )
+ dyld::log("dyld: closure %p built in different boot context\n", mainClosure);
+ return false;
+ }
+ } else {
+ // We didn't get a UUID now, which is ok so long as the closure also doesn't have one.
+ if ( expectedBootUUID != nullptr) {
+ if ( gLinkContext.verboseWarnings )
+ dyld::log("dyld: closure %p has boot-UUID\n", mainClosure);
+ return false;
+ }
+ }
+#endif
}
// verify all mach-o files have not changed since closure was built
@@ -5882,7 +5690,7 @@
__block uint64_t expectedMtime;
if ( image->hasFileModTimeAndInode(expectedInode, expectedMtime) ) {
struct stat statBuf;
- if ( dyld3::stat(image->path(), &statBuf) == 0 ) {
+ if ( ::stat(image->path(), &statBuf) == 0 ) {
if ( (statBuf.st_mtime != expectedMtime) || (statBuf.st_ino != expectedInode) ) {
if ( gLinkContext.verboseWarnings )
dyld::log("dyld: closure %p not used because mtime/inode for '%s' has changed since closure was built\n", mainClosure, image->path());
@@ -5902,7 +5710,7 @@
return false;
// verify cdHash of main executable is same as recorded in closure
- const dyld3::closure::Image* mainImage = mainClosure->topImage();
+ const dyld3::closure::Image* mainImage = mainClosure->images()->imageForNum(mainClosure->topImage());
__block bool foundCDHash = false;
__block bool foundValidCDHash = false;
@@ -5986,7 +5794,7 @@
// verify files that are supposed to be missing actually are missing
mainClosure->forEachMustBeMissingFile(^(const char* path, bool& stop) {
struct stat statBuf;
- if ( dyld3::stat(path, &statBuf) == 0 ) {
+ if ( ::stat(path, &statBuf) == 0 ) {
stop = true;
foundFileThatInvalidatesClosure = true;
if ( gLinkContext.verboseWarnings )
@@ -5997,7 +5805,7 @@
// verify files that are supposed to exist are there with the
mainClosure->forEachSkipIfExistsFile(^(const dyld3::closure::LaunchClosure::SkippedFile &file, bool &stop) {
struct stat statBuf;
- if ( dyld3::stat(file.path, &statBuf) == 0 ) {
+ if ( ::stat(file.path, &statBuf) == 0 ) {
if ( (statBuf.st_mtime != file.mtime) || (statBuf.st_ino != file.inode) ) {
if ( gLinkContext.verboseWarnings )
dyld::log("dyld: closure %p not used because mtime/inode for '%s' has changed since closure was built\n", mainClosure, file.path);
@@ -6043,12 +5851,9 @@
static bool launchWithClosure(const dyld3::closure::LaunchClosure* mainClosure,
const DyldSharedCache* dyldCache,
const dyld3::MachOLoaded* mainExecutableMH, uintptr_t mainExecutableSlide,
- int argc, const char* argv[], const char* envp[], const char* apple[], Diagnostics& diag,
- uintptr_t* entry, uintptr_t* startGlue, bool* closureOutOfDate, bool* recoverable)
-{
- *closureOutOfDate = false;
- *recoverable = true;
-
+ int argc, const char* argv[], const char* envp[], const char* apple[],
+ uintptr_t* entry, uintptr_t* startGlue)
+{
// build list of all known ImageArrays (at most three: cached dylibs, other OS dylibs, and main prog)
STACK_ALLOC_ARRAY(const dyld3::closure::ImageArray*, imagesArrays, 3);
const dyld3::closure::ImageArray* mainClosureImages = mainClosure->images();
@@ -6061,23 +5866,19 @@
// allocate space for Array<LoadedImage>
STACK_ALLOC_ARRAY(dyld3::LoadedImage, allImages, mainClosure->initialLoadCount());
- STACK_ALLOC_ARRAY(dyld3::LoadedImage, noImages, 1);
// Get the pre-optimized Objective-C so that we can bind the selectors
const dyld3::closure::ObjCSelectorOpt* selectorOpt = nullptr;
dyld3::Array<dyld3::closure::Image::ObjCSelectorImage> selectorImages;
mainClosure->selectorHashTable(selectorImages, selectorOpt);
- __block dyld3::Loader loader(noImages, allImages, dyldCache, imagesArrays,
- selectorOpt, selectorImages, sRootsChecker,
- (dyld3::Platform)gProcessInfo->platform,
+ __block dyld3::Loader loader({}, allImages, dyldCache, imagesArrays,
+ selectorOpt, selectorImages,
(gLinkContext.verboseLoading ? &dolog : &nolog),
(gLinkContext.verboseMapping ? &dolog : &nolog),
(gLinkContext.verboseBind ? &dolog : &nolog),
- (gLinkContext.verboseDOF ? &dolog : &nolog),
- (sClosureKind == ClosureKind::minimal),
- (dyld3::LaunchErrorInfo*)&gProcessInfo->errorKind);
- dyld3::closure::ImageNum mainImageNum = mainClosure->topImageNum();
+ (gLinkContext.verboseDOF ? &dolog : &nolog));
+ dyld3::closure::ImageNum mainImageNum = mainClosure->topImage();
mainClosureImages->forEachImage(^(const dyld3::closure::Image* image, bool& stop) {
if ( image->imageNum() == mainImageNum ) {
// add main executable (which is already mapped by kernel) to list
@@ -6095,32 +5896,13 @@
// recursively load all dependents and fill in allImages array
bool someCacheImageOverridden = false;
+ Diagnostics diag;
loader.completeAllDependents(diag, someCacheImageOverridden);
if ( diag.noError() )
- loader.mapAndFixupAllImages(diag, dyld3::Loader::dtraceUserProbesEnabled(), false, closureOutOfDate, recoverable);
+ loader.mapAndFixupAllImages(diag, dyld3::Loader::dtraceUserProbesEnabled());
if ( diag.hasError() ) {
if ( gLinkContext.verboseWarnings )
dyld::log("dyld: %s\n", diag.errorMessage());
- if ( !*recoverable ) {
- // we won't make it to libDyldEntry, so the image list will never be set up
- // hack together an image list here so crash reports show the binaries involved
- __block unsigned loadImageCount = 0;
- loader.forEachImage(^(const dyld3::LoadedImage& li, bool& stop) {
- ++loadImageCount;
- });
- dyld_image_info* tempArray = new dyld_image_info[loadImageCount];
- __block unsigned i = 0;
- loader.forEachImage(^(const dyld3::LoadedImage& li, bool& stop) {
- tempArray[i].imageFilePath = li.image()->path();
- tempArray[i].imageLoadAddress = li.loadedAddress();
- tempArray[i].imageFileModDate = 0;
- ++i;
- });
- dyld::gProcessInfo->infoArray = tempArray;
- dyld::gProcessInfo->infoArrayCount = loadImageCount;
- dyld::gProcessInfo->initialImageCount= loadImageCount;
- dyld::gProcessInfo->infoArrayChangeTimestamp = mach_absolute_time();
- }
return false;
}
@@ -6134,15 +5916,9 @@
mainClosure->libDyldEntry(dyldEntry);
const dyld3::LibDyldEntryVector* libDyldEntry = (dyld3::LibDyldEntryVector*)loader.resolveTarget(dyldEntry);
- // Set the logging function first so that libdyld can log from inside all other entry vector functions
-#if !TARGET_OS_SIMULATOR
- if ( libDyldEntry->vectorVersion > 3 )
- libDyldEntry->setLogFunction(&dyld::vlog);
-#endif
-
// send info on all images to libdyld.dylb
- libDyldEntry->setVars(mainExecutableMH, argc, argv, envp, apple, sKeysDisabled, sOnlyPlatformArm64e, gEnableSharedCacheDataConst);
-#if TARGET_OS_OSX
+ libDyldEntry->setVars(mainExecutableMH, argc, argv, envp, apple);
+#if __MAC_OS_X_VERSION_MIN_REQUIRED
uint32_t progVarsOffset;
if ( mainClosure->hasProgramVars(progVarsOffset) ) {
if ( libDyldEntry->vectorVersion >= 8 ) {
@@ -6170,14 +5946,13 @@
if ( libDyldEntry->vectorVersion > 2 )
libDyldEntry->setChildForkFunction(&_dyld_fork_child);
- if ( libDyldEntry->vectorVersion >= 9 )
- libDyldEntry->setLaunchMode(sLaunchModeUsed);
-
-
+#if !TARGET_OS_SIMULATOR
+ if ( libDyldEntry->vectorVersion > 3 )
+ libDyldEntry->setLogFunction(&dyld::vlog);
+#endif
libDyldEntry->setOldAllImageInfo(gProcessInfo);
dyld3::LoadedImage* libSys = loader.findImage(mainClosure->libSystemImageNum());
- libDyldEntry->setInitialImageList(mainClosure, dyldCache, sSharedCacheLoadInfo.path, allImages, *libSys,
- mach_task_self());
+ libDyldEntry->setInitialImageList(mainClosure, dyldCache, sSharedCacheLoadInfo.path, allImages, *libSys);
// run initializers
CRSetCrashLogMessage("dyld3: launch, running initializers");
libDyldEntry->runInitialzersBottomUp((mach_header*)mainExecutableMH);
@@ -6186,14 +5961,11 @@
if (dyld3::kdebug_trace_dyld_enabled(DBG_DYLD_TIMING_LAUNCH_EXECUTABLE)) {
dyld3::kdebug_trace_dyld_duration_end(launchTraceID, DBG_DYLD_TIMING_LAUNCH_EXECUTABLE, 0, 0, 3);
}
-#if TARGET_OS_OSX
+#if __MAC_OS_X_VERSION_MIN_REQUIRED
if ( gLinkContext.driverKit ) {
- if (libDyldEntry->vectorVersion >= 10)
- *entry = (uintptr_t)libDyldEntry->getDriverkitMain();
+ *entry = (uintptr_t)sEntryOveride;
if ( *entry == 0 )
halt("no entry point registered");
- if ( sClosureKind != ClosureKind::minimal )
- halt("driverkit process should run with minimal closures");
*startGlue = (uintptr_t)(libDyldEntry->startFunc);
}
else
@@ -6206,10 +5978,6 @@
// set entry to "main" function in program
*startGlue = (uintptr_t)(libDyldEntry->startFunc);
*entry = loader.resolveTarget(progEntry);
-#if __has_feature(ptrauth_calls)
- // start() calls the result pointer as a function pointer so we need to sign it.
- *entry = (uintptr_t)__builtin_ptrauth_sign_unauthenticated((void*)*entry, 0, 0);
-#endif
}
else if ( mainClosure->startEntry(progEntry) ) {
// old style app linked with crt1.o
@@ -6226,17 +5994,29 @@
}
+static const char* getTempDir(const char* envp[])
+{
+ if (const char* tempDir = _simple_getenv(envp, "TMPDIR"))
+ return tempDir;
+
+#if __MAC_OS_X_VERSION_MIN_REQUIRED
+ return "/private/tmp/";
+#else
+ return "/private/var/tmp/";
+#endif
+}
+
static const dyld3::closure::LaunchClosure* mapClosureFile(const char* closurePath)
{
struct stat statbuf;
- if ( dyld3::stat(closurePath, &statbuf) == -1 )
+ if ( ::stat(closurePath, &statbuf) == -1 )
return nullptr;
// check for tombstone file
if ( statbuf.st_size == 0 )
return nullptr;
- int fd = dyld3::open(closurePath, O_RDONLY, 0);
+ int fd = ::open(closurePath, O_RDONLY);
if ( fd < 0 )
return nullptr;
@@ -6256,11 +6036,10 @@
return false;
}
+
// Note: buildLaunchClosure calls halt() if there is an error building the closure
static const dyld3::closure::LaunchClosure* buildLaunchClosure(const uint8_t* mainExecutableCDHash,
- const dyld3::closure::LoadedFileInfo& mainFileInfo,
- const char* envp[],
- const dyld3::Array<uint8_t>& bootToken)
+ const dyld3::closure::LoadedFileInfo& mainFileInfo, const char* envp[])
{
const dyld3::MachOLoaded* mainExecutableMH = (const dyld3::MachOLoaded*)mainFileInfo.fileContent;
dyld3::closure::PathOverrides pathOverrides;
@@ -6274,30 +6053,24 @@
}
char closurePath[PATH_MAX];
- bool canSaveClosureToDisk = !bootToken.empty() && dyld3::closure::LaunchClosure::buildClosureCachePath(mainFileInfo.path, envp, true, closurePath);
- dyld3::LaunchErrorInfo* errorInfo = (dyld3::LaunchErrorInfo*)&gProcessInfo->errorKind;
- const dyld3::GradedArchs& archs = dyld3::GradedArchs::forCurrentOS(sKeysDisabled, sOnlyPlatformArm64e);
+ dyld3::closure::ClosureBuilder::LaunchErrorInfo* errorInfo = (dyld3::closure::ClosureBuilder::LaunchErrorInfo*)&gProcessInfo->errorKind;
dyld3::closure::FileSystemPhysical fileSystem;
+ const dyld3::GradedArchs& archs = dyld3::GradedArchs::forCurrentOS(mainExecutableMH);
dyld3::closure::ClosureBuilder::AtPath atPathHanding = (gLinkContext.allowAtPaths ? dyld3::closure::ClosureBuilder::AtPath::all : dyld3::closure::ClosureBuilder::AtPath::none);
- dyld3::closure::ClosureBuilder builder(dyld3::closure::kFirstLaunchClosureImageNum, fileSystem, sRootsChecker, sSharedCacheLoadInfo.loadAddress, true,
- archs, pathOverrides, atPathHanding, gLinkContext.allowEnvVarsPath, errorInfo, (dyld3::Platform)gProcessInfo->platform);
+ dyld3::closure::ClosureBuilder builder(dyld3::closure::kFirstLaunchClosureImageNum, fileSystem, sSharedCacheLoadInfo.loadAddress, true,
+ archs, pathOverrides, atPathHanding, gLinkContext.allowEnvVarsPath, errorInfo);
if (sForceInvalidSharedCacheClosureFormat)
builder.setDyldCacheInvalidFormatVersion();
- if (sClosureKind == ClosureKind::minimal)
- builder.makeMinimalClosures();
- else if ( canSaveClosureToDisk )
- builder.setCanSkipEncodingRebases(); // <rdar://problem/56172089> large iOS apps with massive number of rebases can overflow 16MB closure file limit
if ( !gLinkContext.allowInterposing )
builder.disableInterposing();
-
const dyld3::closure::LaunchClosure* result = builder.makeLaunchClosure(mainFileInfo, gLinkContext.allowInsertFailures);
if ( builder.diagnostics().hasError() ) {
const char* errMsg = builder.diagnostics().errorMessage();
// let apps with this error fallback to dyld2 mode
if ( needsDyld2ErrorMessage(errMsg) ) {
- if ( canSaveClosureToDisk ) {
+ if ( dyld3::closure::LaunchClosure::buildClosureCachePath(mainFileInfo.path, closurePath, getTempDir(envp), true) ) {
// create empty file as a tombstone to not keep trying
- int fd = dyld3::open(closurePath, O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR);
+ int fd = ::open(closurePath, O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR);
if ( fd != -1 ) {
::fchmod(fd, S_IRUSR);
::close(fd);
@@ -6324,24 +6097,8 @@
dyld::log("dyld: somehow just built closure is invalid\n");
return nullptr;
}
-
- // write closure file but only if we have boot-token
- if ( canSaveClosureToDisk ) {
- if ( const dyld3::closure::LaunchClosure* existingClosure = mapClosureFile(closurePath) ) {
- if ( (existingClosure->size() == result->size()) && (memcmp(existingClosure, result, result->size()) == 0) ) {
- // closure file already exists and has same content, so re-use file by altering boot-token
- ::chmod(closurePath, S_IRUSR|S_IWUSR); // file has to be writable to alter attributes
- // handle both attribute size change and missing attribute
- if ( ::setxattr(closurePath, DYLD_CLOSURE_XATTR_NAME, bootToken.begin(), bootToken.count(), 0, XATTR_REPLACE) != 0 )
- ::setxattr(closurePath, DYLD_CLOSURE_XATTR_NAME, bootToken.begin(), bootToken.count(), 0, 0);
- ::chmod(closurePath, S_IRUSR);
- result->deallocate();
- if ( gLinkContext.verboseWarnings )
- dyld::log("dyld: reusing previous boot %s closure %p (size=%lu) for %s\n", existingClosure->topImage()->variantString(), existingClosure, existingClosure->size(), sExecPath);
- return existingClosure;
- }
- }
- // make new file
+ // try to atomically save closure to disk to speed up next launch
+ if ( dyld3::closure::LaunchClosure::buildClosureCachePath(mainFileInfo.path, closurePath, getTempDir(envp), true) ) {
char closurePathTemp[PATH_MAX];
strlcpy(closurePathTemp, closurePath, PATH_MAX);
int mypid = getpid();
@@ -6354,22 +6111,20 @@
putHexByte(mypid, s);
*s = '\0';
strlcat(closurePathTemp, pidBuf, PATH_MAX);
-#if TARGET_OS_OSX
- int fd = dyld3::open(closurePathTemp, O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR);
+#if __MAC_OS_X_VERSION_MIN_REQUIRED
+ int fd = ::open(closurePathTemp, O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR);
#else
int fd = ::open_dprotected_np(closurePathTemp, O_WRONLY|O_CREAT, PROTECTION_CLASS_D, 0, S_IRUSR|S_IWUSR);
#endif
if ( fd != -1 ) {
::ftruncate(fd, result->size());
::write(fd, result, result->size());
- ::fsetxattr(fd, DYLD_CLOSURE_XATTR_NAME, bootToken.begin(), bootToken.count(), 0, 0);
::fchmod(fd, S_IRUSR);
::close(fd);
::rename(closurePathTemp, closurePath);
// free built closure and mmap file() to reduce dirty memory
result->deallocate();
result = mapClosureFile(closurePath);
- sLaunchModeUsed |= DYLD_LAUNCH_MODE_CLOSURE_SAVED_TO_FILE;
}
else if ( gLinkContext.verboseWarnings ) {
dyld::log("could not save closure (errno=%d) to: %s\n", errno, closurePathTemp);
@@ -6377,35 +6132,19 @@
}
if ( gLinkContext.verboseWarnings )
- dyld::log("dyld: just built %s closure %p (size=%lu) for %s\n", result->topImage()->variantString(), result, result->size(), sExecPath);
+ dyld::log("dyld: just built closure %p (size=%lu) for %s\n", result, result->size(), sExecPath);
return result;
}
static const dyld3::closure::LaunchClosure* findCachedLaunchClosure(const uint8_t* mainExecutableCDHash,
const dyld3::closure::LoadedFileInfo& mainFileInfo,
- const char* envp[],
- const dyld3::Array<uint8_t>& bootToken)
-{
- // get path to where closure file will be store for this program
+ const char* envp[])
+{
char closurePath[PATH_MAX];
- if ( !dyld3::closure::LaunchClosure::buildClosureCachePath(mainFileInfo.path, envp, false, closurePath) ) {
- // if cannot construct path to use/store closure file, then use minimal closures
- if ( sClosureKind == ClosureKind::unset )
- sClosureKind = ClosureKind::minimal;
+ // build base path of $TMPDIR/dyld/<prog-name>-
+ if ( !dyld3::closure::LaunchClosure::buildClosureCachePath(mainFileInfo.path, closurePath, getTempDir(envp), false) )
return nullptr;
- }
-
- // if file exists, but extended attribute is wrong, ignore file (might be re-used later)
- if ( bootToken.empty() )
- return nullptr;
- uint8_t filesBootToken[bootToken.count()];
- ssize_t attrSize = ::getxattr(closurePath, DYLD_CLOSURE_XATTR_NAME, filesBootToken, bootToken.count(), 0, 0);
- if ( attrSize != bootToken.count() )
- return nullptr;
- if ( memcmp(bootToken.begin(), filesBootToken, bootToken.count()) != 0 )
- return nullptr;
-
const dyld3::closure::LaunchClosure* closure = mapClosureFile(closurePath);
if ( closure == nullptr )
return nullptr;
@@ -6416,7 +6155,7 @@
}
if ( gLinkContext.verboseWarnings )
- dyld::log("dyld: used cached %s closure %p (size=%lu) for %s\n", closure->topImage()->variantString(), closure, closure->size(), sExecPath);
+ dyld::log("dyld: used cached closure %p (size=%lu) for %s\n", closure, closure->size(), sExecPath);
return closure;
}
@@ -6425,7 +6164,7 @@
static ClosureMode getPlatformDefaultClosureMode() {
-#if TARGET_OS_OSX
+#if __MAC_OS_X_VERSION_MIN_REQUIRED
#if __i386__
// rdar://problem/32701418: Don't use dyld3 for i386 for now.
return ClosureMode::Off;
@@ -6440,7 +6179,7 @@
return ClosureMode::On;
else
return ClosureMode::Off;
-#endif // TARGET_OS_OSX
+#endif // __MAC_OS_X_VERSION_MIN_REQUIRED
}
//
@@ -6461,29 +6200,11 @@
//Check and see if there are any kernel flags
dyld3::BootArgs::setFlags(hexToUInt64(_simple_getenv(apple, "dyld_flags"), nullptr));
-#if __has_feature(ptrauth_calls)
- // Check and see if kernel disabled JOP pointer signing (which lets us load plain arm64 binaries)
- if ( const char* disableStr = _simple_getenv(apple, "ptrauth_disabled") ) {
- if ( strcmp(disableStr, "1") == 0 )
- sKeysDisabled = true;
- }
- else {
- // needed until kernel passes ptrauth_disabled for arm64 main executables
- if ( (mainExecutableMH->cpusubtype == CPU_SUBTYPE_ARM64_V8) || (mainExecutableMH->cpusubtype == CPU_SUBTYPE_ARM64_ALL) )
- sKeysDisabled = true;
- }
-#endif
-
// Grab the cdHash of the main executable from the environment
uint8_t mainExecutableCDHashBuffer[20];
const uint8_t* mainExecutableCDHash = nullptr;
- if ( const char* mainExeCdHashStr = _simple_getenv(apple, "executable_cdhash") ) {
- unsigned bufferLenUsed;
- if ( hexStringToBytes(mainExeCdHashStr, mainExecutableCDHashBuffer, sizeof(mainExecutableCDHashBuffer), bufferLenUsed) )
- mainExecutableCDHash = mainExecutableCDHashBuffer;
- }
-
- getHostInfo(mainExecutableMH, mainExecutableSlide);
+ if ( hexToBytes(_simple_getenv(apple, "executable_cdhash"), 40, mainExecutableCDHashBuffer) )
+ mainExecutableCDHash = mainExecutableCDHashBuffer;
#if !TARGET_OS_SIMULATOR
// Trace dyld's load
@@ -6499,8 +6220,7 @@
// Set the platform ID in the all image infos so debuggers can tell the process type
// FIXME: This can all be removed once we make the kernel handle it in rdar://43369446
- // The host may not have the platform field in its struct, but there's space for it in the padding, so always set it
- {
+ if (gProcessInfo->version >= 16) {
__block bool platformFound = false;
((dyld3::MachOFile*)mainExecutableMH)->forEachSupportedPlatform(^(dyld3::Platform platform, uint32_t minOS, uint32_t sdk) {
if (platformFound) {
@@ -6512,7 +6232,7 @@
if (gProcessInfo->platform == (uint32_t)dyld3::Platform::unknown) {
// There were no platforms found in the binary. This may occur on macOS for alternate toolchains and old binaries.
// It should never occur on any of our embedded platforms.
-#if TARGET_OS_OSX
+#if __MAC_OS_X_VERSION_MIN_REQUIRED
gProcessInfo->platform = (uint32_t)dyld3::Platform::macOS;
#else
halt("MH_EXECUTE binaries must specify a minimum supported OS version");
@@ -6520,21 +6240,16 @@
}
}
-#if TARGET_OS_OSX
+#if __MAC_OS_X_VERSION_MIN_REQUIRED
// Check to see if we need to override the platform
const char* forcedPlatform = _simple_getenv(envp, "DYLD_FORCE_PLATFORM");
if (forcedPlatform) {
- dyld_platform_t forcedPlatformType = 0;
- if (strncmp(forcedPlatform, "6", 1) == 0) {
- forcedPlatformType = PLATFORM_MACCATALYST;
- } else if (strncmp(forcedPlatform, "2", 1) == 0) {
- forcedPlatformType = PLATFORM_IOS;
- } else {
- halt("DYLD_FORCE_PLATFORM is only supported for platform 2 or 6.");
+ if (strncmp(forcedPlatform, "6", 1) != 0) {
+ halt("DYLD_FORCE_PLATFORM is only supported for platform 6");
}
const dyld3::MachOFile* mf = (dyld3::MachOFile*)sMainExecutableMachHeader;
if (mf->allowsAlternatePlatform()) {
- gProcessInfo->platform = forcedPlatformType;
+ gProcessInfo->platform = PLATFORM_IOSMAC;
}
}
@@ -6545,7 +6260,7 @@
char simDyldPath[PATH_MAX];
strlcpy(simDyldPath, rootPath, PATH_MAX);
strlcat(simDyldPath, "/usr/lib/dyld_sim", PATH_MAX);
- int fd = dyld3::open(simDyldPath, O_RDONLY, 0);
+ int fd = my_open(simDyldPath, O_RDONLY, 0);
if ( fd != -1 ) {
const char* errMessage = useSimulatorDyld(fd, mainExecutableMH, simDyldPath, argc, argv, envp, apple, startGlue, &result);
if ( errMessage != NULL )
@@ -6571,7 +6286,7 @@
// <rdar://problem/13868260> Remove interim apple[0] transition code from dyld
if (!sExecPath) sExecPath = apple[0];
-#if TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR
+#if __IPHONE_OS_VERSION_MIN_REQUIRED && !TARGET_OS_SIMULATOR
// <rdar://54095622> kernel is not passing a real path for main executable
if ( strncmp(sExecPath, "/var/containers/Bundle/Application/", 35) == 0 ) {
if ( char* newPath = (char*)malloc(strlen(sExecPath)+10) ) {
@@ -6602,17 +6317,6 @@
else
sExecShortName = sExecPath;
-#if TARGET_OS_OSX && __has_feature(ptrauth_calls)
- // on Apple Silicon macOS, only Apple signed ("platform binary") arm64e can be loaded
- sOnlyPlatformArm64e = true;
-
- // internal builds, or if boot-arg is set, then non-platform-binary arm64e slices can be run
- if ( const char* abiMode = _simple_getenv(apple, "arm64e_abi") ) {
- if ( strcmp(abiMode, "all") == 0 )
- sOnlyPlatformArm64e = false;
- }
-#endif
-
configureProcessRestrictions(mainExecutableMH, envp);
// Check if we should force dyld3. Note we have to do this outside of the regular env parsing due to AMFI
@@ -6621,13 +6325,20 @@
if ( strcmp(useClosures, "0") == 0 ) {
sClosureMode = ClosureMode::Off;
} else if ( strcmp(useClosures, "1") == 0 ) {
- #if !__i386__ // don't support dyld3 for 32-bit macOS
+#if __MAC_OS_X_VERSION_MIN_REQUIRED
+
+#if __i386__
+ // don't support dyld3 for 32-bit macOS
+#else
+ // Also don't support dyld3 for iOSMac right now
+ if ( gProcessInfo->platform != PLATFORM_IOSMAC ) {
+ sClosureMode = ClosureMode::On;
+ }
+#endif // __i386__
+
+#else
sClosureMode = ClosureMode::On;
- sClosureKind = ClosureKind::full;
- #endif
- } else if ( strcmp(useClosures, "2") == 0 ) {
- sClosureMode = ClosureMode::On;
- sClosureKind = ClosureKind::minimal;
+#endif // __MAC_OS_X_VERSION_MIN_REQUIRED
} else {
dyld::warn("unknown option to DYLD_USE_CLOSURES. Valid options are: 0 and 1\n");
}
@@ -6635,36 +6346,7 @@
}
}
- // Check if we should force the shared cache __DATA_CONST to read-only or read-write
- if ( dyld3::BootArgs::forceReadWriteDataConst() ) {
- gEnableSharedCacheDataConst = false;
- } else if ( dyld3::BootArgs::forceReadOnlyDataConst() ) {
- gEnableSharedCacheDataConst = true;
- } else {
- // __DATA_CONST is enabled by default for arm64(e) for now
-#if __arm64__ && __LP64__
- gEnableSharedCacheDataConst = true;
-#else
- gEnableSharedCacheDataConst = false;
-#endif
- }
- bool sharedCacheDataConstIsEnabled = gEnableSharedCacheDataConst;
-
- if ( dyld3::internalInstall() ) {
- if (const char* dataConst = _simple_getenv(envp, "DYLD_SHARED_REGION_DATA_CONST")) {
- if ( strcmp(dataConst, "RW") == 0 ) {
- gEnableSharedCacheDataConst = false;
- } else if ( strcmp(dataConst, "RO") == 0 ) {
- gEnableSharedCacheDataConst = true;
- } else {
- dyld::warn("unknown option to DYLD_SHARED_REGION_DATA_CONST. Valid options are: RW and RO\n");
- }
-
- }
- }
-
-
-#if TARGET_OS_OSX
+#if __MAC_OS_X_VERSION_MIN_REQUIRED
if ( !gLinkContext.allowEnvVarsPrint && !gLinkContext.allowEnvVarsPath && !gLinkContext.allowEnvVarsSharedCache ) {
pruneEnvironmentVariables(envp, &apple);
// set again because envp and apple may have changed or moved
@@ -6676,25 +6358,18 @@
checkEnvironmentVariables(envp);
defaultUninitializedFallbackPaths(envp);
}
-#if TARGET_OS_OSX
- switch (gProcessInfo->platform) {
-#if (TARGET_OS_OSX && TARGET_CPU_ARM64)
- case PLATFORM_IOS:
- sClosureMode = ClosureMode::On; // <rdar://problem/56792308> Run iOS apps on macOS in dyld3 mode
- [[clang::fallthrough]];
-#endif
- case PLATFORM_MACCATALYST:
- gLinkContext.rootPaths = parseColonList("/System/iOSSupport", NULL);
- gLinkContext.iOSonMac = true;
- if ( sEnv.DYLD_FALLBACK_LIBRARY_PATH == sLibraryFallbackPaths )
- sEnv.DYLD_FALLBACK_LIBRARY_PATH = sRestrictedLibraryFallbackPaths;
- if ( sEnv.DYLD_FALLBACK_FRAMEWORK_PATH == sFrameworkFallbackPaths )
- sEnv.DYLD_FALLBACK_FRAMEWORK_PATH = sRestrictedFrameworkFallbackPaths;
- break;
- case PLATFORM_DRIVERKIT:
- gLinkContext.driverKit = true;
- gLinkContext.sharedRegionMode = ImageLoader::kDontUseSharedRegion;
- break;
+#if __MAC_OS_X_VERSION_MIN_REQUIRED
+ if ( gProcessInfo->platform == PLATFORM_IOSMAC ) {
+ gLinkContext.rootPaths = parseColonList("/System/iOSSupport", NULL);
+ gLinkContext.iOSonMac = true;
+ if ( sEnv.DYLD_FALLBACK_LIBRARY_PATH == sLibraryFallbackPaths )
+ sEnv.DYLD_FALLBACK_LIBRARY_PATH = sRestrictedLibraryFallbackPaths;
+ if ( sEnv.DYLD_FALLBACK_FRAMEWORK_PATH == sFrameworkFallbackPaths )
+ sEnv.DYLD_FALLBACK_FRAMEWORK_PATH = sRestrictedFrameworkFallbackPaths;
+ }
+ else if ( ((dyld3::MachOFile*)mainExecutableMH)->supportsPlatform(dyld3::Platform::driverKit) ) {
+ gLinkContext.driverKit = true;
+ gLinkContext.sharedRegionMode = ImageLoader::kDontUseSharedRegion;
}
#endif
if ( sEnv.DYLD_PRINT_OPTS )
@@ -6707,11 +6382,18 @@
#if !TARGET_OS_SIMULATOR
if ( _simple_getenv(envp, "DYLD_JUST_BUILD_CLOSURE") != nullptr ) {
#if TARGET_OS_IPHONE
- char tempClosurePath[PATH_MAX];
- if ( dyld3::closure::LaunchClosure::buildClosureCachePath(sExecPath, envp, false, tempClosurePath) )
- sJustBuildClosure = true;
-#endif
- // If the env vars for the data contain look wrong, don't want to launch the app as that would bring up the UI
+ const char* tempDir = getTempDir(envp);
+ if ( (tempDir != nullptr) && (geteuid() != 0) ) {
+ // Use realpath to prevent something like TMPRIR=/tmp/../usr/bin
+ char realPath[PATH_MAX];
+ if ( realpath(tempDir, realPath) != NULL )
+ tempDir = realPath;
+ if (strncmp(tempDir, "/private/var/mobile/Containers/", strlen("/private/var/mobile/Containers/")) == 0) {
+ sJustBuildClosure = true;
+ }
+ }
+#endif
+ // If we didn't like the format of TMPDIR, just exit. We don't want to launch the app as that would bring up the UI
if (!sJustBuildClosure) {
_exit(EXIT_SUCCESS);
}
@@ -6720,105 +6402,18 @@
if ( sJustBuildClosure )
sClosureMode = ClosureMode::On;
+ getHostInfo(mainExecutableMH, mainExecutableSlide);
// load shared cache
checkSharedRegionDisable((dyld3::MachOLoaded*)mainExecutableMH, mainExecutableSlide);
if ( gLinkContext.sharedRegionMode != ImageLoader::kDontUseSharedRegion ) {
#if TARGET_OS_SIMULATOR
if ( sSharedCacheOverrideDir)
- mapSharedCache(mainExecutableSlide);
+ mapSharedCache();
#else
- mapSharedCache(mainExecutableSlide);
-#endif
-
- // If this process wants a different __DATA_CONST state from the shared region, then override that now
- if ( (sSharedCacheLoadInfo.loadAddress != nullptr) && (gEnableSharedCacheDataConst != sharedCacheDataConstIsEnabled) ) {
- uint32_t permissions = gEnableSharedCacheDataConst ? VM_PROT_READ : (VM_PROT_READ | VM_PROT_WRITE);
- sSharedCacheLoadInfo.loadAddress->changeDataConstPermissions(mach_task_self(), permissions,
- (gLinkContext.verboseMapping ? &dyld::log : nullptr));
- }
- }
-
-#if !TARGET_OS_SIMULATOR
- if ( getpid() == 1 ) {
- // Get the value as set by the boot-args
- uint64_t commPageValue = 0;
- size_t commPageValueSize = sizeof(commPageValue);
- if ( sysctlbyname("kern.dyld_flags", &commPageValue, &commPageValueSize, nullptr, 0) != 0 ) {
- // Try again with the old name
- // TODO: Remove this when we are always on new enough kernels
- sysctlbyname("kern.dyld_system_flags", &commPageValue, &commPageValueSize, nullptr, 0);
- }
-
- commPageValue &= CommPageBootArgMask;
- // logToConsole("dyld: got comm page flags 0x%llx\n", commPageValue);
-
- // If we are PID 1 (launchd) and on macOS, then we should check if the simulator support dylibs
- // are roots or not.
- // If they are not roots at launchd time, and the file system is read-only, then we know for sure
- // they will not be roots later
-#if DYLD_SIMULATOR_ROOTS_SUPPORT
- bool fileSystemIsWritable = true;
-
- // logToConsole("dyld: in launchd\n");
- struct statfs statBuffer;
- int statResult = statfs("/", &statBuffer);
- if ( statResult == 0 ) {
- if ( !strcmp(statBuffer.f_fstypename, "apfs") ) {
- if ( (statBuffer.f_flags & (MNT_RDONLY | MNT_SNAPSHOT)) == (MNT_RDONLY | MNT_SNAPSHOT) ) {
- // logToConsole("dyld: got statfs flags 0x%llx\n", statBuffer.f_flags);
- fileSystemIsWritable = false;
- }
- }
- } else {
- int error = errno;
- logToConsole("dyld: could not stat '/', errno = %d\n", error);
- }
-
- // If the file system is read-only, then we can check now whether any of the simulator support
- // dylibs are roots
- bool libsystemKernelIsRoot = false;
- bool libsystemPlatformIsRoot = false;
- bool libsystemPThreadIsRoot = false;
- if ( !fileSystemIsWritable && (sSharedCacheLoadInfo.loadAddress != nullptr)) {
- dyld3::closure::FileSystemPhysical fileSystem;
- libsystemKernelIsRoot = !dyld3::RootsChecker::uuidMatchesSharedCache("/usr/lib/system/libsystem_kernel.dylib",
- &fileSystem, sSharedCacheLoadInfo.loadAddress);
- libsystemPlatformIsRoot = !dyld3::RootsChecker::uuidMatchesSharedCache("/usr/lib/system/libsystem_platform.dylib",
- &fileSystem, sSharedCacheLoadInfo.loadAddress);
- libsystemPThreadIsRoot = !dyld3::RootsChecker::uuidMatchesSharedCache("/usr/lib/system/libsystem_pthread.dylib",
- &fileSystem, sSharedCacheLoadInfo.loadAddress);
- }
- commPageValue |= (fileSystemIsWritable ? CommPageFlags::fileSystemCanBeModified : CommPageFlags::None);
- commPageValue |= (libsystemKernelIsRoot ? CommPageFlags::libsystemKernelIsRoot : CommPageFlags::None);
- commPageValue |= (libsystemPlatformIsRoot ? CommPageFlags::libsystemPlatformIsRoot : CommPageFlags::None);
- commPageValue |= (libsystemPThreadIsRoot ? CommPageFlags::libsystemPThreadIsRoot : CommPageFlags::None);
-#endif // DYLD_SIMULATOR_ROOTS_SUPPORT
-
- logToConsole("dyld: setting comm page to 0x%llx\n", commPageValue);
- if ( sysctlbyname("kern.dyld_flags", nullptr, 0, &commPageValue, sizeof(commPageValue)) != 0 ) {
- // Try again with the old name
- // TODO: Remove this when we are always on new enough kernels
- sysctlbyname("kern.dyld_system_flags", nullptr, 0, &commPageValue, sizeof(commPageValue));
- }
- }
-
-#if DYLD_SIMULATOR_ROOTS_SUPPORT
- // Set the roots checker to the state from the comm page
- {
- uint64_t dyldFlags = *((uint64_t*)_COMM_PAGE_DYLD_SYSTEM_FLAGS);
- bool fileSystemCanBeModified = dyldFlags & CommPageFlags::fileSystemCanBeModified;
- bool libsystemKernelIsRoot = dyldFlags & CommPageFlags::libsystemKernelIsRoot;
- bool libsystemPlatformIsRoot = dyldFlags & CommPageFlags::libsystemPlatformIsRoot;
- bool libsystemPThreadIsRoot = dyldFlags & CommPageFlags::libsystemPThreadIsRoot;
- sRootsChecker.setFileSystemCanBeModified(fileSystemCanBeModified);
- sRootsChecker.setLibsystemKernelIsRoot(libsystemKernelIsRoot);
- sRootsChecker.setLibsystemPlatformIsRoot(libsystemPlatformIsRoot);
- sRootsChecker.setLibsystemPThreadIsRoot(libsystemPThreadIsRoot);
- }
-#endif // DYLD_SIMULATOR_ROOTS_SUPPORT
-
-#endif // !TARGET_OS_SIMULATOR
+ mapSharedCache();
+#endif
+ }
// If we haven't got a closure mode yet, then check the environment and cache type
if ( sClosureMode == ClosureMode::Unset ) {
@@ -6839,9 +6434,8 @@
#if !TARGET_OS_SIMULATOR
if ( sClosureMode == ClosureMode::Off ) {
if ( gLinkContext.verboseWarnings )
- dyld::log("dyld: not using closures\n");
+ dyld::log("dyld: not using closure because of DYLD_USE_CLOSURES or -force_dyld2=1 override\n");
} else {
- sLaunchModeUsed = DYLD_LAUNCH_MODE_USING_CLOSURE;
const dyld3::closure::LaunchClosure* mainClosure = nullptr;
dyld3::closure::LoadedFileInfo mainFileInfo;
mainFileInfo.fileContent = mainExecutableMH;
@@ -6850,7 +6444,7 @@
mainFileInfo.sliceOffset = 0;
mainFileInfo.sliceLen = -1;
struct stat mainExeStatBuf;
- if ( dyld3::stat(sExecPath, &mainExeStatBuf) == 0 ) {
+ if ( ::stat(sExecPath, &mainExeStatBuf) == 0 ) {
mainFileInfo.inode = mainExeStatBuf.st_ino;
mainFileInfo.mtime = mainExeStatBuf.st_mtime;
}
@@ -6859,8 +6453,6 @@
mainClosure = sSharedCacheLoadInfo.loadAddress->findClosure(sExecPath);
if ( gLinkContext.verboseWarnings && (mainClosure != nullptr) )
dyld::log("dyld: found closure %p (size=%lu) in dyld shared cache\n", mainClosure, mainClosure->size());
- if ( mainClosure != nullptr )
- sLaunchModeUsed |= DYLD_LAUNCH_MODE_CLOSURE_FROM_OS;
}
// We only want to try build a closure at runtime if its an iOS third party binary, or a macOS binary from the shared cache
@@ -6871,32 +6463,17 @@
allowClosureRebuilds = true;
}
- if ( (mainClosure != nullptr) && !closureValid(mainClosure, mainFileInfo, mainExecutableCDHash, true, envp) ) {
+ if ( (mainClosure != nullptr) && !closureValid(mainClosure, mainFileInfo, mainExecutableCDHash, true, envp) )
mainClosure = nullptr;
- sLaunchModeUsed &= ~DYLD_LAUNCH_MODE_CLOSURE_FROM_OS;
- }
-
- // <rdar://60333505> bootToken is a concat of boot-hash kernel passes down for app and dyld's uuid
- uint8_t bootTokenBufer[128];
- unsigned bootTokenBufferLen = 0;
- if ( const char* bootHashStr = _simple_getenv(apple, "executable_boothash") ) {
- if ( hexStringToBytes(bootHashStr, bootTokenBufer, sizeof(bootTokenBufer), bootTokenBufferLen) ) {
- if ( ((dyld3::MachOFile*)&__dso_handle)->getUuid(&bootTokenBufer[bootTokenBufferLen]) )
- bootTokenBufferLen += sizeof(uuid_t);
- }
- }
- dyld3::Array<uint8_t> bootToken(bootTokenBufer, bootTokenBufferLen, bootTokenBufferLen);
// If we didn't find a valid cache closure then try build a new one
if ( (mainClosure == nullptr) && allowClosureRebuilds ) {
// if forcing closures, and no closure in cache, or it is invalid, check for cached closure
if ( !sForceInvalidSharedCacheClosureFormat )
- mainClosure = findCachedLaunchClosure(mainExecutableCDHash, mainFileInfo, envp, bootToken);
+ mainClosure = findCachedLaunchClosure(mainExecutableCDHash, mainFileInfo, envp);
if ( mainClosure == nullptr ) {
// if no cached closure found, build new one
- mainClosure = buildLaunchClosure(mainExecutableCDHash, mainFileInfo, envp, bootToken);
- if ( mainClosure != nullptr )
- sLaunchModeUsed |= DYLD_LAUNCH_MODE_BUILT_CLOSURE_AT_LAUNCH;
+ mainClosure = buildLaunchClosure(mainExecutableCDHash, mainFileInfo, envp);
}
}
@@ -6907,29 +6484,22 @@
// try using launch closure
if ( mainClosure != nullptr ) {
CRSetCrashLogMessage("dyld3: launch started");
- if ( mainClosure->topImage()->fixupsNotEncoded() )
- sLaunchModeUsed |= DYLD_LAUNCH_MODE_MINIMAL_CLOSURE;
- Diagnostics diag;
- bool closureOutOfDate;
- bool recoverable;
bool launched = launchWithClosure(mainClosure, sSharedCacheLoadInfo.loadAddress, (dyld3::MachOLoaded*)mainExecutableMH,
- mainExecutableSlide, argc, argv, envp, apple, diag, &result, startGlue, &closureOutOfDate, &recoverable);
- if ( !launched && closureOutOfDate && allowClosureRebuilds ) {
+ mainExecutableSlide, argc, argv, envp, apple, &result, startGlue);
+ if ( !launched && allowClosureRebuilds ) {
// closure is out of date, build new one
- mainClosure = buildLaunchClosure(mainExecutableCDHash, mainFileInfo, envp, bootToken);
+ mainClosure = buildLaunchClosure(mainExecutableCDHash, mainFileInfo, envp);
if ( mainClosure != nullptr ) {
- diag.clearError();
- sLaunchModeUsed |= DYLD_LAUNCH_MODE_BUILT_CLOSURE_AT_LAUNCH;
- if ( mainClosure->topImage()->fixupsNotEncoded() )
- sLaunchModeUsed |= DYLD_LAUNCH_MODE_MINIMAL_CLOSURE;
- else
- sLaunchModeUsed &= ~DYLD_LAUNCH_MODE_MINIMAL_CLOSURE;
launched = launchWithClosure(mainClosure, sSharedCacheLoadInfo.loadAddress, (dyld3::MachOLoaded*)mainExecutableMH,
- mainExecutableSlide, argc, argv, envp, apple, diag, &result, startGlue, &closureOutOfDate, &recoverable);
+ mainExecutableSlide, argc, argv, envp, apple, &result, startGlue);
}
}
if ( launched ) {
gLinkContext.startedInitializingMainExecutable = true;
+#if __has_feature(ptrauth_calls)
+ // start() calls the result pointer as a function pointer so we need to sign it.
+ result = (uintptr_t)__builtin_ptrauth_sign_unauthenticated((void*)result, 0, 0);
+#endif
if (sSkipMain)
result = (uintptr_t)&fake_main;
return result;
@@ -6938,14 +6508,12 @@
if ( gLinkContext.verboseWarnings ) {
dyld::log("dyld: unable to use closure %p\n", mainClosure);
}
- if ( !recoverable )
- halt(diag.errorMessage());
}
}
}
#endif // TARGET_OS_SIMULATOR
// could not use closure info, launch old way
- sLaunchModeUsed = 0;
+
// install gdb notifier
@@ -6974,13 +6542,13 @@
#if SUPPORT_ACCELERATE_TABLES
#if __arm64e__
// Disable accelerator tables when we have threaded rebase/bind, which is arm64e executables only for now.
- if ((sMainExecutableMachHeader->cpusubtype & ~CPU_SUBTYPE_MASK) == CPU_SUBTYPE_ARM64E)
+ if (sMainExecutableMachHeader->cpusubtype == CPU_SUBTYPE_ARM64E)
sDisableAcceleratorTables = true;
#endif
bool mainExcutableAlreadyRebased = false;
if ( (sSharedCacheLoadInfo.loadAddress != nullptr) && !dylibsCanOverrideCache() && !sDisableAcceleratorTables && (sSharedCacheLoadInfo.loadAddress->header.accelerateInfoAddr != 0) ) {
struct stat statBuf;
- if ( dyld3::stat(IPHONE_DYLD_SHARED_CACHE_DIR "no-dyld2-accelerator-tables", &statBuf) != 0 )
+ if ( ::stat(IPHONE_DYLD_SHARED_CACHE_DIR "no-dyld2-accelerator-tables", &statBuf) != 0 )
sAllCacheImagesProxy = ImageLoaderMegaDylib::makeImageLoaderMegaDylib(&sSharedCacheLoadInfo.loadAddress->header, sSharedCacheLoadInfo.slide, mainExecutableMH, gLinkContext);
}
@@ -6988,7 +6556,7 @@
#endif
-#if TARGET_OS_OSX
+ #if __MAC_OS_X_VERSION_MIN_REQUIRED
gLinkContext.strictMachORequired = false;
// <rdar://problem/22805519> be less strict about old macOS mach-o binaries
((dyld3::MachOFile*)mainExecutableMH)->forEachSupportedPlatform(^(dyld3::Platform platform, uint32_t minOS, uint32_t sdk) {
@@ -7046,54 +6614,6 @@
sAllImages.reserve(INITIAL_IMAGE_COUNT);
#endif
-#if defined(__x86_64__) && !TARGET_OS_SIMULATOR
- if (dyld::isTranslated()) {
- struct dyld_all_runtime_info {
- uint32_t image_count;
- dyld_image_info* images;
- uint32_t uuid_count;
- dyld_uuid_info* uuids;
- uint32_t aot_image_count;
- dyld_aot_image_info* aots;
- dyld_aot_shared_cache_info aot_cache_info;
- };
-
- dyld_all_runtime_info* runtime_info;
- int ret = syscall(0x7000004, &runtime_info);
- if (ret == 0) {
- for (int i = 0; i < runtime_info->uuid_count; i++) {
- dyld_image_info image_info = runtime_info->images[i];
- dyld_uuid_info uuid_info = runtime_info->uuids[i];
-
- // add the arm64 cambria runtime to uuid info
- addNonSharedCacheImageUUID(uuid_info);
-
- struct stat sb;
- if (stat(image_info.imageFilePath, &sb) == 0) {
- fsid_t fsid = {{0, 0}};
- fsobj_id_t fsobj = {0};
- ino_t inode = sb.st_ino;
- fsobj.fid_objno = (uint32_t)inode;
- fsobj.fid_generation = (uint32_t)(inode>>32);
- fsid.val[0] = sb.st_dev;
-
- dyld3::kdebug_trace_dyld_image(DBG_DYLD_UUID_MAP_A, image_info.imageFilePath, &(uuid_info.imageUUID), fsobj, fsid, image_info.imageLoadAddress);
- }
- }
-
- // add aot images to dyld_all_image_info
- addAotImagesToAllAotImages(runtime_info->aot_image_count, runtime_info->aots);
-
- // add the arm64 cambria runtime to dyld_all_image_info
- addImagesToAllImages(runtime_info->image_count, runtime_info->images);
-
- // set the aot shared cache info in dyld_all_image_info
- dyld::gProcessInfo->aotSharedCacheBaseAddress = runtime_info->aot_cache_info.cacheBaseAddress;
- memcpy(dyld::gProcessInfo->aotSharedCacheUUID, runtime_info->aot_cache_info.cacheUUID, sizeof(uuid_t));
- }
- }
-#endif
-
// Now that shared cache is loaded, setup an versioned dylib overrides
#if SUPPORT_VERSIONED_PATHS
checkVersionedPaths();
@@ -7221,7 +6741,7 @@
if ( sInsertedDylibCount > 0 ) {
for(unsigned int i=0; i < sInsertedDylibCount; ++i) {
ImageLoader* image = sAllImages[i+1];
- image->recursiveBind(gLinkContext, sEnv.DYLD_BIND_AT_LAUNCH, true, nullptr);
+ image->recursiveBind(gLinkContext, sEnv.DYLD_BIND_AT_LAUNCH, true);
}
}
@@ -7248,9 +6768,9 @@
}
ARIADNEDBG_CODE(220, 1);
-#if TARGET_OS_OSX
+#if __MAC_OS_X_VERSION_MIN_REQUIRED
if ( gLinkContext.driverKit ) {
- result = (uintptr_t)sEntryOverride;
+ result = (uintptr_t)sEntryOveride;
if ( result == 0 )
halt("no entry point registered");
*startGlue = (uintptr_t)gLibSystemHelpers->startGlueToCallExit;
@@ -7273,6 +6793,10 @@
*startGlue = 0;
}
}
+#if __has_feature(ptrauth_calls)
+ // start() calls the result pointer as a function pointer so we need to sign it.
+ result = (uintptr_t)__builtin_ptrauth_sign_unauthenticated((void*)result, 0, 0);
+#endif
}
catch(const char* message) {
syncAllImages();
@@ -7299,7 +6823,7 @@
result = (uintptr_t)&fake_main;
*startGlue = (uintptr_t)gLibSystemHelpers->startGlueToCallExit;
}
-
+
return result;
}