]> git.saurik.com Git - apple/dyld.git/blobdiff - src/ImageLoader.h
dyld-353.2.3.tar.gz
[apple/dyld.git] / src / ImageLoader.h
index 609c222cff75a7e065be94eeff14f42e24eafeef..6f4c3bc6f14b2623771b035212135676ec2329f7 100644 (file)
@@ -1,6 +1,6 @@
 /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
  *
- * Copyright (c) 2004 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2004-2010 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
 #define __IMAGELOADER__
 
 #include <sys/types.h>
+#include <unistd.h>
+#include <stdlib.h>
 #include <mach/mach_time.h> // struct mach_timebase_info
+#include <mach/mach_init.h> // struct mach_thread_self
+#include <mach/shared_region.h>
+#include <mach-o/loader.h> 
+#include <mach-o/nlist.h> 
 #include <stdint.h>
+#include <stdlib.h>
+#include <TargetConditionals.h>
 #include <vector>
+#include <new>
 
-#include "mach-o/dyld_gdb.h"
+#if __arm__
+ #include <mach/vm_page_size.h>
+#endif
+
+#if __x86_64__ || __i386__
+       #include <CrashReporterClient.h>
+#else
+       // work around until iOS has CrashReporterClient.h
+       #define CRSetCrashLogMessage(x)
+       #define CRSetCrashLogMessage2(x)
+#endif
+
+#ifndef SHARED_REGION_BASE_ARM64
+       #define SHARED_REGION_BASE_ARM64 0x7FFF80000000LL
+#endif
+
+#ifndef SHARED_REGION_SIZE_ARM64
+       #define SHARED_REGION_SIZE_ARM64 0x10000000LL
+#endif
+
+
+#define LOG_BINDINGS 0
+
+#include "mach-o/dyld_images.h"
+#include "mach-o/dyld_priv.h"
+
+#if __i386__
+       #define SHARED_REGION_BASE SHARED_REGION_BASE_I386
+       #define SHARED_REGION_SIZE SHARED_REGION_SIZE_I386
+#elif __x86_64__
+       #define SHARED_REGION_BASE SHARED_REGION_BASE_X86_64
+       #define SHARED_REGION_SIZE SHARED_REGION_SIZE_X86_64
+#elif __arm__
+       #define SHARED_REGION_BASE SHARED_REGION_BASE_ARM
+       #define SHARED_REGION_SIZE SHARED_REGION_SIZE_ARM
+#elif __arm64__
+       #define SHARED_REGION_BASE SHARED_REGION_BASE_ARM64
+       #define SHARED_REGION_SIZE SHARED_REGION_SIZE_ARM64
+#endif
+
+#ifndef EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER
+       #define EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER 0x10
+#endif
+#ifndef EXPORT_SYMBOL_FLAGS_REEXPORT
+       #define EXPORT_SYMBOL_FLAGS_REEXPORT 0x08
+#endif
+
+#ifndef LC_MAIN
+       #define LC_MAIN (0x28|LC_REQ_DYLD) /* replacement for LC_UNIXTHREAD */
+       struct entry_point_command {
+               uint32_t  cmd;  /* LC_MAIN only used in MH_EXECUTE filetypes */
+               uint32_t  cmdsize;      /* 24 */
+               uint64_t  entryoff;     /* file (__TEXT) offset of main() */
+               uint64_t  stacksize;/* if not zero, initial stack size */
+       };
+#endif
+
+#if __IPHONE_OS_VERSION_MIN_REQUIRED          
+       #define SPLIT_SEG_SHARED_REGION_SUPPORT 0
+       #define SPLIT_SEG_DYLIB_SUPPORT                 0
+       #define PREBOUND_IMAGE_SUPPORT                  __arm__
+       #define TEXT_RELOC_SUPPORT                              __i386__
+       #define DYLD_SHARED_CACHE_SUPPORT               (__arm__ || __arm64__)
+       #define SUPPORT_OLD_CRT_INITIALIZATION  0
+       #define SUPPORT_LC_DYLD_ENVIRONMENT             0
+       #define SUPPORT_VERSIONED_PATHS                 0
+       #define SUPPORT_CLASSIC_MACHO                   __arm__
+       #define SUPPORT_ZERO_COST_EXCEPTIONS    (!__USING_SJLJ_EXCEPTIONS__)
+       #define INITIAL_IMAGE_COUNT                             256
+#else
+       #define SPLIT_SEG_SHARED_REGION_SUPPORT 0
+       #define SPLIT_SEG_DYLIB_SUPPORT                 __i386__
+       #define PREBOUND_IMAGE_SUPPORT                  __i386__
+       #define TEXT_RELOC_SUPPORT                              __i386__
+       #define DYLD_SHARED_CACHE_SUPPORT               1
+       #define SUPPORT_OLD_CRT_INITIALIZATION  __i386__
+       #define SUPPORT_LC_DYLD_ENVIRONMENT             (__i386__ || __x86_64__)
+       #define SUPPORT_VERSIONED_PATHS                 1
+       #define SUPPORT_CLASSIC_MACHO                   1
+       #define SUPPORT_ZERO_COST_EXCEPTIONS    1
+       #define INITIAL_IMAGE_COUNT                             200
+#endif
+
+
+
+// <rdar://problem/13590567> optimize away dyld's initializers
+#define VECTOR_NEVER_DESTRUCTED(type) \
+       namespace std { \
+               template <> \
+               __vector_base<type, std::allocator<type> >::~__vector_base() { } \
+       }
+#define VECTOR_NEVER_DESTRUCTED_EXTERN(type) \
+       namespace std { \
+               template <> \
+               __vector_base<type, std::allocator<type> >::~__vector_base(); \
+       }
+#define VECTOR_NEVER_DESTRUCTED_IMPL(type) \
+       namespace std { \
+               template <> \
+               __vector_base<type, std::allocator<type> >::~__vector_base() { } \
+       }
+
+// utilities
+namespace dyld {
+       extern __attribute__((noreturn)) void throwf(const char* format, ...)  __attribute__((format(printf, 1, 2)));
+       extern void log(const char* format, ...)  __attribute__((format(printf, 1, 2)));
+       extern void warn(const char* format, ...)  __attribute__((format(printf, 1, 2)));
+       extern const char* mkstringf(const char* format, ...)  __attribute__((format(printf, 1, 2)));
+#if LOG_BINDINGS
+       extern void logBindings(const char* format, ...)  __attribute__((format(printf, 1, 2)));
+#endif
+}
+extern "C"     int   vm_alloc(vm_address_t* addr, vm_size_t size, uint32_t flags);
+extern "C"     void* xmmap(void* addr, size_t len, int prot, int flags, int fd, off_t offset);
+
+
+#if __LP64__
+       struct macho_header                             : public mach_header_64  {};
+       struct macho_nlist                              : public nlist_64  {};  
+#else
+       struct macho_header                             : public mach_header  {};
+       struct macho_nlist                              : public nlist  {};     
+#endif
+
+
+#if __arm64__
+       #define dyld_page_trunc(__addr)     (__addr & (-16384))
+       #define dyld_page_round(__addr)     ((__addr + 16383) & (-16384))
+       #define dyld_page_size              16384
+#elif __arm__
+       #define dyld_page_trunc(__addr)     trunc_page_kernel(__addr)
+       #define dyld_page_round(__addr)     round_page_kernel(__addr)
+       #define dyld_page_size              vm_kernel_page_size
+#else
+       #define dyld_page_trunc(__addr)     (__addr & (-4096))
+       #define dyld_page_round(__addr)     ((__addr + 4095) & (-4096))
+       #define dyld_page_size              4096
+#endif
+
+
+
+struct ProgramVars
+{
+       const void*             mh;
+       int*                    NXArgcPtr;
+       const char***   NXArgvPtr;
+       const char***   environPtr;
+       const char**    __prognamePtr;
+};
 
 
-// utility
-__attribute__((noreturn)) void throwf(const char* format, ...);
 
 //
 // ImageLoader is an abstract base class.  To support loading a particular executable
@@ -59,12 +214,9 @@ public:
        static const ReferenceFlags kWeakReference = 1;
        static const ReferenceFlags kTentativeDefinition = 2;
        
-
-       enum BindingLaziness { kNonLazyOnly, kLazyAndNonLazy, kLazyOnly, kLazyOnlyNoDependents };
-       enum InitializerRunning { kDontRunInitializers, kRunInitializers, kDontRunInitializersButTellObjc };
        enum PrebindMode { kUseAllPrebinding, kUseSplitSegPrebinding, kUseAllButAppPredbinding, kUseNoPrebinding };
        enum BindingOptions { kBindingNone, kBindingLazyPointers, kBindingNeverSetLazyPointers };
-       enum SharedRegionMode { kUseSharedRegion, kUsePrivateSharedRegion, kDontUseSharedRegion };
+       enum SharedRegionMode { kUseSharedRegion, kUsePrivateSharedRegion, kDontUseSharedRegion, kSharedRegionIsSharedCache };
        
        struct Symbol;  // abstact symbol
 
@@ -72,55 +224,140 @@ public:
                uintptr_t       address;
                size_t          size;
        };
-       typedef std::vector<MappedRegion> RegionsVector;
 
+       struct RPathChain {
+               RPathChain(const RPathChain* n, std::vector<const char*>* p) : next(n), paths(p) {};
+               const RPathChain*                       next;
+               std::vector<const char*>*       paths;
+       };
+
+       struct DOFInfo {
+               void*                           dof;
+               const mach_header*      imageHeader;
+               const char*                     imageShortName;
+       };
+
+       struct DynamicReference {
+               ImageLoader* from;
+               ImageLoader* to;
+       };
+       
        struct LinkContext {
-               ImageLoader*    (*loadLibrary)(const char* libraryName, bool search, const char* origin, const char* rpath[]);
-               uint32_t                (*imageNotification)(ImageLoader* image, uint32_t startIndex);
+               ImageLoader*    (*loadLibrary)(const char* libraryName, bool search, const char* origin, const RPathChain* rpaths);
                void                    (*terminationRecorder)(ImageLoader* image);
-               bool                    (*flatExportFinder)(const char* name, const Symbol** sym, ImageLoader** image);
-               bool                    (*coalescedExportFinder)(const char* name, const Symbol** sym, ImageLoader** image);
+               bool                    (*flatExportFinder)(const char* name, const Symbol** sym, const ImageLoader** image);
+               bool                    (*coalescedExportFinder)(const char* name, const Symbol** sym, const ImageLoader** image);
+               unsigned int    (*getCoalescedImages)(ImageLoader* images[]);
                void                    (*undefinedHandler)(const char* name);
-               void                    (*addImageNeedingNotification)(ImageLoader* image);
-               void                    (*notifyAdding)(std::vector<ImageLoader*>& images);
-               void                    (*getAllMappedRegions)(RegionsVector&);
+               MappedRegion*   (*getAllMappedRegions)(MappedRegion*);
                void *                  (*bindingHandler)(const char *, const char *, void *);
+               void                    (*notifySingle)(dyld_image_states, const ImageLoader* image);
+               void                    (*notifyBatch)(dyld_image_states state);
+               void                    (*removeImage)(ImageLoader* image);
+               void                    (*registerDOFs)(const std::vector<DOFInfo>& dofs);
+               void                    (*clearAllDepths)();
+               void                    (*printAllDepths)();
+               unsigned int    (*imageCount)();
+               void                    (*setNewProgramVars)(const ProgramVars&);
+               bool                    (*inSharedCache)(const char* path);
+               void                    (*setErrorStrings)(unsigned errorCode, const char* errorClientOfDylibPath,
+                                                                               const char* errorTargetDylibPath, const char* errorSymbol);
+               ImageLoader*    (*findImageContainingAddress)(const void* addr);
+               void                    (*addDynamicReference)(ImageLoader* from, ImageLoader* to);
+               
+#if SUPPORT_OLD_CRT_INITIALIZATION
+               void                    (*setRunInitialzersOldWay)();
+#endif
                BindingOptions  bindingOptions;
                int                             argc;
                const char**    argv;
                const char**    envp;
                const char**    apple;
+               const char*             progname;
+               ProgramVars             programVars;
                ImageLoader*    mainExecutable;
                const char*             imageSuffix;
+               const char**    rootPaths;
+               const dyld_interpose_tuple*     dynamicInterposeArray;
+               size_t                  dynamicInterposeCount;
                PrebindMode             prebindUsage;
                SharedRegionMode sharedRegionMode;
+               bool                    dyldLoadedAtSameAddressNeededBySharedCache;
+               bool                    codeSigningEnforced;
+               bool                    mainExecutableCodeSigned;
+               bool                    preFetchDisabled;
+               bool                    prebinding;
                bool                    bindFlat;
-               bool                    slideAndPackDylibs;
+               bool                    linkingMainExecutable;
+               bool                    startedInitializingMainExecutable;
+               bool                    processIsRestricted;
                bool                    verboseOpts;
                bool                    verboseEnv;
                bool                    verboseMapping;
                bool                    verboseRebase;
                bool                    verboseBind;
+               bool                    verboseWeakBind;
                bool                    verboseInit;
+               bool                    verboseDOF;
                bool                    verbosePrebinding;
+               bool                    verboseCoreSymbolication;
                bool                    verboseWarnings;
+               bool                    verboseRPaths;
+               bool                    verboseInterposing;
+               bool                    verboseCodeSignatures;
        };
        
+       struct CoalIterator
+       {
+               ImageLoader*    image;
+               const char*             symbolName;
+               unsigned int    loadOrder;
+               bool                    weakSymbol;
+               bool                    symbolMatches;
+               bool                    done;
+               // the following are private to the ImageLoader subclass
+               uintptr_t               curIndex;
+               uintptr_t               endIndex;
+               uintptr_t               address;
+               uintptr_t               type;
+               uintptr_t               addend;
+       };
+       
+       virtual void                    initializeCoalIterator(CoalIterator&, unsigned int loadOrder) = 0;
+       virtual bool                    incrementCoalIterator(CoalIterator&) = 0;
+       virtual uintptr_t               getAddressCoalIterator(CoalIterator&, const LinkContext& context) = 0;
+       virtual void                    updateUsesCoalIterator(CoalIterator&, uintptr_t newAddr, ImageLoader* target, const LinkContext& context) = 0;
+       
+       struct InitializerTimingList
+       {
+               uintptr_t       count;
+               struct {
+                       ImageLoader*    image;
+                       uint64_t                initTime;
+               }                       images[1];
+       };
+       
+       struct UninitedUpwards
+       {
+               uintptr_t        count;
+               ImageLoader* images[1];
+       };
+
+       
                                                                                // constructor is protected, but anyone can delete an image
        virtual                                                         ~ImageLoader();
        
                                                                                // link() takes a newly instantiated ImageLoader and does all 
                                                                                // fixups needed to make it usable by the process
-       void                                                            link(const LinkContext& context, BindingLaziness mode, InitializerRunning inits, uint32_t notifyCount);
+       void                                                            link(const LinkContext& context, bool forceLazysBound, bool preflight, bool neverUnload, const RPathChain& loaderRPaths);
        
                                                                                // runInitializers() is normally called in link() but the main executable must 
                                                                                // run crt code before initializers
-       void                                                            runInitializers(const LinkContext& context);
+       void                                                            runInitializers(const LinkContext& context, InitializerTimingList& timingInfo);
+       
+                                                                               // called after link() forces all lazy pointers to be bound
+       void                                                            bindAllLazyPointers(const LinkContext& context, bool recursive);
        
-                                                                               // runNotification() is normally called in link() but the main executable must 
-                                                                               // run crt code before initializers
-       void                                                            runNotification(const LinkContext& context, uint32_t notifyCount);
-               
                                                                                // used by dyld to see if a requested library is already loaded (might be symlink)
        bool                                                            statMatch(const struct stat& stat_buf) const;
 
@@ -132,8 +369,8 @@ public:
 
        uint32_t                                                        getPathHash() const { return fPathHash; }
 
-                                                                               // get path used to load this image represents (ZeroLink only) which image this .o is part of
-       const char*                                                     getLogicalPath() const;
+                                                                               // get the "real" path for this image (e.g. no @rpath)
+       const char*                                                     getRealPath() const;
 
                                                                                // get path this image is intended to be placed on disk or NULL if no preferred install location
        virtual const char*                                     getInstallPath() const = 0;
@@ -142,9 +379,6 @@ public:
        bool                                                            matchInstallPath() const;
        void                                                            setMatchInstallPath(bool);
        
-                                                                               // if path was a fat file, offset of image loaded in that fat file
-       uint64_t                                                        getOffsetInFatFile() const;
-
                                                                                // mark that this image's exported symbols should be ignored when linking other images (e.g. RTLD_LOCAL)
        void                                                            setHideExports(bool hide = true);
        
@@ -157,22 +391,31 @@ public:
                                                                                // even if image is deleted, leave segments mapped in
        void                                                            setLeaveMapped();
        
+                                                                               // even if image is deleted, leave segments mapped in
+       bool                                                            leaveMapped() { return fLeaveMapped; }
+
+                                                                               // image resides in dyld shared cache
+       virtual bool                                            inSharedCache() const = 0;
+
                                                                                // checks if the specifed address is within one of this image's segments
        virtual bool                                            containsAddress(const void* addr) const;
 
+                                                                               // checks if the specifed symbol is within this image's symbol table
+       virtual bool                                            containsSymbol(const void* addr) const = 0;
+
+                                                                               // checks if the specifed address range overlaps any of this image's segments
+       virtual bool                                            overlapsWithAddressRange(const void* start, const void* end) const;
+
                                                                                // adds to list of ranges of memory mapped in
-       void                                                            addMappedRegions(RegionsVector& regions) const;
+       void                                                            getMappedRegions(MappedRegion*& region) const;
 
                                                                                // st_mtime from stat() on file
-       time_t                                                          lastModified();
+       time_t                                                          lastModified() const;
 
-                                                                               // image should create prebound version of itself
-       void                                                            reprebind(const LinkContext& context, time_t timestamp);
-       
-                                                                               // if 'commit', the prebound version should be swapped in, otherwise deleted
-       void                                                            reprebindCommit(const LinkContext& context, bool commit);
+                                                                               // only valid for main executables, returns a pointer its entry point from LC_UNIXTHREAD
+       virtual void*                                           getThreadPC() const = 0;
        
-                                                                               // only valid for main executables, returns a pointer its entry point
+                                                                               // only valid for main executables, returns a pointer its main from LC_<MAIN
        virtual void*                                           getMain() const = 0;
        
                                                                                // dyld API's require each image to have an associated mach_header
@@ -181,17 +424,18 @@ public:
                                                                                // dyld API's require each image to have a slide (actual load address minus preferred load address)
        virtual uintptr_t                                       getSlide() const = 0;
        
-                                                                               // dyld API's require each image to have a slide (actual load address minus preferred load address)
-       virtual const void*                                     getBaseAddress() const = 0;
+                                                                               // last address mapped by image
+       virtual const void*                                     getEnd() const = 0;
        
                                                                                // image has exports that participate in runtime coalescing
        virtual bool                                            hasCoalescedExports() const = 0;
        
                                                                                // search symbol table of definitions in this image for requested name
-       virtual const Symbol*                           findExportedSymbol(const char* name, const void* hint, bool searchReExports, ImageLoader** foundIn) const = 0;
+       virtual const Symbol*                           findExportedSymbol(const char* name, bool searchReExports, const ImageLoader** foundIn) const = 0;
        
                                                                                // gets address of implementation (code) of the specified exported symbol
-       virtual uintptr_t                                       getExportedSymbolAddress(const Symbol* sym) const = 0;
+       virtual uintptr_t                                       getExportedSymbolAddress(const Symbol* sym, const LinkContext& context, 
+                                                                                                       const ImageLoader* requestor=NULL, bool runResolver=false) const = 0;
        
                                                                                // gets attributes of the specified exported symbol
        virtual DefinitionFlags                         getExportedSymbolInfo(const Symbol* sym) const = 0;
@@ -206,8 +450,12 @@ public:
        virtual const Symbol*                           getIndexedExportedSymbol(uint32_t index) const = 0;
                        
                                                                                // find exported symbol as if imported by this image
-                                                                               // used by RTLD_NEXT and RTLD_SELF
-       virtual const Symbol*                           resolveSymbol(const char* name, bool searchSelf, ImageLoader** foundIn) const;
+                                                                               // used by RTLD_NEXT
+       virtual const Symbol*                           findExportedSymbolInDependentImages(const char* name, const LinkContext& context, const ImageLoader** foundIn) const;
+       
+                                                                               // find exported symbol as if imported by this image
+                                                                               // used by RTLD_SELF
+       virtual const Symbol*                           findExportedSymbolInImageOrDependentImages(const char* name, const LinkContext& context, const ImageLoader** foundIn) const;
        
                                                                                // gets how many symbols are imported by this image
        virtual uint32_t                                        getImportedSymbolCount() const = 0;
@@ -216,38 +464,48 @@ public:
        virtual const Symbol*                           getIndexedImportedSymbol(uint32_t index) const = 0;
                        
                                                                                // gets attributes of the specified imported symbol
-       virtual ReferenceFlags                          geImportedSymbolInfo(const Symbol* sym) const = 0;
+       virtual ReferenceFlags                          getImportedSymbolInfo(const Symbol* sym) const = 0;
                        
                                                                                // gets name of the specified imported symbol
        virtual const char*                                     getImportedSymbolName(const Symbol* sym) const = 0;
                        
+                                                                               // find the closest symbol before addr
+       virtual const char*                                     findClosestSymbol(const void* addr, const void** closestAddr) const = 0;
+       
                                                                                // checks if this image is a bundle and can be loaded but not linked
        virtual bool                                            isBundle() const = 0;
        
                                                                                // checks if this image is a dylib 
        virtual bool                                            isDylib() const = 0;
        
+                                                                               // checks if this image is a main executable 
+       virtual bool                                            isExecutable() const = 0;
+       
+                                                                               // checks if this image is a main executable 
+       virtual bool                                            isPositionIndependentExecutable() const = 0;
+       
                                                                                // only for main executable
        virtual bool                                            forceFlat() const = 0;
        
                                                                                // called at runtime when a lazily bound function is first called
        virtual uintptr_t                                       doBindLazySymbol(uintptr_t* lazyPointer, const LinkContext& context) = 0;
        
+                                                                               // called at runtime when a fast lazily bound function is first called
+       virtual uintptr_t                                       doBindFastLazySymbol(uint32_t lazyBindingInfoOffset, const LinkContext& context,
+                                                                                                                       void (*lock)(), void (*unlock)()) = 0;
+
                                                                                // calls termination routines (e.g. C++ static destructors for image)
        virtual void                                            doTermination(const LinkContext& context) = 0;
                                        
-                                                                               // tell this image about other images
-       virtual void                                            doNotification(enum dyld_image_mode mode, uint32_t infoCount, const struct dyld_image_info info[]) = 0;
-                                       
                                                                                // return if this image has initialization routines
        virtual bool                                            needsInitialization() = 0;
                        
-                                                                               // return if this image has a routine to be called when any image is loaded or unloaded
-       virtual bool                                            hasImageNotification() = 0;
-       
                                                                                // return if this image has specified section and set start and length
        virtual bool                                            getSectionContent(const char* segmentName, const char* sectionName, void** start, size_t* length) = 0;
-                       
+
+                                                                               // fills in info about __eh_frame and __unwind_info sections
+       virtual void                                            getUnwindInfo(dyld_unwind_sections* info) = 0;
+
                                                                                // given a pointer into an image, find which segment and section it is in
        virtual bool                                            findSection(const void* imageInterior, const char** segmentName, const char** sectionName, size_t* sectionOffset) = 0;
        
@@ -257,68 +515,171 @@ public:
                                                                                // the image is prebindable and its prebinding is valid
        virtual bool                                            usablePrebinding(const LinkContext& context) const = 0;
        
-                                                                               // used to implement refernce counting of images
-       void                                                            incrementReferenceCount();
-       bool                                                            decrementReferenceCount();
+                                                                               // add all RPATH paths this image contains
+       virtual void                                            getRPaths(const LinkContext& context, std::vector<const char*>&) const = 0;
+       
+                                                                               // image has or uses weak definitions that need runtime coalescing
+       virtual bool                                            participatesInCoalescing() const = 0;
+               
+                                                                               // if image has a UUID, copy into parameter and return true
+       virtual bool                                            getUUID(uuid_t) const = 0;
+
+                                                                               // dynamic interpose values onto this image
+       virtual void                                            dynamicInterpose(const LinkContext& context) = 0;
+
+                                                                               // record interposing for any late binding
+       void                                                            addDynamicInterposingTuples(const struct dyld_interpose_tuple array[], size_t count);
+               
+//
+// A segment is a chunk of an executable file that is mapped into memory.  
+//
+       virtual unsigned int                            segmentCount() const = 0;
+       virtual const char*                                     segName(unsigned int) const = 0;
+       virtual uintptr_t                                       segSize(unsigned int) const = 0;
+       virtual uintptr_t                                       segFileSize(unsigned int) const = 0;
+       virtual bool                                            segHasTrailingZeroFill(unsigned int) = 0;
+       virtual uintptr_t                                       segFileOffset(unsigned int) const = 0;
+       virtual bool                                            segReadable(unsigned int) const = 0;
+       virtual bool                                            segWriteable(unsigned int) const = 0;
+       virtual bool                                            segExecutable(unsigned int) const = 0;
+       virtual bool                                            segUnaccessible(unsigned int) const = 0;
+       virtual bool                                            segHasPreferredLoadAddress(unsigned int) const = 0;
+       virtual uintptr_t                                       segPreferredLoadAddress(unsigned int) const = 0;
+       virtual uintptr_t                                       segActualLoadAddress(unsigned int) const = 0;
+       virtual uintptr_t                                       segActualEndAddress(unsigned int) const = 0;
+
+       
+                                                                               // info from LC_VERSION_MIN_MACOSX or LC_VERSION_MIN_IPHONEOS
+       virtual uint32_t                                        sdkVersion() const = 0;
+       virtual uint32_t                                        minOSVersion() const = 0;
+       
+                                                                               // if the image contains interposing functions, register them
+       virtual void                                            registerInterposing() = 0;
+
+                                                                               // when resolving symbols look in subImage if symbol can't be found
+       void                                                            reExport(ImageLoader* subImage);
+       
+       void                                                            weakBind(const LinkContext& context);
+
+       void                                                            applyInterposing(const LinkContext& context);
+
+       dyld_image_states                                       getState() { return (dyld_image_states)fState; }
+       
+                                                                               // used to sort images bottom-up
+       int                                                                     compare(const ImageLoader* right) const;
+       
+       void                                                            incrementDlopenReferenceCount() { ++fDlopenReferenceCount; }
+
+       bool                                                            decrementDlopenReferenceCount();
+       
+       void                                                            printReferenceCounts();
+
+       uint32_t                                                        dlopenCount() const { return fDlopenReferenceCount; }
+
+       void                                                            setCanUnload() { fNeverUnload = false; fLeaveMapped = false; }
 
+       bool                                                            neverUnload() const { return fNeverUnload; }
+
+       void                                                            setNeverUnload() { fNeverUnload = true; fLeaveMapped = true; }
+       void                                                            setNeverUnloadRecursive();
+       
+       bool                                                            isReferencedDownward() { return fIsReferencedDownward; }
+
+       
                                                                                // triggered by DYLD_PRINT_STATISTICS to write info on work done and how fast
-       static void                                                     printStatistics(unsigned int imageCount);
+       static void                                                     printStatistics(unsigned int imageCount, const InitializerTimingList& timingInfo);
                                
                                                                                // used with DYLD_IMAGE_SUFFIX
        static void                                                     addSuffix(const char* path, const char* suffix, char* result);
        
        static uint32_t                                         hash(const char*);
        
-       
-                       void                                            setPath(const char* path);      // only called for images created from memory
-                       void                                            setLogicalPath(const char* path);
+                                                                               // used instead of directly deleting image
+       static void                                                     deleteImage(ImageLoader*);
+               
+                       bool                                            dependsOn(ImageLoader* image);
+                       
+                       void                                            setPath(const char* path);
+                       void                                            setPaths(const char* path, const char* realPath);
+                       void                                            setPathUnowned(const char* path);
+                                               
+                       void                                            clearDepth() { fDepth = 0; }
+                       int                                                     getDepth() { return fDepth; }
+                       
+                       void                                            setBeingRemoved() { fBeingRemoved = true; }
+                       bool                                            isBeingRemoved() const { return fBeingRemoved; }
                        
+                       void                                            markNotUsed() { fMarkedInUse = false; }
+                       void                                            markedUsedRecursive(const std::vector<DynamicReference>&);
+                       bool                                            isMarkedInUse() const   { return fMarkedInUse; }
                
-protected:
+                       void                                            setAddFuncNotified() { fAddFuncNotified = true; }
+                       bool                                            addFuncNotified() const { return fAddFuncNotified; }
+       
+       struct InterposeTuple { 
+               uintptr_t               replacement; 
+               ImageLoader*    neverImage;                     // don't apply replacement to this image
+               ImageLoader*    onlyImage;                      // only apply replacement to this image
+               uintptr_t               replacee; 
+       };
+
+protected:                     
        // abstract base class so all constructors protected
-                                       ImageLoader(const char* path, uint64_t offsetInFat, const struct stat& info); 
-                                       ImageLoader(const char* moduleName); 
+                                       ImageLoader(const char* path, unsigned int libCount); 
                                        ImageLoader(const ImageLoader&);
        void                    operator=(const ImageLoader&);
+       void                    operator delete(void* image) throw() { ::free(image); }
        
 
        struct LibraryInfo {
-               uint64_t                checksum;
+               uint32_t                checksum;
                uint32_t                minVersion;
                uint32_t                maxVersion;
        };
 
        struct DependentLibrary {
-               const char*             name;
                ImageLoader*    image;
-               LibraryInfo             info;
-               bool                    required;
-               bool                    checksumMatches;
-               bool                    isReExported;
-               bool                    isSubFramework;
+               uint32_t                required : 1,
+                                               checksumMatches : 1,
+                                               isReExported : 1,
+                                               isSubFramework : 1;
        };
        
-       typedef void (*Initializer)(int argc, const char* argv[], const char* envp[],const char* apple[]);
+       struct DependentLibraryInfo {
+               const char*                     name;
+               LibraryInfo                     info;
+               bool                            required;
+               bool                            reExported;
+               bool                            upward;
+       };
+
+
+       typedef void (*Initializer)(int argc, const char* argv[], const char* envp[], const char* apple[], const ProgramVars* vars);
        typedef void (*Terminator)(void);
        
+
+
+       unsigned int                    libraryCount() const { return fLibraryCount; }
+       virtual ImageLoader*    libImage(unsigned int) const = 0;
+       virtual bool                    libReExported(unsigned int) const = 0;
+       virtual bool                    libIsUpward(unsigned int) const = 0;
+       virtual void                    setLibImage(unsigned int, ImageLoader*, bool, bool) = 0;
+
                                                // To link() an image, its dependent libraries are loaded, it is rebased, bound, and initialized.
                                                // These methods do the above, exactly once, and it the right order
-       void                            recursiveLoadLibraries(const LinkContext& context);
+       void                            recursiveLoadLibraries(const LinkContext& context, bool preflightOnly, const RPathChain& loaderRPaths);
+       void                            recursiveUnLoadMappedLibraries(const LinkContext& context);
+       unsigned int            recursiveUpdateDepth(unsigned int maxDepth);
+       void                            recursiveValidate(const LinkContext& context);
        void                            recursiveRebase(const LinkContext& context);
-       void                            recursiveBind(const LinkContext& context, BindingLaziness bindness);
-       void                            recursiveImageAnnouncement(const LinkContext& context, std::vector<ImageLoader*>& newImages);
-       void                            recursiveImageNotification(const LinkContext& context, uint32_t addImageCount);
-       void                            recursiveInitialization(const LinkContext& context);
+       void                            recursiveBind(const LinkContext& context, bool forceLazysBound, bool neverUnload);
+       void                            recursiveApplyInterposing(const LinkContext& context);
+       void                            recursiveGetDOFSections(const LinkContext& context, std::vector<DOFInfo>& dofs);
+       void                            recursiveInitialization(const LinkContext& context, mach_port_t this_thread,
+                                                                                               ImageLoader::InitializerTimingList&, ImageLoader::UninitedUpwards&);
 
-                                                               // map any segments this image has into memory and build fSegments
-                                                               // this is called before doGetDependentLibraryCount so if metadata is in segments it is mapped in
-       virtual void                            instantiateSegments(const uint8_t* fileData) = 0;
-       
-                                                               // return how many libraries this image depends on
-       virtual uint32_t                        doGetDependentLibraryCount() = 0;
-       
-                                                               // fill in information about dependent libraries (array length is doGetDependentLibraryCount())
-       virtual void                            doGetDependentLibraries(DependentLibrary libs[]) = 0;
+                                                               // fill in information about dependent libraries (array length is fLibraryCount)
+       virtual void                            doGetDependentLibraries(DependentLibraryInfo libs[]) = 0;
        
                                                                // called on images that are libraries, returns info about itself
        virtual LibraryInfo                     doGetLibraryInfo() = 0;
@@ -327,14 +688,20 @@ protected:
        virtual void                            doRebase(const LinkContext& context) = 0;
        
                                                                // do any symbolic fix ups in this image
-       virtual void                            doBind(const LinkContext& context, BindingLaziness bindness) = 0;
+       virtual void                            doBind(const LinkContext& context, bool forceLazysBound) = 0;
        
-                                                               // run any initialization routines in this image
-       virtual void                            doInitialization(const LinkContext& context) = 0;
+                                                               // called later via API to force all lazy pointer to be bound
+       virtual void                            doBindJustLazies(const LinkContext& context) = 0;
        
-                                                               // write prebinding updates to mapped file fileToPrebind
-       virtual void                            doPrebinding(const LinkContext& context, time_t timestamp, uint8_t* fileToPrebind) = 0;
+                                                               // if image has any dtrace DOF sections, append them to list to be registered
+       virtual void                            doGetDOFSections(const LinkContext& context, std::vector<DOFInfo>& dofs) = 0;
+       
+                                                               // do interpose
+       virtual void                            doInterpose(const LinkContext& context) = 0;
 
+                                                               // run any initialization routines in this image
+       virtual bool                            doInitialization(const LinkContext& context) = 0;
+       
                                                                // return if this image has termination routines
        virtual bool                            needsTermination() = 0;
        
@@ -347,12 +714,6 @@ protected:
                                                                // set how much all segments slide
        virtual void                            setSlide(intptr_t slide) = 0;           
        
-                                                               // utility routine to map in all segements in fSegments from a file
-       virtual void                            mapSegments(int fd, uint64_t offsetInFat, uint64_t lenInFat, uint64_t fileLen, const LinkContext& context);
-       
-                                                               // utility routine to map in all segements in fSegments from a memory image
-       virtual void                            mapSegments(const void* memoryImage, uint64_t imageLen, const LinkContext& context);
-
                                                                // returns if all dependent libraries checksum's were as expected and none slide
                        bool                            allDependentLibrariesAsWhenPreBound() const;
 
@@ -362,98 +723,84 @@ protected:
                                                                // in mach-o a parent library knows name of sub libraries it re-exports..
        virtual bool                            hasSubLibrary(const LinkContext& context, const ImageLoader* child) const  = 0;
        
+                                                               // set fState to dyld_image_state_memory_mapped
+       void                                            setMapped(const LinkContext& context);
+               
+       void                                            setFileInfo(dev_t device, ino_t inode, time_t modDate);
+       
+       static uintptr_t                        interposedAddress(const LinkContext& context, uintptr_t address, const ImageLoader* notInImage, const ImageLoader* onlyInImage=NULL);
+       
+       static uintptr_t                        fgNextPIEDylibAddress;
        static uint32_t                         fgImagesWithUsedPrebinding;
+       static uint32_t                         fgImagesUsedFromSharedCache;
+       static uint32_t                         fgImagesHasWeakDefinitions;
+       static uint32_t                         fgImagesRequiringCoalescing;
        static uint32_t                         fgTotalRebaseFixups;
        static uint32_t                         fgTotalBindFixups;
+       static uint32_t                         fgTotalBindSymbolsResolved;
+       static uint32_t                         fgTotalBindImageSearches;
        static uint32_t                         fgTotalLazyBindFixups;
        static uint32_t                         fgTotalPossibleLazyBindFixups;
+       static uint32_t                         fgTotalSegmentsMapped;
+       static uint64_t                         fgTotalBytesMapped;
+       static uint64_t                         fgTotalBytesPreFetched;
        static uint64_t                         fgTotalLoadLibrariesTime;
        static uint64_t                         fgTotalRebaseTime;
        static uint64_t                         fgTotalBindTime;
-       static uint64_t                         fgTotalNotifyTime;
+       static uint64_t                         fgTotalWeakBindTime;
+       static uint64_t                         fgTotalDOF;
        static uint64_t                         fgTotalInitTime;
-       static uintptr_t                        fgNextSplitSegAddress;
+       static std::vector<InterposeTuple>      fgInterposingTuples;
+       
        const char*                                     fPath;
-       const char*                                     fLogicalPath; // for ZeroLink - the image which this bundle is part of
+       const char*                                     fRealPath;
        dev_t                                           fDevice;
        ino_t                                           fInode;
        time_t                                          fLastModified;
-       uint64_t                                        fOffsetInFatFile;
-       std::vector<class Segment*> fSegments;
-       DependentLibrary*                       fLibraries;
-       uint32_t                                        fLibrariesCount;
        uint32_t                                        fPathHash;
-       uint32_t                                        fReferenceCount;
-       bool                                            fAllLibraryChecksumsAndLoadAddressesMatch;
-       bool                                            fLeaveMapped;           // when unloaded, leave image mapped in cause some other code may have pointers into it
-
+       uint32_t                                        fDlopenReferenceCount;  // count of how many dlopens have been done on this image
 
 private:
-       void                                            init(const char* path, uint64_t offsetInFat, dev_t device, ino_t inode, time_t modDate);
-       intptr_t                                        assignSegmentAddresses(const LinkContext& context);
-       void                                            copyAndMap(const char* tempFile, uint8_t** fileToPrebind, uint64_t* fileToPrebindSize);
-
-
-       bool                                            fHideSymbols;           // ignore this image's exported symbols when linking other images
-       bool                                            fMatchByInstallName;// look at image's install-path not its load path
-       bool                                            fLibrariesLoaded;
-       bool                                            fBased;
-       bool                                            fBoundAllNonLazy;
-       bool                                            fBoundAllLazy;
-       bool                                            fAnnounced;
-       bool                                            fInitialized;
-       uint16_t                                        fNextAddImageIndex;
+       struct recursive_lock {
+                                               recursive_lock(mach_port_t t) : thread(t), count(0) {}
+               mach_port_t             thread;
+               int                             count;
+       };
+       void                                            recursiveSpinLock(recursive_lock&);
+       void                                            recursiveSpinUnLock();
+
+       const ImageLoader::Symbol*      findExportedSymbolInDependentImagesExcept(const char* name, const ImageLoader** dsiStart, 
+                                                                               const ImageLoader**& dsiCur, const ImageLoader** dsiEnd, const ImageLoader** foundIn) const;
+
+       void                                            processInitializers(const LinkContext& context, mach_port_t this_thread,
+                                                                                                       InitializerTimingList& timingInfo, ImageLoader::UninitedUpwards& ups);
+
+
+       recursive_lock*                         fInitializerRecursiveLock;
+       uint16_t                                        fDepth;
+       uint16_t                                        fLoadOrder;
+       uint32_t                                        fState : 8,
+                                                               fLibraryCount : 10,
+                                                               fAllLibraryChecksumsAndLoadAddressesMatch : 1,
+                                                               fLeaveMapped : 1,               // when unloaded, leave image mapped in cause some other code may have pointers into it
+                                                               fNeverUnload : 1,               // image was statically loaded by main executable
+                                                               fHideSymbols : 1,               // ignore this image's exported symbols when linking other images
+                                                               fMatchByInstallName : 1,// look at image's install-path not its load path
+                                                               fInterposed : 1,
+                                                               fRegisteredDOF : 1,
+                                                               fAllLazyPointersBound : 1,
+                                                               fMarkedInUse : 1,
+                                                               fBeingRemoved : 1,
+                                                               fAddFuncNotified : 1,
+                                                               fPathOwnedByImage : 1,
+                                                               fIsReferencedDownward : 1,
+                                                               fWeakSymbolsBound : 1;
+
+       static uint16_t                         fgLoadOrdinal;
 };
 
 
-//
-// Segment is an abstract base class.  A segment is a chunk of an executable
-// file that is mapped into memory.  Each subclass of ImageLoader typically
-// implements its own concrete subclass of Segment.
-//
-//  
-class Segment {
-public:
-       virtual                                         ~Segment() {}
-
-       virtual const ImageLoader*      getImage() = 0;
-       virtual const char*                     getName() = 0;
-       virtual uintptr_t                       getSize() = 0;
-       virtual uintptr_t                       getFileSize() = 0;
-       virtual bool                            hasTrailingZeroFill();
-       virtual uintptr_t                       getFileOffset() = 0;
-       virtual bool                            readable() = 0;
-       virtual bool                            writeable() = 0;
-       virtual bool                            executable() = 0;
-       virtual bool                            unaccessible() = 0;
-       virtual bool                            hasFixUps() = 0;
-       virtual uintptr_t                       getActualLoadAddress() = 0;
-       virtual uintptr_t                       getPreferredLoadAddress() = 0;
-       virtual void                            setUnMapWhenDestructed(bool unmap) = 0;
-       
-protected:
-       // abstract base class so all constructors protected
-                                                               Segment() {}
-                                                               Segment(const Segment&);
-       void                                            operator=(const Segment&);
-
-       virtual bool                            hasPreferredLoadAddress() = 0;
-       //virtual void                          setActualLoadAddress(uint64_t addr) = 0;
-       
-       static bool                                     reserveAddressRange(uintptr_t start, size_t length);
-       static uintptr_t                        reserveAnAddressRange(size_t length, const ImageLoader::LinkContext& context);
-       static uintptr_t                        fgNextNonSplitSegAddress;
-
-private:
-       void                                            map(int fd, uint64_t offsetInFatWrapper, intptr_t slide, const ImageLoader::LinkContext& context);
-       void                                            map(const void* memoryImage, intptr_t slide, const ImageLoader::LinkContext& context);
-       void                                            setPermissions();
-       void                                            tempWritable();
-       
-       friend class ImageLoader;
-       friend class ImageLoaderMachO;
-};
-
+VECTOR_NEVER_DESTRUCTED_EXTERN(ImageLoader::InterposeTuple);
 
 
 #endif