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 CacheBuilder_h
26 #define CacheBuilder_h
31 #include <unordered_map>
32 #include <unordered_set>
34 #include "ClosureFileSystem.h"
35 #include "DyldSharedCache.h"
36 #include "Diagnostics.h"
37 #include "MachOAnalyzer.h"
41 template <typename P
> class LinkeditOptimizer
;
46 CacheBuilder(const DyldSharedCache::CreateOptions
& options
, const dyld3::closure::FileSystem
& fileSystem
);
52 MustBeIncludedForDependent
,
53 MustBeExcludedIfUnused
55 InputFile(const char* path
, State state
) : path(path
), state(state
) { }
60 bool mustBeIncluded() const {
61 return (state
== MustBeIncluded
) || (state
== MustBeIncludedForDependent
);
65 // Contains a MachO which has been loaded from the file system and may potentially need to be unloaded later.
67 DyldSharedCache::MappedMachO mappedFile
;
68 dyld3::closure::LoadedFileInfo loadedFileInfo
;
72 void build(std::vector
<InputFile
>& inputFiles
,
73 std::vector
<DyldSharedCache::FileAlias
>& aliases
);
74 void build(const std::vector
<LoadedMachO
>& dylibs
,
75 const std::vector
<LoadedMachO
>& otherOsDylibsInput
,
76 const std::vector
<LoadedMachO
>& osExecutables
,
77 std::vector
<DyldSharedCache::FileAlias
>& aliases
);
78 void build(const std::vector
<DyldSharedCache::MappedMachO
>& dylibsToCache
,
79 const std::vector
<DyldSharedCache::MappedMachO
>& otherOsDylibs
,
80 const std::vector
<DyldSharedCache::MappedMachO
>& osExecutables
,
81 std::vector
<DyldSharedCache::FileAlias
>& aliases
);
82 void writeFile(const std::string
& path
);
83 void writeBuffer(uint8_t*& buffer
, uint64_t& size
);
84 void writeMapFile(const std::string
& path
);
85 void writeMapFileBuffer(uint8_t*& buffer
, uint64_t& bufferSize
);
87 std::string
errorMessage();
88 const std::set
<std::string
> warnings();
89 const std::set
<const dyld3::MachOAnalyzer
*> evictions();
90 const bool agileSignature();
91 const std::string
cdHashFirst();
92 const std::string
cdHashSecond();
94 void forEachCacheDylib(void (^callback
)(const std::string
& path
));
96 struct SegmentMappingInfo
{
97 const void* srcSegment
;
100 uint64_t dstCacheUnslidAddress
;
101 uint32_t dstCacheFileOffset
;
102 uint32_t dstCacheSegmentSize
;
103 uint32_t copySegmentSize
;
104 uint32_t srcSegmentIndex
;
112 void setDataRegion(const void* rwRegionStart
, size_t rwRegionSize
);
114 void remove(void* p
);
116 const bool* bitmap() { return _bitmap
; }
117 unsigned dataPageCount() { return _pageCount
; }
121 uint8_t* _regionStart
= nullptr;
122 uint8_t* _endStart
= nullptr;
123 bool* _bitmap
= nullptr;
124 unsigned _pageCount
= 0;
125 unsigned _pageSize
= 4096;
128 typedef std::map
<uint64_t, std::set
<void*>> LOH_Tracker
;
132 uint8_t* buffer
= nullptr;
133 uint64_t bufferSize
= 0;
134 uint64_t sizeInUse
= 0;
135 uint64_t unslidLoadAddress
= 0;
136 uint64_t cacheFileOffset
= 0;
140 template <typename P
>
141 friend class LinkeditOptimizer
;
145 uint64_t sharedMemoryStart
;
146 uint64_t sharedMemorySize
;
147 uint64_t sharedRegionPadding
;
148 uint64_t pointerDeltaMask
;
149 const char* archName
;
150 uint32_t branchPoolTextSize
;
151 uint32_t branchPoolLinkEditSize
;
152 uint32_t branchReach
;
153 uint8_t sharedRegionAlignP2
;
154 uint8_t slideInfoBytesPerPage
;
155 bool sharedRegionsAreDiscontiguous
;
159 static const ArchLayout _s_archLayout
[];
160 static const char* const _s_neverStubEliminate
[];
162 struct UnmappedRegion
164 uint8_t* buffer
= nullptr;
165 uint64_t bufferSize
= 0;
166 uint64_t sizeInUse
= 0;
171 const LoadedMachO
* input
;
172 std::string runtimePath
;
173 std::vector
<SegmentMappingInfo
> cacheLocation
;
176 void makeSortedDylibs(const std::vector
<LoadedMachO
>& dylibs
, const std::unordered_map
<std::string
, unsigned> sortOrder
);
177 void assignSegmentAddresses();
179 uint64_t cacheOverflowAmount();
180 size_t evictLeafDylibs(uint64_t reductionTarget
, std::vector
<const LoadedMachO
*>& overflowDylibs
);
184 uint64_t pathHash(const char* path
);
185 void writeCacheHeader();
186 void copyRawSegments();
187 void adjustAllImagesForNewSegmentLocations();
188 void writeSlideInfoV1();
189 void writeSlideInfoV3(const bool bitmap
[], unsigned dataPageCoun
);
190 uint16_t pageStartV3(uint8_t* pageContent
, uint32_t pageSize
, const bool bitmap
[]);
191 void findDylibAndSegment(const void* contentPtr
, std::string
& dylibName
, std::string
& segName
);
192 void addImageArray();
193 void buildImageArray(std::vector
<DyldSharedCache::FileAlias
>& aliases
);
194 void addOtherImageArray(const std::vector
<LoadedMachO
>&, std::vector
<const LoadedMachO
*>& overflowDylibs
);
195 void addClosures(const std::vector
<LoadedMachO
>&);
196 void markPaddingInaccessible();
198 bool writeCache(void (^cacheSizeCallback
)(uint64_t size
), bool (^copyCallback
)(const uint8_t* src
, uint64_t size
, uint64_t dstOffset
));
200 template <typename P
> void writeSlideInfoV2(const bool bitmap
[], unsigned dataPageCount
);
201 template <typename P
> bool makeRebaseChainV2(uint8_t* pageContent
, uint16_t lastLocationOffset
, uint16_t newOffset
, const struct dyld_cache_slide_info2
* info
);
202 template <typename P
> void addPageStartsV2(uint8_t* pageContent
, const bool bitmap
[], const struct dyld_cache_slide_info2
* info
,
203 std::vector
<uint16_t>& pageStarts
, std::vector
<uint16_t>& pageExtras
);
205 template <typename P
> void writeSlideInfoV4(const bool bitmap
[], unsigned dataPageCount
);
206 template <typename P
> bool makeRebaseChainV4(uint8_t* pageContent
, uint16_t lastLocationOffset
, uint16_t newOffset
, const struct dyld_cache_slide_info4
* info
);
207 template <typename P
> void addPageStartsV4(uint8_t* pageContent
, const bool bitmap
[], const struct dyld_cache_slide_info4
* info
,
208 std::vector
<uint16_t>& pageStarts
, std::vector
<uint16_t>& pageExtras
);
210 // implemented in AdjustDylibSegemnts.cpp
211 void adjustDylibSegments(const DylibInfo
& dylib
, Diagnostics
& diag
) const;
213 // implemented in OptimizerLinkedit.cpp
214 void optimizeLinkedit(const std::vector
<uint64_t>& branchPoolOffsets
);
216 // implemented in OptimizerObjC.cpp
219 // implemented in OptimizerBranches.cpp
220 void optimizeAwayStubs(const std::vector
<uint64_t>& branchPoolStartAddrs
, uint64_t branchPoolsLinkEditStartAddr
);
223 typedef std::unordered_map
<std::string
, const dyld3::MachOAnalyzer
*> InstallNameToMA
;
226 const DyldSharedCache::CreateOptions
& _options
;
227 const dyld3::closure::FileSystem
& _fileSystem
;
228 Region _readExecuteRegion
;
229 Region _readWriteRegion
;
230 Region _readOnlyRegion
;
231 UnmappedRegion _localSymbolsRegion
;
232 UnmappedRegion _codeSignatureRegion
;
233 vm_address_t _fullAllocatedBuffer
;
234 uint64_t _nonLinkEditReadOnlySize
;
235 Diagnostics _diagnostics
;
236 std::set
<const dyld3::MachOAnalyzer
*> _evictions
;
237 const ArchLayout
* _archLayout
;
238 uint32_t _aliasCount
;
239 uint64_t _slideInfoFileOffset
;
240 uint64_t _slideInfoBufferSizeAllocated
;
241 uint64_t _allocatedBufferSize
;
242 std::vector
<DylibInfo
> _sortedDylibs
;
243 InstallNameToMA _installNameToCacheDylib
;
244 std::unordered_map
<std::string
, uint32_t> _dataDirtySegsOrder
;
245 // Note this is mutable as the only parallel writes to it are done atomically to the bitmap
246 mutable ASLR_Tracker _aslrTracker
;
247 std::map
<void*, std::string
> _missingWeakImports
;
248 mutable LOH_Tracker _lohTracker
;
249 const dyld3::closure::ImageArray
* _imageArray
;
250 uint32_t _sharedStringsPoolVmOffset
;
251 std::vector
<uint64_t> _branchPoolStarts
;
252 uint64_t _branchPoolsLinkEditStartAddr
;
253 uint8_t _cdHashFirst
[20];
254 uint8_t _cdHashSecond
[20];
260 inline uint64_t align(uint64_t addr
, uint8_t p2
)
262 uint64_t mask
= (1 << p2
);
263 return (addr
+ mask
- 1) & (-mask
);
268 #endif /* CacheBuilder_h */