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