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