dyld-832.7.1.tar.gz
[apple/dyld.git] / dyld3 / MachOLoaded.h
1 /*
2 * Copyright (c) 2017 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
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
11 * file.
12 *
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.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24 #ifndef MachOLoaded_h
25 #define MachOLoaded_h
26
27 #include <stdint.h>
28
29 #include "Array.h"
30 #include "MachOFile.h"
31
32
33 class SharedCacheBuilder;
34
35 namespace dyld3 {
36
37
38 // A mach-o mapped into memory with zero-fill expansion
39 // Can be used in dyld at runtime or during closure building
40 struct VIS_HIDDEN MachOLoaded : public MachOFile
41 {
42 typedef const MachOLoaded* (^DependentToMachOLoaded)(const MachOLoaded* image, uint32_t depIndex);
43
44 // for dlsym()
45 bool hasExportedSymbol(const char* symbolName, DependentToMachOLoaded finder, void** result,
46 bool* resultPointsToInstructions) const;
47
48 // for DYLD_PRINT_SEGMENTS
49 const char* segmentName(uint32_t segIndex) const;
50
51 // used to see if main executable overlaps shared region
52 bool intersectsRange(uintptr_t start, uintptr_t length) const;
53
54 // for _dyld_get_image_slide()
55 intptr_t getSlide() const;
56
57 // for dladdr()
58 bool findClosestSymbol(uint64_t unSlidAddr, const char** symbolName, uint64_t* symbolUnslidAddr) const;
59
60 // for _dyld_find_unwind_sections()
61 const void* findSectionContent(const char* segName, const char* sectName, uint64_t& size) const;
62
63 // used at runtime to validate loaded image matches closure
64 void forEachCDHashOfCodeSignature(const void* codeSigStart, size_t codeSignLen,
65 void (^callback)(const uint8_t cdHash[20])) const;
66
67 // used by DyldSharedCache to find closure
68 static const uint8_t* trieWalk(Diagnostics& diag, const uint8_t* start, const uint8_t* end, const char* symbol);
69
70 // used by cache builder during error handling in chain bind processing
71 const char* dependentDylibLoadPath(uint32_t depIndex) const;
72
73 // used by closure builder to find the offset and size of the trie.
74 bool hasExportTrie(uint32_t& runtimeOffset, uint32_t& size) const;
75
76 // used by dyld/libdyld to apply fixups
77 #if BUILDING_DYLD || BUILDING_LIBDYLD
78 void fixupAllChainedFixups(Diagnostics& diag, const dyld_chained_starts_in_image* starts, uintptr_t slide,
79 Array<const void*> bindTargets, void (^fixupLogger)(void* loc, void* newValue)) const;
80 #endif
81
82 void forEachGlobalSymbol(Diagnostics& diag, void (^callback)(const char* symbolName, uint64_t n_value, uint8_t n_type, uint8_t n_sect, uint16_t n_desc, bool& stop)) const;
83
84
85 // For use with new rebase/bind scheme were each fixup location on disk contains info on what
86 // fix up it needs plus the offset to the next fixup.
87 union ChainedFixupPointerOnDisk
88 {
89 union Arm64e {
90 dyld_chained_ptr_arm64e_auth_rebase authRebase;
91 dyld_chained_ptr_arm64e_auth_bind authBind;
92 dyld_chained_ptr_arm64e_rebase rebase;
93 dyld_chained_ptr_arm64e_bind bind;
94 dyld_chained_ptr_arm64e_bind24 bind24;
95 dyld_chained_ptr_arm64e_auth_bind24 authBind24;
96
97 uint64_t signExtendedAddend() const;
98 uint64_t unpackTarget() const;
99 const char* keyName() const;
100 uint64_t signPointer(void* loc, uint64_t target) const;
101 static uint64_t signPointer(uint64_t unsignedPtr, void* loc, bool addrDiv, uint16_t diversity, uint8_t key);
102 static const char* keyName(uint8_t keyBits);
103 };
104
105 union Generic64 {
106 dyld_chained_ptr_64_rebase rebase;
107 dyld_chained_ptr_64_bind bind;
108
109 uint64_t signExtendedAddend() const;
110 uint64_t unpackedTarget() const;
111 };
112
113 union Generic32 {
114 dyld_chained_ptr_32_rebase rebase;
115 dyld_chained_ptr_32_bind bind;
116
117 uint64_t signExtendedAddend() const;
118 };
119
120 struct Kernel64 : dyld_chained_ptr_64_kernel_cache_rebase {
121 const char* keyName() const;
122 };
123
124 struct Firm32 : dyld_chained_ptr_32_firmware_rebase { };
125
126 typedef dyld_chained_ptr_32_cache_rebase Cache32;
127
128 uint64_t raw64;
129 Arm64e arm64e;
130 Generic64 generic64;
131 Kernel64 kernel64;
132
133 uint32_t raw32;
134 Generic32 generic32;
135 Cache32 cache32;
136 Firm32 firmware32;
137
138 bool isRebase(uint16_t pointerFormat, uint64_t preferedLoadAddress, uint64_t& targetRuntimeOffset) const;
139 bool isBind(uint16_t pointerFormat, uint32_t& bindOrdinal, int64_t& addend) const;
140 static unsigned strideSize(uint16_t pointerFormat);
141 };
142
143
144 struct LayoutInfo {
145 uintptr_t slide;
146 uintptr_t textUnslidVMAddr;
147 uintptr_t linkeditUnslidVMAddr;
148 uint32_t linkeditFileOffset;
149 uint32_t linkeditFileSize;
150 uint32_t linkeditSegIndex;
151 uint32_t lastSegIndex;
152 };
153
154 struct LinkEditInfo
155 {
156 const dyld_info_command* dyldInfo;
157 const linkedit_data_command* exportsTrie;
158 const linkedit_data_command* chainedFixups;
159 const symtab_command* symTab;
160 const dysymtab_command* dynSymTab;
161 const linkedit_data_command* splitSegInfo;
162 const linkedit_data_command* functionStarts;
163 const linkedit_data_command* dataInCode;
164 const linkedit_data_command* codeSig;
165 LayoutInfo layout;
166 };
167 void getLinkEditPointers(Diagnostics& diag, LinkEditInfo&) const;
168
169 void forEachFixupChainSegment(Diagnostics& diag, const dyld_chained_starts_in_image* starts,
170 void (^handler)(const dyld_chained_starts_in_segment* segInfo, uint32_t segIndex, bool& stop)) const;
171
172 void forEachFixupInSegmentChains(Diagnostics& diag, const dyld_chained_starts_in_segment* segInfo, bool notifyNonPointers,
173 void (^handler)(ChainedFixupPointerOnDisk* fixupLocation, const dyld_chained_starts_in_segment* segInfo, bool& stop)) const;
174
175 // for dyld loaded images
176 void forEachFixupInAllChains(Diagnostics& diag, const dyld_chained_starts_in_image* starts, bool notifyNonPointers,
177 void (^callback)(ChainedFixupPointerOnDisk* fixupLocation, const dyld_chained_starts_in_segment* segInfo, bool& stop)) const;
178 // for preload images
179 void forEachFixupInAllChains(Diagnostics& diag, uint16_t pointer_format, uint32_t starts_count, const uint32_t chain_starts[],
180 void (^handler)(ChainedFixupPointerOnDisk* fixupLocation, bool& stop)) const;
181
182 protected:
183 friend SharedCacheBuilder;
184
185 struct FoundSymbol {
186 enum class Kind { headerOffset, absolute, resolverOffset };
187 Kind kind;
188 bool isThreadLocal;
189 bool isWeakDef;
190 const MachOLoaded* foundInDylib;
191 uint64_t value;
192 uint32_t resolverFuncOffset;
193 const char* foundSymbolName;
194 };
195
196 bool findExportedSymbol(Diagnostics& diag, const char* symbolName, bool weakImport, FoundSymbol& foundInfo, DependentToMachOLoaded finder) const;
197
198 void getLinkEditLoadCommands(Diagnostics& diag, LinkEditInfo& result) const;
199 void getLayoutInfo(LayoutInfo&) const;
200 const uint8_t* getLinkEditContent(const LayoutInfo& info, uint32_t fileOffset) const;
201 const uint8_t* getExportsTrie(const LinkEditInfo& info, uint64_t& trieSize) const;
202 void forEachLocalSymbol(Diagnostics& diag, void (^callback)(const char* symbolName, uint64_t n_value, uint8_t n_type, uint8_t n_sect, uint16_t n_desc, bool& stop)) const;
203
204 uint32_t dependentDylibCount() const;
205 bool findClosestFunctionStart(uint64_t address, uint64_t* functionStartAddress) const;
206
207 // This calls the callback for all code directories required for a given platform/binary combination.
208 // On watchOS main executables this is all cd hashes.
209 // On watchOS dylibs this is only the single cd hash we need (by rank defined by dyld, not the kernel).
210 // On all other platforms this always returns a single best cd hash (ranked to match the kernel).
211 // Note the callback parameter is really a CS_CodeDirectory.
212 void forEachCodeDirectoryBlob(const void* codeSigStart, size_t codeSignLen, void (^callback)(const void* cd)) const;
213 bool walkChain(Diagnostics& diag, ChainedFixupPointerOnDisk* start, uint16_t pointer_format, bool notifyNonPointers, uint32_t max_valid_pointer,
214 void (^handler)(ChainedFixupPointerOnDisk* fixupLocation, bool& stop)) const;
215
216 };
217
218 } // namespace dyld3
219
220 #endif /* MachOLoaded_h */