]> git.saurik.com Git - apple/dyld.git/blob - dyld3/LaunchCacheFormat.h
dyld-519.2.2.tar.gz
[apple/dyld.git] / dyld3 / LaunchCacheFormat.h
1 /*
2 * Copyright (c) 2017 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24
25
26 #ifndef LaunchCacheFormat_h
27 #define LaunchCacheFormat_h
28
29
30 #include <stdint.h>
31 #include <assert.h>
32 #include <uuid/uuid.h>
33 #include <mach/mach.h>
34
35 #include "LaunchCache.h"
36
37
38 namespace dyld3 {
39 namespace launch_cache {
40 namespace binary_format {
41
42
43 // bump this number each time binary format changes
44 enum { kFormatVersion = 8 };
45
46 union VIS_HIDDEN ImageRef {
47 ImageRef() : val(0xFFFFFFFF) { }
48 ImageRef(uint8_t kind, uint32_t groupNum, uint32_t indexInGroup) : _linkKind(kind), _groupNum(groupNum), _indexInGroup(indexInGroup) {
49 assert(groupNum < (1 << 18));
50 assert(indexInGroup < (1 << 12));
51 }
52 uint8_t kind() const { return _linkKind; }
53 uint32_t groupNum() const { return _groupNum; }
54 uint32_t indexInGroup() const { return _indexInGroup; }
55 uint16_t value() const { return val; }
56 void clearKind() { _linkKind = 0; }
57
58 bool operator==(const ImageRef& rhs) const {
59 return (val == rhs.val);
60 }
61 bool operator!=(const ImageRef& rhs) const {
62 return (val != rhs.val);
63 }
64 static ImageRef weakImportMissing();
65 static ImageRef makeEmptyImageRef() { return ImageRef(); }
66
67 private:
68 ImageRef(uint32_t v) : val(v) { }
69
70 uint32_t val;
71 struct {
72 uint32_t _linkKind : 2, // Image::LinkKind
73 _groupNum : 18, // 0 => cached dylib group, 1 => other dylib group, 2 => main closure, etc
74 _indexInGroup : 12; // max 64K images in group
75 };
76 };
77
78
79
80
81 // In disk based images, all segments are multiples of page size
82 // This struct just tracks the size (disk and vm) of each segment.
83 // This is compact for most every image which have contiguous segments.
84 // If the image does not have contiguous segments (rare), an extra
85 // DiskSegment is inserted with the paddingNotSeg bit set.
86 struct DiskSegment
87 {
88 uint64_t filePageCount : 30,
89 vmPageCount : 30,
90 permissions : 3,
91 paddingNotSeg : 1;
92 };
93
94
95 // In cache DATA_DIRTY is not page aligned or sized
96 // This struct allows segments with any alignment and up to 256MB in size
97 struct DyldCacheSegment
98 {
99 uint64_t cacheOffset : 32,
100 size : 28,
101 permissions : 4;
102 };
103
104 // When an Image is built on the device, the mtime and inode are recorded.
105 // When built off device, the first 16 bytes of SHA1 of CodeDirectory is recorded.
106 union FileInfo
107 {
108 struct {
109 uint64_t mtime;
110 uint64_t inode;
111 } statInfo;
112 struct {
113 uint8_t bytes[16];
114 } cdHash16;
115 };
116
117 struct Image
118 {
119 uint32_t isDiskImage : 1, // images are DiskImage - not Image
120 isInvalid : 1, // an error occurred creating the info for this image
121 has16KBpages : 1,
122 hasTextRelocs : 1,
123 hasObjC : 1,
124 mayHavePlusLoads : 1,
125 isEncrypted : 1, // image is DSMOS or FairPlay encrypted
126 hasWeakDefs : 1,
127 neverUnload : 1,
128 cwdSameAsThis : 1, // dylibs use file system relative paths, cwd must be main's dir
129 isPlatformBinary : 1, // part of OS - can be loaded into LV process
130 isBundle : 1,
131 overridableDylib : 1, // only applicable to group 0
132 padding : 7,
133 maxLoadCount : 12;
134 int32_t groupOffset; // back pointer to containing ImageGroup (from start of Image)
135 uint32_t pathPoolOffset;
136 uint32_t pathHash;
137 FileInfo fileInfo;
138 uuid_t uuid;
139 uint16_t dependentsArrayStartIndex;
140 uint16_t dependentsArrayCount;
141 uint16_t segmentsArrayStartIndex;
142 uint16_t segmentsArrayCount;
143 uint16_t initBeforeArrayStartIndex;
144 uint16_t initBeforeArrayCount;
145 uint16_t initOffsetsArrayStartIndex;
146 uint16_t initOffsetsArrayCount;
147 uint16_t dofOffsetsArrayStartIndex;
148 uint16_t dofOffsetsArrayCount;
149 };
150
151 // an image in the dyld shared cache
152 struct CachedImage : public Image
153 {
154 uint32_t patchStartIndex;
155 uint32_t patchCount;
156 };
157
158 // an image not in the dyld shared cache (loaded from disk at runtime)
159 struct DiskImage : public Image
160 {
161 uint32_t totalVmPages;
162 uint32_t sliceOffsetIn4K;
163 uint32_t codeSignFileOffset;
164 uint32_t codeSignFileSize;
165 uint32_t fixupsPoolOffset : 28, // offset in ImageGroup's pool for AllFixupsBySegment
166 fixupsPoolSegCount : 4; // count of segments in AllFixupsBySegment for this image
167 uint32_t fairPlayTextPageCount : 28,
168 fairPlayTextStartPage : 4;
169 uint32_t targetsArrayStartIndex; // index in ImageGroup's pool of OrdinalEntry
170 uint32_t targetsArrayCount;
171 };
172
173
174 // if an Image has an alias (symlink to it), the Image does not record the alias, but the ImageGroup does
175 struct AliasEntry
176 {
177 uint32_t aliasHash;
178 uint32_t imageIndexInGroup;
179 uint32_t aliasOffsetInStringPool;
180 };
181
182 // each DiskImage points to an array of these, one per segment with fixups
183 struct AllFixupsBySegment
184 {
185 uint32_t segIndex : 4,
186 offset : 28; // from start of AllFixupsBySegment to this seg's SegmentFixupsByPage
187 };
188
189
190 // This struct is suitable for passing into kernel when kernel supports fixups on page-in.
191 struct SegmentFixupsByPage
192 {
193 uint32_t size; // of this struct, including fixup opcodes
194 uint32_t pageSize; // 0x1000 or 0x4000
195 uint32_t pageCount;
196 uint32_t pageInfoOffsets[1]; // array size is pageCount
197 // each page info is a FixUpOpcode[]
198 };
199
200 enum class FixUpOpcode : uint8_t {
201 done = 0x00,
202 // apply = 0x10,
203 rebase32 = 0x10, // add32 slide at current pageOffset, increment pageOffset by 4
204 rebase64 = 0x11, // add64 slide at current pageOffset, increment pageOffset by 8
205 bind32 = 0x12, // set 32-bit ordinal value at current pageOffset, increment pageOffset by 4
206 bind64 = 0x13, // set 64-bit ordinal value at current pageOffset, increment pageOffset by 8
207 rebaseText32 = 0x14, // add32 slide at current text pageOffset, increment pageOffset by 4
208 bindText32 = 0x15, // set 32-bit ordinal value at current text pageOffset, increment pageOffset by 4
209 bindTextRel32 = 0x16, // set delta to 32-bit ordinal value at current text pageOffset, increment pageOffset by 4 (i386 CALL to dylib)
210 bindImportJmp32 = 0x17, // set delta to 32-bit ordinal value at current text pageOffset, increment pageOffset by 4 (i386 JMP to dylib)
211 // fixupChain64 = 0x18, // current page offset is start of a chain of locations to fix up
212 // adjPageOffset = 0x20,
213 setPageOffset = 0x20, // low 4-bits is amount to increment (1 to 15). If zero, then add next ULEB (note: can set offset for unaligned pointer)
214 incPageOffset = 0x30, // low 4-bits *4 is amount to increment (4 to 60). If zero, then add next ULEB * 4
215 // adjOrdinal = 0x40,
216 setOrdinal = 0x40, // low 4-bits is ordinal (1-15). If zero, then ordinal is next ULEB
217 incOrdinal = 0x50, // low 4-bits is ordinal inc amount (1-15). If zero, then ordinal is next ULEB
218 repeat = 0x60 // low 5-bits is how many next bytes to repeat. next ULEB is repeat count
219 };
220
221 // If a closure uses DYLD_LIBRARY_PATH to override an OS dylib, there is an
222 // ImageRefOverride entry to redirect uses of the OS dylib.
223 struct ImageRefOverride
224 {
225 ImageRef standardDylib;
226 ImageRef overrideDylib;
227 };
228
229 // If a closure interposes on, or has a dylib that overrides, something in the dyld shared cache,
230 // then closure's ImageGroup contains an array of these
231 struct DyldCacheOverride
232 {
233 uint64_t patchTableIndex : 24, // index into PatchTable array of group 0
234 imageIndex : 8, // index in this group (2) of what to replace with
235 imageOffset : 32; // offset within image to override something in cache
236 };
237
238
239 // The ImageGroup for the dyld shared cache dylibs contains and array of these
240 // with one entry for each symbol in a cached dylib that is used by some other cached dylib.
241 struct PatchTable
242 {
243 uint32_t targetCacheOffset; // delta from the base address of the cache to the address of the symbol to patch
244 uint32_t offsetsStartIndex; // index into the PatchOffset array of first location to patch, last offset has low bit set
245 };
246
247 struct PatchOffset
248 {
249 uint32_t last : 1,
250 hasAddend : 1,
251 dataRegionOffset : 30;
252 };
253
254 struct ImageGroup
255 {
256 uint32_t imagesEntrySize : 8,
257 dylibsExpectedOnDisk : 1,
258 imageFileInfoIsCdHash : 1,
259 padding : 14;
260 uint32_t groupNum;
261 uint32_t imagesPoolCount;
262 uint32_t imagesPoolOffset; // offset to array of Image or DiskImage
263 uint32_t imageAliasCount;
264 uint32_t imageAliasOffset; // offset to array of AliasEntry
265 uint32_t segmentsPoolCount;
266 uint32_t segmentsPoolOffset; // offset to array of Segment or DyldCacheSegment
267 uint32_t dependentsPoolCount;
268 uint32_t dependentsPoolOffset; // offset to array of ImageRef
269 uint32_t intializerOffsetPoolCount;
270 uint32_t intializerOffsetPoolOffset; // offset to array of uint32_t
271 uint32_t intializerListPoolCount;
272 uint32_t intializerListPoolOffset; // offset to array of ImageRef
273 uint32_t targetsPoolCount;
274 uint32_t targetsOffset; // offset to array of TargetSymbolValue
275 uint32_t fixupsPoolSize;
276 uint32_t fixupsOffset; // offset to list of AllFixupsBySegment
277 uint32_t cachePatchTableCount;
278 uint32_t cachePatchTableOffset; // offset to array of PatchTable (used only in group 0)
279 uint32_t cachePatchOffsetsCount;
280 uint32_t cachePatchOffsetsOffset; // offset to array of PatchOffset cache offsets (used only in group 0)
281 uint32_t symbolOverrideTableCount;
282 uint32_t symbolOverrideTableOffset; // offset to array of DyldCacheOverride (used only in group 2)
283 uint32_t imageOverrideTableCount;
284 uint32_t imageOverrideTableOffset; // offset to array of ImageRefOverride (used only in group 2)
285 uint32_t dofOffsetPoolCount;
286 uint32_t dofOffsetPoolOffset; // offset to array of uint32_t
287 uint32_t indirectGroupNumPoolCount;
288 uint32_t indirectGroupNumPoolOffset; // offset to array of uint32_t
289 uint32_t stringsPoolSize;
290 uint32_t stringsPoolOffset;
291 // Image array
292 // Alias array
293 // Segment array
294 // ImageRef array
295 // Initializer offsets array
296 // Initializer ImageRef array
297 // TargetSymbolValue array
298 // AllFixupsBySegment pool
299 // PatchTable array
300 // PatchOffset array
301 // DyldCacheOverride array
302 // ImageRefOverride array
303 // string pool
304 // DOF offsets array
305 };
306
307
308 struct Closure
309 {
310 enum { magicV1 = 0x31646c6e };
311
312 uint32_t magic;
313 uint32_t usesCRT : 1,
314 isRestricted : 1,
315 usesLibraryValidation : 1,
316 padding : 29;
317 uint32_t missingFileComponentsOffset; // offset to array of 16-bit string pool offset of path components
318 uint32_t dyldEnvVarsOffset;
319 uint32_t dyldEnvVarsCount;
320 uint32_t stringPoolOffset;
321 uint32_t stringPoolSize;
322 ImageRef libSystemRef;
323 ImageRef libDyldRef;
324 uint32_t libdyldVectorOffset;
325 uint32_t mainExecutableIndexInGroup;
326 uint32_t mainExecutableEntryOffset;
327 uint32_t initialImageCount;
328 uuid_t dyldCacheUUID; // all zero if this closure is embedded in a dyld cache
329 uint8_t mainExecutableCdHash[20]; // or UUID if not code signed
330 ImageGroup group;
331 // MissingFile array
332 // env vars array
333 // string pool
334 };
335
336
337
338 } // namespace binary_format
339
340 } // namespace launch_cache
341 } // namespace dyld
342
343
344 #endif // LaunchCacheFormat_h
345
346