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