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