1/* 2 * Copyright (c) 2009 Apple Inc. All Rights Reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24// 25// dyldcache - access layer to the DYLD Shared Library Cache file 26// 27#ifndef _H_DYLDCACHE 28#define _H_DYLDCACHE 29 30#include <security_utilities/unix++.h> 31#include <security_utilities/memutils.h> 32#include <security_utilities/macho++.h> 33#include <security_utilities/endian.h> 34#include "dyld_cache_format.h" 35 36 37// 38// One (architecture of the) Shared Library Cache. 39// We mmap the file rather than reading a copy, since its format is rather scattered, and we're not 40// interested in the vast majority of it. 41// This is a read-only view of the cache file. It will not allow modifications, though it may 42// tell you where in the file they should go. 43// 44class DYLDCache : public UnixPlusPlus::AutoFileDesc { 45public: 46 DYLDCache(const std::string &path); 47 virtual ~DYLDCache(); 48 49 std::string magic() const { return mHeader->magic; } 50 uint64_t baseAddress() const { return flip(mHeader->dyldBaseAddress); } 51 Architecture architecture() const { return mArch->architecture(); } 52 size_t mapSize() const { return mSigStart; } // size of all the mappings 53 size_t signatureLength() const { return mSigLength; } // size of all the mappings 54 size_t totalSize() const { return mLength; } // size of entire file (>= mapSize(), we hope) 55 56 template <class Int> Int flip(Int x) const { return mFlip ? Security::flip(x) : x; } 57 58public: 59 static std::string pathFor(const Architecture &arch); // file path for given architecture 60 static bool validate(UnixPlusPlus::FileDesc &fd); // does this look like a shared library cache? 61 62protected: 63 template <class SubStruct> 64 class Item { 65 public: 66 Item(const DYLDCache &c, uint32_t off) 67 : cache(c), mStruct(c.at<SubStruct>(off)) { } 68 const DYLDCache &cache; 69 70 protected: 71 const SubStruct *mStruct; 72 template <class Int> Int flip(Int x) const { return cache.flip(x); } 73 }; 74 75public: 76 // 77 // A contiguous mapping established by the cache builder 78 // 79 struct Mapping : public Item<shared_file_mapping_np> { 80 mach_vm_address_t address() const { return flip(mStruct->sfm_address); } 81 mach_vm_size_t size() const { return flip(mStruct->sfm_size); } 82 mach_vm_address_t limit() const { return address() + size(); } 83 mach_vm_offset_t offset() const { return flip(mStruct->sfm_file_offset); } 84 vm_prot_t maxProt() const { return flip(mStruct->sfm_max_prot); } 85 vm_prot_t initProt() const { return flip(mStruct->sfm_init_prot); } 86 87 bool contains(uint64_t address) const 88 { return address >= this->address() && address < this->limit(); } 89 90 Mapping(const DYLDCache &c, uint32_t off) : Item<shared_file_mapping_np>(c, off) { } 91 }; 92 93 uint32_t mappingCount() const { return flip(mHeader->mappingCount); } 94 Mapping mapping(unsigned ix) const; 95 96 Mapping findMap(uint64_t address) const; 97 uint64_t mapAddress(uint64_t address) const; 98 99public: 100 // 101 // One original binary ("image") as embedded in the cache. 102 // 103 struct Image : public Item<dyld_cache_image_info> { 104 Image(const DYLDCache &c, uint32_t off) : Item<dyld_cache_image_info>(c, off) { } 105 106 uint64_t address() const { return flip(mStruct->address); } 107 uint64_t modTime() const { return flip(mStruct->modTime); } 108 uint64_t inode() const { return flip(mStruct->inode); } 109 uint32_t pad() const { return flip(mStruct->pad); } 110 std::string path() const { return cache.at<char>(flip(mStruct->pathFileOffset)); } 111 }; 112 113 uint32_t imageCount() const { return flip(mHeader->imagesCount); } 114 Image image(unsigned ix) const; 115 116public: 117 template <class T> 118 const T *at(uint32_t offset) const 119 { return LowLevelMemoryUtilities::increment<const T>(mBase, offset); } 120 121private: 122 // 123 // A private table correlating cache "magic strings" to information we need about the cache 124 // (This should be in the cache files themselves) 125 // 126 struct ArchType { 127 cpu_type_t cpu; // main architecture 128 cpu_subtype_t sub; // subarchitecture 129 char magic[16]; // cache file magic string 130 char filename[10]; // conventional file name (off cacheFileBase) 131 uint16_t order; // byte order marker 132 133 std::string path() const 134 { return std::string(DYLD_SHARED_CACHE_DIR DYLD_SHARED_CACHE_BASE_NAME) + filename; } 135 136 Architecture architecture() const { return Architecture(cpu, sub); } 137 }; 138 static const ArchType architectures[]; 139 static const ArchType defaultArchitecture; 140 141 static const ArchType *matchArchitecture(const dyld_cache_header &header); 142 143private: 144 const void *mBase; 145 size_t mLength; 146 147 const dyld_cache_header *mHeader; // cache file header (NOT byte order corrected) 148 const ArchType *mArch; // ArchType entry that describes this file 149 bool mFlip; // need to flip all integers? 150 size_t mSigStart; // end of all file mappings (start of signature) 151 size_t mSigLength; // indicated length of signature 152}; 153 154 155#endif //_H_DYLDCACHE 156