unsigned int OSSerialize::ensureCapacity(unsigned int newCapacity) { char *newData; if (newCapacity <= capacity) return capacity; // round up newCapacity = round_page_32(newCapacity); kern_return_t rc = kmem_realloc(kernel_map, (vm_offset_t)data, capacity, (vm_offset_t *)&newData, newCapacity); if (!rc) { ACCUMSIZE(newCapacity); // kmem realloc does not free the old address range kmem_free(kernel_map, (vm_offset_t)data, capacity); ACCUMSIZE(-capacity); // kmem realloc does not zero out the new memory // and this could end up going to user land bzero(&newData[capacity], newCapacity - capacity); data = newData; capacity = newCapacity; } return capacity; }
OSSymbol *OSSymbolPool::insertSymbol(OSSymbol *sym) { const char *cString = sym->string; Bucket *thisBucket; unsigned int j, inLen, hash; OSSymbol *probeSymbol, **list; hashSymbol(cString, &hash, &inLen); inLen++; thisBucket = &buckets[hash % nBuckets]; j = thisBucket->count; if (!j) { thisBucket->symbolP = (OSSymbol **) sym; thisBucket->count++; count++; return sym; } if (j == 1) { probeSymbol = (OSSymbol *) thisBucket->symbolP; if (inLen == probeSymbol->length && strncmp(probeSymbol->string, cString, probeSymbol->length) == 0) return probeSymbol; list = (OSSymbol **) kalloc(2 * sizeof(OSSymbol *)); ACCUMSIZE(2 * sizeof(OSSymbol *)); /* @@@ gvdl: Zero test and panic if can't set up pool */ list[0] = sym; list[1] = probeSymbol; thisBucket->symbolP = list; thisBucket->count++; count++; GROW_POOL(); return sym; } for (list = thisBucket->symbolP; j--; list++) { probeSymbol = *list; if (inLen == probeSymbol->length && strncmp(probeSymbol->string, cString, probeSymbol->length) == 0) return probeSymbol; } j = thisBucket->count++; count++; list = (OSSymbol **) kalloc(thisBucket->count * sizeof(OSSymbol *)); ACCUMSIZE(thisBucket->count * sizeof(OSSymbol *)); /* @@@ gvdl: Zero test and panic if can't set up pool */ list[0] = sym; bcopy(thisBucket->symbolP, list + 1, j * sizeof(OSSymbol *)); kfree(thisBucket->symbolP, j * sizeof(OSSymbol *)); ACCUMSIZE(-(j * sizeof(OSSymbol *))); thisBucket->symbolP = list; GROW_POOL(); return sym; }
unsigned int OSDictionary::ensureCapacity(unsigned int newCapacity) { dictEntry *newDict; int oldSize, newSize; if (newCapacity <= capacity) return capacity; // round up newCapacity = (((newCapacity - 1) / capacityIncrement) + 1) * capacityIncrement; newSize = sizeof(dictEntry) * newCapacity; newDict = (dictEntry *) kalloc(newSize); if (newDict) { oldSize = sizeof(dictEntry) * capacity; bcopy(dictionary, newDict, oldSize); bzero(&newDict[capacity], newSize - oldSize); ACCUMSIZE(newSize - oldSize); kfree((vm_offset_t)dictionary, oldSize); dictionary = newDict; capacity = newCapacity; } return capacity; }
unsigned int OSOrderedSet::ensureCapacity(unsigned int newCapacity) { _Element *newArray; int oldSize, newSize; if (newCapacity <= capacity) return capacity; // round up newCapacity = (((newCapacity - 1) / capacityIncrement) + 1) * capacityIncrement; newSize = sizeof(_Element) * newCapacity; newArray = (_Element *) kalloc(newSize); if (newArray) { oldSize = sizeof(_Element) * capacity; ACCUMSIZE(newSize - oldSize); bcopy(array, newArray, oldSize); bzero(&newArray[capacity], newSize - oldSize); kfree((vm_offset_t)array, oldSize); array = newArray; capacity = newCapacity; } return capacity; }
bool OSSerialize::initWithCapacity(unsigned int inCapacity) { if (!super::init()) return false; tags = OSDictionary::withCapacity(32); if (!tags) { return false; } tag = 0; length = 1; capacity = (inCapacity) ? round_page_32(inCapacity) : round_page_32(1); capacityIncrement = capacity; // allocate from the kernel map so that we can safely map this data // into user space (the primary use of the OSSerialize object) kern_return_t rc = kmem_alloc(kernel_map, (vm_offset_t *)&data, capacity); if (rc) { tags->release(); tags = 0; return false; } bzero((void *)data, capacity); ACCUMSIZE(capacity); return true; }
void *OSMetaClass::preModLoad(const char *kmodName) { if (!loadLock) { loadLock = mutex_alloc(ETAP_IO_AHA); mutex_lock(loadLock); } else mutex_lock(loadLock); sStalled = (StalledData *) kalloc(sizeof(*sStalled)); if (sStalled) { sStalled->classes = (OSMetaClass **) kalloc(kKModCapacityIncrement * sizeof(OSMetaClass *)); if (!sStalled->classes) { kfree((vm_offset_t) sStalled, sizeof(*sStalled)); return 0; } ACCUMSIZE((kKModCapacityIncrement * sizeof(OSMetaClass *)) + sizeof(*sStalled)); sStalled->result = kOSReturnSuccess; sStalled->capacity = kKModCapacityIncrement; sStalled->count = 0; sStalled->kmodName = kmodName; bzero(sStalled->classes, kKModCapacityIncrement * sizeof(OSMetaClass *)); } return sStalled; }
void OSSymbolPool::reconstructSymbols(bool grow) { unsigned int new_nBuckets = nBuckets; OSSymbol *insert; OSSymbolPoolState state; if (grow) { new_nBuckets += new_nBuckets + 1; } else { /* Don't shrink the pool below the default initial size. */ if (nBuckets <= INITIAL_POOL_SIZE) { return; } new_nBuckets = (new_nBuckets - 1) / 2; } /* Create old pool to iterate after doing above check, cause it * gets finalized at return. */ OSSymbolPool old(this); count = 0; nBuckets = new_nBuckets; buckets = (Bucket *) kalloc(nBuckets * sizeof(Bucket)); ACCUMSIZE(nBuckets * sizeof(Bucket)); /* @@@ gvdl: Zero test and panic if can't set up pool */ bzero(buckets, nBuckets * sizeof(Bucket)); state = old.initHashState(); while ( (insert = old.nextHashState(&state)) ) insertSymbol(insert); }
void * OSMetaClass::preModLoad(const char * kextIdentifier) { IOLockLock(sStalledClassesLock); assert (sStalled == NULL); sStalled = (StalledData *)kalloc(sizeof(* sStalled)); if (sStalled) { sStalled->classes = (OSMetaClass **) kalloc(kKModCapacityIncrement * sizeof(OSMetaClass *)); if (!sStalled->classes) { kfree(sStalled, sizeof(*sStalled)); return 0; } ACCUMSIZE((kKModCapacityIncrement * sizeof(OSMetaClass *)) + sizeof(*sStalled)); sStalled->result = kOSReturnSuccess; sStalled->capacity = kKModCapacityIncrement; sStalled->count = 0; sStalled->kextIdentifier = kextIdentifier; bzero(sStalled->classes, kKModCapacityIncrement * sizeof(OSMetaClass *)); } // keep sStalledClassesLock locked until postModLoad return sStalled; }
unsigned int OSOrderedSet::ensureCapacity(unsigned int newCapacity) { _Element *newArray; unsigned int finalCapacity, oldSize, newSize; if (newCapacity <= capacity) return capacity; // round up finalCapacity = (((newCapacity - 1) / capacityIncrement) + 1) * capacityIncrement; if ((finalCapacity < newCapacity) || (finalCapacity > (UINT_MAX / sizeof(_Element)))) { return capacity; } newSize = sizeof(_Element) * finalCapacity; newArray = (_Element *) kalloc(newSize); if (newArray) { oldSize = sizeof(_Element) * capacity; ACCUMSIZE(newSize - oldSize); bcopy(array, newArray, oldSize); bzero(&newArray[capacity], newSize - oldSize); kfree(array, oldSize); array = newArray; capacity = finalCapacity; } return capacity; }
bool OSSerialize::initWithCapacity(unsigned int inCapacity) { if (!super::init()) return false; tags = OSDictionary::withCapacity(32); if (!tags) { return false; } tag = 0; length = 1; capacity = (inCapacity) ? inCapacity : (100); capacityIncrement = capacity; // allocate from the kernel map so that we can safely map this data // into user space (the primary use of the OSSerialize object) data = (char*)kalloc(capacity); assert(data); bzero((void *)data, capacity); ACCUMSIZE(capacity); return true; }
bool OSOrderedSet:: initWithCapacity(unsigned int inCapacity, OSOrderFunction inOrdering, void *inOrderingRef) { unsigned int size; if (!super::init()) return false; if (inCapacity > (UINT_MAX / sizeof(_Element))) return false; size = sizeof(_Element) * inCapacity; array = (_Element *) kalloc(size); if (!array) return false; count = 0; capacity = inCapacity; capacityIncrement = (inCapacity)? inCapacity : 16; ordering = inOrdering; orderingRef = inOrderingRef; bzero(array, size); ACCUMSIZE(size); return this; }
void OSString::free() { if ( !(flags & kOSStringNoCopy) && string) { kfree(string, (vm_size_t)length); ACCUMSIZE(-length); } super::free(); }
void * OSSymbolPool::operator new(size_t size) { void *mem = (void *)kalloc(size); ACCUMSIZE(size); assert(mem); bzero(mem, size); return mem; }
OSSymbolPool::~OSSymbolPool() { if (buckets) { kfree(buckets, nBuckets * sizeof(Bucket)); ACCUMSIZE(-(nBuckets * sizeof(Bucket))); } if (poolGate) lck_mtx_free(poolGate, IOLockGroup); }
void OSDictionary::free() { flushCollection(); if (dictionary) { kfree((vm_offset_t)dictionary, capacity * sizeof(dictEntry)); ACCUMSIZE( -(capacity * sizeof(dictEntry)) ); } super::free(); }
void OSSerialize::free() { if (tags) tags->release(); if (data) { kmem_free(kernel_map, (vm_offset_t)data, capacity); ACCUMSIZE( -capacity ); } super::free(); }
void OSSerialize::free() { if (tags) tags->release(); if (data) { kfree(data, capacity); ACCUMSIZE( -capacity ); } super::free(); }
void OSOrderedSet::free() { flushCollection(); if (array) { kfree((vm_offset_t)array, sizeof(_Element) * capacity); ACCUMSIZE( -(sizeof(_Element) * capacity) ); } super::free(); }
void OSOrderedSet::free() { (void) super::setOptions(0, kImmutable); flushCollection(); if (array) { kfree(array, sizeof(_Element) * capacity); ACCUMSIZE( -(sizeof(_Element) * capacity) ); } super::free(); }
bool OSSymbolPool::init() { count = 0; nBuckets = INITIAL_POOL_SIZE; buckets = (Bucket *) kalloc(nBuckets * sizeof(Bucket)); ACCUMSIZE(nBuckets * sizeof(Bucket)); if (!buckets) return false; bzero(buckets, nBuckets * sizeof(Bucket)); poolGate = lck_mtx_alloc_init(IOLockGroup, LCK_ATTR_NULL); return poolGate != 0; }
bool OSCollectionIterator::isValid() { if (!collIterator) { collIterator = (void *)kalloc(collection->iteratorSize()); ACCUMSIZE(collection->iteratorSize()); if (!collection->initIterator(collIterator)) return false; initialUpdateStamp = collection->updateStamp; valid = true; } else if (!valid || collection->updateStamp != initialUpdateStamp) return false; return true; }
void OSCollectionIterator::free() { if (collIterator) { kfree(collIterator, collection->iteratorSize()); ACCUMSIZE(-(collection->iteratorSize())); collIterator = 0; } if (collection) { collection->release(); collection = 0; } super::free(); }
bool OSString::initWithCString(const char *cString) { if (!cString || !super::init()) return false; length = strlen(cString) + 1; string = (char *) kalloc(length); if (!string) return false; bcopy(cString, string, length); ACCUMSIZE(length); return true; }
/********************************************************************* * The core constructor for a MetaClass (defined with this name always * but within the scope of its represented class). * * MetaClass constructors are invoked in OSRuntimeInitializeCPP(), * in between calls to OSMetaClass::preModLoad(), which sets up for * registration, and OSMetaClass::postModLoad(), which actually * records all the class/kext relationships of the new MetaClasses. *********************************************************************/ OSMetaClass::OSMetaClass( const char * inClassName, const OSMetaClass * inSuperClass, unsigned int inClassSize) { instanceCount = 0; classSize = inClassSize; superClassLink = inSuperClass; /* Hack alert: We are just casting inClassName and storing it in * an OSString * instance variable. This may be because you can't * create C++ objects in static constructors, but I really don't know! */ className = (const OSSymbol *)inClassName; // sStalledClassesLock taken in preModLoad if (!sStalled) { /* There's no way we can look up the kext here, unfortunately. */ OSKextLog(/* kext */ NULL, kOSMetaClassLogSpec, "OSMetaClass: preModLoad() wasn't called for class %s " "(runtime internal error).", inClassName); } else if (!sStalled->result) { // Grow stalled array if neccessary if (sStalled->count >= sStalled->capacity) { OSMetaClass **oldStalled = sStalled->classes; int oldSize = sStalled->capacity * sizeof(OSMetaClass *); int newSize = oldSize + kKModCapacityIncrement * sizeof(OSMetaClass *); sStalled->classes = (OSMetaClass **)kalloc(newSize); if (!sStalled->classes) { sStalled->classes = oldStalled; sStalled->result = kOSMetaClassNoTempData; return; } sStalled->capacity += kKModCapacityIncrement; memmove(sStalled->classes, oldStalled, oldSize); kfree(oldStalled, oldSize); ACCUMSIZE(newSize - oldSize); } sStalled->classes[sStalled->count++] = this; } }
bool OSString::initWithStringOfLength(const char *cString, size_t inlength) { if (!cString || !super::init()) return false; length = inlength + 1; string = (char *) kalloc(length); if (!string) return false; bcopy(cString, string, inlength); string[inlength] = 0; ACCUMSIZE(length); return true; }
void OSCollectionIterator::reset() { valid = false; if (!collIterator) { collIterator = (void *)kalloc(collection->iteratorSize()); ACCUMSIZE(collection->iteratorSize()); if (!collIterator) return; } if (!collection->initIterator(collIterator)) return; initialUpdateStamp = collection->updateStamp; valid = true; }
void OSSymbol::checkForPageUnload(void *startAddr, void *endAddr) { OSSymbol *probeSymbol; OSSymbolPoolState state; pool->closeGate(); state = pool->initHashState(); while ( (probeSymbol = pool->nextHashState(&state)) ) { if (probeSymbol->string >= startAddr && probeSymbol->string < endAddr) { const char *oldString = probeSymbol->string; probeSymbol->string = (char *) kalloc(probeSymbol->length); ACCUMSIZE(probeSymbol->length); bcopy(oldString, probeSymbol->string, probeSymbol->length); probeSymbol->flags &= ~kOSStringNoCopy; } } pool->openGate(); }
bool OSDictionary::initWithCapacity(unsigned int inCapacity) { if (!super::init()) return false; int size = inCapacity * sizeof(dictEntry); dictionary = (dictEntry *) kalloc(size); if (!dictionary) return false; bzero(dictionary, size); ACCUMSIZE(size); count = 0; capacity = inCapacity; capacityIncrement = (inCapacity)? inCapacity : 16; return true; }
OSMetaClass::OSMetaClass(const char *inClassName, const OSMetaClass *inSuperClass, unsigned int inClassSize) { instanceCount = 0; classSize = inClassSize; superClassLink = inSuperClass; className = (const OSSymbol *) inClassName; if (!sStalled) { printf("OSMetaClass::preModLoad wasn't called for %s, " "runtime internal error\n", inClassName); } else if (!sStalled->result) { // Grow stalled array if neccessary if (sStalled->count >= sStalled->capacity) { OSMetaClass **oldStalled = sStalled->classes; int oldSize = sStalled->capacity * sizeof(OSMetaClass *); int newSize = oldSize + kKModCapacityIncrement * sizeof(OSMetaClass *); sStalled->classes = (OSMetaClass **) kalloc(newSize); if (!sStalled->classes) { sStalled->classes = oldStalled; sStalled->result = kOSMetaClassNoTempData; return; } sStalled->capacity += kKModCapacityIncrement; memmove(sStalled->classes, oldStalled, oldSize); kfree((vm_offset_t)oldStalled, oldSize); ACCUMSIZE(newSize - oldSize); } sStalled->classes[sStalled->count++] = this; } }
OSReturn OSMetaClass::postModLoad(void * loadHandle) { OSReturn result = kOSReturnSuccess; OSSymbol * myKextName = 0; // must release OSKext * myKext = 0; // must release if (!sStalled || loadHandle != sStalled) { result = kOSMetaClassInternal; goto finish; } if (sStalled->result) { result = sStalled->result; } else switch (sBootstrapState) { case kNoDictionaries: sBootstrapState = kMakingDictionaries; // No break; fall through case kMakingDictionaries: sAllClassesDict = OSDictionary::withCapacity(kClassCapacityIncrement); if (!sAllClassesDict) { result = kOSMetaClassNoDicts; break; } // No break; fall through case kCompletedBootstrap: { unsigned int i; myKextName = const_cast<OSSymbol *>(OSSymbol::withCStringNoCopy( sStalled->kextIdentifier)); if (!sStalled->count) { break; // Nothing to do so just get out } myKext = OSKext::lookupKextWithIdentifier(myKextName); if (!myKext) { result = kOSMetaClassNoKext; /* Log this error here so we can include the kext name. */ OSKextLog(/* kext */ NULL, kOSMetaClassLogSpec, "OSMetaClass: Can't record classes for kext %s - kext not found.", sStalled->kextIdentifier); break; } /* First pass checking classes aren't already loaded. If any already * exist, we don't register any, and so we don't technically have * to do any C++ teardown. * * Hack alert: me->className has been a C string until now. * We only release the OSSymbol if we store the kext. */ IOLockLock(sAllClassesLock); for (i = 0; i < sStalled->count; i++) { OSMetaClass * me = sStalled->classes[i]; OSMetaClass * orig = OSDynamicCast(OSMetaClass, sAllClassesDict->getObject((const char *)me->className)); if (orig) { /* Log this error here so we can include the class name. * xxx - we should look up the other kext that defines the class */ OSKextLog(myKext, kOSMetaClassLogSpec, "OSMetaClass: Kext %s class %s is a duplicate;" "kext %s already has a class by that name.", sStalled->kextIdentifier, (const char *)me->className, ((OSKext *)orig->reserved)->getIdentifierCString()); result = kOSMetaClassDuplicateClass; break; } } IOLockUnlock(sAllClassesLock); /* Bail if we didn't go through the entire list of new classes * (if we hit a duplicate). */ if (i != sStalled->count) { break; } // Second pass symbolling strings and inserting classes in dictionary IOLockLock(sAllClassesLock); for (i = 0; i < sStalled->count; i++) { OSMetaClass * me = sStalled->classes[i]; /* Hack alert: me->className has been a C string until now. * We only release the OSSymbol in ~OSMetaClass() * if we set the reference to the kext. */ me->className = OSSymbol::withCStringNoCopy((const char *)me->className); // xxx - I suppose if these fail we're going to panic soon.... sAllClassesDict->setObject(me->className, me); /* Do not retain the kext object here. */ me->reserved = (ExpansionData *)myKext; if (myKext) { result = myKext->addClass(me, sStalled->count); if (result != kOSReturnSuccess) { /* OSKext::addClass() logs with kOSMetaClassNoInsKModSet. */ break; } } } IOLockUnlock(sAllClassesLock); sBootstrapState = kCompletedBootstrap; break; } default: result = kOSMetaClassInternal; break; } finish: /* Don't call logError() for success or the conditions logged above * or by called function. */ if (result != kOSReturnSuccess && result != kOSMetaClassNoInsKModSet && result != kOSMetaClassDuplicateClass && result != kOSMetaClassNoKext) { OSMetaClassLogErrorForKext(result, myKext); } OSSafeRelease(myKextName); OSSafeRelease(myKext); if (sStalled) { ACCUMSIZE(-(sStalled->capacity * sizeof(OSMetaClass *) + sizeof(*sStalled))); kfree(sStalled->classes, sStalled->capacity * sizeof(OSMetaClass *)); kfree(sStalled, sizeof(*sStalled)); sStalled = 0; } IOLockUnlock(sStalledClassesLock); return result; }