1 /* 2 * Copyright (c) 2000-2006 Apple Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 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. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 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. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28 /* OSMetaClass.cpp created by gvdl on Fri 1998-11-17 */ 29 30 #include <string.h> 31 32 #include <libkern/OSReturn.h> 33 34 #include <libkern/c++/OSMetaClass.h> 35 #include <libkern/c++/OSObject.h> 36 #include <libkern/c++/OSKext.h> 37 38 #include <libkern/c++/OSCollectionIterator.h> 39 #include <libkern/c++/OSDictionary.h> 40 #include <libkern/c++/OSArray.h> 41 #include <libkern/c++/OSSet.h> 42 #include <libkern/c++/OSSymbol.h> 43 #include <libkern/c++/OSNumber.h> 44 #include <libkern/c++/OSSerialize.h> 45 46 #include <libkern/c++/OSLib.h> 47 #include <libkern/OSAtomic.h> 48 49 #include <IOKit/pwr_mgt/RootDomain.h> 50 #include <IOKit/IOMessage.h> 51 #include <IOKit/IOLib.h> 52 53 __BEGIN_DECLS 54 55 #include <sys/systm.h> 56 #include <mach/mach_types.h> 57 #include <kern/locks.h> 58 #include <kern/clock.h> 59 #include <kern/thread_call.h> 60 #include <kern/host.h> 61 #include <mach/mach_interface.h> 62 63 #if PRAGMA_MARK 64 #pragma mark Macros 65 #endif /* PRAGMA_MARK */ 66 /********************************************************************* 67 * Macros 68 *********************************************************************/ 69 #if OSALLOCDEBUG 70 extern int debug_container_malloc_size; 71 #define ACCUMSIZE(s) do { debug_container_malloc_size += (s); } while (0) 72 #else 73 #define ACCUMSIZE(s) 74 #endif /* OSALLOCDEBUG */ 75 76 __END_DECLS 77 78 #if PRAGMA_MARK 79 #pragma mark Internal constants & data structs 80 #endif /* PRAGMA_MARK */ 81 /********************************************************************* 82 * Internal constants & data structs 83 *********************************************************************/ 84 OSKextLogSpec kOSMetaClassLogSpec = 85 kOSKextLogErrorLevel | 86 kOSKextLogLoadFlag | 87 kOSKextLogKextBookkeepingFlag; 88 89 static enum { 90 kCompletedBootstrap = 0, 91 kNoDictionaries = 1, 92 kMakingDictionaries = 2 93 } sBootstrapState = kNoDictionaries; 94 95 static const int kClassCapacityIncrement = 40; 96 static const int kKModCapacityIncrement = 10; 97 static OSDictionary * sAllClassesDict; 98 IOLock * sAllClassesLock = NULL; 99 100 /* 101 * While loading a kext and running all its constructors to register 102 * all OSMetaClass classes, the classes are queued up here. Only one 103 * kext can be in flight at a time, guarded by sStalledClassesLock 104 */ 105 static struct StalledData { 106 const char * kextIdentifier; 107 OSReturn result; 108 unsigned int capacity; 109 unsigned int count; 110 OSMetaClass ** classes; 111 } * sStalled; 112 IOLock * sStalledClassesLock = NULL; 113 114 #if PRAGMA_MARK 115 #pragma mark OSMetaClassBase 116 #endif /* PRAGMA_MARK */ 117 /********************************************************************* 118 * OSMetaClassBase. 119 *********************************************************************/ 120 121 /********************************************************************* 122 * Reserved vtable functions. 123 *********************************************************************/ 124 #if SLOT_USED 125 void OSMetaClassBase::_RESERVEDOSMetaClassBase0() 126 { panic("OSMetaClassBase::_RESERVEDOSMetaClassBase%d called.", 0); } 127 void OSMetaClassBase::_RESERVEDOSMetaClassBase1() 128 { panic("OSMetaClassBase::_RESERVEDOSMetaClassBase%d called.", 1); } 129 void OSMetaClassBase::_RESERVEDOSMetaClassBase2() 130 { panic("OSMetaClassBase::_RESERVEDOSMetaClassBase%d called.", 2); } 131 #endif /* SLOT_USED */ 132 133 // As these slots are used move them up inside the #if above 134 void OSMetaClassBase::_RESERVEDOSMetaClassBase3() 135 { panic("OSMetaClassBase::_RESERVEDOSMetaClassBase%d called.", 3); } 136 void OSMetaClassBase::_RESERVEDOSMetaClassBase4() 137 { panic("OSMetaClassBase::_RESERVEDOSMetaClassBase%d called.", 4); } 138 void OSMetaClassBase::_RESERVEDOSMetaClassBase5() 139 { panic("OSMetaClassBase::_RESERVEDOSMetaClassBase%d called.", 5); } 140 void OSMetaClassBase::_RESERVEDOSMetaClassBase6() 141 { panic("OSMetaClassBase::_RESERVEDOSMetaClassBase%d called.", 6); } 142 143 /********************************************************************* 144 * These used to be inline in the header but gcc didn't believe us 145 * Now we MUST pull the inline out at least until the compiler is 146 * repaired. 147 * 148 * Helper inlines for runtime type preprocessor macros 149 *********************************************************************/ 150 151 /********************************************************************* 152 *********************************************************************/ 153 OSMetaClassBase * 154 OSMetaClassBase::safeMetaCast( 155 const OSMetaClassBase * me, 156 const OSMetaClass * toType) 157 { 158 return (me)? me->metaCast(toType) : 0; 159 } 160 161 /********************************************************************* 162 *********************************************************************/ 163 bool 164 OSMetaClassBase::checkTypeInst( 165 const OSMetaClassBase * inst, 166 const OSMetaClassBase * typeinst) 167 { 168 const OSMetaClass * toType = OSTypeIDInst(typeinst); 169 return typeinst && inst && (0 != inst->metaCast(toType)); 170 } 171 172 /********************************************************************* 173 *********************************************************************/ 174 void OSMetaClassBase:: 175 initialize() 176 { 177 sAllClassesLock = IOLockAlloc(); 178 sStalledClassesLock = IOLockAlloc(); 179 } 180 181 /********************************************************************* 182 * If you need this slot you had better setup an IOCTL style interface. 183 * 'Cause the whole kernel world depends on OSMetaClassBase and YOU 184 * CANT change the VTABLE size ever. 185 *********************************************************************/ 186 void 187 OSMetaClassBase::_RESERVEDOSMetaClassBase7() 188 { panic("OSMetaClassBase::_RESERVEDOSMetaClassBase%d called.", 7); } 189 190 /********************************************************************* 191 *********************************************************************/ 192 OSMetaClassBase::OSMetaClassBase() 193 { 194 } 195 196 /********************************************************************* 197 *********************************************************************/ 198 OSMetaClassBase::~OSMetaClassBase() 199 { 200 void ** thisVTable; 201 202 thisVTable = (void **) this; 203 *thisVTable = (void *) -1UL; 204 } 205 206 /********************************************************************* 207 *********************************************************************/ 208 bool 209 OSMetaClassBase::isEqualTo(const OSMetaClassBase * anObj) const 210 { 211 return this == anObj; 212 } 213 214 /********************************************************************* 215 *********************************************************************/ 216 OSMetaClassBase * 217 OSMetaClassBase::metaCast(const OSMetaClass * toMeta) const 218 { 219 return toMeta->checkMetaCast(this); 220 } 221 222 /********************************************************************* 223 *********************************************************************/ 224 OSMetaClassBase * 225 OSMetaClassBase::metaCast(const OSSymbol * toMetaSymb) const 226 { 227 return OSMetaClass::checkMetaCastWithName(toMetaSymb, this); 228 } 229 230 /********************************************************************* 231 *********************************************************************/ 232 OSMetaClassBase * 233 OSMetaClassBase::metaCast(const OSString * toMetaStr) const 234 { 235 const OSSymbol * tempSymb = OSSymbol::withString(toMetaStr); 236 OSMetaClassBase * ret = 0; 237 if (tempSymb) { 238 ret = metaCast(tempSymb); 239 tempSymb->release(); 240 } 241 return ret; 242 } 243 244 /********************************************************************* 245 *********************************************************************/ 246 OSMetaClassBase * 247 OSMetaClassBase::metaCast(const char * toMetaCStr) const 248 { 249 const OSSymbol * tempSymb = OSSymbol::withCString(toMetaCStr); 250 OSMetaClassBase * ret = 0; 251 if (tempSymb) { 252 ret = metaCast(tempSymb); 253 tempSymb->release(); 254 } 255 return ret; 256 } 257 258 #if PRAGMA_MARK 259 #pragma mark OSMetaClassMeta 260 #endif /* PRAGMA_MARK */ 261 /********************************************************************* 262 * OSMetaClassMeta - the bootstrap metaclass of OSMetaClass 263 *********************************************************************/ 264 class OSMetaClassMeta : public OSMetaClass 265 { 266 public: 267 OSMetaClassMeta(); 268 OSObject * alloc() const; 269 }; 270 OSMetaClassMeta::OSMetaClassMeta() 271 : OSMetaClass("OSMetaClass", 0, sizeof(OSMetaClass)) 272 { } 273 OSObject * OSMetaClassMeta::alloc() const { return 0; } 274 275 static OSMetaClassMeta sOSMetaClassMeta; 276 277 const OSMetaClass * const OSMetaClass::metaClass = &sOSMetaClassMeta; 278 const OSMetaClass * OSMetaClass::getMetaClass() const 279 { return &sOSMetaClassMeta; } 280 281 #if PRAGMA_MARK 282 #pragma mark OSMetaClass 283 #endif /* PRAGMA_MARK */ 284 /********************************************************************* 285 * OSMetaClass 286 *********************************************************************/ 287 288 /********************************************************************* 289 * Reserved functions. 290 *********************************************************************/ 291 void OSMetaClass::_RESERVEDOSMetaClass0() 292 { panic("OSMetaClass::_RESERVEDOSMetaClass%d called", 0); } 293 void OSMetaClass::_RESERVEDOSMetaClass1() 294 { panic("OSMetaClass::_RESERVEDOSMetaClass%d called", 1); } 295 void OSMetaClass::_RESERVEDOSMetaClass2() 296 { panic("OSMetaClass::_RESERVEDOSMetaClass%d called", 2); } 297 void OSMetaClass::_RESERVEDOSMetaClass3() 298 { panic("OSMetaClass::_RESERVEDOSMetaClass%d called", 3); } 299 void OSMetaClass::_RESERVEDOSMetaClass4() 300 { panic("OSMetaClass::_RESERVEDOSMetaClass%d called", 4); } 301 void OSMetaClass::_RESERVEDOSMetaClass5() 302 { panic("OSMetaClass::_RESERVEDOSMetaClass%d called", 5); } 303 void OSMetaClass::_RESERVEDOSMetaClass6() 304 { panic("OSMetaClass::_RESERVEDOSMetaClass%d called", 6); } 305 void OSMetaClass::_RESERVEDOSMetaClass7() 306 { panic("OSMetaClass::_RESERVEDOSMetaClass%d called", 7); } 307 308 /********************************************************************* 309 *********************************************************************/ 310 static void 311 OSMetaClassLogErrorForKext( 312 OSReturn error, 313 OSKext * aKext) 314 { 315 const char * message = NULL; 316 317 switch (error) { 318 case kOSReturnSuccess: 319 return; 320 case kOSMetaClassNoInit: // xxx - never returned; logged at fail site 321 message = "OSMetaClass: preModLoad() wasn't called (runtime internal error)."; 322 break; 323 case kOSMetaClassNoDicts: 324 message = "OSMetaClass: Allocation failure for OSMetaClass internal dictionaries."; 325 break; 326 case kOSMetaClassNoKModSet: 327 message = "OSMetaClass: Allocation failure for internal kext recording set/set missing."; 328 break; 329 case kOSMetaClassNoInsKModSet: 330 message = "OSMetaClass: Failed to record class in kext."; 331 break; 332 case kOSMetaClassDuplicateClass: 333 message = "OSMetaClass: Duplicate class encountered."; 334 break; 335 case kOSMetaClassNoSuper: // xxx - never returned 336 message = "OSMetaClass: Can't associate a class with its superclass."; 337 break; 338 case kOSMetaClassInstNoSuper: // xxx - never returned 339 message = "OSMetaClass: Instance construction error; unknown superclass."; 340 break; 341 case kOSMetaClassNoKext: 342 message = "OSMetaClass: Kext not found for metaclass."; 343 break; 344 case kOSMetaClassInternal: 345 default: 346 message = "OSMetaClass: Runtime internal error."; 347 break; 348 } 349 350 if (message) { 351 OSKextLog(aKext, kOSMetaClassLogSpec, "%s", message); 352 } 353 return; 354 } 355 356 void 357 OSMetaClass::logError(OSReturn error) 358 { 359 OSMetaClassLogErrorForKext(error, NULL); 360 } 361 362 /********************************************************************* 363 * The core constructor for a MetaClass (defined with this name always 364 * but within the scope of its represented class). 365 * 366 * MetaClass constructors are invoked in OSRuntimeInitializeCPP(), 367 * in between calls to OSMetaClass::preModLoad(), which sets up for 368 * registration, and OSMetaClass::postModLoad(), which actually 369 * records all the class/kext relationships of the new MetaClasses. 370 *********************************************************************/ 371 OSMetaClass::OSMetaClass( 372 const char * inClassName, 373 const OSMetaClass * inSuperClass, 374 unsigned int inClassSize) 375 { 376 instanceCount = 0; 377 classSize = inClassSize; 378 superClassLink = inSuperClass; 379 380 /* Hack alert: We are just casting inClassName and storing it in 381 * an OSString * instance variable. This may be because you can't 382 * create C++ objects in static constructors, but I really don't know! 383 */ 384 className = (const OSSymbol *)inClassName; 385 386 // sStalledClassesLock taken in preModLoad 387 if (!sStalled) { 388 /* There's no way we can look up the kext here, unfortunately. 389 */ 390 OSKextLog(/* kext */ NULL, kOSMetaClassLogSpec, 391 "OSMetaClass: preModLoad() wasn't called for class %s " 392 "(runtime internal error).", 393 inClassName); 394 } else if (!sStalled->result) { 395 // Grow stalled array if neccessary 396 if (sStalled->count >= sStalled->capacity) { 397 OSMetaClass **oldStalled = sStalled->classes; 398 int oldSize = sStalled->capacity * sizeof(OSMetaClass *); 399 int newSize = oldSize 400 + kKModCapacityIncrement * sizeof(OSMetaClass *); 401 402 sStalled->classes = (OSMetaClass **)kalloc(newSize); 403 if (!sStalled->classes) { 404 sStalled->classes = oldStalled; 405 sStalled->result = kOSMetaClassNoTempData; 406 return; 407 } 408 409 sStalled->capacity += kKModCapacityIncrement; 410 memmove(sStalled->classes, oldStalled, oldSize); 411 kfree(oldStalled, oldSize); 412 ACCUMSIZE(newSize - oldSize); 413 } 414 415 sStalled->classes[sStalled->count++] = this; 416 } 417 } 418 419 /********************************************************************* 420 *********************************************************************/ 421 OSMetaClass::~OSMetaClass() 422 { 423 OSKext * myKext = (OSKext *)reserved; // do not release 424 425 /* Hack alert: 'className' is a C string during early C++ init, and 426 * is converted to a real OSSymbol only when we record the OSKext in 427 * OSMetaClass::postModLoad(). So only do this bit if we have an OSKext. 428 * We can't safely cast or check 'className'. 429 * 430 * Also, release className *after* calling into the kext, 431 * as removeClass() may access className. 432 */ 433 IOLockLock(sAllClassesLock); 434 if (sAllClassesDict) { 435 if (myKext) { 436 sAllClassesDict->removeObject(className); 437 } else { 438 sAllClassesDict->removeObject((char *)className); 439 } 440 } 441 IOLockUnlock(sAllClassesLock); 442 443 if (myKext) { 444 if (myKext->removeClass(this) != kOSReturnSuccess) { 445 // xxx - what can we do? 446 } 447 className->release(); 448 } 449 450 // sStalledClassesLock taken in preModLoad 451 if (sStalled) { 452 unsigned int i; 453 454 /* First pass find class in stalled list. If we find it that means 455 * we started C++ init with constructors but now we're tearing down 456 * because of some failure. 457 */ 458 for (i = 0; i < sStalled->count; i++) { 459 if (this == sStalled->classes[i]) { 460 break; 461 } 462 } 463 464 /* Remove this metaclass from the stalled list so postModLoad() doesn't 465 * try to register it. 466 */ 467 if (i < sStalled->count) { 468 sStalled->count--; 469 if (i < sStalled->count) { 470 memmove(&sStalled->classes[i], &sStalled->classes[i+1], 471 (sStalled->count - i) * sizeof(OSMetaClass *)); 472 } 473 } 474 } 475 } 476 477 /********************************************************************* 478 * Empty overrides. 479 *********************************************************************/ 480 void * OSMetaClass::operator new(__unused size_t size) { return 0; } 481 void OSMetaClass::retain() const { } 482 void OSMetaClass::release() const { } 483 void OSMetaClass::release(__unused int when) const { } 484 void OSMetaClass::taggedRetain(__unused const void * tag) const { } 485 void OSMetaClass::taggedRelease(__unused const void * tag) const { } 486 void OSMetaClass::taggedRelease(__unused const void * tag, __unused const int when) const { } 487 int OSMetaClass::getRetainCount() const { return 0; } 488 489 /********************************************************************* 490 *********************************************************************/ 491 const char * 492 OSMetaClass::getClassName() const 493 { 494 return className->getCStringNoCopy(); 495 } 496 497 /********************************************************************* 498 *********************************************************************/ 499 unsigned int 500 OSMetaClass::getClassSize() const 501 { 502 return classSize; 503 } 504 505 /********************************************************************* 506 *********************************************************************/ 507 void * 508 OSMetaClass::preModLoad(const char * kextIdentifier) 509 { 510 IOLockLock(sStalledClassesLock); 511 512 assert (sStalled == NULL); 513 sStalled = (StalledData *)kalloc(sizeof(* sStalled)); 514 if (sStalled) { 515 sStalled->classes = (OSMetaClass **) 516 kalloc(kKModCapacityIncrement * sizeof(OSMetaClass *)); 517 if (!sStalled->classes) { 518 kfree(sStalled, sizeof(*sStalled)); 519 return 0; 520 } 521 ACCUMSIZE((kKModCapacityIncrement * sizeof(OSMetaClass *)) + 522 sizeof(*sStalled)); 523 524 sStalled->result = kOSReturnSuccess; 525 sStalled->capacity = kKModCapacityIncrement; 526 sStalled->count = 0; 527 sStalled->kextIdentifier = kextIdentifier; 528 bzero(sStalled->classes, kKModCapacityIncrement * sizeof(OSMetaClass *)); 529 } 530 531 // keep sStalledClassesLock locked until postModLoad 532 533 return sStalled; 534 } 535 536 /********************************************************************* 537 *********************************************************************/ 538 bool 539 OSMetaClass::checkModLoad(void * loadHandle) 540 { 541 return sStalled && loadHandle == sStalled && 542 sStalled->result == kOSReturnSuccess; 543 } 544 545 /********************************************************************* 546 *********************************************************************/ 547 OSReturn 548 OSMetaClass::postModLoad(void * loadHandle) 549 { 550 OSReturn result = kOSReturnSuccess; 551 OSSymbol * myKextName = 0; // must release 552 OSKext * myKext = 0; // must release 553 554 if (!sStalled || loadHandle != sStalled) { 555 result = kOSMetaClassInternal; 556 goto finish; 557 } 558 559 if (sStalled->result) { 560 result = sStalled->result; 561 } else switch (sBootstrapState) { 562 563 case kNoDictionaries: 564 sBootstrapState = kMakingDictionaries; 565 // No break; fall through 566 567 case kMakingDictionaries: 568 sAllClassesDict = OSDictionary::withCapacity(kClassCapacityIncrement); 569 if (!sAllClassesDict) { 570 result = kOSMetaClassNoDicts; 571 break; 572 } 573 574 // No break; fall through 575 576 case kCompletedBootstrap: 577 { 578 unsigned int i; 579 myKextName = const_cast<OSSymbol *>(OSSymbol::withCStringNoCopy( 580 sStalled->kextIdentifier)); 581 582 if (!sStalled->count) { 583 break; // Nothing to do so just get out 584 } 585 586 myKext = OSKext::lookupKextWithIdentifier(myKextName); 587 if (!myKext) { 588 result = kOSMetaClassNoKext; 589 590 /* Log this error here so we can include the kext name. 591 */ 592 OSKextLog(/* kext */ NULL, kOSMetaClassLogSpec, 593 "OSMetaClass: Can't record classes for kext %s - kext not found.", 594 sStalled->kextIdentifier); 595 break; 596 } 597 598 /* First pass checking classes aren't already loaded. If any already 599 * exist, we don't register any, and so we don't technically have 600 * to do any C++ teardown. 601 * 602 * Hack alert: me->className has been a C string until now. 603 * We only release the OSSymbol if we store the kext. 604 */ 605 IOLockLock(sAllClassesLock); 606 for (i = 0; i < sStalled->count; i++) { 607 OSMetaClass * me = sStalled->classes[i]; 608 OSMetaClass * orig = OSDynamicCast(OSMetaClass, 609 sAllClassesDict->getObject((const char *)me->className)); 610 611 if (orig) { 612 613 /* Log this error here so we can include the class name. 614 * xxx - we should look up the other kext that defines the class 615 */ 616 OSKextLog(myKext, kOSMetaClassLogSpec, 617 "OSMetaClass: Kext %s class %s is a duplicate;" 618 "kext %s already has a class by that name.", 619 sStalled->kextIdentifier, (const char *)me->className, 620 ((OSKext *)orig->reserved)->getIdentifierCString()); 621 result = kOSMetaClassDuplicateClass; 622 break; 623 } 624 } 625 IOLockUnlock(sAllClassesLock); 626 627 /* Bail if we didn't go through the entire list of new classes 628 * (if we hit a duplicate). 629 */ 630 if (i != sStalled->count) { 631 break; 632 } 633 634 // Second pass symbolling strings and inserting classes in dictionary 635 IOLockLock(sAllClassesLock); 636 for (i = 0; i < sStalled->count; i++) { 637 OSMetaClass * me = sStalled->classes[i]; 638 639 /* Hack alert: me->className has been a C string until now. 640 * We only release the OSSymbol in ~OSMetaClass() 641 * if we set the reference to the kext. 642 */ 643 me->className = 644 OSSymbol::withCStringNoCopy((const char *)me->className); 645 646 // xxx - I suppose if these fail we're going to panic soon.... 647 sAllClassesDict->setObject(me->className, me); 648 649 /* Do not retain the kext object here. 650 */ 651 me->reserved = (ExpansionData *)myKext; 652 if (myKext) { 653 result = myKext->addClass(me, sStalled->count); 654 if (result != kOSReturnSuccess) { 655 /* OSKext::addClass() logs with kOSMetaClassNoInsKModSet. */ 656 break; 657 } 658 } 659 } 660 IOLockUnlock(sAllClassesLock); 661 sBootstrapState = kCompletedBootstrap; 662 break; 663 } 664 665 default: 666 result = kOSMetaClassInternal; 667 break; 668 } 669 670 finish: 671 /* Don't call logError() for success or the conditions logged above 672 * or by called function. 673 */ 674 if (result != kOSReturnSuccess && 675 result != kOSMetaClassNoInsKModSet && 676 result != kOSMetaClassDuplicateClass && 677 result != kOSMetaClassNoKext) { 678 679 OSMetaClassLogErrorForKext(result, myKext); 680 } 681 682 OSSafeRelease(myKextName); 683 OSSafeRelease(myKext); 684 685 if (sStalled) { 686 ACCUMSIZE(-(sStalled->capacity * sizeof(OSMetaClass *) + 687 sizeof(*sStalled))); 688 kfree(sStalled->classes, sStalled->capacity * sizeof(OSMetaClass *)); 689 kfree(sStalled, sizeof(*sStalled)); 690 sStalled = 0; 691 } 692 693 IOLockUnlock(sStalledClassesLock); 694 695 return result; 696 } 697 698 699 /********************************************************************* 700 *********************************************************************/ 701 void 702 OSMetaClass::instanceConstructed() const 703 { 704 // if ((0 == OSIncrementAtomic(&(((OSMetaClass *) this)->instanceCount))) && superClassLink) 705 if ((0 == OSIncrementAtomic(&instanceCount)) && superClassLink) { 706 superClassLink->instanceConstructed(); 707 } 708 } 709 710 /********************************************************************* 711 *********************************************************************/ 712 void 713 OSMetaClass::instanceDestructed() const 714 { 715 if ((1 == OSDecrementAtomic(&instanceCount)) && superClassLink) { 716 superClassLink->instanceDestructed(); 717 } 718 719 if (((int)instanceCount) < 0) { 720 OSKext * myKext = (OSKext *)reserved; 721 722 OSKextLog(myKext, kOSMetaClassLogSpec, 723 // xxx - this phrasing is rather cryptic 724 "OSMetaClass: Class %s - bad retain (%d)", 725 getClassName(), instanceCount); 726 } 727 } 728 729 /********************************************************************* 730 *********************************************************************/ 731 bool 732 OSMetaClass::modHasInstance(const char * kextIdentifier) 733 { 734 bool result = false; 735 OSKext * theKext = NULL; // must release 736 737 theKext = OSKext::lookupKextWithIdentifier(kextIdentifier); 738 if (!theKext) { 739 goto finish; 740 } 741 742 result = theKext->hasOSMetaClassInstances(); 743 744 finish: 745 OSSafeRelease(theKext); 746 return result; 747 } 748 749 /********************************************************************* 750 *********************************************************************/ 751 void 752 OSMetaClass::reportModInstances(const char * kextIdentifier) 753 { 754 OSKext::reportOSMetaClassInstances(kextIdentifier, 755 kOSKextLogExplicitLevel); 756 return; 757 } 758 759 /********************************************************************* 760 *********************************************************************/ 761 void 762 OSMetaClass::considerUnloads() 763 { 764 OSKext::considerUnloads(); 765 } 766 767 /********************************************************************* 768 *********************************************************************/ 769 const OSMetaClass * 770 OSMetaClass::getMetaClassWithName(const OSSymbol * name) 771 { 772 OSMetaClass * retMeta = 0; 773 774 if (!name) { 775 return 0; 776 } 777 778 IOLockLock(sAllClassesLock); 779 if (sAllClassesDict) { 780 retMeta = (OSMetaClass *) sAllClassesDict->getObject(name); 781 } 782 IOLockUnlock(sAllClassesLock); 783 784 return retMeta; 785 } 786 787 /********************************************************************* 788 *********************************************************************/ 789 OSObject * 790 OSMetaClass::allocClassWithName(const OSSymbol * name) 791 { 792 OSObject * result = 0; 793 794 const OSMetaClass * const meta = getMetaClassWithName(name); 795 796 if (meta) { 797 result = meta->alloc(); 798 } 799 800 return result; 801 } 802 803 /********************************************************************* 804 *********************************************************************/ 805 OSObject * 806 OSMetaClass::allocClassWithName(const OSString * name) 807 { 808 const OSSymbol * tmpKey = OSSymbol::withString(name); 809 OSObject * result = allocClassWithName(tmpKey); 810 tmpKey->release(); 811 return result; 812 } 813 814 /********************************************************************* 815 *********************************************************************/ 816 OSObject * 817 OSMetaClass::allocClassWithName(const char * name) 818 { 819 const OSSymbol * tmpKey = OSSymbol::withCStringNoCopy(name); 820 OSObject * result = allocClassWithName(tmpKey); 821 tmpKey->release(); 822 return result; 823 } 824 825 826 /********************************************************************* 827 *********************************************************************/ 828 OSMetaClassBase * 829 OSMetaClass::checkMetaCastWithName( 830 const OSSymbol * name, 831 const OSMetaClassBase * in) 832 { 833 OSMetaClassBase * result = 0; 834 835 const OSMetaClass * const meta = getMetaClassWithName(name); 836 837 if (meta) { 838 result = meta->checkMetaCast(in); 839 } 840 841 return result; 842 } 843 844 /********************************************************************* 845 *********************************************************************/ 846 OSMetaClassBase * OSMetaClass:: 847 checkMetaCastWithName( 848 const OSString * name, 849 const OSMetaClassBase * in) 850 { 851 const OSSymbol * tmpKey = OSSymbol::withString(name); 852 OSMetaClassBase * result = checkMetaCastWithName(tmpKey, in); 853 854 tmpKey->release(); 855 return result; 856 } 857 858 /********************************************************************* 859 *********************************************************************/ 860 OSMetaClassBase * 861 OSMetaClass::checkMetaCastWithName( 862 const char * name, 863 const OSMetaClassBase * in) 864 { 865 const OSSymbol * tmpKey = OSSymbol::withCStringNoCopy(name); 866 OSMetaClassBase * result = checkMetaCastWithName(tmpKey, in); 867 868 tmpKey->release(); 869 return result; 870 } 871 872 /********************************************************************* 873 * OSMetaClass::checkMetaCast() 874 * Check to see if the 'check' object has this object in its metaclass chain. 875 * Returns check if it is indeed a kind of the current meta class, 0 otherwise. 876 * 877 * Generally this method is not invoked directly but is used to implement 878 * the OSMetaClassBase::metaCast member function. 879 * 880 * See also OSMetaClassBase::metaCast 881 *********************************************************************/ 882 OSMetaClassBase * OSMetaClass::checkMetaCast( 883 const OSMetaClassBase * check) const 884 { 885 const OSMetaClass * const toMeta = this; 886 const OSMetaClass * fromMeta; 887 888 for (fromMeta = check->getMetaClass(); ; fromMeta = fromMeta->superClassLink) { 889 if (toMeta == fromMeta) { 890 return const_cast<OSMetaClassBase *>(check); // Discard const 891 } 892 if (!fromMeta->superClassLink) { 893 break; 894 } 895 } 896 897 return 0; 898 } 899 900 /********************************************************************* 901 *********************************************************************/ 902 void 903 OSMetaClass::reservedCalled(int ind) const 904 { 905 const char * cname = className->getCStringNoCopy(); 906 panic("%s::_RESERVED%s%d called.", cname, cname, ind); 907 } 908 909 /********************************************************************* 910 *********************************************************************/ 911 const 912 OSMetaClass * 913 OSMetaClass::getSuperClass() const 914 { 915 return superClassLink; 916 } 917 918 /********************************************************************* 919 * xxx - I want to rename this :-/ 920 *********************************************************************/ 921 const OSSymbol * 922 OSMetaClass::getKmodName() const 923 { 924 OSKext * myKext = (OSKext *)reserved; 925 if (myKext) { 926 return myKext->getIdentifier(); 927 } 928 return OSSymbol::withCStringNoCopy("unknown"); 929 } 930 931 /********************************************************************* 932 *********************************************************************/ 933 unsigned int 934 OSMetaClass::getInstanceCount() const 935 { 936 return instanceCount; 937 } 938 939 /********************************************************************* 940 *********************************************************************/ 941 /* static */ 942 void 943 OSMetaClass::printInstanceCounts() 944 { 945 OSCollectionIterator * classes; 946 OSSymbol * className; 947 OSMetaClass * meta; 948 949 IOLockLock(sAllClassesLock); 950 classes = OSCollectionIterator::withCollection(sAllClassesDict); 951 assert(classes); 952 953 while( (className = (OSSymbol *)classes->getNextObject())) { 954 meta = (OSMetaClass *)sAllClassesDict->getObject(className); 955 assert(meta); 956 957 printf("%24s count: %03d x 0x%03x = 0x%06x\n", 958 className->getCStringNoCopy(), 959 meta->getInstanceCount(), 960 meta->getClassSize(), 961 meta->getInstanceCount() * meta->getClassSize() ); 962 } 963 printf("\n"); 964 classes->release(); 965 IOLockUnlock(sAllClassesLock); 966 return; 967 } 968 969 /********************************************************************* 970 *********************************************************************/ 971 OSDictionary * 972 OSMetaClass::getClassDictionary() 973 { 974 panic("OSMetaClass::getClassDictionary() is obsoleted.\n"); 975 return 0; 976 } 977 978 /********************************************************************* 979 *********************************************************************/ 980 bool 981 OSMetaClass::serialize(__unused OSSerialize * s) const 982 { 983 panic("OSMetaClass::serialize(): Obsoleted\n"); 984 return false; 985 } 986 987 /********************************************************************* 988 *********************************************************************/ 989 /* static */ 990 void 991 OSMetaClass::serializeClassDictionary(OSDictionary * serializeDictionary) 992 { 993 OSDictionary * classDict = NULL; 994 995 IOLockLock(sAllClassesLock); 996 997 classDict = OSDictionary::withCapacity(sAllClassesDict->getCount()); 998 if (!classDict) { 999 goto finish; 1000 } 1001 1002 do { 1003 OSCollectionIterator * classes; 1004 const OSSymbol * className; 1005 1006 classes = OSCollectionIterator::withCollection(sAllClassesDict); 1007 if (!classes) { 1008 break; 1009 } 1010 1011 while ((className = (const OSSymbol *)classes->getNextObject())) { 1012 const OSMetaClass * meta; 1013 OSNumber * count; 1014 1015 meta = (OSMetaClass *)sAllClassesDict->getObject(className); 1016 count = OSNumber::withNumber(meta->getInstanceCount(), 32); 1017 if (count) { 1018 classDict->setObject(className, count); 1019 count->release(); 1020 } 1021 } 1022 classes->release(); 1023 1024 serializeDictionary->setObject("Classes", classDict); 1025 } while (0); 1026 1027 finish: 1028 OSSafeRelease(classDict); 1029 1030 IOLockUnlock(sAllClassesLock); 1031 1032 return; 1033 } 1034