#ifndef __IMAGELOADER__
#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 <mach-o/dyld_images.h>
#include <mach-o/dyld_priv.h>
#include <stdint.h>
#include <stdlib.h>
#include <TargetConditionals.h>
#include <vector>
#include <new>
#include <uuid/uuid.h>
#if !TARGET_OS_DRIVERKIT && (BUILDING_LIBDYLD || BUILDING_DYLD)
#include <CrashReporterClient.h>
#else
#define CRSetCrashLogMessage(x)
#define CRSetCrashLogMessage2(x)
#endif
#include "DyldSharedCache.h"
#include "Map.h"
#if __arm__
#include <mach/vm_page_size.h>
#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
#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 0
#define SUPPORT_CLASSIC_MACHO __arm__
#define SUPPORT_ZERO_COST_EXCEPTIONS (!__USING_SJLJ_EXCEPTIONS__)
#define INITIAL_IMAGE_COUNT 150
#define SUPPORT_ACCELERATE_TABLES !TARGET_OS_SIMULATOR
#define SUPPORT_ROOT_PATH TARGET_OS_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 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() { } \
}
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
#define DYLD_PACKED_VERSION(major, minor, tiny) ((((major) & 0xffff) << 16) | (((minor) & 0xff) << 8) | ((tiny) & 0xff))
struct ProgramVars
{
const void* mh;
int* NXArgcPtr;
const char*** NXArgvPtr;
const char*** environPtr;
const char** __prognamePtr;
};
enum dyld_image_states
{
dyld_image_state_mapped = 10, dyld_image_state_dependents_mapped = 20, dyld_image_state_rebased = 30,
dyld_image_state_bound = 40,
dyld_image_state_dependents_initialized = 45, dyld_image_state_initialized = 50,
dyld_image_state_terminated = 60 };
typedef const char* (*dyld_image_state_change_handler)(enum dyld_image_states state, uint32_t infoCount, const struct dyld_image_info info[]);
class ImageLoader {
public:
typedef uint32_t DefinitionFlags;
static const DefinitionFlags kNoDefinitionOptions = 0;
static const DefinitionFlags kWeakDefinition = 1;
typedef uint32_t ReferenceFlags;
static const ReferenceFlags kNoReferenceOptions = 0;
static const ReferenceFlags kWeakReference = 1;
static const ReferenceFlags kTentativeDefinition = 2;
enum PrebindMode { kUseAllPrebinding, kUseSplitSegPrebinding, kUseAllButAppPredbinding, kUseNoPrebinding };
enum BindingOptions { kBindingNone, kBindingLazyPointers, kBindingNeverSetLazyPointers };
enum SharedRegionMode { kUseSharedRegion, kUsePrivateSharedRegion, kDontUseSharedRegion, kSharedRegionIsSharedCache };
struct Symbol;
struct MappedRegion {
uintptr_t address;
size_t size;
};
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 InitializerTimingList
{
uintptr_t count;
struct {
const char* shortName;
uint64_t initTime;
} images[1];
void addTime(const char* name, uint64_t time);
};
typedef void (^CoalesceNotifier)(const Symbol* implSym, const ImageLoader* implIn, const mach_header* implMh);
struct HashCString {
static size_t hash(const char* v);
};
struct EqualCString {
static bool equal(const char* s1, const char* s2);
};
struct LinkContext {
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, CoalesceNotifier);
unsigned int (*getCoalescedImages)(ImageLoader* images[], unsigned imageIndex[]);
void (*undefinedHandler)(const char* name);
MappedRegion* (*getAllMappedRegions)(MappedRegion*);
void * (*bindingHandler)(const char *, const char *, void *);
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 (*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
BindingOptions bindingOptions;
int argc;
const char** argv;
const char** envp;
const char** apple;
const char* progname;
ProgramVars programVars;
ImageLoader* mainExecutable;
const char* const * imageSuffix;
#if SUPPORT_ROOT_PATH
const char** rootPaths;
#endif
const DyldSharedCache* dyldCache;
const dyld_interpose_tuple* dynamicInterposeArray;
size_t dynamicInterposeCount;
PrebindMode prebindUsage;
SharedRegionMode sharedRegionMode;
mutable dyld3::Map<const char*, std::pair<const ImageLoader*, uintptr_t>, HashCString, EqualCString> weakDefMap;
mutable bool weakDefMapInitialized = false;
mutable bool weakDefMapProcessedLaunchDefs = false;
mutable bool useNewWeakBind = false;
bool dyldLoadedAtSameAddressNeededBySharedCache;
bool strictMachORequired;
bool allowAtPaths;
bool allowEnvVarsPrint;
bool allowEnvVarsPath;
bool allowEnvVarsSharedCache;
bool allowClassicFallbackPaths;
bool allowInsertFailures;
bool allowInterposing;
bool mainExecutableCodeSigned;
bool prebinding;
bool bindFlat;
bool linkingMainExecutable;
bool startedInitializingMainExecutable;
#if __MAC_OS_X_VERSION_MIN_REQUIRED
bool iOSonMac;
bool driverKit;
#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;
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;
std::pair<ImageLoader*, const char*> imagesAndPaths[1];
};
virtual ~ImageLoader();
void link(const LinkContext& context, bool forceLazysBound, bool preflight, bool neverUnload, const RPathChain& loaderRPaths, const char* imagePath);
void runInitializers(const LinkContext& context, InitializerTimingList& timingInfo);
void bindAllLazyPointers(const LinkContext& context, bool recursive);
bool statMatch(const struct stat& stat_buf) const;
const char* getShortName() const;
static const char* shortName(const char* fullName);
const char* getPath() const { return fPath; }
uint32_t getPathHash() const { return fPathHash; }
const char* getRealPath() const;
virtual const char* getInstallPath() const = 0;
bool matchInstallPath() const;
void setMatchInstallPath(bool);
void setHideExports(bool hide = true);
bool hasHiddenExports() const;
bool isLinked() const;
void setLeaveMapped();
bool leaveMapped() { return fLeaveMapped; }
virtual bool inSharedCache() const { return false; };
virtual bool containsAddress(const void* addr) const;
virtual bool containsSymbol(const void* addr) const = 0;
virtual bool overlapsWithAddressRange(const void* start, const void* end) const;
void getMappedRegions(MappedRegion*& region) const;
time_t lastModified() const;
virtual void* getEntryFromLC_MAIN() const = 0;
virtual void* getEntryFromLC_UNIXTHREAD() const = 0;
virtual const struct mach_header* machHeader() const = 0;
virtual uintptr_t getSlide() const = 0;
virtual const void* getEnd() const = 0;
virtual bool hasCoalescedExports() const = 0;
virtual bool findExportedSymbolAddress(const LinkContext& context, const char* symbolName,
const ImageLoader* requestorImage, int requestorOrdinalOfDef,
bool runResolver, const ImageLoader** foundIn, uintptr_t* address) const;
virtual const Symbol* findExportedSymbol(const char* name, bool searchReExports, const char* thisPath, 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);
}
virtual uintptr_t getExportedSymbolAddress(const Symbol* sym, const LinkContext& context,
const ImageLoader* requestor=NULL, bool runResolver=false, const char* symbolName=NULL) const = 0;
virtual DefinitionFlags getExportedSymbolInfo(const Symbol* sym) const = 0;
virtual const char* getExportedSymbolName(const Symbol* sym) const = 0;
virtual uint32_t getExportedSymbolCount() const = 0;
virtual const Symbol* getIndexedExportedSymbol(uint32_t index) const = 0;
virtual const Symbol* findExportedSymbolInDependentImages(const char* name, const LinkContext& context, const ImageLoader** foundIn) const;
virtual const Symbol* findExportedSymbolInImageOrDependentImages(const char* name, const LinkContext& context, const ImageLoader** foundIn) const;
virtual uint32_t getImportedSymbolCount() const = 0;
virtual const Symbol* getIndexedImportedSymbol(uint32_t index) const = 0;
virtual ReferenceFlags getImportedSymbolInfo(const Symbol* sym) const = 0;
virtual const char* getImportedSymbolName(const Symbol* sym) const = 0;
virtual const char* findClosestSymbol(const void* addr, const void** closestAddr) const = 0;
virtual const char* getIndexedPath(unsigned) const { return getPath(); }
virtual const char* getIndexedShortName(unsigned) const { return getShortName(); }
virtual bool isBundle() const = 0;
virtual bool isDylib() const = 0;
virtual bool isExecutable() const = 0;
virtual bool isPositionIndependentExecutable() const = 0;
virtual bool forceFlat() const = 0;
virtual uintptr_t doBindLazySymbol(uintptr_t* lazyPointer, const LinkContext& context) = 0;
virtual uintptr_t doBindFastLazySymbol(uint32_t lazyBindingInfoOffset, const LinkContext& context,
void (*lock)(), void (*unlock)()) = 0;
virtual void doTermination(const LinkContext& context) = 0;
virtual bool needsInitialization() = 0;
virtual bool getSectionContent(const char* segmentName, const char* sectionName, void** start, size_t* length) = 0;
virtual void getUnwindInfo(dyld_unwind_sections* info) = 0;
virtual const struct macho_section* findSection(const void* imageInterior) const = 0;
virtual bool findSection(const void* imageInterior, const char** segmentName, const char** sectionName, size_t* sectionOffset) = 0;
virtual bool isPrebindable() const = 0;
virtual bool usablePrebinding(const LinkContext& context) const = 0;
virtual void getRPaths(const LinkContext& context, std::vector<const char*>&) const = 0;
virtual bool participatesInCoalescing() const = 0;
virtual bool getUUID(uuid_t) const = 0;
virtual void dynamicInterpose(const LinkContext& context) = 0;
void addDynamicInterposingTuples(const struct dyld_interpose_tuple array[], size_t count);
virtual const char* libPath(unsigned int) const = 0;
virtual bool notifyObjC() const { return false; }
virtual bool overridesCachedDylib(uint32_t& num) const { return false; }
virtual void setOverridesCachedDylib(uint32_t num) { }
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;
virtual uint32_t sdkVersion() const = 0;
virtual uint32_t minOSVersion() const = 0;
virtual void registerInterposing(const LinkContext& context) = 0;
virtual bool usesChainedFixups() const { return false; }
virtual void makeDataReadOnly() const {}
void reExport(ImageLoader* subImage);
virtual void recursiveBind(const LinkContext& context, bool forceLazysBound, bool neverUnload);
void recursiveBindWithAccounting(const LinkContext& context, bool forceLazysBound, bool neverUnload);
void recursiveRebaseWithAccounting(const LinkContext& context);
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; }
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; }
virtual void recursiveMakeDataReadOnly(const LinkContext& context);
virtual uintptr_t resolveWeak(const LinkContext& context, const char* symbolName, bool weak_import, bool runResolver,
const ImageLoader** foundIn) { return 0; }
static void printStatistics(unsigned int imageCount, const InitializerTimingList& timingInfo);
static void printStatisticsDetails(unsigned int imageCount, const InitializerTimingList& timingInfo);
static void addSuffix(const char* path, const char* suffix, char* result);
static uint32_t hash(const char*);
static const uint8_t* trieWalk(const uint8_t* start, const uint8_t* end, const char* stringToFind);
static void deleteImage(ImageLoader*);
static bool haveInterposingTuples() { return !fgInterposingTuples.empty(); }
static void clearInterposingTuples() { fgInterposingTuples.clear(); }
static void applyInterposingToDyldCache(const LinkContext& context);
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; }
void setAddFuncNotified() { fAddFuncNotified = true; }
bool addFuncNotified() const { return fAddFuncNotified; }
void setObjCMappedNotified() { fObjCMappedNotified = true; }
bool objCMappedNotified() const { return fObjCMappedNotified; }
struct InterposeTuple {
uintptr_t replacement;
ImageLoader* neverImage; ImageLoader* onlyImage; 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);
void vmAccountingSetSuspended(const LinkContext& context, bool suspend);
protected:
ImageLoader(const char* path, unsigned int libCount);
ImageLoader(const ImageLoader&);
void operator=(const ImageLoader&);
void operator delete(void* image) throw() { ::free(image); }
struct LibraryInfo {
uint32_t checksum;
uint32_t minVersion;
uint32_t maxVersion;
};
struct DependentLibrary {
ImageLoader* image;
uint32_t required : 1,
checksumMatches : 1,
isReExported : 1,
isSubFramework : 1;
};
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;
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 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&);
virtual void doGetDependentLibraries(DependentLibraryInfo libs[]) = 0;
virtual LibraryInfo doGetLibraryInfo(const LibraryInfo& requestorInfo) = 0;
virtual void doRebase(const LinkContext& context) = 0;
virtual void doBind(const LinkContext& context, bool forceLazysBound) = 0;
virtual void doBindJustLazies(const LinkContext& context) = 0;
virtual void doGetDOFSections(const LinkContext& context, std::vector<DOFInfo>& dofs) = 0;
virtual void doInterpose(const LinkContext& context) = 0;
virtual bool doInitialization(const LinkContext& context) = 0;
virtual bool needsTermination() = 0;
virtual bool segmentsMustSlideTogether() const = 0;
virtual bool segmentsCanSlide() const = 0;
virtual void setSlide(intptr_t slide) = 0;
bool allDependentLibrariesAsWhenPreBound() const;
virtual bool isSubframeworkOf(const LinkContext& context, const ImageLoader* image) const = 0;
virtual bool hasSubLibrary(const LinkContext& context, const ImageLoader* child) const = 0;
virtual bool weakSymbolsBound(unsigned index) const { return fWeakSymbolsBound; }
virtual void setWeakSymbolsBound(unsigned index) { fWeakSymbolsBound = true; }
void setMapped(const LinkContext& context);
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 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 uint32_t fgSymbolTrieSearchs;
static uint64_t fgTotalBytesMapped;
static uint64_t fgTotalLoadLibrariesTime;
public:
static uint64_t fgTotalObjCSetupTime;
static uint64_t fgTotalDebuggerPausedTime;
static uint64_t fgTotalRebindCacheTime;
static uint64_t fgTotalRebaseTime;
static uint64_t fgTotalBindTime;
static uint64_t fgTotalWeakBindTime;
static uint64_t fgTotalDOF;
static uint64_t fgTotalInitTime;
protected:
static std::vector<InterposeTuple> fgInterposingTuples;
const char* fPath;
const char* fRealPath;
dev_t fDevice;
ino_t fInode;
time_t fLastModified;
uint32_t fPathHash;
uint32_t fDlopenReferenceCount;
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();
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);
void weakBindOld(const LinkContext& context);
recursive_lock* fInitializerRecursiveLock;
union {
struct {
uint16_t fLoadOrder;
uint16_t fDepth : 15,
fObjCMappedNotified : 1;
uint32_t fState : 8,
fLibraryCount : 9,
fMadeReadOnly : 1,
fAllLibraryChecksumsAndLoadAddressesMatch : 1,
fLeaveMapped : 1, fNeverUnload : 1, fHideSymbols : 1, fMatchByInstallName : 1, fInterposed : 1,
fRegisteredDOF : 1,
fAllLazyPointersBound : 1,
fMarkedInUse : 1,
fBeingRemoved : 1,
fAddFuncNotified : 1,
fPathOwnedByImage : 1,
fIsReferencedDownward : 1,
fWeakSymbolsBound : 1;
};
uint64_t sizeOfData;
};
static_assert(sizeof(sizeOfData) == 8, "Bad data size");
static uint16_t fgLoadOrdinal;
};
VECTOR_NEVER_DESTRUCTED_EXTERN(ImageLoader::InterposeTuple);
#endif