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 std::string
errorMessage();
74 struct SegmentMappingInfo
{
75 const void* srcSegment
;
78 uint64_t dstCacheUnslidAddress
;
79 uint32_t dstCacheFileOffset
;
80 uint32_t dstCacheSegmentSize
;
81 uint32_t dstCacheFileSize
;
82 uint32_t copySegmentSize
;
83 uint32_t srcSegmentIndex
;
86 struct DylibTextCoalescer
{
88 typedef std::map
<uint32_t, uint32_t> DylibSectionOffsetToCacheSectionOffset
;
90 DylibSectionOffsetToCacheSectionOffset objcClassNames
;
91 DylibSectionOffsetToCacheSectionOffset objcMethNames
;
92 DylibSectionOffsetToCacheSectionOffset objcMethTypes
;
94 bool sectionWasCoalesced(std::string_view sectionName
) const;
95 DylibSectionOffsetToCacheSectionOffset
& getSectionCoalescer(std::string_view sectionName
);
96 const DylibSectionOffsetToCacheSectionOffset
& getSectionCoalescer(std::string_view sectionName
) const;
99 struct CacheCoalescedText
{
100 static const char* SupportedSections
[3];
101 struct StringSection
{
102 // Map from class name strings to offsets in to the class names buffer
103 std::map
<std::string_view
, uint32_t> stringsToOffsets
;
104 uint8_t* bufferAddr
= nullptr;
105 uint32_t bufferSize
= 0;
106 uint64_t bufferVMAddr
= 0;
108 // Note this is for debugging only
109 uint64_t savedSpace
= 0;
112 StringSection objcClassNames
;
113 StringSection objcMethNames
;
114 StringSection objcMethTypes
;
116 void parseCoalescableText(const dyld3::MachOAnalyzer
* ma
,
117 DylibTextCoalescer
& textCoalescer
);
120 StringSection
& getSectionData(std::string_view sectionName
);
121 const StringSection
& getSectionData(std::string_view sectionName
) const;
129 void setDataRegion(const void* rwRegionStart
, size_t rwRegionSize
);
131 void setHigh8(void* p
, uint8_t high8
);
132 void setAuthData(void* p
, uint16_t diversity
, bool hasAddrDiv
, uint8_t key
);
133 void setRebaseTarget32(void*p
, uint32_t targetVMAddr
);
134 void setRebaseTarget64(void*p
, uint64_t targetVMAddr
);
135 void remove(void* p
);
137 const bool* bitmap() { return _bitmap
; }
138 unsigned dataPageCount() { return _pageCount
; }
139 void disable() { _enabled
= false; };
140 bool hasHigh8(void* p
, uint8_t* highByte
);
141 bool hasAuthData(void* p
, uint16_t* diversity
, bool* hasAddrDiv
, uint8_t* key
);
142 bool hasRebaseTarget32(void* p
, uint32_t* vmAddr
);
143 bool hasRebaseTarget64(void* p
, uint64_t* vmAddr
);
147 uint8_t* _regionStart
= nullptr;
148 uint8_t* _regionEnd
= nullptr;
149 bool* _bitmap
= nullptr;
150 unsigned _pageCount
= 0;
151 unsigned _pageSize
= 4096;
152 bool _enabled
= true;
159 std::unordered_map
<void*, uint8_t> _high8Map
;
160 std::unordered_map
<void*, AuthData
> _authDataMap
;
161 std::unordered_map
<void*, uint32_t> _rebaseTarget32
;
162 std::unordered_map
<void*, uint64_t> _rebaseTarget64
;
165 typedef std::map
<uint64_t, std::set
<void*>> LOH_Tracker
;
167 static const uint64_t kRebaseTargetInSideTableArm64e
= 0x7FFFFFFFFFFULL
;
168 static const uint64_t kRebaseTargetInSideTableArm64
= 0xFFFFFFFFFULL
;
169 static const uint64_t kRebaseTargetInSideTableGeneric32
= 0x3FFFFFFULL
;
174 uint8_t* buffer
= nullptr;
175 uint64_t bufferSize
= 0;
176 uint64_t sizeInUse
= 0;
177 uint64_t unslidLoadAddress
= 0;
178 uint64_t cacheFileOffset
= 0;
182 template <typename P
>
183 friend class LinkeditOptimizer
;
185 struct UnmappedRegion
187 uint8_t* buffer
= nullptr;
188 uint64_t bufferSize
= 0;
189 uint64_t sizeInUse
= 0;
194 const LoadedMachO
* input
;
195 std::string runtimePath
;
196 std::vector
<SegmentMappingInfo
> cacheLocation
;
197 DylibTextCoalescer textCoalescer
;
200 void copyRawSegments();
201 void adjustAllImagesForNewSegmentLocations();
203 // implemented in AdjustDylibSegemnts.cpp
204 void adjustDylibSegments(const DylibInfo
& dylib
, Diagnostics
& diag
) const;
206 // implemented in OptimizerLinkedit.cpp
207 void optimizeLinkedit();
209 const DyldSharedCache::CreateOptions
& _options
;
210 const dyld3::closure::FileSystem
& _fileSystem
;
211 Region _readExecuteRegion
;
212 Region _readWriteRegion
;
213 Region _readOnlyRegion
;
214 UnmappedRegion _localSymbolsRegion
;
215 vm_address_t _fullAllocatedBuffer
;
216 uint64_t _nonLinkEditReadOnlySize
;
217 Diagnostics _diagnostics
;
218 uint64_t _allocatedBufferSize
;
219 std::vector
<DylibInfo
> _sortedDylibs
;
220 CacheCoalescedText _coalescedText
;
221 uint32_t _sharedStringsPoolVmOffset
= 0;
223 // Note this is mutable as the only parallel writes to it are done atomically to the bitmap
224 mutable ASLR_Tracker _aslrTracker
;
225 mutable LOH_Tracker _lohTracker
;
231 inline uint64_t align(uint64_t addr
, uint8_t p2
)
233 uint64_t mask
= (1 << p2
);
234 return (addr
+ mask
- 1) & (-mask
);
239 #endif /* CacheBuilder_h */