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