]> git.saurik.com Git - apple/dyld.git/blob - dyld3/shared-cache/ImageProxy.h
35bf42cdf9ce1f128fda865cd3c9eb8c472df29b
[apple/dyld.git] / dyld3 / shared-cache / ImageProxy.h
1 /*
2 * Copyright (c) 2017 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
26 #ifndef ImageProxy_h
27 #define ImageProxy_h
28
29 #include <stdint.h>
30
31 #include <string>
32 #include <vector>
33 #include <set>
34 #include <unordered_map>
35
36 #include "DyldSharedCache.h"
37 #include "Diagnostics.h"
38 #include "LaunchCache.h"
39 #include "LaunchCacheWriter.h"
40 #include "PathOverrides.h"
41 #include "ClosureBuffer.h"
42 #include "DyldCacheParser.h"
43
44
45 namespace dyld3 {
46
47 typedef launch_cache::binary_format::Image BinaryImageData;
48 typedef launch_cache::binary_format::ImageGroup BinaryImageGroupData;
49 typedef launch_cache::binary_format::Closure BinaryClosureData;
50 typedef launch_cache::binary_format::ImageRef ImageRef;
51 typedef launch_cache::Image::LinkKind LinkKind;
52 typedef launch_cache::ImageGroupWriter::FixUp FixUp;
53 typedef launch_cache::binary_format::DyldCacheOverride DyldCacheOverride;
54 typedef launch_cache::ImageGroupList ImageGroupList;
55
56
57
58
59 class ImageProxyGroup;
60
61 class ImageProxy
62 {
63 public:
64 ImageProxy(const mach_header* mh, const BinaryImageData* image, uint32_t indexInGroup, bool dyldCacheIsRaw);
65 ImageProxy(const DyldSharedCache::MappedMachO& mapping, uint32_t groupNum, uint32_t indexInGroup, bool dyldCacheIsRaw);
66
67 struct RPathChain {
68 ImageProxy* inProxy;
69 const RPathChain* prev;
70 const std::vector<std::string>& rpaths;
71 };
72
73 struct InitOrderInfo {
74 bool beforeHas(ImageRef);
75 bool upwardHas(ImageProxy*);
76 void removeRedundantUpwards();
77 std::vector<ImageRef> initBefore;
78 std::vector<ImageProxy*> danglingUpward;
79 };
80
81 struct FixupInfo {
82 std::vector<FixUp> fixups;
83 bool hasTextRelocs = false;
84 };
85
86 void recursiveBuildInitBeforeInfo(ImageProxyGroup& owningGroup);
87 void addDependentsShallow(ImageProxyGroup& owningGroup, RPathChain* chain=nullptr);
88 void addDependentsDeep(ImageProxyGroup& owningGroup, RPathChain* chain, bool staticallyReferenced);
89 void markInvalid() { _invalid = true; }
90
91 uint32_t groupNum() const { return _groupNum; }
92 uint32_t indexInGroup() const { return _indexInGroup; }
93 const mach_header* mh() const { return _mh; }
94 const std::string& runtimePath() const { return _runtimePath; }
95 uint64_t sliceFileOffset() const { return _sliceFileOffset; }
96 uint64_t fileModTime() const { return _modTime; }
97 uint64_t fileInode() const { return _inode; }
98 bool isSetUID() const { return _isSetUID; }
99 bool invalid() const { return _invalid; }
100 bool staticallyReferenced() const { return _staticallyReferenced; }
101 bool cwdMustBeThisDir() const { return _cwdMustBeThisDir; }
102 bool isPlatformBinary() const { return _platformBinary; }
103 bool isProxyForCachedDylib() const { return _imageBinaryData != nullptr; }
104 const Diagnostics& diagnostics() const { return _diag; }
105 ImageRef overrideOf() const { return _overrideOf; }
106 bool inLibSystem() const;
107 void setCwdMustBeThisDir() { _cwdMustBeThisDir = true; }
108 void setPlatformBinary() { _platformBinary = true; }
109 void setOverrideOf(uint32_t groupNum, uint32_t indexInGroup);
110 void checkIfImageOverride(const std::string& runtimeLoadPath);
111 void forEachDependent(void (^handler)(ImageProxy* dep, LinkKind)) const;
112 FixupInfo buildFixups(Diagnostics& diag, uint64_t cacheUnslideBaseAddress, launch_cache::ImageGroupWriter& groupWriter) const;
113 bool findExportedSymbol(Diagnostics& diag, const char* symbolName, MachOParser::FoundSymbol& foundInfo) const;
114 void convertInitBeforeInfoToArray(ImageProxyGroup& owningGroup);
115 void addToFlatLookup(std::vector<ImageProxy*>& imageList);
116 const std::vector<ImageRef>& getInitBeforeList(ImageProxyGroup& owningGroup);
117 const std::vector<std::string>& rpaths() { return _rpaths; }
118
119 private:
120 void processRPaths(ImageProxyGroup& owningGroup);
121
122 const mach_header* const _mh;
123 uint64_t const _sliceFileOffset;
124 uint64_t const _modTime;
125 uint64_t const _inode;
126 const BinaryImageData* const _imageBinaryData; // only used if proxy is for image in shared cache
127 std::string const _runtimePath;
128 bool const _isSetUID;
129 bool const _dyldCacheIsRaw;
130 uint32_t const _groupNum;
131 uint32_t const _indexInGroup;
132 bool _platformBinary;
133 Diagnostics _diag;
134 std::vector<ImageProxy*> _dependents;
135 std::vector<LinkKind> _dependentsKind;
136 std::vector<std::string> _rpaths;
137 InitOrderInfo _initBeforesInfo;
138 std::vector<ImageRef> _initBeforesArray;
139 ImageRef _overrideOf;
140 bool _directDependentsSet;
141 bool _deepDependentsSet;
142 bool _initBeforesArraySet;
143 bool _initBeforesComputed;
144 bool _invalid;
145 bool _staticallyReferenced;
146 bool _cwdMustBeThisDir;
147 };
148
149
150 class ImageProxyGroup
151 {
152 public:
153 ~ImageProxyGroup();
154
155
156 typedef std::unordered_map<const mach_header*, std::unordered_map<uint32_t, std::unordered_set<uint32_t>>> PatchTable;
157
158
159 // used when building dyld shared cache
160 static ImageProxyGroup* makeDyldCacheDylibsGroup(Diagnostics& diag, const DyldCacheParser& dyldCache, const std::vector<DyldSharedCache::MappedMachO>& cachedDylibs,
161 const std::vector<std::string>& buildTimePrefixes, const PatchTable& patchTable,
162 bool stubEliminated, bool dylibsExpectedOnDisk);
163
164 // used when building dyld shared cache
165 static ImageProxyGroup* makeOtherOsGroup(Diagnostics& diag, const DyldCacheParser& dyldCache, ImageProxyGroup* cachedDylibsGroup,
166 const std::vector<DyldSharedCache::MappedMachO>& otherDylibsAndBundles,
167 bool inodesAreSameAsRuntime, const std::vector<std::string>& buildTimePrefixes);
168
169 const BinaryImageGroupData* makeImageGroupBinary(Diagnostics& diag, const char* const neverEliminateStubs[]=nullptr);
170
171 // used when building dyld shared cache
172 static BinaryClosureData* makeClosure(Diagnostics& diag, const DyldCacheParser& dyldCache, ImageProxyGroup* cachedDylibsGroup,
173 ImageProxyGroup* otherOsDylibs, const DyldSharedCache::MappedMachO& mainProg,
174 bool inodesAreSameAsRuntime, const std::vector<std::string>& buildTimePrefixes);
175
176 // used by closured for dlopen of unknown dylibs
177 static const BinaryImageGroupData* makeDlopenGroup(Diagnostics& diag, const DyldCacheParser& dyldCache, uint32_t groupNum,
178 const std::vector<const BinaryImageGroupData*>& existingGroups,
179 const std::string& imagePath, const std::vector<std::string>& envVars);
180
181 static const BinaryImageGroupData* makeDlopenGroup(Diagnostics& diag, const ClosureBuffer& buffer, task_t requestor, const std::vector<std::string>& buildTimePrefixes={});
182
183 static BinaryClosureData* makeClosure(Diagnostics& diag, const ClosureBuffer& buffer, task_t requestor, const std::vector<std::string>& buildTimePrefixes={});
184
185
186 //
187 // Creates a binary launch closure for the specified main executable.
188 // Used by closured and dyld_closure_util
189 //
190 // The closure is allocated with malloc(). Use free() to release when done.
191 // The size of the closure can be determined using Closure::size().
192 // If the closure cannot be built (e.g. app needs a symbol not exported by a framework),
193 // the reason for the failure is returned as a string in the diag parameter.
194 // The mainProgRuntimePath path is the path the program will be at runtime.
195 // The buildTimePrefixes is a list of prefixes to add to each path during closure
196 // creation to find the files at buildtime.
197 //
198 static BinaryClosureData* makeClosure(Diagnostics& diag, const DyldCacheParser& dyldCache,
199 const std::string& mainProgRuntimePath, bool includeDylibsInDir,
200 const std::vector<std::string>& buildTimePrefixes={},
201 const std::vector<std::string>& envVars={});
202
203
204 private:
205 friend class ImageProxy;
206
207 ImageProxyGroup(uint32_t groupNum, const DyldCacheParser& dyldCache, const BinaryImageGroupData* basedOn,
208 ImageProxyGroup* next, const std::string& mainProgRuntimePath,
209 const std::vector<const BinaryImageGroupData*>& knownGroups,
210 const std::vector<std::string>& buildTimePrefixes,
211 const std::vector<std::string>& envVars,
212 bool stubsEliminated=false, bool dylibsExpectedOnDisk=true, bool inodesAreSameAsRuntime=true);
213
214 ImageProxy* findImage(Diagnostics& diag, const std::string& runtimePath, bool canBeMissing, ImageProxy::RPathChain*);
215 ImageProxy* findAbsoluteImage(Diagnostics& diag, const std::string& runtimePath, bool canBeMissing, bool makeErrorMessage, bool pathIsReal=false);
216 bool builtImageStillValid(const launch_cache::Image& image);
217 const std::string& mainProgRuntimePath() { return _mainProgRuntimePath; }
218 DyldSharedCache::MappedMachO* addMappingIfValidMachO(Diagnostics& diag, const std::string& runtimePath, bool ignoreMainExecutables=false);
219 BinaryClosureData* makeClosureBinary(Diagnostics& diag, ImageProxy* mainProg, bool includeDylibsInDir);
220 void findLibdyldEntry(Diagnostics& diag, ImageRef& ref, uint32_t& offset);
221 void findLibSystem(Diagnostics& diag, bool sim, ImageRef& ref);
222 void populateGroupWriter(Diagnostics& diag, launch_cache::ImageGroupWriter& groupWriter, const char* const neverEliminateStubs[]=nullptr);
223 std::string normalizedPath(const std::string& path);
224 void addExtraMachOsInBundle(const std::string& appDir);
225 bool addInsertedDylibs(Diagnostics& diag);
226 std::vector<ImageProxy*> flatLookupOrder();
227
228 PathOverrides _pathOverrides;
229 const BinaryImageGroupData* _basedOn; // if not null, then lazily populate _images
230 const PatchTable* _patchTable;
231 ImageProxyGroup* const _nextSearchGroup;
232 const DyldCacheParser _dyldCache;
233 uint32_t const _groupNum;
234 bool const _stubEliminated;
235 bool const _dylibsExpectedOnDisk;
236 bool const _inodesAreSameAsRuntime;
237 uint32_t _mainExecutableIndex;
238 std::vector<const BinaryImageGroupData*> _knownGroups;
239 std::vector<ImageProxy*> _images;
240 std::unordered_map<std::string, ImageProxy*> _pathToProxy;
241 std::vector<DyldSharedCache::MappedMachO> _ownedMappings;
242 std::vector<std::string> _buildTimePrefixes;
243 std::vector<DyldCacheOverride> _cacheOverrides;
244 std::string _mainProgRuntimePath;
245 std::string _archName;
246 Platform _platform;
247 std::set<std::string> _mustBeMissingFiles;
248 };
249
250
251
252
253
254 }
255
256 #endif // ImageProxy_h