]>
Commit | Line | Data |
---|---|---|
b1ab9ed8 | 1 | /* |
d8f41ccd | 2 | * Copyright (c) 2009,2011-2012 Apple Inc. All Rights Reserved. |
b1ab9ed8 A |
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 | // | |
44 | class DYLDCache : public UnixPlusPlus::AutoFileDesc { | |
45 | public: | |
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 | ||
58 | public: | |
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 | ||
62 | protected: | |
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 | ||
75 | public: | |
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 | ||
99 | public: | |
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 | ||
116 | public: | |
117 | template <class T> | |
118 | const T *at(uint32_t offset) const | |
5c19dc3a A |
119 | { |
120 | size_t end = offset + sizeof(T); | |
121 | if (offset > end || end > mLength) | |
122 | UnixError::throwMe(ENOEXEC); | |
123 | return LowLevelMemoryUtilities::increment<const T>(mBase, offset); | |
124 | } | |
b1ab9ed8 A |
125 | |
126 | private: | |
127 | // | |
128 | // A private table correlating cache "magic strings" to information we need about the cache | |
129 | // (This should be in the cache files themselves) | |
130 | // | |
131 | struct ArchType { | |
132 | cpu_type_t cpu; // main architecture | |
133 | cpu_subtype_t sub; // subarchitecture | |
134 | char magic[16]; // cache file magic string | |
135 | char filename[10]; // conventional file name (off cacheFileBase) | |
136 | uint16_t order; // byte order marker | |
137 | ||
138 | std::string path() const | |
139 | { return std::string(DYLD_SHARED_CACHE_DIR DYLD_SHARED_CACHE_BASE_NAME) + filename; } | |
140 | ||
141 | Architecture architecture() const { return Architecture(cpu, sub); } | |
142 | }; | |
143 | static const ArchType architectures[]; | |
c2a06e24 | 144 | static const ArchType defaultArchitecture; |
b1ab9ed8 A |
145 | |
146 | static const ArchType *matchArchitecture(const dyld_cache_header &header); | |
147 | ||
148 | private: | |
149 | const void *mBase; | |
150 | size_t mLength; | |
151 | ||
152 | const dyld_cache_header *mHeader; // cache file header (NOT byte order corrected) | |
153 | const ArchType *mArch; // ArchType entry that describes this file | |
154 | bool mFlip; // need to flip all integers? | |
155 | size_t mSigStart; // end of all file mappings (start of signature) | |
156 | size_t mSigLength; // indicated length of signature | |
157 | }; | |
158 | ||
159 | ||
160 | #endif //_H_DYLDCACHE |