dyld-655.1.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 "Loading.h"
36
37
38
39 namespace dyld3 {
40
41
42 namespace closure {
43
44
45
46 class VIS_HIDDEN ClosureBuilder
47 {
48 public:
49
50 struct LaunchErrorInfo
51 {
52 uintptr_t kind;
53 const char* clientOfDylibPath;
54 const char* targetDylibPath;
55 const char* symbol;
56 };
57
58 struct ResolvedTargetInfo
59 {
60 const MachOLoaded* foundInDylib;
61 const char* requestedSymbolName;
62 const char* foundSymbolName;
63 uint64_t addend;
64 bool weakBindCoalese;
65 bool weakBindSameImage;
66 bool isWeakDef;
67 int libOrdinal;
68 };
69
70 typedef Image::PatchableExport::PatchLocation PatchLocation;
71
72 struct CacheDylibsBindingHandlers
73 {
74 struct PatchInfo
75 {
76 const char* exportSymbolName;
77 uint32_t exportCacheOffset;
78 uint32_t usesCount;
79 const PatchLocation* usesArray;
80 };
81
82 void (^rebase)(ImageNum, const MachOLoaded* imageToFix, uint32_t runtimeOffset);
83 void (^bind)(ImageNum, const MachOLoaded* imageToFix, uint32_t runtimeOffset, Image::ResolvedSymbolTarget target, const ResolvedTargetInfo& targetInfo);
84 void (^chainedBind)(ImageNum, const MachOLoaded*, const Array<uint64_t>& starts, const Array<Image::ResolvedSymbolTarget>& targets, const Array<ResolvedTargetInfo>& targetInfos);
85 void (^forEachExportsPatch)(ImageNum, void (^handler)(const PatchInfo&));
86 };
87
88 enum class AtPath { none, all, onlyInRPaths };
89
90 ClosureBuilder(uint32_t startImageNum, const FileSystem& fileSystem, const DyldSharedCache* dyldCache, bool dyldCacheIsLive,
91 const PathOverrides& pathOverrides, AtPath atPathHandling=AtPath::all,
92 LaunchErrorInfo* errorInfo=nullptr,
93 const char* archName=MachOFile::currentArchName(), Platform platform=MachOFile::currentPlatform(),
94 const CacheDylibsBindingHandlers* handlers=nullptr);
95 ~ClosureBuilder();
96 Diagnostics& diagnostics() { return _diag; }
97
98 const LaunchClosure* makeLaunchClosure(const LoadedFileInfo& fileInfo, bool allowInsertFailures);
99
100 const LaunchClosure* makeLaunchClosure(const char* mainPath,bool allowInsertFailures);
101
102
103 static const DlopenClosure* sRetryDlopenClosure;
104 const DlopenClosure* makeDlopenClosure(const char* dylibPath, const LaunchClosure* mainClosure, const Array<LoadedImage>& loadedList,
105 closure::ImageNum callerImageNum, bool noLoad, bool canUseSharedCacheClosure,
106 closure::ImageNum* topImageNum);
107
108 ImageNum nextFreeImageNum() const { return _startImageNum + _nextIndex; }
109
110
111 struct PatchableExport
112 {
113 uint32_t cacheOffsetOfImpl;
114 uint32_t cacheOffsetOfName;
115 uint32_t patchLocationsCount;
116 const PatchLocation* patchLocations;
117 };
118
119 struct CachedDylibInfo
120 {
121 LoadedFileInfo fileInfo;
122 };
123
124 struct CachedDylibAlias
125 {
126 const char* realPath;
127 const char* aliasPath;
128 };
129
130 const ImageArray* makeDyldCacheImageArray(bool customerCache, const Array<CachedDylibInfo>& dylibs, const Array<CachedDylibAlias>& aliases);
131
132 const ImageArray* makeOtherDylibsImageArray(const Array<LoadedFileInfo>& otherDylibs, uint32_t cachedDylibsCount);
133
134 static void buildLoadOrder(Array<LoadedImage>& loadedList, const Array<const ImageArray*>& imagesArrays, const Closure* toAdd);
135
136 private:
137
138
139 struct InitInfo
140 {
141 uint32_t initOrder;
142 bool danglingUpward;
143 bool visited;
144 };
145
146 struct BuilderLoadedImage
147 {
148 Array<Image::LinkedImage> dependents;
149 ImageNum imageNum;
150 uint32_t unmapWhenDone : 1,
151 contentRebased : 1,
152 hasInits : 1,
153 markNeverUnload : 1,
154 rtldLocal : 1,
155 isBadImage : 1,
156 padding : 14,
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
172 void recursiveLoadDependents(LoadedImageChain& forImageChain);
173 void loadDanglingUpwardLinks();
174 const char* resolvePathVar(const char* loadPath, const LoadedImageChain& forImageChain, bool implictRPath);
175 bool findImage(const char* loadPath, const LoadedImageChain& forImageChain, BuilderLoadedImage*& foundImage, bool mustBeDylib, bool allowOther=true);
176 void buildImage(ImageWriter& writer, BuilderLoadedImage& forImage);
177 void addSegments(ImageWriter& writer, const MachOAnalyzer* mh);
178 void addRebaseInfo(ImageWriter& writer, const MachOAnalyzer* mh);
179 void addSynthesizedRebaseInfo(ImageWriter& writer, const MachOAnalyzer* mh);
180 void addSynthesizedBindInfo(ImageWriter& writer, const MachOAnalyzer* mh);
181 void addBindInfo(ImageWriter& writer, BuilderLoadedImage& forImage);
182 void reportRebasesAndBinds(ImageWriter& writer, BuilderLoadedImage& forImage);
183 void addChainedFixupInfo(ImageWriter& writer, const BuilderLoadedImage& forImage);
184 void addInterposingTuples(LaunchClosureWriter& writer, const Image* image, const MachOAnalyzer* mh);
185 void computeInitOrder(ImageWriter& writer, uint32_t loadIndex);
186 void addCachePatchInfo(ImageWriter& writer, const BuilderLoadedImage& forImage);
187 void addClosureInfo(LaunchClosureWriter& closureWriter);
188 void depthFirstRecurseSetInitInfo(uint32_t loadIndex, InitInfo initInfos[], uint32_t& initOrder, bool& hasError);
189 bool findSymbol(const BuilderLoadedImage& fromImage, int libraryOrdinal, const char* symbolName, bool weakImport, uint64_t addend,
190 Image::ResolvedSymbolTarget& target, ResolvedTargetInfo& targetInfo);
191 bool findSymbolInImage(const MachOAnalyzer* macho, const char* symbolName, uint64_t addend, bool followReExports, Image::ResolvedSymbolTarget& target, ResolvedTargetInfo& targetInfo);
192 const MachOAnalyzer* machOForImageNum(ImageNum imageNum);
193 ImageNum imageNumForMachO(const MachOAnalyzer* mh);
194 const MachOAnalyzer* findDependent(const MachOLoaded* mh, uint32_t depIndex);
195 BuilderLoadedImage& findLoadedImage(ImageNum imageNum);
196 BuilderLoadedImage& findLoadedImage(const MachOAnalyzer* mh);
197 uint32_t index(const BuilderLoadedImage&);
198 bool expandAtLoaderPath(const char* loadPath, bool fromLCRPATH, const BuilderLoadedImage& loadedImage, char fixedPath[]);
199 bool expandAtExecutablePath(const char* loadPath, bool fromLCRPATH, char fixedPath[]);
200 void addMustBeMissingPath(const char* path);
201 const char* strdup_temp(const char* path);
202 bool overridableDylib(const BuilderLoadedImage& forImage);
203 void forEachBind(BuilderLoadedImage& forImage, void (^handler)(uint64_t runtimeOffset, Image::ResolvedSymbolTarget target, const ResolvedTargetInfo& targetInfo, bool& stop),
204 void (^strongHandler)(const char* strongSymbolName));
205
206 static bool inLoadedImageArray(const Array<LoadedImage>& loadedList, ImageNum imageNum);
207 static void buildLoadOrderRecurse(Array<LoadedImage>& loadedList, const Array<const ImageArray*>& imagesArrays, const Image* toAdd);
208
209 const FileSystem& _fileSystem;
210 const DyldSharedCache* const _dyldCache;
211 const PathOverrides& _pathOverrides;
212 const char* const _archName;
213 Platform const _platform;
214 uint32_t const _startImageNum;
215 const ImageArray* _dyldImageArray = nullptr;
216 const CacheDylibsBindingHandlers* _handlers = nullptr;
217 const Array<CachedDylibAlias>* _aliases = nullptr;
218 const AtPath _atPathHandling = AtPath::none;
219 uint32_t _mainProgLoadIndex = 0;
220 Diagnostics _diag;
221 LaunchErrorInfo* _launchErrorInfo = nullptr;
222 PathPool* _tempPaths = nullptr;
223 PathPool* _mustBeMissingPaths = nullptr;
224 uint32_t _nextIndex = 0;
225 OverflowSafeArray<BuilderLoadedImage> _loadedImages;
226 OverflowSafeArray<Image::LinkedImage,65536> _dependencies; // all dylibs in cache need ~20,000 edges
227 OverflowSafeArray<InterposingTuple> _interposingTuples;
228 OverflowSafeArray<Closure::PatchEntry> _weakDefCacheOverrides;
229 OverflowSafeArray<const char*> _weakDefsFromChainedBinds;
230 uint32_t _alreadyInitedIndex = 0;
231 bool _isLaunchClosure = false;
232 bool _makingDyldCacheImages = false;
233 bool _dyldCacheIsLive = false; // means kernel is rebasing dyld cache content being viewed
234 bool _makingClosuresInCache = false;
235 bool _makingCustomerCache = false;
236 bool _atPathUsed = false;
237 bool _fallbackPathUsed = false;
238 ImageNum _libDyldImageNum = 0;
239 ImageNum _libSystemImageNum = 0;
240 };
241
242
243
244
245
246 } // namespace closure
247 } // namespace dyld3
248
249
250 #endif /* ClosureBuilder_h */