1 /* 2 * Copyright (c) 2000-2016 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 #include <IOKit/IOKitDebug.h> 52 53 54 __BEGIN_DECLS 55 56 #include <sys/systm.h> 57 #include <mach/mach_types.h> 58 #include <kern/locks.h> 59 #include <kern/clock.h> 60 #include <kern/thread_call.h> 61 #include <kern/host.h> 62 #include <mach/mach_interface.h> 63 #include <stddef.h> 64 65 #if PRAGMA_MARK 66 #pragma mark Macros 67 #endif /* PRAGMA_MARK */ 68 /********************************************************************* 69 * Macros 70 *********************************************************************/ 71 __END_DECLS 72 73 #if PRAGMA_MARK 74 #pragma mark Internal constants & data structs 75 #endif /* PRAGMA_MARK */ 76 /********************************************************************* 77 * Internal constants & data structs 78 *********************************************************************/ 79 OSKextLogSpec kOSMetaClassLogSpec = 80 kOSKextLogErrorLevel | 81 kOSKextLogLoadFlag | 82 kOSKextLogKextBookkeepingFlag; 83 84 static enum { 85 kCompletedBootstrap = 0, 86 kNoDictionaries = 1, 87 kMakingDictionaries = 2 88 } sBootstrapState = kNoDictionaries; 89 90 static const int kClassCapacityIncrement = 40; 91 static const int kKModCapacityIncrement = 10; 92 static OSDictionary * sAllClassesDict; 93 static unsigned int sDeepestClass; 94 IOLock * sAllClassesLock = NULL; 95 IOLock * sInstancesLock = NULL; 96 97 /* 98 * While loading a kext and running all its constructors to register 99 * all OSMetaClass classes, the classes are queued up here. Only one 100 * kext can be in flight at a time, guarded by sStalledClassesLock 101 */ 102 static struct StalledData { 103 const char * kextIdentifier; 104 OSReturn result; 105 unsigned int capacity; 106 unsigned int count; 107 OSMetaClass ** classes; 108 } * sStalled; 109 IOLock * sStalledClassesLock = NULL; 110 111 struct ExpansionData { 112 OSOrderedSet * instances; 113 OSKext * kext; 114 uint32_t retain; 115 #if IOTRACKING 116 IOTrackingQueue * tracking; 117 #endif 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 133 void 134 OSMetaClassBase::_RESERVEDOSMetaClassBase0() 135 { 136 panic("OSMetaClassBase::_RESERVEDOSMetaClassBase%d called.", 0); 137 } 138 void 139 OSMetaClassBase::_RESERVEDOSMetaClassBase1() 140 { 141 panic("OSMetaClassBase::_RESERVEDOSMetaClassBase%d called.", 1); 142 } 143 void 144 OSMetaClassBase::_RESERVEDOSMetaClassBase2() 145 { 146 panic("OSMetaClassBase::_RESERVEDOSMetaClassBase%d called.", 2); 147 } 148 void 149 OSMetaClassBase::_RESERVEDOSMetaClassBase3() 150 { 151 panic("OSMetaClassBase::_RESERVEDOSMetaClassBase%d called.", 3); 152 } 153 #endif /* SLOT_USED */ 154 155 // As these slots are used move them up inside the #if above 156 void 157 OSMetaClassBase::_RESERVEDOSMetaClassBase4() 158 { 159 panic("OSMetaClassBase::_RESERVEDOSMetaClassBase%d called.", 4); 160 } 161 void 162 OSMetaClassBase::_RESERVEDOSMetaClassBase5() 163 { 164 panic("OSMetaClassBase::_RESERVEDOSMetaClassBase%d called.", 5); 165 } 166 void 167 OSMetaClassBase::_RESERVEDOSMetaClassBase6() 168 { 169 panic("OSMetaClassBase::_RESERVEDOSMetaClassBase%d called.", 6); 170 } 171 #endif 172 173 /********************************************************************* 174 *********************************************************************/ 175 176 #if defined(__arm__) || defined(__arm64__) 177 178 #if defined(HAS_APPLE_PAC) 179 #include <ptrauth.h> 180 #endif /* defined(HAS_APPLE_PAC) */ 181 182 /* 183 * IHI0059A "C++ Application Binary Interface Standard for the ARM 64 - bit Architecture": 184 * 185 * 3.2.1 Representation of pointer to member function The generic C++ ABI [GC++ABI] 186 * specifies that a pointer to member function is a pair of words <ptr, adj>. The 187 * least significant bit of ptr discriminates between (0) the address of a non- 188 * virtual member function and (1) the offset in the class's virtual table of the 189 * address of a virtual function. This encoding cannot work for the AArch64 190 * instruction set where the architecture reserves all bits of code addresses. This 191 * ABI specifies that adj contains twice the this adjustment, plus 1 if the member 192 * function is virtual. The least significant bit of adj then makes exactly the 193 * same discrimination as the least significant bit of ptr does for Itanium. A 194 * pointer to member function is NULL when ptr = 0 and the least significant bit of 195 * adj is zero. 196 */ 197 198 OSMetaClassBase::_ptf_t 199 #if defined(HAS_APPLE_PAC) && __has_feature(ptrauth_type_discriminator) 200 OSMetaClassBase::_ptmf2ptf(const OSMetaClassBase *self __attribute__((unused)), 201 void (OSMetaClassBase::*func)(void), uintptr_t typeDisc) 202 #else 203 OSMetaClassBase::_ptmf2ptf(const OSMetaClassBase *self, 204 void (OSMetaClassBase::*func)(void), 205 uintptr_t typeDisc 206 __attribute__((unused))) 207 #endif 208 { 209 struct ptmf_t { 210 _ptf_t fPFN; 211 ptrdiff_t delta; 212 }; 213 union { 214 void (OSMetaClassBase::*fIn)(void); 215 struct ptmf_t pTMF; 216 } map; 217 _ptf_t pfn; 218 219 map.fIn = func; 220 pfn = map.pTMF.fPFN; 221 222 #if defined(HAS_APPLE_PAC) && __has_feature(ptrauth_type_discriminator) 223 // Authenticate 'pfn' using the member function pointer type discriminator 224 // and resign it as a C function pointer. 'pfn' can point to either a 225 // non-virtual function or a virtual member function thunk. 226 pfn = ptrauth_auth_function(pfn, ptrauth_key_function_pointer, typeDisc); 227 return pfn; 228 #else 229 if (map.pTMF.delta & 1) { 230 // virtual 231 union { 232 const OSMetaClassBase *fObj; 233 _ptf_t **vtablep; 234 } u; 235 u.fObj = self; 236 237 // Virtual member function so dereference table 238 #if defined(HAS_APPLE_PAC) 239 // The entity hash is stored in the top 32-bits of the vtable offset of a 240 // member function pointer. 241 uint32_t entity_hash = ((uintptr_t)pfn) >> 32; 242 pfn = (_ptf_t)(((uintptr_t) pfn) & 0xFFFFFFFF); 243 244 // Authenticate the vtable pointer. 245 _ptf_t *vtablep = ptrauth_auth_data(*u.vtablep, 246 ptrauth_key_cxx_vtable_pointer, 0); 247 // Calculate the address of the vtable entry. 248 _ptf_t *vtentryp = (_ptf_t *)(((uintptr_t)vtablep) + (uintptr_t)pfn); 249 // Load the pointer from the vtable entry. 250 pfn = *vtentryp; 251 252 // Finally, resign the vtable entry as a function pointer. 253 uintptr_t auth_data = ptrauth_blend_discriminator(vtentryp, entity_hash); 254 pfn = ptrauth_auth_and_resign(pfn, ptrauth_key_function_pointer, 255 auth_data, ptrauth_key_function_pointer, 0); 256 #else /* defined(HAS_APPLE_PAC) */ 257 pfn = *(_ptf_t *)(((uintptr_t)*u.vtablep) + (uintptr_t)pfn); 258 #endif /* !defined(HAS_APPLE_PAC) */ 259 return pfn; 260 } else { 261 // Not virtual, i.e. plain member func 262 return pfn; 263 } 264 #endif 265 } 266 267 #endif /* defined(__arm__) || defined(__arm64__) */ 268 /********************************************************************* 269 * These used to be inline in the header but gcc didn't believe us 270 * Now we MUST pull the inline out at least until the compiler is 271 * repaired. 272 * 273 * Helper inlines for runtime type preprocessor macros 274 *********************************************************************/ 275 276 /********************************************************************* 277 *********************************************************************/ 278 OSMetaClassBase * 279 OSMetaClassBase::safeMetaCast( 280 const OSMetaClassBase * me, 281 const OSMetaClass * toType) 282 { 283 return (me)? me->metaCast(toType) : NULL; 284 } 285 286 /// A helper function to crash with a kernel panic. 287 __attribute__((cold, not_tail_called, noreturn)) 288 static inline void 289 panic_crash_fail_cast(const OSMetaClassBase *me, 290 const OSMetaClass *toType) 291 { 292 panic("Unexpected cast fail: from %p to %p", me, toType); 293 __builtin_unreachable(); 294 } 295 296 OSMetaClassBase * 297 OSMetaClassBase::requiredMetaCast( 298 const OSMetaClassBase * me, 299 const OSMetaClass * toType) 300 { 301 if (!me) { 302 return NULL; 303 } 304 OSMetaClassBase *tmp = safeMetaCast(me, toType); 305 if (!tmp) { 306 panic_crash_fail_cast(me, toType); 307 } 308 return tmp; 309 } 310 311 /********************************************************************* 312 *********************************************************************/ 313 bool 314 OSMetaClassBase::checkTypeInst( 315 const OSMetaClassBase * inst, 316 const OSMetaClassBase * typeinst) 317 { 318 const OSMetaClass * toType = OSTypeIDInst(typeinst); 319 return typeinst && inst && (NULL != inst->metaCast(toType)); 320 } 321 322 /********************************************************************* 323 *********************************************************************/ 324 void 325 OSMetaClassBase:: 326 initialize() 327 { 328 sAllClassesLock = IOLockAlloc(); 329 sStalledClassesLock = IOLockAlloc(); 330 sInstancesLock = IOLockAlloc(); 331 } 332 333 #if APPLE_KEXT_VTABLE_PADDING 334 /********************************************************************* 335 * If you need this slot you had better setup an IOCTL style interface. 336 * 'Cause the whole kernel world depends on OSMetaClassBase and YOU 337 * CANT change the VTABLE size ever. 338 *********************************************************************/ 339 void 340 OSMetaClassBase::_RESERVEDOSMetaClassBase7() 341 { 342 panic("OSMetaClassBase::_RESERVEDOSMetaClassBase%d called.", 7); 343 } 344 #endif 345 346 /********************************************************************* 347 *********************************************************************/ 348 OSMetaClassBase::OSMetaClassBase() 349 { 350 } 351 352 /********************************************************************* 353 *********************************************************************/ 354 OSMetaClassBase::~OSMetaClassBase() 355 { 356 void ** thisVTable; 357 358 thisVTable = (void **) this; 359 *thisVTable = (void *) -1UL; 360 } 361 362 /********************************************************************* 363 *********************************************************************/ 364 bool 365 OSMetaClassBase::isEqualTo(const OSMetaClassBase * anObj) const 366 { 367 return this == anObj; 368 } 369 370 /********************************************************************* 371 *********************************************************************/ 372 OSMetaClassBase * 373 OSMetaClassBase::metaCast(const OSMetaClass * toMeta) const 374 { 375 return toMeta->checkMetaCast(this); 376 } 377 378 /********************************************************************* 379 *********************************************************************/ 380 OSMetaClassBase * 381 OSMetaClassBase::metaCast(const OSSymbol * toMetaSymb) const 382 { 383 return OSMetaClass::checkMetaCastWithName(toMetaSymb, this); 384 } 385 386 /********************************************************************* 387 *********************************************************************/ 388 OSMetaClassBase * 389 OSMetaClassBase::metaCast(const OSString * toMetaStr) const 390 { 391 const OSSymbol * tempSymb = OSSymbol::withString(toMetaStr); 392 OSMetaClassBase * ret = NULL; 393 if (tempSymb) { 394 ret = metaCast(tempSymb); 395 tempSymb->release(); 396 } 397 return ret; 398 } 399 400 /********************************************************************* 401 *********************************************************************/ 402 OSMetaClassBase * 403 OSMetaClassBase::metaCast(const char * toMetaCStr) const 404 { 405 const OSSymbol * tempSymb = OSSymbol::withCString(toMetaCStr); 406 OSMetaClassBase * ret = NULL; 407 if (tempSymb) { 408 ret = metaCast(tempSymb); 409 tempSymb->release(); 410 } 411 return ret; 412 } 413 414 #if PRAGMA_MARK 415 #pragma mark OSMetaClassMeta 416 #endif /* PRAGMA_MARK */ 417 /********************************************************************* 418 * OSMetaClassMeta - the bootstrap metaclass of OSMetaClass 419 *********************************************************************/ 420 class OSMetaClassMeta : public OSMetaClass 421 { 422 public: 423 OSMetaClassMeta(); 424 OSObject * alloc() const; 425 }; 426 OSMetaClassMeta::OSMetaClassMeta() 427 : OSMetaClass("OSMetaClass", NULL, sizeof(OSMetaClass)) 428 { 429 } 430 OSObject * 431 OSMetaClassMeta::alloc() const 432 { 433 return NULL; 434 } 435 436 static OSMetaClassMeta sOSMetaClassMeta; 437 438 const OSMetaClass * const OSMetaClass::metaClass = &sOSMetaClassMeta; 439 const OSMetaClass * 440 OSMetaClass::getMetaClass() const 441 { 442 return &sOSMetaClassMeta; 443 } 444 445 #if PRAGMA_MARK 446 #pragma mark OSMetaClass 447 #endif /* PRAGMA_MARK */ 448 /********************************************************************* 449 * OSMetaClass 450 *********************************************************************/ 451 452 #if APPLE_KEXT_VTABLE_PADDING 453 /********************************************************************* 454 * Reserved functions. 455 *********************************************************************/ 456 void 457 OSMetaClass::_RESERVEDOSMetaClass0() 458 { 459 panic("OSMetaClass::_RESERVEDOSMetaClass%d called", 0); 460 } 461 void 462 OSMetaClass::_RESERVEDOSMetaClass1() 463 { 464 panic("OSMetaClass::_RESERVEDOSMetaClass%d called", 1); 465 } 466 void 467 OSMetaClass::_RESERVEDOSMetaClass2() 468 { 469 panic("OSMetaClass::_RESERVEDOSMetaClass%d called", 2); 470 } 471 void 472 OSMetaClass::_RESERVEDOSMetaClass3() 473 { 474 panic("OSMetaClass::_RESERVEDOSMetaClass%d called", 3); 475 } 476 void 477 OSMetaClass::_RESERVEDOSMetaClass4() 478 { 479 panic("OSMetaClass::_RESERVEDOSMetaClass%d called", 4); 480 } 481 void 482 OSMetaClass::_RESERVEDOSMetaClass5() 483 { 484 panic("OSMetaClass::_RESERVEDOSMetaClass%d called", 5); 485 } 486 void 487 OSMetaClass::_RESERVEDOSMetaClass6() 488 { 489 panic("OSMetaClass::_RESERVEDOSMetaClass%d called", 6); 490 } 491 void 492 OSMetaClass::_RESERVEDOSMetaClass7() 493 { 494 panic("OSMetaClass::_RESERVEDOSMetaClass%d called", 7); 495 } 496 #endif 497 498 /********************************************************************* 499 *********************************************************************/ 500 static void 501 OSMetaClassLogErrorForKext( 502 OSReturn error, 503 OSKext * aKext) 504 { 505 const char * message = NULL; 506 507 switch (error) { 508 case kOSReturnSuccess: 509 return; 510 case kOSMetaClassNoInit: // xxx - never returned; logged at fail site 511 message = "OSMetaClass: preModLoad() wasn't called (runtime internal error)."; 512 break; 513 case kOSMetaClassNoDicts: 514 message = "OSMetaClass: Allocation failure for OSMetaClass internal dictionaries."; 515 break; 516 case kOSMetaClassNoKModSet: 517 message = "OSMetaClass: Allocation failure for internal kext recording set/set missing."; 518 break; 519 case kOSMetaClassNoInsKModSet: 520 message = "OSMetaClass: Failed to record class in kext."; 521 break; 522 case kOSMetaClassDuplicateClass: 523 message = "OSMetaClass: Duplicate class encountered."; 524 break; 525 case kOSMetaClassNoSuper: // xxx - never returned 526 message = "OSMetaClass: Can't associate a class with its superclass."; 527 break; 528 case kOSMetaClassInstNoSuper: // xxx - never returned 529 message = "OSMetaClass: Instance construction error; unknown superclass."; 530 break; 531 case kOSMetaClassNoKext: 532 message = "OSMetaClass: Kext not found for metaclass."; 533 break; 534 case kOSMetaClassInternal: 535 default: 536 message = "OSMetaClass: Runtime internal error."; 537 break; 538 } 539 540 if (message) { 541 OSKextLog(aKext, kOSMetaClassLogSpec, "%s", message); 542 } 543 return; 544 } 545 546 void 547 OSMetaClass::logError(OSReturn error) 548 { 549 OSMetaClassLogErrorForKext(error, NULL); 550 } 551 552 /********************************************************************* 553 * The core constructor for a MetaClass (defined with this name always 554 * but within the scope of its represented class). 555 * 556 * MetaClass constructors are invoked in OSRuntimeInitializeCPP(), 557 * in between calls to OSMetaClass::preModLoad(), which sets up for 558 * registration, and OSMetaClass::postModLoad(), which actually 559 * records all the class/kext relationships of the new MetaClasses. 560 *********************************************************************/ 561 562 OSMetaClass::OSMetaClass( 563 const char * inClassName, 564 const OSMetaClass * inSuperClass, 565 unsigned int inClassSize) 566 { 567 instanceCount = 0; 568 classSize = inClassSize; 569 superClassLink = inSuperClass; 570 571 reserved = IONew(ExpansionData, 1); 572 bzero(reserved, sizeof(ExpansionData)); 573 #if IOTRACKING 574 uint32_t numSiteQs = 0; 575 if ((this == &OSSymbol ::gMetaClass) 576 || (this == &OSString ::gMetaClass) 577 || (this == &OSNumber ::gMetaClass) 578 || (this == &OSString ::gMetaClass) 579 || (this == &OSData ::gMetaClass) 580 || (this == &OSDictionary::gMetaClass) 581 || (this == &OSArray ::gMetaClass) 582 || (this == &OSSet ::gMetaClass)) { 583 numSiteQs = 27; 584 } 585 586 reserved->tracking = IOTrackingQueueAlloc(inClassName, (uintptr_t) this, 587 inClassSize, 0, kIOTrackingQueueTypeAlloc, 588 numSiteQs); 589 #endif 590 591 /* Hack alert: We are just casting inClassName and storing it in 592 * an OSString * instance variable. This may be because you can't 593 * create C++ objects in static constructors, but I really don't know! 594 */ 595 className = (const OSSymbol *)inClassName; 596 597 // sStalledClassesLock taken in preModLoad 598 if (!sStalled) { 599 /* There's no way we can look up the kext here, unfortunately. 600 */ 601 OSKextLog(/* kext */ NULL, kOSMetaClassLogSpec, 602 "OSMetaClass: preModLoad() wasn't called for class %s " 603 "(runtime internal error).", 604 inClassName); 605 } else if (!sStalled->result) { 606 // Grow stalled array if neccessary 607 if (sStalled->count >= sStalled->capacity) { 608 OSMetaClass **oldStalled = sStalled->classes; 609 int oldSize = sStalled->capacity * sizeof(OSMetaClass *); 610 int newSize = oldSize 611 + kKModCapacityIncrement * sizeof(OSMetaClass *); 612 613 sStalled->classes = (OSMetaClass **)kalloc_tag(newSize, VM_KERN_MEMORY_OSKEXT); 614 if (!sStalled->classes) { 615 sStalled->classes = oldStalled; 616 sStalled->result = kOSMetaClassNoTempData; 617 return; 618 } 619 620 sStalled->capacity += kKModCapacityIncrement; 621 memmove(sStalled->classes, oldStalled, oldSize); 622 kfree(oldStalled, oldSize); 623 OSMETA_ACCUMSIZE(((size_t)newSize) - ((size_t)oldSize)); 624 } 625 626 sStalled->classes[sStalled->count++] = this; 627 } 628 } 629 630 /********************************************************************* 631 *********************************************************************/ 632 OSMetaClass::~OSMetaClass() 633 { 634 OSKext * myKext = reserved ? reserved->kext : NULL; // do not release 635 636 /* Hack alert: 'className' is a C string during early C++ init, and 637 * is converted to a real OSSymbol only when we record the OSKext in 638 * OSMetaClass::postModLoad(). So only do this bit if we have an OSKext. 639 * We can't safely cast or check 'className'. 640 * 641 * Also, release className *after* calling into the kext, 642 * as removeClass() may access className. 643 */ 644 IOLockLock(sAllClassesLock); 645 if (sAllClassesDict) { 646 if (myKext) { 647 sAllClassesDict->removeObject(className); 648 } else { 649 sAllClassesDict->removeObject((const char *)className); 650 } 651 } 652 IOLockUnlock(sAllClassesLock); 653 654 if (myKext) { 655 if (myKext->removeClass(this) != kOSReturnSuccess) { 656 // xxx - what can we do? 657 } 658 className->release(); 659 } 660 661 // sStalledClassesLock taken in preModLoad 662 if (sStalled) { 663 unsigned int i; 664 665 /* First pass find class in stalled list. If we find it that means 666 * we started C++ init with constructors but now we're tearing down 667 * because of some failure. 668 */ 669 for (i = 0; i < sStalled->count; i++) { 670 if (this == sStalled->classes[i]) { 671 break; 672 } 673 } 674 675 /* Remove this metaclass from the stalled list so postModLoad() doesn't 676 * try to register it. 677 */ 678 if (i < sStalled->count) { 679 sStalled->count--; 680 if (i < sStalled->count) { 681 memmove(&sStalled->classes[i], &sStalled->classes[i + 1], 682 (sStalled->count - i) * sizeof(OSMetaClass *)); 683 } 684 } 685 } 686 #if IOTRACKING 687 IOTrackingQueueFree(reserved->tracking); 688 #endif 689 IODelete(reserved, ExpansionData, 1); 690 } 691 692 /********************************************************************* 693 * Empty overrides. 694 *********************************************************************/ 695 void 696 OSMetaClass::retain() const 697 { 698 } 699 void 700 OSMetaClass::release() const 701 { 702 } 703 void 704 OSMetaClass::release(__unused int when) const 705 { 706 } 707 void 708 OSMetaClass::taggedRetain(__unused const void * tag) const 709 { 710 } 711 void 712 OSMetaClass::taggedRelease(__unused const void * tag) const 713 { 714 } 715 void 716 OSMetaClass::taggedRelease(__unused const void * tag, __unused const int when) const 717 { 718 } 719 int 720 OSMetaClass::getRetainCount() const 721 { 722 return 0; 723 } 724 725 /********************************************************************* 726 *********************************************************************/ 727 const char * 728 OSMetaClass::getClassName() const 729 { 730 if (!className) { 731 return NULL; 732 } 733 return className->getCStringNoCopy(); 734 } 735 /********************************************************************* 736 *********************************************************************/ 737 const OSSymbol * 738 OSMetaClass::getClassNameSymbol() const 739 { 740 return className; 741 } 742 /********************************************************************* 743 *********************************************************************/ 744 unsigned int 745 OSMetaClass::getClassSize() const 746 { 747 return classSize; 748 } 749 750 /********************************************************************* 751 *********************************************************************/ 752 void * 753 OSMetaClass::preModLoad(const char * kextIdentifier) 754 { 755 IOLockLock(sStalledClassesLock); 756 757 assert(sStalled == NULL); 758 sStalled = (StalledData *)kalloc_tag(sizeof(*sStalled), VM_KERN_MEMORY_OSKEXT); 759 if (sStalled) { 760 sStalled->classes = (OSMetaClass **) 761 kalloc_tag(kKModCapacityIncrement * sizeof(OSMetaClass *), VM_KERN_MEMORY_OSKEXT); 762 if (!sStalled->classes) { 763 kfree(sStalled, sizeof(*sStalled)); 764 return NULL; 765 } 766 OSMETA_ACCUMSIZE((kKModCapacityIncrement * sizeof(OSMetaClass *)) + 767 sizeof(*sStalled)); 768 769 sStalled->result = kOSReturnSuccess; 770 sStalled->capacity = kKModCapacityIncrement; 771 sStalled->count = 0; 772 sStalled->kextIdentifier = kextIdentifier; 773 bzero(sStalled->classes, kKModCapacityIncrement * sizeof(OSMetaClass *)); 774 } 775 776 // keep sStalledClassesLock locked until postModLoad 777 778 return sStalled; 779 } 780 781 /********************************************************************* 782 *********************************************************************/ 783 bool 784 OSMetaClass::checkModLoad(void * loadHandle) 785 { 786 return sStalled && loadHandle == sStalled && 787 sStalled->result == kOSReturnSuccess; 788 } 789 790 /********************************************************************* 791 *********************************************************************/ 792 OSReturn 793 OSMetaClass::postModLoad(void * loadHandle) 794 { 795 OSReturn result = kOSReturnSuccess; 796 OSSymbol * myKextName = NULL;// must release 797 OSKext * myKext = NULL;// must release 798 799 if (!sStalled || loadHandle != sStalled) { 800 result = kOSMetaClassInternal; 801 goto finish; 802 } 803 804 if (sStalled->result) { 805 result = sStalled->result; 806 } else { 807 switch (sBootstrapState) { 808 case kNoDictionaries: 809 sBootstrapState = kMakingDictionaries; 810 // No break; fall through 811 [[clang::fallthrough]]; 812 813 case kMakingDictionaries: 814 sAllClassesDict = OSDictionary::withCapacity(kClassCapacityIncrement); 815 if (!sAllClassesDict) { 816 result = kOSMetaClassNoDicts; 817 break; 818 } 819 sAllClassesDict->setOptions(OSCollection::kSort, OSCollection::kSort); 820 821 // No break; fall through 822 [[clang::fallthrough]]; 823 824 case kCompletedBootstrap: 825 { 826 unsigned int i; 827 myKextName = const_cast<OSSymbol *>(OSSymbol::withCStringNoCopy( 828 sStalled->kextIdentifier)); 829 830 if (!sStalled->count) { 831 break; // Nothing to do so just get out 832 } 833 834 myKext = OSKext::lookupKextWithIdentifier(myKextName); 835 if (!myKext) { 836 result = kOSMetaClassNoKext; 837 838 /* Log this error here so we can include the kext name. 839 */ 840 OSKextLog(/* kext */ NULL, kOSMetaClassLogSpec, 841 "OSMetaClass: Can't record classes for kext %s - kext not found.", 842 sStalled->kextIdentifier); 843 break; 844 } 845 846 /* First pass checking classes aren't already loaded. If any already 847 * exist, we don't register any, and so we don't technically have 848 * to do any C++ teardown. 849 * 850 * Hack alert: me->className has been a C string until now. 851 * We only release the OSSymbol if we store the kext. 852 */ 853 IOLockLock(sAllClassesLock); 854 for (i = 0; i < sStalled->count; i++) { 855 const OSMetaClass * me = sStalled->classes[i]; 856 OSMetaClass * orig = OSDynamicCast(OSMetaClass, 857 sAllClassesDict->getObject((const char *)me->className)); 858 859 if (orig) { 860 /* Log this error here so we can include the class name. 861 * xxx - we should look up the other kext that defines the class 862 */ 863 #if CONFIG_EMBEDDED 864 panic( 865 #else 866 OSKextLog(myKext, kOSMetaClassLogSpec, 867 #endif /* CONFIG_EMBEDDED */ 868 "OSMetaClass: Kext %s class %s is a duplicate;" 869 "kext %s already has a class by that name.", 870 sStalled->kextIdentifier, (const char *)me->className, 871 ((OSKext *)orig->reserved->kext)->getIdentifierCString()); 872 result = kOSMetaClassDuplicateClass; 873 break; 874 } 875 unsigned int depth = 1; 876 while ((me = me->superClassLink)) { 877 depth++; 878 } 879 if (depth > sDeepestClass) { 880 sDeepestClass = depth; 881 } 882 } 883 IOLockUnlock(sAllClassesLock); 884 885 /* Bail if we didn't go through the entire list of new classes 886 * (if we hit a duplicate). 887 */ 888 if (i != sStalled->count) { 889 break; 890 } 891 892 // Second pass symbolling strings and inserting classes in dictionary 893 IOLockLock(sAllClassesLock); 894 for (i = 0; i < sStalled->count; i++) { 895 OSMetaClass * me = sStalled->classes[i]; 896 897 /* Hack alert: me->className has been a C string until now. 898 * We only release the OSSymbol in ~OSMetaClass() 899 * if we set the reference to the kext. 900 */ 901 me->className = 902 OSSymbol::withCStringNoCopy((const char *)me->className); 903 904 // xxx - I suppose if these fail we're going to panic soon.... 905 sAllClassesDict->setObject(me->className, me); 906 907 /* Do not retain the kext object here. 908 */ 909 me->reserved->kext = myKext; 910 if (myKext) { 911 result = myKext->addClass(me, sStalled->count); 912 if (result != kOSReturnSuccess) { 913 /* OSKext::addClass() logs with kOSMetaClassNoInsKModSet. */ 914 break; 915 } 916 } 917 } 918 IOLockUnlock(sAllClassesLock); 919 sBootstrapState = kCompletedBootstrap; 920 break; 921 } 922 923 default: 924 result = kOSMetaClassInternal; 925 break; 926 } 927 } 928 929 finish: 930 /* Don't call logError() for success or the conditions logged above 931 * or by called function. 932 */ 933 if (result != kOSReturnSuccess && 934 result != kOSMetaClassNoInsKModSet && 935 result != kOSMetaClassDuplicateClass && 936 result != kOSMetaClassNoKext) { 937 OSMetaClassLogErrorForKext(result, myKext); 938 } 939 940 OSSafeReleaseNULL(myKextName); 941 OSSafeReleaseNULL(myKext); 942 943 if (sStalled) { 944 OSMETA_ACCUMSIZE(-(sStalled->capacity * sizeof(OSMetaClass *) + 945 sizeof(*sStalled))); 946 kfree(sStalled->classes, sStalled->capacity * sizeof(OSMetaClass *)); 947 kfree(sStalled, sizeof(*sStalled)); 948 sStalled = NULL; 949 } 950 951 IOLockUnlock(sStalledClassesLock); 952 953 return result; 954 } 955 956 957 /********************************************************************* 958 *********************************************************************/ 959 void 960 OSMetaClass::instanceConstructed() const 961 { 962 // if ((0 == OSIncrementAtomic(&(((OSMetaClass *) this)->instanceCount))) && superClassLink) 963 if ((0 == OSIncrementAtomic(&instanceCount)) && superClassLink) { 964 superClassLink->instanceConstructed(); 965 } 966 } 967 968 /********************************************************************* 969 *********************************************************************/ 970 void 971 OSMetaClass::instanceDestructed() const 972 { 973 if ((1 == OSDecrementAtomic(&instanceCount)) && superClassLink) { 974 superClassLink->instanceDestructed(); 975 } 976 977 if (((int)instanceCount) < 0) { 978 OSKext * myKext = reserved->kext; 979 980 OSKextLog(myKext, kOSMetaClassLogSpec, 981 // xxx - this phrasing is rather cryptic 982 "OSMetaClass: Class %s - bad retain (%d)", 983 getClassName(), instanceCount); 984 } 985 } 986 987 /********************************************************************* 988 *********************************************************************/ 989 bool 990 OSMetaClass::modHasInstance(const char * kextIdentifier) 991 { 992 bool result = false; 993 OSKext * theKext = NULL; // must release 994 995 theKext = OSKext::lookupKextWithIdentifier(kextIdentifier); 996 if (!theKext) { 997 goto finish; 998 } 999 1000 result = theKext->hasOSMetaClassInstances(); 1001 1002 finish: 1003 OSSafeReleaseNULL(theKext); 1004 return result; 1005 } 1006 1007 /********************************************************************* 1008 *********************************************************************/ 1009 void 1010 OSMetaClass::reportModInstances(const char * kextIdentifier) 1011 { 1012 OSKext::reportOSMetaClassInstances(kextIdentifier, 1013 kOSKextLogExplicitLevel); 1014 return; 1015 } 1016 /********************************************************************* 1017 *********************************************************************/ 1018 1019 void 1020 OSMetaClass::addInstance(const OSObject * instance, bool super) const 1021 { 1022 if (!super) { 1023 IOLockLock(sInstancesLock); 1024 } 1025 1026 if (!reserved->instances) { 1027 reserved->instances = OSOrderedSet::withCapacity(16); 1028 if (superClassLink) { 1029 superClassLink->addInstance(reserved->instances, true); 1030 } 1031 } 1032 reserved->instances->setLastObject(instance); 1033 1034 if (!super) { 1035 IOLockUnlock(sInstancesLock); 1036 } 1037 } 1038 1039 void 1040 OSMetaClass::removeInstance(const OSObject * instance, bool super) const 1041 { 1042 if (!super) { 1043 IOLockLock(sInstancesLock); 1044 } 1045 1046 if (reserved->instances) { 1047 reserved->instances->removeObject(instance); 1048 if (0 == reserved->instances->getCount()) { 1049 if (superClassLink) { 1050 superClassLink->removeInstance(reserved->instances, true); 1051 } 1052 IOLockLock(sAllClassesLock); 1053 reserved->instances->release(); 1054 reserved->instances = NULL; 1055 IOLockUnlock(sAllClassesLock); 1056 } 1057 } 1058 1059 if (!super) { 1060 IOLockUnlock(sInstancesLock); 1061 } 1062 } 1063 1064 void 1065 OSMetaClass::applyToInstances(OSOrderedSet * set, 1066 OSMetaClassInstanceApplierFunction applier, 1067 void * context) 1068 { 1069 enum { kLocalDepth = 24 }; 1070 unsigned int _nextIndex[kLocalDepth]; 1071 OSOrderedSet * _sets[kLocalDepth]; 1072 unsigned int * nextIndex = &_nextIndex[0]; 1073 OSOrderedSet ** sets = &_sets[0]; 1074 OSObject * obj; 1075 OSOrderedSet * childSet; 1076 unsigned int maxDepth; 1077 unsigned int idx; 1078 unsigned int level; 1079 bool done; 1080 1081 maxDepth = sDeepestClass; 1082 if (maxDepth > kLocalDepth) { 1083 nextIndex = IONew(typeof(nextIndex[0]), maxDepth); 1084 sets = IONew(typeof(sets[0]), maxDepth); 1085 } 1086 done = false; 1087 level = 0; 1088 idx = 0; 1089 do{ 1090 while (!done && (obj = set->getObject(idx++))) { 1091 if ((childSet = OSDynamicCast(OSOrderedSet, obj))) { 1092 if (level >= maxDepth) { 1093 panic(">maxDepth"); 1094 } 1095 sets[level] = set; 1096 nextIndex[level] = idx; 1097 level++; 1098 set = childSet; 1099 idx = 0; 1100 break; 1101 } 1102 done = (*applier)(obj, context); 1103 } 1104 if (!obj) { 1105 if (!done && level) { 1106 level--; 1107 set = sets[level]; 1108 idx = nextIndex[level]; 1109 } else { 1110 done = true; 1111 } 1112 } 1113 }while (!done); 1114 if (maxDepth > kLocalDepth) { 1115 IODelete(nextIndex, typeof(nextIndex[0]), maxDepth); 1116 IODelete(sets, typeof(sets[0]), maxDepth); 1117 } 1118 } 1119 1120 void 1121 OSMetaClass::applyToInstances(OSMetaClassInstanceApplierFunction applier, 1122 void * context) const 1123 { 1124 IOLockLock(sInstancesLock); 1125 if (reserved->instances) { 1126 applyToInstances(reserved->instances, applier, context); 1127 } 1128 IOLockUnlock(sInstancesLock); 1129 } 1130 1131 void 1132 OSMetaClass::applyToInstancesOfClassName( 1133 const OSSymbol * name, 1134 OSMetaClassInstanceApplierFunction applier, 1135 void * context) 1136 { 1137 OSMetaClass * meta; 1138 OSOrderedSet * set = NULL; 1139 1140 IOLockLock(sAllClassesLock); 1141 if (sAllClassesDict 1142 && (meta = (OSMetaClass *) sAllClassesDict->getObject(name)) 1143 && (set = meta->reserved->instances)) { 1144 set->retain(); 1145 } 1146 IOLockUnlock(sAllClassesLock); 1147 1148 if (!set) { 1149 return; 1150 } 1151 1152 IOLockLock(sInstancesLock); 1153 applyToInstances(set, applier, context); 1154 IOLockUnlock(sInstancesLock); 1155 set->release(); 1156 } 1157 1158 /********************************************************************* 1159 *********************************************************************/ 1160 void 1161 OSMetaClass::considerUnloads() 1162 { 1163 OSKext::considerUnloads(); 1164 } 1165 1166 /********************************************************************* 1167 *********************************************************************/ 1168 bool 1169 OSMetaClass::removeClasses(OSCollection * metaClasses) 1170 { 1171 OSCollectionIterator * classIterator; 1172 OSMetaClass * checkClass; 1173 bool result; 1174 1175 classIterator = OSCollectionIterator::withCollection(metaClasses); 1176 if (!classIterator) { 1177 return false; 1178 } 1179 1180 IOLockLock(sAllClassesLock); 1181 1182 result = false; 1183 do{ 1184 while ((checkClass = (OSMetaClass *)classIterator->getNextObject()) 1185 && !checkClass->getInstanceCount() 1186 && !checkClass->reserved->retain) { 1187 } 1188 if (checkClass) { 1189 break; 1190 } 1191 classIterator->reset(); 1192 while ((checkClass = (OSMetaClass *)classIterator->getNextObject())) { 1193 sAllClassesDict->removeObject(checkClass->className); 1194 } 1195 result = true; 1196 }while (false); 1197 1198 IOLockUnlock(sAllClassesLock); 1199 OSSafeReleaseNULL(classIterator); 1200 1201 return result; 1202 } 1203 1204 1205 /********************************************************************* 1206 *********************************************************************/ 1207 const OSMetaClass * 1208 OSMetaClass::getMetaClassWithName(const OSSymbol * name) 1209 { 1210 OSMetaClass * retMeta = NULL; 1211 1212 if (!name) { 1213 return NULL; 1214 } 1215 1216 IOLockLock(sAllClassesLock); 1217 if (sAllClassesDict) { 1218 retMeta = (OSMetaClass *) sAllClassesDict->getObject(name); 1219 } 1220 IOLockUnlock(sAllClassesLock); 1221 1222 return retMeta; 1223 } 1224 1225 /********************************************************************* 1226 *********************************************************************/ 1227 const OSMetaClass * 1228 OSMetaClass::copyMetaClassWithName(const OSSymbol * name) 1229 { 1230 const OSMetaClass * meta; 1231 1232 if (!name) { 1233 return NULL; 1234 } 1235 1236 meta = NULL; 1237 IOLockLock(sAllClassesLock); 1238 if (sAllClassesDict) { 1239 meta = (OSMetaClass *) sAllClassesDict->getObject(name); 1240 if (meta) { 1241 OSIncrementAtomic(&meta->reserved->retain); 1242 } 1243 } 1244 IOLockUnlock(sAllClassesLock); 1245 1246 return meta; 1247 } 1248 1249 /********************************************************************* 1250 *********************************************************************/ 1251 void 1252 OSMetaClass::releaseMetaClass() const 1253 { 1254 OSDecrementAtomic(&reserved->retain); 1255 } 1256 1257 /********************************************************************* 1258 *********************************************************************/ 1259 OSObject * 1260 OSMetaClass::allocClassWithName(const OSSymbol * name) 1261 { 1262 const OSMetaClass * meta; 1263 OSObject * result; 1264 1265 result = NULL; 1266 meta = copyMetaClassWithName(name); 1267 if (meta) { 1268 result = meta->alloc(); 1269 meta->releaseMetaClass(); 1270 } 1271 1272 return result; 1273 } 1274 1275 /********************************************************************* 1276 *********************************************************************/ 1277 OSObject * 1278 OSMetaClass::allocClassWithName(const OSString * name) 1279 { 1280 const OSSymbol * tmpKey = OSSymbol::withString(name); 1281 OSObject * result = allocClassWithName(tmpKey); 1282 tmpKey->release(); 1283 return result; 1284 } 1285 1286 /********************************************************************* 1287 *********************************************************************/ 1288 OSObject * 1289 OSMetaClass::allocClassWithName(const char * name) 1290 { 1291 const OSSymbol * tmpKey = OSSymbol::withCStringNoCopy(name); 1292 OSObject * result = allocClassWithName(tmpKey); 1293 tmpKey->release(); 1294 return result; 1295 } 1296 1297 1298 /********************************************************************* 1299 *********************************************************************/ 1300 OSMetaClassBase * 1301 OSMetaClass::checkMetaCastWithName( 1302 const OSSymbol * name, 1303 const OSMetaClassBase * in) 1304 { 1305 OSMetaClassBase * result = NULL; 1306 1307 const OSMetaClass * const meta = getMetaClassWithName(name); 1308 1309 if (meta) { 1310 result = meta->checkMetaCast(in); 1311 } 1312 1313 return result; 1314 } 1315 1316 /********************************************************************* 1317 *********************************************************************/ 1318 OSMetaClassBase * 1319 OSMetaClass:: 1320 checkMetaCastWithName( 1321 const OSString * name, 1322 const OSMetaClassBase * in) 1323 { 1324 const OSSymbol * tmpKey = OSSymbol::withString(name); 1325 OSMetaClassBase * result = checkMetaCastWithName(tmpKey, in); 1326 1327 tmpKey->release(); 1328 return result; 1329 } 1330 1331 /********************************************************************* 1332 *********************************************************************/ 1333 OSMetaClassBase * 1334 OSMetaClass::checkMetaCastWithName( 1335 const char * name, 1336 const OSMetaClassBase * in) 1337 { 1338 const OSSymbol * tmpKey = OSSymbol::withCStringNoCopy(name); 1339 OSMetaClassBase * result = checkMetaCastWithName(tmpKey, in); 1340 1341 tmpKey->release(); 1342 return result; 1343 } 1344 1345 /********************************************************************* 1346 * OSMetaClass::checkMetaCast() 1347 * Check to see if the 'check' object has this object in its metaclass chain. 1348 * Returns check if it is indeed a kind of the current meta class, 0 otherwise. 1349 * 1350 * Generally this method is not invoked directly but is used to implement 1351 * the OSMetaClassBase::metaCast member function. 1352 * 1353 * See also OSMetaClassBase::metaCast 1354 *********************************************************************/ 1355 OSMetaClassBase * 1356 OSMetaClass::checkMetaCast( 1357 const OSMetaClassBase * check) const 1358 { 1359 const OSMetaClass * const toMeta = this; 1360 const OSMetaClass * fromMeta; 1361 1362 for (fromMeta = check->getMetaClass();; fromMeta = fromMeta->superClassLink) { 1363 if (toMeta == fromMeta) { 1364 return const_cast<OSMetaClassBase *>(check); // Discard const 1365 } 1366 if (!fromMeta->superClassLink) { 1367 break; 1368 } 1369 } 1370 1371 return NULL; 1372 } 1373 1374 /********************************************************************* 1375 *********************************************************************/ 1376 __dead2 1377 void 1378 OSMetaClass::reservedCalled(int ind) const 1379 { 1380 const char * cname = className->getCStringNoCopy(); 1381 panic("%s::_RESERVED%s%d called.", cname, cname, ind); 1382 } 1383 1384 /********************************************************************* 1385 *********************************************************************/ 1386 const 1387 OSMetaClass * 1388 OSMetaClass::getSuperClass() const 1389 { 1390 return superClassLink; 1391 } 1392 1393 /********************************************************************* 1394 * xxx - I want to rename this :-/ 1395 *********************************************************************/ 1396 const OSSymbol * 1397 OSMetaClass::getKmodName() const 1398 { 1399 OSKext * myKext = reserved ? reserved->kext : NULL; 1400 if (myKext) { 1401 return myKext->getIdentifier(); 1402 } 1403 return OSSymbol::withCStringNoCopy("unknown"); 1404 } 1405 1406 /********************************************************************* 1407 *********************************************************************/ 1408 unsigned int 1409 OSMetaClass::getInstanceCount() const 1410 { 1411 return instanceCount; 1412 } 1413 1414 /********************************************************************* 1415 *********************************************************************/ 1416 /* static */ 1417 void 1418 OSMetaClass::printInstanceCounts() 1419 { 1420 OSCollectionIterator * classes; 1421 OSSymbol * className; 1422 OSMetaClass * meta; 1423 1424 IOLockLock(sAllClassesLock); 1425 classes = OSCollectionIterator::withCollection(sAllClassesDict); 1426 assert(classes); 1427 1428 while ((className = (OSSymbol *)classes->getNextObject())) { 1429 meta = (OSMetaClass *)sAllClassesDict->getObject(className); 1430 assert(meta); 1431 1432 printf("%24s count: %03d x 0x%03x = 0x%06x\n", 1433 className->getCStringNoCopy(), 1434 meta->getInstanceCount(), 1435 meta->getClassSize(), 1436 meta->getInstanceCount() * meta->getClassSize()); 1437 } 1438 printf("\n"); 1439 classes->release(); 1440 IOLockUnlock(sAllClassesLock); 1441 return; 1442 } 1443 1444 /********************************************************************* 1445 *********************************************************************/ 1446 OSDictionary * 1447 OSMetaClass::getClassDictionary() 1448 { 1449 panic("OSMetaClass::getClassDictionary() is obsoleted.\n"); 1450 return NULL; 1451 } 1452 1453 /********************************************************************* 1454 *********************************************************************/ 1455 bool 1456 OSMetaClass::serialize(__unused OSSerialize * s) const 1457 { 1458 panic("OSMetaClass::serialize(): Obsoleted\n"); 1459 return false; 1460 } 1461 1462 /********************************************************************* 1463 *********************************************************************/ 1464 /* static */ 1465 void 1466 OSMetaClass::serializeClassDictionary(OSDictionary * serializeDictionary) 1467 { 1468 OSDictionary * classDict = NULL; 1469 1470 IOLockLock(sAllClassesLock); 1471 1472 classDict = OSDictionary::withCapacity(sAllClassesDict->getCount()); 1473 if (!classDict) { 1474 goto finish; 1475 } 1476 1477 do { 1478 OSCollectionIterator * classes; 1479 const OSSymbol * className; 1480 1481 classes = OSCollectionIterator::withCollection(sAllClassesDict); 1482 if (!classes) { 1483 break; 1484 } 1485 1486 while ((className = (const OSSymbol *)classes->getNextObject())) { 1487 const OSMetaClass * meta; 1488 OSNumber * count; 1489 1490 meta = (OSMetaClass *)sAllClassesDict->getObject(className); 1491 count = OSNumber::withNumber(meta->getInstanceCount(), 32); 1492 if (count) { 1493 classDict->setObject(className, count); 1494 count->release(); 1495 } 1496 } 1497 classes->release(); 1498 1499 serializeDictionary->setObject("Classes", classDict); 1500 } while (0); 1501 1502 finish: 1503 OSSafeReleaseNULL(classDict); 1504 1505 IOLockUnlock(sAllClassesLock); 1506 1507 return; 1508 } 1509 1510 1511 /********************************************************************* 1512 *********************************************************************/ 1513 1514 #if IOTRACKING 1515 1516 void * 1517 OSMetaClass::trackedNew(size_t size) 1518 { 1519 IOTracking * mem; 1520 1521 mem = (typeof(mem))kalloc_tag_bt(size + sizeof(IOTracking), VM_KERN_MEMORY_LIBKERN); 1522 assert(mem); 1523 if (!mem) { 1524 return mem; 1525 } 1526 1527 memset(mem, 0, size + sizeof(IOTracking)); 1528 mem++; 1529 1530 OSIVAR_ACCUMSIZE(size); 1531 1532 return mem; 1533 } 1534 1535 void 1536 OSMetaClass::trackedDelete(void * instance, size_t size) 1537 { 1538 IOTracking * mem = (typeof(mem))instance; mem--; 1539 1540 kfree(mem, size + sizeof(IOTracking)); 1541 OSIVAR_ACCUMSIZE(-size); 1542 } 1543 1544 void 1545 OSMetaClass::trackedInstance(OSObject * instance) const 1546 { 1547 IOTracking * mem = (typeof(mem))instance; mem--; 1548 1549 return IOTrackingAdd(reserved->tracking, mem, classSize, false, VM_KERN_MEMORY_NONE); 1550 } 1551 1552 void 1553 OSMetaClass::trackedFree(OSObject * instance) const 1554 { 1555 IOTracking * mem = (typeof(mem))instance; mem--; 1556 1557 return IOTrackingRemove(reserved->tracking, mem, classSize); 1558 } 1559 1560 void 1561 OSMetaClass::trackedAccumSize(OSObject * instance, size_t size) const 1562 { 1563 IOTracking * mem = (typeof(mem))instance; mem--; 1564 1565 return IOTrackingAccumSize(reserved->tracking, mem, size); 1566 } 1567 1568 IOTrackingQueue * 1569 OSMetaClass::getTracking() const 1570 { 1571 return reserved->tracking; 1572 } 1573 1574 #endif /* IOTRACKING */ 1575