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@
30 #include "MachOFile.h"
33 class SharedCacheBuilder
;
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
42 typedef const MachOLoaded
* (^DependentToMachOLoaded
)(const MachOLoaded
* image
, uint32_t depIndex
);
45 bool hasExportedSymbol(const char* symbolName
, DependentToMachOLoaded finder
, void** result
,
46 bool* resultPointsToInstructions
) const;
48 // for DYLD_PRINT_SEGMENTS
49 const char* segmentName(uint32_t segIndex
) const;
51 // used to see if main executable overlaps shared region
52 bool intersectsRange(uintptr_t start
, uintptr_t length
) const;
54 // for _dyld_get_image_slide()
55 intptr_t getSlide() const;
58 bool findClosestSymbol(uint64_t unSlidAddr
, const char** symbolName
, uint64_t* symbolUnslidAddr
) const;
60 // for _dyld_find_unwind_sections()
61 const void* findSectionContent(const char* segName
, const char* sectName
, uint64_t& size
) const;
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;
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
);
70 // used by cache builder during error handling in chain bind processing
71 const char* dependentDylibLoadPath(uint32_t depIndex
) const;
73 // used by closure builder to find the offset and size of the trie.
74 bool hasExportTrie(uint32_t& runtimeOffset
, uint32_t& size
) const;
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;
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;
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
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
;
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
);
106 dyld_chained_ptr_64_rebase rebase
;
107 dyld_chained_ptr_64_bind bind
;
109 uint64_t signExtendedAddend() const;
110 uint64_t unpackedTarget() const;
114 dyld_chained_ptr_32_rebase rebase
;
115 dyld_chained_ptr_32_bind bind
;
117 uint64_t signExtendedAddend() const;
120 struct Kernel64
: dyld_chained_ptr_64_kernel_cache_rebase
{
121 const char* keyName() const;
124 struct Firm32
: dyld_chained_ptr_32_firmware_rebase
{ };
126 typedef dyld_chained_ptr_32_cache_rebase Cache32
;
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
);
146 uintptr_t textUnslidVMAddr
;
147 uintptr_t linkeditUnslidVMAddr
;
148 uint32_t linkeditFileOffset
;
149 uint32_t linkeditFileSize
;
150 uint32_t linkeditSegIndex
;
151 uint32_t lastSegIndex
;
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
;
167 void getLinkEditPointers(Diagnostics
& diag
, LinkEditInfo
&) const;
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;
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;
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;
183 friend SharedCacheBuilder
;
186 enum class Kind
{ headerOffset
, absolute
, resolverOffset
};
190 const MachOLoaded
* foundInDylib
;
192 uint32_t resolverFuncOffset
;
193 const char* foundSymbolName
;
196 bool findExportedSymbol(Diagnostics
& diag
, const char* symbolName
, bool weakImport
, FoundSymbol
& foundInfo
, DependentToMachOLoaded finder
) const;
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;
204 uint32_t dependentDylibCount() const;
205 bool findClosestFunctionStart(uint64_t address
, uint64_t* functionStartAddress
) const;
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;
220 #endif /* MachOLoaded_h */