]>
Commit | Line | Data |
---|---|---|
1c79356b | 1 | /* |
b0d623f7 | 2 | * Copyright (c) 2000,2008-2009 Apple Inc. All rights reserved. |
1c79356b | 3 | * |
2d21ac55 | 4 | * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ |
1c79356b | 5 | * |
2d21ac55 A |
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. The rights granted to you under the License | |
10 | * may not be used to create, or enable the creation or redistribution of, | |
11 | * unlawful or unlicensed copies of an Apple operating system, or to | |
12 | * circumvent, violate, or enable the circumvention or violation of, any | |
13 | * terms of an Apple operating system software license agreement. | |
8f6c56a5 | 14 | * |
2d21ac55 A |
15 | * Please obtain a copy of the License at |
16 | * http://www.opensource.apple.com/apsl/ and read it before using this file. | |
17 | * | |
18 | * The Original Code and all software distributed under the License are | |
19 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
8f6c56a5 A |
20 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, |
21 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
2d21ac55 A |
22 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. |
23 | * Please see the License for the specific language governing rights and | |
24 | * limitations under the License. | |
8f6c56a5 | 25 | * |
2d21ac55 | 26 | * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ |
1c79356b A |
27 | */ |
28 | /* | |
b0d623f7 | 29 | * Copyright (c) 1997 Apple Inc. |
1c79356b A |
30 | * |
31 | */ | |
32 | #include <libkern/c++/OSMetaClass.h> | |
b0d623f7 | 33 | #include <libkern/c++/OSKext.h> |
1c79356b A |
34 | #include <libkern/c++/OSLib.h> |
35 | #include <libkern/c++/OSSymbol.h> | |
3e170ce0 | 36 | #include <IOKit/IOKitDebug.h> |
1c79356b A |
37 | |
38 | #include <sys/cdefs.h> | |
39 | ||
40 | __BEGIN_DECLS | |
41 | ||
42 | #include <string.h> | |
1c79356b | 43 | #include <mach/mach_types.h> |
b0d623f7 | 44 | #include <libkern/kernel_mach_header.h> |
d9a64523 | 45 | #include <libkern/prelink.h> |
1c79356b A |
46 | #include <stdarg.h> |
47 | ||
b0d623f7 A |
48 | #if PRAGMA_MARK |
49 | #pragma mark Constants &c. | |
50 | #endif /* PRAGMA_MARK */ | |
51 | OSKextLogSpec kOSRuntimeLogSpec = | |
52 | kOSKextLogErrorLevel | | |
53 | kOSKextLogLoadFlag | | |
54 | kOSKextLogKextBookkeepingFlag; | |
55 | ||
56 | #if PRAGMA_MARK | |
57 | #pragma mark Logging Bootstrap | |
58 | #endif /* PRAGMA_MARK */ | |
59 | /********************************************************************* | |
60 | * kern_os Logging Bootstrap | |
61 | * | |
62 | * We can't call in to OSKext until the kernel's C++ environment is up | |
63 | * and running, so let's mask those references with a check variable. | |
64 | * We print unconditionally if C++ isn't up, but if that's the case | |
65 | * we've generally hit a serious error in kernel init! | |
66 | *********************************************************************/ | |
67 | static bool gKernelCPPInitialized = false; | |
68 | ||
69 | #define OSRuntimeLog(kext, flags, format, args...) \ | |
70 | do { \ | |
71 | if (gKernelCPPInitialized) { \ | |
72 | OSKextLog((kext), (flags), (format), ## args); \ | |
73 | } else { \ | |
74 | printf((format), ## args); \ | |
75 | } \ | |
76 | } while (0) | |
77 | ||
b0d623f7 A |
78 | #if PRAGMA_MARK |
79 | #pragma mark kern_os Allocator Package | |
80 | #endif /* PRAGMA_MARK */ | |
81 | /********************************************************************* | |
82 | * kern_os Allocator Package | |
83 | *********************************************************************/ | |
84 | ||
85 | /********************************************************************* | |
86 | *********************************************************************/ | |
1c79356b A |
87 | #if OSALLOCDEBUG |
88 | extern int debug_iomalloc_size; | |
89 | #endif | |
90 | ||
b0d623f7 A |
91 | /********************************************************************* |
92 | *********************************************************************/ | |
93 | void * | |
94 | kern_os_malloc(size_t size) | |
1c79356b | 95 | { |
39037602 | 96 | void *mem; |
b0d623f7 A |
97 | if (size == 0) { |
98 | return (0); | |
99 | } | |
1c79356b | 100 | |
39037602 | 101 | mem = kallocp_tag_bt((vm_size_t *)&size, VM_KERN_MEMORY_LIBKERN); |
b0d623f7 A |
102 | if (!mem) { |
103 | return (0); | |
104 | } | |
1c79356b A |
105 | |
106 | #if OSALLOCDEBUG | |
39037602 | 107 | OSAddAtomic(size, &debug_iomalloc_size); |
1c79356b A |
108 | #endif |
109 | ||
39037602 | 110 | bzero(mem, size); |
1c79356b | 111 | |
39037602 | 112 | return mem; |
1c79356b A |
113 | } |
114 | ||
b0d623f7 A |
115 | /********************************************************************* |
116 | *********************************************************************/ | |
117 | void | |
118 | kern_os_free(void * addr) | |
1c79356b | 119 | { |
39037602 A |
120 | size_t size; |
121 | size = kalloc_size(addr); | |
1c79356b | 122 | #if OSALLOCDEBUG |
39037602 | 123 | OSAddAtomic(-size, &debug_iomalloc_size); |
1c79356b A |
124 | #endif |
125 | ||
39037602 | 126 | kfree_addr(addr); |
1c79356b A |
127 | } |
128 | ||
b0d623f7 A |
129 | /********************************************************************* |
130 | *********************************************************************/ | |
131 | void * | |
132 | kern_os_realloc( | |
133 | void * addr, | |
134 | size_t nsize) | |
1c79356b | 135 | { |
39037602 A |
136 | void *nmem; |
137 | size_t osize; | |
b0d623f7 A |
138 | |
139 | if (!addr) { | |
140 | return (kern_os_malloc(nsize)); | |
141 | } | |
142 | ||
39037602 | 143 | osize = kalloc_size(addr); |
b0d623f7 A |
144 | if (nsize == osize) { |
145 | return (addr); | |
146 | } | |
147 | ||
148 | if (nsize == 0) { | |
39037602 | 149 | kfree_addr(addr); |
b0d623f7 A |
150 | return (0); |
151 | } | |
152 | ||
39037602 | 153 | nmem = kallocp_tag_bt((vm_size_t *)&nsize, VM_KERN_MEMORY_LIBKERN); |
b0d623f7 | 154 | if (!nmem){ |
39037602 | 155 | kfree_addr(addr); |
b0d623f7 A |
156 | return (0); |
157 | } | |
1c79356b A |
158 | |
159 | #if OSALLOCDEBUG | |
39037602 | 160 | OSAddAtomic((nsize - osize), &debug_iomalloc_size); |
1c79356b A |
161 | #endif |
162 | ||
b0d623f7 | 163 | if (nsize > osize) { |
39037602 | 164 | (void)memset((char *)nmem + osize, 0, nsize - osize); |
b0d623f7 | 165 | } |
39037602 A |
166 | (void)memcpy(nmem, addr, (nsize > osize) ? osize : nsize); |
167 | kfree_addr(addr); | |
1c79356b | 168 | |
39037602 | 169 | return (nmem); |
1c79356b A |
170 | } |
171 | ||
b0d623f7 | 172 | #if PRAGMA_MARK |
d9a64523 | 173 | #pragma mark Libkern Init |
b0d623f7 A |
174 | #endif /* PRAGMA_MARK */ |
175 | /********************************************************************* | |
d9a64523 | 176 | * Libkern Init |
b0d623f7 A |
177 | *********************************************************************/ |
178 | ||
9bccf70c | 179 | #if __GNUC__ >= 3 |
b0d623f7 | 180 | void __cxa_pure_virtual( void ) { panic("%s", __FUNCTION__); } |
9bccf70c | 181 | #else |
b0d623f7 | 182 | void __pure_virtual( void ) { panic("%s", __FUNCTION__); } |
9bccf70c | 183 | #endif |
1c79356b | 184 | |
d9a64523 A |
185 | extern lck_grp_t * IOLockGroup; |
186 | extern kmod_info_t g_kernel_kmod_info; | |
6d2010ae | 187 | |
d9a64523 A |
188 | enum { |
189 | kOSSectionNamesDefault = 0, | |
190 | kOSSectionNamesBuiltinKext = 1, | |
191 | kOSSectionNamesCount = 2, | |
192 | }; | |
193 | enum { | |
194 | kOSSectionNameInitializer = 0, | |
195 | kOSSectionNameFinalizer = 1, | |
196 | kOSSectionNameCount = 2 | |
197 | }; | |
6d2010ae | 198 | |
d9a64523 A |
199 | static const char * |
200 | gOSStructorSectionNames[kOSSectionNamesCount][kOSSectionNameCount] = { | |
201 | { SECT_MODINITFUNC, SECT_MODTERMFUNC }, | |
202 | { kBuiltinInitSection, kBuiltinTermSection } | |
203 | }; | |
b0d623f7 | 204 | |
d9a64523 | 205 | void OSlibkernInit(void) |
b0d623f7 | 206 | { |
d9a64523 A |
207 | // This must be called before calling OSRuntimeInitializeCPP. |
208 | OSMetaClassBase::initialize(); | |
b0d623f7 | 209 | |
d9a64523 A |
210 | g_kernel_kmod_info.address = (vm_address_t) &_mh_execute_header; |
211 | if (kOSReturnSuccess != OSRuntimeInitializeCPP(NULL)) { | |
212 | // &g_kernel_kmod_info, gOSSectionNamesStandard, 0, 0)) { | |
213 | panic("OSRuntime: C++ runtime failed to initialize."); | |
b0d623f7 | 214 | } |
1c79356b | 215 | |
d9a64523 | 216 | gKernelCPPInitialized = true; |
1c79356b A |
217 | |
218 | return; | |
219 | } | |
220 | ||
d9a64523 | 221 | __END_DECLS |
b0d623f7 | 222 | |
d9a64523 A |
223 | #if PRAGMA_MARK |
224 | #pragma mark C++ Runtime Load/Unload | |
225 | #endif /* PRAGMA_MARK */ | |
b0d623f7 | 226 | /********************************************************************* |
d9a64523 | 227 | * kern_os C++ Runtime Load/Unload |
b0d623f7 | 228 | *********************************************************************/ |
1c79356b | 229 | |
1c79356b | 230 | |
d9a64523 | 231 | typedef void (*structor_t)(void); |
1c79356b | 232 | |
d9a64523 A |
233 | static bool |
234 | OSRuntimeCallStructorsInSection( | |
235 | OSKext * theKext, | |
236 | kmod_info_t * kmodInfo, | |
237 | void * metaHandle, | |
238 | kernel_segment_command_t * segment, | |
239 | const char * sectionName, | |
240 | uintptr_t textStart, | |
241 | uintptr_t textEnd) | |
242 | { | |
243 | kernel_section_t * section; | |
244 | bool result = TRUE; | |
1c79356b | 245 | |
d9a64523 A |
246 | for (section = firstsect(segment); |
247 | section != NULL; | |
248 | section = nextsect(segment, section)) | |
249 | { | |
250 | if (strncmp(section->sectname, sectionName, sizeof(section->sectname) - 1)) continue; | |
251 | ||
252 | structor_t * structors = (structor_t *)section->addr; | |
253 | if (!structors) continue; | |
254 | ||
255 | structor_t structor; | |
256 | unsigned int num_structors = section->size / sizeof(structor_t); | |
257 | unsigned int hit_null_structor = 0; | |
258 | unsigned int firstIndex = 0; | |
259 | ||
260 | if (textStart) | |
261 | { | |
262 | // bsearch for any in range | |
263 | unsigned int baseIdx; | |
264 | unsigned int lim; | |
265 | uintptr_t value; | |
266 | firstIndex = num_structors; | |
267 | for (lim = num_structors, baseIdx = 0; lim; lim >>= 1) | |
268 | { | |
269 | value = (uintptr_t) structors[baseIdx + (lim >> 1)]; | |
270 | if (!value) panic("%s: null structor", kmodInfo->name); | |
271 | if ((value >= textStart) && (value < textEnd)) | |
272 | { | |
273 | firstIndex = (baseIdx + (lim >> 1)); | |
274 | // scan back for the first in range | |
275 | for (; firstIndex; firstIndex--) | |
276 | { | |
277 | value = (uintptr_t) structors[firstIndex - 1]; | |
278 | if ((value < textStart) || (value >= textEnd)) break; | |
279 | } | |
280 | break; | |
281 | } | |
282 | if (textStart > value) | |
283 | { | |
284 | // move right | |
285 | baseIdx += (lim >> 1) + 1; | |
286 | lim--; | |
287 | } | |
288 | // else move left | |
289 | } | |
290 | baseIdx = (baseIdx + (lim >> 1)); | |
1c79356b | 291 | } |
d9a64523 A |
292 | for (; |
293 | (firstIndex < num_structors) | |
294 | && (!metaHandle || OSMetaClass::checkModLoad(metaHandle)); | |
295 | firstIndex++) | |
296 | { | |
297 | if ((structor = structors[firstIndex])) | |
298 | { | |
299 | if ((textStart && ((uintptr_t) structor < textStart)) | |
300 | || (textEnd && ((uintptr_t) structor >= textEnd))) break; | |
301 | ||
302 | (*structor)(); | |
303 | } | |
304 | else if (!hit_null_structor) | |
305 | { | |
306 | hit_null_structor = 1; | |
307 | OSRuntimeLog(theKext, kOSRuntimeLogSpec, | |
308 | "Null structor in kext %s segment %s!", | |
309 | kmodInfo->name, section->segname); | |
310 | } | |
311 | } | |
312 | if (metaHandle) result = OSMetaClass::checkModLoad(metaHandle); | |
313 | break; | |
314 | } /* for (section...) */ | |
315 | return (result); | |
1c79356b A |
316 | } |
317 | ||
b0d623f7 A |
318 | /********************************************************************* |
319 | *********************************************************************/ | |
320 | kern_return_t | |
321 | OSRuntimeFinalizeCPP( | |
d9a64523 | 322 | OSKext * theKext) |
1c79356b | 323 | { |
d9a64523 A |
324 | kern_return_t result = KMOD_RETURN_FAILURE; |
325 | void * metaHandle = NULL; // do not free | |
326 | kernel_mach_header_t * header; | |
327 | kernel_segment_command_t * segment; | |
328 | kmod_info_t * kmodInfo; | |
329 | const char ** sectionNames; | |
330 | uintptr_t textStart; | |
331 | uintptr_t textEnd; | |
332 | ||
333 | textStart = 0; | |
334 | textEnd = 0; | |
335 | sectionNames = gOSStructorSectionNames[kOSSectionNamesDefault]; | |
336 | if (theKext) { | |
337 | if (!theKext->isCPPInitialized()) { | |
338 | result = KMOD_RETURN_SUCCESS; | |
339 | goto finish; | |
340 | } | |
341 | kmodInfo = theKext->kmod_info; | |
342 | if (!kmodInfo || !kmodInfo->address) { | |
343 | result = kOSKextReturnInvalidArgument; | |
344 | goto finish; | |
345 | } | |
346 | header = (kernel_mach_header_t *)kmodInfo->address; | |
347 | if (theKext->flags.builtin) { | |
348 | header = (kernel_mach_header_t *)g_kernel_kmod_info.address; | |
349 | textStart = kmodInfo->address; | |
350 | textEnd = textStart + kmodInfo->size; | |
351 | sectionNames = gOSStructorSectionNames[kOSSectionNamesBuiltinKext]; | |
352 | } | |
353 | } else { | |
354 | kmodInfo = &g_kernel_kmod_info; | |
355 | header = (kernel_mach_header_t *)kmodInfo->address; | |
b0d623f7 A |
356 | } |
357 | ||
358 | /* OSKext checks for this condition now, but somebody might call | |
359 | * this function directly (the symbol is exported....). | |
360 | */ | |
361 | if (OSMetaClass::modHasInstance(kmodInfo->name)) { | |
362 | // xxx - Don't log under errors? this is more of an info thing | |
363 | OSRuntimeLog(theKext, kOSRuntimeLogSpec, | |
364 | "Can't tear down kext %s C++; classes have instances:", | |
365 | kmodInfo->name); | |
366 | OSKext::reportOSMetaClassInstances(kmodInfo->name, kOSRuntimeLogSpec); | |
367 | result = kOSMetaClassHasInstances; | |
368 | goto finish; | |
369 | } | |
370 | ||
371 | /* Tell the meta class system that we are starting to unload. | |
372 | * metaHandle isn't actually needed on the finalize path, | |
373 | * so we don't check it here, even though OSMetaClass::postModLoad() will | |
374 | * return a failure (it only does actual work on the init path anyhow). | |
375 | */ | |
376 | metaHandle = OSMetaClass::preModLoad(kmodInfo->name); | |
d9a64523 A |
377 | |
378 | OSSymbol::checkForPageUnload((void *)kmodInfo->address, | |
379 | (void *)(kmodInfo->address + kmodInfo->size)); | |
380 | ||
381 | header = (kernel_mach_header_t *)kmodInfo->address; | |
382 | segment = firstsegfromheader(header); | |
383 | ||
384 | for (segment = firstsegfromheader(header); | |
385 | segment != 0; | |
386 | segment = nextsegfromheader(header, segment)) { | |
387 | ||
388 | OSRuntimeCallStructorsInSection(theKext, kmodInfo, NULL, segment, | |
389 | sectionNames[kOSSectionNameFinalizer], textStart, textEnd); | |
390 | } | |
391 | ||
b0d623f7 | 392 | (void)OSMetaClass::postModLoad(metaHandle); |
1c79356b | 393 | |
b0d623f7 A |
394 | if (theKext) { |
395 | theKext->setCPPInitialized(false); | |
396 | } | |
397 | result = KMOD_RETURN_SUCCESS; | |
398 | finish: | |
b0d623f7 | 399 | return result; |
1c79356b A |
400 | } |
401 | ||
b0d623f7 A |
402 | /********************************************************************* |
403 | *********************************************************************/ | |
404 | kern_return_t | |
405 | OSRuntimeInitializeCPP( | |
d9a64523 | 406 | OSKext * theKext) |
1c79356b | 407 | { |
b0d623f7 | 408 | kern_return_t result = KMOD_RETURN_FAILURE; |
b0d623f7 A |
409 | kernel_mach_header_t * header = NULL; |
410 | void * metaHandle = NULL; // do not free | |
411 | bool load_success = true; | |
412 | kernel_segment_command_t * segment = NULL; // do not free | |
413 | kernel_segment_command_t * failure_segment = NULL; // do not free | |
d9a64523 A |
414 | kmod_info_t * kmodInfo; |
415 | const char ** sectionNames; | |
416 | uintptr_t textStart; | |
417 | uintptr_t textEnd; | |
418 | ||
419 | textStart = 0; | |
420 | textEnd = 0; | |
421 | sectionNames = gOSStructorSectionNames[kOSSectionNamesDefault]; | |
422 | if (theKext) { | |
423 | if (theKext->isCPPInitialized()) { | |
424 | result = KMOD_RETURN_SUCCESS; | |
425 | goto finish; | |
426 | } | |
b0d623f7 | 427 | |
d9a64523 A |
428 | kmodInfo = theKext->kmod_info; |
429 | if (!kmodInfo || !kmodInfo->address) { | |
430 | result = kOSKextReturnInvalidArgument; | |
431 | goto finish; | |
432 | } | |
433 | header = (kernel_mach_header_t *)kmodInfo->address; | |
b0d623f7 | 434 | |
d9a64523 A |
435 | if (theKext->flags.builtin) { |
436 | header = (kernel_mach_header_t *)g_kernel_kmod_info.address; | |
437 | textStart = kmodInfo->address; | |
438 | textEnd = textStart + kmodInfo->size; | |
439 | sectionNames = gOSStructorSectionNames[kOSSectionNamesBuiltinKext]; | |
440 | } | |
441 | } else { | |
442 | kmodInfo = &g_kernel_kmod_info; | |
443 | header = (kernel_mach_header_t *)kmodInfo->address; | |
b0d623f7 A |
444 | } |
445 | ||
b0d623f7 A |
446 | /* Tell the meta class system that we are starting the load |
447 | */ | |
448 | metaHandle = OSMetaClass::preModLoad(kmodInfo->name); | |
1c79356b | 449 | assert(metaHandle); |
b0d623f7 A |
450 | if (!metaHandle) { |
451 | goto finish; | |
452 | } | |
1c79356b | 453 | |
b0d623f7 | 454 | /* NO GOTO PAST HERE. */ |
1c79356b | 455 | |
b0d623f7 | 456 | /* Scan the header for all constructor sections, in any |
1c79356b A |
457 | * segment, and invoke the constructors within those sections. |
458 | */ | |
459 | for (segment = firstsegfromheader(header); | |
b0d623f7 | 460 | segment != NULL && load_success; |
d9a64523 A |
461 | segment = nextsegfromheader(header, segment)) |
462 | { | |
1c79356b A |
463 | /* Record the current segment in the event of a failure. |
464 | */ | |
465 | failure_segment = segment; | |
d9a64523 A |
466 | load_success = OSRuntimeCallStructorsInSection( |
467 | theKext, kmodInfo, metaHandle, segment, | |
468 | sectionNames[kOSSectionNameInitializer], | |
469 | textStart, textEnd); | |
1c79356b A |
470 | } /* for (segment...) */ |
471 | ||
b0d623f7 A |
472 | /* We failed so call all of the destructors. We must do this before |
473 | * calling OSMetaClass::postModLoad() as the OSMetaClass destructors | |
474 | * will alter state (in the metaHandle) used by that function. | |
475 | */ | |
1c79356b A |
476 | if (!load_success) { |
477 | ||
b0d623f7 | 478 | /* Scan the header for all destructor sections, in any |
1c79356b A |
479 | * segment, and invoke the constructors within those sections. |
480 | */ | |
481 | for (segment = firstsegfromheader(header); | |
482 | segment != failure_segment && segment != 0; | |
b0d623f7 | 483 | segment = nextsegfromheader(header, segment)) { |
1c79356b | 484 | |
d9a64523 A |
485 | OSRuntimeCallStructorsInSection(theKext, kmodInfo, NULL, segment, |
486 | sectionNames[kOSSectionNameFinalizer], textStart, textEnd); | |
1c79356b A |
487 | |
488 | } /* for (segment...) */ | |
489 | } | |
490 | ||
b0d623f7 A |
491 | /* Now, regardless of success so far, do the post-init registration |
492 | * and cleanup. If we had to call the unloadCPP function, static | |
493 | * destructors have removed classes from the stalled list so no | |
494 | * metaclasses will actually be registered. | |
495 | */ | |
496 | result = OSMetaClass::postModLoad(metaHandle); | |
497 | ||
498 | /* If we've otherwise been fine up to now, but OSMetaClass::postModLoad() | |
499 | * fails (typically due to a duplicate class), tear down all the C++ | |
500 | * stuff from the kext. This isn't necessary for libkern/OSMetaClass stuff, | |
501 | * but may be necessary for other C++ code. We ignore the return value | |
502 | * because it's only a fail when there are existing instances of libkern | |
503 | * classes, and there had better not be any created on the C++ init path. | |
504 | */ | |
505 | if (load_success && result != KMOD_RETURN_SUCCESS) { | |
d9a64523 | 506 | (void)OSRuntimeFinalizeCPP(theKext); //kmodInfo, sectionNames, textStart, textEnd); |
b0d623f7 A |
507 | } |
508 | ||
509 | if (theKext && load_success && result == KMOD_RETURN_SUCCESS) { | |
510 | theKext->setCPPInitialized(true); | |
511 | } | |
512 | finish: | |
b0d623f7 | 513 | return result; |
1c79356b A |
514 | } |
515 | ||
b0d623f7 | 516 | /********************************************************************* |
d9a64523 | 517 | Unload a kernel segment. |
b0d623f7 | 518 | *********************************************************************/ |
2d21ac55 | 519 | |
d9a64523 A |
520 | void |
521 | OSRuntimeUnloadCPPForSegment( | |
522 | kernel_segment_command_t * segment) | |
1c79356b | 523 | { |
d9a64523 A |
524 | OSRuntimeCallStructorsInSection(NULL, &g_kernel_kmod_info, NULL, segment, |
525 | gOSStructorSectionNames[kOSSectionNamesDefault][kOSSectionNameFinalizer], 0, 0); | |
1c79356b A |
526 | } |
527 | ||
b0d623f7 A |
528 | #if PRAGMA_MARK |
529 | #pragma mark C++ Allocators & Deallocators | |
530 | #endif /* PRAGMA_MARK */ | |
531 | /********************************************************************* | |
532 | * C++ Allocators & Deallocators | |
533 | *********************************************************************/ | |
534 | void * | |
535 | operator new(size_t size) | |
1c79356b A |
536 | { |
537 | void * result; | |
538 | ||
b0d623f7 A |
539 | result = (void *) kern_os_malloc(size); |
540 | return result; | |
1c79356b A |
541 | } |
542 | ||
b0d623f7 A |
543 | void |
544 | operator delete(void * addr) | |
3e170ce0 A |
545 | #if __cplusplus >= 201103L |
546 | noexcept | |
547 | #endif | |
b0d623f7 A |
548 | { |
549 | kern_os_free(addr); | |
550 | return; | |
551 | } | |
552 | ||
553 | void * | |
554 | operator new[](unsigned long sz) | |
555 | { | |
556 | if (sz == 0) sz = 1; | |
557 | return kern_os_malloc(sz); | |
558 | } | |
559 | ||
560 | void | |
561 | operator delete[](void * ptr) | |
3e170ce0 A |
562 | #if __cplusplus >= 201103L |
563 | noexcept | |
564 | #endif | |
b0d623f7 A |
565 | { |
566 | if (ptr) { | |
567 | kern_os_free(ptr); | |
568 | } | |
569 | return; | |
570 | } | |
571 | ||
572 | /* PR-6481964 - The compiler is going to check for size overflows in calls to | |
573 | * new[], and if there is an overflow, it will call __throw_length_error. | |
574 | * This is an unrecoverable error by the C++ standard, so we must panic here. | |
575 | * | |
576 | * We have to put the function inside the std namespace because of how the | |
577 | * compiler expects the name to be mangled. | |
578 | */ | |
579 | namespace std { | |
580 | ||
581 | void | |
582 | __throw_length_error(const char *msg __unused) | |
1c79356b | 583 | { |
b0d623f7 | 584 | panic("Size of array created by new[] has overflowed"); |
1c79356b A |
585 | } |
586 | ||
b0d623f7 | 587 | }; |