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 #define MDECL(reqlen) \ 48 typedef union { \ 49 struct _mhead hdr; \ 50 char _m[(reqlen) + sizeof (struct _mhead)]; \ 51 } hdr_t; \ 52 hdr_t 53 54 struct _mhead { 55 size_t mlen; 56 char dat[0]; 57 }; 58 59 void *kern_os_malloc( 60 size_t size) 61 { 62 MDECL(size) *mem; 63 size_t memsize = sizeof (*mem); 64 65 if (size == 0) 66 return (0); 67 68 mem = (hdr_t *)kalloc(memsize); 69 if (!mem) 70 return (0); 71 72 #if OSALLOCDEBUG 73 debug_iomalloc_size += memsize; 74 #endif 75 76 mem->hdr.mlen = memsize; 77 (void) memset(mem->hdr.dat, 0, size); 78 79 return (mem->hdr.dat); 80 } 81 82 void kern_os_free( 83 void *addr) 84 { 85 struct _mhead *hdr; 86 87 if (!addr) 88 return; 89 90 hdr = (struct _mhead *) addr; hdr--; 91 92 #if OSALLOCDEBUG 93 debug_iomalloc_size -= hdr->mlen; 94 #endif 95 96 #if 0 97 memset((vm_offset_t)hdr, 0xbb, hdr->mlen); 98 #else 99 kfree((vm_offset_t)hdr, hdr->mlen); 100 #endif 101 } 102 103 void *kern_os_realloc( 104 void *addr, 105 size_t nsize) 106 { 107 struct _mhead *ohdr; 108 MDECL(nsize) *nmem; 109 size_t nmemsize, osize; 110 111 if (!addr) 112 return (kern_os_malloc(nsize)); 113 114 ohdr = (struct _mhead *) addr; ohdr--; 115 osize = ohdr->mlen - sizeof (*ohdr); 116 if (nsize == osize) 117 return (addr); 118 119 if (nsize == 0) { 120 kern_os_free(addr); 121 return (0); 122 } 123 124 nmemsize = sizeof (*nmem); 125 nmem = (hdr_t *) kalloc(nmemsize); 126 if (!nmem){ 127 kern_os_free(addr); 128 return (0); 129 } 130 131 #if OSALLOCDEBUG 132 debug_iomalloc_size += (nmemsize - ohdr->mlen); 133 #endif 134 135 nmem->hdr.mlen = nmemsize; 136 if (nsize > osize) 137 (void) memset(&nmem->hdr.dat[osize], 0, nsize - osize); 138 (void) memcpy(nmem->hdr.dat, ohdr->dat, 139 (nsize > osize) ? osize : nsize); 140 kfree((vm_offset_t)ohdr, ohdr->mlen); 141 142 return (nmem->hdr.dat); 143 } 144 145 size_t kern_os_malloc_size( 146 void *addr) 147 { 148 struct _mhead *hdr; 149 150 if (!addr) 151 return( 0); 152 153 hdr = (struct _mhead *) addr; hdr--; 154 return( hdr->mlen - sizeof (struct _mhead)); 155 } 156 157 void __pure_virtual( void ) { panic(__FUNCTION__); } 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