Loading...
cache_builder/Optimizers.cpp dyld-1340 /dev/null
--- dyld/dyld-1340/cache_builder/Optimizers.cpp
+++ /dev/null
@@ -1,551 +0,0 @@
-/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*-
-*
-* Copyright (c) 2017 Apple Inc. All rights reserved.
-*
-* @APPLE_LICENSE_HEADER_START@
-*
-* This file contains Original Code and/or Modifications of Original Code
-* as defined in and that are subject to the Apple Public Source License
-* Version 2.0 (the 'License'). You may not use this file except in
-* compliance with the License. Please obtain a copy of the License at
-* http://www.opensource.apple.com/apsl/ and read it before using this
-* file.
-*
-* The Original Code and all software distributed under the License are
-* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
-* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
-* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
-* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
-* Please see the License for the specific language governing rights and
-* limitations under the License.
-*
-* @APPLE_LICENSE_HEADER_END@
-*/
-
-#include "Optimizers.h"
-
-using namespace cache_builder;
-
-
-//
-// MARK: --- StubOptimizer methods ---
-//
-
-// These are functions that are interposed by Instruments.app or ASan or libRPAC.dylib
-const char* const neverStubEliminateSymbols[] = {
-    "___bzero",
-    "___cxa_atexit",
-    "___cxa_throw",
-    "__longjmp",
-    "__objc_autoreleasePoolPop",
-    "_accept",
-    "_access",
-    "_asctime",
-    "_asctime_r",
-    "_asprintf",
-    "_atoi",
-    "_atol",
-    "_atoll",
-    "_calloc",
-    "_chmod",
-    "_chown",
-    "_close",
-    "_confstr",
-    "_cp_drawable_present",
-    "_cp_drawable_encode_present",
-    "_cp_drawable_enqueue_present",
-    "_CGImageDestinationFinalize",
-    "_CGImageSourceCreateThumbnailAtIndex",
-    "_CGImageSourceCreateImageAtIndex",
-    "_ctime",
-    "_ctime_r",
-    "_dispatch_after",
-    "_dispatch_after_f",
-    "_dispatch_async",
-    "_dispatch_async_f",
-    "_dispatch_barrier_async_f",
-    "_dispatch_group_async",
-    "_dispatch_group_async_f",
-    "_dispatch_source_set_cancel_handler",
-    "_dispatch_source_set_event_handler",
-    "_dispatch_sync_f",
-    "_dlclose",
-    "_dlopen",
-    "_dlsym",
-    "_dup",
-    "_dup2",
-    "_endgrent",
-    "_endpwent",
-    "_ether_aton",
-    "_ether_hostton",
-    "_ether_line",
-    "_ether_ntoa",
-    "_ether_ntohost",
-    "_fchmod",
-    "_fchown",
-    "_fclose",
-    "_fdopen",
-    "_fflush",
-    "_fopen",
-    "_fork",
-    "_fprintf",
-    "_free",
-    "_freopen",
-    "_frexp",
-    "_frexpf",
-    "_frexpl",
-    "_fscanf",
-    "_fstat",
-    "_fstatfs",
-    "_fstatfs64",
-    "_fsync",
-    "_ftime",
-    "_getaddrinfo",
-    "_getattrlist",
-    "_getcwd",
-    "_getgrent",
-    "_getgrgid",
-    "_getgrgid_r",
-    "_getgrnam",
-    "_getgrnam_r",
-    "_getgroups",
-    "_gethostbyaddr",
-    "_gethostbyname",
-    "_gethostbyname2",
-    "_gethostent",
-    "_getifaddrs",
-    "_getitimer",
-    "_getnameinfo",
-    "_getpass",
-    "_getpeername",
-    "_getpwent",
-    "_getpwnam",
-    "_getpwnam_r",
-    "_getpwuid",
-    "_getpwuid_r",
-    "_getsockname",
-    "_getsockopt",
-    "_gmtime",
-    "_gmtime_r",
-    "_if_indextoname",
-    "_if_nametoindex",
-    "_index",
-    "_inet_aton",
-    "_inet_ntop",
-    "_inet_pton",
-    "_initgroups",
-    "_ioctl",
-    "_lchown",
-    "_lgamma",
-    "_lgammaf",
-    "_lgammal",
-    "_link",
-    "_listxattr",
-    "_localtime",
-    "_localtime_r",
-    "_longjmp",
-    "_lseek",
-    "_lstat",
-    "_malloc",
-    "_malloc_create_zone",
-    "_malloc_default_purgeable_zone",
-    "_malloc_default_zone",
-    "_malloc_destroy_zone",
-    "_malloc_good_size",
-    "_malloc_make_nonpurgeable",
-    "_malloc_make_purgeable",
-    "_malloc_set_zone_name",
-    "_malloc_zone_from_ptr",
-    "_mbsnrtowcs",
-    "_mbsrtowcs",
-    "_mbstowcs",
-    "_memchr",
-    "_memcmp",
-    "_memcpy",
-    "_memmove",
-    "_memset",
-    "_mktime",
-    "_mlock",
-    "_mlockall",
-    "_modf",
-    "_modff",
-    "_modfl",
-    "_mprotect",
-    "_munlock",
-    "_munlockall",
-    "_objc_autoreleasePoolPop",
-    "_objc_setProperty",
-    "_objc_setProperty_atomic",
-    "_objc_setProperty_atomic_copy",
-    "_objc_setProperty_nonatomic",
-    "_objc_setProperty_nonatomic_copy",
-    "_objc_storeStrong",
-    "_open",
-    "_opendir",
-    "_poll",
-    "_posix_memalign",
-    "_pread",
-    "_printf",
-    "_pthread_attr_getdetachstate",
-    "_pthread_attr_getguardsize",
-    "_pthread_attr_getinheritsched",
-    "_pthread_attr_getschedparam",
-    "_pthread_attr_getschedpolicy",
-    "_pthread_attr_getscope",
-    "_pthread_attr_getstack",
-    "_pthread_attr_getstacksize",
-    "_pthread_cond_broadcast",
-    "_pthread_condattr_getpshared",
-    "_pthread_cond_signal",
-    "_pthread_cond_signal_thread_np",
-    "_pthread_cond_timedwait_relative_np",
-    "_pthread_cond_timedwait",
-    "_pthread_cond_wait",
-    "_pthread_create",
-    "_pthread_getschedparam",
-    "_pthread_join",
-    "_pthread_mutex_lock",
-    "_pthread_mutex_unlock",
-    "_pthread_mutexattr_getprioceiling",
-    "_pthread_mutexattr_getprotocol",
-    "_pthread_mutexattr_getpshared",
-    "_pthread_mutexattr_gettype",
-    "_pthread_rwlockattr_getpshared",
-    "_pthread_rwlock_rdlock",
-    "_pthread_rwlock_wrlock",
-    "_pthread_rwlock_unlock",
-    "_pwrite",
-    "_rand_r",
-    "_read",
-    "_readdir",
-    "_readdir_r",
-    "_readv",
-    "_readv$UNIX2003",
-    "_realloc",
-    "_realpath",
-    "_recv",
-    "_recvfrom",
-    "_recvmsg",
-    "_remquo",
-    "_remquof",
-    "_remquol",
-    "_scanf",
-    "_send",
-    "_sendmsg",
-    "_sendto",
-    "_setattrlist",
-    "_setgrent",
-    "_setitimer",
-    "_setlocale",
-    "_setpwent",
-    "_shm_open",
-    "_shm_unlink",
-    "_sigaction",
-    "_sigemptyset",
-    "_sigfillset",
-    "_siglongjmp",
-    "_signal",
-    "_sigpending",
-    "_sigprocmask",
-    "_sigwait",
-    "_snprintf",
-    "_sprintf",
-    "_sqlite3_close",
-    "_sqlite3_close_v2",
-    "_sqlite3_exec",
-    "_sqlite3_exec_b",
-    "_sqlite3_finalize",
-    "_sqlite3_open",
-    "_sqlite3_open16",
-    "_sqlite3_open_v2",
-    "_sqlite3_prepare",
-    "_sqlite3_prepare16",
-    "_sqlite3_prepare16_v2",
-    "_sqlite3_prepare16_v3",
-    "_sqlite3_prepare_v2",
-    "_sqlite3_prepare_v3",
-    "_sqlite3_step",
-    "_sqlite3_wal_autocheckpoint",
-    "_sqlite3_wal_checkpoint",
-    "_sqlite3_wal_checkpoint_v2",
-    "_sqlite3_wal_hook",
-    "_sscanf",
-    "_stat",
-    "_statfs",
-    "_statfs64",
-    "_strcasecmp",
-    "_strcat",
-    "_strchr",
-    "_strcmp",
-    "_strcpy",
-    "_strdup",
-    "_strerror",
-    "_strerror_r",
-    "_strlen",
-    "_strncasecmp",
-    "_strncat",
-    "_strncmp",
-    "_strncpy",
-    "_strptime",
-    "_strtoimax",
-    "_strtol",
-    "_strtoll",
-    "_strtoumax",
-    "_tempnam",
-    "_time",
-    "_times",
-    "_tmpnam",
-    "_tsearch",
-    "_unlink",
-    "_valloc",
-    "_vasprintf",
-    "_vfprintf",
-    "_vfscanf",
-    "_vprintf",
-    "_vscanf",
-    "_vsnprintf",
-    "_vsprintf",
-    "_vsscanf",
-    "_wait",
-    "_wait$UNIX2003",
-    "_wait3",
-    "_wait4",
-    "_waitid",
-    "_waitid$UNIX2003",
-    "_waitpid",
-    "_waitpid$UNIX2003",
-    "_wcslen",
-    "_wcsnrtombs",
-    "_wcsrtombs",
-    "_wcstombs",
-    "_wordexp",
-    "_write",
-    "_writev",
-    "_writev$UNIX2003",
-    "___pwrite_nocancel",
-    "___pwritev_nocancel",
-    "___write_nocancel",
-    "___writev_nocancel",
-    "_pwrite$NOCANCEL",
-    "_pwritev$NOCANCEL",
-    "_write$NOCANCEL",
-    "_writev$NOCANCEL",
-    "_xpc_connection_send_message_with_reply_sync",
-    "__dyld_register_func_for_add_image",
-    "__dyld_register_func_for_remove_image",
-    // <rdar://problem/22050956> always use stubs for C++ symbols that can be overridden
-    "__ZdaPv",
-    "__ZdlPv",
-    "__Znam",
-    "__Znwm",
-    "__ZnwmSt19__type_descriptor_t",
-    "__ZnamSt19__type_descriptor_t",
-
-    nullptr
-};
-
-void StubOptimizer::addDefaultSymbols()
-{
-    for (const char* const* p=neverStubEliminateSymbols; *p != nullptr; ++p)
-        neverStubEliminate.insert(*p);
-}
-
-
-uint64_t StubOptimizer::gotAddrFromArm64Stub(Diagnostics& diag, std::string_view dylibID,
-                                             const uint8_t* stubInstructions, uint64_t stubVMAddr)
-{
-    uint32_t stubInstr1 = *(uint32_t*)stubInstructions;
-    if ( (stubInstr1 & 0x9F00001F) != 0x90000010 ) {
-        diag.warning("first instruction of stub (0x%08X) is not ADRP for stub at addr 0x%0llX in %s",
-                     stubInstr1, (uint64_t)stubVMAddr, dylibID.data());
-        return 0;
-    }
-    int32_t adrpValue = ((stubInstr1 & 0x00FFFFE0) >> 3) | ((stubInstr1 & 0x60000000) >> 29);
-    if ( stubInstr1 & 0x00800000 )
-        adrpValue |= 0xFFF00000;
-    uint32_t stubInstr2 = *(uint32_t*)(stubInstructions + 4);
-    if ( (stubInstr2 & 0xFFC003FF) != 0xF9400210 ) {
-        diag.warning("second instruction of stub (0x%08X) is not LDR for stub at addr 0x%0llX in %s",
-                     stubInstr2, (uint64_t)stubVMAddr, dylibID.data());
-        return 0;
-    }
-    uint32_t ldrValue = ((stubInstr2 >> 10) & 0x00000FFF);
-    return (stubVMAddr & (-4096)) + adrpValue*4096 + ldrValue*8;
-}
-
-void StubOptimizer::generateArm64StubTo(uint8_t* stubBuffer, uint64_t stubVMAddr,
-                                         uint64_t gotVMAddr, uint64_t targetVMAddr)
-{
-    int64_t adrpDelta = (targetVMAddr & -4096) - (stubVMAddr & -4096);
-    if ( std::abs(adrpDelta) > 0xFFFFE000 ) {
-        generateArm64StubToGOT(stubBuffer, stubVMAddr, gotVMAddr);
-        return;
-    }
-    uint32_t immhi   = (adrpDelta >> 9) & (0x00FFFFE0);
-    uint32_t immlo   = (adrpDelta << 17) & (0x60000000);
-    uint32_t newADRP = (0x90000010) | immlo | immhi;
-    uint32_t off12   = (targetVMAddr & 0xFFF);
-    uint32_t newADD  = (0x91000210) | (off12 << 10);
-
-    uint32_t* stubInstructions = (uint32_t*)stubBuffer;
-    stubInstructions[0] = newADRP;     //      ADRP   X16, target@page
-    stubInstructions[1] = newADD;      //      ADD    X16, X16, target@pageoff
-    stubInstructions[2] = 0xD61F0200;  //      BR     X16
-}
-
-void StubOptimizer::generateArm64StubToGOT(uint8_t* stubBuffer,
-                                           uint64_t stubVMAddr, uint64_t gotVMAddr)
-{
-    int64_t adrpDelta = (gotVMAddr & -4096) - (stubVMAddr & -4096);
-
-    uint32_t immhi   = (adrpDelta >> 9) & (0x00FFFFE0);
-    uint32_t immlo   = (adrpDelta << 17) & (0x60000000);
-    uint32_t newADRP = (0x90000010) | immlo | immhi;
-    uint32_t off12   = (gotVMAddr & 0xFFF) >> 3;
-    uint32_t newLDR  = (0xF9400210) | (off12 << 10);
-
-    uint32_t* stubInstructions = (uint32_t*)stubBuffer;
-    stubInstructions[0] = newADRP;     // ADRP  X16, lazy_pointer@page
-    stubInstructions[1] = newLDR;      // LDR   X16, [X16, lazy_pointer@pageoff]
-    stubInstructions[2] = 0xD61F0200;  // BR    X16
-}
-
-uint64_t StubOptimizer::gotAddrFromArm64_32Stub(Diagnostics& diag, std::string_view dylibID,
-                                                const uint8_t* stubInstructions, uint64_t stubVMAddr)
-{
-    uint32_t stubInstr1 = *(uint32_t*)stubInstructions;
-    if ( (stubInstr1 & 0x9F00001F) != 0x90000010 ) {
-        diag.warning("first instruction of stub (0x%08X) is not ADRP for stub at addr 0x%0llX in %s",
-                     stubInstr1, (uint64_t)stubVMAddr, dylibID.data());
-        return 0;
-    }
-    int32_t adrpValue = ((stubInstr1 & 0x00FFFFE0) >> 3) | ((stubInstr1 & 0x60000000) >> 29);
-    if ( stubInstr1 & 0x00800000 )
-        adrpValue |= 0xFFF00000;
-    uint32_t stubInstr2 = *(uint32_t*)(stubInstructions + 4);
-    if ( (stubInstr2 & 0xFFC003FF) != 0xB9400210 ) {
-        diag.warning("second instruction of stub (0x%08X) is not LDR for stub at addr 0x%0llX in %s",
-                     stubInstr2, (uint64_t)stubVMAddr, dylibID.data());
-        return 0;
-    }
-    uint32_t ldrValue = ((stubInstr2 >> 10) & 0x00000FFF);
-    return (stubVMAddr & (-4096)) + adrpValue*4096 + ldrValue*4; // LDR Wn has a scale factor of 4
-
-}
-
-void StubOptimizer::generateArm64_32StubTo(uint8_t* stubBuffer,
-                                        uint64_t stubVMAddr, uint64_t targetVMAddr)
-{
-    int64_t adrpDelta = (targetVMAddr & -4096) - (stubVMAddr & -4096);
-
-    uint32_t immhi   = (adrpDelta >> 9) & (0x00FFFFE0);
-    uint32_t immlo   = (adrpDelta << 17) & (0x60000000);
-    uint32_t newADRP = (0x90000010) | immlo | immhi;
-    uint32_t off12   = (targetVMAddr & 0xFFF);
-    uint32_t newADD  = (0x91000210) | (off12 << 10);
-
-    uint32_t* stubInstructions = (uint32_t*)stubBuffer;
-    stubInstructions[0] = newADRP;     //      ADRP   X16, target@page
-    stubInstructions[1] = newADD;      //      ADD    X16, X16, target@pageoff
-    stubInstructions[2] = 0xD61F0200;  //      BR     X16
-}
-
-void StubOptimizer::generateArm64_32StubToGOT(uint8_t* stubBuffer,
-                                              uint64_t stubVMAddr, uint64_t gotVMAddr)
-{
-    int64_t adrpDelta = (gotVMAddr & -4096) - (stubVMAddr & -4096);
-
-    uint32_t immhi   = (adrpDelta >> 9) & (0x00FFFFE0);
-    uint32_t immlo   = (adrpDelta << 17) & (0x60000000);
-    uint32_t newADRP = (0x90000010) | immlo | immhi;
-    uint32_t off12   = (gotVMAddr & 0xFFF) >> 2;
-    uint32_t newLDR  = (0xB9400210) | (off12 << 10);
-
-    uint32_t* stubInstructions = (uint32_t*)stubBuffer;
-    stubInstructions[0] = newADRP;     // ADRP  X16, lazy_pointer@page
-    stubInstructions[1] = newLDR;      // LDR   W16, [X16, lazy_pointer@pageoff]
-    stubInstructions[2] = 0xD61F0200;  // BR    X16
-}
-
-uint64_t StubOptimizer::gotAddrFromArm64eStub(Diagnostics& diag, std::string_view dylibID,
-                                              const uint8_t* stubInstructions, uint64_t stubVMAddr)
-{
-    uint32_t stubInstr1 = *(uint32_t*)stubInstructions;
-    // ADRP  X17, dyld_ImageLoaderCache@page
-    if ( (stubInstr1 & 0x9F00001F) != 0x90000011 ) {
-        diag.warning("first instruction of stub (0x%08X) is not ADRP for stub at addr 0x%0llX in %s",
-                     stubInstr1, (uint64_t)stubVMAddr, dylibID.data());
-        return 0;
-    }
-    int32_t adrpValue = ((stubInstr1 & 0x00FFFFE0) >> 3) | ((stubInstr1 & 0x60000000) >> 29);
-    if ( stubInstr1 & 0x00800000 )
-        adrpValue |= 0xFFF00000;
-
-    // ADD     X17, X17, dyld_ImageLoaderCache@pageoff
-    uint32_t stubInstr2 = *(uint32_t*)(stubInstructions + 4);
-    if ( (stubInstr2 & 0xFFC003FF) != 0x91000231 ) {
-        diag.warning("second instruction of stub (0x%08X) is not ADD for stub at addr 0x%0llX in %s",
-                     stubInstr2, (uint64_t)stubVMAddr, dylibID.data());
-        return 0;
-    }
-    uint32_t addValue = ((stubInstr2 & 0x003FFC00) >> 10);
-
-    // LDR   X16, [X17]
-    uint32_t stubInstr3 = *(uint32_t*)(stubInstructions + 8);
-    if ( stubInstr3 != 0xF9400230 ) {
-        diag.warning("second instruction of stub (0x%08X) is not LDR for stub at addr 0x%0llX in %s",
-                     stubInstr2, (uint64_t)stubVMAddr, dylibID.data());
-        return 0;
-    }
-    return (stubVMAddr & (-4096)) + adrpValue*4096 + addValue;
-}
-
-void StubOptimizer::generateArm64eStubTo(uint8_t* stubBuffer, uint64_t stubVMAddr,
-                                         uint64_t gotVMAddr, uint64_t targetVMAddr)
-{
-    int64_t adrpDelta = (targetVMAddr & -4096) - (stubVMAddr & -4096);
-    if ( std::abs(adrpDelta) > 0xFFFFE000 ) {
-        generateArm64eStubToGOT(stubBuffer, stubVMAddr, gotVMAddr);
-        return;
-    }
-    uint32_t immhi   = (adrpDelta >> 9) & (0x00FFFFE0);
-    uint32_t immlo   = (adrpDelta << 17) & (0x60000000);
-    uint32_t newADRP = (0x90000010) | immlo | immhi;
-    uint32_t off12   = (targetVMAddr & 0xFFF);
-    uint32_t newADD  = (0x91000210) | (off12 << 10);
-
-    uint32_t* stubInstructions = (uint32_t*)stubBuffer;
-    stubInstructions[0] = newADRP;     //      ADRP   X16, target@page
-    stubInstructions[1] = newADD;      //      ADD    X16, X16, target@pageoff
-    stubInstructions[2] = 0xD61F0200;  //      BR     X16
-    stubInstructions[3] = 0xD4200020;  //      TRAP
-}
-
-void StubOptimizer::generateArm64eStubToGOT(uint8_t* stubBuffer,
-                                            uint64_t stubVMAddr, uint64_t gotVMAddr)
-{
-    int64_t adrpDelta = (gotVMAddr & -4096) - (stubVMAddr & -4096);
-
-    uint32_t immhi   = (adrpDelta >> 9) & (0x00FFFFE0);
-    uint32_t immlo   = (adrpDelta << 17) & (0x60000000);
-    uint32_t newADRP = (0x90000011) | immlo | immhi;
-    uint32_t off12   = (gotVMAddr & 0xFFF);
-    uint32_t newADD  = (0x91000231) | (off12 << 10);
-
-    uint32_t* stubInstructions = (uint32_t*)stubBuffer;
-    stubInstructions[0] = newADRP;     // ADRP  X17, lazy_pointer@page
-    stubInstructions[1] = newADD;      // ADD   X17, X17, lazy_pointer@pageoff
-    stubInstructions[2] = 0xF9400230;  // LDR   X16, [X17]
-    stubInstructions[3] = 0xD71F0A11;  // BRAA  X16, X17
-}
-
-//
-// MARK: --- UniquedGOTsOptimizer methods ---
-//
-void UniquedGOTsOptimizer::forEachFunctionVariant(void (^callback)(const CoalescedGOTSection::FunctionVariantInfo& tv, uint64_t gotVMAddr,
-                                                                   dyld3::MachOFile::PointerMetaData pmd)) const
-{
-    this->regularGOTs.forEachFunctionVariant(callback);
-    this->authGOTs.forEachFunctionVariant(callback);
-    this->authPtrs.forEachFunctionVariant(callback);
-}