]>
git.saurik.com Git - apple/dyld.git/blob - dyld3/DyldCacheParser.cpp
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@
28 #include <uuid/uuid.h>
33 #include <sys/param.h>
34 #include <sys/sysctl.h>
35 #include <sys/resource.h>
36 #include <sys/types.h>
41 #include "DyldCacheParser.h"
47 DyldCacheParser::DyldCacheParser(const DyldSharedCache
* cacheHeader
, bool rawFile
)
49 _data
= (long)cacheHeader
;
54 const dyld_cache_header
* DyldCacheParser::header() const
56 return (dyld_cache_header
*)(_data
& -2);
59 const DyldSharedCache
* DyldCacheParser::cacheHeader() const
61 return (DyldSharedCache
*)header();
64 bool DyldCacheParser::cacheIsMappedRaw() const
70 uint64_t DyldCacheParser::dataRegionRuntimeVmOffset() const
72 const dyld_cache_header
* cacheHeader
= header();
73 const dyld_cache_mapping_info
* mappings
= (dyld_cache_mapping_info
*)((char*)cacheHeader
+ cacheHeader
->mappingOffset
);
74 return (mappings
[1].address
- mappings
[0].address
);
77 const dyld3::launch_cache::binary_format::ImageGroup
* DyldCacheParser::cachedDylibsGroup() const
79 const dyld_cache_header
* cacheHeader
= header();
80 const dyld_cache_mapping_info
* mappings
= (dyld_cache_mapping_info
*)((char*)cacheHeader
+ cacheHeader
->mappingOffset
);
82 if ( cacheIsMappedRaw() ) {
83 // Whole file is mapped read-only. Use mapping file-offsets to find ImageGroup
84 uint64_t offsetInLinkEditRegion
= (cacheHeader
->dylibsImageGroupAddr
- mappings
[2].address
);
85 return (dyld3::launch_cache::binary_format::ImageGroup
*)((uint8_t*)cacheHeader
+ mappings
[2].fileOffset
+ offsetInLinkEditRegion
);
88 // Cache file is mapped in three non-contiguous ranges. Use mapping addresses to find ImageGroup
89 return (dyld3::launch_cache::binary_format::ImageGroup
*)((uint8_t*)cacheHeader
+ (cacheHeader
->dylibsImageGroupAddr
- mappings
[0].address
));
94 const dyld3::launch_cache::binary_format::ImageGroup
* DyldCacheParser::otherDylibsGroup() const
96 const dyld_cache_header
* cacheHeader
= header();
97 const dyld_cache_mapping_info
* mappings
= (dyld_cache_mapping_info
*)((char*)cacheHeader
+ cacheHeader
->mappingOffset
);
99 if ( cacheIsMappedRaw() ) {
100 // Whole file is mapped read-only. Use mapping file-offsets to find ImageGroup
101 uint64_t offsetInLinkEditRegion
= (cacheHeader
->otherImageGroupAddr
- mappings
[2].address
);
102 return (dyld3::launch_cache::binary_format::ImageGroup
*)((uint8_t*)cacheHeader
+ mappings
[2].fileOffset
+ offsetInLinkEditRegion
);
105 // Cache file is mapped in three non-contiguous ranges. Use mapping addresses to find ImageGroup
106 return (dyld3::launch_cache::binary_format::ImageGroup
*)((uint8_t*)cacheHeader
+ (cacheHeader
->otherImageGroupAddr
- mappings
[0].address
));
110 const dyld3::launch_cache::binary_format::Closure
* DyldCacheParser::findClosure(const char* path
) const
112 const dyld_cache_header
* cacheHeader
= header();
113 const dyld_cache_mapping_info
* mappings
= (dyld_cache_mapping_info
*)((char*)cacheHeader
+ cacheHeader
->mappingOffset
);
115 const uint8_t* executableTrieStart
= nullptr;
116 const uint8_t* executableTrieEnd
= nullptr;
117 const uint8_t* closuresStart
= nullptr;
119 if ( cacheIsMappedRaw() ) {
120 // Whole file is mapped read-only. Use mapping file-offsets to find trie and closures
121 executableTrieStart
= (uint8_t*)cacheHeader
+ cacheHeader
->progClosuresTrieAddr
- mappings
[2].address
+ mappings
[2].fileOffset
;
122 executableTrieEnd
= executableTrieStart
+ cacheHeader
->progClosuresTrieSize
;
123 closuresStart
= (uint8_t*)cacheHeader
+ cacheHeader
->progClosuresAddr
- mappings
[2].address
+ mappings
[2].fileOffset
;
126 // Cache file is mapped in three non-contiguous ranges. Use mapping addresses to find trie and closures
127 uintptr_t slide
= (uintptr_t)cacheHeader
- (uintptr_t)(mappings
[0].address
);
128 executableTrieStart
= (uint8_t*)(cacheHeader
->progClosuresTrieAddr
+ slide
);
129 executableTrieEnd
= executableTrieStart
+ cacheHeader
->progClosuresTrieSize
;
130 closuresStart
= (uint8_t*)(cacheHeader
->progClosuresAddr
+ slide
);
133 const uint8_t* imageNode
= dyld3::MachOParser::trieWalk(diag
, executableTrieStart
, executableTrieEnd
, path
);
134 if ( imageNode
!= NULL
) {
135 uint32_t closureOffset
= (uint32_t)dyld3::MachOParser::read_uleb128(diag
, imageNode
, executableTrieEnd
);
136 return (const dyld3::launch_cache::BinaryClosureData
*)((uint8_t*)closuresStart
+ closureOffset
);
143 void DyldCacheParser::forEachClosure(void (^handler
)(const char* runtimePath
, const dyld3::launch_cache::binary_format::Closure
* cls
)) const
145 const dyld_cache_header
* cacheHeader
= header();
146 const dyld_cache_mapping_info
* mappings
= (dyld_cache_mapping_info
*)((char*)cacheHeader
+ cacheHeader
->mappingOffset
);
148 const uint8_t* executableTrieStart
= nullptr;
149 const uint8_t* executableTrieEnd
= nullptr;
150 const uint8_t* closuresStart
= nullptr;
152 if ( cacheIsMappedRaw() ) {
153 // Whole file is mapped read-only. Use mapping file-offsets to find trie and closures
154 executableTrieStart
= (uint8_t*)cacheHeader
+ cacheHeader
->progClosuresTrieAddr
- mappings
[2].address
+ mappings
[2].fileOffset
;
155 executableTrieEnd
= executableTrieStart
+ cacheHeader
->progClosuresTrieSize
;
156 closuresStart
= (uint8_t*)cacheHeader
+ cacheHeader
->progClosuresAddr
- mappings
[2].address
+ mappings
[2].fileOffset
;
159 // Cache file is mapped in three non-contiguous ranges. Use mapping addresses to find trie and closures
160 uintptr_t slide
= (uintptr_t)cacheHeader
- (uintptr_t)(mappings
[0].address
);
161 executableTrieStart
= (uint8_t*)(cacheHeader
->progClosuresTrieAddr
+ slide
);
162 executableTrieEnd
= executableTrieStart
+ cacheHeader
->progClosuresTrieSize
;
163 closuresStart
= (uint8_t*)(cacheHeader
->progClosuresAddr
+ slide
);
166 std::vector
<DylibIndexTrie::Entry
> closureEntries
;
167 if ( Trie
<DylibIndex
>::parseTrie(executableTrieStart
, executableTrieEnd
, closureEntries
) ) {
168 for (DylibIndexTrie::Entry
& entry
: closureEntries
) {
169 uint32_t offset
= entry
.info
.index
;
170 if ( offset
< cacheHeader
->progClosuresSize
)
171 handler(entry
.name
.c_str(), (const dyld3::launch_cache::binary_format::Closure
*)(closuresStart
+offset
));