]>
git.saurik.com Git - apple/xnu.git/blob - libkern/c++/OSRuntime.cpp
c2d1908f16b796bf486181ceb0e572b31e3e1cfe
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
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. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 * Copyright (c) 1997 Apple Computer, Inc.
32 #include <libkern/c++/OSMetaClass.h>
33 #include <libkern/c++/OSLib.h>
34 #include <libkern/c++/OSSymbol.h>
35 #include <libkern/c++/OSBoolean.h>
37 #include <sys/cdefs.h>
45 #include <mach/mach_types.h>
46 #include <mach-o/mach_header.h>
50 extern int debug_iomalloc_size
;
62 size_t memsize
= sizeof (*mem
) + size
;
67 mem
= (struct _mhead
*)kalloc(memsize
);
72 debug_iomalloc_size
+= memsize
;
76 bzero( mem
->dat
, size
);
89 hdr
= (struct _mhead
*) addr
; hdr
--;
92 debug_iomalloc_size
-= hdr
->mlen
;
96 memset((vm_offset_t
)hdr
, 0xbb, hdr
->mlen
);
98 kfree(hdr
, hdr
->mlen
);
102 void *kern_os_realloc(
108 size_t nmemsize
, osize
;
111 return (kern_os_malloc(nsize
));
113 ohdr
= (struct _mhead
*) addr
; ohdr
--;
114 osize
= ohdr
->mlen
- sizeof (*ohdr
);
123 nmemsize
= sizeof (*nmem
) + nsize
;
124 nmem
= (struct _mhead
*) kalloc(nmemsize
);
131 debug_iomalloc_size
+= (nmemsize
- ohdr
->mlen
);
134 nmem
->mlen
= nmemsize
;
136 (void) memset(&nmem
->dat
[osize
], 0, nsize
- osize
);
137 (void) memcpy(nmem
->dat
, ohdr
->dat
,
138 (nsize
> osize
) ? osize
: nsize
);
139 kfree(ohdr
, ohdr
->mlen
);
144 size_t kern_os_malloc_size(
152 hdr
= (struct _mhead
*) addr
; hdr
--;
153 return( hdr
->mlen
- sizeof (struct _mhead
));
157 void __cxa_pure_virtual( void ) { panic(__FUNCTION__
); }
159 void __pure_virtual( void ) { panic(__FUNCTION__
); }
162 typedef void (*structor_t
)(void);
164 // Given a pointer to a 32 bit mach object segment, iterate the segment to
165 // obtain a 32 bit destructor section for C++ objects, and call each of the
166 // destructors there.
168 OSRuntimeUnloadCPPForSegment(struct segment_command
* segment
) {
170 struct section
* section
;
172 for (section
= firstsect(segment
);
174 section
= nextsect(segment
, section
)) {
176 if (strcmp(section
->sectname
, "__destructor") == 0) {
177 structor_t
* destructors
= (structor_t
*)section
->addr
;
180 int num_destructors
= section
->size
/ sizeof(structor_t
);
182 for (int i
= 0; i
< num_destructors
; i
++) {
185 } /* if (destructors) */
186 } /* if (strcmp...) */
187 } /* for (section...) */
192 // This function will only operate on 32 bit kmods
193 void OSRuntimeUnloadCPP(kmod_info_t
*ki
, void *)
195 if (ki
&& ki
->address
) {
197 struct segment_command
* segment
;
198 struct mach_header
*header
;
200 OSSymbol::checkForPageUnload((void *) ki
->address
,
201 (void *) (ki
->address
+ ki
->size
));
203 header
= (struct mach_header
*)ki
->address
;
204 segment
= firstsegfromheader(header
);
206 for (segment
= firstsegfromheader(header
);
208 segment
= nextseg(segment
)) {
210 OSRuntimeUnloadCPPForSegment(segment
);
215 kern_return_t
OSRuntimeFinalizeCPP(kmod_info_t
*ki
, void *)
219 if (OSMetaClass::modHasInstance(ki
->name
)) {
220 // @@@ gvdl should have a verbose flag
221 printf("Can't unload %s due to -\n", ki
->name
);
222 OSMetaClass::reportModInstances(ki
->name
);
223 return kOSMetaClassHasInstances
;
226 // Tell the meta class system that we are starting to unload
227 metaHandle
= OSMetaClass::preModLoad(ki
->name
);
228 OSRuntimeUnloadCPP(ki
, 0); // Do the actual unload
229 (void) OSMetaClass::postModLoad(metaHandle
);
231 return KMOD_RETURN_SUCCESS
;
234 // Functions used by the extenTools/kmod library project
235 // This function will only operate on 32 bit kmods
236 kern_return_t
OSRuntimeInitializeCPP(kmod_info_t
*ki
, void *)
238 struct mach_header
*header
;
241 struct segment_command
* segment
;
242 struct segment_command
* failure_segment
;
244 if (!ki
|| !ki
->address
)
245 return KMOD_RETURN_FAILURE
;
247 header
= (struct mach_header
*) ki
->address
;
249 // Tell the meta class system that we are starting the load
250 metaHandle
= OSMetaClass::preModLoad(ki
->name
);
253 return KMOD_RETURN_FAILURE
;
258 /* Scan the header for all sections named "__constructor", in any
259 * segment, and invoke the constructors within those sections.
261 for (segment
= firstsegfromheader(header
);
262 segment
!= 0 && load_success
;
263 segment
= nextseg(segment
)) {
265 struct section
* section
;
267 /* Record the current segment in the event of a failure.
269 failure_segment
= segment
;
271 for (section
= firstsect(segment
);
272 section
!= 0 && load_success
;
273 section
= nextsect(segment
, section
)) {
275 if (strcmp(section
->sectname
, "__constructor") == 0) {
276 structor_t
* constructors
= (structor_t
*)section
->addr
;
279 // FIXME: can we break here under the assumption that
280 // section names are unique within a segment?
282 int num_constructors
= section
->size
/ sizeof(structor_t
);
283 int hit_null_constructor
= 0;
286 i
< num_constructors
&&
287 OSMetaClass::checkModLoad(metaHandle
);
290 if (constructors
[i
]) {
291 (*constructors
[i
])();
292 } else if (!hit_null_constructor
) {
293 hit_null_constructor
= 1;
294 printf("Error! Null constructor in segment %s.\n",
298 load_success
= OSMetaClass::checkModLoad(metaHandle
);
300 } /* if (constructors) */
301 } /* if (strcmp...) */
302 } /* for (section...) */
303 } /* for (segment...) */
306 // We failed so call all of the destructors
309 /* Scan the header for all sections named "__constructor", in any
310 * segment, and invoke the constructors within those sections.
312 for (segment
= firstsegfromheader(header
);
313 segment
!= failure_segment
&& segment
!= 0;
314 segment
= nextseg(segment
)) {
316 OSRuntimeUnloadCPPForSegment(segment
);
318 } /* for (segment...) */
321 return OSMetaClass::postModLoad(metaHandle
);
324 static KMOD_LIB_DECL(__kernel__
, 0);
325 void OSlibkernInit(void)
327 vm_address_t
*headerArray
= (vm_address_t
*) getmachheaders();
329 KMOD_INFO_NAME
.address
= headerArray
[0]; assert(!headerArray
[1]);
330 if (kOSReturnSuccess
!= OSRuntimeInitializeCPP(&KMOD_INFO_NAME
, 0))
331 panic("OSRuntime: C++ runtime failed to initialize");
333 OSBoolean::initialize();
338 void * operator new( size_t size
)
342 result
= (void *) kern_os_malloc( size
);
346 void operator delete( void * addr
)