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 344