]> git.saurik.com Git - apple/dyld.git/blobdiff - src/ImageLoader.h
dyld-551.3.tar.gz
[apple/dyld.git] / src / ImageLoader.h
index e7795d0f6bc631e7070a8293d265cb18f1ea5708..fd70e2d42c67caa2db33d42f43fcf63c797d585a 100644 (file)
@@ -1,6 +1,6 @@
 /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
  *
- * Copyright (c) 2004-2007 Apple 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 <set>
+#include <new>
+
+#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
 
-#define SPLIT_SEG_SHARED_REGION_SUPPORT 0
-#define SPLIT_SEG_DYLIB_SUPPORT (__ppc__ || __i386__)
-#define TEXT_RELOC_SUPPORT (__ppc__ || __i386__)
-#define DYLD_SHARED_CACHE_SUPPORT (__ppc__ || __i386__ || __ppc64__ || __x86_64__)
-#define IMAGE_NOTIFY_SUPPORT 0
-#define RECURSIVE_INITIALIZER_LOCK 1
-#define SUPPORT_OLD_CRT_INITIALIZATION (__ppc__ || __i386__)
+#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 SUPPORT_OLD_CRT_INITIALIZATION  0
+       #define SUPPORT_LC_DYLD_ENVIRONMENT             1
+       #define SUPPORT_VERSIONED_PATHS                 1
+       #define SUPPORT_CLASSIC_MACHO                   __arm__
+       #define SUPPORT_ZERO_COST_EXCEPTIONS    (!__USING_SJLJ_EXCEPTIONS__)
+       #define INITIAL_IMAGE_COUNT                             150
+       #define SUPPORT_ACCELERATE_TABLES               (__arm__ || __arm64__)
+       #define SUPPORT_ROOT_PATH                               TARGET_IPHONE_SIMULATOR
+#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 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
+       #define SUPPORT_ACCELERATE_TABLES               0
+       #define SUPPORT_ROOT_PATH                               1
+#endif
 
+#define MAX_MACH_O_HEADER_AND_LOAD_COMMANDS_SIZE (32*1024)
+
+#define MH_HAS_OBJC                    0x40000000
+
+// <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 {
@@ -52,7 +152,37 @@ namespace dyld {
        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
@@ -111,29 +241,50 @@ public:
                const char*                     imageShortName;
        };
 
+       struct DynamicReference {
+               ImageLoader* from;
+               ImageLoader* to;
+       };
+       
+       struct InitializerTimingList
+       {
+               uintptr_t       count;
+               struct {
+                       const char*             shortName;
+                       uint64_t                initTime;
+               }                       images[1];
+
+               void addTime(const char* name, uint64_t time);
+       };
+       
        struct LinkContext {
-               ImageLoader*    (*loadLibrary)(const char* libraryName, bool search, bool findDLL, const char* origin, const RPathChain* rpaths);
+               ImageLoader*    (*loadLibrary)(const char* libraryName, bool search, const char* origin, const RPathChain* rpaths, unsigned& cacheIndex);
                void                    (*terminationRecorder)(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[], unsigned imageIndex[]);
                void                    (*undefinedHandler)(const char* name);
-#if IMAGE_NOTIFY_SUPPORT
-               void                    (*addImageNeedingNotification)(ImageLoader* image);
-               void                    (*notifyAdding)(const ImageLoader* const * images, unsigned int count);
-#endif
                MappedRegion*   (*getAllMappedRegions)(MappedRegion*);
                void *                  (*bindingHandler)(const char *, const char *, void *);
-               void                    (*notifySingle)(dyld_image_states, const struct mach_header*, const char* path, time_t modDate);
-               void                    (*notifyBatch)(dyld_image_states state);
+               void                    (*notifySingle)(dyld_image_states, const ImageLoader* image, InitializerTimingList*);
+               void                    (*notifyBatch)(dyld_image_states state, bool preflightOnly);
                void                    (*removeImage)(ImageLoader* image);
                void                    (*registerDOFs)(const std::vector<DOFInfo>& dofs);
                void                    (*clearAllDepths)();
+               void                    (*printAllDepths)();
                unsigned int    (*imageCount)();
-               void                    (*notifySharedCacheInvalid)();
-#if __i386__
-               void                    (*makeSharedCacheImportSegmentsWritable)(bool writable);
-#endif
                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_ACCELERATE_TABLES
+               void                    (*notifySingleFromCache)(dyld_image_states, const mach_header* mh, const char* path);
+               dyld_image_state_change_handler (*getPreInitNotifyHandler)(unsigned index);
+               dyld_image_state_change_handler (*getBoundBatchHandler)(unsigned index);
+#endif
+               
 #if SUPPORT_OLD_CRT_INITIALIZATION
                void                    (*setRunInitialzersOldWay)();
 #endif
@@ -146,34 +297,82 @@ public:
                ProgramVars             programVars;
                ImageLoader*    mainExecutable;
                const char*             imageSuffix;
+#if SUPPORT_ROOT_PATH
+               const char**    rootPaths;
+#endif
+               const dyld_interpose_tuple*     dynamicInterposeArray;
+               size_t                  dynamicInterposeCount;
                PrebindMode             prebindUsage;
                SharedRegionMode sharedRegionMode;
-               bool                    dyldLoadedAtSameAddressNeededBySharedCache; 
+               bool                    dyldLoadedAtSameAddressNeededBySharedCache;
+               bool                    strictMachORequired;
+               bool                    requireCodeSignature;
+               bool                    mainExecutableCodeSigned;
                bool                    preFetchDisabled;
                bool                    prebinding;
                bool                    bindFlat;
                bool                    linkingMainExecutable;
+               bool                    startedInitializingMainExecutable;
+#if __MAC_OS_X_VERSION_MIN_REQUIRED
+               bool                    processIsRestricted;
+               bool                    processUsingLibraryValidation;
+#endif
                bool                    verboseOpts;
                bool                    verboseEnv;
+               bool                    verboseLoading;
                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;
+               uintptr_t               imageIndex;
+       };
+       
+       virtual void                    initializeCoalIterator(CoalIterator&, unsigned int loadOrder, unsigned imageIndex) = 0;
+       virtual bool                    incrementCoalIterator(CoalIterator&) = 0;
+       virtual uintptr_t               getAddressCoalIterator(CoalIterator&, const LinkContext& context) = 0;
+       virtual void                    updateUsesCoalIterator(CoalIterator&, uintptr_t newAddr, ImageLoader* target, unsigned targetIndex, const LinkContext& context) = 0;
+       
+       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, bool forceLazysBound, bool preflight, const RPathChain& loaderRPaths);
+       void                                                            link(const LinkContext& context, bool forceLazysBound, bool preflight, bool neverUnload, const RPathChain& loaderRPaths, const char* imagePath);
        
                                                                                // 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);
@@ -184,24 +383,24 @@ public:
                                                                                // get short name of this image
        const char*                                                     getShortName() const;
 
+                                                                               // returns leaf name
+       static const char*                                      shortName(const char* fullName);
+
                                                                                // get path used to load this image, not necessarily the "real" path
        const char*                                                     getPath() const { return fPath; }
 
        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;
 
-                                                                               // image was loaded with NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME and all clients are looking for install path 
+                                                                               // image was loaded with NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME and all clients are looking for install path
        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);
        
@@ -217,9 +416,15 @@ public:
                                                                                // 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;
 
@@ -229,7 +434,10 @@ public:
                                                                                // st_mtime from stat() on file
        time_t                                                          lastModified() const;
 
-                                                                               // only valid for main executables, returns a pointer its entry point
+                                                                               // 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 main from LC_<MAIN
        virtual void*                                           getMain() const = 0;
        
                                                                                // dyld API's require each image to have an associated mach_header
@@ -243,12 +451,23 @@ public:
        
                                                                                // 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 bool                                            findExportedSymbolAddress(const LinkContext& context, const char* symbolName,
+                                                                                                                               const ImageLoader* requestorImage, int requestorOrdinalOfDef,
+                                                                                                                               bool runResolver, const ImageLoader** foundIn, uintptr_t* address) const;
+
+                                                                               // search symbol table of definitions in this image for requested name
+       virtual const Symbol*                           findExportedSymbol(const char* name, bool searchReExports, const char* thisPath, const ImageLoader** foundIn) 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, const ImageLoader** foundIn) const = 0;
+       virtual const Symbol*                           findExportedSymbol(const char* name, bool searchReExports, const ImageLoader** foundIn) const {
+                                                                                       return findExportedSymbol(name, searchReExports, this->getPath(), foundIn);
+                                                                               }
        
                                                                                // gets address of implementation (code) of the specified exported symbol
-       virtual uintptr_t                                       getExportedSymbolAddress(const Symbol* sym, const LinkContext& context, const ImageLoader* requestor=NULL) const = 0;
+       virtual uintptr_t                                       getExportedSymbolAddress(const Symbol* sym, const LinkContext& context, 
+                                                                                                       const ImageLoader* requestor=NULL, bool runResolver=false, const char* symbolName=NULL) const = 0;
        
                                                                                // gets attributes of the specified exported symbol
        virtual DefinitionFlags                         getExportedSymbolInfo(const Symbol* sym) const = 0;
@@ -277,40 +496,52 @@ 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;
+       
+                                                                               // for use with accelerator tables
+       virtual const char*                                     getIndexedPath(unsigned) const { return getPath(); }
+       virtual const char*                                     getIndexedShortName(unsigned) const { return getShortName(); }
+
                                                                                // 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;
                                        
-#if IMAGE_NOTIFY_SUPPORT
-                                                                               // tell this image about other images
-       virtual void                                            doNotification(enum dyld_image_mode mode, uint32_t infoCount, const struct dyld_image_info info[]) = 0;
-#endif                                 
                                                                                // return if this image has initialization routines
        virtual bool                                            needsInitialization() = 0;
                        
-#if IMAGE_NOTIFY_SUPPORT
-                                                                               // return if this image has a routine to be called when any image is loaded or unloaded
-       virtual bool                                            hasImageNotification() = 0;
-#endif 
                                                                                // 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;
        
@@ -323,10 +554,61 @@ public:
                                                                                // 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);
+               
+       virtual const char*                                     libPath(unsigned int) const = 0;
+
+                                                                               // Image has objc sections, so information objc about when it comes and goes
+       virtual bool                                            notifyObjC() const { return false; }
+
+//
+// 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;
 
-       dyld_image_states                                       getState() { return (dyld_image_states)fState; }
+                                                                               // 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; }
+
+       ino_t                                                           getInode() const { return fInode; }
+    dev_t                               getDevice() const { return fDevice; }
+
                                                                                // used to sort images bottom-up
        int                                                                     compare(const ImageLoader* right) const;
        
@@ -336,61 +618,70 @@ public:
        
        void                                                            printReferenceCounts();
 
-       uint32_t                                                        referenceCount() const { return fDlopenReferenceCount + fStaticReferenceCount + fDynamicReferenceCount; }
+       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);
+       static void                                                     printStatisticsDetails(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                                            setPathUnowned(const char* path);
-                       
-                       void                                            setLogicalPath(const char* path);
+       
+       static const uint8_t*                           trieWalk(const uint8_t* start, const uint8_t* end, const char* stringToFind);
+
+                                                                               // used instead of directly deleting image
+       static void                                                     deleteImage(ImageLoader*);
+
+       static bool                                                     haveInterposingTuples() { return !fgInterposingTuples.empty(); }
+       static void                                                     clearInterposingTuples() { fgInterposingTuples.clear(); }
+
+                       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; }
                        
-       
-protected:     
-       struct DependentLibrary;
-public:
-       friend class iterator;
-       
-       class iterator
-       {
-       public:
-               iterator&               operator++() { ++fLocation; return *this; }
-               bool                    operator!=(const iterator& it) const { return (it.fLocation != this->fLocation); }
-               ImageLoader*    operator*() const { return fLocation->image; }
-       private:
-               friend class ImageLoader;
-               iterator(DependentLibrary* loc) : fLocation(loc) {}
-               DependentLibrary*       fLocation;
-       };
-       
-       iterator beginDependents() { return iterator(fLibraries); }
-       iterator endDependents() { return iterator(&fLibraries[fLibrariesCount]); }
-       
-       
-               
-       friend class Segment;
+                       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; 
+       };
+
+       static uintptr_t read_uleb128(const uint8_t*& p, const uint8_t* end);
+       static intptr_t read_sleb128(const uint8_t*& p, const uint8_t* end);
+
+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 {
@@ -412,44 +703,37 @@ protected:
                LibraryInfo                     info;
                bool                            required;
                bool                            reExported;
+               bool                            upward;
        };
 
-       class SegmentIterator
-       {
-       public:
-               SegmentIterator&        operator++(); // use inline later to work around circular reference
-               bool                            operator!=(const SegmentIterator& it) const { return (it.fLocation != this->fLocation); }
-               class Segment*          operator*() const { return fLocation; }
-               SegmentIterator(class Segment* loc) : fLocation(loc) {}
-       private:
-               class Segment*          fLocation;
-       };
 
        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, 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, bool forceLazysBound);
-       void                            recursiveGetDOFSections(const LinkContext& context, std::vector<DOFInfo>& dofs);
-#if IMAGE_NOTIFY_SUPPORT
-       void                            recursiveImageAnnouncement(const LinkContext& context, ImageLoader**& newImages);
-#endif
-       void                            recursiveInitialization(const LinkContext& context, mach_port_t this_thread);
-
-                                                               // 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            recursiveLoadLibraries(const LinkContext& context, bool preflightOnly, const RPathChain& loaderRPaths, const char* loadPath);
+       virtual unsigned        recursiveUpdateDepth(unsigned int maxDepth);
+       virtual void            recursiveRebase(const LinkContext& context);
+       virtual void            recursiveBind(const LinkContext& context, bool forceLazysBound, bool neverUnload);
+       virtual void            recursiveApplyInterposing(const LinkContext& context);
+       virtual void            recursiveGetDOFSections(const LinkContext& context, std::vector<DOFInfo>& dofs);
+       virtual void            recursiveInitialization(const LinkContext& context, mach_port_t this_thread, const char* pathToInitialize,
+                                                                                               ImageLoader::InitializerTimingList&, ImageLoader::UninitedUpwards&);
+
+                                                               // 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;
+       virtual LibraryInfo                     doGetLibraryInfo(const LibraryInfo& requestorInfo) = 0;
        
                                                                // do any fix ups in this image that depend only on the load address of the image
        virtual void                            doRebase(const LinkContext& context) = 0;
@@ -457,14 +741,17 @@ protected:
                                                                // do any symbolic fix ups in this image
        virtual void                            doBind(const LinkContext& context, bool forceLazysBound) = 0;
        
-                                                               // update any segment permissions
-       virtual void                            doUpdateMappingPermissions(const LinkContext& context) = 0;
+                                                               // called later via API to force all lazy pointer to be bound
+       virtual void                            doBindJustLazies(const LinkContext& context) = 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 void                            doInitialization(const LinkContext& context) = 0;
+       virtual bool                            doInitialization(const LinkContext& context) = 0;
        
                                                                // return if this image has termination routines
        virtual bool                            needsTermination() = 0;
@@ -474,15 +761,9 @@ protected:
        
                                                                // built with PIC code and can load at any address
        virtual bool                            segmentsCanSlide() const = 0;           
-       
+
                                                                // 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;
@@ -492,23 +773,24 @@ 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;
-       
+
+       virtual bool                            weakSymbolsBound(unsigned index) { return fWeakSymbolsBound; }
+       virtual void                            setWeakSymbolsBound(unsigned index) { fWeakSymbolsBound = true; }
+
                                                                // set fState to dyld_image_state_memory_mapped
        void                                            setMapped(const LinkContext& context);
-       
-                                                               // mark that target should not be unloaded unless this is also unloaded
-       void                                            addDynamicReference(const ImageLoader* target);
-                               
-                                                               // used to start iterating Segments
-       virtual SegmentIterator         beginSegments() const = 0;
-       
-                                                               // used to end iterating Segments
-       virtual SegmentIterator         endSegments() const = 0;
-       
+               
+       void                                            setFileInfo(dev_t device, ino_t inode, time_t modDate);
 
+       void                                            setDepth(uint16_t depth) { fDepth = depth; }
+
+       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                         fgImagesRequiringNoFixups;
+       static uint32_t                         fgImagesHasWeakDefinitions;
+       static uint32_t                         fgImagesRequiringCoalescing;
        static uint32_t                         fgTotalRebaseFixups;
        static uint32_t                         fgTotalBindFixups;
        static uint32_t                         fgTotalBindSymbolsResolved;
@@ -516,29 +798,30 @@ protected:
        static uint32_t                         fgTotalLazyBindFixups;
        static uint32_t                         fgTotalPossibleLazyBindFixups;
        static uint32_t                         fgTotalSegmentsMapped;
+       static uint32_t                         fgSymbolTrieSearchs;
        static uint64_t                         fgTotalBytesMapped;
        static uint64_t                         fgTotalBytesPreFetched;
        static uint64_t                         fgTotalLoadLibrariesTime;
+public:
+       static uint64_t                         fgTotalObjCSetupTime;
+       static uint64_t                         fgTotalDebuggerPausedTime;
+       static uint64_t                         fgTotalRebindCacheTime;
+protected:
        static uint64_t                         fgTotalRebaseTime;
        static uint64_t                         fgTotalBindTime;
+       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;
-       DependentLibrary*                       fLibraries;
-       uint32_t                                        fLibrariesCount;
        uint32_t                                        fPathHash;
        uint32_t                                        fDlopenReferenceCount;  // count of how many dlopens have been done on this image
-       uint32_t                                        fStaticReferenceCount;  // count of images that have a fLibraries entry pointing to this image
-       uint32_t                                        fDynamicReferenceCount; // count of images that have a fDynamicReferences entry pointer to this image
-       std::set<const ImageLoader*>* fDynamicReferences;       // list of all images this image used because of a flat/coalesced lookup
 
-private:
-#if RECURSIVE_INITIALIZER_LOCK
        struct recursive_lock {
                                                recursive_lock(mach_port_t t) : thread(t), count(0) {}
                mach_port_t             thread;
@@ -546,94 +829,40 @@ private:
        };
        void                                            recursiveSpinLock(recursive_lock&);
        void                                            recursiveSpinUnLock();
-#endif 
 
-       void                                            init(const char* path, uint64_t offsetInFat, dev_t device, ino_t inode, time_t modDate);
-       intptr_t                                        assignSegmentAddresses(const LinkContext& context);
+private:
        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,
-#if IMAGE_NOTIFY_SUPPORT
-                                                               fAnnounced : 1,
-#endif
                                                                fAllLazyPointersBound : 1,
+                                                               fMarkedInUse : 1,
                                                                fBeingRemoved : 1,
-                                                               fPathOwnedByImage : 1;
+                                                               fAddFuncNotified : 1,
+                                                               fPathOwnedByImage : 1,
+                                                               fIsReferencedDownward : 1,
+                                                               fWeakSymbolsBound : 1;
 
-#if RECURSIVE_INITIALIZER_LOCK
-       recursive_lock*                         fInitializerRecursiveLock;
-#else
-       uint32_t                                        fInitializerLock;
-#endif
        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 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 uintptr_t                       getActualLoadAddress(const ImageLoader*) = 0;
-       virtual uintptr_t                       getPreferredLoadAddress() = 0;
-       virtual void                            unmap(const ImageLoader*) = 0;
-       virtual Segment*                        next(Segment*) = 0;
-#if __i386__
-       virtual bool                            readOnlyImportStubs() = 0;
-#endif
-       
-       
-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;
-       virtual void                            map(int fd, uint64_t offsetInFatWrapper, intptr_t slide, const ImageLoader* image, const ImageLoader::LinkContext& context);
-       
-       static bool                                     reserveAddressRange(uintptr_t start, size_t length);
-       static uintptr_t                        reserveAnAddressRange(size_t length, const class ImageLoader::LinkContext& context);
-       static uintptr_t                        fgNextPIEDylibAddress;
-
-private:
-       void                                            setPermissions(const ImageLoader::LinkContext& context, const ImageLoader* image);
-       void                                            map(const void* memoryImage, intptr_t slide, const ImageLoader* image, const ImageLoader::LinkContext& context);
-       void                                            tempWritable(const ImageLoader::LinkContext& context, const ImageLoader* image);
-       
-       friend class ImageLoader;
-       friend class ImageLoaderMachO;
-};
-
-inline ImageLoader::SegmentIterator& ImageLoader::SegmentIterator::operator++() { fLocation = fLocation->next(fLocation); return *this; }
-
-
+VECTOR_NEVER_DESTRUCTED_EXTERN(ImageLoader::InterposeTuple);
 
 
 #endif