dyld-732.8.tar.gz
[apple/dyld.git] / dyld3 / ClosureBuilder.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 #ifndef ClosureBuilder_h
26 #define ClosureBuilder_h
27
28
29 #include "Closure.h"
30 #include "ClosureFileSystem.h"
31 #include "ClosureWriter.h"
32 #include "PathOverrides.h"
33 #include "DyldSharedCache.h"
34 #include "MachOAnalyzer.h"
35 #include "Map.h"
36 #include "Loading.h"
37
38 #include <optional>
39
40 namespace objc_opt {
41 struct objc_clsopt_t;
42 struct objc_selopt_t;
43 struct objc_protocolopt2_t;
44 }
45
46 namespace dyld3 {
47
48
49 namespace closure {
50
51
52
53 class VIS_HIDDEN ClosureBuilder
54 {
55 public:
56
57 struct LaunchErrorInfo
58 {
59 uintptr_t kind;
60 const char* clientOfDylibPath;
61 const char* targetDylibPath;
62 const char* symbol;
63 };
64
65 struct ResolvedTargetInfo
66 {
67 const MachOLoaded* foundInDylib;
68 const char* requestedSymbolName;
69 const char* foundSymbolName;
70 uint64_t addend;
71 bool weakBindCoalese;
72 bool weakBindSameImage;
73 bool isWeakDef;
74 bool skippableWeakDef;
75 int libOrdinal;
76 };
77
78 struct CacheDylibsBindingHandlers
79 {
80 void (^rebase)(ImageNum, const MachOLoaded* imageToFix, uint32_t runtimeOffset);
81 void (^bind)(ImageNum, const MachOLoaded* imageToFix, uint32_t runtimeOffset, Image::ResolvedSymbolTarget target, const ResolvedTargetInfo& targetInfo);
82 void (^chainedBind)(ImageNum, const MachOLoaded*, const dyld_chained_starts_in_image* starts, const Array<Image::ResolvedSymbolTarget>& targets, const Array<ResolvedTargetInfo>& targetInfos);
83 };
84
85 enum class AtPath { none, all, onlyInRPaths };
86
87 ClosureBuilder(uint32_t startImageNum, const FileSystem& fileSystem, const DyldSharedCache* dyldCache, bool dyldCacheIsLive,
88 const GradedArchs& archs, const PathOverrides& pathOverrides,
89 AtPath atPathHandling=AtPath::all, bool allowRelativePaths=true, LaunchErrorInfo* errorInfo=nullptr,
90 Platform platform=MachOFile::currentPlatform(), const CacheDylibsBindingHandlers* handlers=nullptr);
91 ~ClosureBuilder();
92 Diagnostics& diagnostics() { return _diag; }
93
94 const LaunchClosure* makeLaunchClosure(const LoadedFileInfo& fileInfo, bool allowInsertFailures);
95
96 const LaunchClosure* makeLaunchClosure(const char* mainPath,bool allowInsertFailures);
97
98
99 static const DlopenClosure* sRetryDlopenClosure;
100 const DlopenClosure* makeDlopenClosure(const char* dylibPath, const LaunchClosure* mainClosure, const Array<LoadedImage>& loadedList,
101 closure::ImageNum callerImageNum, bool noLoad, bool forceBindLazies, bool canUseSharedCacheClosure,
102 closure::ImageNum* topImageNum);
103
104 ImageNum nextFreeImageNum() const { return _startImageNum + _nextIndex; }
105
106 void setDyldCacheInvalidFormatVersion();
107
108
109 struct PatchableExport
110 {
111 uint32_t cacheOffsetOfImpl;
112 uint32_t cacheOffsetOfName;
113 uint32_t patchLocationsCount;
114 const dyld_cache_patchable_location* patchLocations;
115 };
116
117 struct CachedDylibInfo
118 {
119 LoadedFileInfo fileInfo;
120 };
121
122 struct CachedDylibAlias
123 {
124 const char* realPath;
125 const char* aliasPath;
126 };
127
128 const ImageArray* makeDyldCacheImageArray(bool customerCache, const Array<CachedDylibInfo>& dylibs, const Array<CachedDylibAlias>& aliases);
129
130 const ImageArray* makeOtherDylibsImageArray(const Array<LoadedFileInfo>& otherDylibs, uint32_t cachedDylibsCount);
131
132 static void buildLoadOrder(Array<LoadedImage>& loadedList, const Array<const ImageArray*>& imagesArrays, const Closure* toAdd);
133
134 private:
135
136
137 struct InitInfo
138 {
139 uint32_t initOrder;
140 bool danglingUpward;
141 bool visited;
142 };
143
144 struct BuilderLoadedImage
145 {
146 Array<Image::LinkedImage> dependents;
147 ImageNum imageNum;
148 uint32_t unmapWhenDone : 1,
149 contentRebased : 1,
150 hasInits : 1,
151 markNeverUnload : 1,
152 rtldLocal : 1,
153 isBadImage : 1,
154 mustBuildClosure : 1,
155 hasMissingWeakImports : 1,
156 padding : 12,
157 overrideImageNum : 12;
158 LoadedFileInfo loadedFileInfo;
159
160 // Convenience method to get the information from the loadedFileInfo
161 const MachOAnalyzer* loadAddress() const { return (const MachOAnalyzer*)loadedFileInfo.fileContent; }
162 const char* path() const { return loadedFileInfo.path; }
163 };
164
165 struct LoadedImageChain
166 {
167 LoadedImageChain* previous;
168 BuilderLoadedImage& image;
169 };
170
171 // Represents how the current image is linked
172 enum class LinkageType {
173 kStatic, // Linked via LC_LOAD_* by main executable or other dylib
174 kDynamic, // Only used for the image we dlopen'ed, not anything it links
175 kInserted // This is an inserted library
176 };
177
178 typedef LaunchClosure::SkippedFile SkippedFile;
179
180
181 void recursiveLoadDependents(LoadedImageChain& forImageChain, bool canUseSharedCacheClosure = true);
182 void loadDanglingUpwardLinks(bool canUseSharedCacheClosure = true);
183 void forEachResolvedPathVar(const char* loadPath, const LoadedImageChain& forImageChain, bool implictRPath, LinkageType linkageType,
184 void (^handler)(const char* possiblePath, bool& stop));
185 bool findImage(const char* loadPath, const LoadedImageChain& forImageChain, BuilderLoadedImage*& foundImage, LinkageType linkageType,
186 uint32_t compatVersion, bool canUseSharedCacheClosure);
187 void buildImage(ImageWriter& writer, BuilderLoadedImage& forImage);
188 void addSegments(ImageWriter& writer, const MachOAnalyzer* mh);
189 void addRebaseInfo(ImageWriter& writer, const MachOAnalyzer* mh);
190 void addSynthesizedRebaseInfo(ImageWriter& writer, const MachOAnalyzer* mh);
191 void addSynthesizedBindInfo(ImageWriter& writer, const MachOAnalyzer* mh);
192 void addBindInfo(ImageWriter& writer, BuilderLoadedImage& forImage);
193 void reportRebasesAndBinds(ImageWriter& writer, BuilderLoadedImage& forImage);
194 void addChainedFixupInfo(ImageWriter& writer, BuilderLoadedImage& forImage);
195 void addInterposingTuples(LaunchClosureWriter& writer, const Image* image, const MachOAnalyzer* mh);
196 void computeInitOrder(ImageWriter& writer, uint32_t loadIndex);
197 void addClosureInfo(LaunchClosureWriter& closureWriter);
198 void depthFirstRecurseSetInitInfo(uint32_t loadIndex, InitInfo initInfos[], uint32_t& initOrder, bool& hasError);
199 bool findSymbol(BuilderLoadedImage& fromImage, int libraryOrdinal, const char* symbolName, bool weakImport, bool lazyBind, uint64_t addend,
200 Image::ResolvedSymbolTarget& target, ResolvedTargetInfo& targetInfo);
201 bool findSymbolInImage(const MachOAnalyzer* macho, const char* symbolName, uint64_t addend, bool followReExports,
202 bool weakImport, Image::ResolvedSymbolTarget& target, ResolvedTargetInfo& targetInfo);
203 const MachOAnalyzer* machOForImageNum(ImageNum imageNum);
204 ImageNum imageNumForMachO(const MachOAnalyzer* mh);
205 const MachOAnalyzer* findDependent(const MachOLoaded* mh, uint32_t depIndex);
206 BuilderLoadedImage& findLoadedImage(ImageNum imageNum);
207 BuilderLoadedImage& findLoadedImage(const MachOAnalyzer* mh);
208 uint32_t index(const BuilderLoadedImage&);
209 bool expandAtLoaderPath(const char* loadPath, bool fromLCRPATH, const BuilderLoadedImage& loadedImage, char fixedPath[]);
210 bool expandAtExecutablePath(const char* loadPath, bool fromLCRPATH, char fixedPath[]);
211 void addMustBeMissingPath(const char* path);
212 void addSkippedFile(const char* path, uint64_t inode, uint64_t mtime);
213 const char* strdup_temp(const char* path);
214 bool overridableDylib(const BuilderLoadedImage& forImage);
215 void forEachBind(BuilderLoadedImage& forImage, void (^handler)(uint64_t runtimeOffset, Image::ResolvedSymbolTarget target, const ResolvedTargetInfo& targetInfo, bool& stop),
216 void (^strongHandler)(const char* strongSymbolName),
217 void (^missingLazyBindHandler)());
218 bool findMissingSymbolHandler(Image::ResolvedSymbolTarget& target, ResolvedTargetInfo& targetInfo);
219
220 struct HashCString {
221 static size_t hash(const char* v);
222 };
223
224 struct EqualCString {
225 static bool equal(const char* s1, const char* s2);
226 };
227
228 struct HashPointer {
229 template<typename T>
230 static size_t hash(const T* v) {
231 return std::hash<const T*>{}(v);
232 }
233 };
234
235 struct EqualPointer {
236 template<typename T>
237 static bool equal(const T* s1, const T* s2) {
238 return s1 == s2;
239 }
240 };
241
242 struct ObjCOptimizerImage {
243
244 ObjCOptimizerImage() {
245 }
246
247 ~ObjCOptimizerImage() {
248 }
249
250 typedef std::pair<closure::Image::ObjCClassNameImageOffset, closure::Image::ObjCClassImageOffset> SeenClass;
251
252 struct SelectorFixup {
253 uint32_t fixupVMOffset;
254 bool isSharedCache;
255 union {
256 struct {
257 uint32_t selectorTableIndex;
258 } sharedCache;
259 struct {
260 const char* selectorString;
261 } image;
262 };
263 };
264
265 BuilderLoadedImage* loadedImage = nullptr;
266 ImageWriter* writer = nullptr;
267 uint64_t fairplayFileOffsetStart = 0;
268 uint64_t fairplayFileOffsetEnd = 0;
269 Diagnostics diag;
270
271 // Image info optimisation
272 uint64_t objcImageInfoVMOffset;
273
274 // Class and protocol optimisation data structures
275 OverflowSafeArray<std::pair<uint64_t, uint64_t>> classesNameAndDataVMOffsets;
276 OverflowSafeArray<SeenClass> seenClasses;
277 OverflowSafeArray<uint64_t> classStableSwiftFixups;
278 Map<const char*, dyld3::closure::Image::ObjCDuplicateClass, HashCString, EqualCString> classSharedCacheDuplicates;
279 OverflowSafeArray<SeenClass> seenProtocols;
280 OverflowSafeArray<uint64_t> protocolISAFixups;
281
282 // Selector optimsation data structures
283 OverflowSafeArray<SelectorFixup> selectorFixups;
284 Map<const char*, dyld3::closure::Image::ObjCImageOffset, HashCString, EqualCString> selectorMap;
285 std::optional<uint64_t> methodNameVMOffset;
286 };
287
288 bool optimizeObjC(Array<ImageWriter>& writers);
289 void optimizeObjCSelectors(const objc_opt::objc_selopt_t* objcSelOpt,
290 const Map<const char*, dyld3::closure::Image::ObjCImageOffset, HashCString, EqualCString>& closureSelectorMap,
291 ObjCOptimizerImage& image);
292 void optimizeObjCClasses(const objc_opt::objc_clsopt_t* objcClassOpt,
293 const Map<const dyld3::MachOAnalyzer*, bool, HashPointer, EqualPointer>& sharedCacheImagesMap,
294 const Map<const char*, dyld3::closure::Image::ObjCDuplicateClass, HashCString, EqualCString>& duplicateSharedCacheClasses,
295 ObjCOptimizerImage& image);
296 void optimizeObjCProtocols(const objc_opt::objc_protocolopt2_t* objcProtocolOpt,
297 const Map<const dyld3::MachOAnalyzer*, bool, HashPointer, EqualPointer>& sharedCacheImagesMap,
298 ObjCOptimizerImage& image);
299 void writeClassOrProtocolHashTable(bool classes, Array<ObjCOptimizerImage>& objcImages);
300
301 void addDuplicateObjCClassWarning(const char* className,
302 const char* duplicateDefinitionPath,
303 const char* canonicalDefinitionPath);
304
305 static bool inLoadedImageArray(const Array<LoadedImage>& loadedList, ImageNum imageNum);
306 static void buildLoadOrderRecurse(Array<LoadedImage>& loadedList, const Array<const ImageArray*>& imagesArrays, const Image* toAdd);
307 void invalidateInitializerRoots();
308
309 const FileSystem& _fileSystem;
310 const DyldSharedCache* const _dyldCache;
311 const PathOverrides& _pathOverrides;
312 const GradedArchs& _archs;
313 Platform const _platform;
314 uint32_t const _startImageNum;
315 const ImageArray* _dyldImageArray = nullptr;
316 const CacheDylibsBindingHandlers* _handlers = nullptr;
317 const Array<CachedDylibAlias>* _aliases = nullptr;
318 const AtPath _atPathHandling = AtPath::none;
319 uint32_t _mainProgLoadIndex = 0;
320 const char* _mainProgLoadPath = nullptr;
321 Diagnostics _diag;
322 LaunchErrorInfo* _launchErrorInfo = nullptr;
323 PathPool* _tempPaths = nullptr;
324 PathPool* _mustBeMissingPaths = nullptr;
325 OverflowSafeArray<SkippedFile> _skippedFiles;
326 uint32_t _nextIndex = 0;
327 OverflowSafeArray<BuilderLoadedImage,2048> _loadedImages;
328 OverflowSafeArray<Image::LinkedImage,65536> _dependencies; // all dylibs in cache need ~20,000 edges
329 OverflowSafeArray<InterposingTuple> _interposingTuples;
330 OverflowSafeArray<Closure::PatchEntry> _weakDefCacheOverrides;
331 OverflowSafeArray<const char*> _weakDefsFromChainedBinds;
332 OverflowSafeArray<uint8_t> _objcSelectorsHashTable;
333 OverflowSafeArray<Image::ObjCSelectorImage> _objcSelectorsHashTableImages;
334 OverflowSafeArray<uint8_t> _objcClassesHashTable;
335 OverflowSafeArray<uint8_t> _objcProtocolsHashTable;
336 OverflowSafeArray<Image::ObjCClassImage> _objcClassesHashTableImages;
337 OverflowSafeArray<uint8_t> _objcClassesDuplicatesHashTable;
338 PathPool* _objcDuplicateClassWarnings = nullptr;
339 uint32_t _alreadyInitedIndex = 0;
340 bool _isLaunchClosure = false;
341 bool _makingDyldCacheImages = false;
342 bool _dyldCacheIsLive = false; // means kernel is rebasing dyld cache content being viewed
343 bool _makingClosuresInCache = false;
344 bool _makingCustomerCache = false;
345 bool _allowRelativePaths = false;
346 bool _atPathUsed = false;
347 bool _fallbackPathUsed = false;
348 bool _allowMissingLazies = false;
349 bool _dyldCacheInvalidFormatVersion = false;
350 bool _foundNonCachedImage = false; // true means we have one or more images from disk we need to build closure(s) for
351 bool _foundDyldCacheRoots = false; // true if one or more images are roots of the shared cache
352 bool _foundMissingLazyBinds = false; // true if one or more images having missing lazy binds
353 ImageNum _libDyldImageNum = 0;
354 ImageNum _libSystemImageNum = 0;
355 };
356
357
358
359
360
361 } // namespace closure
362 } // namespace dyld3
363
364
365 #endif /* ClosureBuilder_h */