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@
32 #include <uuid/uuid.h>
33 #include <mach/mach.h>
34 #include <mach-o/loader.h>
36 #include "Diagnostics.h"
38 #include "MachOLoaded.h"
39 #include "SupportedArchs.h"
46 // bump this number each time binary format changes
47 enum { kFormatVersion
= 10 };
50 typedef uint32_t ImageNum
;
52 const ImageNum kFirstDyldCacheImageNum
= 0x00000001;
53 const ImageNum kLastDyldCacheImageNum
= 0x00000FFF;
54 const ImageNum kFirstOtherOSImageNum
= 0x00001001;
55 const ImageNum kLastOtherOSImageNum
= 0x00001FFF;
56 const ImageNum kFirstLaunchClosureImageNum
= 0x00002000;
57 const ImageNum kMissingWeakLinkedImage
= 0x0FFFFFFF;
61 // Generic typed range of bytes (similar to load commands)
62 // Must be 4-byte aligned
64 struct VIS_HIDDEN TypedBytes
70 // containers which have an overall length and TypedBytes inside their content
71 launchClosure
= 1, // contains TypedBytes of closure attributes including imageArray
72 imageArray
= 2, // sizeof(ImageArray) + sizeof(uint32_t)*count + size of all images
73 image
= 3, // contains TypedBytes of image attributes
74 dlopenClosure
= 4, // contains TypedBytes of closure attributes including imageArray
76 // attributes for Images
77 imageFlags
= 7, // sizeof(Image::Flags)
78 pathWithHash
= 8, // len = uint32_t + length path + 1, use multiple entries for aliases
79 fileInodeAndTime
= 9, // sizeof(FileInfo)
82 mappingInfo
= 12, // sizeof(MappingInfo)
83 diskSegment
= 13, // sizeof(DiskSegment) * count
84 cacheSegment
= 14, // sizeof(DyldCacheSegment) * count
85 dependents
= 15, // sizeof(LinkedImage) * count
86 initOffsets
= 16, // sizeof(uint32_t) * count
87 dofOffsets
= 17, // sizeof(uint32_t) * count
88 codeSignLoc
= 18, // sizeof(CodeSignatureLocation)
89 fairPlayLoc
= 19, // sizeof(FairPlayRange)
90 rebaseFixups
= 20, // sizeof(RebasePattern) * count
91 bindFixups
= 21, // sizeof(BindPattern) * count
92 cachePatchInfo
= 22, // sizeof(PatchableExport) + count*sizeof(PatchLocation) + strlen(name) // only in dyld cache Images
93 textFixups
= 23, // sizeof(TextFixupPattern) * count
94 imageOverride
= 24, // sizeof(ImageNum)
95 initBefores
= 25, // sizeof(ImageNum) * count
96 chainedFixupsStarts
= 26, // sizeof(uint64_t) * count
97 chainedFixupsTargets
= 27, // sizeof(ResolvedSymbolTarget) * count
99 // attributes for Closures (launch or dlopen)
100 closureFlags
= 32, // sizeof(Closure::Flags)
101 dyldCacheUUID
= 33, // 16
103 envVar
= 35, // "DYLD_BLAH=stuff"
104 topImage
= 36, // sizeof(ImageNum)
105 libDyldEntry
= 37, // sizeof(ResolvedSymbolTarget)
106 libSystemNum
= 38, // sizeof(ImageNum)
107 bootUUID
= 39, // c-string 40
108 mainEntry
= 40, // sizeof(ResolvedSymbolTarget)
109 startEntry
= 41, // sizeof(ResolvedSymbolTarget) // used by programs built with crt1.o
110 cacheOverrides
= 42, // sizeof(PatchEntry) * count // used if process uses interposing or roots (cached dylib overrides)
111 interposeTuples
= 43, // sizeof(InterposingTuple) * count
114 const void* payload() const;
120 // A TypedBytes which is a bag of other TypedBytes
122 struct VIS_HIDDEN ContainerTypedBytes
: TypedBytes
124 void forEachAttribute(void (^callback
)(const TypedBytes
* typedBytes
, bool& stop
)) const;
125 void forEachAttributePayload(Type requestedType
, void (^handler
)(const void* payload
, uint32_t size
, bool& stop
)) const;
126 const void* findAttributePayload(Type requestedType
, uint32_t* payloadSize
=nullptr) const;
128 const TypedBytes
* first() const;
129 const TypedBytes
* next(const TypedBytes
*) const;
134 // Information about a mach-o file
136 struct VIS_HIDDEN Image
: ContainerTypedBytes
138 enum class LinkKind
{ regular
=0, weak
=1, upward
=2, reExport
=3 };
141 ImageNum
imageNum() const;
142 bool representsImageNum(ImageNum num
) const; // imageNum() or isOverrideOfDyldCacheImage()
143 uint32_t maxLoadCount() const;
144 const char* path() const;
145 const char* leafName() const;
146 bool getUuid(uuid_t
) const;
147 bool isInvalid() const;
148 bool inDyldCache() const;
149 bool hasObjC() const;
150 bool hasInitializers() const;
151 bool isBundle() const;
152 bool isDylib() const;
153 bool isExecutable() const;
154 bool hasWeakDefs() const;
155 bool mayHavePlusLoads() const;
157 bool neverUnload() const;
158 bool cwdMustBeThisDir() const;
159 bool isPlatformBinary() const;
160 bool overridableDylib() const;
161 bool hasFileModTimeAndInode(uint64_t& inode
, uint64_t& mTime
) const;
162 bool hasCdHash(uint8_t cdHash
[20]) const;
163 void forEachAlias(void (^handler
)(const char* aliasPath
, bool& stop
)) const;
164 void forEachDependentImage(void (^handler
)(uint32_t dependentIndex
, LinkKind kind
, ImageNum imageNum
, bool& stop
)) const;
165 ImageNum
dependentImageNum(uint32_t depIndex
) const;
166 bool containsAddress(const void* addr
, const void* imageLoadAddress
, uint8_t* permissions
=nullptr) const;
167 void forEachInitializer(const void* imageLoadAddress
, void (^handler
)(const void* initializer
)) const;
168 void forEachImageToInitBefore(void (^handler
)(ImageNum imageToInit
, bool& stop
)) const;
169 void forEachDOF(const void* imageLoadAddress
, void (^handler
)(const void* initializer
)) const;
170 bool hasPathWithHash(const char* path
, uint32_t hash
) const;
171 bool isOverrideOfDyldCacheImage(ImageNum
& cacheImageNum
) const;
172 uint64_t textSize() const;
174 union ResolvedSymbolTarget
176 enum Kinds
{ kindRebase
, kindSharedCache
, kindImage
, kindAbsolute
};
179 uint64_t kind
: 2, // kindRebase
180 unused
: 62; // all zeros
183 uint64_t kind
: 2, // kindSharedCache
187 uint64_t kind
: 2, // kindImage
188 imageNum
: 22, // ImageNum
192 uint64_t kind
: 2, // kindAbsolute
193 value
: 62; // sign extended
196 SharedCache sharedCache
;
201 bool operator==(const ResolvedSymbolTarget
& rhs
) const {
202 return (raw
== rhs
.raw
);
204 bool operator!=(const ResolvedSymbolTarget
& rhs
) const {
205 return (raw
!= rhs
.raw
);
209 typedef MachOLoaded
::ChainedFixupPointerOnDisk ChainedFixupPointerOnDisk
;
211 // the following are only valid if inDyldCache() returns true
212 uint32_t cacheOffset() const;
213 uint32_t patchStartIndex() const;
214 uint32_t patchCount() const;
215 void forEachCacheSegment(void (^handler
)(uint32_t segIndex
, uint64_t vmOffset
, uint64_t vmSize
, uint8_t permissions
, bool& stop
)) const;
218 // the following are only valid if inDyldCache() returns false
219 uint64_t vmSizeToMap() const;
220 uint64_t sliceOffsetInFile() const;
221 bool hasCodeSignature(uint32_t& fileOffset
, uint32_t& size
) const;
222 bool isFairPlayEncrypted(uint32_t& textOffset
, uint32_t& size
) const;
223 void forEachDiskSegment(void (^handler
)(uint32_t segIndex
, uint32_t fileOffset
, uint32_t fileSize
, int64_t vmOffset
, uint64_t vmSize
, uint8_t permissions
, bool& stop
)) const;
224 void forEachFixup(void (^rebase
)(uint64_t imageOffsetToRebase
, bool& stop
),
225 void (^bind
)(uint64_t imageOffsetToBind
, ResolvedSymbolTarget bindTarget
, bool& stop
),
226 void (^chainedFixupStart
)(uint64_t imageOffsetStart
, const Array
<ResolvedSymbolTarget
>& targets
, bool& stop
)) const;
227 void forEachTextReloc(void (^rebase
)(uint32_t imageOffsetToRebase
, bool& stop
),
228 void (^bind
)(uint32_t imageOffsetToBind
, ResolvedSymbolTarget bindTarget
, bool& stop
)) const;
229 static void forEachChainedFixup(void* imageLoadAddress
, uint64_t imageOffsetChainStart
,
230 void (^chainedFixupStart
)(uint64_t* fixupLoc
, ChainedFixupPointerOnDisk fixupInfo
, bool& stop
));
232 static_assert(sizeof(ResolvedSymbolTarget
) == 8, "Overflow in size of SymbolTargetLocation");
234 static uint32_t hashFunction(const char*);
237 // only in Image for cached dylibs
238 struct PatchableExport
242 uint64_t cacheOffset
: 32,
243 addend
: 12, // +/- 2048
245 usesAddressDiversity
: 1,
249 PatchLocation(size_t cacheOffset
, uint64_t addend
);
250 PatchLocation(size_t cacheOffset
, uint64_t addend
, dyld3
::MachOLoaded
::ChainedFixupPointerOnDisk authInfo
);
252 uint64_t getAddend() const {
253 uint64_t unsingedAddend
= addend
;
254 int64_t signedAddend
= (int64_t)unsingedAddend
;
255 signedAddend
= (signedAddend
<< 52) >> 52;
256 return (uint64_t)signedAddend
;
259 const char* keyName() const;
260 bool operator==(const PatchLocation
& other
) const {
261 return this->cacheOffset
== other
.cacheOffset
;
265 uint32_t cacheOffsetOfImpl
;
266 uint32_t patchLocationsCount
;
267 PatchLocation patchLocations
[];
270 uint32_t patchableExportCount() const;
271 void forEachPatchableExport(void (^handler
)(uint32_t cacheOffsetOfImpl
, const char* exportName
)) const;
272 void forEachPatchableUseOfExport(uint32_t cacheOffsetOfImpl
, void (^handler
)(PatchableExport
::PatchLocation patchLocation
)) const;
275 friend struct Closure
;
276 friend class ImageWriter
;
277 friend class ClosureBuilder
;
278 friend class LaunchClosureWriter
;
280 uint32_t pageSize() const;
284 uint64_t imageNum
: 16,
286 isInvalid
: 1, // an error occurred creating the info for this image
290 mayHavePlusLoads
: 1,
291 isEncrypted
: 1, // image is DSMOS or FairPlay encrypted
294 cwdSameAsThis
: 1, // dylibs use file system relative paths, cwd must be main's dir
295 isPlatformBinary
: 1, // part of OS - can be loaded into LV process
299 overridableDylib
: 1, // only applicable to cached dylibs
304 const Flags
& getFlags() const;
312 // In disk based images, all segments are multiples of page size
313 // This struct just tracks the size (disk and vm) of each segment.
314 // This is compact for most every image which have contiguous segments.
315 // If the image does not have contiguous segments (rare), an extra
316 // DiskSegment is inserted with the paddingNotSeg bit set.
319 uint64_t filePageCount
: 30,
326 // In cache DATA_DIRTY is not page aligned or sized
327 // This struct allows segments with any alignment and up to 256MB in size
328 struct DyldCacheSegment
330 uint64_t cacheOffset
: 32,
335 struct CodeSignatureLocation
349 uint32_t textPageCount
: 28,
355 uint32_t totalVmPages
;
356 uint32_t sliceOffsetIn4K
;
361 LinkedImage() : imgNum(0), linkKind(0) {
363 LinkedImage(LinkKind k
, ImageNum num
) : imgNum(num
), linkKind((uint32_t)k
) {
364 assert((num
& 0xC0000000) == 0);
367 LinkKind
kind() const { return (LinkKind
)linkKind
; }
368 ImageNum
imageNum() const { return imgNum
; }
369 void clearKind() { linkKind
= 0; }
371 bool operator==(const LinkedImage
& rhs
) const {
372 return (linkKind
== rhs
.linkKind
) && (imgNum
== rhs
.imgNum
);
374 bool operator!=(const LinkedImage
& rhs
) const {
375 return (linkKind
!= rhs
.linkKind
) || (imgNum
!= rhs
.imgNum
);
378 uint32_t imgNum
: 30,
379 linkKind
: 2; // LinkKind
382 const Array
<LinkedImage
> dependentsArray() const;
386 uint32_t repeatCount
: 20,
387 contigCount
: 8, // how many contiguous pointers neeed rebasing
388 skipCount
: 4; // how many pointers to skip between contig groups
389 // If contigCount == 0, then there are no rebases for this entry,
390 // instead it advances the rebase location by repeatCount*skipCount.
391 // If all fields are zero, then the rebase position is reset to the start.
392 // This is to support old binaries with some non-monotonically-increasing rebases.
394 const Array
<RebasePattern
> rebaseFixups() const;
398 Image
::ResolvedSymbolTarget target
;
399 uint64_t startVmOffset
: 40, // max 1TB offset
403 const Array
<BindPattern
> bindFixups() const;
405 struct TextFixupPattern
407 Image
::ResolvedSymbolTarget target
;
408 uint32_t startVmOffset
;
409 uint16_t repeatCount
;
412 const Array
<TextFixupPattern
> textFixups() const;
414 // for use with chained fixups
415 const Array
<uint64_t> chainedStarts() const;
416 const Array
<Image
::ResolvedSymbolTarget
> chainedTargets() const;
421 Dyld cache patching notes:
423 The dyld cache needs to be patched to support interposing and dylib "roots".
425 For cached dylibs overrides:
427 1) LoadedImages will contain the new dylib, so all symbol look ups
428 will naturally find new impl. Only dyld cache needs special help.
429 2) LoadedImages entry will have flag for images that override cache.
430 3) When setting Closure attributes, if flag is set, builder will
431 iterate PatchableExport entries in Image* from cache and create
432 a PatchEntry for each.
434 1) [lib]dyld will iterate PatchEntry in closure and patch cache
438 1) After Images built, if __interpose section(s) exist, builder will
439 build InterposingTuple entries for closure
440 2) For being-built closure and launch closure, apply any InterposingTuple
441 to modify Image fixups before Image finalized.
442 3) Builder will find PatchableExport entry that matchs stock Impl
443 and add PatchEntry to closure for it.
445 1) When closure is loaded (launch or dlopen) PatchEntries are
446 applied (exactly once) to whole cache.
447 2) For each DlopenClosure loaded, any InterposeTuples in *launch* closure
448 are applied to all new images in new DlopenClosure.
450 For weak-def coalesing:
452 1) weak_bind entries are turned into -3 ordinal lookup which search through images
453 in load order for first def (like flat). This fixups up all images not in cache.
454 2) When processing -3 ordinals, it continues past first found and if any images
455 past it are in dyld cache and export that same symbol, a PatchEntry is added to
456 closure to fix up all cached uses of that symbol.
457 3) If a weak_bind has strong bit set (no fixup, just def), all images from the dyld
458 cache are checked to see if the export that symbol, if so, a PatchEntry is added
461 1) When closure is loaded (launch or dlopen) PatchEntries are
462 applied (exactly once) to whole cache.
468 // An array (accessible by index) list of Images
470 struct VIS_HIDDEN ImageArray
: public TypedBytes
473 size_t startImageNum() const;
474 uint32_t imageCount() const;
475 void forEachImage(void (^callback
)(const Image
* image
, bool& stop
)) const;
476 bool hasPath(const char* path
, ImageNum
& num
) const;
477 const Image
* imageForNum(ImageNum
) const;
479 static const Image
* findImage(const Array
<const ImageArray
*> imagesArrays
, ImageNum imageNum
);
482 friend class ImageArrayWriter
;
484 uint32_t firstImageNum
;
491 struct InterposingTuple
493 Image
::ResolvedSymbolTarget stockImplementation
;
494 Image
::ResolvedSymbolTarget newImplementation
;
499 // Describes how dyld should load a set of mach-o files
501 struct VIS_HIDDEN Closure
: public ContainerTypedBytes
504 const ImageArray
* images() const;
505 ImageNum
topImage() const;
506 void deallocate() const;
508 friend class ClosureWriter
;
512 ImageNum overriddenDylibInCache
;
513 uint32_t exportCacheOffset
;
514 Image
::ResolvedSymbolTarget replacement
;
516 void forEachPatchEntry(void (^handler
)(const PatchEntry
& entry
)) const;
521 // Describes how dyld should launch a main executable
523 struct VIS_HIDDEN LaunchClosure
: public Closure
525 bool builtAgainstDyldCache(uuid_t cacheUUID
) const;
526 const char* bootUUID() const;
527 void forEachMustBeMissingFile(void (^handler
)(const char* path
, bool& stop
)) const;
528 void forEachEnvVar(void (^handler
)(const char* keyEqualValue
, bool& stop
)) const;
529 ImageNum
libSystemImageNum() const;
530 void libDyldEntry(Image
::ResolvedSymbolTarget
& loc
) const;
531 bool mainEntry(Image
::ResolvedSymbolTarget
& mainLoc
) const;
532 bool startEntry(Image
::ResolvedSymbolTarget
& startLoc
) const;
533 uint32_t initialLoadCount() const;
534 void forEachInterposingTuple(void (^handler
)(const InterposingTuple
& tuple
, bool& stop
)) const;
535 bool usedAtPaths() const;
536 bool usedFallbackPaths() const;
540 friend class LaunchClosureWriter
;
544 uint32_t usedAtPaths
: 1,
545 usedFallbackPaths
: 1,
549 const Flags
& getFlags() const;
555 // Describes how dyld should dlopen() a mach-o file
557 struct VIS_HIDDEN DlopenClosure
: public Closure
564 } // namespace closure