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