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"
46 // Tuple of info about a loaded image. Contains the loaded address, Image*, and state.
48 class VIS_HIDDEN LoadedImage
{
50 enum class State
{ unmapped
=0, mapped
=1, fixedUp
=2, beingInited
=3, inited
=4 };
52 static LoadedImage
make(const closure::Image
* img
) { LoadedImage result
; result
._image
= img
; return result
; }
53 static LoadedImage
make(const closure::Image
* img
, const MachOLoaded
* mh
)
54 { LoadedImage result
; result
._image
= img
; result
.setLoadedAddress(mh
); return result
; }
56 const closure::Image
* image() const { return _image
; }
57 const MachOLoaded
* loadedAddress() const { return (MachOLoaded
*)(_loadAddr
& (-4096)); }
58 void setLoadedAddress(const MachOLoaded
* a
) { _loadAddr
|= ((uintptr_t)a
& (-4096)); }
59 State
state() const { return (State
)(asBits().state
); }
60 void setState(State s
) { asBits().state
= (int)s
; }
61 bool hideFromFlatSearch() const { return asBits().hide
; }
62 void setHideFromFlatSearch(bool h
) { asBits().hide
= h
; }
63 bool leaveMapped() const { return asBits().leaveMapped
; }
64 void markLeaveMapped() { asBits().leaveMapped
= true; }
67 // since loaded MachO files are always page aligned, that means at least low 12-bits are always zero
68 // so we don't need to record the low 12 bits, instead those bits hold various flags in the _loadeAddr field
80 AddrBits
& asBits() { return *((AddrBits
*)&_loadAddr
); }
81 const AddrBits
& asBits() const { return *((AddrBits
*)&_loadAddr
); }
83 // Note: this must be statically initializable so as to not cause static initializers
84 const closure::Image
* _image
= nullptr;
85 uintptr_t _loadAddr
= 0; // really AddrBits
90 // Utility class to recursively load dependents
92 class VIS_HIDDEN Loader
{
94 typedef bool (*LogFunc
)(const char*, ...) __attribute__((format(printf
, 1, 2)));
96 Loader(const Array
<LoadedImage
>& existingImages
, Array
<LoadedImage
>& newImagesStorage
,
97 const void* cacheAddress
, const Array
<const dyld3::closure::ImageArray
*>& imagesArrays
,
98 const closure::ObjCSelectorOpt
* selOpt
, const Array
<closure::Image::ObjCSelectorImage
>& selImages
,
99 LogFunc log_loads
, LogFunc log_segments
, LogFunc log_fixups
, LogFunc log_dofs
);
101 void addImage(const LoadedImage
&);
102 void completeAllDependents(Diagnostics
& diag
, bool& someCacheImageOverridden
);
103 void mapAndFixupAllImages(Diagnostics
& diag
, bool processDOFs
, bool fromOFI
=false);
104 uintptr_t resolveTarget(closure::Image::ResolvedSymbolTarget target
);
105 LoadedImage
* findImage(closure::ImageNum targetImageNum
);
107 static void unmapImage(LoadedImage
& info
);
108 static bool dtraceUserProbesEnabled();
109 static void vmAccountingSetSuspended(bool suspend
, LogFunc
);
115 closure::ImageNum inCache
;
116 closure::ImageNum replacement
;
121 const mach_header
* imageHeader
;
122 const char* imageShortName
;
126 struct LaunchImagesCache
{
127 LoadedImage
* findImage(closure::ImageNum targetImageNum
,
128 Array
<LoadedImage
>& images
) const;
129 void tryAddImage(closure::ImageNum targetImageNum
, uint64_t allImagesIndex
);
131 static const uint64_t _cacheSize
= 128;
132 static const closure::ImageNum _firstImageNum
= closure::kFirstLaunchClosureImageNum
;
133 static const closure::ImageNum _lastImageNum
= closure::kFirstLaunchClosureImageNum
+ _cacheSize
;
135 // Note, the cache stores "indices + 1" into the _allImages array.
136 // 0 means we haven't cached an entry yet
137 uint32_t _cacheStorage
[_cacheSize
] = { 0 };
138 Array
<uint32_t> _imageIndices
= { &_cacheStorage
[0], _cacheSize
, _cacheSize
};
142 void mapImage(Diagnostics
& diag
, LoadedImage
& info
, bool fromOFI
);
143 void applyFixupsToImage(Diagnostics
& diag
, LoadedImage
& info
);
144 void registerDOFs(const Array
<DOFInfo
>& dofs
);
145 void setSegmentProtects(const LoadedImage
& info
, bool write
);
146 bool sandboxBlockedMmap(const char* path
);
147 bool sandboxBlockedOpen(const char* path
);
148 bool sandboxBlockedStat(const char* path
);
149 bool sandboxBlocked(const char* path
, const char* kind
);
151 const Array
<LoadedImage
>& _existingImages
;
152 Array
<LoadedImage
>& _newImages
;
153 const Array
<const closure::ImageArray
*>& _imagesArrays
;
154 const void* _dyldCacheAddress
;
155 const objc_opt::objc_selopt_t
* _dyldCacheSelectorOpt
;
156 const closure::ObjCSelectorOpt
* _closureSelectorOpt
;
157 const Array
<closure::Image::ObjCSelectorImage
>& _closureSelectorImages
;
159 LaunchImagesCache _launchImagesCache
;
162 LogFunc _logSegments
;
169 #if (BUILDING_LIBDYLD || BUILDING_DYLD)
170 bool internalInstall();
173 void forEachLineInFile(const char* path
, void (^lineHandler
)(const char* line
, bool& stop
));
174 void forEachLineInFile(const char* buffer
, size_t bufferLen
, void (^lineHandler
)(const char* line
, bool& stop
));
179 #endif // __DYLD_LOADING_H__