X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/5dd5f9ec28f304ca377c42fd7f711d6cf12b90e1..5c19dc3ae3bd8e40a9c028b0deddd50ff337692c:/OSX/libsecurity_utilities/lib/dyldcache.h diff --git a/OSX/libsecurity_utilities/lib/dyldcache.h b/OSX/libsecurity_utilities/lib/dyldcache.h new file mode 100644 index 00000000..f1ebe2b8 --- /dev/null +++ b/OSX/libsecurity_utilities/lib/dyldcache.h @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2009,2011-2012 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +// +// dyldcache - access layer to the DYLD Shared Library Cache file +// +#ifndef _H_DYLDCACHE +#define _H_DYLDCACHE + +#include +#include +#include +#include +#include "dyld_cache_format.h" + + +// +// One (architecture of the) Shared Library Cache. +// We mmap the file rather than reading a copy, since its format is rather scattered, and we're not +// interested in the vast majority of it. +// This is a read-only view of the cache file. It will not allow modifications, though it may +// tell you where in the file they should go. +// +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 of all the mappings + size_t signatureLength() const { return mSigLength; } // size of all the mappings + size_t totalSize() const { return mLength; } // size of entire file (>= mapSize(), we hope) + + template Int flip(Int x) const { return mFlip ? Security::flip(x) : x; } + +public: + static std::string pathFor(const Architecture &arch); // file path for given architecture + static bool validate(UnixPlusPlus::FileDesc &fd); // does this look like a shared library cache? + +protected: + template + class Item { + public: + Item(const DYLDCache &c, uint32_t off) + : cache(c), mStruct(c.at(off)) { } + const DYLDCache &cache; + + protected: + const SubStruct *mStruct; + template Int flip(Int x) const { return cache.flip(x); } + }; + +public: + // + // A contiguous mapping established by the cache builder + // + struct Mapping : public Item { + 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(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: + // + // One original binary ("image") as embedded in the cache. + // + struct Image : public Item { + Image(const DYLDCache &c, uint32_t off) : Item(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(flip(mStruct->pathFileOffset)); } + }; + + uint32_t imageCount() const { return flip(mHeader->imagesCount); } + Image image(unsigned ix) const; + +public: + template + const T *at(uint32_t offset) const + { + size_t end = offset + sizeof(T); + if (offset > end || end > mLength) + UnixError::throwMe(ENOEXEC); + return LowLevelMemoryUtilities::increment(mBase, offset); + } + +private: + // + // A private table correlating cache "magic strings" to information we need about the cache + // (This should be in the cache files themselves) + // + struct ArchType { + cpu_type_t cpu; // main architecture + cpu_subtype_t sub; // subarchitecture + char magic[16]; // cache file magic string + char filename[10]; // conventional file name (off cacheFileBase) + uint16_t order; // byte order marker + + 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 defaultArchitecture; + + static const ArchType *matchArchitecture(const dyld_cache_header &header); + +private: + const void *mBase; + size_t mLength; + + const dyld_cache_header *mHeader; // cache file header (NOT byte order corrected) + const ArchType *mArch; // ArchType entry that describes this file + bool mFlip; // need to flip all integers? + size_t mSigStart; // end of all file mappings (start of signature) + size_t mSigLength; // indicated length of signature +}; + + +#endif //_H_DYLDCACHE