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@
26 #ifndef __DYLD_LOADING_H__
27 #define __DYLD_LOADING_H__
31 #include <mach/mach.h>
35 #include "MachOLoaded.h"
36 #include "MachOAnalyzerSet.h"
47 struct LaunchErrorInfo
50 const char* clientOfDylibPath
;
51 const char* targetDylibPath
;
56 // Tuple of info about a loaded image. Contains the loaded address, Image*, and state.
58 class VIS_HIDDEN LoadedImage
{
60 enum class State
{ unmapped
=0, mapped
=1, fixedUp
=2, beingInited
=3, inited
=4 };
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
; }
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; }
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
90 AddrBits
& asBits() { return *((AddrBits
*)&_loadAddr
); }
91 const AddrBits
& asBits() const { return *((AddrBits
*)&_loadAddr
); }
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
100 // Utility class to recursively load dependents
102 class VIS_HIDDEN Loader
: public MachOAnalyzerSet
{
104 typedef bool (*LogFunc
)(const char*, ...) __attribute__((format(printf
, 1, 2)));
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
,
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);
113 void addImage(const LoadedImage
&);
114 void completeAllDependents(Diagnostics
& diag
, bool& someCacheImageOverridden
);
115 void mapAndFixupAllImages(Diagnostics
& diag
, bool processDOFs
, bool fromOFI
, bool* closureOutOfDate
, bool* recoverable
);
116 uintptr_t resolveTarget(closure
::Image
::ResolvedSymbolTarget target
);
117 LoadedImage
* findImage(closure
::ImageNum targetImageNum
) const;
118 void forEachImage(void (^handler
)(const LoadedImage
& li
, bool& stop
)) const;
120 static void unmapImage(LoadedImage
& info
);
121 static bool dtraceUserProbesEnabled();
122 static void vmAccountingSetSuspended(bool suspend
, LogFunc
);
128 closure
::ImageNum inCache
;
129 closure
::ImageNum replacement
;
134 const mach_header
* imageHeader
;
135 const char* imageShortName
;
139 struct LaunchImagesCache
{
140 LoadedImage
* findImage(closure
::ImageNum targetImageNum
,
141 Array
<LoadedImage
>& images
) const;
142 void tryAddImage(closure
::ImageNum targetImageNum
, uint64_t allImagesIndex
) const;
144 static const uint64_t _cacheSize
= 128;
145 static const closure
::ImageNum _firstImageNum
= closure
::kFirstLaunchClosureImageNum
;
146 static const closure
::ImageNum _lastImageNum
= closure
::kFirstLaunchClosureImageNum
+ _cacheSize
;
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 };
151 mutable Array
<uint32_t> _imageIndices
= { &_cacheStorage
[0], _cacheSize
, _cacheSize
};
155 void mapImage(Diagnostics
& diag
, LoadedImage
& info
, bool fromOFI
, bool* closureOutOfDate
);
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
);
163 void unmapAllImages();
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
;
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
;
181 const RootsChecker
& _rootsChecker
;
183 LaunchImagesCache _launchImagesCache
;
185 bool _allowMissingLazies
;
186 dyld3
::Platform _platform
;
188 LogFunc _logSegments
;
191 dyld3
::LaunchErrorInfo
* _launchErrorInfo
;
196 #if (BUILDING_LIBDYLD || BUILDING_DYLD)
197 bool internalInstall();
200 void forEachLineInFile(const char* path
, void (^lineHandler
)(const char* line
, bool& stop
));
201 void forEachLineInFile(const char* buffer
, size_t bufferLen
, void (^lineHandler
)(const char* line
, bool& stop
));
206 #endif // __DYLD_LOADING_H__