dyld-832.7.1.tar.gz
[apple/dyld.git] / dyld3 / AllImages.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
25 #ifndef __ALL_IMAGES_H__
26 #define __ALL_IMAGES_H__
27
28 #include <mach-o/loader.h>
29 #include <pthread.h>
30 #include <os/lock_private.h>
31 #include <mach-o/dyld_priv.h>
32
33 #include "Closure.h"
34 #include "Loading.h"
35 #include "MachOLoaded.h"
36 #include "DyldSharedCache.h"
37
38
39 #if TARGET_OS_OSX
40 // only in macOS and deprecated
41 struct VIS_HIDDEN OFIInfo
42 {
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;
48 };
49 #endif
50
51 namespace dyld3 {
52
53 class VIS_HIDDEN AllImages
54 {
55 public:
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);
60
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();
69
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);
78
79 uint32_t count() const;
80
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;
93
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; }
105
106 const Array<const closure::ImageArray*>& imagesArrays();
107
108 void incRefCount(const mach_header* loadAddress);
109 void decRefCount(const mach_header* loadAddress);
110
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);
117
118
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);
124
125 #if TARGET_OS_OSX
126 NSObjectFileImage addNSObjectFileImage(const OFIInfo&);
127 void removeNSObjectFileImage(NSObjectFileImage);
128 bool forNSObjectFileImage(NSObjectFileImage imageHandle,
129 void (^handler)(OFIInfo& image));
130 #endif
131
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;
137
138 MainFunc getDriverkitMain();
139 void setDriverkitMain(MainFunc mainFunc);
140
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);
144
145 struct ProgramVars
146 {
147 const void* mh;
148 int* NXArgcPtr;
149 const char*** NXArgvPtr;
150 const char*** environPtr;
151 const char** __prognamePtr;
152 };
153 void setProgramVars(ProgramVars* vars, bool keysOff, bool platformBinariesOnly);
154
155 // Note these are to be used exclusively by forking
156 void takeLockBeforeFork();
157 void releaseLockInForkParent();
158 void resetLockInForkChild();
159
160 private:
161 friend class Reaper;
162
163 struct DlopenCount {
164 const mach_header* loadAddress;
165 uintptr_t refCount;
166 };
167
168 //
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.
179 //
180 struct ImmutableRanges {
181 std::atomic<ImmutableRanges*> next;
182 uintptr_t arraySize;
183 struct {
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
187 };
188
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);
193
194
195 typedef void (*Initializer)(int argc, const char* argv[], char* envp[], const char* apple[], const ProgramVars* vars);
196 typedef const Array<LoadedImage> StartImageArray;
197
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);
215
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);
221
222 static void runAllStaticTerminatorsHelper(void*);
223
224 typedef closure::ImageArray ImageArray;
225
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;
252
253 MainFunc _driverkitMain = nullptr;
254 #ifdef OS_UNFAIR_RECURSIVE_LOCK_INIT
255 mutable os_unfair_recursive_lock _globalLock = OS_UNFAIR_RECURSIVE_LOCK_INIT;
256 #else
257 mutable pthread_mutex_t _globalLock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER;
258 #endif
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;
266 #if TARGET_OS_OSX
267 uint64_t _nextObjectFileImageNum = 0;
268 GrowableArray<OFIInfo, 4, 1> _objectFileImages;
269 #endif
270
271 // ObjC selectors
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;
275
276 // ObjC classes
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;
283 };
284
285 extern AllImages gAllImages;
286
287
288 } // dyld3
289
290
291 #endif // __ALL_IMAGES_H__