1/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*- 2 * 3 * Copyright (c) 2004-2008 Apple Inc. All rights reserved. 4 * 5 * @APPLE_LICENSE_HEADER_START@ 6 * 7 * This file contains Original Code and/or Modifications of Original Code 8 * as defined in and that are subject to the Apple Public Source License 9 * Version 2.0 (the 'License'). You may not use this file except in 10 * compliance with the License. Please obtain a copy of the License at 11 * http://www.opensource.apple.com/apsl/ and read it before using this 12 * file. 13 * 14 * The Original Code and all software distributed under the License are 15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 19 * Please see the License for the specific language governing rights and 20 * limitations under the License. 21 * 22 * @APPLE_LICENSE_HEADER_END@ 23 */ 24 25 26#include <stdlib.h> 27#include <stdint.h> 28#include <string.h> 29#include <mach/mach.h> 30#include <sys/mman.h> 31 32extern "C" void* __dso_handle; 33 34#include "dyld.h" 35#include "dyldLibSystemInterface.h" 36 37// 38// dyld initially allocates all memory from a pool inside dyld. 39// Once libSystem.dylib is initialized, dyld uses libSystem's malloc/free. 40// 41 42#if __LP64__ 43 // room for about ~1000 initial dylibs 44 #define DYLD_POOL_CHUNK_SIZE 224*1024 45#else 46 // room for about ~900 initial dylibs 47 #define DYLD_POOL_CHUNK_SIZE 150*1024 48#endif 49 50struct dyld_static_pool { 51 dyld_static_pool* previousPool; 52 uint8_t* current; 53 uint8_t* end; 54 uint8_t pool[1]; 55}; 56 57// allocate initial pool independently of pool header to take less space on disk 58static uint8_t initialPoolContent[DYLD_POOL_CHUNK_SIZE] __attribute__((__aligned__(16))); 59static dyld_static_pool initialPool = { NULL, initialPoolContent, &initialPoolContent[DYLD_POOL_CHUNK_SIZE] }; 60static dyld_static_pool* currentPool = &initialPool; 61 62 63void* malloc(size_t size) 64{ 65 if ( dyld::gLibSystemHelpers != NULL) { 66 void* p = dyld::gLibSystemHelpers->malloc(size); 67 //dyld::log("malloc(%lu) => %p from libSystem\n", size, p); 68 return p; 69 } 70 else { 71 size = (size+sizeof(void*)-1) & (-sizeof(void*)); // pointer align 72 uint8_t* result = currentPool->current; 73 currentPool->current += size; 74 if ( currentPool->current > currentPool->end ) { 75 vm_address_t addr = 0; 76 kern_return_t r = vm_allocate(mach_task_self(), &addr, DYLD_POOL_CHUNK_SIZE, VM_FLAGS_ANYWHERE); 77 if ( r != KERN_SUCCESS ) { 78 dyld::log("out of address space for dyld memory pool\n"); 79 exit(1); 80 } 81 dyld_static_pool* newPool = (dyld_static_pool*)addr; 82 newPool->previousPool = NULL; 83 newPool->current = newPool->pool; 84 newPool->end = (uint8_t*)(addr + DYLD_POOL_CHUNK_SIZE); 85 newPool->previousPool = currentPool; 86 currentPool = newPool; 87 if ( (currentPool->current + size) > currentPool->end ) { 88 dyld::log("dyld memory pool exhausted: size=%lu\n", size); 89 exit(1); 90 } 91 result = currentPool->current; 92 currentPool->current += size; 93 } 94 //dyld::log("%p = malloc(%3lu) from pool %p, free space = %lu\n", result, size, currentPool, (long)(currentPool->end - currentPool->current)); 95 return result; 96 } 97} 98 99 100void free(void* ptr) 101{ 102 // ignore any pointer within dyld (i.e. stuff from pool or static strings) 103 if ( (dyld::gLibSystemHelpers != NULL) && ((ptr < &__dso_handle) || (ptr >= &initialPoolContent[DYLD_POOL_CHUNK_SIZE])) ) { 104 // ignore stuff in any dynamically alloated dyld pools 105 for (dyld_static_pool* p = initialPool.previousPool; p != NULL; p = p->previousPool) { 106 if ( (p->pool < ptr) && (ptr < p->end) ) { 107 // do nothing, pool entries can't be reclaimed 108 //dyld::log("free(%p) from dynamic pool\n", ptr); 109 return; 110 } 111 } 112 113 //dyld::log("free(%p) from libSystem\n", ptr); 114 return dyld::gLibSystemHelpers->free(ptr); 115 } 116 else { 117 // do nothing, pool entries can't be reclaimed 118 //dyld::log("free(%p) from static pool\n", ptr); 119 } 120} 121 122 123void* calloc(size_t count, size_t size) 124{ 125 if ( dyld::gLibSystemHelpers != NULL ) { 126 void* result = dyld::gLibSystemHelpers->malloc(size*count); 127 bzero(result, size*count); 128 return result; 129 } 130 else { 131 return malloc(count*size); 132 } 133} 134 135 136void* realloc(void *ptr, size_t size) 137{ 138 void* result = malloc(size); 139 memcpy(result, ptr, size); 140 return result; 141} 142 143// void* reallocf(void *ptr, size_t size); 144// void* valloc(size_t size); 145 146// needed __libc_init() 147extern "C" int _malloc_lock; 148int _malloc_lock = 0; 149 150 151// <rdar://problem/12857033> dyld calls this which uses libSystem.dylib's vm_allocate if available 152int vm_alloc(vm_address_t* addr, vm_size_t size, uint32_t flags) 153{ 154 if ( (dyld::gLibSystemHelpers != NULL) && (dyld::gLibSystemHelpers->version >= 12) ) { 155 return dyld::gLibSystemHelpers->vm_alloc(mach_task_self(), addr, size, flags); 156 } 157 else { 158 return ::vm_allocate(mach_task_self(), addr, size, flags); 159 } 160} 161 162void* xmmap(void* addr, size_t len, int prot, int flags, int fd, off_t offset) 163{ 164 if ( (dyld::gLibSystemHelpers != NULL) && (dyld::gLibSystemHelpers->version >= 12) ) { 165 return dyld::gLibSystemHelpers->mmap(addr, len, prot, flags, fd, offset); 166 } 167 else { 168 return ::mmap(addr, len, prot, flags, fd, offset); 169 } 170} 171 172 173 174