]>
Commit | Line | Data |
---|---|---|
10b92d3b A |
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 | ||
26 | #ifndef __DYLD_LOADING_H__ | |
27 | #define __DYLD_LOADING_H__ | |
28 | ||
29 | #include <string.h> | |
30 | #include <stdint.h> | |
31 | #include <mach/mach.h> | |
32 | #include <_simple.h> | |
10b92d3b | 33 | |
6cae9b63 A |
34 | #include "Closure.h" |
35 | #include "MachOLoaded.h" | |
bc3b7c8c | 36 | #include "MachOAnalyzerSet.h" |
10b92d3b | 37 | |
cf998323 A |
38 | namespace objc_opt { |
39 | struct objc_clsopt_t; | |
40 | struct objc_selopt_t; | |
41 | } | |
42 | ||
10b92d3b A |
43 | namespace dyld3 { |
44 | ||
bc3b7c8c A |
45 | class RootsChecker; |
46 | ||
47 | struct LaunchErrorInfo | |
48 | { | |
49 | uintptr_t kind; | |
50 | const char* clientOfDylibPath; | |
51 | const char* targetDylibPath; | |
52 | const char* symbol; | |
53 | }; | |
10b92d3b | 54 | |
6cae9b63 A |
55 | // |
56 | // Tuple of info about a loaded image. Contains the loaded address, Image*, and state. | |
57 | // | |
58 | class VIS_HIDDEN LoadedImage { | |
59 | public: | |
60 | enum class State { unmapped=0, mapped=1, fixedUp=2, beingInited=3, inited=4 }; | |
61 | ||
62 | static LoadedImage make(const closure::Image* img) { LoadedImage result; result._image = img; return result; } | |
63 | static LoadedImage make(const closure::Image* img, const MachOLoaded* mh) | |
64 | { LoadedImage result; result._image = img; result.setLoadedAddress(mh); return result; } | |
65 | ||
66 | const closure::Image* image() const { return _image; } | |
67 | const MachOLoaded* loadedAddress() const { return (MachOLoaded*)(_loadAddr & (-4096)); } | |
68 | void setLoadedAddress(const MachOLoaded* a) { _loadAddr |= ((uintptr_t)a & (-4096)); } | |
69 | State state() const { return (State)(asBits().state); } | |
70 | void setState(State s) { asBits().state = (int)s; } | |
71 | bool hideFromFlatSearch() const { return asBits().hide; } | |
72 | void setHideFromFlatSearch(bool h) { asBits().hide = h; } | |
73 | bool leaveMapped() const { return asBits().leaveMapped; } | |
74 | void markLeaveMapped() { asBits().leaveMapped = true; } | |
75 | ||
76 | private: | |
77 | // since loaded MachO files are always page aligned, that means at least low 12-bits are always zero | |
78 | // so we don't need to record the low 12 bits, instead those bits hold various flags in the _loadeAddr field | |
79 | struct AddrBits { | |
80 | uintptr_t state : 3, | |
81 | hide : 1, | |
82 | leaveMapped : 1, | |
83 | extra : 7, | |
84 | #if __LP64__ | |
85 | addr : 52; | |
86 | #else | |
87 | addr : 20; | |
88 | #endif | |
89 | }; | |
90 | AddrBits& asBits() { return *((AddrBits*)&_loadAddr); } | |
91 | const AddrBits& asBits() const { return *((AddrBits*)&_loadAddr); } | |
92 | ||
93 | // Note: this must be statically initializable so as to not cause static initializers | |
94 | const closure::Image* _image = nullptr; | |
95 | uintptr_t _loadAddr = 0; // really AddrBits | |
10b92d3b A |
96 | }; |
97 | ||
98 | ||
6cae9b63 A |
99 | // |
100 | // Utility class to recursively load dependents | |
101 | // | |
bc3b7c8c | 102 | class VIS_HIDDEN Loader : public MachOAnalyzerSet { |
6cae9b63 A |
103 | public: |
104 | typedef bool (*LogFunc)(const char*, ...) __attribute__((format(printf, 1, 2))); | |
105 | ||
cf998323 A |
106 | Loader(const Array<LoadedImage>& existingImages, Array<LoadedImage>& newImagesStorage, |
107 | const void* cacheAddress, const Array<const dyld3::closure::ImageArray*>& imagesArrays, | |
108 | const closure::ObjCSelectorOpt* selOpt, const Array<closure::Image::ObjCSelectorImage>& selImages, | |
bc3b7c8c A |
109 | const RootsChecker& rootsChecker, dyld3::Platform platform, |
110 | LogFunc log_loads, LogFunc log_segments, LogFunc log_fixups, LogFunc log_dofs, | |
111 | bool allowMissingLazies=false, dyld3::LaunchErrorInfo* launchErrorInfo=nullptr); | |
6cae9b63 A |
112 | |
113 | void addImage(const LoadedImage&); | |
cf998323 | 114 | void completeAllDependents(Diagnostics& diag, bool& someCacheImageOverridden); |
bc3b7c8c | 115 | void mapAndFixupAllImages(Diagnostics& diag, bool processDOFs, bool fromOFI, bool* closureOutOfDate, bool* recoverable); |
6cae9b63 | 116 | uintptr_t resolveTarget(closure::Image::ResolvedSymbolTarget target); |
bc3b7c8c A |
117 | LoadedImage* findImage(closure::ImageNum targetImageNum) const; |
118 | void forEachImage(void (^handler)(const LoadedImage& li, bool& stop)) const; | |
6cae9b63 A |
119 | |
120 | static void unmapImage(LoadedImage& info); | |
121 | static bool dtraceUserProbesEnabled(); | |
122 | static void vmAccountingSetSuspended(bool suspend, LogFunc); | |
123 | ||
124 | private: | |
125 | ||
126 | struct ImageOverride | |
127 | { | |
128 | closure::ImageNum inCache; | |
129 | closure::ImageNum replacement; | |
130 | }; | |
131 | ||
132 | struct DOFInfo { | |
133 | const void* dof; | |
134 | const mach_header* imageHeader; | |
135 | const char* imageShortName; | |
136 | }; | |
137 | ||
cf998323 A |
138 | #if BUILDING_DYLD |
139 | struct LaunchImagesCache { | |
140 | LoadedImage* findImage(closure::ImageNum targetImageNum, | |
141 | Array<LoadedImage>& images) const; | |
bc3b7c8c | 142 | void tryAddImage(closure::ImageNum targetImageNum, uint64_t allImagesIndex) const; |
cf998323 A |
143 | |
144 | static const uint64_t _cacheSize = 128; | |
145 | static const closure::ImageNum _firstImageNum = closure::kFirstLaunchClosureImageNum; | |
146 | static const closure::ImageNum _lastImageNum = closure::kFirstLaunchClosureImageNum + _cacheSize; | |
147 | ||
148 | // Note, the cache stores "indices + 1" into the _allImages array. | |
149 | // 0 means we haven't cached an entry yet | |
150 | uint32_t _cacheStorage[_cacheSize] = { 0 }; | |
bc3b7c8c | 151 | mutable Array<uint32_t> _imageIndices = { &_cacheStorage[0], _cacheSize, _cacheSize }; |
cf998323 A |
152 | }; |
153 | #endif | |
154 | ||
bc3b7c8c | 155 | void mapImage(Diagnostics& diag, LoadedImage& info, bool fromOFI, bool* closureOutOfDate); |
6cae9b63 A |
156 | void applyFixupsToImage(Diagnostics& diag, LoadedImage& info); |
157 | void registerDOFs(const Array<DOFInfo>& dofs); | |
158 | void setSegmentProtects(const LoadedImage& info, bool write); | |
159 | bool sandboxBlockedMmap(const char* path); | |
160 | bool sandboxBlockedOpen(const char* path); | |
161 | bool sandboxBlockedStat(const char* path); | |
162 | bool sandboxBlocked(const char* path, const char* kind); | |
bc3b7c8c A |
163 | void unmapAllImages(); |
164 | ||
165 | // MachOAnalyzerSet support | |
166 | void mas_forEachImage(void (^handler)(const WrappedMachO& anImage, bool hidden, bool& stop)) const override; | |
167 | void mas_mainExecutable(WrappedMachO& anImage) const override; | |
168 | void* mas_dyldCache() const override; | |
169 | bool wmo_dependent(const WrappedMachO* image, uint32_t depIndex, WrappedMachO& childObj, bool& missingWeakDylib) const override; | |
170 | const char* wmo_path(const WrappedMachO* image) const override; | |
171 | bool wmo_missingSymbolResolver(const WrappedMachO* fromWmo, bool weakImport, bool lazyBind, const char* symbolName, const char* expectedInDylibPath, const char* clientPath, FixupTarget& target) const override; | |
172 | ||
6cae9b63 | 173 | |
cf998323 A |
174 | const Array<LoadedImage>& _existingImages; |
175 | Array<LoadedImage>& _newImages; | |
176 | const Array<const closure::ImageArray*>& _imagesArrays; | |
177 | const void* _dyldCacheAddress; | |
178 | const objc_opt::objc_selopt_t* _dyldCacheSelectorOpt; | |
179 | const closure::ObjCSelectorOpt* _closureSelectorOpt; | |
180 | const Array<closure::Image::ObjCSelectorImage>& _closureSelectorImages; | |
bc3b7c8c | 181 | const RootsChecker& _rootsChecker; |
cf998323 A |
182 | #if BUILDING_DYLD |
183 | LaunchImagesCache _launchImagesCache; | |
184 | #endif | |
bc3b7c8c A |
185 | bool _allowMissingLazies; |
186 | dyld3::Platform _platform; | |
cf998323 A |
187 | LogFunc _logLoads; |
188 | LogFunc _logSegments; | |
189 | LogFunc _logFixups; | |
190 | LogFunc _logDofs; | |
bc3b7c8c | 191 | dyld3::LaunchErrorInfo* _launchErrorInfo; |
6cae9b63 | 192 | }; |
10b92d3b A |
193 | |
194 | ||
10b92d3b | 195 | |
cf998323 | 196 | #if (BUILDING_LIBDYLD || BUILDING_DYLD) |
10b92d3b | 197 | bool internalInstall(); |
cf998323 A |
198 | #endif |
199 | #if BUILDING_DYLD | |
10b92d3b | 200 | void forEachLineInFile(const char* path, void (^lineHandler)(const char* line, bool& stop)); |
6cae9b63 | 201 | void forEachLineInFile(const char* buffer, size_t bufferLen, void (^lineHandler)(const char* line, bool& stop)); |
10b92d3b | 202 | #endif |
10b92d3b | 203 | |
10b92d3b A |
204 | } // namespace dyld3 |
205 | ||
10b92d3b A |
206 | #endif // __DYLD_LOADING_H__ |
207 | ||
208 |