]> git.saurik.com Git - apple/xnu.git/blame - libkern/c++/OSRuntime.cpp
xnu-792.6.56.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 *
ff6e181a
A
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.
1c79356b 12 *
ff6e181a
A
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
1c79356b
A
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
ff6e181a
A
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.
1c79356b
A
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
38struct mach_header;
39
40#include <mach/mach_types.h>
41#include <mach-o/mach_header.h>
42#include <stdarg.h>
43
44#if OSALLOCDEBUG
45extern int debug_iomalloc_size;
46#endif
47
1c79356b
A
48struct _mhead {
49 size_t mlen;
50 char dat[0];
51};
52
53void *kern_os_malloc(
54 size_t size)
55{
9bccf70c
A
56 struct _mhead *mem;
57 size_t memsize = sizeof (*mem) + size ;
1c79356b
A
58
59 if (size == 0)
60 return (0);
61
9bccf70c 62 mem = (struct _mhead *)kalloc(memsize);
1c79356b
A
63 if (!mem)
64 return (0);
65
66#if OSALLOCDEBUG
67 debug_iomalloc_size += memsize;
68#endif
69
9bccf70c 70 mem->mlen = memsize;
91447636 71 bzero( mem->dat, size);
1c79356b 72
9bccf70c 73 return (mem->dat);
1c79356b
A
74}
75
76void 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
91447636 93 kfree(hdr, hdr->mlen);
1c79356b
A
94#endif
95}
96
97void *kern_os_realloc(
98 void *addr,
99 size_t nsize)
100{
101 struct _mhead *ohdr;
9bccf70c 102 struct _mhead *nmem;
1c79356b
A
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
9bccf70c
A
118 nmemsize = sizeof (*nmem) + nsize ;
119 nmem = (struct _mhead *) kalloc(nmemsize);
1c79356b
A
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
9bccf70c 129 nmem->mlen = nmemsize;
1c79356b 130 if (nsize > osize)
9bccf70c
A
131 (void) memset(&nmem->dat[osize], 0, nsize - osize);
132 (void) memcpy(nmem->dat, ohdr->dat,
1c79356b 133 (nsize > osize) ? osize : nsize);
91447636 134 kfree(ohdr, ohdr->mlen);
1c79356b 135
9bccf70c 136 return (nmem->dat);
1c79356b
A
137}
138
139size_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
9bccf70c
A
151#if __GNUC__ >= 3
152void __cxa_pure_virtual( void ) { panic(__FUNCTION__); }
153#else
1c79356b 154void __pure_virtual( void ) { panic(__FUNCTION__); }
9bccf70c 155#endif
1c79356b
A
156
157typedef void (*structor_t)(void);
158
91447636
A
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.
162void
163OSRuntimeUnloadCPPForSegment(struct segment_command * segment) {
1c79356b
A
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
91447636 187// This function will only operate on 32 bit kmods
1c79356b
A
188void 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
210kern_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
91447636 230// This function will only operate on 32 bit kmods
1c79356b
A
231kern_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
319static KMOD_LIB_DECL(__kernel__, 0);
320void 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
333void * operator new( size_t size)
334{
335 void * result;
336
337 result = (void *) kern_os_malloc( size);
1c79356b
A
338 return( result);
339}
340
341void operator delete( void * addr)
342{
343 kern_os_free( addr);
344}
345