]> git.saurik.com Git - apple/xnu.git/blob - libkern/c++/OSRuntime.cpp
xnu-792.12.6.tar.gz
[apple/xnu.git] / libkern / c++ / OSRuntime.cpp
1 /*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_OSREFERENCE_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. The rights granted to you under the
10 * License may not be used to create, or enable the creation or
11 * redistribution of, unlawful or unlicensed copies of an Apple operating
12 * system, or to circumvent, violate, or enable the circumvention or
13 * violation of, any terms of an Apple operating system software license
14 * agreement.
15 *
16 * Please obtain a copy of the License at
17 * http://www.opensource.apple.com/apsl/ and read it before using this
18 * file.
19 *
20 * The Original Code and all software distributed under the License are
21 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
22 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
23 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
25 * Please see the License for the specific language governing rights and
26 * limitations under the License.
27 *
28 * @APPLE_LICENSE_OSREFERENCE_HEADER_END@
29 */
30 /*
31 * Copyright (c) 1997 Apple Computer, Inc.
32 *
33 */
34 #include <libkern/c++/OSMetaClass.h>
35 #include <libkern/c++/OSLib.h>
36 #include <libkern/c++/OSSymbol.h>
37 #include <libkern/c++/OSBoolean.h>
38
39 #include <sys/cdefs.h>
40
41 __BEGIN_DECLS
42
43 #include <string.h>
44
45 struct mach_header;
46
47 #include <mach/mach_types.h>
48 #include <mach-o/mach_header.h>
49 #include <stdarg.h>
50
51 #if OSALLOCDEBUG
52 extern int debug_iomalloc_size;
53 #endif
54
55 struct _mhead {
56 size_t mlen;
57 char dat[0];
58 };
59
60 void *kern_os_malloc(
61 size_t size)
62 {
63 struct _mhead *mem;
64 size_t memsize = sizeof (*mem) + size ;
65
66 if (size == 0)
67 return (0);
68
69 mem = (struct _mhead *)kalloc(memsize);
70 if (!mem)
71 return (0);
72
73 #if OSALLOCDEBUG
74 debug_iomalloc_size += memsize;
75 #endif
76
77 mem->mlen = memsize;
78 bzero( mem->dat, size);
79
80 return (mem->dat);
81 }
82
83 void kern_os_free(
84 void *addr)
85 {
86 struct _mhead *hdr;
87
88 if (!addr)
89 return;
90
91 hdr = (struct _mhead *) addr; hdr--;
92
93 #if OSALLOCDEBUG
94 debug_iomalloc_size -= hdr->mlen;
95 #endif
96
97 #if 0
98 memset((vm_offset_t)hdr, 0xbb, hdr->mlen);
99 #else
100 kfree(hdr, hdr->mlen);
101 #endif
102 }
103
104 void *kern_os_realloc(
105 void *addr,
106 size_t nsize)
107 {
108 struct _mhead *ohdr;
109 struct _mhead *nmem;
110 size_t nmemsize, osize;
111
112 if (!addr)
113 return (kern_os_malloc(nsize));
114
115 ohdr = (struct _mhead *) addr; ohdr--;
116 osize = ohdr->mlen - sizeof (*ohdr);
117 if (nsize == osize)
118 return (addr);
119
120 if (nsize == 0) {
121 kern_os_free(addr);
122 return (0);
123 }
124
125 nmemsize = sizeof (*nmem) + nsize ;
126 nmem = (struct _mhead *) kalloc(nmemsize);
127 if (!nmem){
128 kern_os_free(addr);
129 return (0);
130 }
131
132 #if OSALLOCDEBUG
133 debug_iomalloc_size += (nmemsize - ohdr->mlen);
134 #endif
135
136 nmem->mlen = nmemsize;
137 if (nsize > osize)
138 (void) memset(&nmem->dat[osize], 0, nsize - osize);
139 (void) memcpy(nmem->dat, ohdr->dat,
140 (nsize > osize) ? osize : nsize);
141 kfree(ohdr, ohdr->mlen);
142
143 return (nmem->dat);
144 }
145
146 size_t kern_os_malloc_size(
147 void *addr)
148 {
149 struct _mhead *hdr;
150
151 if (!addr)
152 return( 0);
153
154 hdr = (struct _mhead *) addr; hdr--;
155 return( hdr->mlen - sizeof (struct _mhead));
156 }
157
158 #if __GNUC__ >= 3
159 void __cxa_pure_virtual( void ) { panic(__FUNCTION__); }
160 #else
161 void __pure_virtual( void ) { panic(__FUNCTION__); }
162 #endif
163
164 typedef void (*structor_t)(void);
165
166 // Given a pointer to a 32 bit mach object segment, iterate the segment to
167 // obtain a 32 bit destructor section for C++ objects, and call each of the
168 // destructors there.
169 void
170 OSRuntimeUnloadCPPForSegment(struct segment_command * segment) {
171
172 struct section * section;
173
174 for (section = firstsect(segment);
175 section != 0;
176 section = nextsect(segment, section)) {
177
178 if (strcmp(section->sectname, "__destructor") == 0) {
179 structor_t * destructors = (structor_t *)section->addr;
180
181 if (destructors) {
182 int num_destructors = section->size / sizeof(structor_t);
183
184 for (int i = 0; i < num_destructors; i++) {
185 (*destructors[i])();
186 }
187 } /* if (destructors) */
188 } /* if (strcmp...) */
189 } /* for (section...) */
190
191 return;
192 }
193
194 // This function will only operate on 32 bit kmods
195 void OSRuntimeUnloadCPP(kmod_info_t *ki, void *)
196 {
197 if (ki && ki->address) {
198
199 struct segment_command * segment;
200 struct mach_header *header;
201
202 OSSymbol::checkForPageUnload((void *) ki->address,
203 (void *) (ki->address + ki->size));
204
205 header = (struct mach_header *)ki->address;
206 segment = firstsegfromheader(header);
207
208 for (segment = firstsegfromheader(header);
209 segment != 0;
210 segment = nextseg(segment)) {
211
212 OSRuntimeUnloadCPPForSegment(segment);
213 }
214 }
215 }
216
217 kern_return_t OSRuntimeFinalizeCPP(kmod_info_t *ki, void *)
218 {
219 void *metaHandle;
220
221 if (OSMetaClass::modHasInstance(ki->name)) {
222 // @@@ gvdl should have a verbose flag
223 printf("Can't unload %s due to -\n", ki->name);
224 OSMetaClass::reportModInstances(ki->name);
225 return kOSMetaClassHasInstances;
226 }
227
228 // Tell the meta class system that we are starting to unload
229 metaHandle = OSMetaClass::preModLoad(ki->name);
230 OSRuntimeUnloadCPP(ki, 0); // Do the actual unload
231 (void) OSMetaClass::postModLoad(metaHandle);
232
233 return KMOD_RETURN_SUCCESS;
234 }
235
236 // Functions used by the extenTools/kmod library project
237 // This function will only operate on 32 bit kmods
238 kern_return_t OSRuntimeInitializeCPP(kmod_info_t *ki, void *)
239 {
240 struct mach_header *header;
241 void *metaHandle;
242 bool load_success;
243 struct segment_command * segment;
244 struct segment_command * failure_segment;
245
246 if (!ki || !ki->address)
247 return KMOD_RETURN_FAILURE;
248 else
249 header = (struct mach_header *) ki->address;
250
251 // Tell the meta class system that we are starting the load
252 metaHandle = OSMetaClass::preModLoad(ki->name);
253 assert(metaHandle);
254 if (!metaHandle)
255 return KMOD_RETURN_FAILURE;
256
257 load_success = true;
258 failure_segment = 0;
259
260 /* Scan the header for all sections named "__constructor", in any
261 * segment, and invoke the constructors within those sections.
262 */
263 for (segment = firstsegfromheader(header);
264 segment != 0 && load_success;
265 segment = nextseg(segment)) {
266
267 struct section * section;
268
269 /* Record the current segment in the event of a failure.
270 */
271 failure_segment = segment;
272
273 for (section = firstsect(segment);
274 section != 0 && load_success;
275 section = nextsect(segment, section)) {
276
277 if (strcmp(section->sectname, "__constructor") == 0) {
278 structor_t * constructors = (structor_t *)section->addr;
279
280 if (constructors) {
281 // FIXME: can we break here under the assumption that
282 // section names are unique within a segment?
283
284 int num_constructors = section->size / sizeof(structor_t);
285 int hit_null_constructor = 0;
286
287 for (int i = 0;
288 i < num_constructors &&
289 OSMetaClass::checkModLoad(metaHandle);
290 i++) {
291
292 if (constructors[i]) {
293 (*constructors[i])();
294 } else if (!hit_null_constructor) {
295 hit_null_constructor = 1;
296 printf("Error! Null constructor in segment %s.\n",
297 section->segname);
298 }
299 }
300 load_success = OSMetaClass::checkModLoad(metaHandle);
301
302 } /* if (constructors) */
303 } /* if (strcmp...) */
304 } /* for (section...) */
305 } /* for (segment...) */
306
307
308 // We failed so call all of the destructors
309 if (!load_success) {
310
311 /* Scan the header for all sections named "__constructor", in any
312 * segment, and invoke the constructors within those sections.
313 */
314 for (segment = firstsegfromheader(header);
315 segment != failure_segment && segment != 0;
316 segment = nextseg(segment)) {
317
318 OSRuntimeUnloadCPPForSegment(segment);
319
320 } /* for (segment...) */
321 }
322
323 return OSMetaClass::postModLoad(metaHandle);
324 }
325
326 static KMOD_LIB_DECL(__kernel__, 0);
327 void OSlibkernInit(void)
328 {
329 vm_address_t *headerArray = (vm_address_t *) getmachheaders();
330
331 KMOD_INFO_NAME.address = headerArray[0]; assert(!headerArray[1]);
332 if (kOSReturnSuccess != OSRuntimeInitializeCPP(&KMOD_INFO_NAME, 0))
333 panic("OSRuntime: C++ runtime failed to initialize");
334
335 OSBoolean::initialize();
336 }
337
338 __END_DECLS
339
340 void * operator new( size_t size)
341 {
342 void * result;
343
344 result = (void *) kern_os_malloc( size);
345 return( result);
346 }
347
348 void operator delete( void * addr)
349 {
350 kern_os_free( addr);
351 }
352