Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 | /* * Copyright (c) 2008 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@ */ /* * objc-selopt.h * Interface between libobjc and dyld * for selector uniquing in the dyld shared cache. * * When building the shared cache, dyld locates all selectors and selector * references in the cached images. It builds a perfect hash table out of * them and writes the table into the shared cache copy of libobjc. * libobjc then uses that table as the builtin selector list. * * Versioning * The table has a version number. dyld and objc can both ignore the table * if the other used the wrong version number. * * Completeness * Not all libraries are in the shared cache. Libraries that are in the * shared cache and were optimized are specially marked. Libraries on * disk never include those marks. * * Coherency * Libraries optimized in the shared cache can be replaced by unoptimized * copies from disk when loaded. The copy from disk is not marked and will * be fixed up by libobjc. The shared cache copy is still mapped into the * process, so the table can point to cstring data in that library's part * of the shared cache without trouble. * * Atomicity * dyld writes the table itself last. If dyld marks some metadata as * updated but then fails to write a table for some reason, libobjc * fixes up all metadata as if it were not marked. */ #ifndef _OBJC_SELOPT_H #define _OBJC_SELOPT_H #include <stdint.h> #include <stdlib.h> // Tell libobjc that this dyld is built for large caches // This really means the dyld SPIs are going to visit shared cache hash tables #define DYLD_LARGE_SHARED_CACHE_SUPPORT 1 namespace objc { class SelectorHashTable; class ClassHashTable; class ProtocolHashTable; } namespace objc_opt { // Precomputed image list. struct objc_headeropt_ro_t; // Precomputed image list. struct objc_headeropt_rw_t; // Edit objc-sel-table.s if you change this value. // lldb and Symbolication read these structures. Inform them of any changes. enum { VERSION = 16 }; // Values for objc_opt_t::flags enum : uint32_t { IsProduction = (1 << 0), // never set in development cache NoMissingWeakSuperclasses = (1 << 1), // set in development cache and customer LargeSharedCache = (1 << 2), // Shared cache was built with the new Large format }; // Top-level optimization structure. // Edit objc-sel-table.s if you change this structure. struct alignas(alignof(uint64_t)) objc_opt_t { uint32_t version; uint32_t flags; int32_t selopt_offset; int32_t headeropt_ro_offset; int32_t unused_clsopt_offset; int32_t unused_protocolopt_offset; // This is now 0 as we've moved to the new protocolopt_offset int32_t headeropt_rw_offset; int32_t unused_protocolopt2_offset; int32_t largeSharedCachesClassOffset; int32_t largeSharedCachesProtocolOffset; int64_t relativeMethodSelectorBaseAddressOffset; // Relative method list selectors are offsets from this address const objc::SelectorHashTable* selectorOpt() const { if (selopt_offset == 0) return NULL; return (objc::SelectorHashTable *)((uint8_t *)this + selopt_offset); } struct objc_headeropt_ro_t* headeropt_ro() const { if (headeropt_ro_offset == 0) return NULL; return (struct objc_headeropt_ro_t *)((uint8_t *)this + headeropt_ro_offset); } void* oldClassOpt() const { if (unused_clsopt_offset == 0) return NULL; return (void *)((uint8_t *)this + unused_clsopt_offset); } void* protocolopt() const { return NULL; } void* oldProtocolOpt2() const { if (unused_protocolopt2_offset == 0) return NULL; return (void *)((uint8_t *)this + unused_protocolopt2_offset); } struct objc_headeropt_rw_t* headeropt_rw() const { if (headeropt_rw_offset == 0) return NULL; return (struct objc_headeropt_rw_t *)((uint8_t *)this + headeropt_rw_offset); } const objc::ClassHashTable* classOpt() const { if (largeSharedCachesClassOffset == 0) return NULL; return (objc::ClassHashTable *)((uint8_t *)this + largeSharedCachesClassOffset); } const objc::ProtocolHashTable* protocolOpt() const { if (largeSharedCachesProtocolOffset == 0) return NULL; return (objc::ProtocolHashTable *)((uint8_t *)this + largeSharedCachesProtocolOffset); } const void* relativeMethodListsBaseAddress() const { if (relativeMethodSelectorBaseAddressOffset == 0) return NULL; return (const void*)((uint8_t *)this + relativeMethodSelectorBaseAddressOffset); } }; // sizeof(objc_opt_t) must be pointer-aligned static_assert(sizeof(objc_opt_t) % sizeof(void*) == 0); // List of offsets in libobjc that the shared cache optimization needs to use. template <typename T> struct objc_opt_pointerlist_tt { T protocolClass; }; typedef struct objc_opt_pointerlist_tt<uintptr_t> objc_opt_pointerlist_t; } // namespace objc_opt #endif |