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