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 bzero( mem->dat, 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(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(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 // Given a pointer to a 32 bit mach object segment, iterate the segment to 159 // obtain a 32 bit destructor section for C++ objects, and call each of the 160 // destructors there. 161 void 162 OSRuntimeUnloadCPPForSegment(struct segment_command * segment) { 163 164 struct section * section; 165 166 for (section = firstsect(segment); 167 section != 0; 168 section = nextsect(segment, section)) { 169 170 if (strcmp(section->sectname, "__destructor") == 0) { 171 structor_t * destructors = (structor_t *)section->addr; 172 173 if (destructors) { 174 int num_destructors = section->size / sizeof(structor_t); 175 176 for (int i = 0; i < num_destructors; i++) { 177 (*destructors[i])(); 178 } 179 } /* if (destructors) */ 180 } /* if (strcmp...) */ 181 } /* for (section...) */ 182 183 return; 184 } 185 186 // This function will only operate on 32 bit kmods 187 void OSRuntimeUnloadCPP(kmod_info_t *ki, void *) 188 { 189 if (ki && ki->address) { 190 191 struct segment_command * segment; 192 struct mach_header *header; 193 194 OSSymbol::checkForPageUnload((void *) ki->address, 195 (void *) (ki->address + ki->size)); 196 197 header = (struct mach_header *)ki->address; 198 segment = firstsegfromheader(header); 199 200 for (segment = firstsegfromheader(header); 201 segment != 0; 202 segment = nextseg(segment)) { 203 204 OSRuntimeUnloadCPPForSegment(segment); 205 } 206 } 207 } 208 209 kern_return_t OSRuntimeFinalizeCPP(kmod_info_t *ki, void *) 210 { 211 void *metaHandle; 212 213 if (OSMetaClass::modHasInstance(ki->name)) { 214 // @@@ gvdl should have a verbose flag 215 printf("Can't unload %s due to -\n", ki->name); 216 OSMetaClass::reportModInstances(ki->name); 217 return kOSMetaClassHasInstances; 218 } 219 220 // Tell the meta class system that we are starting to unload 221 metaHandle = OSMetaClass::preModLoad(ki->name); 222 OSRuntimeUnloadCPP(ki, 0); // Do the actual unload 223 (void) OSMetaClass::postModLoad(metaHandle); 224 225 return KMOD_RETURN_SUCCESS; 226 } 227 228 // Functions used by the extenTools/kmod library project 229 // This function will only operate on 32 bit kmods 230 kern_return_t OSRuntimeInitializeCPP(kmod_info_t *ki, void *) 231 { 232 struct mach_header *header; 233 void *metaHandle; 234 bool load_success; 235 struct segment_command * segment; 236 struct segment_command * failure_segment; 237 238 if (!ki || !ki->address) 239 return KMOD_RETURN_FAILURE; 240 else 241 header = (struct mach_header *) ki->address; 242 243 // Tell the meta class system that we are starting the load 244 metaHandle = OSMetaClass::preModLoad(ki->name); 245 assert(metaHandle); 246 if (!metaHandle) 247 return KMOD_RETURN_FAILURE; 248 249 load_success = true; 250 failure_segment = 0; 251 252 /* Scan the header for all sections named "__constructor", in any 253 * segment, and invoke the constructors within those sections. 254 */ 255 for (segment = firstsegfromheader(header); 256 segment != 0 && load_success; 257 segment = nextseg(segment)) { 258 259 struct section * section; 260 261 /* Record the current segment in the event of a failure. 262 */ 263 failure_segment = segment; 264 265 for (section = firstsect(segment); 266 section != 0 && load_success; 267 section = nextsect(segment, section)) { 268 269 if (strcmp(section->sectname, "__constructor") == 0) { 270 structor_t * constructors = (structor_t *)section->addr; 271 272 if (constructors) { 273 // FIXME: can we break here under the assumption that 274 // section names are unique within a segment? 275 276 int num_constructors = section->size / sizeof(structor_t); 277 int hit_null_constructor = 0; 278 279 for (int i = 0; 280 i < num_constructors && 281 OSMetaClass::checkModLoad(metaHandle); 282 i++) { 283 284 if (constructors[i]) { 285 (*constructors[i])(); 286 } else if (!hit_null_constructor) { 287 hit_null_constructor = 1; 288 printf("Error! Null constructor in segment %s.\n", 289 section->segname); 290 } 291 } 292 load_success = OSMetaClass::checkModLoad(metaHandle); 293 294 } /* if (constructors) */ 295 } /* if (strcmp...) */ 296 } /* for (section...) */ 297 } /* for (segment...) */ 298 299 300 // We failed so call all of the destructors 301 if (!load_success) { 302 303 /* Scan the header for all sections named "__constructor", in any 304 * segment, and invoke the constructors within those sections. 305 */ 306 for (segment = firstsegfromheader(header); 307 segment != failure_segment && segment != 0; 308 segment = nextseg(segment)) { 309 310 OSRuntimeUnloadCPPForSegment(segment); 311 312 } /* for (segment...) */ 313 } 314 315 return OSMetaClass::postModLoad(metaHandle); 316 } 317 318 static KMOD_LIB_DECL(__kernel__, 0); 319 void OSlibkernInit(void) 320 { 321 vm_address_t *headerArray = (vm_address_t *) getmachheaders(); 322 323 KMOD_INFO_NAME.address = headerArray[0]; assert(!headerArray[1]); 324 if (kOSReturnSuccess != OSRuntimeInitializeCPP(&KMOD_INFO_NAME, 0)) 325 panic("OSRuntime: C++ runtime failed to initialize"); 326 327 OSBoolean::initialize(); 328 } 329 330 __END_DECLS 331 332 void * operator new( size_t size) 333 { 334 void * result; 335 336 result = (void *) kern_os_malloc( size); 337 return( result); 338 } 339 340 void operator delete( void * addr) 341 { 342 kern_os_free( addr); 343 } 344 345