]> git.saurik.com Git - apple/xnu.git/blame - libkern/c++/OSRuntime.cpp
xnu-344.21.73.tar.gz
[apple/xnu.git] / libkern / c++ / OSRuntime.cpp
CommitLineData
1c79356b
A
1/*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
d7e50217 6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
1c79356b 7 *
d7e50217
A
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
1c79356b
A
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
d7e50217
A
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.
1c79356b
A
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
40struct mach_header;
41
42#include <mach/mach_types.h>
43#include <mach-o/mach_header.h>
44#include <stdarg.h>
45
46#if OSALLOCDEBUG
47extern int debug_iomalloc_size;
48#endif
49
1c79356b
A
50struct _mhead {
51 size_t mlen;
52 char dat[0];
53};
54
55void *kern_os_malloc(
56 size_t size)
57{
9bccf70c
A
58 struct _mhead *mem;
59 size_t memsize = sizeof (*mem) + size ;
1c79356b
A
60
61 if (size == 0)
62 return (0);
63
9bccf70c 64 mem = (struct _mhead *)kalloc(memsize);
1c79356b
A
65 if (!mem)
66 return (0);
67
68#if OSALLOCDEBUG
69 debug_iomalloc_size += memsize;
70#endif
71
9bccf70c
A
72 mem->mlen = memsize;
73 (void) memset(mem->dat, 0, size);
1c79356b 74
9bccf70c 75 return (mem->dat);
1c79356b
A
76}
77
78void 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
99void *kern_os_realloc(
100 void *addr,
101 size_t nsize)
102{
103 struct _mhead *ohdr;
9bccf70c 104 struct _mhead *nmem;
1c79356b
A
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
9bccf70c
A
120 nmemsize = sizeof (*nmem) + nsize ;
121 nmem = (struct _mhead *) kalloc(nmemsize);
1c79356b
A
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
9bccf70c 131 nmem->mlen = nmemsize;
1c79356b 132 if (nsize > osize)
9bccf70c
A
133 (void) memset(&nmem->dat[osize], 0, nsize - osize);
134 (void) memcpy(nmem->dat, ohdr->dat,
1c79356b
A
135 (nsize > osize) ? osize : nsize);
136 kfree((vm_offset_t)ohdr, ohdr->mlen);
137
9bccf70c 138 return (nmem->dat);
1c79356b
A
139}
140
141size_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
9bccf70c
A
153#if __GNUC__ >= 3
154void __cxa_pure_virtual( void ) { panic(__FUNCTION__); }
155#else
1c79356b 156void __pure_virtual( void ) { panic(__FUNCTION__); }
9bccf70c 157#endif
1c79356b
A
158
159typedef void (*structor_t)(void);
160
161void 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
185void 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
207kern_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
227kern_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
315static KMOD_LIB_DECL(__kernel__, 0);
316void 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
329void * 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
339void operator delete( void * addr)
340{
341 kern_os_free( addr);
342}
343