]> git.saurik.com Git - apple/dyld.git/blob - dyld3/ClosureBuffer.cpp
dyld-519.2.2.tar.gz
[apple/dyld.git] / dyld3 / ClosureBuffer.cpp
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 #include <assert.h>
26 #include <mach/mach.h>
27 #include <dispatch/dispatch.h>
28 #include <bootstrap.h>
29
30 #include "ClosureBuffer.h"
31 #include "PathOverrides.h"
32
33
34 namespace dyld3 {
35
36 TypedContentBuffer::TypedContentBuffer(size_t elementsCount, size_t elementsTotalSize)
37 {
38 _size = elementsTotalSize + (elementsCount+1)*(sizeof(Element)+4); // worst case padding, plus "end" element
39 vm_address_t bufferAddress = 0;
40 assert(::vm_allocate(mach_task_self(), &bufferAddress, _size, VM_FLAGS_ANYWHERE) == 0);
41 _buffer = (Element*)bufferAddress;
42 _currentEnd = _buffer;
43 _readOnly = false;
44 }
45
46 void TypedContentBuffer::free()
47 {
48 if ( _buffer != nullptr )
49 vm_deallocate(mach_task_self(), (long)_buffer, _size);
50 _buffer = nullptr;
51 }
52
53 void TypedContentBuffer::addItem(uint32_t k, const void* content, size_t len)
54 {
55 assert(!_readOnly);
56 assert(((char*)_currentEnd + len) < ((char*)_buffer + _size));
57 _currentEnd->kind = k;
58 _currentEnd->contentLength = (uint32_t)len;
59 if ( len != 0 )
60 memmove(&(_currentEnd->content), content, len);
61 size_t delta = (sizeof(Element) + len + 3) & (-4);
62 _currentEnd = (Element*)((char*)_currentEnd + delta);
63 }
64
65 vm_address_t TypedContentBuffer::vmBuffer() const
66 {
67 assert(_readOnly);
68 return (vm_address_t)_buffer;
69 }
70
71 uint32_t TypedContentBuffer::vmBufferSize() const
72 {
73 assert(_readOnly);
74 return (uint32_t)_size;
75 }
76
77 void TypedContentBuffer::doneBuilding()
78 {
79 _readOnly = true;
80 }
81
82
83 const TypedContentBuffer::Element* TypedContentBuffer::Element::next() const
84 {
85 return (Element*)((char*)this + sizeof(Element) + ((contentLength + 3) & -4));
86 }
87
88 TypedContentBuffer::TypedContentBuffer(const void* buff, size_t buffSize)
89 : _size(buffSize), _buffer((Element*)buff), _currentEnd((Element*)((char*)buff+buffSize)), _readOnly(true)
90 {
91 }
92
93 unsigned TypedContentBuffer::count(uint32_t kind) const
94 {
95 assert(_readOnly);
96 unsigned count = 0;
97 for (const Element* e = _buffer; e->kind != 0; e = e->next()) {
98 if ( e->kind == kind )
99 ++count;
100 }
101 return count;
102 }
103
104 void TypedContentBuffer::forEach(uint32_t kind, void (^callback)(const void* content, size_t length)) const
105 {
106 assert(_readOnly);
107 for (const Element* e = _buffer; e->kind != 0; e = e->next()) {
108 if ( e->kind == kind ) {
109 callback(&(e->content), e->contentLength);
110 }
111 }
112 }
113
114 #if !BUILDING_CLOSURED
115
116 ClosureBuffer::ClosureBuffer(const CacheIdent& cacheIdent, const char* path, const launch_cache::ImageGroupList& groups, const PathOverrides& envVars)
117 : TypedContentBuffer(2 + envVars.envVarCount() + groups.count(), computeSize(path, groups, envVars))
118 {
119 addItem(kindCacheIdent, &cacheIdent, sizeof(CacheIdent));
120 addItem(kindTargetPath, path, strlen(path)+1);
121 envVars.forEachEnvVar(^(const char* envVar) {
122 addItem(kindEnvVar, envVar, strlen(envVar)+1);
123 });
124 for (size_t i=0; i < groups.count(); ++i) {
125 launch_cache::ImageGroup group(groups[i]);
126 addItem(kindImageGroup, group.binaryData(), group.size());
127 }
128 addItem(kindEnd, nullptr, 0);
129 doneBuilding();
130 }
131
132 size_t ClosureBuffer::computeSize(const char* path, const launch_cache::ImageGroupList& groups, const PathOverrides& envVars)
133 {
134 __block size_t result = sizeof(CacheIdent);
135 result += (strlen(path) + 1);
136 envVars.forEachEnvVar(^(const char* envVar) {
137 result += (strlen(envVar) + 1);
138 });
139 for (size_t i=0; i < groups.count(); ++i) {
140 launch_cache::ImageGroup group(groups[i]);
141 result += group.size();
142 }
143 return result;
144 }
145
146 #endif
147
148 ClosureBuffer::ClosureBuffer(const char* errorMessage)
149 : TypedContentBuffer(1, strlen(errorMessage+2))
150 {
151 addItem(kindErrorMessage, errorMessage, strlen(errorMessage)+1);
152 doneBuilding();
153 }
154
155 ClosureBuffer::ClosureBuffer(const launch_cache::BinaryImageGroupData* imageGroup)
156 : TypedContentBuffer(1, launch_cache::ImageGroup(imageGroup).size())
157 {
158 addItem(kindImageGroup, imageGroup, launch_cache::ImageGroup(imageGroup).size());
159 doneBuilding();
160 }
161
162 ClosureBuffer::ClosureBuffer(const launch_cache::BinaryClosureData* closure)
163 : TypedContentBuffer(1, launch_cache::Closure(closure).size())
164 {
165 addItem(kindClosure, closure, launch_cache::Closure(closure).size());
166 doneBuilding();
167 }
168
169
170 ClosureBuffer::ClosureBuffer(const void* buff, size_t buffSize)
171 : TypedContentBuffer(buff, buffSize)
172 {
173 }
174
175 const ClosureBuffer::CacheIdent& ClosureBuffer::cacheIndent() const
176 {
177 __block CacheIdent* ident = nullptr;
178 forEach(kindCacheIdent, ^(const void* content, size_t length) {
179 ident = (CacheIdent*)content;
180 assert(length == sizeof(CacheIdent));
181 });
182 assert(ident != nullptr);
183 return *ident;
184 }
185
186 const char* ClosureBuffer::targetPath() const
187 {
188 __block char* path = nullptr;
189 forEach(kindTargetPath, ^(const void* content, size_t length) {
190 path = (char*)content;
191 });
192 assert(path != nullptr);
193 return path;
194 }
195
196 uint32_t ClosureBuffer::envVarCount() const
197 {
198 __block uint32_t count = 0;
199 forEach(kindEnvVar, ^(const void* content, size_t length) {
200 ++count;
201 });
202 return count;
203 }
204
205 void ClosureBuffer::copyImageGroups(const char* envVars[]) const
206 {
207 __block uint32_t index = 0;
208 forEach(kindEnvVar, ^(const void* content, size_t length) {
209 envVars[index] = (char*)content;
210 ++index;
211 });
212 }
213
214 uint32_t ClosureBuffer::imageGroupCount() const
215 {
216 __block uint32_t count = 0;
217 forEach(kindImageGroup, ^(const void* content, size_t length) {
218 ++count;
219 });
220 return count;
221 }
222
223 void ClosureBuffer::copyImageGroups(const launch_cache::BinaryImageGroupData* imageGroups[]) const
224 {
225 __block uint32_t index = 0;
226 forEach(kindImageGroup, ^(const void* content, size_t length) {
227 imageGroups[index] = (launch_cache::BinaryImageGroupData*)content;
228 ++index;
229 });
230 }
231
232 bool ClosureBuffer::isError() const
233 {
234 return ( errorMessage() != nullptr );
235 }
236
237 const char* ClosureBuffer::errorMessage() const
238 {
239 __block char* message = nullptr;
240 forEach(kindErrorMessage, ^(const void* content, size_t length) {
241 message = (char*)content;
242 });
243 return message;
244 }
245
246 const launch_cache::BinaryClosureData* ClosureBuffer::closure() const
247 {
248 __block const launch_cache::BinaryClosureData* result = nullptr;
249 forEach(kindClosure, ^(const void* content, size_t length) {
250 result = (const launch_cache::BinaryClosureData*)content;
251 });
252 assert(result != nullptr);
253 return result;
254 }
255
256
257 const launch_cache::BinaryImageGroupData* ClosureBuffer::imageGroup() const
258 {
259 __block const launch_cache::BinaryImageGroupData* result = nullptr;
260 forEach(kindImageGroup, ^(const void* content, size_t length) {
261 result = (const launch_cache::BinaryImageGroupData*)content;
262 });
263 assert(result != nullptr);
264 return result;
265 }
266
267
268
269
270
271
272 } // namespace dyld3
273