]> git.saurik.com Git - apple/dyld.git/blobdiff - src/dyldNew.cpp
dyld-851.27.tar.gz
[apple/dyld.git] / src / dyldNew.cpp
index bd99cde389be5b172abf0f92b9824e5df4b91c13..2bdafba21da777798b99a917f906e6d5e87d7811 100644 (file)
@@ -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);
        }
 }