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 if (!className) return NULL; 495 return className->getCStringNoCopy(); 496 } 497 498 /********************************************************************* 499 *********************************************************************/ 500 unsigned int 501 OSMetaClass::getClassSize() const 502 { 503 return classSize; 504 } 505 506 /********************************************************************* 507 *********************************************************************/ 508 void * 509 OSMetaClass::preModLoad(const char * kextIdentifier) 510 { 511 IOLockLock(sStalledClassesLock); 512 513 assert (sStalled == NULL); 514 sStalled = (StalledData *)kalloc(sizeof(* sStalled)); 515 if (sStalled) { 516 sStalled->classes = (OSMetaClass **) 517 kalloc(kKModCapacityIncrement * sizeof(OSMetaClass *)); 518 if (!sStalled->classes) { 519 kfree(sStalled, sizeof(*sStalled)); 520 return 0; 521 } 522 ACCUMSIZE((kKModCapacityIncrement * sizeof(OSMetaClass *)) + 523 sizeof(*sStalled)); 524 525 sStalled->result = kOSReturnSuccess; 526 sStalled->capacity = kKModCapacityIncrement; 527 sStalled->count = 0; 528 sStalled->kextIdentifier = kextIdentifier; 529 bzero(sStalled->classes, kKModCapacityIncrement * sizeof(OSMetaClass *)); 530 } 531 532 // keep sStalledClassesLock locked until postModLoad 533 534 return sStalled; 535 } 536 537 /********************************************************************* 538 *********************************************************************/ 539 bool 540 OSMetaClass::checkModLoad(void * loadHandle) 541 { 542 return sStalled && loadHandle == sStalled && 543 sStalled->result == kOSReturnSuccess; 544 } 545 546 /********************************************************************* 547 *********************************************************************/ 548 OSReturn 549 OSMetaClass::postModLoad(void * loadHandle) 550 { 551 OSReturn result = kOSReturnSuccess; 552 OSSymbol * myKextName = 0; // must release 553 OSKext * myKext = 0; // must release 554 555 if (!sStalled || loadHandle != sStalled) { 556 result = kOSMetaClassInternal; 557 goto finish; 558 } 559 560 if (sStalled->result) { 561 result = sStalled->result; 562 } else switch (sBootstrapState) { 563 564 case kNoDictionaries: 565 sBootstrapState = kMakingDictionaries; 566 // No break; fall through 567 568 case kMakingDictionaries: 569 sAllClassesDict = OSDictionary::withCapacity(kClassCapacityIncrement); 570 if (!sAllClassesDict) { 571 result = kOSMetaClassNoDicts; 572 break; 573 } 574 575 // No break; fall through 576 577 case kCompletedBootstrap: 578 { 579 unsigned int i; 580 myKextName = const_cast<OSSymbol *>(OSSymbol::withCStringNoCopy( 581 sStalled->kextIdentifier)); 582 583 if (!sStalled->count) { 584 break; // Nothing to do so just get out 585 } 586 587 myKext = OSKext::lookupKextWithIdentifier(myKextName); 588 if (!myKext) { 589 result = kOSMetaClassNoKext; 590 591 /* Log this error here so we can include the kext name. 592 */ 593 OSKextLog(/* kext */ NULL, kOSMetaClassLogSpec, 594 "OSMetaClass: Can't record classes for kext %s - kext not found.", 595 sStalled->kextIdentifier); 596 break; 597 } 598 599 /* First pass checking classes aren't already loaded. If any already 600 * exist, we don't register any, and so we don't technically have 601 * to do any C++ teardown. 602 * 603 * Hack alert: me->className has been a C string until now. 604 * We only release the OSSymbol if we store the kext. 605 */ 606 IOLockLock(sAllClassesLock); 607 for (i = 0; i < sStalled->count; i++) { 608 OSMetaClass * me = sStalled->classes[i]; 609 OSMetaClass * orig = OSDynamicCast(OSMetaClass, 610 sAllClassesDict->getObject((const char *)me->className)); 611 612 if (orig) { 613 614 /* Log this error here so we can include the class name. 615 * xxx - we should look up the other kext that defines the class 616 */ 617 OSKextLog(myKext, kOSMetaClassLogSpec, 618 "OSMetaClass: Kext %s class %s is a duplicate;" 619 "kext %s already has a class by that name.", 620 sStalled->kextIdentifier, (const char *)me->className, 621 ((OSKext *)orig->reserved)->getIdentifierCString()); 622 result = kOSMetaClassDuplicateClass; 623 break; 624 } 625 } 626 IOLockUnlock(sAllClassesLock); 627 628 /* Bail if we didn't go through the entire list of new classes 629 * (if we hit a duplicate). 630 */ 631 if (i != sStalled->count) { 632 break; 633 } 634 635 // Second pass symbolling strings and inserting classes in dictionary 636 IOLockLock(sAllClassesLock); 637 for (i = 0; i < sStalled->count; i++) { 638 OSMetaClass * me = sStalled->classes[i]; 639 640 /* Hack alert: me->className has been a C string until now. 641 * We only release the OSSymbol in ~OSMetaClass() 642 * if we set the reference to the kext. 643 */ 644 me->className = 645 OSSymbol::withCStringNoCopy((const char *)me->className); 646 647 // xxx - I suppose if these fail we're going to panic soon.... 648 sAllClassesDict->setObject(me->className, me); 649 650 /* Do not retain the kext object here. 651 */ 652 me->reserved = (ExpansionData *)myKext; 653 if (myKext) { 654 result = myKext->addClass(me, sStalled->count); 655 if (result != kOSReturnSuccess) { 656 /* OSKext::addClass() logs with kOSMetaClassNoInsKModSet. */ 657 break; 658 } 659 } 660 } 661 IOLockUnlock(sAllClassesLock); 662 sBootstrapState = kCompletedBootstrap; 663 break; 664 } 665 666 default: 667 result = kOSMetaClassInternal; 668 break; 669 } 670 671 finish: 672 /* Don't call logError() for success or the conditions logged above 673 * or by called function. 674 */ 675 if (result != kOSReturnSuccess && 676 result != kOSMetaClassNoInsKModSet && 677 result != kOSMetaClassDuplicateClass && 678 result != kOSMetaClassNoKext) { 679 680 OSMetaClassLogErrorForKext(result, myKext); 681 } 682 683 OSSafeRelease(myKextName); 684 OSSafeRelease(myKext); 685 686 if (sStalled) { 687 ACCUMSIZE(-(sStalled->capacity * sizeof(OSMetaClass *) + 688 sizeof(*sStalled))); 689 kfree(sStalled->classes, sStalled->capacity * sizeof(OSMetaClass *)); 690 kfree(sStalled, sizeof(*sStalled)); 691 sStalled = 0; 692 } 693 694 IOLockUnlock(sStalledClassesLock); 695 696 return result; 697 } 698 699 700 /********************************************************************* 701 *********************************************************************/ 702 void 703 OSMetaClass::instanceConstructed() const 704 { 705 // if ((0 == OSIncrementAtomic(&(((OSMetaClass *) this)->instanceCount))) && superClassLink) 706 if ((0 == OSIncrementAtomic(&instanceCount)) && superClassLink) { 707 superClassLink->instanceConstructed(); 708 } 709 } 710 711 /********************************************************************* 712 *********************************************************************/ 713 void 714 OSMetaClass::instanceDestructed() const 715 { 716 if ((1 == OSDecrementAtomic(&instanceCount)) && superClassLink) { 717 superClassLink->instanceDestructed(); 718 } 719 720 if (((int)instanceCount) < 0) { 721 OSKext * myKext = (OSKext *)reserved; 722 723 OSKextLog(myKext, kOSMetaClassLogSpec, 724 // xxx - this phrasing is rather cryptic 725 "OSMetaClass: Class %s - bad retain (%d)", 726 getClassName(), instanceCount); 727 } 728 } 729 730 /********************************************************************* 731 *********************************************************************/ 732 bool 733 OSMetaClass::modHasInstance(const char * kextIdentifier) 734 { 735 bool result = false; 736 OSKext * theKext = NULL; // must release 737 738 theKext = OSKext::lookupKextWithIdentifier(kextIdentifier); 739 if (!theKext) { 740 goto finish; 741 } 742 743 result = theKext->hasOSMetaClassInstances(); 744 745 finish: 746 OSSafeRelease(theKext); 747 return result; 748 } 749 750 /********************************************************************* 751 *********************************************************************/ 752 void 753 OSMetaClass::reportModInstances(const char * kextIdentifier) 754 { 755 OSKext::reportOSMetaClassInstances(kextIdentifier, 756 kOSKextLogExplicitLevel); 757 return; 758 } 759 760 /********************************************************************* 761 *********************************************************************/ 762 void 763 OSMetaClass::considerUnloads() 764 { 765 OSKext::considerUnloads(); 766 } 767 768 /********************************************************************* 769 *********************************************************************/ 770 const OSMetaClass * 771 OSMetaClass::getMetaClassWithName(const OSSymbol * name) 772 { 773 OSMetaClass * retMeta = 0; 774 775 if (!name) { 776 return 0; 777 } 778 779 IOLockLock(sAllClassesLock); 780 if (sAllClassesDict) { 781 retMeta = (OSMetaClass *) sAllClassesDict->getObject(name); 782 } 783 IOLockUnlock(sAllClassesLock); 784 785 return retMeta; 786 } 787 788 /********************************************************************* 789 *********************************************************************/ 790 OSObject * 791 OSMetaClass::allocClassWithName(const OSSymbol * name) 792 { 793 OSObject * result = 0; 794 795 const OSMetaClass * const meta = getMetaClassWithName(name); 796 797 if (meta) { 798 result = meta->alloc(); 799 } 800 801 return result; 802 } 803 804 /********************************************************************* 805 *********************************************************************/ 806 OSObject * 807 OSMetaClass::allocClassWithName(const OSString * name) 808 { 809 const OSSymbol * tmpKey = OSSymbol::withString(name); 810 OSObject * result = allocClassWithName(tmpKey); 811 tmpKey->release(); 812 return result; 813 } 814 815 /********************************************************************* 816 *********************************************************************/ 817 OSObject * 818 OSMetaClass::allocClassWithName(const char * name) 819 { 820 const OSSymbol * tmpKey = OSSymbol::withCStringNoCopy(name); 821 OSObject * result = allocClassWithName(tmpKey); 822 tmpKey->release(); 823 return result; 824 } 825 826 827 /********************************************************************* 828 *********************************************************************/ 829 OSMetaClassBase * 830 OSMetaClass::checkMetaCastWithName( 831 const OSSymbol * name, 832 const OSMetaClassBase * in) 833 { 834 OSMetaClassBase * result = 0; 835 836 const OSMetaClass * const meta = getMetaClassWithName(name); 837 838 if (meta) { 839 result = meta->checkMetaCast(in); 840 } 841 842 return result; 843 } 844 845 /********************************************************************* 846 *********************************************************************/ 847 OSMetaClassBase * OSMetaClass:: 848 checkMetaCastWithName( 849 const OSString * name, 850 const OSMetaClassBase * in) 851 { 852 const OSSymbol * tmpKey = OSSymbol::withString(name); 853 OSMetaClassBase * result = checkMetaCastWithName(tmpKey, in); 854 855 tmpKey->release(); 856 return result; 857 } 858 859 /********************************************************************* 860 *********************************************************************/ 861 OSMetaClassBase * 862 OSMetaClass::checkMetaCastWithName( 863 const char * name, 864 const OSMetaClassBase * in) 865 { 866 const OSSymbol * tmpKey = OSSymbol::withCStringNoCopy(name); 867 OSMetaClassBase * result = checkMetaCastWithName(tmpKey, in); 868 869 tmpKey->release(); 870 return result; 871 } 872 873 /********************************************************************* 874 * OSMetaClass::checkMetaCast() 875 * Check to see if the 'check' object has this object in its metaclass chain. 876 * Returns check if it is indeed a kind of the current meta class, 0 otherwise. 877 * 878 * Generally this method is not invoked directly but is used to implement 879 * the OSMetaClassBase::metaCast member function. 880 * 881 * See also OSMetaClassBase::metaCast 882 *********************************************************************/ 883 OSMetaClassBase * OSMetaClass::checkMetaCast( 884 const OSMetaClassBase * check) const 885 { 886 const OSMetaClass * const toMeta = this; 887 const OSMetaClass * fromMeta; 888 889 for (fromMeta = check->getMetaClass(); ; fromMeta = fromMeta->superClassLink) { 890 if (toMeta == fromMeta) { 891 return const_cast<OSMetaClassBase *>(check); // Discard const 892 } 893 if (!fromMeta->superClassLink) { 894 break; 895 } 896 } 897 898 return 0; 899 } 900 901 /********************************************************************* 902 *********************************************************************/ 903 void 904 OSMetaClass::reservedCalled(int ind) const 905 { 906 const char * cname = className->getCStringNoCopy(); 907 panic("%s::_RESERVED%s%d called.", cname, cname, ind); 908 } 909 910 /********************************************************************* 911 *********************************************************************/ 912 const 913 OSMetaClass * 914 OSMetaClass::getSuperClass() const 915 { 916 return superClassLink; 917 } 918 919 /********************************************************************* 920 * xxx - I want to rename this :-/ 921 *********************************************************************/ 922 const OSSymbol * 923 OSMetaClass::getKmodName() const 924 { 925 OSKext * myKext = (OSKext *)reserved; 926 if (myKext) { 927 return myKext->getIdentifier(); 928 } 929 return OSSymbol::withCStringNoCopy("unknown"); 930 } 931 932 /********************************************************************* 933 *********************************************************************/ 934 unsigned int 935 OSMetaClass::getInstanceCount() const 936 { 937 return instanceCount; 938 } 939 940 /********************************************************************* 941 *********************************************************************/ 942 /* static */ 943 void 944 OSMetaClass::printInstanceCounts() 945 { 946 OSCollectionIterator * classes; 947 OSSymbol * className; 948 OSMetaClass * meta; 949 950 IOLockLock(sAllClassesLock); 951 classes = OSCollectionIterator::withCollection(sAllClassesDict); 952 assert(classes); 953 954 while( (className = (OSSymbol *)classes->getNextObject())) { 955 meta = (OSMetaClass *)sAllClassesDict->getObject(className); 956 assert(meta); 957 958 printf("%24s count: %03d x 0x%03x = 0x%06x\n", 959 className->getCStringNoCopy(), 960 meta->getInstanceCount(), 961 meta->getClassSize(), 962 meta->getInstanceCount() * meta->getClassSize() ); 963 } 964 printf("\n"); 965 classes->release(); 966 IOLockUnlock(sAllClassesLock); 967 return; 968 } 969 970 /********************************************************************* 971 *********************************************************************/ 972 OSDictionary * 973 OSMetaClass::getClassDictionary() 974 { 975 panic("OSMetaClass::getClassDictionary() is obsoleted.\n"); 976 return 0; 977 } 978 979 /********************************************************************* 980 *********************************************************************/ 981 bool 982 OSMetaClass::serialize(__unused OSSerialize * s) const 983 { 984 panic("OSMetaClass::serialize(): Obsoleted\n"); 985 return false; 986 } 987 988 /********************************************************************* 989 *********************************************************************/ 990 /* static */ 991 void 992 OSMetaClass::serializeClassDictionary(OSDictionary * serializeDictionary) 993 { 994 OSDictionary * classDict = NULL; 995 996 IOLockLock(sAllClassesLock); 997 998 classDict = OSDictionary::withCapacity(sAllClassesDict->getCount()); 999 if (!classDict) { 1000 goto finish; 1001 } 1002 1003 do { 1004 OSCollectionIterator * classes; 1005 const OSSymbol * className; 1006 1007 classes = OSCollectionIterator::withCollection(sAllClassesDict); 1008 if (!classes) { 1009 break; 1010 } 1011 1012 while ((className = (const OSSymbol *)classes->getNextObject())) { 1013 const OSMetaClass * meta; 1014 OSNumber * count; 1015 1016 meta = (OSMetaClass *)sAllClassesDict->getObject(className); 1017 count = OSNumber::withNumber(meta->getInstanceCount(), 32); 1018 if (count) { 1019 classDict->setObject(className, count); 1020 count->release(); 1021 } 1022 } 1023 classes->release(); 1024 1025 serializeDictionary->setObject("Classes", classDict); 1026 } while (0); 1027 1028 finish: 1029 OSSafeRelease(classDict); 1030 1031 IOLockUnlock(sAllClassesLock); 1032 1033 return; 1034 } 1035