#ifndef __ALL_IMAGES_H__
#define __ALL_IMAGES_H__
#include <pthread.h>
#include <mach-o/loader.h>
#include "dyld_priv.h"
#include "LaunchCache.h"
#include "Loading.h"
#if __MAC_OS_X_VERSION_MIN_REQUIRED
struct VIS_HIDDEN __NSObjectFileImage
{
const char* path = nullptr;
const void* memSource = nullptr;
size_t memLength = 0;
const mach_header* loadAddress = nullptr;
const dyld3::launch_cache::binary_format::Image* binImage = nullptr;
};
#endif
namespace dyld3 {
class VIS_HIDDEN AllImages
{
public:
typedef launch_cache::binary_format::Closure BinaryClosure;
typedef launch_cache::binary_format::ImageGroup BinaryImageGroup;
typedef launch_cache::binary_format::Image BinaryImage;
typedef launch_cache::ImageGroupList ImageGroupList;
typedef void (*NotifyFunc)(const mach_header* mh, intptr_t slide);
void init(const BinaryClosure* closure, const void* dyldCacheLoadAddress, const char* dyldCachePath,
const dyld3::launch_cache::DynArray<loader::ImageInfo>& initialImages);
void setMainPath(const char* path);
void applyInitialImages();
void addImages(const dyld3::launch_cache::DynArray<loader::ImageInfo>& newImages);
void removeImages(const launch_cache::DynArray<loader::ImageInfo>& unloadImages);
void setNeverUnload(const loader::ImageInfo& existingImage);
void applyInterposingToDyldCache(const launch_cache::binary_format::Closure* closure, const dyld3::launch_cache::DynArray<loader::ImageInfo>& initialImages);
void runInitialzersBottomUp(const mach_header* imageLoadAddress);
void setInitialGroups();
uint32_t count() const;
const BinaryImageGroup* cachedDylibsGroup();
const BinaryImageGroup* otherDylibsGroup();
const BinaryImageGroup* mainClosureGroup();
const BinaryClosure* mainClosure() { return _mainClosure; }
uint32_t currentGroupsCount() const;
void copyCurrentGroups(ImageGroupList& groups) const;
const BinaryImage* messageClosured(const char* path, const char* apiName, const char* closuredErrorMessages[3], int& closuredErrorMessagesCount);
launch_cache::Image findByLoadOrder(uint32_t index, const mach_header** loadAddress) const;
launch_cache::Image findByLoadAddress(const mach_header* loadAddress) const;
launch_cache::Image findByOwnedAddress(const void* addr, const mach_header** loadAddress, uint8_t* permissions=nullptr) const;
const mach_header* findLoadAddressByImage(const BinaryImage*) const;
bool findIndexForLoadAddress(const mach_header* loadAddress, uint32_t& index);
void forEachImage(void (^handler)(uint32_t imageIndex, const mach_header* loadAddress, const launch_cache::Image image, bool& stop)) const;
const mach_header* mainExecutable() const;
launch_cache::Image mainExecutableImage() const;
const void* cacheLoadAddress() const { return _dyldCacheAddress; }
const char* dyldCachePath() const { return _dyldCachePath; }
const char* imagePath(const BinaryImage*) const;
const mach_header* alreadyLoaded(const char* path, bool bumpRefCount);
const mach_header* alreadyLoaded(const BinaryImage*, bool bumpRefCount);
const mach_header* alreadyLoaded(uint64_t inode, uint64_t mtime, bool bumpRefCount);
const BinaryImage* findImageInKnownGroups(const char* path);
bool imageUnloadable(const launch_cache::Image& image, const mach_header* loadAddress) const;
void incRefCount(const mach_header* loadAddress);
void decRefCount(const mach_header* loadAddress);
void addLoadNotifier(NotifyFunc);
void addUnloadNotifier(NotifyFunc);
void setObjCNotifiers(_dyld_objc_notify_mapped, _dyld_objc_notify_init, _dyld_objc_notify_unmapped);
void notifyObjCUnmap(const char* path, const struct mach_header* mh);
void runLibSystemInitializer(const mach_header* imageLoadAddress, const launch_cache::binary_format::Image* binImage);
void setOldAllImageInfo(dyld_all_image_infos* old) { _oldAllImageInfos = old; }
dyld_all_image_infos* oldAllImageInfo() const { return _oldAllImageInfos;}
void notifyMonitorMain();
void notifyMonitorLoads(const launch_cache::DynArray<loader::ImageInfo>& newImages);
void notifyMonitorUnloads(const launch_cache::DynArray<loader::ImageInfo>& unloadingImages);
#if __MAC_OS_X_VERSION_MIN_REQUIRED
__NSObjectFileImage* addNSObjectFileImage();
bool hasNSObjectFileImage(__NSObjectFileImage*);
void removeNSObjectFileImage(__NSObjectFileImage*);
#endif
struct ProgramVars
{
const void* mh;
int* NXArgcPtr;
const char*** NXArgvPtr;
const char*** environPtr;
const char** __prognamePtr;
};
void setProgramVars(ProgramVars* vars);
private:
typedef void (*Initializer)(int argc, const char* argv[], char* envp[], const char* apple[], const ProgramVars* vars);
typedef const launch_cache::DynArray<loader::ImageInfo> StartImageArray;
void runInitialzersInImage(const mach_header* imageLoadAddress, const launch_cache::binary_format::Image* binImage);
void mirrorToOldAllImageInfos();
void garbageCollectImages();
void vmAccountingSetSuspended(bool suspend);
void copyCurrentGroupsNoLock(ImageGroupList& groups) const;
const BinaryClosure* _mainClosure = nullptr;
const void* _dyldCacheAddress = nullptr;
const char* _dyldCachePath = nullptr;
uint64_t _dyldCacheSlide = 0;
StartImageArray* _initialImages = nullptr;
const char* _mainExeOverridePath = nullptr;
_dyld_objc_notify_mapped _objcNotifyMapped = nullptr;
_dyld_objc_notify_init _objcNotifyInit = nullptr;
_dyld_objc_notify_unmapped _objcNotifyUnmapped = nullptr;
ProgramVars* _programVars = nullptr;
dyld_all_image_infos* _oldAllImageInfos = nullptr;
dyld_image_info* _oldAllImageArray = nullptr;
uint32_t _oldArrayAllocCount = 0;
pthread_mutex_t _initializerLock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER;
pthread_cond_t _initializerCondition= PTHREAD_COND_INITIALIZER;
int32_t _gcCount = 0;
};
extern AllImages gAllImages;
}
#endif // __ALL_IMAGES_H__