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