X-Git-Url: https://git.saurik.com/apple/dyld.git/blobdiff_plain/2fd3f4e8fd2c2f2c7d149fbea471d8b3fb56f15a..refs/heads/master:/src/dyldNew.cpp?ds=inline diff --git a/src/dyldNew.cpp b/src/dyldNew.cpp index bd99cde..2bdafba 100644 --- a/src/dyldNew.cpp +++ b/src/dyldNew.cpp @@ -31,7 +31,7 @@ extern "C" void* __dso_handle; -#include "dyld.h" +#include "dyld2.h" #include "dyldLibSystemInterface.h" // @@ -41,7 +41,7 @@ extern "C" void* __dso_handle; #if __LP64__ // room for about ~1000 initial dylibs - #define DYLD_POOL_CHUNK_SIZE 224*1024 + #define DYLD_POOL_CHUNK_SIZE 200*1024 #else // room for about ~900 initial dylibs #define DYLD_POOL_CHUNK_SIZE 150*1024 @@ -51,7 +51,10 @@ struct dyld_static_pool { dyld_static_pool* previousPool; uint8_t* current; uint8_t* end; - uint8_t pool[1]; + + // libunwind, and probably others, need the pool to be 16-byte aligned as malloc guarantees that + __attribute__((__aligned__(16))) + uint8_t pool[1]; }; // allocate initial pool independently of pool header to take less space on disk @@ -62,12 +65,19 @@ static dyld_static_pool* currentPool = &initialPool; void* malloc(size_t size) { - if ( dyld::gLibSystemHelpers != NULL) { + if ( (dyld::gLibSystemHelpers != NULL) && dyld::gProcessInfo->libSystemInitialized ) { void* p = dyld::gLibSystemHelpers->malloc(size); //dyld::log("malloc(%lu) => %p from libSystem\n", size, p); return p; } else { + // keep allocations 16-byte aligned + size = ((size + 15) & -16); + + if ( size > DYLD_POOL_CHUNK_SIZE ) { + dyld::log("dyld malloc overflow: size=%lu\n", size); + dyld::halt("dyld malloc overflow\n"); + } size = (size+sizeof(void*)-1) & (-sizeof(void*)); // pointer align uint8_t* result = currentPool->current; currentPool->current += size; @@ -75,8 +85,7 @@ void* malloc(size_t size) vm_address_t addr = 0; kern_return_t r = vm_allocate(mach_task_self(), &addr, DYLD_POOL_CHUNK_SIZE, VM_FLAGS_ANYWHERE); if ( r != KERN_SUCCESS ) { - dyld::log("out of address space for dyld memory pool\n"); - exit(1); + dyld::halt("out of address space for dyld memory pool\n"); } dyld_static_pool* newPool = (dyld_static_pool*)addr; newPool->previousPool = NULL; @@ -86,7 +95,7 @@ void* malloc(size_t size) currentPool = newPool; if ( (currentPool->current + size) > currentPool->end ) { dyld::log("dyld memory pool exhausted: size=%lu\n", size); - exit(1); + dyld::halt("dyld memory pool exhausted\n"); } result = currentPool->current; currentPool->current += size; @@ -102,8 +111,8 @@ void free(void* ptr) // ignore any pointer within dyld (i.e. stuff from pool or static strings) if ( (dyld::gLibSystemHelpers != NULL) && ((ptr < &__dso_handle) || (ptr >= &initialPoolContent[DYLD_POOL_CHUNK_SIZE])) ) { // ignore stuff in any dynamically alloated dyld pools - for (dyld_static_pool* p = initialPool.previousPool; p != NULL; p = p->previousPool) { - if ( (p->pool < ptr) && (ptr < p->end) ) { + for (dyld_static_pool* p = currentPool; p != NULL; p = p->previousPool) { + if ( (p->pool <= ptr) && (ptr < p->end) ) { // do nothing, pool entries can't be reclaimed //dyld::log("free(%p) from dynamic pool\n", ptr); return; @@ -122,13 +131,21 @@ void free(void* ptr) void* calloc(size_t count, size_t size) { + // Check for overflow of integer multiplication + size_t total = count * size; + if ( total/count != size ) { + dyld::log("dyld calloc overflow: count=%zu, size=%zu\n", count, size); + dyld::halt("dyld calloc overflow"); + } if ( dyld::gLibSystemHelpers != NULL ) { - void* result = dyld::gLibSystemHelpers->malloc(size*count); - bzero(result, size*count); + void* result = dyld::gLibSystemHelpers->malloc(total); + if ( result != NULL ) + bzero(result, total); return result; } else { - return malloc(count*size); + // this allocates out of static buffer which is already zero filled + return malloc(total); } }