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