1 /* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*-
3 * Copyright (c) 2014 Apple Inc. All rights reserved.
5 * @APPLE_LICENSE_HEADER_START@
7 * This file contains Original Code and/or Modifications of Original Code
8 * as defined in and that are subject to the Apple Public Source License
9 * Version 2.0 (the 'License'). You may not use this file except in
10 * compliance with the License. Please obtain a copy of the License at
11 * http://www.opensource.apple.com/apsl/ and read it before using this
14 * The Original Code and all software distributed under the License are
15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
19 * Please see the License for the specific language governing rights and
20 * limitations under the License.
22 * @APPLE_LICENSE_HEADER_END@
25 #ifndef __MEGA_DYLIB_UTILS_H__
26 #define __MEGA_DYLIB_UTILS_H__
28 #include <sys/types.h>
37 #include <dispatch/dispatch.h>
45 #include <unordered_set>
46 #include <unordered_map>
48 #include "CacheFileAbstraction.hpp"
50 #include "MachOFileAbstraction.hpp"
53 #include "MachOProxy.h"
59 std::tuple
<uint8_t *, struct stat
, bool> cacheLoad(const std::string path
);
60 void preflightCache(const std::string
& path
);
61 void preflightCache(const std::unordered_set
<std::string
> &paths
);
63 void fill(const std::string
& path
);
65 std::unordered_map
<std::string
, std::tuple
<uint8_t *, struct stat
, bool>> entries
;
66 dispatch_queue_t cache_queue
;
69 extern FileCache fileCache
;
71 typedef std::pair
<Manifest
*,std::set
<std::pair
<std::string
, std::string
>>> WarningTargets
;
73 inline uint64_t align(uint64_t addr
, uint8_t p2
)
75 uint64_t mask
= (1 << p2
);
76 return (addr
+ mask
- 1) & (-mask
);
80 uint64_t sharedRegionRegionSize(ArchPair arch
);
81 uint8_t sharedRegionRegionAlignment(ArchPair arch
);
82 ArchPair
archForString(const std::string
& archStr
);
83 std::string
stringForArch(ArchPair arch
, bool allowUnknown
= false);
84 std::string
fallbackArchStringForArchString( const std::string
& archStr
);
88 SegmentInfo(const MachOProxy::Segment
* seg
)
89 : base(seg
), address(0), cacheFileOffset(0), cacheSegSize(0) { }
91 const MachOProxy::Segment
* base
;
93 uint64_t cacheFileOffset
;
94 uint64_t cacheSegSize
;
104 SharedCache(Manifest
& manifest
,
105 const std::string
& configuration
, const std::string
& architecture
);
107 // We do not need an explicit destructor despite our move/copy constructor because the resource the are dealing with is a
108 // std::unique<void> which has a registered destructor
110 //FIXME reminants of merging the two classes, unifyu these
111 uint64_t vmSize() const { return _vmSize
; }
112 uint64_t fileSize() const { return _fileSize
; }
113 const uint8_t* cdHash() { return _cdHash
; }
114 std::string
cdHashString();
116 //FIXME: This should be private, but we can't do that until we move write out into the class after the next refactor
117 std::shared_ptr
<void> buffer() const;
119 void buildForDevelopment(const std::string
& cachePath
);
120 void buildForProduction(const std::string
& cachePath
);
121 bool writeCacheMapFile(const std::string
& mapPath
);
123 typedef std::function
<void(const void* machHeader
, const char* installName
, time_t lastModTime
, ino_t inode
,
124 const std::vector
<MachOProxy::Segment
>& segments
)> DylibHandler
;
125 // Calls lambda once per image in the cache
126 void forEachImage(DylibHandler handler
);
128 typedef std::function
<void(void* content
, uint64_t vmAddr
, uint64_t size
, uint32_t permissions
)> RegionHandler
;
129 // Calls lambda once per region in the cache
130 void forEachRegion(RegionHandler handler
);
132 void setLinkeditsMappingEndFileOffset(uint64_t newFileSize
);
133 void setAcceleratorInfoRange(uint64_t accelInfoAddr
, uint32_t accelInfoSize
);
134 void setUnmappedLocalsRange(uint64_t localSymbolsOffset
, uint32_t unmappedSize
);
135 void recomputeCacheUUID(void);
138 void loadDirtyDataOrderFile(const std::string
& dirtyDataOrderFile
);
139 void sortDylibs(const std::string
& dylibOrderFile
);
140 void assignSegmentAddresses();
141 void bypassStubs(const std::vector
<uint64_t>& branchPoolStartAddrs
);
142 void optimizeLinkedit(bool dontMapLocalSymbols
, bool addAcceleratorTables
, const std::vector
<uint64_t>& branchPoolOffsets
);
144 // Once all a dylib's segments are copied into a cache, this function will adjust the contents of
145 // the TEXT, DATA, and LINKEDIT segments in the cache to be correct for their new addresses.
146 void bindAllImagesInCache(const std::unordered_map
<std::string
, void*>& dylibPathToMachHeader
, std::vector
<void*>& pointersForASLR
);
148 // After adjustImageForNewSegmentLocations() is called to rebase all segments, this function can be called to
149 // bind all symbols to their new addresses
150 void adjustImageForNewSegmentLocations(const std::vector
<uint64_t>& segNewStartAddresses
,
151 const std::vector
<uint64_t>& segCacheFileOffsets
,
152 const std::vector
<uint64_t>& segCacheSizes
, std::vector
<void*>& pointersForASLR
);
154 uint64_t pathHash(const char* path
);
155 void writeCacheHeader(void);
156 void writeCacheSegments(void);
157 void rebaseAll(void);
158 void rebase(MachOProxy
* dylib
);
160 void optimizeObjC(bool forProduction
);
161 void writeSlideInfoV2(void);
163 void buildUnoptimizedCache();
164 void appendCodeSignature(const std::string
& suffix
);
165 template <typename P
> void buildForDevelopment(const std::string
& cachePath
);
166 template <typename P
> void buildForProduction(const std::string
& cachePath
);
167 template <typename P
> void forEachImage(DylibHandler handler
);
168 template <typename P
> void forEachRegion(RegionHandler handler
);
169 template <typename P
> void setLinkeditsMappingEndFileOffset(uint64_t newFileSize
);
170 template <typename P
> void setAcceleratorInfoRange(uint64_t accelInfoAddr
, uint32_t accelInfoSize
);
171 template <typename P
> void setUnmappedLocalsRange(uint64_t localSymbolsOffset
, uint32_t unmappedSize
);
172 template <typename P
> void recomputeCacheUUID(void);
173 template <typename P
> void bypassStubs(const std::vector
<uint64_t>& branchPoolStartAddrs
);
174 template <typename P
> void optimizeLinkedit(bool dontMapLocalSymbols
, bool addAcceleratorTables
, const std::vector
<uint64_t>& branchPoolOffsets
);
175 template <typename P
> void writeCacheHeader(void);
176 template <typename E
> void writeSlideInfo(void);
177 template <typename P
> void writeSlideInfoV2(uint64_t deltaMask
, uint64_t valueAdd
);
179 template <typename P
> void findImplicitAliases(std::shared_ptr
<MachOProxy
> dylib
);
180 template <typename P
> void addPageStarts(uint8_t* pageContent
, const bool bitmap
[], const dyldCacheSlideInfo2
<typename
P::E
>* info
,
181 std::vector
<uint16_t>& pageStarts
, std::vector
<uint16_t>& pageExtras
);
182 template <typename P
> bool makeRebaseChain(uint8_t* pageContent
, uint16_t lastLocationOffset
, uint16_t newOffset
, const dyldCacheSlideInfo2
<typename
P::E
>* info
);
183 void findDylibAndSegment(const void* contentPtr
, std::string
& dylibName
, std::string
& segName
);
186 std::vector
<MachOProxy
*> _dylibs
;
187 std::shared_ptr
<void> _buffer
;
188 std::unordered_map
<const MachOProxy
*, std::vector
<SegmentInfo
>> _segmentMap
;
190 std::string
archName();
193 const Manifest::Architecture
& _archManifest
;
194 uint32_t _aliasCount
;
197 Region _readOnlyRegion
;
198 uint64_t _slideInfoFileOffset
;
199 uint64_t _slideInfoBufferSize
;
202 std::unordered_map
<std::string
, uint32_t> _dataDirtySegsOrder
;
203 std::vector
<void*> _pointersForASLR
;
204 std::vector
<uint64_t> _branchPoolStarts
;
205 uint64_t _branchPoolsLinkEditStartAddr
;
209 std::string
normalize_absolute_file_path(const std::string
&path
);
210 std::string
baspath(const std::string
& path
);
211 std::string
dirpath(const std::string
& path
);
213 std::string
toolDir();
214 bool isProtectedBySIP(const std::string
& path
, int fd
=-1);
217 template <class Set1
, class Set2
>
218 inline bool is_disjoint(const Set1
& set1
, const Set2
& set2
)
220 if (set1
.empty() || set2
.empty())
223 typename
Set1::const_iterator it1
= set1
.begin(), it1End
= set1
.end();
224 typename
Set2::const_iterator it2
= set2
.begin(), it2End
= set2
.end();
226 if (*it1
> *set2
.rbegin() || *it2
> *set1
.rbegin())
229 while (it1
!= it1End
&& it2
!= it2End
) {
242 inline bool has_prefix(const std::string
& str
, const std::string
& prefix
)
244 return std::mismatch(prefix
.begin(), prefix
.end(), str
.begin()).first
== prefix
.end();
248 #define NEW_CACHE_FILE_FORMAT 0
250 #endif // __MEGA_DYLIB_UTILS_H__