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