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>
33 #include "dyld_cache_format.h"
34 #include "Diagnostics.h"
35 #include "MachOParser.h"
39 namespace launch_cache
{
40 namespace binary_format
{
49 class VIS_HIDDEN DyldSharedCache
53 enum CodeSigningDigestMode
63 dyld3::Platform platform
;
64 bool excludeLocalSymbols
;
67 CodeSigningDigestMode codeSigningDigestMode
;
68 bool agileSignatureChooseSHA256CdHash
;
69 bool dylibsRemovedDuringMastering
;
70 bool inodesAreSameAsRuntime
;
71 bool cacheSupportsASLR
;
74 bool evictLeafDylibsOnOverflow
;
75 std::unordered_map
<std::string
, unsigned> dylibOrdering
;
76 std::unordered_map
<std::string
, unsigned> dirtyDataSegmentOrdering
;
77 std::vector
<std::string
> pathPrefixes
;
78 std::string loggingPrefix
;
84 : mh(nullptr), length(0), isSetUID(false), protectedBySIP(false), sliceFileOffset(0), modTime(0), inode(0) { }
85 MappedMachO(const std::string
& path
, const mach_header
* p
, size_t l
, bool isu
, bool sip
, uint64_t o
, uint64_t m
, uint64_t i
)
86 : runtimePath(path
), mh(p
), length(l
), isSetUID(isu
), protectedBySIP(sip
), sliceFileOffset(o
), modTime(m
), inode(i
) { }
88 std::string runtimePath
;
89 const mach_header
* mh
;
91 uint64_t isSetUID
: 1,
94 uint64_t modTime
; // only recorded if inodesAreSameAsRuntime
95 uint64_t inode
; // only recorded if inodesAreSameAsRuntime
100 const DyldSharedCache
* cacheContent
= nullptr; // caller needs to vm_deallocate() when done
101 size_t cacheLength
= 0;
102 std::string errorMessage
;
103 std::set
<std::string
> warnings
;
104 std::set
<const mach_header
*> evictions
;
105 bool agileSignature
= false;
106 std::string cdHashFirst
;
107 std::string cdHashSecond
;
111 // This function verifies the set of dylibs that will go into the cache are self contained. That the depend on no dylibs
112 // outset the set. It will call back the loader function to try to find any mising dylibs.
113 static bool verifySelfContained(std::vector
<MappedMachO
>& dylibsToCache
, MappedMachO (^loader
)(const std::string
& runtimePath
), std::vector
<std::pair
<DyldSharedCache::MappedMachO
, std::set
<std::string
>>>& excluded
);
117 // This function is single threaded and creates a shared cache. The cache file is created in-memory.
120 // options: various per-platform flags
121 // dylibsToCache: a list of dylibs to include in the cache
122 // otherOsDylibs: a list of other OS dylibs and bundle which should have load info added to the cache
123 // osExecutables: a list of main executables which should have closures created in the cache
127 // cacheContent: start of the allocated cache buffer which must be vm_deallocated after the caller writes out the buffer.
128 // cacheLength: size of the allocated cache buffer
129 // cdHash: hash of the code directory of the code blob of the created cache
130 // warnings: all warning messsages generated during the creation of the cache
133 // cacheContent: nullptr
134 // errorMessage: the string describing why the cache could not be created
135 // warnings: all warning messsages generated before the failure
137 static CreateResults
create(const CreateOptions
& options
,
138 const std::vector
<MappedMachO
>& dylibsToCache
,
139 const std::vector
<MappedMachO
>& otherOsDylibs
,
140 const std::vector
<MappedMachO
>& osExecutables
);
144 // Returns a text "map" file as a big string
146 std::string
mapFile() const;
150 // Returns the architecture name of the shared cache, e.g. "arm64"
152 std::string
archName() const;
156 // Returns the platform the cache is for
158 uint32_t platform() const;
162 // Iterates over each dylib in the cache
164 void forEachImage(void (^handler
)(const mach_header
* mh
, const char* installName
)) const;
168 // Iterates over each dylib in the cache
170 void forEachImageEntry(void (^handler
)(const char* path
, uint64_t mTime
, uint64_t inode
)) const;
174 // Iterates over each dylib in the cache
176 void forEachImageTextSegment(void (^handler
)(uint64_t loadAddressUnslid
, uint64_t textSegmentSize
, const uuid_t dylibUUID
, const char* installName
)) const;
180 // Iterates over each of the three regions in the cache
182 void forEachRegion(void (^handler
)(const void* content
, uint64_t vmAddr
, uint64_t size
, uint32_t permissions
)) const;
186 // returns address the cache would load at if unslid
188 uint64_t unslidLoadAddress() const;
192 // returns UUID of cache
194 void getUUID(uuid_t uuid
) const;
198 // returns the vm size required to map cache
200 uint64_t mappedSize() const;
203 dyld_cache_header header
;
213 #endif /* DyldSharedCache_h */