diff --git a/debian/darling-dkms.lintian-overrides b/debian/darling-dkms.lintian-overrides deleted file mode 100644 index d2f90a98e..000000000 --- a/debian/darling-dkms.lintian-overrides +++ /dev/null @@ -1,3 +0,0 @@ -package-contains-vcs-control-file usr/src/darling-mach-0.1/lkm/.gitignore -executable-not-elf-or-script usr/src/darling-mach-0.1/lkm* -extended-description-is-empty diff --git a/debian/source/lintian-overrides b/debian/source/lintian-overrides deleted file mode 100644 index cbf5567bb..000000000 --- a/debian/source/lintian-overrides +++ /dev/null @@ -1,6 +0,0 @@ -darling source: configure-generated-file-in-source * -darling source: autotools-pkg-config-macro-not-cross-compilation-safe * -darling source: source-contains-prebuilt-windows-binary * -darling source: maintainer-script-lacks-debhelper-token debian/* -darling source: debhelper-but-no-misc-depends darling-dkms -darling source: package-needs-versioned-debhelper-build-depends 10 diff --git a/src/dyld/src/dyld2.cpp.rej b/src/dyld/src/dyld2.cpp.rej deleted file mode 100644 index 8f5e244e8..000000000 --- a/src/dyld/src/dyld2.cpp.rej +++ /dev/null @@ -1,1642 +0,0 @@ ---- src/dyld.cpp -+++ src/dyld2.cpp -@@ -60,79 +62,78 @@ - #include - #include - #include -+#include -+#include -+ -+#if TARGET_OS_SIMULATOR -+ enum { -+ AMFI_DYLD_INPUT_PROC_IN_SIMULATOR = (1 << 0), -+ }; -+ enum amfi_dyld_policy_output_flag_set { -+ AMFI_DYLD_OUTPUT_ALLOW_AT_PATH = (1 << 0), -+ AMFI_DYLD_OUTPUT_ALLOW_PATH_VARS = (1 << 1), -+ AMFI_DYLD_OUTPUT_ALLOW_CUSTOM_SHARED_CACHE = (1 << 2), -+ AMFI_DYLD_OUTPUT_ALLOW_FALLBACK_PATHS = (1 << 3), -+ AMFI_DYLD_OUTPUT_ALLOW_PRINT_VARS = (1 << 4), -+ AMFI_DYLD_OUTPUT_ALLOW_FAILED_LIBRARY_INSERTION = (1 << 5), -+ }; -+ extern "C" int amfi_check_dyld_policy_self(uint64_t input_flags, uint64_t* output_flags); -+#else -+ #include -+#endif - #include - #include -- --#include -- --#ifndef CPU_SUBTYPE_ARM_V5TEJ -- #define CPU_SUBTYPE_ARM_V5TEJ ((cpu_subtype_t) 7) --#endif --#ifndef CPU_SUBTYPE_ARM_XSCALE -- #define CPU_SUBTYPE_ARM_XSCALE ((cpu_subtype_t) 8) --#endif --#ifndef CPU_SUBTYPE_ARM_V7 -- #define CPU_SUBTYPE_ARM_V7 ((cpu_subtype_t) 9) --#endif --#ifndef CPU_SUBTYPE_ARM_V7F -- #define CPU_SUBTYPE_ARM_V7F ((cpu_subtype_t) 10) --#endif --#ifndef CPU_SUBTYPE_ARM_V7S -- #define CPU_SUBTYPE_ARM_V7S ((cpu_subtype_t) 11) --#endif --#ifndef CPU_SUBTYPE_ARM_V7K -- #define CPU_SUBTYPE_ARM_V7K ((cpu_subtype_t) 12) --#endif --#ifndef LC_DYLD_ENVIRONMENT -- #define LC_DYLD_ENVIRONMENT 0x27 -+#if __has_feature(ptrauth_calls) -+ #include - #endif - --#ifndef CPU_SUBTYPE_X86_64_H -- #define CPU_SUBTYPE_X86_64_H ((cpu_subtype_t) 8) --#endif -- --#ifndef VM_PROT_SLIDE -- #define VM_PROT_SLIDE 0x20 --#endif -+extern "C" int __fork(); - --#include -+#include - #include -+#include - --#include "mach-o/dyld_gdb.h" - --#include "dyld.h" -+#include "dyld2.h" - #include "ImageLoader.h" - #include "ImageLoaderMachO.h" - #include "dyldLibSystemInterface.h" --#if DYLD_SHARED_CACHE_SUPPORT - #include "dyld_cache_format.h" --#endif - #include "dyld_process_info_internal.h" --#include --#if TARGET_IPHONE_SIMULATOR -- extern "C" void xcoresymbolication_load_notifier(void *connection, uint64_t load_timestamp, const char *image_path, const struct mach_header *mach_header); -- extern "C" void xcoresymbolication_unload_notifier(void *connection, uint64_t unload_timestamp, const char *image_path, const struct mach_header *mach_header); -- #define coresymbolication_load_notifier(c, t, p, h) xcoresymbolication_load_notifier(c, t, p, h) -- #define coresymbolication_unload_notifier(c, t, p, h) xcoresymbolication_unload_notifier(c, t, p, h) --#endif - - #if SUPPORT_ACCELERATE_TABLES - #include "ImageLoaderMegaDylib.h" - #endif - --#if TARGET_IPHONE_SIMULATOR -+#if TARGET_OS_SIMULATOR - extern "C" void* gSyscallHelpers; - #else - #include "dyldSyscallInterface.h" - #endif - -+#include "Closure.h" -+#include "libdyldEntryVector.h" -+#include "MachOLoaded.h" -+#include "Loading.h" -+#include "DyldSharedCache.h" -+#include "SharedCacheRuntime.h" -+#include "StringUtils.h" -+#include "Tracing.h" -+#include "ClosureBuilder.h" -+#include "ClosureFileSystemPhysical.h" -+#include "FileUtils.h" -+#include "BootArgs.h" -+ -+#ifndef MH_HAS_OBJC -+ #define MH_HAS_OBJC 0x40000000 -+#endif - - // not libc header for send() syscall interface - extern "C" ssize_t __sendto(int, const void *, size_t, int, const struct sockaddr *, socklen_t); - - - // ARM and x86_64 are the only architecture that use cpu-sub-types --#define CPU_SUBTYPES_SUPPORTED ((__arm__ || __x86_64__) && !TARGET_IPHONE_SIMULATOR) -+#define CPU_SUBTYPES_SUPPORTED ((__arm__ || __arm64__ || __x86_64__) && !TARGET_OS_SIMULATOR) - - #if __LP64__ - #define LC_SEGMENT_COMMAND LC_SEGMENT_64 -@@ -784,125 +818,124 @@ static void notifySingleFromCache(dyld_image_states state, const mach_header* mh - } - } - if ( (state == dyld_image_state_dependents_initialized) && (sNotifyObjCInit != NULL) && (mh->flags & MH_HAS_OBJC) ) { -+ dyld3::ScopedTimer timer(DBG_DYLD_TIMING_OBJC_INIT, (uint64_t)mh, 0, 0); - (*sNotifyObjCInit)(path, mh); - } - } - #endif - --static mach_port_t sNotifyReplyPorts[DYLD_MAX_PROCESS_INFO_NOTIFY_COUNT]; -- -- --static void notifyMonitoringDyld(bool unloading, unsigned portSlot, unsigned imageCount, const dyld_image_info infos[]) --{ -- unsigned entriesSize = imageCount*sizeof(dyld_process_info_image_entry); -- unsigned pathsSize = 0; -- for (unsigned j=0; j < imageCount; ++j) { -- pathsSize += (strlen(infos[j].imageFilePath) + 1); -+#if !TARGET_OS_SIMULATOR -+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; - } -- 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, portSlot, imageHalfCount, infos); -- notifyMonitoringDyld(unloading, portSlot, imageCount - imageHalfCount, &infos[imageHalfCount]); -+ 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; - } -- uint8_t buffer[totalSize]; -- 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 = mach_absolute_time(); -- 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, infos[j].imageFilePath); -- uint32_t len = (uint32_t)strlen(pathPool); -- bzero(entries->uuid, 16); -- const ImageLoader* image = findImageByMachHeader(infos[j].imageLoadAddress); -- if ( image != NULL ) { -- image->getUUID(entries->uuid); -- } --#if SUPPORT_ACCELERATE_TABLES -- else if ( sAllCacheImagesProxy != NULL ) { -- const mach_header* mh; -- const char* path; -- unsigned index; -- if ( sAllCacheImagesProxy->addressInCache(infos[j].imageLoadAddress, &mh, &path, &index) ) { -- sAllCacheImagesProxy->getDylibUUID(index, entries->uuid); -- } -+ // 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); -+ 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; - } --#endif -- entries->loadAddress = (uint64_t)infos[j].imageLoadAddress; -- entries->pathStringOffset = (uint32_t)(pathPool - pathPoolStart); -- entries->pathLength = len; -- pathPool += (len +1); -- ++entries; -- } -- -- if ( sNotifyReplyPorts[portSlot] == 0 ) { -- if ( !mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &sNotifyReplyPorts[portSlot]) ) -- mach_port_insert_right(mach_task_self(), sNotifyReplyPorts[portSlot], sNotifyReplyPorts[portSlot], MACH_MSG_TYPE_MAKE_SEND); -- //dyld::log("allocated reply port %d\n", sNotifyReplyPorts[portSlot]); -- } -- //dyld::log("found port to send to\n"); -- mach_msg_header_t* h = (mach_msg_header_t*)buffer; -- h->msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND,MACH_MSG_TYPE_MAKE_SEND); // MACH_MSG_TYPE_MAKE_SEND_ONCE -- h->msgh_id = unloading ? DYLD_PROCESS_INFO_NOTIFY_UNLOAD_ID : DYLD_PROCESS_INFO_NOTIFY_LOAD_ID; -- h->msgh_local_port = sNotifyReplyPorts[portSlot]; -- h->msgh_remote_port = dyld::gProcessInfo->notifyPorts[portSlot]; -- h->msgh_reserved = 0; -- h->msgh_size = (mach_msg_size_t)sizeof(buffer); -- //dyld::log("sending to port[%d]=%d, size=%d, reply port=%d, id=0x%X\n", portSlot, dyld::gProcessInfo->notifyPorts[portSlot], h->msgh_size, sNotifyReplyPorts[portSlot], h->msgh_id); -- kern_return_t sendResult = mach_msg(h, MACH_SEND_MSG | MACH_RCV_MSG | MACH_SEND_TIMEOUT, h->msgh_size, h->msgh_size, sNotifyReplyPorts[portSlot], 100, MACH_PORT_NULL); -- //dyld::log("send result = 0x%X, msg_id=%d, msg_size=%d\n", sendResult, h->msgh_id, h->msgh_size); -- if ( sendResult == MACH_SEND_INVALID_DEST ) { -- // sender is not responding, detatch -- //dyld::log("process requesting notification gone. deallocation send port %d and receive port %d\n", dyld::gProcessInfo->notifyPorts[portSlot], sNotifyReplyPorts[portSlot]); -- mach_port_deallocate(mach_task_self(), dyld::gProcessInfo->notifyPorts[portSlot]); -- mach_port_deallocate(mach_task_self(), sNotifyReplyPorts[portSlot]); -- dyld::gProcessInfo->notifyPorts[portSlot] = 0; -- sNotifyReplyPorts[portSlot] = 0; -- } --} -- --#define MAX_KERNEL_IMAGES_PER_CALL (100) -- --static void flushKernelNotifications(bool loading, bool force, std::array& kernelInfos, uint32_t &kernelInfoCount) { -- if ((force && kernelInfoCount != 0) || kernelInfoCount == MAX_KERNEL_IMAGES_PER_CALL) { -- if (loading) { -- task_register_dyld_image_infos(mach_task_self(), kernelInfos.data(), kernelInfoCount); -+ 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 { -- task_unregister_dyld_image_infos(mach_task_self(), kernelInfos.data(), kernelInfoCount); -+ sendMessage(slot, DYLD_PROCESS_INFO_NOTIFY_LOAD_ID, totalSize, (mach_msg_header_t*)buffer, totalSize+MAX_TRAILER_SIZE); - } -- kernelInfoCount = 0; - } - } - --static --void queueKernelNotification(const ImageLoader& image, bool loading, std::array& kernelInfos, uint32_t &kernelInfoCount) { -- if ( !image.inSharedCache() ) { -- ino_t inode = image.getInode(); -- image.getUUID(kernelInfos[kernelInfoCount].uuid); -- memcpy(&kernelInfos[kernelInfoCount].fsobjid, &inode, 8); -- kernelInfos[kernelInfoCount].load_addr = (uint64_t)image.machHeader(); -- // FIXME we should also be grabbing the device ID, but that is not necessary yet, -- // and requires threading it through the ImageLoader -- kernelInfos[kernelInfoCount].fsid.val[0] = 0; -- kernelInfos[kernelInfoCount].fsid.val[1] = 0; -- kernelInfoCount++; -+static void notifyMonitoringDyldMain() -+{ -+ dyld3::ScopedTimer(DBG_DYLD_REMOTE_IMAGE_NOTIFIER, 0, 0, 0); -+ 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); - } -- flushKernelNotifications(loading, false, kernelInfos, kernelInfoCount); - } -+#else -+extern void notifyMonitoringDyldMain() VIS_HIDDEN; -+extern void notifyMonitoringDyld(bool unloading, unsigned imageCount, const struct mach_header* loadAddresses[], -+ const char* imagePaths[]) VIS_HIDDEN; -+#endif - - void notifyKernel(const ImageLoader& image, bool loading) { -- std::array kernelInfos; -- uint32_t kernelInfoCount = 0; -- queueKernelNotification(image, loading, kernelInfos, kernelInfoCount); -- flushKernelNotifications(loading, true, kernelInfos, kernelInfoCount); -+ uint32_t baseCode = loading ? DBG_DYLD_UUID_MAP_A : DBG_DYLD_UUID_UNMAP_A; -+ uuid_t uuid; -+ image.getUUID(uuid); -+ if ( image.inSharedCache() ) { -+ dyld3::kdebug_trace_dyld_image(baseCode, image.getInstallPath(), (const uuid_t *)&uuid, {0}, {{ 0, 0 }}, image.machHeader()); -+ } else { -+ fsid_t fsid = {{0, 0}}; -+ fsobj_id_t fsobj = {0}; -+ ino_t inode = image.getInode(); -+ fsobj.fid_objno = (uint32_t)inode; -+ fsobj.fid_generation = (uint32_t)(inode>>32); -+ fsid.val[0] = image.getDevice(); -+ dyld3::kdebug_trace_dyld_image(baseCode, image.getPath(), (const uuid_t *)&uuid, fsobj, fsid, image.machHeader()); -+ } - } - - static void notifySingle(dyld_image_states state, const ImageLoader* image, ImageLoader::InitializerTimingList* timingInfo) -@@ -949,32 +983,10 @@ static void notifySingle(dyld_image_states state, const ImageLoader* image, Imag - // mach message csdlc about dynamically unloaded images - if ( image->addFuncNotified() && (state == dyld_image_state_terminated) ) { - notifyKernel(*image, false); -- -- uint64_t loadTimestamp = mach_absolute_time(); -- if ( sEnv.DYLD_PRINT_CS_NOTIFICATIONS ) { -- dyld::log("dyld: coresymbolication_unload_notifier(%p, 0x%016llX, %p, %s)\n", -- dyld::gProcessInfo->coreSymbolicationShmPage, loadTimestamp, image->machHeader(), image->getPath()); -- } -- if ( dyld::gProcessInfo->coreSymbolicationShmPage != NULL) { -- coresymbolication_unload_notifier(dyld::gProcessInfo->coreSymbolicationShmPage, loadTimestamp, image->getPath(), image->machHeader()); -- } -- for (int slot=0; slot < DYLD_MAX_PROCESS_INFO_NOTIFY_COUNT; ++slot) { -- if ( dyld::gProcessInfo->notifyPorts[slot] != 0 ) { -- dyld_image_info info; -- info.imageLoadAddress = image->machHeader(); -- info.imageFilePath = image->getPath(); -- info.imageFileModDate = 0; -- notifyMonitoringDyld(true, slot, 1, &info); -- } -- else if ( sNotifyReplyPorts[slot] != 0 ) { -- // monitoring process detached from this process, so release reply port -- //dyld::log("deallocated reply port %d\n", sNotifyReplyPorts[slot]); -- mach_port_deallocate(mach_task_self(), sNotifyReplyPorts[slot]); -- sNotifyReplyPorts[slot] = 0; -- } -- } -+ const struct mach_header* loadAddress[] = { image->machHeader() }; -+ const char* loadPath[] = { image->getPath() }; -+ notifyMonitoringDyld(true, 1, loadAddress, loadPath); - } -- - } - - -@@ -1186,32 +1237,80 @@ static void notifyBatchPartial(dyld_image_states state, bool orLater, dyld_image - if ( dontLoadReason != NULL ) - throw dontLoadReason; - if ( !preflightOnly && (state == dyld_image_state_dependents_mapped) ) { -- if ( (dyld::gProcessInfo->coreSymbolicationShmPage != NULL) || sEnv.DYLD_PRINT_CS_NOTIFICATIONS ) { -- // mach message csdlc about loaded images -- uint64_t loadTimestamp = mach_absolute_time(); -- for (unsigned j=0; j < imageCount; ++j) { -- if ( sEnv.DYLD_PRINT_CS_NOTIFICATIONS ) { -- dyld::log("dyld: coresymbolication_load_notifier(%p, 0x%016llX, %p, %s)\n", -- dyld::gProcessInfo->coreSymbolicationShmPage, loadTimestamp, infos[j].imageLoadAddress, infos[j].imageFilePath); -- } -- coresymbolication_load_notifier(dyld::gProcessInfo->coreSymbolicationShmPage, loadTimestamp, infos[j].imageFilePath, infos[j].imageLoadAddress); -- } -- } -- for (int slot=0; slot < DYLD_MAX_PROCESS_INFO_NOTIFY_COUNT; ++slot) { -- if ( dyld::gProcessInfo->notifyPorts[slot] ) -- notifyMonitoringDyld(false, slot, imageCount, infos); -+ const struct mach_header* loadAddresses[imageCount]; -+ const char* loadPaths[imageCount]; -+ for(uint32_t i = 0; iprocessDetachedFromSharedRegion = opts.forcePrivate; -+ dyld::gProcessInfo->sharedCacheSlide = sSharedCacheLoadInfo.slide; -+ dyld::gProcessInfo->sharedCacheBaseAddress = (unsigned long)sSharedCacheLoadInfo.loadAddress; -+ sSharedCacheLoadInfo.loadAddress->getUUID(dyld::gProcessInfo->sharedCacheUUID); -+ 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); -+ } - --static int __attribute__((noinline)) _shared_region_check_np(uint64_t* start_address) --{ -- if ( gLinkContext.sharedRegionMode == ImageLoader::kUseSharedRegion ) -- return syscall(294, start_address); -- return -1; -+//#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 ) { -+// if ( sSharedCacheLoadInfo.errorMessage != nullptr ) -+// halt(sSharedCacheLoadInfo.errorMessage); -+// else -+// halt("error loading dyld shared cache"); -+// } -+//#endif - } - - --static void rebaseChain(uint8_t* pageContent, uint16_t startOffset, uintptr_t slideAmount, const dyld_cache_slide_info2* slideInfo) --{ -- const uintptr_t deltaMask = (uintptr_t)(slideInfo->delta_mask); -- const uintptr_t valueMask = ~deltaMask; -- const uintptr_t valueAdd = (uintptr_t)(slideInfo->value_add); -- const unsigned deltaShift = __builtin_ctzll(deltaMask) - 2; - -- uint32_t pageOffset = startOffset; -- uint32_t delta = 1; -- while ( delta != 0 ) { -- uint8_t* loc = pageContent + pageOffset; -- uintptr_t rawValue = *((uintptr_t*)loc); -- delta = (uint32_t)((rawValue & deltaMask) >> deltaShift); -- uintptr_t value = (rawValue & valueMask); -- if ( value != 0 ) { -- value += valueAdd; -- value += slideAmount; -- } -- *((uintptr_t*)loc) = value; -- //dyld::log(" pageOffset=0x%03X, loc=%p, org value=0x%08llX, new value=0x%08llX, delta=0x%X\n", pageOffset, loc, (uint64_t)rawValue, (uint64_t)value, delta); -- pageOffset += delta; -- } -+// create when NSLinkModule is called for a second time on a bundle -+ImageLoader* cloneImage(ImageLoader* image) -+{ -+ // open file (automagically closed when this function exits) -+ FileOpener file(image->getPath()); -+ -+ struct stat stat_buf; -+ if ( fstat(file.getFileDescriptor(), &stat_buf) == -1) -+ throw "stat error"; -+ -+ dyld::LoadContext context; -+ context.useSearchPaths = false; -+ context.useFallbackPaths = false; -+ context.useLdLibraryPath = false; -+ context.implicitRPath = false; -+ context.matchByInstallName = false; -+ context.dontLoad = false; -+ context.mustBeBundle = true; -+ context.mustBeDylib = false; -+ context.canBePIE = false; -+ context.origin = NULL; -+ context.rpath = NULL; -+ return loadPhase6(file.getFileDescriptor(), stat_buf, image->getPath(), context); - } - - --static void loadAndCheckCodeSignature(int fd, uint32_t count, const shared_file_mapping_np mappings[], -- off_t codeSignatureOffset, size_t codeSignatureSize, -- const void *firstPages, size_t firstPagesSize) -+ImageLoader* loadFromMemory(const uint8_t* mem, uint64_t len, const char* moduleName) - { -- // register code signature blob for whole dyld cache -- fsignatures_t siginfo; -- siginfo.fs_file_start = 0; // cache always starts at beginning of file -- siginfo.fs_blob_start = (void*)codeSignatureOffset; -- siginfo.fs_blob_size = codeSignatureSize; -+ // if fat wrapper, find usable sub-file -+ const fat_header* memStartAsFat = (fat_header*)mem; -+ uint64_t fileOffset = 0; -+ uint64_t fileLength = len; -+ if ( memStartAsFat->magic == OSSwapBigToHostInt32(FAT_MAGIC) ) { -+ if ( fatFindBest(memStartAsFat, &fileOffset, &fileLength) ) { -+ mem = &mem[fileOffset]; -+ len = fileLength; -+ } -+ else { -+ throw "no matching architecture in universal wrapper"; -+ } -+ } - -- int result = fcntl(fd, F_ADDFILESIGS_RETURN, &siginfo); -- // don't warn in chrooted case because mapping syscall is about to fail too -- if ( result == -1 ) { --#if __IPHONE_OS_VERSION_MIN_REQUIRED -- throwf("code signature registration for shared cache failed with errno=%d\n", errno); --#else -- if ( gLinkContext.verboseMapping ) -- dyld::log("dyld: code signature registration for shared cache failed with errno=%d\n", errno); --#endif -+ // try each loader -+ if ( isCompatibleMachO(mem, moduleName) ) { -+ ImageLoader* image = ImageLoaderMachO::instantiateFromMemory(moduleName, (macho_header*)mem, len, gLinkContext); -+ // don't add bundles to global list, they can be loaded but not linked. When linked it will be added to list -+ if ( ! image->isBundle() ) -+ addImage(image); -+ return image; - } -- uint64_t codeSignedLength = siginfo.fs_file_start; -- for (uint32_t i = 0; i < count; ++i) { -- if ( (mappings[i].sfm_size > codeSignedLength) || (mappings[i].sfm_file_offset > (codeSignedLength - mappings[i].sfm_size)) ) -- throw "dyld shared cache mapping not covered by code signature"; -+ -+ // try other file formats here... -+ -+ // throw error about what was found -+ switch (*(uint32_t*)mem) { -+ case MH_MAGIC: -+ case MH_CIGAM: -+ case MH_MAGIC_64: -+ case MH_CIGAM_64: -+ throw "mach-o, but wrong architecture"; -+ default: -+ throwf("unknown file type, first eight bytes: 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X", -+ mem[0], mem[1], mem[2], mem[3], mem[4], mem[5], mem[6],mem[7]); - } -- -- void *fdata = xmmap(NULL, firstPagesSize, PROT_READ|PROT_EXEC, MAP_PRIVATE, fd, 0); -- if ( fdata == MAP_FAILED ) -- throwf("mmap() errno=%d validating first page of shared cache", errno); -- if ( memcmp(fdata, firstPages, firstPagesSize) != 0 ) -- throwf("mmap() page compare failed for shared cache"); -- munmap(fdata, firstPagesSize); - } - --static int __attribute__((noinline)) _shared_region_map_and_slide_np(int fd, uint32_t count, const shared_file_mapping_np mappings[], -- long slide, void* slideInfo, unsigned long slideInfoSize) --{ -- if ( gLinkContext.sharedRegionMode == ImageLoader::kUseSharedRegion ) { -- return syscall(438, fd, count, mappings, slide, slideInfo, slideInfoSize); -- } - -- // remove the shared region sub-map -- vm_deallocate(mach_task_self(), (vm_address_t)SHARED_REGION_BASE, SHARED_REGION_SIZE); -+void registerAddCallback(ImageCallback func) -+{ -+ // now add to list to get notified when any more images are added -+ sAddImageCallbacks.push_back(func); - -- // notify gdb or other lurkers that this process is no longer using the shared region -- dyld::gProcessInfo->processDetachedFromSharedRegion = true; -- -- // map cache just for this process with mmap() -- const shared_file_mapping_np* const start = mappings; -- const shared_file_mapping_np* const end = &mappings[count]; -- for (const shared_file_mapping_np* p = start; p < end; ++p ) { -- void* mmapAddress = (void*)(uintptr_t)(p->sfm_address); -- size_t size = p->sfm_size; -- //dyld::log("dyld: mapping address %p with size 0x%08lX\n", mmapAddress, size); -- int protection = 0; -- if ( p->sfm_init_prot & VM_PROT_EXECUTE ) -- protection |= PROT_EXEC; -- if ( p->sfm_init_prot & VM_PROT_READ ) -- protection |= PROT_READ; -- if ( p->sfm_init_prot & VM_PROT_WRITE ) -- protection |= PROT_WRITE; -- off_t offset = p->sfm_file_offset; -- if ( mmap(mmapAddress, size, protection, MAP_FIXED | MAP_PRIVATE, fd, offset) != mmapAddress ) { -- // failed to map some chunk of this shared cache file -- // clear shared region -- vm_deallocate(mach_task_self(), (vm_address_t)SHARED_REGION_BASE, SHARED_REGION_SIZE); -- // go back to not using shared region at all -- gLinkContext.sharedRegionMode = ImageLoader::kDontUseSharedRegion; -- if ( gLinkContext.verboseMapping ) { -- dyld::log("dyld: shared cached region cannot be mapped at address %p with size 0x%08lX\n", -- mmapAddress, size); -- } -- // return failure -- return -1; -- } -- } -- -- // update all __DATA pages with slide info -- const dyld_cache_slide_info* slideInfoHeader = (dyld_cache_slide_info*)slideInfo; -- if ( slideInfoHeader->version == 2 ) { -- const dyld_cache_slide_info2* slideHeader = (dyld_cache_slide_info2*)slideInfo; -- const uint32_t page_size = slideHeader->page_size; -- const uint16_t* page_starts = (uint16_t*)((long)(slideInfo) + slideHeader->page_starts_offset); -- const uint16_t* page_extras = (uint16_t*)((long)(slideInfo) + slideHeader->page_extras_offset); -- const uintptr_t dataPagesStart = mappings[1].sfm_address; -- for (int i=0; i < slideHeader->page_starts_count; ++i) { -- uint8_t* page = (uint8_t*)(long)(dataPagesStart + (page_size*i)); -- uint16_t pageEntry = page_starts[i]; -- //dyld::log("page[%d]: page_starts[i]=0x%04X\n", i, pageEntry); -- if ( pageEntry == DYLD_CACHE_SLIDE_PAGE_ATTR_NO_REBASE ) -- continue; -- if ( pageEntry & DYLD_CACHE_SLIDE_PAGE_ATTR_EXTRA ) { -- uint16_t chainIndex = (pageEntry & 0x3FFF); -- bool done = false; -- while ( !done ) { -- uint16_t info = page_extras[chainIndex]; -- uint16_t pageStartOffset = (info & 0x3FFF)*4; -- //dyld::log(" chain[%d] pageOffset=0x%03X\n", chainIndex, pageStartOffset); -- rebaseChain(page, pageStartOffset, slide, slideHeader); -- done = (info & DYLD_CACHE_SLIDE_PAGE_ATTR_END); -- ++chainIndex; -- } -- } -- else { -- uint32_t pageOffset = pageEntry * 4; -- //dyld::log(" start pageOffset=0x%03X\n", pageOffset); -- rebaseChain(page, pageOffset, slide, slideHeader); -- } -+ // call callback with all existing images -+ for (std::vector::iterator it=sAllImages.begin(); it != sAllImages.end(); it++) { -+ ImageLoader* image = *it; -+ if ( image->getState() >= dyld_image_state_bound && image->getState() < dyld_image_state_terminated ) { -+ dyld3::ScopedTimer timer(DBG_DYLD_TIMING_FUNC_FOR_ADD_IMAGE, (uint64_t)image->machHeader(), (uint64_t)(*func), 0); -+ (*func)(image->machHeader(), image->getSlide()); - } - } -- else if ( slide != 0 ) { -- const uintptr_t dataPagesStart = mappings[1].sfm_address; -- const uint16_t* toc = (uint16_t*)((long)(slideInfoHeader) + slideInfoHeader->toc_offset); -- const uint8_t* entries = (uint8_t*)((long)(slideInfoHeader) + slideInfoHeader->entries_offset); -- for(uint32_t i=0; i < slideInfoHeader->toc_count; ++i) { -- const uint8_t* entry = &entries[toc[i]*slideInfoHeader->entries_size]; -- const uint8_t* page = (uint8_t*)(long)(dataPagesStart + (4096*i)); -- //dyld::log("page=%p toc[%d]=%d entries=%p\n", page, i, toc[i], entry); -- for(int j=0; j < 128; ++j) { -- uint8_t b = entry[j]; -- //dyld::log(" entry[%d] = 0x%02X\n", j, b); -- if ( b != 0 ) { -- for(int k=0; k < 8; ++k) { -- if ( b & (1<appendImagesToNotify(dyld_image_state_bound, true, infos); -+ for (unsigned i=0; i < cacheCount; ++i) { -+ dyld3::ScopedTimer timer(DBG_DYLD_TIMING_FUNC_FOR_ADD_IMAGE, (uint64_t)infos[i].imageLoadAddress, (uint64_t)(*func), 0); -+ (*func)(infos[i].imageLoadAddress, sSharedCacheLoadInfo.slide); - } - } -- -- // succesfully mapped shared cache for just this process -- gLinkContext.sharedRegionMode = ImageLoader::kUsePrivateSharedRegion; -- -- return 0; --} -- -- --const void* imMemorySharedCacheHeader() --{ -- return sSharedCache; --} -- --const char* getStandardSharedCacheFilePath() --{ --#if __IPHONE_OS_VERSION_MIN_REQUIRED -- return IPHONE_DYLD_SHARED_CACHE_DIR DYLD_SHARED_CACHE_BASE_NAME ARCH_NAME; --#else -- #if __x86_64__ -- if ( sHaswell ) { -- const char* path2 = MACOSX_DYLD_SHARED_CACHE_DIR DYLD_SHARED_CACHE_BASE_NAME ARCH_NAME_H; -- struct stat statBuf; -- if ( my_stat(path2, &statBuf) == 0 ) -- return path2; -- } -- #endif -- return MACOSX_DYLD_SHARED_CACHE_DIR DYLD_SHARED_CACHE_BASE_NAME ARCH_NAME; - #endif - } - --int openSharedCacheFile() -+void registerLoadCallback(LoadImageCallback func) - { -- char path[MAXPATHLEN]; -- strlcpy(path, sSharedCacheDir, MAXPATHLEN); -- strlcat(path, "/", MAXPATHLEN); --#if __x86_64__ -- if ( sHaswell ) { -- strlcat(path, DYLD_SHARED_CACHE_BASE_NAME ARCH_NAME_H, MAXPATHLEN); -- int fd = my_open(path, O_RDONLY, 0); -- if ( fd != -1 ) { -- if ( gLinkContext.verboseMapping ) -- dyld::log("dyld: Mapping%s shared cache from %s\n", (gLinkContext.sharedRegionMode == ImageLoader::kUsePrivateSharedRegion) ? " private": "", path); -- return fd; -- } -- strlcpy(path, sSharedCacheDir, MAXPATHLEN); -- } --#endif -- strlcat(path, DYLD_SHARED_CACHE_BASE_NAME ARCH_NAME, MAXPATHLEN); --#if __IPHONE_OS_VERSION_MIN_REQUIRED -- struct stat enableStatBuf; -- struct stat devCacheStatBuf; -- struct stat prodCacheStatBuf; -- if ( ((my_stat(IPHONE_DYLD_SHARED_CACHE_DIR "enable-dylibs-to-override-cache", &enableStatBuf) == 0) -- && (enableStatBuf.st_size < ENABLE_DYLIBS_TO_OVERRIDE_CACHE_SIZE) -- && (my_stat(IPHONE_DYLD_SHARED_CACHE_DIR DYLD_SHARED_CACHE_BASE_NAME ARCH_NAME DYLD_SHARED_CACHE_DEVELOPMENT_EXT, &devCacheStatBuf) == 0)) -- || (my_stat(IPHONE_DYLD_SHARED_CACHE_DIR DYLD_SHARED_CACHE_BASE_NAME ARCH_NAME, &prodCacheStatBuf) != 0)) -- strlcat(path, DYLD_SHARED_CACHE_DEVELOPMENT_EXT, MAXPATHLEN); --#endif -- if ( gLinkContext.verboseMapping ) -- dyld::log("dyld: Mapping%s shared cache from %s\n", (gLinkContext.sharedRegionMode == ImageLoader::kUsePrivateSharedRegion) ? " private": "", path); -- return my_open(path, O_RDONLY, 0); --} -- -+ // now add to list to get notified when any more images are added -+ sAddLoadImageCallbacks.push_back(func); - --static void getCacheBounds(uint32_t mappingsCount, const shared_file_mapping_np mappings[], uint64_t& lowAddress, uint64_t& highAddress) --{ -- lowAddress = 0; -- highAddress = 0; -- for(uint32_t i=0; i < mappingsCount; ++i) { -- if ( lowAddress == 0 ) { -- lowAddress = mappings[i].sfm_address; -- highAddress = mappings[i].sfm_address + mappings[i].sfm_size; -- } -- else { -- if ( mappings[i].sfm_address < lowAddress ) -- lowAddress = mappings[i].sfm_address; -- if ( (mappings[i].sfm_address + mappings[i].sfm_size) > highAddress ) -- highAddress = mappings[i].sfm_address + mappings[i].sfm_size; -+ // call callback with all existing images -+ for (ImageLoader* image : sAllImages) { -+ if ( image->getState() >= dyld_image_state_bound && image->getState() < dyld_image_state_terminated ) { -+ dyld3::ScopedTimer timer(DBG_DYLD_TIMING_FUNC_FOR_ADD_IMAGE, (uint64_t)image->machHeader(), (uint64_t)(*func), 0); -+ (*func)(image->machHeader(), image->getPath(), !image->neverUnload()); - } - } --} -- --static long pickCacheSlide(uint32_t mappingsCount, shared_file_mapping_np mappings[]) --{ --#if __x86_64__ -- // x86_64 has a two memory regions: -- // 256MB at 0x00007FFF70000000 -- // 1024MB at 0x00007FFF80000000 -- // Some old shared caches have r/w region after rx region, so all regions slide within 1GB range -- // Newer shared caches have r/w region based at 0x7FFF70000000 and r/o regions at 0x7FFF80000000, so each part has max slide -- if ( (mappingsCount >= 3) && (mappings[1].sfm_init_prot == (VM_PROT_READ|VM_PROT_WRITE)) && (mappings[1].sfm_address == 0x00007FFF70000000) ) { -- const uint64_t rwSize = mappings[1].sfm_size; -- const uint64_t rwSlop = 0x10000000ULL - rwSize; -- const uint64_t roSize = (mappings[2].sfm_address + mappings[2].sfm_size) - mappings[0].sfm_address; -- const uint64_t roSlop = 0x40000000ULL - roSize; -- const uint64_t space = (rwSlop < roSlop) ? rwSlop : roSlop; -- -- // choose new random slide -- long slide = (arc4random() % space) & (-4096); -- //dyld::log("rwSlop=0x%0llX, roSlop=0x%0llX\n", rwSlop, roSlop); -- //dyld::log("space=0x%0llX, slide=0x%0lX\n", space, slide); -- -- // update mappings -- for(uint32_t i=0; i < mappingsCount; ++i) { -- mappings[i].sfm_address += slide; -+#if SUPPORT_ACCELERATE_TABLES -+ if ( sAllCacheImagesProxy != NULL ) { -+ dyld_image_info infos[allImagesCount()+1]; -+ unsigned cacheCount = sAllCacheImagesProxy->appendImagesToNotify(dyld_image_state_bound, true, infos); -+ for (unsigned i=0; i < cacheCount; ++i) { -+ dyld3::ScopedTimer timer(DBG_DYLD_TIMING_FUNC_FOR_ADD_IMAGE, (uint64_t)infos[i].imageLoadAddress, (uint64_t)(*func), 0); -+ (*func)(infos[i].imageLoadAddress, infos[i].imageFilePath, false); - } -- -- return slide; - } -- // else fall through to handle old style cache - #endif -- // get bounds of cache -- uint64_t lowAddress; -- uint64_t highAddress; -- getCacheBounds(mappingsCount, mappings, lowAddress, highAddress); -- -- // find slop space -- const uint64_t space = (SHARED_REGION_BASE + SHARED_REGION_SIZE) - highAddress; -- -- // choose new random slide --#if __arm__ -- // change shared cache slide for 32-bit arm to always be 16k aligned -- long slide = ((arc4random() % space) & (-16384)); --#else -- long slide = dyld_page_trunc(arc4random() % space); --#endif -- //dyld::log("slideSpace=0x%0llX\n", space); -- //dyld::log("slide=0x%0lX\n", slide); -- -- // update mappings -- for(uint32_t i=0; i < mappingsCount; ++i) { -- mappings[i].sfm_address += slide; -- } -- -- return slide; - } - --static void mapSharedCache() -+void registerBulkLoadCallback(LoadImageBulkCallback func) - { -- uint64_t cacheBaseAddress = 0; -- // quick check if a cache is already mapped into shared region -- if ( _shared_region_check_np(&cacheBaseAddress) == 0 ) { -- sSharedCache = (dyld_cache_header*)cacheBaseAddress; -- // if we don't understand the currently mapped shared cache, then ignore --#if __x86_64__ -- const char* magic = (sHaswell ? ARCH_CACHE_MAGIC_H : ARCH_CACHE_MAGIC); --#else -- const char* magic = ARCH_CACHE_MAGIC; --#endif -- if ( strcmp(sSharedCache->magic, magic) != 0 ) { -- sSharedCache = NULL; -- if ( gLinkContext.verboseMapping ) { -- dyld::log("dyld: existing shared cached in memory is not compatible\n"); -- return; -- } -- } -- // check if cache file is slidable -- const dyld_cache_header* header = sSharedCache; -- if ( (header->mappingOffset >= 0x48) && (header->slideInfoSize != 0) ) { -- // solve for slide by comparing loaded address to address of first region -- const uint8_t* loadedAddress = (uint8_t*)sSharedCache; -- const dyld_cache_mapping_info* const mappings = (dyld_cache_mapping_info*)(loadedAddress+header->mappingOffset); -- const uint8_t* preferedLoadAddress = (uint8_t*)(long)(mappings[0].address); -- sSharedCacheSlide = loadedAddress - preferedLoadAddress; -- dyld::gProcessInfo->sharedCacheSlide = sSharedCacheSlide; -- dyld::gProcessInfo->sharedCacheBaseAddress = cacheBaseAddress; -- //dyld::log("sSharedCacheSlide=0x%08lX, loadedAddress=%p, preferedLoadAddress=%p\n", sSharedCacheSlide, loadedAddress, preferedLoadAddress); -- } -- // if cache has a uuid, copy it -- if ( header->mappingOffset >= 0x68 ) { -- memcpy(dyld::gProcessInfo->sharedCacheUUID, header->uuid, 16); -- } -- // verbose logging -- if ( gLinkContext.verboseMapping ) { -- dyld::log("dyld: re-using existing %s shared cache mapping\n", (header->cacheType == kDyldSharedCacheTypeDevelopment ? "development" : "production")); -- } -- if (header->mappingOffset >= 0x68) { -- dyld_kernel_image_info_t kernelCacheInfo; -- memcpy(&kernelCacheInfo.uuid[0], &sSharedCache->uuid[0], sizeof(uuid_t)); -- kernelCacheInfo.load_addr = (uint64_t)sSharedCache; -- kernelCacheInfo.fsobjid.fid_objno = 0; -- kernelCacheInfo.fsobjid.fid_generation = 0; -- kernelCacheInfo.fsid.val[0] = 0; -- kernelCacheInfo.fsid.val[0] = 0; -- task_register_dyld_shared_cache_image_info(mach_task_self(), kernelCacheInfo, false, false); -- } -- } -- else { --#if __i386__ || __x86_64__ -- // Safe Boot should disable dyld shared cache -- // if we are in safe-boot mode and the cache was not made during this boot cycle, -- // delete the cache file -- uint32_t safeBootValue = 0; -- size_t safeBootValueSize = sizeof(safeBootValue); -- if ( (sysctlbyname("kern.safeboot", &safeBootValue, &safeBootValueSize, NULL, 0) == 0) && (safeBootValue != 0) ) { -- // user booted machine in safe-boot mode -- struct stat dyldCacheStatInfo; -- // Don't use custom DYLD_SHARED_CACHE_DIR if provided, use standard path -- if ( my_stat(MACOSX_DYLD_SHARED_CACHE_DIR DYLD_SHARED_CACHE_BASE_NAME ARCH_NAME, &dyldCacheStatInfo) == 0 ) { -- struct timeval bootTimeValue; -- size_t bootTimeValueSize = sizeof(bootTimeValue); -- if ( (sysctlbyname("kern.boottime", &bootTimeValue, &bootTimeValueSize, NULL, 0) == 0) && (bootTimeValue.tv_sec != 0) ) { -- // if the cache file was created before this boot, then throw it away and let it rebuild itself -- if ( dyldCacheStatInfo.st_mtime < bootTimeValue.tv_sec ) { -- ::unlink(MACOSX_DYLD_SHARED_CACHE_DIR DYLD_SHARED_CACHE_BASE_NAME ARCH_NAME); -- gLinkContext.sharedRegionMode = ImageLoader::kDontUseSharedRegion; -- return; -- } -- } -- } -- } --#endif -- // map in shared cache to shared region -- int fd = openSharedCacheFile(); -- if ( fd != -1 ) { -- uint8_t firstPages[8192]; -- if ( ::read(fd, firstPages, 8192) == 8192 ) { -- dyld_cache_header* header = (dyld_cache_header*)firstPages; -- #if __x86_64__ -- const char* magic = (sHaswell ? ARCH_CACHE_MAGIC_H : ARCH_CACHE_MAGIC); -- #else -- const char* magic = ARCH_CACHE_MAGIC; -- #endif -- if ( strcmp(header->magic, magic) == 0 ) { -- const dyld_cache_mapping_info* const fileMappingsStart = (dyld_cache_mapping_info*)&firstPages[header->mappingOffset]; -- const dyld_cache_mapping_info* const fileMappingsEnd = &fileMappingsStart[header->mappingCount]; -- #if __IPHONE_OS_VERSION_MIN_REQUIRED -- if ( (header->mappingCount != 3) -- || (header->mappingOffset > 256) -- || (fileMappingsStart[0].fileOffset != 0) -- || (fileMappingsStart[0].address != SHARED_REGION_BASE) -- || ((fileMappingsStart[0].address + fileMappingsStart[0].size) > fileMappingsStart[1].address) -- || ((fileMappingsStart[1].address + fileMappingsStart[1].size) > fileMappingsStart[2].address) -- || ((fileMappingsStart[0].fileOffset + fileMappingsStart[0].size) != fileMappingsStart[1].fileOffset) -- || ((fileMappingsStart[1].fileOffset + fileMappingsStart[1].size) != fileMappingsStart[2].fileOffset) ) -- throw "dyld shared cache file is invalid"; -- #endif -- shared_file_mapping_np mappings[header->mappingCount]; -- unsigned int mappingCount = header->mappingCount; -- int readWriteMappingIndex = -1; -- int readOnlyMappingIndex = -1; -- // validate that the cache file has not been truncated -- bool goodCache = false; -- struct stat stat_buf; -- if ( fstat(fd, &stat_buf) == 0 ) { -- goodCache = true; -- int i=0; -- for (const dyld_cache_mapping_info* p = fileMappingsStart; p < fileMappingsEnd; ++p, ++i) { -- mappings[i].sfm_address = p->address; -- mappings[i].sfm_size = p->size; -- mappings[i].sfm_file_offset = p->fileOffset; -- mappings[i].sfm_max_prot = p->maxProt; -- mappings[i].sfm_init_prot = p->initProt; -- // rdar://problem/5694507 old update_dyld_shared_cache tool could make a cache file -- // that is not page aligned, but otherwise ok. -- if ( p->fileOffset+p->size > (uint64_t)(stat_buf.st_size+4095 & (-4096)) ) { -- dyld::log("dyld: shared cached file is corrupt: %s" DYLD_SHARED_CACHE_BASE_NAME ARCH_NAME "\n", sSharedCacheDir); -- goodCache = false; -- } -- if ( (mappings[i].sfm_init_prot & (VM_PROT_READ|VM_PROT_WRITE)) == (VM_PROT_READ|VM_PROT_WRITE) ) { -- readWriteMappingIndex = i; -- } -- if ( mappings[i].sfm_init_prot == VM_PROT_READ ) { -- readOnlyMappingIndex = i; -- } -- } -- // if shared cache is code signed, add a mapping for the code signature -- uint64_t signatureSize = header->codeSignatureSize; -- // zero size in header means signature runs to end-of-file -- if ( signatureSize == 0 ) -- signatureSize = stat_buf.st_size - header->codeSignatureOffset; -- if ( signatureSize != 0 ) { --#if __arm__ || __arm64__ -- size_t alignedSignatureSize = (signatureSize+16383) & (-16384); --#else -- size_t alignedSignatureSize = (signatureSize+4095) & (-4096); --#endif -- // validate code signature covers entire shared cache -- loadAndCheckCodeSignature(fd, mappingCount, mappings, header->codeSignatureOffset, alignedSignatureSize, firstPages, sizeof(firstPages)); -- } --#if __IPHONE_OS_VERSION_MIN_REQUIRED -- else { -- throw "dyld shared cache file not code signed"; -- } --#endif -- } --#if __MAC_OS_X_VERSION_MIN_REQUIRED -- // sanity check that /usr/lib/libSystem.B.dylib stat() info matches cache -- if ( header->imagesCount * sizeof(dyld_cache_image_info) + header->imagesOffset < 8192 ) { -- bool foundLibSystem = false; -- if ( my_stat("/usr/lib/libSystem.B.dylib", &stat_buf) == 0 ) { -- const dyld_cache_image_info* images = (dyld_cache_image_info*)&firstPages[header->imagesOffset]; -- const dyld_cache_image_info* const imagesEnd = &images[header->imagesCount]; -- for (const dyld_cache_image_info* p = images; p < imagesEnd; ++p) { -- if ( ((time_t)p->modTime == stat_buf.st_mtime) && ((ino_t)p->inode == stat_buf.st_ino) ) { -- foundLibSystem = true; -- break; -- } -- } -- } -- if ( !sSharedCacheIgnoreInodeAndTimeStamp && !foundLibSystem ) { -- dyld::log("dyld: shared cached file was built against a different libSystem.dylib, ignoring cache.\n" -- "to update dyld shared cache run: 'sudo update_dyld_shared_cache' then reboot.\n"); -- goodCache = false; -- } -- } --#endif --#if __IPHONE_OS_VERSION_MIN_REQUIRED -- { -- uint64_t lowAddress; -- uint64_t highAddress; -- getCacheBounds(mappingCount, mappings, lowAddress, highAddress); -- if ( (highAddress-lowAddress) > SHARED_REGION_SIZE ) -- throw "dyld shared cache is too big to fit in shared region"; -- } --#endif -- -- if ( goodCache && (readWriteMappingIndex == -1) ) { -- dyld::log("dyld: shared cached file is missing read/write mapping: %s" DYLD_SHARED_CACHE_BASE_NAME ARCH_NAME "\n", sSharedCacheDir); -- goodCache = false; -- } -- if ( goodCache && (readOnlyMappingIndex == -1) ) { -- dyld::log("dyld: shared cached file is missing read-only mapping: %s" DYLD_SHARED_CACHE_BASE_NAME ARCH_NAME "\n", sSharedCacheDir); -- goodCache = false; -- } -- if ( goodCache ) { -- long cacheSlide = 0; -- void* slideInfo = (void*)(long)(mappings[readOnlyMappingIndex].sfm_address + (header->slideInfoOffset - mappings[readOnlyMappingIndex].sfm_file_offset));; -- uint64_t slideInfoSize = header->slideInfoSize; -- // check if shared cache contains slid info -- if ( slideInfoSize != 0 ) { -- // don't slide shared cache if ASLR disabled (main executable didn't slide) -- if ( sMainExecutable->isPositionIndependentExecutable() && (sMainExecutable->getSlide() == 0) ) { -- cacheSlide = 0; -- } -- else { -- // generate random slide amount -- cacheSlide = pickCacheSlide(mappingCount, mappings); -- } -- -- slideInfo = (void*)((uint8_t*)slideInfo + cacheSlide); -- // add VM_PROT_SLIDE bit to __DATA area of cache -- mappings[readWriteMappingIndex].sfm_max_prot |= VM_PROT_SLIDE; -- mappings[readWriteMappingIndex].sfm_init_prot |= VM_PROT_SLIDE; -- } -- if ( gLinkContext.verboseMapping ) { -- dyld::log("dyld: calling _shared_region_map_and_slide_np() with regions:\n"); -- for (int i=0; i < mappingCount; ++i) { -- dyld::log(" address=0x%08llX, size=0x%08llX, fileOffset=0x%08llX\n", mappings[i].sfm_address, mappings[i].sfm_size, mappings[i].sfm_file_offset); -- } -- } -- -- if (_shared_region_map_and_slide_np(fd, mappingCount, mappings, cacheSlide, slideInfo, slideInfoSize) == 0) { -- // successfully mapped cache into shared region -- sSharedCache = (dyld_cache_header*)mappings[0].sfm_address; -- sSharedCacheSlide = cacheSlide; -- dyld::gProcessInfo->sharedCacheSlide = cacheSlide; -- dyld::gProcessInfo->sharedCacheBaseAddress = mappings[0].sfm_address; -- //dyld::log("sSharedCache=%p sSharedCacheSlide=0x%08lX\n", sSharedCache, sSharedCacheSlide); -- // if cache has a uuid, copy it -- if ( header->mappingOffset >= 0x68 ) { -- const bool privateSharedCache = gLinkContext.sharedRegionMode == ImageLoader::kUsePrivateSharedRegion; -- memcpy(dyld::gProcessInfo->sharedCacheUUID, header->uuid, 16); -- dyld_kernel_image_info_t kernelCacheInfo; -- memcpy(&kernelCacheInfo.uuid[0], &sSharedCache->uuid[0], sizeof(uuid_t)); -- kernelCacheInfo.load_addr = (uint64_t)sSharedCache; -- kernelCacheInfo.fsobjid.fid_objno = 0; -- kernelCacheInfo.fsobjid.fid_generation = 0; -- kernelCacheInfo.fsid.val[0] = 0; -- kernelCacheInfo.fsid.val[0] = 0; -- if (privateSharedCache) { -- kernelCacheInfo.fsobjid = *(fsobj_id_t*)(&stat_buf.st_ino); -- struct statfs statfs_buf; -- if ( fstatfs(fd, &statfs_buf) == 0 ) { -- kernelCacheInfo.fsid = statfs_buf.f_fsid; -- } -- } -- task_register_dyld_shared_cache_image_info(mach_task_self(), kernelCacheInfo, false, privateSharedCache); -- } -- } -- else { --#if __IPHONE_OS_VERSION_MIN_REQUIRED -- throwf("dyld shared cache could not be mapped. errno=%d, slide=0x%08lX, slideInfo=%p, slideInfoSize=0x%08llX, mappingCount=%u, " -- "address/size/off/init/max [0]=0x%0llX/0x%0llX/0x%0llX/0x%02X/0x%02X, [1]=0x%0llX/0x%0llX/0x%0llX/0x%02X/0x%02X, [2]=0x%0llX/0x%0llX/0x%0llX/0x%02X/0x%02X", -- errno, cacheSlide, slideInfo, slideInfoSize, mappingCount, -- mappings[0].sfm_address, mappings[0].sfm_size, mappings[0].sfm_file_offset, mappings[0].sfm_init_prot, mappings[0].sfm_max_prot, -- mappings[1].sfm_address, mappings[1].sfm_size, mappings[1].sfm_file_offset, mappings[1].sfm_init_prot, mappings[1].sfm_max_prot, -- mappings[2].sfm_address, mappings[2].sfm_size, mappings[2].sfm_file_offset, mappings[2].sfm_init_prot, mappings[2].sfm_max_prot); --#endif -- if ( gLinkContext.verboseMapping ) -- dyld::log("dyld: shared cached file could not be mapped\n"); -- } -- } -- } -- else { -- if ( gLinkContext.verboseMapping ) -- dyld::log("dyld: shared cached file is invalid\n"); -- } -- } -- else { -- if ( gLinkContext.verboseMapping ) -- dyld::log("dyld: shared cached file cannot be read\n"); -- } -- close(fd); -- } -- else { -- if ( gLinkContext.verboseMapping ) -- dyld::log("dyld: shared cached file cannot be opened\n"); -- } -- } -- -- // remember if dyld loaded at same address as when cache built -- if ( sSharedCache != NULL ) { -- gLinkContext.dyldLoadedAtSameAddressNeededBySharedCache = ((uintptr_t)(sSharedCache->dyldBaseAddress) == (uintptr_t)&_mh_dylinker_header); -- } -- -- // tell gdb where the shared cache is -- if ( sSharedCache != NULL ) { -- const dyld_cache_mapping_info* const start = (dyld_cache_mapping_info*)((uint8_t*)sSharedCache + sSharedCache->mappingOffset); -- dyld_shared_cache_ranges.sharedRegionsCount = sSharedCache->mappingCount; -- // only room to tell gdb about first four regions -- if ( dyld_shared_cache_ranges.sharedRegionsCount > 4 ) -- dyld_shared_cache_ranges.sharedRegionsCount = 4; -- const dyld_cache_mapping_info* const end = &start[dyld_shared_cache_ranges.sharedRegionsCount]; -- int index = 0; -- for (const dyld_cache_mapping_info* p = start; p < end; ++p, ++index ) { -- dyld_shared_cache_ranges.ranges[index].start = p->address+sSharedCacheSlide; -- dyld_shared_cache_ranges.ranges[index].length = p->size; -- if ( gLinkContext.verboseMapping ) { -- dyld::log(" 0x%08llX->0x%08llX %s%s%s init=%x, max=%x\n", -- p->address+sSharedCacheSlide, p->address+sSharedCacheSlide+p->size-1, -- ((p->initProt & VM_PROT_READ) ? "read " : ""), -- ((p->initProt & VM_PROT_WRITE) ? "write " : ""), -- ((p->initProt & VM_PROT_EXECUTE) ? "execute " : ""), p->initProt, p->maxProt); -- } -- #if __i386__ -- // If a non-writable and executable region is found in the R/W shared region, then this is __IMPORT segments -- // This is an old cache. Make writable. dyld no longer supports turn W on and off as it binds -- if ( (p->initProt == (VM_PROT_READ|VM_PROT_EXECUTE)) && ((p->address & 0xF0000000) == 0xA0000000) ) { -- if ( p->size != 0 ) { -- vm_prot_t prot = VM_PROT_EXECUTE | PROT_READ | VM_PROT_WRITE; -- vm_protect(mach_task_self(), p->address, p->size, false, prot); -- if ( gLinkContext.verboseMapping ) { -- dyld::log("%18s at 0x%08llX->0x%08llX altered permissions to %c%c%c\n", "", p->address, -- p->address+p->size-1, -- (prot & PROT_READ) ? 'r' : '.', (prot & PROT_WRITE) ? 'w' : '.', (prot & PROT_EXEC) ? 'x' : '.' ); -- } -- } -- } -- #endif -- } -- if ( gLinkContext.verboseMapping ) { -- // list the code blob -- dyld_cache_header* header = (dyld_cache_header*)sSharedCache; -- uint64_t signatureSize = header->codeSignatureSize; -- // zero size in header means signature runs to end-of-file -- if ( signatureSize == 0 ) { -- struct stat stat_buf; -- // FIXME: need size of cache file actually used -- if ( my_stat(IPHONE_DYLD_SHARED_CACHE_DIR DYLD_SHARED_CACHE_BASE_NAME ARCH_NAME, &stat_buf) == 0 ) -- signatureSize = stat_buf.st_size - header->codeSignatureOffset; -- } -- if ( signatureSize != 0 ) { -- const dyld_cache_mapping_info* const last = &start[dyld_shared_cache_ranges.sharedRegionsCount-1]; -- uint64_t codeBlobStart = last->address + last->size; -- dyld::log(" 0x%08llX->0x%08llX (code signature)\n", codeBlobStart, codeBlobStart+signatureSize); -- } -- } -- #if SUPPORT_ACCELERATE_TABLES -- if ( !dylibsCanOverrideCache() && !sDisableAcceleratorTables && (sSharedCache->mappingOffset > 0x80) && (sSharedCache->accelerateInfoAddr != 0) ) { -- sAllCacheImagesProxy = ImageLoaderMegaDylib::makeImageLoaderMegaDylib(sSharedCache, sSharedCacheSlide, gLinkContext); -- } -- #endif -- } --} --#endif // #if DYLD_SHARED_CACHE_SUPPORT -- -- -- --// create when NSLinkModule is called for a second time on a bundle --ImageLoader* cloneImage(ImageLoader* image) --{ -- // open file (automagically closed when this function exits) -- FileOpener file(image->getPath()); -- -- struct stat stat_buf; -- if ( fstat(file.getFileDescriptor(), &stat_buf) == -1) -- throw "stat error"; -- -- dyld::LoadContext context; -- context.useSearchPaths = false; -- context.useFallbackPaths = false; -- context.useLdLibraryPath = false; -- context.implicitRPath = false; -- context.matchByInstallName = false; -- context.dontLoad = false; -- context.mustBeBundle = true; -- context.mustBeDylib = false; -- context.canBePIE = false; -- context.origin = NULL; -- context.rpath = NULL; -- return loadPhase6(file.getFileDescriptor(), stat_buf, image->getPath(), context); --} -- -- --ImageLoader* loadFromMemory(const uint8_t* mem, uint64_t len, const char* moduleName) --{ -- // if fat wrapper, find usable sub-file -- const fat_header* memStartAsFat = (fat_header*)mem; -- uint64_t fileOffset = 0; -- uint64_t fileLength = len; -- if ( memStartAsFat->magic == OSSwapBigToHostInt32(FAT_MAGIC) ) { -- if ( fatFindBest(memStartAsFat, &fileOffset, &fileLength) ) { -- mem = &mem[fileOffset]; -- len = fileLength; -- } -- else { -- throw "no matching architecture in universal wrapper"; -+ // call callback with all existing images -+ unsigned count = dyld::gProcessInfo->infoArrayCount; -+ const dyld_image_info* infoArray = dyld::gProcessInfo->infoArray; -+ if ( infoArray != NULL ) { -+ const mach_header* mhs[count]; -+ const char* paths[count]; -+ for (unsigned i=0; i < count; ++i) { -+ mhs[i] = infoArray[i].imageLoadAddress; -+ paths[i] = infoArray[i].imageFilePath; - } -+ dyld3::ScopedTimer timer(DBG_DYLD_TIMING_FUNC_FOR_ADD_IMAGE, (uint64_t)mhs[0], (uint64_t)func, 0); -+ func(count, mhs, paths); - } - -- // try each loader -- if ( isCompatibleMachO(mem, moduleName) ) { -- ImageLoader* image = ImageLoaderMachO::instantiateFromMemory(moduleName, (macho_header*)mem, len, gLinkContext); -- // don't add bundles to global list, they can be loaded but not linked. When linked it will be added to list -- if ( ! image->isBundle() ) -- addImage(image); -- return image; -- } -- -- // try other file formats here... -- -- // throw error about what was found -- switch (*(uint32_t*)mem) { -- case MH_MAGIC: -- case MH_CIGAM: -- case MH_MAGIC_64: -- case MH_CIGAM_64: -- throw "mach-o, but wrong architecture"; -- default: -- throwf("unknown file type, first eight bytes: 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X", -- mem[0], mem[1], mem[2], mem[3], mem[4], mem[5], mem[6],mem[7]); -- } --} -- -- --void registerAddCallback(ImageCallback func) --{ - // now add to list to get notified when any more images are added -- sAddImageCallbacks.push_back(func); -- -- // call callback with all existing images -- for (std::vector::iterator it=sAllImages.begin(); it != sAllImages.end(); it++) { -- ImageLoader* image = *it; -- if ( image->getState() >= dyld_image_state_bound && image->getState() < dyld_image_state_terminated ) -- (*func)(image->machHeader(), image->getSlide()); -- } --#if SUPPORT_ACCELERATE_TABLES -- if ( sAllCacheImagesProxy != NULL ) { -- dyld_image_info infos[allImagesCount()+1]; -- unsigned cacheCount = sAllCacheImagesProxy->appendImagesToNotify(dyld_image_state_bound, true, infos); -- for (unsigned i=0; i < cacheCount; ++i) { -- (*func)(infos[i].imageLoadAddress, sSharedCacheSlide); -- } -- } --#endif -+ sAddBulkLoadImageCallbacks.push_back(func); - } - - void registerRemoveCallback(ImageCallback func) -@@ -5626,75 +5386,81 @@ static void loadInsertedDylib(const char* path) - } - - --// --// Sets: --// sEnvMode --// gLinkContext.requireCodeSignature --// gLinkContext.processIsRestricted // Mac OS X only --// gLinkContext.processUsingLibraryValidation // Mac OS X only --// --static void configureProcessRestrictions(const macho_header* mainExecutableMH) -+static void configureProcessRestrictions(const macho_header* mainExecutableMH, const char* envp[]) - { -- uint32_t flags; --#if TARGET_IPHONE_SIMULATOR -- sEnvMode = envAll; -- gLinkContext.requireCodeSignature = true; -+ uint64_t amfiInputFlags = 0; -+#if TARGET_OS_SIMULATOR -+ amfiInputFlags |= AMFI_DYLD_INPUT_PROC_IN_SIMULATOR; -+#elif __MAC_OS_X_VERSION_MIN_REQUIRED -+ if ( hasRestrictedSegment(mainExecutableMH) ) -+ amfiInputFlags |= AMFI_DYLD_INPUT_PROC_HAS_RESTRICT_SEG; - #elif __IPHONE_OS_VERSION_MIN_REQUIRED -- sEnvMode = envNone; -- gLinkContext.requireCodeSignature = true; -- if ( csops(0, CS_OPS_STATUS, &flags, sizeof(flags)) != -1 ) { -- if ( flags & CS_ENFORCEMENT ) { -- if ( flags & CS_GET_TASK_ALLOW ) { -- // Xcode built app for Debug allowed to use DYLD_* variables -- sEnvMode = envAll; -+ if ( isFairPlayEncrypted(mainExecutableMH) ) -+ amfiInputFlags |= AMFI_DYLD_INPUT_PROC_IS_ENCRYPTED; -+#endif -+ uint64_t amfiOutputFlags = 0; -+ const char* amfiFake = nullptr; -+ if ( dyld3::internalInstall() && dyld3::BootArgs::enableDyldTestMode() ) { -+ amfiFake = _simple_getenv(envp, "DYLD_AMFI_FAKE"); -+ } -+ if ( amfiFake != nullptr ) { -+ amfiOutputFlags = hexToUInt64(amfiFake, nullptr); -+ } -+ if ( (amfiFake != nullptr) || (amfi_check_dyld_policy_self(amfiInputFlags, &amfiOutputFlags) == 0) ) { -+ gLinkContext.allowAtPaths = (amfiOutputFlags & AMFI_DYLD_OUTPUT_ALLOW_AT_PATH); -+ gLinkContext.allowEnvVarsPrint = (amfiOutputFlags & AMFI_DYLD_OUTPUT_ALLOW_PRINT_VARS); -+ gLinkContext.allowEnvVarsPath = (amfiOutputFlags & AMFI_DYLD_OUTPUT_ALLOW_PATH_VARS); -+ gLinkContext.allowEnvVarsSharedCache = (amfiOutputFlags & AMFI_DYLD_OUTPUT_ALLOW_CUSTOM_SHARED_CACHE); -+ gLinkContext.allowClassicFallbackPaths = (amfiOutputFlags & AMFI_DYLD_OUTPUT_ALLOW_FALLBACK_PATHS); -+ gLinkContext.allowInsertFailures = (amfiOutputFlags & AMFI_DYLD_OUTPUT_ALLOW_FAILED_LIBRARY_INSERTION); -+ } -+ else { -+#if __MAC_OS_X_VERSION_MIN_REQUIRED -+ // support chrooting from old kernel -+ bool isRestricted = false; -+ bool libraryValidation = false; -+ // any processes with setuid or setgid bit set or with __RESTRICT segment is restricted -+ if ( issetugid() || hasRestrictedSegment(mainExecutableMH) ) { -+ isRestricted = true; -+ } -+ bool usingSIP = (csr_check(CSR_ALLOW_TASK_FOR_PID) != 0); -+ uint32_t flags; -+ if ( csops(0, CS_OPS_STATUS, &flags, sizeof(flags)) != -1 ) { -+ // On OS X CS_RESTRICT means the program was signed with entitlements -+ if ( ((flags & CS_RESTRICT) == CS_RESTRICT) && usingSIP ) { -+ isRestricted = true; - } -- else { -- // Development kernel can use DYLD_PRINT_* variables on any FairPlay encrypted app -- uint32_t secureValue = 0; -- size_t secureValueSize = sizeof(secureValue); -- if ( (sysctlbyname("kern.secure_kernel", &secureValue, &secureValueSize, NULL, 0) == 0) && (secureValue == 0) && isFairPlayEncrypted(mainExecutableMH) ) { -- sEnvMode = envPrintOnly; -- } -+ // Library Validation loosens searching but requires everything to be code signed -+ if ( flags & CS_REQUIRE_LV ) { -+ isRestricted = false; -+ libraryValidation = true; - } - } -- else { -- // Development kernel can run unsigned code -- sEnvMode = envAll; -- gLinkContext.requireCodeSignature = false; -- } -- } -- if ( issetugid() ) { -- sEnvMode = envNone; -- } --#elif __MAC_OS_X_VERSION_MIN_REQUIRED -- sEnvMode = envAll; -- gLinkContext.requireCodeSignature = false; -- gLinkContext.processIsRestricted = false; -- gLinkContext.processUsingLibraryValidation = false; -- // any processes with setuid or setgid bit set or with __RESTRICT segment is restricted -- if ( issetugid() || hasRestrictedSegment(mainExecutableMH) ) { -- gLinkContext.processIsRestricted = true; -- } -- if ( csops(0, CS_OPS_STATUS, &flags, sizeof(flags)) != -1 ) { -- // On OS X CS_RESTRICT means the program was signed with entitlements -- if ( ((flags & CS_RESTRICT) == CS_RESTRICT) && (csr_check(CSR_ALLOW_TASK_FOR_PID) != 0) ) { -- gLinkContext.processIsRestricted = true; -- } -- // Library Validation loosens searching but requires everything to be code signed -- if ( flags & CS_REQUIRE_LV ) { -- gLinkContext.processIsRestricted = false; -- //gLinkContext.requireCodeSignature = true; -- gLinkContext.processUsingLibraryValidation = true; -- } -- } -+ gLinkContext.allowAtPaths = !isRestricted; -+ gLinkContext.allowEnvVarsPrint = !isRestricted; -+ gLinkContext.allowEnvVarsPath = !isRestricted; -+ gLinkContext.allowEnvVarsSharedCache = !libraryValidation || !usingSIP; -+ gLinkContext.allowClassicFallbackPaths = !isRestricted; -+ gLinkContext.allowInsertFailures = false; -+#else -+ halt("amfi_check_dyld_policy_self() failed\n"); - #endif -+ } - } - -+// called by _dyld_register_driverkit_main() -+void setMainEntry(void (*main)()) -+{ -+ if ( sEntryOveride == nullptr ) -+ sEntryOveride = main; -+ else -+ halt("_dyld_register_driverkit_main() may only be called once"); -+} - - bool processIsRestricted() - { - #if __MAC_OS_X_VERSION_MIN_REQUIRED -- return gLinkContext.processIsRestricted; -+ return !gLinkContext.allowEnvVarsPath; - #else - return false; - #endif -@@ -5742,14 +5516,11 @@ void notifyKernelAboutDyld() - case LC_UUID: { - // Add dyld to the kernel image info - uuid_command* uc = (uuid_command*)cmd; -- dyld_kernel_image_info_t kernelInfo; -- memcpy(kernelInfo.uuid, uc->uuid, 16); -- kernelInfo.load_addr = (uint64_t)mh; -- kernelInfo.fsobjid.fid_objno = 0; -- kernelInfo.fsobjid.fid_generation = 0; -- kernelInfo.fsid.val[0] = 0; -- kernelInfo.fsid.val[1] = 0; -- task_register_dyld_image_infos(mach_task_self(), &kernelInfo, 1); -+ char path[MAXPATHLEN]; -+ if (fsgetpath(path, MAXPATHLEN, &fsid, fsobj_id_scalar) < 0) { -+ path[0] = 0; -+ } -+ dyld3::kdebug_trace_dyld_image(DBG_DYLD_UUID_MAP_A, path, (const uuid_t *)&uc->uuid[0], fsobj_id, fsid, (const mach_header *)mh); - return; - } - } -@@ -5812,12 +5583,28 @@ static SyscallHelpers sSysCalls = { - // Added in version 6 - &abort_with_payload, - // Added in version 7 -- &task_register_dyld_image_infos, -- &task_unregister_dyld_image_infos, -- &task_get_dyld_image_infos, -- &task_register_dyld_shared_cache_image_info, -- &task_register_dyld_set_dyld_state, -- &task_register_dyld_get_process_state -+ &legacy_task_register_dyld_image_infos, -+ &legacy_task_unregister_dyld_image_infos, -+ &legacy_task_get_dyld_image_infos, -+ &legacy_task_register_dyld_shared_cache_image_info, -+ &legacy_task_register_dyld_set_dyld_state, -+ &legacy_task_register_dyld_get_process_state, -+ // Added in version 8 -+ &task_info, -+ &thread_info, -+ &kdebug_is_enabled, -+ &kdebug_trace, -+ // Added in version 9 -+ &kdebug_trace_string, -+ // Added in version 10 -+ &amfi_check_dyld_policy_self, -+ // Added in version 11 -+ ¬ifyMonitoringDyldMain, -+ ¬ifyMonitoringDyld, -+ // Add in version 12 -+ &mach_msg_destroy, -+ &mach_port_construct, -+ &mach_port_destruct - }; - - __attribute__((noinline)) -@@ -7100,32 +7806,6 @@ reloadAllImages: - #endif - - -- #if __MAC_OS_X_VERSION_MIN_REQUIRED -- // be less strict about old mach-o binaries -- uint32_t mainSDK = sMainExecutable->sdkVersion(); -- gLinkContext.strictMachORequired = (mainSDK >= DYLD_MACOSX_VERSION_10_12) || gLinkContext.processUsingLibraryValidation; -- #else -- // simulators, iOS, tvOS, and watchOS are always strict -- gLinkContext.strictMachORequired = true; -- #endif -- -- // load shared cache -- checkSharedRegionDisable(); -- #if DYLD_SHARED_CACHE_SUPPORT -- if ( gLinkContext.sharedRegionMode != ImageLoader::kDontUseSharedRegion ) { -- mapSharedCache(); -- } else { -- dyld_kernel_image_info_t kernelCacheInfo; -- bzero(&kernelCacheInfo.uuid[0], sizeof(uuid_t)); -- kernelCacheInfo.load_addr = 0; -- kernelCacheInfo.fsobjid.fid_objno = 0; -- kernelCacheInfo.fsobjid.fid_generation = 0; -- kernelCacheInfo.fsid.val[0] = 0; -- kernelCacheInfo.fsid.val[0] = 0; -- task_register_dyld_shared_cache_image_info(mach_task_self(), kernelCacheInfo, true, false); -- } -- #endif -- - #if SUPPORT_ACCELERATE_TABLES - sAllImages.reserve((sAllCacheImagesProxy != NULL) ? 16 : INITIAL_IMAGE_COUNT); - #else diff --git a/src/dyld/src/dyldInitialization.cpp.rej b/src/dyld/src/dyldInitialization.cpp.rej deleted file mode 100644 index 3ca569022..000000000 --- a/src/dyld/src/dyldInitialization.cpp.rej +++ /dev/null @@ -1,197 +0,0 @@ ---- src/dyldInitialization.cpp -+++ src/dyldInitialization.cpp -@@ -81,116 +57,48 @@ static void runDyldInitializers(const struct macho_header* mh, intptr_t slide, i - - - // --// The kernel may have slid a Position Independent Executable -+// On disk, all pointers in dyld's DATA segment are chained together. -+// They need to be fixed up to be real pointers to run. - // --static uintptr_t slideOfMainExecutable(const struct macho_header* mh) -+static void rebaseDyld(const dyld3::MachOLoaded* dyldMH) - { -- const uint32_t cmd_count = mh->ncmds; -- const struct load_command* const cmds = (struct load_command*)(((char*)mh)+sizeof(macho_header)); -- const struct load_command* cmd = cmds; -- for (uint32_t i = 0; i < cmd_count; ++i) { -- if ( cmd->cmd == LC_SEGMENT_COMMAND ) { -- const struct macho_segment_command* segCmd = (struct macho_segment_command*)cmd; -- if ( (segCmd->fileoff == 0) && (segCmd->filesize != 0)) { -- return (uintptr_t)mh - segCmd->vmaddr; -- } -- } -- cmd = (const struct load_command*)(((char*)cmd)+cmd->cmdsize); -- } -- return 0; -+ // walk all fixups chains and rebase dyld -+ const dyld3::MachOAnalyzer* ma = (dyld3::MachOAnalyzer*)dyldMH; -+ assert(ma->hasChainedFixups()); -+ uintptr_t slide = (long)ma; // all fixup chain based images have a base address of zero, so slide == load address -+ __block Diagnostics diag; -+ ma->withChainStarts(diag, 0, ^(const dyld_chained_starts_in_image* starts) { -+ ma->fixupAllChainedFixups(diag, starts, slide, dyld3::Array(), nullptr); -+ }); -+ diag.assertNoError(); -+ -+ // now that rebasing done, initialize mach/syscall layer -+ mach_init(); -+ -+ // mark __DATA_CONST segment in dyld as read-only (once fixups are done) -+ ma->forEachSegment(^(const dyld3::MachOFile::SegmentInfo& info, bool& stop) { -+ if ( info.readOnlyData ) { -+ ::mprotect(((uint8_t*)(dyldMH))+info.vmAddr, (size_t)info.vmSize, VM_PROT_READ); -+ } -+ }); - } - - --// --// If the kernel does not load dyld at its preferred address, we need to apply --// fixups to various initialized parts of the __DATA segment --// --static void rebaseDyld(const struct macho_header* mh, intptr_t slide) --{ -- // rebase non-lazy pointers (which all point internal to dyld, since dyld uses no shared libraries) -- // and get interesting pointers into dyld -- const uint32_t cmd_count = mh->ncmds; -- const struct load_command* const cmds = (struct load_command*)(((char*)mh)+sizeof(macho_header)); -- const struct load_command* cmd = cmds; -- const struct macho_segment_command* linkEditSeg = NULL; --#if __x86_64__ -- const struct macho_segment_command* firstWritableSeg = NULL; --#endif -- const struct dysymtab_command* dynamicSymbolTable = NULL; -- for (uint32_t i = 0; i < cmd_count; ++i) { -- switch (cmd->cmd) { -- case LC_SEGMENT_COMMAND: -- { -- const struct macho_segment_command* seg = (struct macho_segment_command*)cmd; -- if ( strcmp(seg->segname, "__LINKEDIT") == 0 ) -- linkEditSeg = seg; -- const struct macho_section* const sectionsStart = (struct macho_section*)((char*)seg + sizeof(struct macho_segment_command)); -- const struct macho_section* const sectionsEnd = §ionsStart[seg->nsects]; -- for (const struct macho_section* sect=sectionsStart; sect < sectionsEnd; ++sect) { -- const uint8_t type = sect->flags & SECTION_TYPE; -- if ( type == S_NON_LAZY_SYMBOL_POINTERS ) { -- // rebase non-lazy pointers (which all point internal to dyld, since dyld uses no shared libraries) -- const uint32_t pointerCount = (uint32_t)(sect->size / sizeof(uintptr_t)); -- uintptr_t* const symbolPointers = (uintptr_t*)(sect->addr + slide); -- for (uint32_t j=0; j < pointerCount; ++j) { -- symbolPointers[j] += slide; -- } -- } -- } --#if __x86_64__ -- if ( (firstWritableSeg == NULL) && (seg->initprot & VM_PROT_WRITE) ) -- firstWritableSeg = seg; --#endif -- } -- break; -- case LC_DYSYMTAB: -- dynamicSymbolTable = (struct dysymtab_command *)cmd; -- break; -- } -- cmd = (const struct load_command*)(((char*)cmd)+cmd->cmdsize); -- } -- -- // use reloc's to rebase all random data pointers --#if __x86_64__ -- const uintptr_t relocBase = firstWritableSeg->vmaddr + slide; --#else -- const uintptr_t relocBase = (uintptr_t)mh; --#endif -- const relocation_info* const relocsStart = (struct relocation_info*)(linkEditSeg->vmaddr + slide + dynamicSymbolTable->locreloff - linkEditSeg->fileoff); -- const relocation_info* const relocsEnd = &relocsStart[dynamicSymbolTable->nlocrel]; -- for (const relocation_info* reloc=relocsStart; reloc < relocsEnd; ++reloc) { -- if ( reloc->r_length != RELOC_SIZE ) -- throw "relocation in dyld has wrong size"; -- -- if ( reloc->r_type != POINTER_RELOC ) -- throw "relocation in dyld has wrong type"; -- -- // update pointer by amount dyld slid -- *((uintptr_t*)(reloc->r_address + relocBase)) += slide; -- } --} -- -- --extern "C" void mach_init(); --extern "C" void __guard_setup(const char* apple[]); -- - - // - // This is code to bootstrap dyld. This work in normally done for a program by dyld and crt. - // In dyld we have to do this manually. - // --uintptr_t start(const struct macho_header* appsMachHeader, int argc, const char* argv[], -- intptr_t slide, const struct macho_header* dyldsMachHeader, -- uintptr_t* startGlue) -+uintptr_t start(const dyld3::MachOLoaded* appsMachHeader, int argc, const char* argv[], -+ const dyld3::MachOLoaded* dyldsMachHeader, uintptr_t* startGlue) - { -+ -+ // Emit kdebug tracepoint to indicate dyld bootstrap has started -+ dyld3::kdebug_trace_dyld_marker(DBG_DYLD_TIMING_BOOTSTRAP_START, 0, 0, 0, 0); -+ - // if kernel had to slide dyld, we need to fix up load sensitive locations - // we have to do this before using any global variables -- if ( slide != 0 ) { -- rebaseDyld(dyldsMachHeader, slide); -- } -- -- // allow dyld to use mach messaging -- mach_init(); -+ rebaseDyld(dyldsMachHeader); - - // kernel sets up env pointer to be just past end of agv array - const char** envp = &argv[argc+1]; -@@ -205,37 +113,31 @@ uintptr_t start(const struct macho_header* appsMachHeader, int argc, const char* - - #if DYLD_INITIALIZER_SUPPORT - // run all C++ initializers inside dyld -- runDyldInitializers(dyldsMachHeader, slide, argc, argv, envp, apple); -+ runDyldInitializers(argc, argv, envp, apple); - #endif - - // now that we are done bootstrapping dyld, call dyld's main -- uintptr_t appsSlide = slideOfMainExecutable(appsMachHeader); -- return dyld::_main(appsMachHeader, appsSlide, argc, argv, envp, apple, startGlue); -+ uintptr_t appsSlide = appsMachHeader->getSlide(); -+ return dyld::_main((macho_header*)appsMachHeader, appsSlide, argc, argv, envp, apple, startGlue); - } - - --#if TARGET_IPHONE_SIMULATOR -+#if TARGET_OS_SIMULATOR - - extern "C" uintptr_t start_sim(int argc, const char* argv[], const char* envp[], const char* apple[], -- const macho_header* mainExecutableMH, const macho_header* dyldMH, uintptr_t dyldSlide, -+ const dyld3::MachOLoaded* mainExecutableMH, const dyld3::MachOLoaded* dyldMH, uintptr_t dyldSlide, - const dyld::SyscallHelpers*, uintptr_t* startGlue); - -- -+ - uintptr_t start_sim(int argc, const char* argv[], const char* envp[], const char* apple[], -- const macho_header* mainExecutableMH, const macho_header* dyldMH, uintptr_t dyldSlide, -+ const dyld3::MachOLoaded* mainExecutableMH, const dyld3::MachOLoaded* dyldSimMH, uintptr_t dyldSlide, - const dyld::SyscallHelpers* sc, uintptr_t* startGlue) - { -- // if simulator dyld loaded slid, it needs to rebase itself -- // we have to do this before using any global variables -- if ( dyldSlide != 0 ) { -- rebaseDyld(dyldMH, dyldSlide); -- } -+ // save table of syscall pointers -+ gSyscallHelpers = sc; - -- // save table of syscall pointers -- gSyscallHelpers = sc; -- -- // allow dyld to use mach messaging -- mach_init(); -+ // dyld_sim uses chained rebases, so it always need to be fixed up -+ rebaseDyld(dyldSimMH); - - // set up random value for stack canary - __guard_setup(apple); diff --git a/src/dyld/src/dyld_process_info.cpp.rej b/src/dyld/src/dyld_process_info.cpp.rej deleted file mode 100644 index b2c707fc8..000000000 --- a/src/dyld/src/dyld_process_info.cpp.rej +++ /dev/null @@ -1,40 +0,0 @@ ---- src/dyld_process_info.cpp -+++ src/dyld_process_info.cpp -@@ -238,28 +408,32 @@ private: - uint64_t size; - }; - -- dyld_process_info_base(unsigned imageCount, size_t totalSize); -+ dyld_process_info_base(dyld_platform_t platform, unsigned imageCount, size_t totalSize); - void* operator new (size_t, void* buf) { return buf; } - - static bool inCache(uint64_t addr) { return (addr > SHARED_REGION_BASE) && (addr < SHARED_REGION_BASE+SHARED_REGION_SIZE); } -- kern_return_t addImage(task_t task, bool sameCacheAsThisProcess, uint64_t imageAddress, uint64_t imagePath, const char* imagePathLocal); -+ bool addImage(task_t task, bool sameCacheAsThisProcess, uint64_t imageAddress, uint64_t imagePath, const char* imagePathLocal); -+ - kern_return_t addDyldImage(task_t task, uint64_t dyldAddress, uint64_t dyldPathAddress, const char* localPath); - - bool invalid() { return ((char*)_stringRevBumpPtr < (char*)_curSegment); } -- const char* copyPath(task_t task, uint64_t pathAddr, kern_return_t* kr); -- const char* addString(const char*); -+ const char* copyPath(task_t task, uint64_t pathAddr); -+ const char* addString(const char*, size_t); - const char* copySegmentName(const char*); - - void addInfoFromLoadCommands(const mach_header* mh, uint64_t addressInTask, size_t size); -+ kern_return_t addInfoFromRemoteLoadCommands(task_t task, uint64_t remoteMH); - - void inspectLocalImageLoadCommands(uint64_t imageAddress, void* func); - kern_return_t inspectRemoteImageLoadCommands(task_t task, uint64_t imageAddress, void* func); - -- mutable uint32_t _retainCount; -+ mutable std::atomic _retainCount; - const uint32_t _cacheInfoOffset; - const uint32_t _stateInfoOffset; - const uint32_t _imageInfosOffset; - const uint32_t _segmentInfosOffset; -+ size_t _freeSpace; -+ dyld_platform_t _platform; - ImageInfo* const _firstImage; - ImageInfo* _curImage; - SegmentInfo* const _firstSegment; diff --git a/tools/debian/make-deb b/tools/debian/make-deb index bd144e004..808bed9dc 100755 --- a/tools/debian/make-deb +++ b/tools/debian/make-deb @@ -17,4 +17,4 @@ else ARG='-b' fi -debuild -us -uc ${ARG} +debuild -us -uc --no-lintian ${ARG}