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>
32 #include "dyld_priv.h"
36 #include "MachOLoaded.h"
37 #include "DyldSharedCache.h"
40 #if __MAC_OS_X_VERSION_MIN_REQUIRED
41 // only in macOS and deprecated
42 struct VIS_HIDDEN OFIInfo
44 const char* path
; // = nullptr;
45 const void* memSource
; // = nullptr;
46 size_t memLength
; // = 0;
47 const dyld3
::MachOLoaded
* loadAddress
; // = nullptr;
48 uint64_t imageNum
; // = 0;
54 class VIS_HIDDEN AllImages
57 typedef void (*NotifyFunc
)(const mach_header
* mh
, intptr_t slide
);
58 typedef void (*LoadNotifyFunc
)(const mach_header
* mh
, const char* path
, bool unloadable
);
60 void init(const closure
::LaunchClosure
* closure
, const DyldSharedCache
* dyldCacheLoadAddress
, const char* dyldCachePath
,
61 const Array
<LoadedImage
>& initialImages
);
62 void setRestrictions(bool allowAtPaths
, bool allowEnvPaths
);
63 void setMainPath(const char* path
);
64 void applyInitialImages();
66 void addImages(const Array
<LoadedImage
>& newImages
);
67 void removeImages(const Array
<LoadedImage
>& unloadImages
);
68 void runImageNotifiers(const Array
<LoadedImage
>& newImages
);
69 void applyInterposingToDyldCache(const closure
::Closure
* closure
);
70 void runStartupInitialzers();
71 void runInitialzersBottomUp(const closure
::Image
* topImage
);
72 void runLibSystemInitializer(const LoadedImage
& libSystem
);
74 uint32_t count() const;
76 void forEachImage(void (^handler
)(const LoadedImage
& loadedImage
, bool& stop
)) const;
77 const MachOLoaded
* findDependent(const MachOLoaded
* mh
, uint32_t depIndex
);
78 void visitDependentsTopDown(const LoadedImage
& start
, void (^handler
)(const LoadedImage
& aLoadedImage
, bool& stop
)) const;
79 void infoForImageMappedAt(const void* addr
, void (^handler
)(const LoadedImage
& foundImage
, uint8_t permissions
)) const;
80 bool infoForImageMappedAt(const void* addr
, const MachOLoaded
** ml
, uint64_t* textSize
, const char** path
) const;
81 void infoForNonCachedImageMappedAt(const void* addr
, void (^handler
)(const LoadedImage
& foundImage
, uint8_t permissions
)) const;
82 void infoForImageWithLoadAddress(const MachOLoaded
*, void (^handler
)(const LoadedImage
& foundImage
)) const;
83 const char* pathForImageMappedAt(const void* addr
) const;
84 const char* imagePathByIndex(uint32_t index
) const;
85 const mach_header
* imageLoadAddressByIndex(uint32_t index
) const;
86 bool immutableMemory(const void* addr
, size_t length
) const;
88 bool isRestricted() const;
89 const MachOLoaded
* mainExecutable() const;
90 const closure
::Image
* mainExecutableImage() const;
91 const void* cacheLoadAddress() const { return _dyldCacheAddress
; }
92 const char* dyldCachePath() const { return _dyldCachePath
; }
93 bool dyldCacheHasPath(const char* path
) const;
94 const char* imagePath(const closure
::Image
*) const;
95 dyld_platform_t
platform() const;
97 const Array
<const closure
::ImageArray
*>& imagesArrays();
99 void incRefCount(const mach_header
* loadAddress
);
100 void decRefCount(const mach_header
* loadAddress
);
102 void addLoadNotifier(NotifyFunc
);
103 void addUnloadNotifier(NotifyFunc
);
104 void setObjCNotifiers(_dyld_objc_notify_mapped
, _dyld_objc_notify_init
, _dyld_objc_notify_unmapped
);
105 void notifyObjCUnmap(const char* path
, const struct mach_header
* mh
);
106 void addLoadNotifier(LoadNotifyFunc
);
109 void setOldAllImageInfo(dyld_all_image_infos
* old
) { _oldAllImageInfos
= old
; }
110 dyld_all_image_infos
* oldAllImageInfo() const { return _oldAllImageInfos
;}
111 void notifyMonitorMain();
112 void notifyMonitorLoads(const Array
<LoadedImage
>& newImages
);
113 void notifyMonitorUnloads(const Array
<LoadedImage
>& unloadingImages
);
115 #if __MAC_OS_X_VERSION_MIN_REQUIRED
116 NSObjectFileImage
addNSObjectFileImage(const OFIInfo
&);
117 void removeNSObjectFileImage(NSObjectFileImage
);
118 bool forNSObjectFileImage(NSObjectFileImage imageHandle
,
119 void (^handler
)(OFIInfo
& image
));
122 const MachOLoaded
* dlopen(Diagnostics
& diag
, const char* path
, bool rtldNoLoad
, bool rtldLocal
, bool rtldNoDelete
, bool fromOFI
, const void* callerAddress
);
128 const char*** NXArgvPtr
;
129 const char*** environPtr
;
130 const char** __prognamePtr
;
132 void setProgramVars(ProgramVars
* vars
);
138 const mach_header
* loadAddress
;
143 typedef void (*Initializer
)(int argc
, const char* argv
[], char* envp
[], const char* apple
[], const ProgramVars
* vars
);
144 typedef const Array
<LoadedImage
> StartImageArray
;
146 void runInitialzersInImage(const mach_header
* imageLoadAddress
, const closure
::Image
* image
);
147 void mirrorToOldAllImageInfos();
148 void garbageCollectImages();
149 void breadthFirstRecurseDependents(Array
<closure
::ImageNum
>& visited
, const LoadedImage
& nodeLi
, bool& stop
, void (^handler
)(const LoadedImage
& aLoadedImage
, bool& stop
)) const;
150 void appendToImagesArray(const closure
::ImageArray
* newArray
);
151 void withReadLock(void (^work
)()) const;
152 void withWriteLock(void (^work
)());
153 void withNotifiersLock(void (^work
)()) const;
154 bool findImage(const mach_header
* loadAddress
, LoadedImage
& foundImage
) const;
155 bool findImageNum(closure
::ImageNum imageNum
, LoadedImage
& foundImage
) const;
156 LoadedImage
findImageNum(closure
::ImageNum num
, uint32_t& indexHint
);
157 bool swapImageState(closure
::ImageNum num
, uint32_t& indexHint
, LoadedImage
::State expectedCurrentState
, LoadedImage
::State newState
);
158 void runAllInitializersInImage(const closure
::Image
* image
, const MachOLoaded
* ml
);
159 void recomputeBounds();
161 void constructMachPorts(int slot
);
162 void teardownMachPorts(int slot
);
163 void forEachPortSlot(void (^callback
)(int slot
));
164 void sendMachMessage(int slot
, mach_msg_id_t msg_id
, mach_msg_header_t
* msg_buffer
, mach_msg_size_t msg_size
);
165 void notifyMonitoringDyld(bool unloading
, const Array
<LoadedImage
>& images
);
167 typedef closure
::ImageArray ImageArray
;
169 const closure
::LaunchClosure
* _mainClosure
= nullptr;
170 const DyldSharedCache
* _dyldCacheAddress
= nullptr;
171 const char* _dyldCachePath
= nullptr;
172 uint64_t _dyldCacheSlide
= 0;
173 StartImageArray
* _initialImages
= nullptr;
174 const char* _mainExeOverridePath
= nullptr;
175 _dyld_objc_notify_mapped _objcNotifyMapped
= nullptr;
176 _dyld_objc_notify_init _objcNotifyInit
= nullptr;
177 _dyld_objc_notify_unmapped _objcNotifyUnmapped
= nullptr;
178 ProgramVars
* _programVars
= nullptr;
179 dyld_all_image_infos
* _oldAllImageInfos
= nullptr;
180 dyld_image_info
* _oldAllImageArray
= nullptr;
181 dyld_platform_t _platform
= 0;
182 uint32_t _oldArrayAllocCount
= 0;
183 closure
::ImageNum _nextImageNum
= 0;
184 int32_t _gcCount
= 0;
185 bool _processDOFs
= false;
186 bool _allowAtPaths
= false;
187 bool _allowEnvPaths
= false;
188 uintptr_t _lowestNonCached
= 0;
189 uintptr_t _highestNonCached
= UINTPTR_MAX
;
190 #ifdef OS_UNFAIR_RECURSIVE_LOCK_INIT
191 mutable os_unfair_recursive_lock _loadImagesLock
= OS_UNFAIR_RECURSIVE_LOCK_INIT
;
192 mutable os_unfair_recursive_lock _notifiersLock
= OS_UNFAIR_RECURSIVE_LOCK_INIT
;
194 mutable pthread_mutex_t _loadImagesLock
= PTHREAD_RECURSIVE_MUTEX_INITIALIZER
;
195 mutable pthread_mutex_t _notifiersLock
= PTHREAD_RECURSIVE_MUTEX_INITIALIZER
;
197 GrowableArray
<const ImageArray
*, 4, 4> _imagesArrays
;
198 GrowableArray
<NotifyFunc
, 4, 4> _loadNotifiers
;
199 GrowableArray
<NotifyFunc
, 4, 4> _unloadNotifiers
;
200 GrowableArray
<LoadNotifyFunc
, 4, 4> _loadNotifiers2
;
201 GrowableArray
<DlopenCount
, 4, 4> _dlopenRefCounts
;
202 GrowableArray
<LoadedImage
, 16> _loadedImages
;
203 #if __MAC_OS_X_VERSION_MIN_REQUIRED
204 uint64_t _nextObjectFileImageNum
= 0;
205 GrowableArray
<OFIInfo
, 4, 1> _objectFileImages
;
209 extern AllImages gAllImages
;
215 #endif // __ALL_IMAGES_H__