]> git.saurik.com Git - apple/dyld.git/blame - src/ImageLoader.h
dyld-851.27.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>
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
123namespace 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}
132extern "C" int vm_alloc(vm_address_t* addr, vm_size_t size, uint32_t flags);
133extern "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
162struct 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
173enum 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};
183typedef 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//
195class ImageLoader {
196public:
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 715protected:
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
840public:
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
850protected:
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 872private:
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 915VECTOR_NEVER_DESTRUCTED_EXTERN(ImageLoader::InterposeTuple);
0959b6d4
A
916
917
918#endif
919