]>
Commit | Line | Data |
---|---|---|
0959b6d4 A |
1 | /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- |
2 | * | |
412ebb8e | 3 | * Copyright (c) 2004-2010 Apple Inc. All rights reserved. |
0959b6d4 A |
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 | ||
25 | ||
26 | #ifndef __IMAGELOADER__ | |
27 | #define __IMAGELOADER__ | |
28 | ||
29 | #include <sys/types.h> | |
39a8cd10 | 30 | #include <unistd.h> |
2fd3f4e8 | 31 | #include <stdlib.h> |
0959b6d4 | 32 | #include <mach/mach_time.h> // struct mach_timebase_info |
bac542e6 | 33 | #include <mach/mach_init.h> // struct mach_thread_self |
39a8cd10 A |
34 | #include <mach/shared_region.h> |
35 | #include <mach-o/loader.h> | |
36 | #include <mach-o/nlist.h> | |
cf998323 A |
37 | #include <mach-o/dyld_images.h> |
38 | #include <mach-o/dyld_priv.h> | |
0959b6d4 | 39 | #include <stdint.h> |
2fd3f4e8 A |
40 | #include <stdlib.h> |
41 | #include <TargetConditionals.h> | |
0959b6d4 | 42 | #include <vector> |
39a8cd10 | 43 | #include <new> |
6cae9b63 | 44 | #include <uuid/uuid.h> |
0959b6d4 | 45 | |
cf998323 A |
46 | #if !TARGET_OS_DRIVERKIT && (BUILDING_LIBDYLD || BUILDING_DYLD) |
47 | #include <CrashReporterClient.h> | |
48 | #else | |
49 | #define CRSetCrashLogMessage(x) | |
50 | #define CRSetCrashLogMessage2(x) | |
51 | #endif | |
52 | ||
53 | #include "DyldSharedCache.h" | |
a9a4db61 | 54 | #include "Map.h" |
797cc951 | 55 | #include "PointerAuth.h" |
a9a4db61 | 56 | |
19894a12 A |
57 | #if __arm__ |
58 | #include <mach/vm_page_size.h> | |
59 | #endif | |
60 | ||
412ebb8e | 61 | |
19894a12 A |
62 | #ifndef SHARED_REGION_BASE_ARM64 |
63 | #define SHARED_REGION_BASE_ARM64 0x7FFF80000000LL | |
64 | #endif | |
65 | ||
66 | #ifndef SHARED_REGION_SIZE_ARM64 | |
67 | #define SHARED_REGION_SIZE_ARM64 0x10000000LL | |
68 | #endif | |
69 | ||
70 | ||
412ebb8e A |
71 | #define LOG_BINDINGS 0 |
72 | ||
39a8cd10 | 73 | |
bc3b7c8c | 74 | #if TARGET_OS_IPHONE |
2fd3f4e8 A |
75 | #define SPLIT_SEG_SHARED_REGION_SUPPORT 0 |
76 | #define SPLIT_SEG_DYLIB_SUPPORT 0 | |
19894a12 | 77 | #define PREBOUND_IMAGE_SUPPORT __arm__ |
2fd3f4e8 | 78 | #define TEXT_RELOC_SUPPORT __i386__ |
2fd3f4e8 | 79 | #define SUPPORT_OLD_CRT_INITIALIZATION 0 |
df9d6cf7 | 80 | #define SUPPORT_LC_DYLD_ENVIRONMENT 1 |
cf998323 | 81 | #define SUPPORT_VERSIONED_PATHS 0 |
2fd3f4e8 | 82 | #define SUPPORT_CLASSIC_MACHO __arm__ |
19894a12 | 83 | #define SUPPORT_ZERO_COST_EXCEPTIONS (!__USING_SJLJ_EXCEPTIONS__) |
9f83892a | 84 | #define INITIAL_IMAGE_COUNT 150 |
16b475fc | 85 | #define SUPPORT_ACCELERATE_TABLES 0 |
cf998323 | 86 | #define SUPPORT_ROOT_PATH TARGET_OS_SIMULATOR |
412ebb8e | 87 | #else |
2fd3f4e8 A |
88 | #define SPLIT_SEG_SHARED_REGION_SUPPORT 0 |
89 | #define SPLIT_SEG_DYLIB_SUPPORT __i386__ | |
90 | #define PREBOUND_IMAGE_SUPPORT __i386__ | |
91 | #define TEXT_RELOC_SUPPORT __i386__ | |
2fd3f4e8 | 92 | #define SUPPORT_OLD_CRT_INITIALIZATION __i386__ |
bc3b7c8c | 93 | #define SUPPORT_LC_DYLD_ENVIRONMENT 1 |
2fd3f4e8 A |
94 | #define SUPPORT_VERSIONED_PATHS 1 |
95 | #define SUPPORT_CLASSIC_MACHO 1 | |
19894a12 | 96 | #define SUPPORT_ZERO_COST_EXCEPTIONS 1 |
2fd3f4e8 | 97 | #define INITIAL_IMAGE_COUNT 200 |
9f83892a A |
98 | #define SUPPORT_ACCELERATE_TABLES 0 |
99 | #define SUPPORT_ROOT_PATH 1 | |
39a8cd10 | 100 | #endif |
bac542e6 | 101 | |
9f83892a | 102 | #define MAX_MACH_O_HEADER_AND_LOAD_COMMANDS_SIZE (32*1024) |
2fd3f4e8 | 103 | |
6cae9b63 | 104 | |
2fd3f4e8 A |
105 | // <rdar://problem/13590567> optimize away dyld's initializers |
106 | #define VECTOR_NEVER_DESTRUCTED(type) \ | |
107 | namespace std { \ | |
108 | template <> \ | |
109 | __vector_base<type, std::allocator<type> >::~__vector_base() { } \ | |
110 | } | |
111 | #define VECTOR_NEVER_DESTRUCTED_EXTERN(type) \ | |
112 | namespace std { \ | |
113 | template <> \ | |
114 | __vector_base<type, std::allocator<type> >::~__vector_base(); \ | |
115 | } | |
116 | #define VECTOR_NEVER_DESTRUCTED_IMPL(type) \ | |
117 | namespace std { \ | |
118 | template <> \ | |
119 | __vector_base<type, std::allocator<type> >::~__vector_base() { } \ | |
120 | } | |
bac542e6 A |
121 | |
122 | // utilities | |
123 | namespace dyld { | |
124 | extern __attribute__((noreturn)) void throwf(const char* format, ...) __attribute__((format(printf, 1, 2))); | |
125 | extern void log(const char* format, ...) __attribute__((format(printf, 1, 2))); | |
126 | extern void warn(const char* format, ...) __attribute__((format(printf, 1, 2))); | |
127 | extern const char* mkstringf(const char* format, ...) __attribute__((format(printf, 1, 2))); | |
412ebb8e A |
128 | #if LOG_BINDINGS |
129 | extern void logBindings(const char* format, ...) __attribute__((format(printf, 1, 2))); | |
130 | #endif | |
2fd3f4e8 A |
131 | } |
132 | extern "C" int vm_alloc(vm_address_t* addr, vm_size_t size, uint32_t flags); | |
133 | extern "C" void* xmmap(void* addr, size_t len, int prot, int flags, int fd, off_t offset); | |
bac542e6 A |
134 | |
135 | ||
39a8cd10 A |
136 | #if __LP64__ |
137 | struct macho_header : public mach_header_64 {}; | |
138 | struct macho_nlist : public nlist_64 {}; | |
139 | #else | |
140 | struct macho_header : public mach_header {}; | |
141 | struct macho_nlist : public nlist {}; | |
142 | #endif | |
143 | ||
144 | ||
19894a12 A |
145 | #if __arm64__ |
146 | #define dyld_page_trunc(__addr) (__addr & (-16384)) | |
147 | #define dyld_page_round(__addr) ((__addr + 16383) & (-16384)) | |
148 | #define dyld_page_size 16384 | |
149 | #elif __arm__ | |
150 | #define dyld_page_trunc(__addr) trunc_page_kernel(__addr) | |
151 | #define dyld_page_round(__addr) round_page_kernel(__addr) | |
152 | #define dyld_page_size vm_kernel_page_size | |
153 | #else | |
154 | #define dyld_page_trunc(__addr) (__addr & (-4096)) | |
155 | #define dyld_page_round(__addr) ((__addr + 4095) & (-4096)) | |
156 | #define dyld_page_size 4096 | |
157 | #endif | |
158 | ||
159 | ||
cf998323 | 160 | #define DYLD_PACKED_VERSION(major, minor, tiny) ((((major) & 0xffff) << 16) | (((minor) & 0xff) << 8) | ((tiny) & 0xff)) |
19894a12 | 161 | |
bac542e6 A |
162 | struct ProgramVars |
163 | { | |
164 | const void* mh; | |
165 | int* NXArgcPtr; | |
166 | const char*** NXArgvPtr; | |
167 | const char*** environPtr; | |
168 | const char** __prognamePtr; | |
169 | }; | |
0959b6d4 A |
170 | |
171 | ||
0959b6d4 | 172 | |
cf998323 A |
173 | enum dyld_image_states |
174 | { | |
175 | dyld_image_state_mapped = 10, // No batch notification for this | |
176 | dyld_image_state_dependents_mapped = 20, // Only batch notification for this | |
177 | dyld_image_state_rebased = 30, | |
178 | dyld_image_state_bound = 40, | |
179 | dyld_image_state_dependents_initialized = 45, // Only single notification for this | |
180 | dyld_image_state_initialized = 50, | |
181 | dyld_image_state_terminated = 60 // Only single notification for this | |
182 | }; | |
183 | typedef const char* (*dyld_image_state_change_handler)(enum dyld_image_states state, uint32_t infoCount, const struct dyld_image_info info[]); | |
184 | ||
0959b6d4 A |
185 | // |
186 | // ImageLoader is an abstract base class. To support loading a particular executable | |
187 | // file format, you make a concrete subclass of ImageLoader. | |
188 | // | |
189 | // For each executable file (dynamic shared object) in use, an ImageLoader is instantiated. | |
190 | // | |
191 | // The ImageLoader base class does the work of linking together images, but it knows nothing | |
192 | // about any particular file format. | |
193 | // | |
194 | // | |
195 | class ImageLoader { | |
196 | public: | |
197 | ||
198 | typedef uint32_t DefinitionFlags; | |
199 | static const DefinitionFlags kNoDefinitionOptions = 0; | |
200 | static const DefinitionFlags kWeakDefinition = 1; | |
201 | ||
202 | typedef uint32_t ReferenceFlags; | |
203 | static const ReferenceFlags kNoReferenceOptions = 0; | |
204 | static const ReferenceFlags kWeakReference = 1; | |
205 | static const ReferenceFlags kTentativeDefinition = 2; | |
206 | ||
0959b6d4 A |
207 | enum PrebindMode { kUseAllPrebinding, kUseSplitSegPrebinding, kUseAllButAppPredbinding, kUseNoPrebinding }; |
208 | enum BindingOptions { kBindingNone, kBindingLazyPointers, kBindingNeverSetLazyPointers }; | |
bac542e6 | 209 | enum SharedRegionMode { kUseSharedRegion, kUsePrivateSharedRegion, kDontUseSharedRegion, kSharedRegionIsSharedCache }; |
0959b6d4 A |
210 | |
211 | struct Symbol; // abstact symbol | |
212 | ||
213 | struct MappedRegion { | |
214 | uintptr_t address; | |
215 | size_t size; | |
216 | }; | |
bac542e6 A |
217 | |
218 | struct RPathChain { | |
219 | RPathChain(const RPathChain* n, std::vector<const char*>* p) : next(n), paths(p) {}; | |
220 | const RPathChain* next; | |
221 | std::vector<const char*>* paths; | |
222 | }; | |
223 | ||
224 | struct DOFInfo { | |
225 | void* dof; | |
226 | const mach_header* imageHeader; | |
227 | const char* imageShortName; | |
228 | }; | |
0959b6d4 | 229 | |
2fd3f4e8 A |
230 | struct DynamicReference { |
231 | ImageLoader* from; | |
232 | ImageLoader* to; | |
233 | }; | |
234 | ||
9f83892a A |
235 | struct InitializerTimingList |
236 | { | |
237 | uintptr_t count; | |
238 | struct { | |
239 | const char* shortName; | |
240 | uint64_t initTime; | |
241 | } images[1]; | |
242 | ||
243 | void addTime(const char* name, uint64_t time); | |
244 | }; | |
6cae9b63 A |
245 | |
246 | typedef void (^CoalesceNotifier)(const Symbol* implSym, const ImageLoader* implIn, const mach_header* implMh); | |
a9a4db61 A |
247 | |
248 | struct HashCString { | |
249 | static size_t hash(const char* v); | |
250 | }; | |
251 | ||
252 | struct EqualCString { | |
253 | static bool equal(const char* s1, const char* s2); | |
254 | }; | |
9f83892a | 255 | |
0959b6d4 | 256 | struct LinkContext { |
cf998323 | 257 | ImageLoader* (*loadLibrary)(const char* libraryName, bool search, const char* origin, const RPathChain* rpaths, unsigned& cacheIndex); |
0959b6d4 | 258 | void (*terminationRecorder)(ImageLoader* image); |
bac542e6 | 259 | bool (*flatExportFinder)(const char* name, const Symbol** sym, const ImageLoader** image); |
6cae9b63 | 260 | bool (*coalescedExportFinder)(const char* name, const Symbol** sym, const ImageLoader** image, CoalesceNotifier); |
9f83892a | 261 | unsigned int (*getCoalescedImages)(ImageLoader* images[], unsigned imageIndex[]); |
0959b6d4 | 262 | void (*undefinedHandler)(const char* name); |
bac542e6 | 263 | MappedRegion* (*getAllMappedRegions)(MappedRegion*); |
0959b6d4 | 264 | void * (*bindingHandler)(const char *, const char *, void *); |
9f83892a A |
265 | void (*notifySingle)(dyld_image_states, const ImageLoader* image, InitializerTimingList*); |
266 | void (*notifyBatch)(dyld_image_states state, bool preflightOnly); | |
bac542e6 A |
267 | void (*removeImage)(ImageLoader* image); |
268 | void (*registerDOFs)(const std::vector<DOFInfo>& dofs); | |
269 | void (*clearAllDepths)(); | |
832b6fce | 270 | void (*printAllDepths)(); |
bac542e6 | 271 | unsigned int (*imageCount)(); |
bac542e6 | 272 | void (*setNewProgramVars)(const ProgramVars&); |
39a8cd10 | 273 | bool (*inSharedCache)(const char* path); |
412ebb8e A |
274 | void (*setErrorStrings)(unsigned errorCode, const char* errorClientOfDylibPath, |
275 | const char* errorTargetDylibPath, const char* errorSymbol); | |
2fd3f4e8 A |
276 | ImageLoader* (*findImageContainingAddress)(const void* addr); |
277 | void (*addDynamicReference)(ImageLoader* from, ImageLoader* to); | |
9f83892a A |
278 | #if SUPPORT_ACCELERATE_TABLES |
279 | void (*notifySingleFromCache)(dyld_image_states, const mach_header* mh, const char* path); | |
280 | dyld_image_state_change_handler (*getPreInitNotifyHandler)(unsigned index); | |
281 | dyld_image_state_change_handler (*getBoundBatchHandler)(unsigned index); | |
282 | #endif | |
2fd3f4e8 | 283 | |
bac542e6 A |
284 | #if SUPPORT_OLD_CRT_INITIALIZATION |
285 | void (*setRunInitialzersOldWay)(); | |
286 | #endif | |
0959b6d4 A |
287 | BindingOptions bindingOptions; |
288 | int argc; | |
289 | const char** argv; | |
290 | const char** envp; | |
291 | const char** apple; | |
bac542e6 A |
292 | const char* progname; |
293 | ProgramVars programVars; | |
0959b6d4 | 294 | ImageLoader* mainExecutable; |
6cae9b63 | 295 | const char* const * imageSuffix; |
9f83892a | 296 | #if SUPPORT_ROOT_PATH |
39a8cd10 | 297 | const char** rootPaths; |
9f83892a | 298 | #endif |
6cae9b63 | 299 | const DyldSharedCache* dyldCache; |
19894a12 A |
300 | const dyld_interpose_tuple* dynamicInterposeArray; |
301 | size_t dynamicInterposeCount; | |
0959b6d4 A |
302 | PrebindMode prebindUsage; |
303 | SharedRegionMode sharedRegionMode; | |
a9a4db61 A |
304 | mutable dyld3::Map<const char*, std::pair<const ImageLoader*, uintptr_t>, HashCString, EqualCString> weakDefMap; |
305 | mutable bool weakDefMapInitialized = false; | |
306 | mutable bool weakDefMapProcessedLaunchDefs = false; | |
307 | mutable bool useNewWeakBind = false; | |
2fd3f4e8 | 308 | bool dyldLoadedAtSameAddressNeededBySharedCache; |
9f83892a | 309 | bool strictMachORequired; |
6cae9b63 A |
310 | bool allowAtPaths; |
311 | bool allowEnvVarsPrint; | |
312 | bool allowEnvVarsPath; | |
313 | bool allowEnvVarsSharedCache; | |
314 | bool allowClassicFallbackPaths; | |
315 | bool allowInsertFailures; | |
dd1e3476 | 316 | bool allowInterposing; |
2fd3f4e8 | 317 | bool mainExecutableCodeSigned; |
577cc7d1 | 318 | bool prebinding; |
0959b6d4 | 319 | bool bindFlat; |
bac542e6 | 320 | bool linkingMainExecutable; |
2028a915 | 321 | bool startedInitializingMainExecutable; |
bc3b7c8c | 322 | #if TARGET_OS_OSX |
cf998323 | 323 | bool iOSonMac; |
bc3b7c8c | 324 | // dyld doesn't build for driverKit, so we use the macOS define to control whether driverKit is supported |
cf998323 | 325 | bool driverKit; |
9f83892a | 326 | #endif |
0959b6d4 A |
327 | bool verboseOpts; |
328 | bool verboseEnv; | |
9f83892a | 329 | bool verboseLoading; |
0959b6d4 A |
330 | bool verboseMapping; |
331 | bool verboseRebase; | |
332 | bool verboseBind; | |
39a8cd10 | 333 | bool verboseWeakBind; |
0959b6d4 | 334 | bool verboseInit; |
bac542e6 | 335 | bool verboseDOF; |
0959b6d4 | 336 | bool verbosePrebinding; |
412ebb8e | 337 | bool verboseCoreSymbolication; |
0959b6d4 | 338 | bool verboseWarnings; |
412ebb8e A |
339 | bool verboseRPaths; |
340 | bool verboseInterposing; | |
2fd3f4e8 | 341 | bool verboseCodeSignatures; |
0959b6d4 A |
342 | }; |
343 | ||
39a8cd10 A |
344 | struct CoalIterator |
345 | { | |
346 | ImageLoader* image; | |
347 | const char* symbolName; | |
348 | unsigned int loadOrder; | |
349 | bool weakSymbol; | |
350 | bool symbolMatches; | |
351 | bool done; | |
352 | // the following are private to the ImageLoader subclass | |
353 | uintptr_t curIndex; | |
354 | uintptr_t endIndex; | |
355 | uintptr_t address; | |
356 | uintptr_t type; | |
357 | uintptr_t addend; | |
9f83892a | 358 | uintptr_t imageIndex; |
39a8cd10 A |
359 | }; |
360 | ||
9f83892a | 361 | virtual void initializeCoalIterator(CoalIterator&, unsigned int loadOrder, unsigned imageIndex) = 0; |
39a8cd10 A |
362 | virtual bool incrementCoalIterator(CoalIterator&) = 0; |
363 | virtual uintptr_t getAddressCoalIterator(CoalIterator&, const LinkContext& context) = 0; | |
9f83892a | 364 | virtual void updateUsesCoalIterator(CoalIterator&, uintptr_t newAddr, ImageLoader* target, unsigned targetIndex, const LinkContext& context) = 0; |
39a8cd10 | 365 | |
19894a12 A |
366 | struct UninitedUpwards |
367 | { | |
cf998323 A |
368 | uintptr_t count; |
369 | std::pair<ImageLoader*, const char*> imagesAndPaths[1]; | |
19894a12 A |
370 | }; |
371 | ||
39a8cd10 | 372 | |
0959b6d4 A |
373 | // constructor is protected, but anyone can delete an image |
374 | virtual ~ImageLoader(); | |
375 | ||
376 | // link() takes a newly instantiated ImageLoader and does all | |
377 | // fixups needed to make it usable by the process | |
9f83892a | 378 | void link(const LinkContext& context, bool forceLazysBound, bool preflight, bool neverUnload, const RPathChain& loaderRPaths, const char* imagePath); |
0959b6d4 A |
379 | |
380 | // runInitializers() is normally called in link() but the main executable must | |
381 | // run crt code before initializers | |
412ebb8e | 382 | void runInitializers(const LinkContext& context, InitializerTimingList& timingInfo); |
0959b6d4 | 383 | |
bac542e6 A |
384 | // called after link() forces all lazy pointers to be bound |
385 | void bindAllLazyPointers(const LinkContext& context, bool recursive); | |
386 | ||
0959b6d4 A |
387 | // used by dyld to see if a requested library is already loaded (might be symlink) |
388 | bool statMatch(const struct stat& stat_buf) const; | |
389 | ||
390 | // get short name of this image | |
391 | const char* getShortName() const; | |
392 | ||
9f83892a A |
393 | // returns leaf name |
394 | static const char* shortName(const char* fullName); | |
395 | ||
0959b6d4 A |
396 | // get path used to load this image, not necessarily the "real" path |
397 | const char* getPath() const { return fPath; } | |
398 | ||
399 | uint32_t getPathHash() const { return fPathHash; } | |
400 | ||
832b6fce A |
401 | // get the "real" path for this image (e.g. no @rpath) |
402 | const char* getRealPath() const; | |
403 | ||
0959b6d4 A |
404 | // get path this image is intended to be placed on disk or NULL if no preferred install location |
405 | virtual const char* getInstallPath() const = 0; | |
406 | ||
9f83892a | 407 | // image was loaded with NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME and all clients are looking for install path |
0959b6d4 A |
408 | bool matchInstallPath() const; |
409 | void setMatchInstallPath(bool); | |
410 | ||
0959b6d4 A |
411 | // mark that this image's exported symbols should be ignored when linking other images (e.g. RTLD_LOCAL) |
412 | void setHideExports(bool hide = true); | |
413 | ||
414 | // check if this image's exported symbols should be ignored when linking other images | |
415 | bool hasHiddenExports() const; | |
416 | ||
417 | // checks if this image is already linked into the process | |
418 | bool isLinked() const; | |
419 | ||
420 | // even if image is deleted, leave segments mapped in | |
421 | void setLeaveMapped(); | |
422 | ||
bac542e6 A |
423 | // even if image is deleted, leave segments mapped in |
424 | bool leaveMapped() { return fLeaveMapped; } | |
425 | ||
412ebb8e | 426 | // image resides in dyld shared cache |
6cae9b63 | 427 | virtual bool inSharedCache() const { return false; }; |
412ebb8e | 428 | |
0959b6d4 A |
429 | // checks if the specifed address is within one of this image's segments |
430 | virtual bool containsAddress(const void* addr) const; | |
431 | ||
39a8cd10 A |
432 | // checks if the specifed symbol is within this image's symbol table |
433 | virtual bool containsSymbol(const void* addr) const = 0; | |
434 | ||
bac542e6 A |
435 | // checks if the specifed address range overlaps any of this image's segments |
436 | virtual bool overlapsWithAddressRange(const void* start, const void* end) const; | |
437 | ||
0959b6d4 | 438 | // adds to list of ranges of memory mapped in |
bac542e6 | 439 | void getMappedRegions(MappedRegion*& region) const; |
0959b6d4 A |
440 | |
441 | // st_mtime from stat() on file | |
bac542e6 | 442 | time_t lastModified() const; |
0959b6d4 | 443 | |
6cae9b63 A |
444 | // only valid for main executables, returns a pointer its entry point from LC_MAIN |
445 | virtual void* getEntryFromLC_MAIN() const = 0; | |
832b6fce | 446 | |
6cae9b63 A |
447 | // only valid for main executables, returns a pointer its main from LC_UNIXTHREAD |
448 | virtual void* getEntryFromLC_UNIXTHREAD() const = 0; | |
0959b6d4 A |
449 | |
450 | // dyld API's require each image to have an associated mach_header | |
451 | virtual const struct mach_header* machHeader() const = 0; | |
452 | ||
453 | // dyld API's require each image to have a slide (actual load address minus preferred load address) | |
454 | virtual uintptr_t getSlide() const = 0; | |
455 | ||
bac542e6 A |
456 | // last address mapped by image |
457 | virtual const void* getEnd() const = 0; | |
0959b6d4 A |
458 | |
459 | // image has exports that participate in runtime coalescing | |
460 | virtual bool hasCoalescedExports() const = 0; | |
9f83892a A |
461 | |
462 | // search symbol table of definitions in this image for requested name | |
463 | virtual bool findExportedSymbolAddress(const LinkContext& context, const char* symbolName, | |
464 | const ImageLoader* requestorImage, int requestorOrdinalOfDef, | |
465 | bool runResolver, const ImageLoader** foundIn, uintptr_t* address) const; | |
466 | ||
467 | // search symbol table of definitions in this image for requested name | |
468 | virtual const Symbol* findExportedSymbol(const char* name, bool searchReExports, const char* thisPath, const ImageLoader** foundIn) const = 0; | |
0959b6d4 A |
469 | |
470 | // search symbol table of definitions in this image for requested name | |
9f83892a A |
471 | virtual const Symbol* findExportedSymbol(const char* name, bool searchReExports, const ImageLoader** foundIn) const { |
472 | return findExportedSymbol(name, searchReExports, this->getPath(), foundIn); | |
473 | } | |
0959b6d4 A |
474 | |
475 | // gets address of implementation (code) of the specified exported symbol | |
412ebb8e | 476 | virtual uintptr_t getExportedSymbolAddress(const Symbol* sym, const LinkContext& context, |
9f83892a | 477 | const ImageLoader* requestor=NULL, bool runResolver=false, const char* symbolName=NULL) const = 0; |
0959b6d4 A |
478 | |
479 | // gets attributes of the specified exported symbol | |
480 | virtual DefinitionFlags getExportedSymbolInfo(const Symbol* sym) const = 0; | |
481 | ||
482 | // gets name of the specified exported symbol | |
483 | virtual const char* getExportedSymbolName(const Symbol* sym) const = 0; | |
484 | ||
485 | // gets how many symbols are exported by this image | |
486 | virtual uint32_t getExportedSymbolCount() const = 0; | |
487 | ||
488 | // gets the i'th exported symbol | |
489 | virtual const Symbol* getIndexedExportedSymbol(uint32_t index) const = 0; | |
490 | ||
491 | // find exported symbol as if imported by this image | |
0be5d81c | 492 | // used by RTLD_NEXT |
bac542e6 | 493 | virtual const Symbol* findExportedSymbolInDependentImages(const char* name, const LinkContext& context, const ImageLoader** foundIn) const; |
0be5d81c A |
494 | |
495 | // find exported symbol as if imported by this image | |
496 | // used by RTLD_SELF | |
bac542e6 | 497 | virtual const Symbol* findExportedSymbolInImageOrDependentImages(const char* name, const LinkContext& context, const ImageLoader** foundIn) const; |
0959b6d4 A |
498 | |
499 | // gets how many symbols are imported by this image | |
500 | virtual uint32_t getImportedSymbolCount() const = 0; | |
501 | ||
502 | // gets the i'th imported symbol | |
503 | virtual const Symbol* getIndexedImportedSymbol(uint32_t index) const = 0; | |
504 | ||
505 | // gets attributes of the specified imported symbol | |
39a8cd10 | 506 | virtual ReferenceFlags getImportedSymbolInfo(const Symbol* sym) const = 0; |
0959b6d4 A |
507 | |
508 | // gets name of the specified imported symbol | |
509 | virtual const char* getImportedSymbolName(const Symbol* sym) const = 0; | |
510 | ||
39a8cd10 A |
511 | // find the closest symbol before addr |
512 | virtual const char* findClosestSymbol(const void* addr, const void** closestAddr) const = 0; | |
513 | ||
9f83892a A |
514 | // for use with accelerator tables |
515 | virtual const char* getIndexedPath(unsigned) const { return getPath(); } | |
516 | virtual const char* getIndexedShortName(unsigned) const { return getShortName(); } | |
517 | ||
0959b6d4 A |
518 | // checks if this image is a bundle and can be loaded but not linked |
519 | virtual bool isBundle() const = 0; | |
520 | ||
521 | // checks if this image is a dylib | |
522 | virtual bool isDylib() const = 0; | |
523 | ||
39a8cd10 A |
524 | // checks if this image is a main executable |
525 | virtual bool isExecutable() const = 0; | |
526 | ||
527 | // checks if this image is a main executable | |
528 | virtual bool isPositionIndependentExecutable() const = 0; | |
529 | ||
0959b6d4 A |
530 | // only for main executable |
531 | virtual bool forceFlat() const = 0; | |
532 | ||
533 | // called at runtime when a lazily bound function is first called | |
797cc951 A |
534 | virtual uintptr_t doBindLazySymbol(uintptr_t* lazyPointer, const LinkContext& context, |
535 | DyldSharedCache::DataConstLazyScopedWriter& patcher) = 0; | |
0959b6d4 | 536 | |
39a8cd10 | 537 | // called at runtime when a fast lazily bound function is first called |
412ebb8e A |
538 | virtual uintptr_t doBindFastLazySymbol(uint32_t lazyBindingInfoOffset, const LinkContext& context, |
539 | void (*lock)(), void (*unlock)()) = 0; | |
39a8cd10 | 540 | |
0959b6d4 A |
541 | // calls termination routines (e.g. C++ static destructors for image) |
542 | virtual void doTermination(const LinkContext& context) = 0; | |
543 | ||
0959b6d4 A |
544 | // return if this image has initialization routines |
545 | virtual bool needsInitialization() = 0; | |
546 | ||
0959b6d4 A |
547 | // return if this image has specified section and set start and length |
548 | virtual bool getSectionContent(const char* segmentName, const char* sectionName, void** start, size_t* length) = 0; | |
39a8cd10 A |
549 | |
550 | // fills in info about __eh_frame and __unwind_info sections | |
551 | virtual void getUnwindInfo(dyld_unwind_sections* info) = 0; | |
552 | ||
6cae9b63 A |
553 | // given a pointer into an image, find which segment and section it is in |
554 | virtual const struct macho_section* findSection(const void* imageInterior) const = 0; | |
555 | ||
0959b6d4 A |
556 | // given a pointer into an image, find which segment and section it is in |
557 | virtual bool findSection(const void* imageInterior, const char** segmentName, const char** sectionName, size_t* sectionOffset) = 0; | |
558 | ||
559 | // the image supports being prebound | |
560 | virtual bool isPrebindable() const = 0; | |
561 | ||
562 | // the image is prebindable and its prebinding is valid | |
563 | virtual bool usablePrebinding(const LinkContext& context) const = 0; | |
564 | ||
bac542e6 A |
565 | // add all RPATH paths this image contains |
566 | virtual void getRPaths(const LinkContext& context, std::vector<const char*>&) const = 0; | |
567 | ||
39a8cd10 A |
568 | // image has or uses weak definitions that need runtime coalescing |
569 | virtual bool participatesInCoalescing() const = 0; | |
570 | ||
571 | // if image has a UUID, copy into parameter and return true | |
572 | virtual bool getUUID(uuid_t) const = 0; | |
19894a12 A |
573 | |
574 | // dynamic interpose values onto this image | |
575 | virtual void dynamicInterpose(const LinkContext& context) = 0; | |
576 | ||
577 | // record interposing for any late binding | |
578 | void addDynamicInterposingTuples(const struct dyld_interpose_tuple array[], size_t count); | |
579 | ||
9f83892a A |
580 | virtual const char* libPath(unsigned int) const = 0; |
581 | ||
582 | // Image has objc sections, so information objc about when it comes and goes | |
583 | virtual bool notifyObjC() const { return false; } | |
584 | ||
6cae9b63 A |
585 | virtual bool overridesCachedDylib(uint32_t& num) const { return false; } |
586 | virtual void setOverridesCachedDylib(uint32_t num) { } | |
587 | ||
588 | ||
39a8cd10 A |
589 | // |
590 | // A segment is a chunk of an executable file that is mapped into memory. | |
591 | // | |
592 | virtual unsigned int segmentCount() const = 0; | |
593 | virtual const char* segName(unsigned int) const = 0; | |
594 | virtual uintptr_t segSize(unsigned int) const = 0; | |
595 | virtual uintptr_t segFileSize(unsigned int) const = 0; | |
596 | virtual bool segHasTrailingZeroFill(unsigned int) = 0; | |
597 | virtual uintptr_t segFileOffset(unsigned int) const = 0; | |
598 | virtual bool segReadable(unsigned int) const = 0; | |
599 | virtual bool segWriteable(unsigned int) const = 0; | |
600 | virtual bool segExecutable(unsigned int) const = 0; | |
601 | virtual bool segUnaccessible(unsigned int) const = 0; | |
602 | virtual bool segHasPreferredLoadAddress(unsigned int) const = 0; | |
603 | virtual uintptr_t segPreferredLoadAddress(unsigned int) const = 0; | |
604 | virtual uintptr_t segActualLoadAddress(unsigned int) const = 0; | |
605 | virtual uintptr_t segActualEndAddress(unsigned int) const = 0; | |
606 | ||
bac542e6 | 607 | |
19894a12 | 608 | // info from LC_VERSION_MIN_MACOSX or LC_VERSION_MIN_IPHONEOS |
2fd3f4e8 | 609 | virtual uint32_t sdkVersion() const = 0; |
19894a12 | 610 | virtual uint32_t minOSVersion() const = 0; |
2fd3f4e8 | 611 | |
412ebb8e | 612 | // if the image contains interposing functions, register them |
6cae9b63 A |
613 | virtual void registerInterposing(const LinkContext& context) = 0; |
614 | ||
615 | virtual bool usesChainedFixups() const { return false; } | |
616 | ||
cf998323 A |
617 | virtual void makeDataReadOnly() const {} |
618 | ||
412ebb8e A |
619 | // when resolving symbols look in subImage if symbol can't be found |
620 | void reExport(ImageLoader* subImage); | |
6cae9b63 | 621 | |
bc3b7c8c | 622 | virtual void recursiveBind(const LinkContext& context, bool forceLazysBound, bool neverUnload, const ImageLoader* parent); |
cf998323 A |
623 | void recursiveBindWithAccounting(const LinkContext& context, bool forceLazysBound, bool neverUnload); |
624 | void recursiveRebaseWithAccounting(const LinkContext& context); | |
2fd3f4e8 A |
625 | void weakBind(const LinkContext& context); |
626 | ||
412ebb8e | 627 | void applyInterposing(const LinkContext& context); |
bac542e6 A |
628 | |
629 | dyld_image_states getState() { return (dyld_image_states)fState; } | |
9f83892a A |
630 | |
631 | ino_t getInode() const { return fInode; } | |
10b92d3b | 632 | dev_t getDevice() const { return fDevice; } |
9f83892a | 633 | |
bac542e6 A |
634 | // used to sort images bottom-up |
635 | int compare(const ImageLoader* right) const; | |
636 | ||
637 | void incrementDlopenReferenceCount() { ++fDlopenReferenceCount; } | |
638 | ||
639 | bool decrementDlopenReferenceCount(); | |
640 | ||
641 | void printReferenceCounts(); | |
642 | ||
2fd3f4e8 A |
643 | uint32_t dlopenCount() const { return fDlopenReferenceCount; } |
644 | ||
645 | void setCanUnload() { fNeverUnload = false; fLeaveMapped = false; } | |
bac542e6 A |
646 | |
647 | bool neverUnload() const { return fNeverUnload; } | |
648 | ||
649 | void setNeverUnload() { fNeverUnload = true; fLeaveMapped = true; } | |
2fd3f4e8 | 650 | void setNeverUnloadRecursive(); |
832b6fce | 651 | |
bc3b7c8c A |
652 | void forEachReExportDependent( void (^callback)(const ImageLoader*, bool& stop)) const; |
653 | ||
832b6fce | 654 | bool isReferencedDownward() { return fIsReferencedDownward; } |
0959b6d4 | 655 | |
cf998323 A |
656 | virtual void recursiveMakeDataReadOnly(const LinkContext& context); |
657 | ||
6cae9b63 | 658 | virtual uintptr_t resolveWeak(const LinkContext& context, const char* symbolName, bool weak_import, bool runResolver, |
797cc951 A |
659 | const ImageLoader** foundIn, |
660 | DyldSharedCache::DataConstLazyScopedWriter& patcher) { return 0; } | |
6cae9b63 | 661 | |
0959b6d4 | 662 | // triggered by DYLD_PRINT_STATISTICS to write info on work done and how fast |
412ebb8e | 663 | static void printStatistics(unsigned int imageCount, const InitializerTimingList& timingInfo); |
9f83892a A |
664 | static void printStatisticsDetails(unsigned int imageCount, const InitializerTimingList& timingInfo); |
665 | ||
0959b6d4 A |
666 | // used with DYLD_IMAGE_SUFFIX |
667 | static void addSuffix(const char* path, const char* suffix, char* result); | |
668 | ||
669 | static uint32_t hash(const char*); | |
39a8cd10 | 670 | |
9f83892a A |
671 | static const uint8_t* trieWalk(const uint8_t* start, const uint8_t* end, const char* stringToFind); |
672 | ||
39a8cd10 A |
673 | // used instead of directly deleting image |
674 | static void deleteImage(ImageLoader*); | |
9f83892a A |
675 | |
676 | static bool haveInterposingTuples() { return !fgInterposingTuples.empty(); } | |
677 | static void clearInterposingTuples() { fgInterposingTuples.clear(); } | |
678 | ||
6cae9b63 A |
679 | static void applyInterposingToDyldCache(const LinkContext& context); |
680 | ||
2fd3f4e8 A |
681 | bool dependsOn(ImageLoader* image); |
682 | ||
683 | void setPath(const char* path); | |
832b6fce | 684 | void setPaths(const char* path, const char* realPath); |
bac542e6 | 685 | void setPathUnowned(const char* path); |
39a8cd10 | 686 | |
bac542e6 | 687 | void clearDepth() { fDepth = 0; } |
832b6fce | 688 | int getDepth() { return fDepth; } |
bac542e6 A |
689 | |
690 | void setBeingRemoved() { fBeingRemoved = true; } | |
691 | bool isBeingRemoved() const { return fBeingRemoved; } | |
692 | ||
2fd3f4e8 A |
693 | void markNotUsed() { fMarkedInUse = false; } |
694 | void markedUsedRecursive(const std::vector<DynamicReference>&); | |
695 | bool isMarkedInUse() const { return fMarkedInUse; } | |
cf998323 | 696 | |
2028a915 A |
697 | void setAddFuncNotified() { fAddFuncNotified = true; } |
698 | bool addFuncNotified() const { return fAddFuncNotified; } | |
bac542e6 | 699 | |
cf998323 A |
700 | void setObjCMappedNotified() { fObjCMappedNotified = true; } |
701 | bool objCMappedNotified() const { return fObjCMappedNotified; } | |
702 | ||
2fd3f4e8 | 703 | struct InterposeTuple { |
797cc951 A |
704 | uintptr_t replacement; |
705 | dyld3::AuthenticatedValue<const ImageLoader*> neverImage; // don't apply replacement to this image | |
706 | dyld3::AuthenticatedValue<const ImageLoader*> onlyImage; // only apply replacement to this image | |
707 | uintptr_t replacee; | |
2fd3f4e8 A |
708 | }; |
709 | ||
9f83892a A |
710 | static uintptr_t read_uleb128(const uint8_t*& p, const uint8_t* end); |
711 | static intptr_t read_sleb128(const uint8_t*& p, const uint8_t* end); | |
712 | ||
6cae9b63 A |
713 | void vmAccountingSetSuspended(const LinkContext& context, bool suspend); |
714 | ||
39a8cd10 | 715 | protected: |
0959b6d4 | 716 | // abstract base class so all constructors protected |
39a8cd10 | 717 | ImageLoader(const char* path, unsigned int libCount); |
0959b6d4 A |
718 | ImageLoader(const ImageLoader&); |
719 | void operator=(const ImageLoader&); | |
2fd3f4e8 | 720 | void operator delete(void* image) throw() { ::free(image); } |
0959b6d4 A |
721 | |
722 | ||
723 | struct LibraryInfo { | |
bac542e6 | 724 | uint32_t checksum; |
0959b6d4 A |
725 | uint32_t minVersion; |
726 | uint32_t maxVersion; | |
727 | }; | |
728 | ||
729 | struct DependentLibrary { | |
0959b6d4 | 730 | ImageLoader* image; |
bac542e6 A |
731 | uint32_t required : 1, |
732 | checksumMatches : 1, | |
733 | isReExported : 1, | |
734 | isSubFramework : 1; | |
0959b6d4 A |
735 | }; |
736 | ||
bac542e6 A |
737 | struct DependentLibraryInfo { |
738 | const char* name; | |
739 | LibraryInfo info; | |
740 | bool required; | |
741 | bool reExported; | |
412ebb8e | 742 | bool upward; |
bac542e6 A |
743 | }; |
744 | ||
bac542e6 A |
745 | |
746 | typedef void (*Initializer)(int argc, const char* argv[], const char* envp[], const char* apple[], const ProgramVars* vars); | |
0959b6d4 A |
747 | typedef void (*Terminator)(void); |
748 | ||
39a8cd10 A |
749 | |
750 | ||
751 | unsigned int libraryCount() const { return fLibraryCount; } | |
752 | virtual ImageLoader* libImage(unsigned int) const = 0; | |
753 | virtual bool libReExported(unsigned int) const = 0; | |
412ebb8e A |
754 | virtual bool libIsUpward(unsigned int) const = 0; |
755 | virtual void setLibImage(unsigned int, ImageLoader*, bool, bool) = 0; | |
39a8cd10 | 756 | |
0959b6d4 A |
757 | // To link() an image, its dependent libraries are loaded, it is rebased, bound, and initialized. |
758 | // These methods do the above, exactly once, and it the right order | |
9f83892a | 759 | virtual void recursiveLoadLibraries(const LinkContext& context, bool preflightOnly, const RPathChain& loaderRPaths, const char* loadPath); |
bc3b7c8c A |
760 | virtual unsigned recursiveUpdateDepth(unsigned int maxDepth, dyld3::Array<ImageLoader*>& danglingUpwards); |
761 | virtual unsigned updateDepth(unsigned int maxDepth); | |
9f83892a | 762 | virtual void recursiveRebase(const LinkContext& context); |
9f83892a A |
763 | virtual void recursiveApplyInterposing(const LinkContext& context); |
764 | virtual void recursiveGetDOFSections(const LinkContext& context, std::vector<DOFInfo>& dofs); | |
765 | virtual void recursiveInitialization(const LinkContext& context, mach_port_t this_thread, const char* pathToInitialize, | |
19894a12 | 766 | ImageLoader::InitializerTimingList&, ImageLoader::UninitedUpwards&); |
0959b6d4 | 767 | |
39a8cd10 | 768 | // fill in information about dependent libraries (array length is fLibraryCount) |
bac542e6 | 769 | virtual void doGetDependentLibraries(DependentLibraryInfo libs[]) = 0; |
0959b6d4 A |
770 | |
771 | // called on images that are libraries, returns info about itself | |
9f83892a | 772 | virtual LibraryInfo doGetLibraryInfo(const LibraryInfo& requestorInfo) = 0; |
0959b6d4 A |
773 | |
774 | // do any fix ups in this image that depend only on the load address of the image | |
775 | virtual void doRebase(const LinkContext& context) = 0; | |
776 | ||
777 | // do any symbolic fix ups in this image | |
bc3b7c8c | 778 | virtual void doBind(const LinkContext& context, bool forceLazysBound, const ImageLoader* reExportParent) = 0; |
bac542e6 | 779 | |
2028a915 | 780 | // called later via API to force all lazy pointer to be bound |
797cc951 | 781 | virtual void doBindJustLazies(const LinkContext& context, DyldSharedCache::DataConstLazyScopedWriter& patcher) = 0; |
2028a915 | 782 | |
bac542e6 A |
783 | // if image has any dtrace DOF sections, append them to list to be registered |
784 | virtual void doGetDOFSections(const LinkContext& context, std::vector<DOFInfo>& dofs) = 0; | |
0959b6d4 | 785 | |
412ebb8e A |
786 | // do interpose |
787 | virtual void doInterpose(const LinkContext& context) = 0; | |
788 | ||
0959b6d4 | 789 | // run any initialization routines in this image |
412ebb8e | 790 | virtual bool doInitialization(const LinkContext& context) = 0; |
0959b6d4 | 791 | |
0959b6d4 A |
792 | // return if this image has termination routines |
793 | virtual bool needsTermination() = 0; | |
794 | ||
795 | // support for runtimes in which segments don't have to maintain their relative positions | |
796 | virtual bool segmentsMustSlideTogether() const = 0; | |
797 | ||
798 | // built with PIC code and can load at any address | |
799 | virtual bool segmentsCanSlide() const = 0; | |
9f83892a | 800 | |
0959b6d4 A |
801 | // set how much all segments slide |
802 | virtual void setSlide(intptr_t slide) = 0; | |
9f83892a | 803 | |
0959b6d4 A |
804 | // returns if all dependent libraries checksum's were as expected and none slide |
805 | bool allDependentLibrariesAsWhenPreBound() const; | |
806 | ||
807 | // in mach-o a child tells it parent to re-export, instead of the other way around... | |
808 | virtual bool isSubframeworkOf(const LinkContext& context, const ImageLoader* image) const = 0; | |
809 | ||
810 | // in mach-o a parent library knows name of sub libraries it re-exports.. | |
811 | virtual bool hasSubLibrary(const LinkContext& context, const ImageLoader* child) const = 0; | |
9f83892a | 812 | |
a9a4db61 | 813 | virtual bool weakSymbolsBound(unsigned index) const { return fWeakSymbolsBound; } |
9f83892a A |
814 | virtual void setWeakSymbolsBound(unsigned index) { fWeakSymbolsBound = true; } |
815 | ||
bac542e6 A |
816 | // set fState to dyld_image_state_memory_mapped |
817 | void setMapped(const LinkContext& context); | |
2fd3f4e8 | 818 | |
39a8cd10 | 819 | void setFileInfo(dev_t device, ino_t inode, time_t modDate); |
9f83892a A |
820 | |
821 | void setDepth(uint16_t depth) { fDepth = depth; } | |
822 | ||
19894a12 A |
823 | static uintptr_t interposedAddress(const LinkContext& context, uintptr_t address, const ImageLoader* notInImage, const ImageLoader* onlyInImage=NULL); |
824 | ||
39a8cd10 | 825 | static uintptr_t fgNextPIEDylibAddress; |
0959b6d4 | 826 | static uint32_t fgImagesWithUsedPrebinding; |
bac542e6 | 827 | static uint32_t fgImagesUsedFromSharedCache; |
39a8cd10 A |
828 | static uint32_t fgImagesHasWeakDefinitions; |
829 | static uint32_t fgImagesRequiringCoalescing; | |
0959b6d4 A |
830 | static uint32_t fgTotalRebaseFixups; |
831 | static uint32_t fgTotalBindFixups; | |
bac542e6 A |
832 | static uint32_t fgTotalBindSymbolsResolved; |
833 | static uint32_t fgTotalBindImageSearches; | |
0959b6d4 A |
834 | static uint32_t fgTotalLazyBindFixups; |
835 | static uint32_t fgTotalPossibleLazyBindFixups; | |
bac542e6 | 836 | static uint32_t fgTotalSegmentsMapped; |
9f83892a | 837 | static uint32_t fgSymbolTrieSearchs; |
bac542e6 | 838 | static uint64_t fgTotalBytesMapped; |
0959b6d4 | 839 | static uint64_t fgTotalLoadLibrariesTime; |
9f83892a A |
840 | public: |
841 | static uint64_t fgTotalObjCSetupTime; | |
842 | static uint64_t fgTotalDebuggerPausedTime; | |
843 | static uint64_t fgTotalRebindCacheTime; | |
0959b6d4 A |
844 | static uint64_t fgTotalRebaseTime; |
845 | static uint64_t fgTotalBindTime; | |
39a8cd10 A |
846 | static uint64_t fgTotalWeakBindTime; |
847 | static uint64_t fgTotalDOF; | |
0959b6d4 | 848 | static uint64_t fgTotalInitTime; |
6cae9b63 A |
849 | |
850 | protected: | |
412ebb8e | 851 | static std::vector<InterposeTuple> fgInterposingTuples; |
2fd3f4e8 | 852 | |
bc3b7c8c A |
853 | #if __x86_64__ |
854 | const char* fAotPath; | |
855 | #endif | |
0959b6d4 | 856 | const char* fPath; |
832b6fce | 857 | const char* fRealPath; |
0959b6d4 A |
858 | dev_t fDevice; |
859 | ino_t fInode; | |
860 | time_t fLastModified; | |
0959b6d4 | 861 | uint32_t fPathHash; |
bac542e6 | 862 | uint32_t fDlopenReferenceCount; // count of how many dlopens have been done on this image |
0959b6d4 | 863 | |
bac542e6 A |
864 | struct recursive_lock { |
865 | recursive_lock(mach_port_t t) : thread(t), count(0) {} | |
866 | mach_port_t thread; | |
867 | int count; | |
868 | }; | |
869 | void recursiveSpinLock(recursive_lock&); | |
870 | void recursiveSpinUnLock(); | |
bac542e6 | 871 | |
9f83892a | 872 | private: |
bac542e6 A |
873 | const ImageLoader::Symbol* findExportedSymbolInDependentImagesExcept(const char* name, const ImageLoader** dsiStart, |
874 | const ImageLoader**& dsiCur, const ImageLoader** dsiEnd, const ImageLoader** foundIn) const; | |
875 | ||
19894a12 A |
876 | void processInitializers(const LinkContext& context, mach_port_t this_thread, |
877 | InitializerTimingList& timingInfo, ImageLoader::UninitedUpwards& ups); | |
bac542e6 | 878 | |
a9a4db61 A |
879 | void weakBindOld(const LinkContext& context); |
880 | ||
bac542e6 | 881 | |
39a8cd10 | 882 | recursive_lock* fInitializerRecursiveLock; |
cf998323 A |
883 | union { |
884 | struct { | |
885 | uint16_t fLoadOrder; | |
886 | uint16_t fDepth : 15, | |
887 | fObjCMappedNotified : 1; | |
888 | uint32_t fState : 8, | |
889 | fLibraryCount : 9, | |
890 | fMadeReadOnly : 1, | |
891 | fAllLibraryChecksumsAndLoadAddressesMatch : 1, | |
892 | fLeaveMapped : 1, // when unloaded, leave image mapped in cause some other code may have pointers into it | |
893 | fNeverUnload : 1, // image was statically loaded by main executable | |
894 | fHideSymbols : 1, // ignore this image's exported symbols when linking other images | |
895 | fMatchByInstallName : 1,// look at image's install-path not its load path | |
896 | fInterposed : 1, | |
897 | fRegisteredDOF : 1, | |
898 | fAllLazyPointersBound : 1, | |
899 | fMarkedInUse : 1, | |
900 | fBeingRemoved : 1, | |
901 | fAddFuncNotified : 1, | |
902 | fPathOwnedByImage : 1, | |
903 | fIsReferencedDownward : 1, | |
904 | fWeakSymbolsBound : 1; | |
905 | }; | |
906 | uint64_t sizeOfData; | |
907 | }; | |
908 | static_assert(sizeof(sizeOfData) == 8, "Bad data size"); | |
bac542e6 | 909 | |
bac542e6 | 910 | static uint16_t fgLoadOrdinal; |
bc3b7c8c | 911 | |
0959b6d4 A |
912 | }; |
913 | ||
914 | ||
2fd3f4e8 | 915 | VECTOR_NEVER_DESTRUCTED_EXTERN(ImageLoader::InterposeTuple); |
0959b6d4 A |
916 | |
917 | ||
918 | #endif | |
919 |