dyld-750.6.tar.gz
[apple/dyld.git] / launch-cache / dyld_cache_format.h
1 /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
2 *
3 * Copyright (c) 2006-2015 Apple Inc. All rights reserved.
4 *
5 * @APPLE_LICENSE_HEADER_START@
6 *
7 * This file contains Original Code and/or Modifications of Original Code
8 * as defined in and that are subject to the Apple Public Source License
9 * Version 2.0 (the 'License'). You may not use this file except in
10 * compliance with the License. Please obtain a copy of the License at
11 * http://www.opensource.apple.com/apsl/ and read it before using this
12 * file.
13 *
14 * The Original Code and all software distributed under the License are
15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
19 * Please see the License for the specific language governing rights and
20 * limitations under the License.
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24 #ifndef __DYLD_CACHE_FORMAT__
25 #define __DYLD_CACHE_FORMAT__
26
27 #include <sys/types.h>
28 #include <stdint.h>
29 #include <mach/shared_region.h>
30 #include <uuid/uuid.h>
31
32
33 struct dyld_cache_header
34 {
35 char magic[16]; // e.g. "dyld_v0 i386"
36 uint32_t mappingOffset; // file offset to first dyld_cache_mapping_info
37 uint32_t mappingCount; // number of dyld_cache_mapping_info entries
38 uint32_t imagesOffset; // file offset to first dyld_cache_image_info
39 uint32_t imagesCount; // number of dyld_cache_image_info entries
40 uint64_t dyldBaseAddress; // base address of dyld when cache was built
41 uint64_t codeSignatureOffset; // file offset of code signature blob
42 uint64_t codeSignatureSize; // size of code signature blob (zero means to end of file)
43 uint64_t slideInfoOffset; // file offset of kernel slid info
44 uint64_t slideInfoSize; // size of kernel slid info
45 uint64_t localSymbolsOffset; // file offset of where local symbols are stored
46 uint64_t localSymbolsSize; // size of local symbols information
47 uint8_t uuid[16]; // unique value for each shared cache file
48 uint64_t cacheType; // 0 for development, 1 for production
49 uint32_t branchPoolsOffset; // file offset to table of uint64_t pool addresses
50 uint32_t branchPoolsCount; // number of uint64_t entries
51 uint64_t accelerateInfoAddr; // (unslid) address of optimization info
52 uint64_t accelerateInfoSize; // size of optimization info
53 uint64_t imagesTextOffset; // file offset to first dyld_cache_image_text_info
54 uint64_t imagesTextCount; // number of dyld_cache_image_text_info entries
55 };
56
57
58 struct dyld_cache_mapping_info {
59 uint64_t address;
60 uint64_t size;
61 uint64_t fileOffset;
62 uint32_t maxProt;
63 uint32_t initProt;
64 };
65
66 struct dyld_cache_image_info
67 {
68 uint64_t address;
69 uint64_t modTime;
70 uint64_t inode;
71 uint32_t pathFileOffset;
72 uint32_t pad;
73 };
74
75 struct dyld_cache_image_info_extra
76 {
77 uint64_t exportsTrieAddr; // address of trie in unslid cache
78 uint64_t weakBindingsAddr;
79 uint32_t exportsTrieSize;
80 uint32_t weakBindingsSize;
81 uint32_t dependentsStartArrayIndex;
82 uint32_t reExportsStartArrayIndex;
83 };
84
85
86 struct dyld_cache_accelerator_info
87 {
88 uint32_t version; // currently 1
89 uint32_t imageExtrasCount; // does not include aliases
90 uint32_t imagesExtrasOffset; // offset into this chunk of first dyld_cache_image_info_extra
91 uint32_t bottomUpListOffset; // offset into this chunk to start of 16-bit array of sorted image indexes
92 uint32_t dylibTrieOffset; // offset into this chunk to start of trie containing all dylib paths
93 uint32_t dylibTrieSize; // size of trie containing all dylib paths
94 uint32_t initializersOffset; // offset into this chunk to start of initializers list
95 uint32_t initializersCount; // size of initializers list
96 uint32_t dofSectionsOffset; // offset into this chunk to start of DOF sections list
97 uint32_t dofSectionsCount; // size of initializers list
98 uint32_t reExportListOffset; // offset into this chunk to start of 16-bit array of re-exports
99 uint32_t reExportCount; // size of re-exports
100 uint32_t depListOffset; // offset into this chunk to start of 16-bit array of dependencies (0x8000 bit set if upward)
101 uint32_t depListCount; // size of dependencies
102 uint32_t rangeTableOffset; // offset into this chunk to start of ss
103 uint32_t rangeTableCount; // size of dependencies
104 uint64_t dyldSectionAddr; // address of libdyld's __dyld section in unslid cache
105 };
106
107 struct dyld_cache_accelerator_initializer
108 {
109 uint32_t functionOffset; // address offset from start of cache mapping
110 uint32_t imageIndex;
111 };
112
113 struct dyld_cache_range_entry
114 {
115 uint64_t startAddress; // unslid address of start of region
116 uint32_t size;
117 uint32_t imageIndex;
118 };
119
120 struct dyld_cache_accelerator_dof
121 {
122 uint64_t sectionAddress; // unslid address of start of region
123 uint32_t sectionSize;
124 uint32_t imageIndex;
125 };
126
127 struct dyld_cache_image_text_info
128 {
129 uuid_t uuid;
130 uint64_t loadAddress; // unslid address of start of __TEXT
131 uint32_t textSegmentSize;
132 uint32_t pathOffset; // offset from start of cache file
133 };
134
135 // The rebasing info is to allow the kernel to lazily rebase DATA pages of the
136 // dyld shared cache. Rebasing is adding the slide to interior pointers.
137 struct dyld_cache_slide_info
138 {
139 uint32_t version; // currently 1
140 uint32_t toc_offset;
141 uint32_t toc_count;
142 uint32_t entries_offset;
143 uint32_t entries_count;
144 uint32_t entries_size; // currently 128
145 // uint16_t toc[toc_count];
146 // entrybitmap entries[entries_count];
147 };
148
149
150 // The version 2 of the slide info uses a different compression scheme. Since
151 // only interior pointers (pointers that point within the cache) are rebased
152 // (slid), we know the possible range of the pointers and thus know there are
153 // unused bits in each pointer. We use those bits to form a linked list of
154 // locations needing rebasing in each page.
155 //
156 // Definitions:
157 //
158 // pageIndex = (pageAddress - startOfAllDataAddress)/info->page_size
159 // pageStarts[] = info + info->page_starts_offset
160 // pageExtras[] = info + info->page_extras_offset
161 // valueMask = ~(info->delta_mask)
162 // deltaShift = __builtin_ctzll(info->delta_mask) - 2
163 //
164 // There are three cases:
165 //
166 // 1) pageStarts[pageIndex] == DYLD_CACHE_SLIDE_PAGE_ATTR_NO_REBASE
167 // The page contains no values that need rebasing.
168 //
169 // 2) (pageStarts[pageIndex] & DYLD_CACHE_SLIDE_PAGE_ATTR_EXTRA) == 0
170 // All rebase locations are in one linked list. The offset of the first
171 // rebase location in the page is pageStarts[pageIndex] * 4.
172 //
173 // 3) pageStarts[pageIndex] & DYLD_CACHE_SLIDE_PAGE_ATTR_EXTRA
174 // Multiple linked lists are needed for all rebase locations in a page.
175 // The pagesExtras array contains 2 or more entries each of which is the
176 // start of a new linked list in the page. The first is at:
177 // extrasStartIndex = (pageStarts[pageIndex] & 0x3FFF)
178 // The next is at extrasStartIndex+1. The last is denoted by
179 // having the high bit (DYLD_CACHE_SLIDE_PAGE_ATTR_END) of the pageExtras[]
180 // set.
181 //
182 // For 64-bit architectures, there is always enough free bits to encode all
183 // possible deltas. The info->delta_mask field shows where the delta is located
184 // in the pointer. That value must be masked off (valueMask) before the slide
185 // is added to the pointer.
186 //
187 // For 32-bit architectures, there are only three bits free (the three most
188 // significant bits). To extract the delta, you must first subtract value_add
189 // from the pointer value, then AND with delta_mask, then shift by deltaShift.
190 // That still leaves a maximum delta to the next rebase location of 28 bytes.
191 // To reduce the number or chains needed, an optimization was added. Turns
192 // out zero is common in the DATA region. A zero can be turned into a
193 // non-rebasing entry in the linked list. The can be done because nothing
194 // in the shared cache should point out of its dylib to the start of the shared
195 // cache.
196 //
197 // The code for processing a linked list (chain) is:
198 //
199 // uint32_t delta = 1;
200 // while ( delta != 0 ) {
201 // uint8_t* loc = pageStart + pageOffset;
202 // uintptr_t rawValue = *((uintptr_t*)loc);
203 // delta = ((rawValue & deltaMask) >> deltaShift);
204 // uintptr_t newValue = (rawValue & valueMask);
205 // if ( newValue != 0 ) {
206 // newValue += valueAdd;
207 // newValue += slideAmount;
208 // }
209 // *((uintptr_t*)loc) = newValue;
210 // pageOffset += delta;
211 // }
212 //
213 //
214 struct dyld_cache_slide_info2
215 {
216 uint32_t version; // currently 2
217 uint32_t page_size; // currently 4096 (may also be 16384)
218 uint32_t page_starts_offset;
219 uint32_t page_starts_count;
220 uint32_t page_extras_offset;
221 uint32_t page_extras_count;
222 uint64_t delta_mask; // which (contiguous) set of bits contains the delta to the next rebase location
223 uint64_t value_add;
224 //uint16_t page_starts[page_starts_count];
225 //uint16_t page_extras[page_extras_count];
226 };
227 #define DYLD_CACHE_SLIDE_PAGE_ATTRS 0xC000 // high bits of uint16_t are flags
228 #define DYLD_CACHE_SLIDE_PAGE_ATTR_EXTRA 0x8000 // index is into extras array (not starts array)
229 #define DYLD_CACHE_SLIDE_PAGE_ATTR_NO_REBASE 0x4000 // page has no rebasing
230 #define DYLD_CACHE_SLIDE_PAGE_ATTR_END 0x8000 // last chain entry for page
231
232
233
234 // The version 3 of the slide info uses a different compression scheme. Since
235 // only interior pointers (pointers that point within the cache) are rebased
236 // (slid), we know the possible range of the pointers and thus know there are
237 // unused bits in each pointer. We use those bits to form a linked list of
238 // locations needing rebasing in each page.
239 //
240 // Definitions:
241 //
242 // pageIndex = (pageAddress - startOfAllDataAddress)/info->page_size
243 // pageStarts[] = info + info->page_starts_offset
244 //
245 // There are two cases:
246 //
247 // 1) pageStarts[pageIndex] == DYLD_CACHE_SLIDE_V3_PAGE_ATTR_NO_REBASE
248 // The page contains no values that need rebasing.
249 //
250 // 2) otherwise...
251 // All rebase locations are in one linked list. The offset of the first
252 // rebase location in the page is pageStarts[pageIndex].
253 //
254 // A pointer is one of :
255 // {
256 // uint64_t pointerValue : 51;
257 // uint64_t offsetToNextPointer : 11;
258 // uint64_t isBind : 1 = 0;
259 // uint64_t authenticated : 1 = 0;
260 // }
261 // {
262 // uint32_t offsetFromSharedCacheBase;
263 // uint16_t diversityData;
264 // uint16_t hasAddressDiversity : 1;
265 // uint16_t key : 2;
266 // uint16_t offsetToNextPointer : 11;
267 // uint16_t isBind : 1;
268 // uint16_t authenticated : 1 = 1;
269 // }
270 //
271 // The code for processing a linked list (chain) is:
272 //
273 // uint32_t delta = pageStarts[pageIndex];
274 // uint8_t* loc = pageStart;
275 // do {
276 // loc += delta;
277 // uintptr_t rawValue = *((uintptr_t*)loc);
278 // delta = ( (value & 0x3FF8000000000000) >> 51) * sizeof(uint64_t);
279 // if (extraBindData.isAuthenticated) {
280 // newValue = ( value & 0xFFFFFFFF ) + results->slide + auth_value_add;
281 // newValue = sign_using_the_various_bits(newValue);
282 // } else {
283 // uint64_t top8Bits = value & 0x0007F80000000000ULL;
284 // uint64_t bottom43Bits = value & 0x000007FFFFFFFFFFULL;
285 // uint64_t targetValue = ( top8Bits << 13 ) | bottom43Bits;
286 // newValue = targetValue + results->slide;
287 // }
288 // *((uintptr_t*)loc) = newValue;
289 // } while (delta != 0 )
290 //
291 //
292 struct dyld_cache_slide_info3
293 {
294 uint32_t version; // currently 3
295 uint32_t page_size; // currently 4096 (may also be 16384)
296 uint32_t page_starts_count;
297 uint64_t auth_value_add;
298 uint16_t page_starts[/* page_starts_count */];
299 };
300
301 #define DYLD_CACHE_SLIDE_V3_PAGE_ATTR_NO_REBASE 0xFFFF // page has no rebasing
302
303
304 struct dyld_cache_local_symbols_info
305 {
306 uint32_t nlistOffset; // offset into this chunk of nlist entries
307 uint32_t nlistCount; // count of nlist entries
308 uint32_t stringsOffset; // offset into this chunk of string pool
309 uint32_t stringsSize; // byte count of string pool
310 uint32_t entriesOffset; // offset into this chunk of array of dyld_cache_local_symbols_entry
311 uint32_t entriesCount; // number of elements in dyld_cache_local_symbols_entry array
312 };
313
314 struct dyld_cache_local_symbols_entry
315 {
316 uint32_t dylibOffset; // offset in cache file of start of dylib
317 uint32_t nlistStartIndex; // start index of locals for this dylib
318 uint32_t nlistCount; // number of local symbols for this dylib
319 };
320
321 struct dyld_cache_image_patches
322 {
323 uint32_t patchExportsStartIndex;
324 uint32_t patchExportsCount;
325 };
326
327 struct dyld_cache_patchable_export
328 {
329 uint32_t cacheOffsetOfImpl;
330 uint32_t patchLocationsStartIndex;
331 uint32_t patchLocationsCount;
332 uint32_t exportNameOffset;
333 };
334
335 struct dyld_cache_patchable_location
336 {
337 uint64_t cacheOffset : 32,
338 addend : 12, // +/- 2048
339 authenticated : 1,
340 usesAddressDiversity : 1,
341 key : 2,
342 discriminator : 16;
343
344 dyld_cache_patchable_location(size_t cacheOffset, uint64_t addend);
345 //dyld_cache_patchable_location(size_t cacheOffset, uint64_t addend, dyld3::MachOLoaded::ChainedFixupPointerOnDisk authInfo);
346
347 uint64_t getAddend() const {
348 uint64_t unsingedAddend = addend;
349 int64_t signedAddend = (int64_t)unsingedAddend;
350 signedAddend = (signedAddend << 52) >> 52;
351 return (uint64_t)signedAddend;
352 }
353
354 const char* keyName() const;
355 bool operator==(const dyld_cache_patchable_location& other) const {
356 return this->cacheOffset == other.cacheOffset;
357 }
358 };
359
360
361
362 #define MACOSX_DYLD_SHARED_CACHE_DIR "/private/var/db/dyld/"
363 #define IPHONE_DYLD_SHARED_CACHE_DIR "/System/Library/Caches/com.apple.dyld/"
364 #define DYLD_SHARED_CACHE_BASE_NAME "dyld_shared_cache_"
365 #define DYLD_SHARED_CACHE_DEVELOPMENT_EXT ".development"
366
367 static const uint64_t kDyldSharedCacheTypeDevelopment = 0;
368 static const uint64_t kDyldSharedCacheTypeProduction = 1;
369
370
371
372
373 #endif // __DYLD_CACHE_FORMAT__
374
375