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 DyldSharedCache_h
26 #define DyldSharedCache_h
31 #include <unordered_map>
32 #include <uuid/uuid.h>
34 #include "dyld_cache_format.h"
35 #include "Diagnostics.h"
36 #include "MachOAnalyzer.h"
40 class VIS_HIDDEN DyldSharedCache
44 enum CodeSigningDigestMode
53 std::string outputFilePath
;
54 std::string outputMapFilePath
;
56 dyld3::Platform platform
;
57 bool excludeLocalSymbols
;
60 CodeSigningDigestMode codeSigningDigestMode
;
61 bool dylibsRemovedDuringMastering
;
62 bool inodesAreSameAsRuntime
;
63 bool cacheSupportsASLR
;
65 bool isLocallyBuiltCache
;
67 bool evictLeafDylibsOnOverflow
;
68 std::unordered_map
<std::string
, unsigned> dylibOrdering
;
69 std::unordered_map
<std::string
, unsigned> dirtyDataSegmentOrdering
;
70 std::vector
<std::string
> pathPrefixes
;
71 std::string loggingPrefix
;
77 : mh(nullptr), length(0), isSetUID(false), protectedBySIP(false), sliceFileOffset(0), modTime(0), inode(0) { }
78 MappedMachO(const std::string
& path
, const dyld3::MachOAnalyzer
* p
, size_t l
, bool isu
, bool sip
, uint64_t o
, uint64_t m
, uint64_t i
)
79 : runtimePath(path
), mh(p
), length(l
), isSetUID(isu
), protectedBySIP(sip
), sliceFileOffset(o
), modTime(m
), inode(i
) { }
81 std::string runtimePath
;
82 const dyld3::MachOAnalyzer
* mh
;
84 uint64_t isSetUID
: 1,
87 uint64_t modTime
; // only recorded if inodesAreSameAsRuntime
88 uint64_t inode
; // only recorded if inodesAreSameAsRuntime
93 std::string errorMessage
;
94 std::set
<std::string
> warnings
;
95 std::set
<const dyld3::MachOAnalyzer
*> evictions
;
96 bool agileSignature
= false;
97 std::string cdHashFirst
;
98 std::string cdHashSecond
;
104 std::string realPath
;
105 std::string aliasPath
;
109 // This function verifies the set of dylibs that will go into the cache are self contained. That the depend on no dylibs
110 // outset the set. It will call back the loader function to try to find any mising dylibs.
111 static bool verifySelfContained(std::vector
<MappedMachO
>& dylibsToCache
, MappedMachO (^loader
)(const std::string
& runtimePath
), std::vector
<std::pair
<DyldSharedCache::MappedMachO
, std::set
<std::string
>>>& excluded
);
115 // This function is single threaded and creates a shared cache. The cache file is created in-memory.
118 // options: various per-platform flags
119 // dylibsToCache: a list of dylibs to include in the cache
120 // otherOsDylibs: a list of other OS dylibs and bundle which should have load info added to the cache
121 // osExecutables: a list of main executables which should have closures created in the cache
125 // cacheContent: start of the allocated cache buffer which must be vm_deallocated after the caller writes out the buffer.
126 // cacheLength: size of the allocated cache buffer
127 // cdHash: hash of the code directory of the code blob of the created cache
128 // warnings: all warning messsages generated during the creation of the cache
131 // cacheContent: nullptr
132 // errorMessage: the string describing why the cache could not be created
133 // warnings: all warning messsages generated before the failure
135 static CreateResults
create(const CreateOptions
& options
,
136 const std::vector
<MappedMachO
>& dylibsToCache
,
137 const std::vector
<MappedMachO
>& otherOsDylibs
,
138 const std::vector
<MappedMachO
>& osExecutables
);
142 // Returns a text "map" file as a big string
144 std::string
mapFile() const;
148 // Returns the architecture name of the shared cache, e.g. "arm64"
150 const char* archName() const;
154 // Returns the platform the cache is for
156 dyld3::Platform
platform() const;
160 // Iterates over each dylib in the cache
162 void forEachImage(void (^handler
)(const mach_header
* mh
, const char* installName
)) const;
166 // Searches cache for dylib with specified path
168 bool hasImagePath(const char* dylibPath
, uint32_t& imageIndex
) const;
172 // Searches cache for dylib with specified mach_header
174 bool findMachHeaderImageIndex(const mach_header
* mh
, uint32_t& imageIndex
) const;
177 // Iterates over each dylib in the cache
179 void forEachImageEntry(void (^handler
)(const char* path
, uint64_t mTime
, uint64_t inode
)) const;
183 // Iterates over each dylib in the cache
185 const mach_header
* getIndexedImageEntry(uint32_t index
, uint64_t& mTime
, uint64_t& node
) const;
189 // Iterates over each dylib in the cache
191 void forEachImageTextSegment(void (^handler
)(uint64_t loadAddressUnslid
, uint64_t textSegmentSize
, const uuid_t dylibUUID
, const char* installName
, bool& stop
)) const;
195 // Iterates over each of the three regions in the cache
197 void forEachRegion(void (^handler
)(const void* content
, uint64_t vmAddr
, uint64_t size
, uint32_t permissions
)) const;
201 // Returns if an address range is in this cache, and if so if in a read-only area
203 bool inCache(const void* addr
, size_t length
, bool& readOnly
) const;
207 // returns address the cache would load at if unslid
209 uint64_t unslidLoadAddress() const;
213 // returns UUID of cache
215 void getUUID(uuid_t uuid
) const;
219 // returns the vm size required to map cache
221 uint64_t mappedSize() const;
225 // searches cache for pre-built closure for program
227 const dyld3::closure::LaunchClosure
* findClosure(const char* executablePath
) const;
231 // iterates all pre-built closures for program
233 void forEachLaunchClosure(void (^handler
)(const char* executableRuntimePath
, const dyld3::closure::LaunchClosure
* closure
)) const;
237 // iterates all pre-built Image* for OS dylibs/bundles not in dyld cache
239 void forEachDlopenImage(void (^handler
)(const char* runtimePath
, const dyld3::closure::Image
* image
)) const;
243 // returns the ImageArray pointer to Images in dyld shared cache
245 const dyld3::closure::ImageArray
* cachedDylibsImageArray() const;
249 // returns the ImageArray pointer to Images in OS with pre-build dlopen closure
251 const dyld3::closure::ImageArray
* otherOSImageArray() const;
255 // searches cache for pre-built dlopen closure for OS dylib/bundle
257 const dyld3::closure::Image
* findDlopenOtherImage(const char* path
) const;
261 // returns true if the offset is in the TEXT of some cached dylib and sets *index to the dylib index
263 bool addressInText(uint32_t cacheOffset
, uint32_t* index
) const;
267 dyld_cache_header header
;
277 #endif /* DyldSharedCache_h */