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 = IONew(ExpansionData, 1); 584 bzero(reserved, sizeof(ExpansionData)); 585 #if IOTRACKING 586 uint32_t numSiteQs = 0; 587 if ((this == &OSSymbol ::gMetaClass) 588 || (this == &OSString ::gMetaClass) 589 || (this == &OSNumber ::gMetaClass) 590 || (this == &OSString ::gMetaClass) 591 || (this == &OSData ::gMetaClass) 592 || (this == &OSDictionary::gMetaClass) 593 || (this == &OSArray ::gMetaClass) 594 || (this == &OSSet ::gMetaClass)) { 595 numSiteQs = 27; 596 } 597 598 reserved->tracking = IOTrackingQueueAlloc(inClassName, (uintptr_t) this, 599 inClassSize, 0, kIOTrackingQueueTypeAlloc, 600 numSiteQs); 601 #endif 602 603 /* Hack alert: We are just casting inClassName and storing it in 604 * an OSString * instance variable. This may be because you can't 605 * create C++ objects in static constructors, but I really don't know! 606 */ 607 className = (const OSSymbol *)inClassName; 608 609 // sStalledClassesLock taken in preModLoad 610 if (!sStalled) { 611 /* There's no way we can look up the kext here, unfortunately. 612 */ 613 OSKextLog(/* kext */ NULL, kOSMetaClassLogSpec, 614 "OSMetaClass: preModLoad() wasn't called for class %s " 615 "(runtime internal error).", 616 inClassName); 617 } else if (!sStalled->result) { 618 // Grow stalled array if neccessary 619 if (sStalled->count >= sStalled->capacity) { 620 OSMetaClass **oldStalled = sStalled->classes; 621 int oldSize = sStalled->capacity * sizeof(OSMetaClass *); 622 int newSize = oldSize 623 + kKModCapacityIncrement * sizeof(OSMetaClass *); 624 625 sStalled->classes = (OSMetaClass **)kalloc_tag(newSize, VM_KERN_MEMORY_OSKEXT); 626 if (!sStalled->classes) { 627 sStalled->classes = oldStalled; 628 sStalled->result = kOSMetaClassNoTempData; 629 return; 630 } 631 632 sStalled->capacity += kKModCapacityIncrement; 633 memmove(sStalled->classes, oldStalled, oldSize); 634 kfree(oldStalled, oldSize); 635 OSMETA_ACCUMSIZE(((size_t)newSize) - ((size_t)oldSize)); 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 IODelete(reserved, ExpansionData, 1); 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 = (StalledData *)kalloc_tag(sizeof(*sStalled), VM_KERN_MEMORY_OSKEXT); 786 if (sStalled) { 787 sStalled->classes = (OSMetaClass **) 788 kalloc_tag(kKModCapacityIncrement * sizeof(OSMetaClass *), VM_KERN_MEMORY_OSKEXT); 789 if (!sStalled->classes) { 790 kfree(sStalled, sizeof(*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 bzero(sStalled->classes, kKModCapacityIncrement * sizeof(OSMetaClass *)); 801 } 802 803 // keep sStalledClassesLock locked until postModLoad 804 805 return sStalled; 806 } 807 808 /********************************************************************* 809 *********************************************************************/ 810 bool 811 OSMetaClass::checkModLoad(void * loadHandle) 812 { 813 return sStalled && loadHandle == sStalled && 814 sStalled->result == kOSReturnSuccess; 815 } 816 817 /********************************************************************* 818 *********************************************************************/ 819 OSReturn 820 OSMetaClass::postModLoad(void * loadHandle) 821 { 822 OSReturn result = kOSReturnSuccess; 823 OSSymbol * myKextName = NULL;// must release 824 OSKext * myKext = NULL;// must release 825 826 if (!sStalled || loadHandle != sStalled) { 827 result = kOSMetaClassInternal; 828 goto finish; 829 } 830 831 if (sStalled->result) { 832 result = sStalled->result; 833 } else { 834 switch (sBootstrapState) { 835 case kNoDictionaries: 836 sBootstrapState = kMakingDictionaries; 837 // No break; fall through 838 [[clang::fallthrough]]; 839 840 case kMakingDictionaries: 841 sAllClassesDict = OSDictionary::withCapacity(kClassCapacityIncrement); 842 if (!sAllClassesDict) { 843 result = kOSMetaClassNoDicts; 844 break; 845 } 846 sAllClassesDict->setOptions(OSCollection::kSort, OSCollection::kSort); 847 848 // No break; fall through 849 [[clang::fallthrough]]; 850 851 case kCompletedBootstrap: 852 { 853 unsigned int i; 854 myKextName = const_cast<OSSymbol *>(OSSymbol::withCStringNoCopy( 855 sStalled->kextIdentifier)); 856 857 if (!sStalled->count) { 858 break; // Nothing to do so just get out 859 } 860 861 myKext = OSKext::lookupKextWithIdentifier(myKextName); 862 if (!myKext) { 863 result = kOSMetaClassNoKext; 864 865 /* Log this error here so we can include the kext name. 866 */ 867 OSKextLog(/* kext */ NULL, kOSMetaClassLogSpec, 868 "OSMetaClass: Can't record classes for kext %s - kext not found.", 869 sStalled->kextIdentifier); 870 break; 871 } 872 873 /* First pass checking classes aren't already loaded. If any already 874 * exist, we don't register any, and so we don't technically have 875 * to do any C++ teardown. 876 * 877 * Hack alert: me->className has been a C string until now. 878 * We only release the OSSymbol if we store the kext. 879 */ 880 IOLockLock(sAllClassesLock); 881 for (i = 0; i < sStalled->count; i++) { 882 const OSMetaClass * me = sStalled->classes[i]; 883 OSMetaClass * orig = OSDynamicCast(OSMetaClass, 884 sAllClassesDict->getObject((const char *)me->className)); 885 886 if (orig) { 887 /* Log this error here so we can include the class name. 888 * xxx - we should look up the other kext that defines the class 889 */ 890 #if defined(XNU_TARGET_OS_OSX) 891 OSKextLog(myKext, kOSMetaClassLogSpec, 892 #else 893 panic( 894 #endif /* defined(XNU_TARGET_OS_OSX) */ 895 "OSMetaClass: Kext %s class %s is a duplicate;" 896 "kext %s already has a class by that name.", 897 sStalled->kextIdentifier, (const char *)me->className, 898 ((OSKext *)orig->reserved->kext)->getIdentifierCString()); 899 result = kOSMetaClassDuplicateClass; 900 break; 901 } 902 unsigned int depth = 1; 903 while ((me = me->superClassLink)) { 904 depth++; 905 } 906 if (depth > sDeepestClass) { 907 sDeepestClass = depth; 908 } 909 } 910 IOLockUnlock(sAllClassesLock); 911 912 /* Bail if we didn't go through the entire list of new classes 913 * (if we hit a duplicate). 914 */ 915 if (i != sStalled->count) { 916 break; 917 } 918 919 // Second pass symbolling strings and inserting classes in dictionary 920 IOLockLock(sAllClassesLock); 921 for (i = 0; i < sStalled->count; i++) { 922 OSMetaClass * me = sStalled->classes[i]; 923 924 /* Hack alert: me->className has been a C string until now. 925 * We only release the OSSymbol in ~OSMetaClass() 926 * if we set the reference to the kext. 927 */ 928 me->className = 929 OSSymbol::withCStringNoCopy((const char *)me->className); 930 931 // xxx - I suppose if these fail we're going to panic soon.... 932 sAllClassesDict->setObject(me->className, me); 933 934 /* Do not retain the kext object here. 935 */ 936 me->reserved->kext = myKext; 937 if (myKext) { 938 result = myKext->addClass(me, sStalled->count); 939 if (result != kOSReturnSuccess) { 940 /* OSKext::addClass() logs with kOSMetaClassNoInsKModSet. */ 941 break; 942 } 943 } 944 } 945 IOLockUnlock(sAllClassesLock); 946 sBootstrapState = kCompletedBootstrap; 947 break; 948 } 949 950 default: 951 result = kOSMetaClassInternal; 952 break; 953 } 954 } 955 956 finish: 957 /* Don't call logError() for success or the conditions logged above 958 * or by called function. 959 */ 960 if (result != kOSReturnSuccess && 961 result != kOSMetaClassNoInsKModSet && 962 result != kOSMetaClassDuplicateClass && 963 result != kOSMetaClassNoKext) { 964 OSMetaClassLogErrorForKext(result, myKext); 965 } 966 967 OSSafeReleaseNULL(myKextName); 968 OSSafeReleaseNULL(myKext); 969 970 if (sStalled) { 971 OSMETA_ACCUMSIZE(-(sStalled->capacity * sizeof(OSMetaClass *) + 972 sizeof(*sStalled))); 973 kfree(sStalled->classes, sStalled->capacity * sizeof(OSMetaClass *)); 974 kfree(sStalled, sizeof(*sStalled)); 975 sStalled = NULL; 976 } 977 978 IOLockUnlock(sStalledClassesLock); 979 980 return result; 981 } 982 983 984 /********************************************************************* 985 *********************************************************************/ 986 void 987 OSMetaClass::instanceConstructed() const 988 { 989 // if ((0 == OSIncrementAtomic(&(((OSMetaClass *) this)->instanceCount))) && superClassLink) 990 if ((0 == OSIncrementAtomic(&instanceCount)) && superClassLink) { 991 superClassLink->instanceConstructed(); 992 } 993 } 994 995 /********************************************************************* 996 *********************************************************************/ 997 void 998 OSMetaClass::instanceDestructed() const 999 { 1000 if ((1 == OSDecrementAtomic(&instanceCount)) && superClassLink) { 1001 superClassLink->instanceDestructed(); 1002 } 1003 1004 if (((int)instanceCount) < 0) { 1005 OSKext * myKext = reserved->kext; 1006 1007 OSKextLog(myKext, kOSMetaClassLogSpec, 1008 // xxx - this phrasing is rather cryptic 1009 "OSMetaClass: Class %s - bad retain (%d)", 1010 getClassName(), instanceCount); 1011 } 1012 } 1013 1014 /********************************************************************* 1015 *********************************************************************/ 1016 bool 1017 OSMetaClass::modHasInstance(const char * kextIdentifier) 1018 { 1019 bool result = false; 1020 OSKext * theKext = NULL; // must release 1021 1022 theKext = OSKext::lookupKextWithIdentifier(kextIdentifier); 1023 if (!theKext) { 1024 goto finish; 1025 } 1026 1027 result = theKext->hasOSMetaClassInstances(); 1028 1029 finish: 1030 OSSafeReleaseNULL(theKext); 1031 return result; 1032 } 1033 1034 /********************************************************************* 1035 *********************************************************************/ 1036 void 1037 OSMetaClass::reportModInstances(const char * kextIdentifier) 1038 { 1039 OSKext::reportOSMetaClassInstances(kextIdentifier, 1040 kOSKextLogExplicitLevel); 1041 return; 1042 } 1043 /********************************************************************* 1044 *********************************************************************/ 1045 1046 void 1047 OSMetaClass::addInstance(const OSObject * instance, bool super) const 1048 { 1049 if (!super) { 1050 IOLockLock(sInstancesLock); 1051 } 1052 1053 if (!reserved->instances) { 1054 reserved->instances = OSOrderedSet::withCapacity(16); 1055 if (superClassLink) { 1056 superClassLink->addInstance(reserved->instances, true); 1057 } 1058 } 1059 reserved->instances->setLastObject(instance); 1060 1061 if (!super) { 1062 IOLockUnlock(sInstancesLock); 1063 } 1064 } 1065 1066 void 1067 OSMetaClass::removeInstance(const OSObject * instance, bool super) const 1068 { 1069 if (!super) { 1070 IOLockLock(sInstancesLock); 1071 } 1072 1073 if (reserved->instances) { 1074 reserved->instances->removeObject(instance); 1075 if (0 == reserved->instances->getCount()) { 1076 if (superClassLink) { 1077 superClassLink->removeInstance(reserved->instances, true); 1078 } 1079 IOLockLock(sAllClassesLock); 1080 reserved->instances->release(); 1081 reserved->instances = NULL; 1082 IOLockUnlock(sAllClassesLock); 1083 } 1084 } 1085 1086 if (!super) { 1087 IOLockUnlock(sInstancesLock); 1088 } 1089 } 1090 1091 void 1092 OSMetaClass::applyToInstances(OSOrderedSet * set, 1093 OSMetaClassInstanceApplierFunction applier, 1094 void * context) 1095 { 1096 enum { kLocalDepth = 24 }; 1097 unsigned int _nextIndex[kLocalDepth]; 1098 OSOrderedSet * _sets[kLocalDepth]; 1099 unsigned int * nextIndex = &_nextIndex[0]; 1100 OSOrderedSet ** sets = &_sets[0]; 1101 OSObject * obj; 1102 OSOrderedSet * childSet; 1103 unsigned int maxDepth; 1104 unsigned int idx; 1105 unsigned int level; 1106 bool done; 1107 1108 maxDepth = sDeepestClass; 1109 if (maxDepth > kLocalDepth) { 1110 nextIndex = IONew(typeof(nextIndex[0]), maxDepth); 1111 sets = IONew(typeof(sets[0]), maxDepth); 1112 } 1113 done = false; 1114 level = 0; 1115 idx = 0; 1116 do{ 1117 while (!done && (obj = set->getObject(idx++))) { 1118 if ((childSet = OSDynamicCast(OSOrderedSet, obj))) { 1119 if (level >= maxDepth) { 1120 panic(">maxDepth"); 1121 } 1122 sets[level] = set; 1123 nextIndex[level] = idx; 1124 level++; 1125 set = childSet; 1126 idx = 0; 1127 break; 1128 } 1129 done = (*applier)(obj, context); 1130 } 1131 if (!obj) { 1132 if (!done && level) { 1133 level--; 1134 set = sets[level]; 1135 idx = nextIndex[level]; 1136 } else { 1137 done = true; 1138 } 1139 } 1140 }while (!done); 1141 if (maxDepth > kLocalDepth) { 1142 IODelete(nextIndex, typeof(nextIndex[0]), maxDepth); 1143 IODelete(sets, typeof(sets[0]), maxDepth); 1144 } 1145 } 1146 1147 void 1148 OSMetaClass::applyToInstances(OSMetaClassInstanceApplierFunction applier, 1149 void * context) const 1150 { 1151 IOLockLock(sInstancesLock); 1152 if (reserved->instances) { 1153 applyToInstances(reserved->instances, applier, context); 1154 } 1155 IOLockUnlock(sInstancesLock); 1156 } 1157 1158 void 1159 OSMetaClass::applyToInstancesOfClassName( 1160 const OSSymbol * name, 1161 OSMetaClassInstanceApplierFunction applier, 1162 void * context) 1163 { 1164 OSMetaClass * meta; 1165 OSOrderedSet * set = NULL; 1166 1167 IOLockLock(sAllClassesLock); 1168 if (sAllClassesDict 1169 && (meta = (OSMetaClass *) sAllClassesDict->getObject(name)) 1170 && (set = meta->reserved->instances)) { 1171 set->retain(); 1172 } 1173 IOLockUnlock(sAllClassesLock); 1174 1175 if (!set) { 1176 return; 1177 } 1178 1179 IOLockLock(sInstancesLock); 1180 applyToInstances(set, applier, context); 1181 IOLockUnlock(sInstancesLock); 1182 set->release(); 1183 } 1184 1185 /********************************************************************* 1186 *********************************************************************/ 1187 void 1188 OSMetaClass::considerUnloads() 1189 { 1190 OSKext::considerUnloads(); 1191 } 1192 1193 /********************************************************************* 1194 *********************************************************************/ 1195 bool 1196 OSMetaClass::removeClasses(OSCollection * metaClasses) 1197 { 1198 OSCollectionIterator * classIterator; 1199 OSMetaClass * checkClass; 1200 bool result; 1201 1202 classIterator = OSCollectionIterator::withCollection(metaClasses); 1203 if (!classIterator) { 1204 return false; 1205 } 1206 1207 IOLockLock(sAllClassesLock); 1208 1209 result = false; 1210 do{ 1211 while ((checkClass = (OSMetaClass *)classIterator->getNextObject()) 1212 && !checkClass->getInstanceCount() 1213 && !checkClass->reserved->retain) { 1214 } 1215 if (checkClass) { 1216 break; 1217 } 1218 classIterator->reset(); 1219 while ((checkClass = (OSMetaClass *)classIterator->getNextObject())) { 1220 sAllClassesDict->removeObject(checkClass->className); 1221 } 1222 result = true; 1223 }while (false); 1224 1225 IOLockUnlock(sAllClassesLock); 1226 OSSafeReleaseNULL(classIterator); 1227 1228 return result; 1229 } 1230 1231 1232 /********************************************************************* 1233 *********************************************************************/ 1234 const OSMetaClass * 1235 OSMetaClass::getMetaClassWithName(const OSSymbol * name) 1236 { 1237 OSMetaClass * retMeta = NULL; 1238 1239 if (!name) { 1240 return NULL; 1241 } 1242 1243 IOLockLock(sAllClassesLock); 1244 if (sAllClassesDict) { 1245 retMeta = (OSMetaClass *) sAllClassesDict->getObject(name); 1246 } 1247 IOLockUnlock(sAllClassesLock); 1248 1249 return retMeta; 1250 } 1251 1252 /********************************************************************* 1253 *********************************************************************/ 1254 const OSMetaClass * 1255 OSMetaClass::copyMetaClassWithName(const OSSymbol * name) 1256 { 1257 const OSMetaClass * meta; 1258 1259 if (!name) { 1260 return NULL; 1261 } 1262 1263 meta = NULL; 1264 IOLockLock(sAllClassesLock); 1265 if (sAllClassesDict) { 1266 meta = (OSMetaClass *) sAllClassesDict->getObject(name); 1267 if (meta) { 1268 OSIncrementAtomic(&meta->reserved->retain); 1269 } 1270 } 1271 IOLockUnlock(sAllClassesLock); 1272 1273 return meta; 1274 } 1275 1276 /********************************************************************* 1277 *********************************************************************/ 1278 void 1279 OSMetaClass::releaseMetaClass() const 1280 { 1281 OSDecrementAtomic(&reserved->retain); 1282 } 1283 1284 /********************************************************************* 1285 *********************************************************************/ 1286 OSObject * 1287 OSMetaClass::allocClassWithName(const OSSymbol * name) 1288 { 1289 const OSMetaClass * meta; 1290 OSObject * result; 1291 1292 result = NULL; 1293 meta = copyMetaClassWithName(name); 1294 if (meta) { 1295 result = meta->alloc(); 1296 meta->releaseMetaClass(); 1297 } 1298 1299 return result; 1300 } 1301 1302 /********************************************************************* 1303 *********************************************************************/ 1304 OSObject * 1305 OSMetaClass::allocClassWithName(const OSString * name) 1306 { 1307 const OSSymbol * tmpKey = OSSymbol::withString(name); 1308 OSObject * result = allocClassWithName(tmpKey); 1309 tmpKey->release(); 1310 return result; 1311 } 1312 1313 /********************************************************************* 1314 *********************************************************************/ 1315 OSObject * 1316 OSMetaClass::allocClassWithName(const char * name) 1317 { 1318 const OSSymbol * tmpKey = OSSymbol::withCStringNoCopy(name); 1319 OSObject * result = allocClassWithName(tmpKey); 1320 tmpKey->release(); 1321 return result; 1322 } 1323 1324 1325 /********************************************************************* 1326 *********************************************************************/ 1327 OSMetaClassBase * 1328 OSMetaClass::checkMetaCastWithName( 1329 const OSSymbol * name, 1330 const OSMetaClassBase * in) 1331 { 1332 OSMetaClassBase * result = NULL; 1333 1334 const OSMetaClass * const meta = getMetaClassWithName(name); 1335 1336 if (meta) { 1337 result = meta->checkMetaCast(in); 1338 } 1339 1340 return result; 1341 } 1342 1343 /********************************************************************* 1344 *********************************************************************/ 1345 OSMetaClassBase * 1346 OSMetaClass:: 1347 checkMetaCastWithName( 1348 const OSString * name, 1349 const OSMetaClassBase * in) 1350 { 1351 const OSSymbol * tmpKey = OSSymbol::withString(name); 1352 OSMetaClassBase * result = checkMetaCastWithName(tmpKey, in); 1353 1354 tmpKey->release(); 1355 return result; 1356 } 1357 1358 /********************************************************************* 1359 *********************************************************************/ 1360 OSMetaClassBase * 1361 OSMetaClass::checkMetaCastWithName( 1362 const char * name, 1363 const OSMetaClassBase * in) 1364 { 1365 const OSSymbol * tmpKey = OSSymbol::withCStringNoCopy(name); 1366 OSMetaClassBase * result = checkMetaCastWithName(tmpKey, in); 1367 1368 tmpKey->release(); 1369 return result; 1370 } 1371 1372 /********************************************************************* 1373 * OSMetaClass::checkMetaCast() 1374 * Check to see if the 'check' object has this object in its metaclass chain. 1375 * Returns check if it is indeed a kind of the current meta class, 0 otherwise. 1376 * 1377 * Generally this method is not invoked directly but is used to implement 1378 * the OSMetaClassBase::metaCast member function. 1379 * 1380 * See also OSMetaClassBase::metaCast 1381 *********************************************************************/ 1382 OSMetaClassBase * 1383 OSMetaClass::checkMetaCast( 1384 const OSMetaClassBase * check) const 1385 { 1386 const OSMetaClass * const toMeta = this; 1387 const OSMetaClass * fromMeta; 1388 1389 for (fromMeta = check->getMetaClass();; fromMeta = fromMeta->superClassLink) { 1390 if (toMeta == fromMeta) { 1391 return const_cast<OSMetaClassBase *>(check); // Discard const 1392 } 1393 if (!fromMeta->superClassLink) { 1394 break; 1395 } 1396 } 1397 1398 return NULL; 1399 } 1400 1401 /********************************************************************* 1402 *********************************************************************/ 1403 __dead2 1404 void 1405 OSMetaClass::reservedCalled(int ind) const 1406 { 1407 const char * cname = className->getCStringNoCopy(); 1408 panic("%s::_RESERVED%s%d called.", cname, cname, ind); 1409 } 1410 1411 /********************************************************************* 1412 *********************************************************************/ 1413 const 1414 OSMetaClass * 1415 OSMetaClass::getSuperClass() const 1416 { 1417 return superClassLink; 1418 } 1419 1420 /********************************************************************* 1421 *********************************************************************/ 1422 const OSSymbol * 1423 OSMetaClass::getKmodName() const 1424 { 1425 OSKext * myKext = reserved ? reserved->kext : NULL; 1426 if (myKext) { 1427 return myKext->getIdentifier(); 1428 } 1429 return OSSymbol::withCStringNoCopy("unknown"); 1430 } 1431 1432 /********************************************************************* 1433 *********************************************************************/ 1434 OSKext * 1435 OSMetaClass::getKext() const 1436 { 1437 return reserved ? reserved->kext : NULL; 1438 } 1439 1440 /********************************************************************* 1441 *********************************************************************/ 1442 unsigned int 1443 OSMetaClass::getInstanceCount() const 1444 { 1445 return instanceCount; 1446 } 1447 1448 /********************************************************************* 1449 *********************************************************************/ 1450 /* static */ 1451 void 1452 OSMetaClass::printInstanceCounts() 1453 { 1454 OSCollectionIterator * classes; 1455 OSSymbol * className; 1456 OSMetaClass * meta; 1457 1458 IOLockLock(sAllClassesLock); 1459 classes = OSCollectionIterator::withCollection(sAllClassesDict); 1460 assert(classes); 1461 1462 while ((className = (OSSymbol *)classes->getNextObject())) { 1463 meta = (OSMetaClass *)sAllClassesDict->getObject(className); 1464 assert(meta); 1465 1466 printf("%24s count: %03d x 0x%03x = 0x%06x\n", 1467 className->getCStringNoCopy(), 1468 meta->getInstanceCount(), 1469 meta->getClassSize(), 1470 meta->getInstanceCount() * meta->getClassSize()); 1471 } 1472 printf("\n"); 1473 classes->release(); 1474 IOLockUnlock(sAllClassesLock); 1475 return; 1476 } 1477 1478 /********************************************************************* 1479 *********************************************************************/ 1480 OSDictionary * 1481 OSMetaClass::getClassDictionary() 1482 { 1483 panic("OSMetaClass::getClassDictionary() is obsoleted.\n"); 1484 return NULL; 1485 } 1486 1487 /********************************************************************* 1488 *********************************************************************/ 1489 bool 1490 OSMetaClass::serialize(__unused OSSerialize * s) const 1491 { 1492 panic("OSMetaClass::serialize(): Obsoleted\n"); 1493 return false; 1494 } 1495 1496 /********************************************************************* 1497 *********************************************************************/ 1498 /* static */ 1499 void 1500 OSMetaClass::serializeClassDictionary(OSDictionary * serializeDictionary) 1501 { 1502 OSDictionary * classDict = NULL; 1503 1504 IOLockLock(sAllClassesLock); 1505 1506 classDict = OSDictionary::withCapacity(sAllClassesDict->getCount()); 1507 if (!classDict) { 1508 goto finish; 1509 } 1510 1511 do { 1512 OSCollectionIterator * classes; 1513 const OSSymbol * className; 1514 1515 classes = OSCollectionIterator::withCollection(sAllClassesDict); 1516 if (!classes) { 1517 break; 1518 } 1519 1520 while ((className = (const OSSymbol *)classes->getNextObject())) { 1521 const OSMetaClass * meta; 1522 OSNumber * count; 1523 1524 meta = (OSMetaClass *)sAllClassesDict->getObject(className); 1525 count = OSNumber::withNumber(meta->getInstanceCount(), 32); 1526 if (count) { 1527 classDict->setObject(className, count); 1528 count->release(); 1529 } 1530 } 1531 classes->release(); 1532 1533 serializeDictionary->setObject("Classes", classDict); 1534 } while (0); 1535 1536 finish: 1537 OSSafeReleaseNULL(classDict); 1538 1539 IOLockUnlock(sAllClassesLock); 1540 1541 return; 1542 } 1543 1544 1545 /********************************************************************* 1546 *********************************************************************/ 1547 1548 #if IOTRACKING 1549 1550 void * 1551 OSMetaClass::trackedNew(size_t size) 1552 { 1553 IOTracking * mem; 1554 1555 mem = (typeof(mem))kalloc_tag_bt(size + sizeof(IOTracking), VM_KERN_MEMORY_LIBKERN); 1556 assert(mem); 1557 if (!mem) { 1558 return mem; 1559 } 1560 1561 memset(mem, 0, size + sizeof(IOTracking)); 1562 mem++; 1563 1564 OSIVAR_ACCUMSIZE(size); 1565 1566 return mem; 1567 } 1568 1569 void 1570 OSMetaClass::trackedDelete(void * instance, size_t size) 1571 { 1572 IOTracking * mem = (typeof(mem))instance; mem--; 1573 1574 kfree(mem, size + sizeof(IOTracking)); 1575 OSIVAR_ACCUMSIZE(-size); 1576 } 1577 1578 void 1579 OSMetaClass::trackedInstance(OSObject * instance) const 1580 { 1581 IOTracking * mem = (typeof(mem))instance; mem--; 1582 1583 return IOTrackingAdd(reserved->tracking, mem, classSize, false, VM_KERN_MEMORY_NONE); 1584 } 1585 1586 void 1587 OSMetaClass::trackedFree(OSObject * instance) const 1588 { 1589 IOTracking * mem = (typeof(mem))instance; mem--; 1590 1591 return IOTrackingRemove(reserved->tracking, mem, classSize); 1592 } 1593 1594 void 1595 OSMetaClass::trackedAccumSize(OSObject * instance, size_t size) const 1596 { 1597 IOTracking * mem = (typeof(mem))instance; mem--; 1598 1599 return IOTrackingAccumSize(reserved->tracking, mem, size); 1600 } 1601 1602 IOTrackingQueue * 1603 OSMetaClass::getTracking() const 1604 { 1605 return reserved->tracking; 1606 } 1607 1608 #endif /* IOTRACKING */ 1609