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@
25 #ifndef __ALL_IMAGES_H__
26 #define __ALL_IMAGES_H__
28 #include <mach-o/loader.h>
30 #include <os/lock_private.h>
31 #include <mach-o/dyld_priv.h>
35 #include "MachOLoaded.h"
36 #include "DyldSharedCache.h"
40 // only in macOS and deprecated
41 struct VIS_HIDDEN OFIInfo
43 const char* path
; // = nullptr;
44 const void* memSource
; // = nullptr;
45 size_t memLength
; // = 0;
46 const dyld3
::MachOLoaded
* loadAddress
; // = nullptr;
47 uint64_t imageNum
; // = 0;
53 class VIS_HIDDEN AllImages
56 typedef void (*NotifyFunc
)(const mach_header
* mh
, intptr_t slide
);
57 typedef void (*LoadNotifyFunc
)(const mach_header
* mh
, const char* path
, bool unloadable
);
58 typedef void (*BulkLoadNotifier
)(unsigned count
, const mach_header
* mhs
[], const char* paths
[]);
59 typedef void (*MainFunc
)(void);
61 void init(const closure
::LaunchClosure
* closure
, const DyldSharedCache
* dyldCacheLoadAddress
, const char* dyldCachePath
,
62 const Array
<LoadedImage
>& initialImages
);
63 void setRestrictions(bool allowAtPaths
, bool allowEnvPaths
);
64 void setHasCacheOverrides(bool someCacheImageOverriden
);
65 bool hasCacheOverrides() const;
66 void setMainPath(const char* path
);
67 void setLaunchMode(uint32_t flags
);
68 void applyInitialImages();
70 void addImages(const Array
<LoadedImage
>& newImages
);
71 void removeImages(const Array
<LoadedImage
>& unloadImages
);
72 void runImageNotifiers(const Array
<LoadedImage
>& newImages
);
73 void runImageCallbacks(const Array
<LoadedImage
>& newImages
);
74 void applyInterposingToDyldCache(const closure
::Closure
* closure
);
75 void runStartupInitialzers();
76 void runInitialzersBottomUp(const closure
::Image
* topImage
);
77 void runLibSystemInitializer(LoadedImage
& libSystem
);
79 uint32_t count() const;
81 void forEachImage(void (^handler
)(const LoadedImage
& loadedImage
, bool& stop
)) const;
82 const MachOLoaded
* findDependent(const MachOLoaded
* mh
, uint32_t depIndex
);
83 void visitDependentsTopDown(const LoadedImage
& start
, void (^handler
)(const LoadedImage
& aLoadedImage
, bool& stop
)) const;
84 void infoForImageMappedAt(const void* addr
, void (^handler
)(const LoadedImage
& foundImage
, uint8_t permissions
)) const;
85 bool infoForImageMappedAt(const void* addr
, const MachOLoaded
** ml
, uint64_t* textSize
, const char** path
) const;
86 void infoForNonCachedImageMappedAt(const void* addr
, void (^handler
)(const LoadedImage
& foundImage
, uint8_t permissions
)) const;
87 void infoForImageWithLoadAddress(const MachOLoaded
*, void (^handler
)(const LoadedImage
& foundImage
)) const;
88 const char* pathForImageMappedAt(const void* addr
) const;
89 const char* imagePathByIndex(uint32_t index
) const;
90 const mach_header
* imageLoadAddressByIndex(uint32_t index
) const;
91 bool immutableMemory(const void* addr
, size_t length
) const;
92 void* interposeValue(void* value
) const;
94 bool hasInsertedOrInterposingLibraries() const;
95 bool isRestricted() const;
96 const MachOLoaded
* mainExecutable() const;
97 const closure
::Image
* mainExecutableImage() const;
98 const void* cacheLoadAddress() const { return _dyldCacheAddress
; }
99 const char* dyldCachePath() const { return _dyldCachePath
; }
100 bool dyldCacheHasPath(const char* path
) const;
101 const char* imagePath(const closure
::Image
*) const;
102 dyld_platform_t
platform() const;
103 const GradedArchs
& archs() const;
104 uint32_t launchMode() const { return _launchMode
; }
106 const Array
<const closure
::ImageArray
*>& imagesArrays();
108 void incRefCount(const mach_header
* loadAddress
);
109 void decRefCount(const mach_header
* loadAddress
);
111 void addLoadNotifier(NotifyFunc
);
112 void addUnloadNotifier(NotifyFunc
);
113 void setObjCNotifiers(_dyld_objc_notify_mapped
, _dyld_objc_notify_init
, _dyld_objc_notify_unmapped
);
114 void notifyObjCUnmap(const char* path
, const struct mach_header
* mh
);
115 void addLoadNotifier(LoadNotifyFunc
);
116 void addBulkLoadNotifier(BulkLoadNotifier
);
119 void setOldAllImageInfo(dyld_all_image_infos
* old
) { _oldAllImageInfos
= old
; }
120 dyld_all_image_infos
* oldAllImageInfo() const { return _oldAllImageInfos
;}
121 void notifyMonitorMain();
122 void notifyMonitorLoads(const Array
<LoadedImage
>& newImages
);
123 void notifyMonitorUnloads(const Array
<LoadedImage
>& unloadingImages
);
126 NSObjectFileImage
addNSObjectFileImage(const OFIInfo
&);
127 void removeNSObjectFileImage(NSObjectFileImage
);
128 bool forNSObjectFileImage(NSObjectFileImage imageHandle
,
129 void (^handler
)(OFIInfo
& image
));
132 const char* getObjCSelector(const char* selName
) const;
133 void forEachObjCClass(const char* className
,
134 void (^callback
)(void* classPtr
, bool isLoaded
, bool* stop
)) const;
135 void forEachObjCProtocol(const char* protocolName
,
136 void (^callback
)(void* protocolPtr
, bool isLoaded
, bool* stop
)) const;
138 MainFunc
getDriverkitMain();
139 void setDriverkitMain(MainFunc mainFunc
);
141 const MachOLoaded
* dlopen(Diagnostics
& diag
, const char* path
, bool rtldNoLoad
, bool rtldLocal
, bool rtldNoDelete
,
142 bool forceBindLazies
, bool fromOFI
, const void* callerAddress
,
143 bool canUsePrebuiltSharedCacheClosure
= true);
149 const char*** NXArgvPtr
;
150 const char*** environPtr
;
151 const char** __prognamePtr
;
153 void setProgramVars(ProgramVars
* vars
, bool keysOff
, bool platformBinariesOnly
);
155 // Note these are to be used exclusively by forking
156 void takeLockBeforeFork();
157 void releaseLockInForkParent();
158 void resetLockInForkChild();
164 const mach_header
* loadAddress
;
169 // The ImmutableRanges structure is used to make dyld_is_memory_immutable()
170 // fast and lock free. The table contains just ranges that are immutable,
171 // which means they are non-writable and will never be unloaded.
172 // This means the table is only every appended to. No entries are ever removed
173 // or changed. This makes it easier to be lock-less. The array fields
174 // all start as zero. Entries are only appended with the writer lock,
175 // so we don't need to worry about multiple writers colliding. And when
176 // appending, the end field is set before the start field. Readers
177 // of this structure just walk down the array and quit at the first
178 // start field that is zero.
180 struct ImmutableRanges
{
181 std
::atomic
<ImmutableRanges
*> next
;
184 std
::atomic
<uintptr_t> start
;
185 std
::atomic
<uintptr_t> end
;
186 } array
[2]; // programs with only main-exe and dyld cache fit in here
189 const MachOLoaded
* loadImage(Diagnostics
& diag
, const char* path
,
190 closure
::ImageNum topImageNum
, const closure
::DlopenClosure
* newClosure
,
191 bool rtldLocal
, bool rtldNoDelete
, bool rtldNow
, bool fromOFI
,
192 const void* callerAddress
);
195 typedef void (*Initializer
)(int argc
, const char* argv
[], char* envp
[], const char* apple
[], const ProgramVars
* vars
);
196 typedef const Array
<LoadedImage
> StartImageArray
;
198 void runInitialzersInImage(const mach_header
* imageLoadAddress
, const closure
::Image
* image
);
199 void mirrorToOldAllImageInfos();
200 void garbageCollectImages();
201 void breadthFirstRecurseDependents(Array
<closure
::ImageNum
>& visited
, const LoadedImage
& nodeLi
, bool& stop
, void (^handler
)(const LoadedImage
& aLoadedImage
, bool& stop
)) const;
202 void appendToImagesArray(const closure
::ImageArray
* newArray
);
203 void withReadLock(void (^work
)()) const;
204 void withWriteLock(void (^work
)());
205 void withNotifiersLock(void (^work
)()) const;
206 bool findImage(const mach_header
* loadAddress
, LoadedImage
& foundImage
) const;
207 bool findImageNum(closure
::ImageNum imageNum
, LoadedImage
& foundImage
) const;
208 LoadedImage
findImageNum(closure
::ImageNum num
, uint32_t& indexHint
);
209 bool swapImageState(closure
::ImageNum num
, uint32_t& indexHint
, LoadedImage
::State expectedCurrentState
, LoadedImage
::State newState
);
210 void runAllInitializersInImage(const closure
::Image
* image
, const MachOLoaded
* ml
);
211 void recomputeBounds();
212 void runAllStaticTerminators();
213 uintptr_t resolveTarget(closure
::Image
::ResolvedSymbolTarget target
) const;
214 void addImmutableRange(uintptr_t start
, uintptr_t end
);
216 void constructMachPorts(int slot
);
217 void teardownMachPorts(int slot
);
218 void forEachPortSlot(void (^callback
)(int slot
));
219 void sendMachMessage(int slot
, mach_msg_id_t msg_id
, mach_msg_header_t
* msg_buffer
, mach_msg_size_t msg_size
);
220 void notifyMonitoringDyld(bool unloading
, const Array
<LoadedImage
>& images
);
222 static void runAllStaticTerminatorsHelper(void*);
224 typedef closure
::ImageArray ImageArray
;
226 const closure
::LaunchClosure
* _mainClosure
= nullptr;
227 const DyldSharedCache
* _dyldCacheAddress
= nullptr;
228 const char* _dyldCachePath
= nullptr;
229 uint64_t _dyldCacheSlide
= 0;
230 StartImageArray
* _initialImages
= nullptr;
231 const char* _mainExeOverridePath
= nullptr;
232 _dyld_objc_notify_mapped _objcNotifyMapped
= nullptr;
233 _dyld_objc_notify_init _objcNotifyInit
= nullptr;
234 _dyld_objc_notify_unmapped _objcNotifyUnmapped
= nullptr;
235 ProgramVars
* _programVars
= nullptr;
236 dyld_all_image_infos
* _oldAllImageInfos
= nullptr;
237 dyld_image_info
* _oldAllImageArray
= nullptr;
238 dyld_uuid_info
* _oldUUIDArray
= nullptr;
239 const GradedArchs
* _archs
= nullptr;
240 ImmutableRanges _immutableRanges
= { nullptr, 2 };
241 uint32_t _oldArrayAllocCount
= 0;
242 uint32_t _oldUUIDAllocCount
= 0;
243 closure
::ImageNum _nextImageNum
= 0;
244 int32_t _gcCount
= 0;
245 bool _processDOFs
= false;
246 bool _allowAtPaths
= false;
247 bool _allowEnvPaths
= false;
248 bool _someImageOverridden
= false;
249 uint32_t _launchMode
= 0;
250 uintptr_t _lowestNonCached
= 0;
251 uintptr_t _highestNonCached
= UINTPTR_MAX
;
253 MainFunc _driverkitMain
= nullptr;
254 #ifdef OS_UNFAIR_RECURSIVE_LOCK_INIT
255 mutable os_unfair_recursive_lock _globalLock
= OS_UNFAIR_RECURSIVE_LOCK_INIT
;
257 mutable pthread_mutex_t _globalLock
= PTHREAD_RECURSIVE_MUTEX_INITIALIZER
;
259 GrowableArray
<const ImageArray
*, 4, 4> _imagesArrays
;
260 GrowableArray
<NotifyFunc
, 4, 4> _loadNotifiers
;
261 GrowableArray
<NotifyFunc
, 4, 4> _unloadNotifiers
;
262 GrowableArray
<LoadNotifyFunc
, 4, 4> _loadNotifiers2
;
263 GrowableArray
<BulkLoadNotifier
, 2, 2> _loadBulkNotifiers
;
264 GrowableArray
<DlopenCount
, 4, 4> _dlopenRefCounts
;
265 GrowableArray
<LoadedImage
, 16> _loadedImages
;
267 uint64_t _nextObjectFileImageNum
= 0;
268 GrowableArray
<OFIInfo
, 4, 1> _objectFileImages
;
272 // This is an array of the base addresses of sections containing selector strings
273 GrowableArray
<uintptr_t, 4, 4> _objcSelectorHashTableImages
;
274 const closure
::ObjCSelectorOpt
* _objcSelectorHashTable
= nullptr;
277 // This is an array of the base addresses of (name vmaddr, data vmaddr) pairs of sections in each image
278 GrowableArray
<std
::pair
<uintptr_t, uintptr_t>, 4, 4> _objcClassHashTableImages
;
279 const closure
::ObjCClassOpt
* _objcClassHashTable
= nullptr;
280 const closure
::ObjCClassDuplicatesOpt
* _objcClassDuplicatesHashTable
= nullptr;
281 const closure
::ObjCClassOpt
* _objcProtocolHashTable
= nullptr;
282 const objc_opt
::objc_opt_t
* _dyldCacheObjCOpt
= nullptr;
285 extern AllImages gAllImages
;
291 #endif // __ALL_IMAGES_H__