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@
34 #include <unordered_map>
36 #include "DyldSharedCache.h"
37 #include "Diagnostics.h"
38 #include "LaunchCache.h"
39 #include "LaunchCacheWriter.h"
40 #include "PathOverrides.h"
41 #include "ClosureBuffer.h"
42 #include "DyldCacheParser.h"
47 typedef launch_cache::binary_format::Image BinaryImageData
;
48 typedef launch_cache::binary_format::ImageGroup BinaryImageGroupData
;
49 typedef launch_cache::binary_format::Closure BinaryClosureData
;
50 typedef launch_cache::binary_format::ImageRef ImageRef
;
51 typedef launch_cache::Image::LinkKind LinkKind
;
52 typedef launch_cache::ImageGroupWriter::FixUp FixUp
;
53 typedef launch_cache::binary_format::DyldCacheOverride DyldCacheOverride
;
54 typedef launch_cache::ImageGroupList ImageGroupList
;
59 class ImageProxyGroup
;
64 ImageProxy(const mach_header
* mh
, const BinaryImageData
* image
, uint32_t indexInGroup
, bool dyldCacheIsRaw
);
65 ImageProxy(const DyldSharedCache::MappedMachO
& mapping
, uint32_t groupNum
, uint32_t indexInGroup
, bool dyldCacheIsRaw
);
69 const RPathChain
* prev
;
70 const std::vector
<std::string
>& rpaths
;
73 struct InitOrderInfo
{
74 bool beforeHas(ImageRef
);
75 bool upwardHas(ImageProxy
*);
76 void removeRedundantUpwards();
77 std::vector
<ImageRef
> initBefore
;
78 std::vector
<ImageProxy
*> danglingUpward
;
82 std::vector
<FixUp
> fixups
;
83 bool hasTextRelocs
= false;
86 void recursiveBuildInitBeforeInfo(ImageProxyGroup
& owningGroup
);
87 void addDependentsShallow(ImageProxyGroup
& owningGroup
, RPathChain
* chain
=nullptr);
88 void addDependentsDeep(ImageProxyGroup
& owningGroup
, RPathChain
* chain
, bool staticallyReferenced
);
89 void markInvalid() { _invalid
= true; }
91 uint32_t groupNum() const { return _groupNum
; }
92 uint32_t indexInGroup() const { return _indexInGroup
; }
93 const mach_header
* mh() const { return _mh
; }
94 const std::string
& runtimePath() const { return _runtimePath
; }
95 uint64_t sliceFileOffset() const { return _sliceFileOffset
; }
96 uint64_t fileModTime() const { return _modTime
; }
97 uint64_t fileInode() const { return _inode
; }
98 bool isSetUID() const { return _isSetUID
; }
99 bool invalid() const { return _invalid
; }
100 bool staticallyReferenced() const { return _staticallyReferenced
; }
101 bool cwdMustBeThisDir() const { return _cwdMustBeThisDir
; }
102 bool isPlatformBinary() const { return _platformBinary
; }
103 bool isProxyForCachedDylib() const { return _imageBinaryData
!= nullptr; }
104 const Diagnostics
& diagnostics() const { return _diag
; }
105 ImageRef
overrideOf() const { return _overrideOf
; }
106 bool inLibSystem() const;
107 void setCwdMustBeThisDir() { _cwdMustBeThisDir
= true; }
108 void setPlatformBinary() { _platformBinary
= true; }
109 void setOverrideOf(uint32_t groupNum
, uint32_t indexInGroup
);
110 void checkIfImageOverride(const std::string
& runtimeLoadPath
);
111 void forEachDependent(void (^handler
)(ImageProxy
* dep
, LinkKind
)) const;
112 FixupInfo
buildFixups(Diagnostics
& diag
, uint64_t cacheUnslideBaseAddress
, launch_cache::ImageGroupWriter
& groupWriter
) const;
113 bool findExportedSymbol(Diagnostics
& diag
, const char* symbolName
, MachOParser::FoundSymbol
& foundInfo
) const;
114 void convertInitBeforeInfoToArray(ImageProxyGroup
& owningGroup
);
115 void addToFlatLookup(std::vector
<ImageProxy
*>& imageList
);
116 const std::vector
<ImageRef
>& getInitBeforeList(ImageProxyGroup
& owningGroup
);
117 const std::vector
<std::string
>& rpaths() { return _rpaths
; }
120 void processRPaths(ImageProxyGroup
& owningGroup
);
122 const mach_header
* const _mh
;
123 uint64_t const _sliceFileOffset
;
124 uint64_t const _modTime
;
125 uint64_t const _inode
;
126 const BinaryImageData
* const _imageBinaryData
; // only used if proxy is for image in shared cache
127 std::string
const _runtimePath
;
128 bool const _isSetUID
;
129 bool const _dyldCacheIsRaw
;
130 uint32_t const _groupNum
;
131 uint32_t const _indexInGroup
;
132 bool _platformBinary
;
134 std::vector
<ImageProxy
*> _dependents
;
135 std::vector
<LinkKind
> _dependentsKind
;
136 std::vector
<std::string
> _rpaths
;
137 InitOrderInfo _initBeforesInfo
;
138 std::vector
<ImageRef
> _initBeforesArray
;
139 ImageRef _overrideOf
;
140 bool _directDependentsSet
;
141 bool _deepDependentsSet
;
142 bool _initBeforesArraySet
;
143 bool _initBeforesComputed
;
145 bool _staticallyReferenced
;
146 bool _cwdMustBeThisDir
;
150 class ImageProxyGroup
156 typedef std::unordered_map
<const mach_header
*, std::unordered_map
<uint32_t, std::unordered_set
<uint32_t>>> PatchTable
;
159 // used when building dyld shared cache
160 static ImageProxyGroup
* makeDyldCacheDylibsGroup(Diagnostics
& diag
, const DyldCacheParser
& dyldCache
, const std::vector
<DyldSharedCache::MappedMachO
>& cachedDylibs
,
161 const std::vector
<std::string
>& buildTimePrefixes
, const PatchTable
& patchTable
,
162 bool stubEliminated
, bool dylibsExpectedOnDisk
);
164 // used when building dyld shared cache
165 static ImageProxyGroup
* makeOtherOsGroup(Diagnostics
& diag
, const DyldCacheParser
& dyldCache
, ImageProxyGroup
* cachedDylibsGroup
,
166 const std::vector
<DyldSharedCache::MappedMachO
>& otherDylibsAndBundles
,
167 bool inodesAreSameAsRuntime
, const std::vector
<std::string
>& buildTimePrefixes
);
169 const BinaryImageGroupData
* makeImageGroupBinary(Diagnostics
& diag
, const char* const neverEliminateStubs
[]=nullptr);
171 // used when building dyld shared cache
172 static BinaryClosureData
* makeClosure(Diagnostics
& diag
, const DyldCacheParser
& dyldCache
, ImageProxyGroup
* cachedDylibsGroup
,
173 ImageProxyGroup
* otherOsDylibs
, const DyldSharedCache::MappedMachO
& mainProg
,
174 bool inodesAreSameAsRuntime
, const std::vector
<std::string
>& buildTimePrefixes
);
176 // used by closured for dlopen of unknown dylibs
177 static const BinaryImageGroupData
* makeDlopenGroup(Diagnostics
& diag
, const DyldCacheParser
& dyldCache
, uint32_t groupNum
,
178 const std::vector
<const BinaryImageGroupData
*>& existingGroups
,
179 const std::string
& imagePath
, const std::vector
<std::string
>& envVars
);
181 static const BinaryImageGroupData
* makeDlopenGroup(Diagnostics
& diag
, const ClosureBuffer
& buffer
, task_t requestor
, const std::vector
<std::string
>& buildTimePrefixes
={});
183 static BinaryClosureData
* makeClosure(Diagnostics
& diag
, const ClosureBuffer
& buffer
, task_t requestor
, const std::vector
<std::string
>& buildTimePrefixes
={});
187 // Creates a binary launch closure for the specified main executable.
188 // Used by closured and dyld_closure_util
190 // The closure is allocated with malloc(). Use free() to release when done.
191 // The size of the closure can be determined using Closure::size().
192 // If the closure cannot be built (e.g. app needs a symbol not exported by a framework),
193 // the reason for the failure is returned as a string in the diag parameter.
194 // The mainProgRuntimePath path is the path the program will be at runtime.
195 // The buildTimePrefixes is a list of prefixes to add to each path during closure
196 // creation to find the files at buildtime.
198 static BinaryClosureData
* makeClosure(Diagnostics
& diag
, const DyldCacheParser
& dyldCache
,
199 const std::string
& mainProgRuntimePath
, bool includeDylibsInDir
,
200 const std::vector
<std::string
>& buildTimePrefixes
={},
201 const std::vector
<std::string
>& envVars
={});
205 friend class ImageProxy
;
207 ImageProxyGroup(uint32_t groupNum
, const DyldCacheParser
& dyldCache
, const BinaryImageGroupData
* basedOn
,
208 ImageProxyGroup
* next
, const std::string
& mainProgRuntimePath
,
209 const std::vector
<const BinaryImageGroupData
*>& knownGroups
,
210 const std::vector
<std::string
>& buildTimePrefixes
,
211 const std::vector
<std::string
>& envVars
,
212 bool stubsEliminated
=false, bool dylibsExpectedOnDisk
=true, bool inodesAreSameAsRuntime
=true);
214 ImageProxy
* findImage(Diagnostics
& diag
, const std::string
& runtimePath
, bool canBeMissing
, ImageProxy::RPathChain
*);
215 ImageProxy
* findAbsoluteImage(Diagnostics
& diag
, const std::string
& runtimePath
, bool canBeMissing
, bool makeErrorMessage
, bool pathIsReal
=false);
216 bool builtImageStillValid(const launch_cache::Image
& image
);
217 const std::string
& mainProgRuntimePath() { return _mainProgRuntimePath
; }
218 DyldSharedCache::MappedMachO
* addMappingIfValidMachO(Diagnostics
& diag
, const std::string
& runtimePath
, bool ignoreMainExecutables
=false);
219 BinaryClosureData
* makeClosureBinary(Diagnostics
& diag
, ImageProxy
* mainProg
, bool includeDylibsInDir
);
220 void findLibdyldEntry(Diagnostics
& diag
, ImageRef
& ref
, uint32_t& offset
);
221 void findLibSystem(Diagnostics
& diag
, bool sim
, ImageRef
& ref
);
222 void populateGroupWriter(Diagnostics
& diag
, launch_cache::ImageGroupWriter
& groupWriter
, const char* const neverEliminateStubs
[]=nullptr);
223 std::string
normalizedPath(const std::string
& path
);
224 void addExtraMachOsInBundle(const std::string
& appDir
);
225 bool addInsertedDylibs(Diagnostics
& diag
);
226 std::vector
<ImageProxy
*> flatLookupOrder();
228 PathOverrides _pathOverrides
;
229 const BinaryImageGroupData
* _basedOn
; // if not null, then lazily populate _images
230 const PatchTable
* _patchTable
;
231 ImageProxyGroup
* const _nextSearchGroup
;
232 const DyldCacheParser _dyldCache
;
233 uint32_t const _groupNum
;
234 bool const _stubEliminated
;
235 bool const _dylibsExpectedOnDisk
;
236 bool const _inodesAreSameAsRuntime
;
237 uint32_t _mainExecutableIndex
;
238 std::vector
<const BinaryImageGroupData
*> _knownGroups
;
239 std::vector
<ImageProxy
*> _images
;
240 std::unordered_map
<std::string
, ImageProxy
*> _pathToProxy
;
241 std::vector
<DyldSharedCache::MappedMachO
> _ownedMappings
;
242 std::vector
<std::string
> _buildTimePrefixes
;
243 std::vector
<DyldCacheOverride
> _cacheOverrides
;
244 std::string _mainProgRuntimePath
;
245 std::string _archName
;
247 std::set
<std::string
> _mustBeMissingFiles
;
256 #endif // ImageProxy_h