this repo has no description
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Implement libgmalloc

This is a simple implementation of libgmalloc as found on OS X.
Use it like this:
$ DYLD_INSERT_LIBRARIES=/usr/lib/libgmalloc.dylib DYLD_FORCE_FLAT_NAMESPACE=1 ./executable
You may also want to try using MALLOC_PROTECT_BEFORE and/or MALLOC_FILL_SPACE.

Unfortunately, using libgmalloc skyrockets the memory and address space usage,
so it's nearly impossible to use it with complex executables.

+265
+1
src/CMakeLists.txt
··· 230 230 add_subdirectory(external/coretls) 231 231 add_subdirectory(libffi) 232 232 add_subdirectory(xtrace) 233 + add_subdirectory(libgmalloc) 233 234 add_subdirectory(dyld) 234 235 add_subdirectory(external/objc4/runtime) 235 236 add_subdirectory(external/syslog)
+15
src/libgmalloc/CMakeLists.txt
··· 1 + project(libgmalloc) 2 + 3 + include_directories( 4 + ${CMAKE_SOURCE_DIR}/src/dyld/include 5 + ) 6 + 7 + set(libgmalloc_sources 8 + gmalloc.c 9 + ) 10 + 11 + set(DYLIB_INSTALL_NAME "/usr/lib/libgmalloc.dylib") 12 + add_darling_library(gmalloc ${libgmalloc_sources}) 13 + target_link_libraries(gmalloc PRIVATE system) 14 + 15 + install(TARGETS gmalloc DESTINATION libexec/darling/usr/lib)
+249
src/libgmalloc/gmalloc.c
··· 1 + #include <errno.h> 2 + #include <stdlib.h> 3 + #include <string.h> 4 + #include <unistd.h> 5 + #include <sys/cdefs.h> 6 + #include <sys/mman.h> 7 + #include <mach/vm_page_size.h> 8 + #include <os/overflow.h> 9 + 10 + #ifdef __LP64__ 11 + #define GMALLOC_MAGIC 0xdeadbeefdeadbeef 12 + #else 13 + #define GMALLOC_MAGIC 0xdeadbeef 14 + #endif 15 + 16 + struct gmalloc_header { 17 + size_t magic; 18 + size_t size; 19 + void *mmap_base; 20 + size_t mmap_size; 21 + size_t magic_again; 22 + }; 23 + 24 + static int gmalloc_protect_before; 25 + static int gmalloc_fill_space; 26 + static int gmalloc_allow_reads; 27 + static int gmalloc_strict_size; 28 + static int gmalloc_check_header = 1; 29 + 30 + void __malloc_init(const char *apple[]) { 31 + (void) apple; 32 + 33 + if (getenv("MALLOC_PROTECT_BEFORE")) gmalloc_protect_before = 1; 34 + if (getenv("MALLOC_FILL_SPACE")) gmalloc_fill_space = 1; 35 + if (getenv("MALLOC_ALLOW_READS")) gmalloc_allow_reads = 1; 36 + if (getenv("MALLOC_STRICT_SIZE")) gmalloc_strict_size = 1; 37 + 38 + const char *check_header = getenv("MALLOC_CHECK_HEADER"); 39 + if (check_header && (!strcmp(check_header, "0") || !strcmp(check_header, "NO"))) { 40 + gmalloc_check_header = 0; 41 + } 42 + } 43 + 44 + static inline size_t round_up(size_t size, size_t increment) { 45 + if ((size & (increment - 1)) == 0) { 46 + return size; 47 + } 48 + return (size | (increment - 1)) + 1; 49 + } 50 + 51 + static inline void *round_down(void *address, size_t align) { 52 + uintptr_t v = (uintptr_t) address; 53 + return (void *) (v & ~(align - 1)); 54 + } 55 + 56 + static struct gmalloc_header *header_for_ptr(void *ptr) { 57 + return (struct gmalloc_header *) ((char *) ptr - sizeof(struct gmalloc_header)); 58 + } 59 + 60 + static void *do_alloc(size_t payload_size, size_t align) { 61 + if (align > vm_page_size) { 62 + // We don't support this. 63 + align = vm_page_size; 64 + } 65 + 66 + // Decide how much memory we're going to allocate, 67 + // not counting the guard page. 68 + size_t accessible_size = round_up(payload_size, align); 69 + if (gmalloc_protect_before) { 70 + // In protect-before mode, the header will reside 71 + // on the guard page, so need to add it here. 72 + } else { 73 + accessible_size += sizeof(struct gmalloc_header); 74 + } 75 + accessible_size = round_up(accessible_size, vm_page_size); 76 + 77 + void *mmap_base = mmap( 78 + NULL, accessible_size + vm_page_size, 79 + PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, 80 + -1, 0 81 + ); 82 + if (mmap_base == MAP_FAILED) { 83 + return NULL; 84 + } 85 + 86 + void *guard = gmalloc_protect_before ? mmap_base : mmap_base + accessible_size; 87 + void *accessible = gmalloc_protect_before ? mmap_base + vm_page_size : mmap_base; 88 + void *payload = gmalloc_protect_before ? accessible : accessible + accessible_size - payload_size; 89 + payload = round_down(payload, align); 90 + 91 + if (gmalloc_fill_space) { 92 + memset(accessible, 0x55, accessible_size); 93 + } 94 + 95 + struct gmalloc_header *header = header_for_ptr(payload); 96 + header->magic = header->magic_again = GMALLOC_MAGIC; 97 + header->size = payload_size; 98 + header->mmap_base = mmap_base; 99 + header->mmap_size = accessible_size + vm_page_size; 100 + 101 + int guard_page_prot = gmalloc_allow_reads ? PROT_READ : PROT_NONE; 102 + int rc = mprotect(guard, vm_page_size, guard_page_prot); 103 + if (rc < 0) { 104 + int saved_errno = errno; 105 + munmap(mmap_base, accessible_size + vm_page_size); 106 + errno = saved_errno; 107 + return NULL; 108 + } 109 + 110 + return payload; 111 + } 112 + 113 + void *aligned_alloc(size_t align, size_t size) { 114 + void *ptr = do_alloc(size, align); 115 + 116 + if (ptr == NULL) { 117 + int saved_errno = errno; 118 + const char msg[] = "Failed to alloc: "; 119 + write(2, msg, sizeof(msg)); 120 + // Do not use strerror(), because it allocates. 121 + extern const char *const sys_errlist[]; 122 + write(2, sys_errlist[saved_errno], strlen(sys_errlist[saved_errno])); 123 + write(2, "\n", 1); 124 + 125 + errno = saved_errno; 126 + return NULL; 127 + } 128 + 129 + return ptr; 130 + } 131 + 132 + void *malloc(size_t size) { 133 + return aligned_alloc(gmalloc_strict_size ? 1 : 16, size); 134 + } 135 + 136 + int posix_memalign(void **ptr, size_t align, size_t size) { 137 + *ptr = aligned_alloc(align, size); 138 + if (*ptr == NULL) { 139 + return ENOMEM; 140 + } 141 + return 0; 142 + } 143 + 144 + void *calloc(size_t num, size_t size) { 145 + void *ptr = malloc(num * size); 146 + memset(ptr, 0, num * size); 147 + return ptr; 148 + } 149 + 150 + static void check_header(const struct gmalloc_header *header) { 151 + if (!gmalloc_check_header) { 152 + return; 153 + } 154 + 155 + if (gmalloc_protect_before && !gmalloc_allow_reads) { 156 + mprotect(round_down((void *) header, vm_page_size), vm_page_size, PROT_READ); 157 + } 158 + 159 + if (header->magic != GMALLOC_MAGIC || header->magic_again != GMALLOC_MAGIC) { 160 + abort(); 161 + } 162 + } 163 + 164 + void free(void *ptr) { 165 + if (ptr == NULL) { 166 + return; 167 + } 168 + 169 + struct gmalloc_header *header = header_for_ptr(ptr); 170 + check_header(header); 171 + 172 + munmap(header->mmap_base, header->mmap_size); 173 + } 174 + 175 + void *realloc(void *old_ptr, size_t new_size) { 176 + size_t size_to_copy; 177 + if (old_ptr == NULL) { 178 + size_to_copy = 0; 179 + } else { 180 + struct gmalloc_header *header = header_for_ptr(old_ptr); 181 + check_header(header); 182 + size_to_copy = header->size; 183 + } 184 + if (size_to_copy > new_size) { 185 + size_to_copy = new_size; 186 + } 187 + 188 + void *new_ptr = malloc(new_size); 189 + if (new_ptr == NULL) { 190 + return NULL; 191 + } 192 + memcpy(new_ptr, old_ptr, size_to_copy); 193 + free(old_ptr); 194 + 195 + return new_ptr; 196 + } 197 + 198 + void *reallocarray(void *old_ptr, size_t num, size_t size) __DARWIN_EXTSN(reallocarray); 199 + void *reallocarray(void *old_ptr, size_t num, size_t size) { 200 + size_t new_size; 201 + if (os_mul_overflow(num, size, &new_size)) { 202 + errno = ENOMEM; 203 + return NULL; 204 + } 205 + return realloc(old_ptr, new_size); 206 + } 207 + 208 + void *reallocarrayf(void *old_ptr, size_t num, size_t size) __DARWIN_EXTSN(reallocarrayf); 209 + void *reallocarrayf(void *old_ptr, size_t num, size_t size) { 210 + size_t new_size; 211 + if (os_mul_overflow(num, size, &new_size)) { 212 + errno = ENOMEM; 213 + return NULL; 214 + } 215 + void *new_ptr = realloc(old_ptr, new_size); 216 + if (new_ptr == NULL) { 217 + free(old_ptr); 218 + } 219 + return new_ptr; 220 + } 221 + 222 + // Zone versions 223 + typedef void malloc_zone_t; 224 + void *malloc_zone_malloc(malloc_zone_t *zone, size_t size) { 225 + (void) zone; 226 + return malloc(size); 227 + } 228 + 229 + void *malloc_zone_calloc(malloc_zone_t *zone, size_t num, size_t size) { 230 + (void) zone; 231 + return calloc(num, size); 232 + } 233 + 234 + void *malloc_zone_realloc(malloc_zone_t *zone, void *ptr, size_t size) { 235 + (void) zone; 236 + return realloc(ptr, size); 237 + } 238 + 239 + void *malloc_zone_memalign(malloc_zone_t *zone, size_t align, size_t size) { 240 + (void) zone; 241 + void *ptr; 242 + posix_memalign(&ptr, align, size); 243 + return ptr; 244 + } 245 + 246 + void malloc_zone_free(malloc_zone_t *zone, void *ptr) { 247 + (void) zone; 248 + free(ptr); 249 + }