2 * Copyright (c) 2017 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
25 #ifndef ClosureBuilder_h
26 #define ClosureBuilder_h
30 #include "ClosureFileSystem.h"
31 #include "ClosureWriter.h"
32 #include "PathOverrides.h"
33 #include "DyldSharedCache.h"
34 #include "MachOAnalyzer.h"
46 class VIS_HIDDEN ClosureBuilder
50 struct LaunchErrorInfo
53 const char* clientOfDylibPath
;
54 const char* targetDylibPath
;
58 struct ResolvedTargetInfo
60 const MachOLoaded
* foundInDylib
;
61 const char* requestedSymbolName
;
62 const char* foundSymbolName
;
65 bool weakBindSameImage
;
70 typedef Image::PatchableExport::PatchLocation PatchLocation
;
72 struct CacheDylibsBindingHandlers
76 const char* exportSymbolName
;
77 uint32_t exportCacheOffset
;
79 const PatchLocation
* usesArray
;
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
&));
88 enum class AtPath
{ none
, all
, onlyInRPaths
};
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);
96 Diagnostics
& diagnostics() { return _diag
; }
98 const LaunchClosure
* makeLaunchClosure(const LoadedFileInfo
& fileInfo
, bool allowInsertFailures
);
100 const LaunchClosure
* makeLaunchClosure(const char* mainPath
,bool allowInsertFailures
);
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
);
108 ImageNum
nextFreeImageNum() const { return _startImageNum
+ _nextIndex
; }
111 struct PatchableExport
113 uint32_t cacheOffsetOfImpl
;
114 uint32_t cacheOffsetOfName
;
115 uint32_t patchLocationsCount
;
116 const PatchLocation
* patchLocations
;
119 struct CachedDylibInfo
121 LoadedFileInfo fileInfo
;
124 struct CachedDylibAlias
126 const char* realPath
;
127 const char* aliasPath
;
130 const ImageArray
* makeDyldCacheImageArray(bool customerCache
, const Array
<CachedDylibInfo
>& dylibs
, const Array
<CachedDylibAlias
>& aliases
);
132 const ImageArray
* makeOtherDylibsImageArray(const Array
<LoadedFileInfo
>& otherDylibs
, uint32_t cachedDylibsCount
);
134 static void buildLoadOrder(Array
<LoadedImage
>& loadedList
, const Array
<const ImageArray
*>& imagesArrays
, const Closure
* toAdd
);
146 struct BuilderLoadedImage
148 Array
<Image::LinkedImage
> dependents
;
150 uint32_t unmapWhenDone
: 1,
157 overrideImageNum
: 12;
158 LoadedFileInfo loadedFileInfo
;
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
; }
165 struct LoadedImageChain
167 LoadedImageChain
* previous
;
168 BuilderLoadedImage
& image
;
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
));
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
);
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;
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;
246 } // namespace closure
250 #endif /* ClosureBuilder_h */