#ifndef _H_DYLDCACHE
#define _H_DYLDCACHE
#include <security_utilities/unix++.h>
#include <security_utilities/memutils.h>
#include <security_utilities/macho++.h>
#include <security_utilities/endian.h>
#include "dyld_cache_format.h"
class DYLDCache : public UnixPlusPlus::AutoFileDesc {
public:
DYLDCache(const std::string &path);
virtual ~DYLDCache();
std::string magic() const { return mHeader->magic; }
uint64_t baseAddress() const { return flip(mHeader->dyldBaseAddress); }
Architecture architecture() const { return mArch->architecture(); }
size_t mapSize() const { return mSigStart; } size_t signatureLength() const { return mSigLength; } size_t totalSize() const { return mLength; }
template <class Int> Int flip(Int x) const { return mFlip ? Security::flip(x) : x; }
public:
static std::string pathFor(const Architecture &arch); static bool validate(UnixPlusPlus::FileDesc &fd);
protected:
template <class SubStruct>
class Item {
public:
Item(const DYLDCache &c, uint32_t off)
: cache(c), mStruct(c.at<SubStruct>(off)) { }
const DYLDCache &cache;
protected:
const SubStruct *mStruct;
template <class Int> Int flip(Int x) const { return cache.flip(x); }
};
public:
struct Mapping : public Item<shared_file_mapping_np> {
mach_vm_address_t address() const { return flip(mStruct->sfm_address); }
mach_vm_size_t size() const { return flip(mStruct->sfm_size); }
mach_vm_address_t limit() const { return address() + size(); }
mach_vm_offset_t offset() const { return flip(mStruct->sfm_file_offset); }
vm_prot_t maxProt() const { return flip(mStruct->sfm_max_prot); }
vm_prot_t initProt() const { return flip(mStruct->sfm_init_prot); }
bool contains(uint64_t address) const
{ return address >= this->address() && address < this->limit(); }
Mapping(const DYLDCache &c, uint32_t off) : Item<shared_file_mapping_np>(c, off) { }
};
uint32_t mappingCount() const { return flip(mHeader->mappingCount); }
Mapping mapping(unsigned ix) const;
Mapping findMap(uint64_t address) const;
uint64_t mapAddress(uint64_t address) const;
public:
struct Image : public Item<dyld_cache_image_info> {
Image(const DYLDCache &c, uint32_t off) : Item<dyld_cache_image_info>(c, off) { }
uint64_t address() const { return flip(mStruct->address); }
uint64_t modTime() const { return flip(mStruct->modTime); }
uint64_t inode() const { return flip(mStruct->inode); }
uint32_t pad() const { return flip(mStruct->pad); }
std::string path() const { return cache.at<char>(flip(mStruct->pathFileOffset)); }
};
uint32_t imageCount() const { return flip(mHeader->imagesCount); }
Image image(unsigned ix) const;
public:
template <class T>
const T *at(uint32_t offset) const
{ return LowLevelMemoryUtilities::increment<const T>(mBase, offset); }
private:
struct ArchType {
cpu_type_t cpu; cpu_subtype_t sub; char magic[16]; char filename[10]; uint16_t order;
std::string path() const
{ return std::string(DYLD_SHARED_CACHE_DIR DYLD_SHARED_CACHE_BASE_NAME) + filename; }
Architecture architecture() const { return Architecture(cpu, sub); }
};
static const ArchType architectures[];
static const ArchType *matchArchitecture(const dyld_cache_header &header);
private:
const void *mBase;
size_t mLength;
const dyld_cache_header *mHeader; const ArchType *mArch; bool mFlip; size_t mSigStart; size_t mSigLength; };
#endif //_H_DYLDCACHE