1 2 #ifdef _FILE_OFFSET_BITS 3 #undef _FILE_OFFSET_BITS 4 #endif 5 #define _FILE_OFFSET_BITS 64 6 7 #include <magic_mem.h> 8 #include <stdio.h> 9 #include <errno.h> 10 #include <stdarg.h> 11 #include <magic_asr.h> 12 13 #ifdef __MINIX 14 #define util_time_tsc_read_ns(x) 0 15 #define util_strhash(x, y) 0 16 #define util_stacktrace_hash() 0 17 #define util_stacktrace_print_custom(x) 18 #define util_stacktrace_hash_skip(x) 0 19 #else 20 #include <common/util/stacktrace.h> 21 #include <common/util/time.h> 22 #include <common/util/string.h> 23 #endif 24 25 #define DEBUG MAGIC_DEBUG_SET(0) 26 #define DEBUG_TYPE_SIZE_MISMATCH MAGIC_DEBUG_SET(0) 27 28 #if DEBUG 29 #define MAGIC_MEM_PRINTF _magic_printf 30 #else 31 #define MAGIC_MEM_PRINTF magic_null_printf 32 #endif 33 34 /* CPU frequency (used for timestamp logging) */ 35 PUBLIC double magic_cycles_per_ns = 0; 36 37 /* 38 * External callbacks. 39 */ 40 PUBLIC magic_mem_heap_alloc_cb_t magic_mem_heap_alloc_cb = NULL; 41 PUBLIC magic_mem_create_dsentry_cb_t magic_mem_create_dsentry_cb = NULL; 42 PUBLIC magic_mem_heap_free_cb_t magic_mem_heap_free_cb = NULL; 43 44 PUBLIC short magic_mem_create_dsentry_site_id = 0; 45 PUBLIC THREAD_LOCAL short magic_mem_wrapper_active = 0; 46 PUBLIC THREAD_LOCAL short magic_mempool_mgmt_active_level = 0; 47 PUBLIC THREAD_LOCAL short magic_mempool_ids[MAGIC_MEMPOOL_MAX_FUNC_RECURSIONS]; 48 49 const char* const MAGIC_MEMPOOL_NAME_UNKNOWN = "_magic_mempool_unknown#"; 50 const char* const MAGIC_MEMPOOL_NAME_DETACHED = "_magic_mempool_detached#"; 51 52 __attribute__((weak)) int magic_mempool_allow_reset = 1; 53 __attribute__((weak)) int magic_mempool_allow_reuse = 1; 54 __attribute__((weak)) int magic_mempool_allow_external_alloc = 0; 55 56 #define MAGIC_MEM_FAILED ((void*) -1) 57 58 #ifndef SHM_REMAP 59 #define SHM_REMAP 0 60 #endif 61 62 EXTERN char **environ; 63 64 PRIVATE magic_dsentry_cb_t magic_destroy_dsentry_ext_cb = NULL; 65 66 /* Magic real mem function definitions. */ 67 PUBLIC void *(*magic_real_malloc)(size_t size) = &malloc; 68 PUBLIC void *(*magic_real_calloc)(size_t nmemb, size_t size) = &calloc; 69 PUBLIC void (*magic_real_free)(void *ptr) = &free; 70 PUBLIC void *(*magic_real_realloc)(void *ptr, size_t size) = &realloc; 71 72 PUBLIC int (*magic_real_posix_memalign)(void **memptr, size_t alignment, size_t size) = &posix_memalign; 73 74 #ifndef __MINIX 75 PUBLIC void *(*magic_real_valloc)(size_t size) = &valloc; 76 PUBLIC void *(*magic_real_memalign)(size_t boundary, size_t size) = &memalign; 77 #endif 78 79 PUBLIC void *(*magic_real_mmap)(void *start, size_t length, int prot, int flags, 80 int fd, off_t offset) = &mmap; 81 PUBLIC int (*magic_real_munmap)(void *start, size_t length) = &munmap; 82 83 PUBLIC int (*magic_real_brk)(void *addr) = &brk; 84 PUBLIC void *(*magic_real_sbrk)(intptr_t increment) = &sbrk; 85 86 #ifndef __MINIX 87 PUBLIC void *(*magic_real_shmat)(int shmid, const void *shmaddr, int shmflg) = &shmat; 88 PUBLIC int (*magic_real_shmdt)(const void *shmaddr) = &shmdt; 89 90 PUBLIC void *(*magic_real_mmap64)(void *start, size_t length, int prot, int flags, 91 int fd, off_t pgoffset) = &mmap64; 92 #else 93 PUBLIC void *(*magic_real_vm_map_cacheblock)(dev_t dev, off_t dev_offset, 94 ino_t ino, off_t ino_offset, u32_t *flags, int blocksize) = &vm_map_cacheblock; 95 #endif 96 97 /* Use magic_real* functions in the rest of the file. */ 98 #include <magic_real_mem.h> 99 100 /* Macros for memory usage logging. */ 101 #if MAGIC_MEM_USAGE_OUTPUT_CTL 102 #define MAGIC_MEM_DEBUG_PREFIX "MEM_USAGE: " 103 #define TIMESTAMP_STR "%llu" 104 #define TIMESTAMP_ARG (util_time_tsc_read_ns(magic_cycles_per_ns)) 105 #define MAGIC_MEM_DEBUG_EVENT(EVENT, FORMAT, ...) \ 106 _magic_printf(MAGIC_MEM_DEBUG_PREFIX TIMESTAMP_STR " " #EVENT " " FORMAT "\n", TIMESTAMP_ARG, __VA_ARGS__) 107 #define MAGIC_MEM_DEBUG_EVENT_1(event, ptr) MAGIC_MEM_DEBUG_EVENT(event, "%u", (unsigned) ptr) 108 #define MAGIC_MEM_DEBUG_EVENT_2(event, ptr, type) MAGIC_MEM_DEBUG_EVENT(event, "%u %lu", (unsigned) ptr, type) 109 #define MAGIC_MEM_DEBUG_EVENT_3(event, ptr, type, size) MAGIC_MEM_DEBUG_EVENT(event, "%u %lu %d", (unsigned) ptr, type, size) 110 111 #if (MAGIC_MEM_USAGE_OUTPUT_CTL == 1) 112 /* use the hash of the name (extended with line number & file name) as dynamic type */ 113 #define MAGIC_MEM_GET_DTYPE() util_strhash(0, name) 114 #elif (MAGIC_MEM_USAGE_OUTPUT_CTL == 2) 115 /* use the hash of the stacktrace as a dynamic type */ 116 #define MAGIC_MEM_GET_DTYPE() util_stacktrace_hash() 117 #endif 118 #define MAGIC_MEM_DEBUG_ALLOC(ptr, size) MAGIC_MEM_DEBUG_EVENT_3(alloc, ptr, (MAGIC_MEMPOOL_MGMT_IS_ACTIVE() ? MAGIC_MEMPOOL_GET_DTYPE() : MAGIC_MEM_GET_DTYPE()), size) 119 #define MAGIC_MEM_DEBUG_FREE(ptr) MAGIC_MEM_DEBUG_EVENT_1(dealloc, ptr) 120 #define MAGIC_MEM_DEBUG_RESET(ptr) MAGIC_MEM_DEBUG_EVENT_1(reset, ptr) 121 #define MAGIC_MEM_DEBUG_REUSE(ptr, type) MAGIC_MEM_DEBUG_EVENT_2(reuse, ptr, type) 122 #else 123 #define MAGIC_MEM_GET_DTYPE() 0 124 #define MAGIC_MEM_DEBUG_ALLOC(ptr, size) 125 #define MAGIC_MEM_DEBUG_FREE(ptr) 126 #define MAGIC_MEM_DEBUG_RESET(ptr) 127 #define MAGIC_MEM_DEBUG_REUSE(ptr, type) 128 #endif 129 130 /*===========================================================================* 131 * magic_mempool_alloc_id * 132 *===========================================================================*/ 133 MAGIC_MACRO_FUNC short magic_mempool_alloc_id(void) 134 { 135 short i, id = -1; 136 137 MAGIC_MPDESC_LOCK(); 138 139 /* Find a free slot. */ 140 for(i = 0; i < MAGIC_MAX_MEMPOOLS; i++) { 141 if(MAGIC_MPDESC_IS_FREE(&_magic_mpdescs[i])) { 142 MAGIC_MPDESC_ALLOC(&_magic_mpdescs[i]); 143 id = i + 1; 144 break; 145 } 146 } 147 148 MAGIC_MPDESC_UNLOCK(); 149 150 assert((id > 0) && (id <= MAGIC_MAX_MEMPOOLS) && "Ran out of memory pool descriptors!"); 151 152 return id; 153 } 154 155 /*===========================================================================* 156 * magic_mempool_create_begin * 157 *===========================================================================*/ 158 MAGIC_HOOK void magic_mempool_create_begin(__MDEBUG_ARGS__) 159 { 160 MAGIC_MEMPOOL_MGMT_SET_ACTIVE(); 161 assert(MAGIC_MEMPOOL_MGMT_IS_ACTIVE()); 162 MAGIC_MEMPOOL_SET_ID(magic_mempool_alloc_id()); 163 MAGIC_MEMPOOL_SET_DTYPE(MAGIC_MEM_GET_DTYPE()); 164 } 165 166 /*===========================================================================* 167 * magic_mempool_create_end * 168 *===========================================================================*/ 169 MAGIC_HOOK void magic_mempool_create_end(void* addr, int indirection) 170 { 171 void* pool; 172 pool = (indirection && addr) ? *((void**)addr) : addr; 173 assert(pool && "Cannot have a NULL pool pointer."); 174 _magic_mpdescs[MAGIC_MEMPOOL_GET_ID() - 1].addr = pool; 175 magic_mempool_mgmt_end(); 176 } 177 178 /*===========================================================================* 179 * magic_mempool_lookup_by_addr * 180 *===========================================================================*/ 181 MAGIC_MACRO_FUNC short magic_mempool_lookup_by_addr(void* addr) 182 { 183 short i, id = MAGIC_MEMPOOL_ID_UNKNOWN; 184 185 if (addr) { 186 for(i = 0; i < MAGIC_MAX_MEMPOOLS; i++) { 187 if(_magic_mpdescs[i].addr == addr) { 188 id = i + 1; 189 break; 190 } 191 } 192 } 193 194 return id; 195 } 196 197 /*===========================================================================* 198 * magic_mempool_reset * 199 *===========================================================================*/ 200 MAGIC_MACRO_FUNC void magic_mempool_reset(const char* mempool_name, int reset_name) 201 { 202 struct _magic_dsentry *prev_dsentry, *dsentry, *block_dsentry; 203 struct _magic_sentry* sentry; 204 205 MAGIC_DSENTRY_LOCK(); 206 MAGIC_DSENTRY_MEMPOOL_ALIVE_ITER(_magic_first_mempool_dsentry, prev_dsentry, dsentry, sentry, 207 if (sentry->name == mempool_name) { 208 block_dsentry = MAGIC_DSENTRY_NEXT_MEMBLOCK(dsentry); 209 if (block_dsentry != NULL) { 210 struct _magic_dsentry *tmp_block_dsentry = 211 MAGIC_PCAS(&MAGIC_DSENTRY_NEXT_MEMBLOCK(dsentry), block_dsentry, NULL); 212 assert(tmp_block_dsentry == block_dsentry && "New blocks have been allocated from a reseted mempool!"); 213 } 214 if (reset_name) { 215 const char *tmp_name = 216 MAGIC_PCAS(&sentry->name, mempool_name, MAGIC_MEMPOOL_NAME_UNKNOWN); 217 assert(tmp_name == mempool_name && "The name of the mempool has changed while being reseted!"); 218 } 219 MAGIC_MEM_DEBUG_RESET((char*)dsentry); 220 } 221 ); 222 223 MAGIC_DSENTRY_UNLOCK(); 224 } 225 226 /*===========================================================================* 227 * magic_mempool_destroy_begin * 228 *===========================================================================*/ 229 MAGIC_HOOK void magic_mempool_destroy_begin(void* addr, int memory_reuse) 230 { 231 magic_mempool_mgmt_begin(addr); 232 if (addr && memory_reuse) { 233 assert(MAGIC_MEMPOOL_ID_IS_SET() && "Cannot destroy a pool with an unknown id."); 234 magic_mempool_reset(MAGIC_MEMPOOL_GET_NAME(), TRUE); 235 } 236 } 237 238 /*===========================================================================* 239 * magic_mempool_destroy_end * 240 *===========================================================================*/ 241 MAGIC_HOOK void magic_mempool_destroy_end() 242 { 243 MAGIC_MPDESC_LOCK(); 244 245 MAGIC_MPDESC_FREE(&_magic_mpdescs[MAGIC_MEMPOOL_GET_ID() - 1]); 246 247 MAGIC_MPDESC_UNLOCK(); 248 249 magic_mempool_mgmt_end(); 250 } 251 252 /*===========================================================================* 253 * magic_mempool_mgmt_begin * 254 *===========================================================================*/ 255 MAGIC_HOOK void magic_mempool_mgmt_begin(void* addr) 256 { 257 short id; 258 259 MAGIC_MEMPOOL_MGMT_SET_ACTIVE(); 260 assert(MAGIC_MEMPOOL_MGMT_IS_ACTIVE()); 261 262 id = magic_mempool_lookup_by_addr(addr); 263 /* For some reason, this mempool has not been registered yet, reserve a new slot in the mempool array. */ 264 if (addr && (id == MAGIC_MEMPOOL_ID_UNKNOWN)) { 265 id = magic_mempool_alloc_id(); 266 _magic_mpdescs[id - 1].addr = addr; 267 } 268 MAGIC_MEMPOOL_SET_ID(id); 269 } 270 271 /*===========================================================================* 272 * magic_mempool_mgmt_end * 273 *===========================================================================*/ 274 MAGIC_HOOK void magic_mempool_mgmt_end() 275 { 276 MAGIC_MEMPOOL_SET_ID(MAGIC_MEMPOOL_ID_UNKNOWN); 277 assert(MAGIC_MEMPOOL_MGMT_IS_ACTIVE()); 278 MAGIC_MEMPOOL_MGMT_UNSET_ACTIVE(); 279 } 280 281 /*===========================================================================* 282 * magic_mempool_reset_begin * 283 *===========================================================================*/ 284 MAGIC_HOOK void magic_mempool_reset_begin(void* addr) 285 { 286 magic_mempool_mgmt_begin(addr); 287 /* skip reset when it has been disabled by the application. */ 288 if (magic_mempool_allow_reset) { 289 if (addr != NULL) { 290 assert(MAGIC_MEMPOOL_ID_IS_SET() && "Cannot reset a pool with an unknown id."); 291 magic_mempool_reset(MAGIC_MEMPOOL_GET_NAME(), TRUE); 292 } 293 } 294 } 295 296 /*===========================================================================* 297 * magic_mempool_dsentry_set_name * 298 *===========================================================================*/ 299 MAGIC_MACRO_FUNC void magic_mempool_dsentry_set_name(struct _magic_dsentry* dsentry, 300 const char* name) 301 { 302 const char *old_name, *ret; 303 304 if ((name == MAGIC_MEMPOOL_NAME_UNKNOWN) || (name == MAGIC_MEMPOOL_NAME_DETACHED)) { 305 do { 306 old_name = MAGIC_DSENTRY_TO_SENTRY(dsentry)->name; 307 } while (MAGIC_CAS(&MAGIC_DSENTRY_TO_SENTRY(dsentry)->name, old_name, name) != old_name && old_name != name); 308 } else { 309 old_name = MAGIC_DSENTRY_TO_SENTRY(dsentry)->name; 310 if (old_name != name) { 311 if (!strncmp(old_name, MAGIC_MEMPOOL_NAME_PREFIX, strlen(MAGIC_MEMPOOL_NAME_PREFIX))) { 312 assert(((old_name == MAGIC_MEMPOOL_NAME_UNKNOWN) || (old_name == MAGIC_MEMPOOL_NAME_DETACHED)) 313 && "Cannot overwrite an already existing valid memory pool name!"); 314 } 315 ret = MAGIC_CAS(&MAGIC_DSENTRY_TO_SENTRY(dsentry)->name, old_name, name); 316 assert((ret == old_name || ret == name) && "Cannot overwrite an already existing valid memory pool name!"); 317 } 318 } 319 } 320 321 /*===========================================================================* 322 * magic_mempool_dsentry_update * 323 *===========================================================================*/ 324 MAGIC_MACRO_FUNC void magic_mempool_dsentry_update(struct _magic_dsentry* dsentry, 325 const char* name) 326 { 327 struct _magic_sentry* sentry = MAGIC_DSENTRY_TO_SENTRY(dsentry); 328 struct _magic_dsentry* next_mempool_dsentry; 329 int flags; 330 /* set the magic state mempool flag atomically */ 331 do { 332 flags = sentry->flags; 333 } while (MAGIC_CAS(&sentry->flags, flags, flags | MAGIC_STATE_MEMPOOL) != flags && !(flags & MAGIC_STATE_MEMPOOL)); 334 magic_mempool_dsentry_set_name(dsentry, name); 335 /* the thread that updates the id adds the dsentry to the mempool dsentry list */ 336 if (!(flags & MAGIC_STATE_MEMPOOL)) { 337 /* Add the new dsentry before the first dsentry atomically. */ 338 do { 339 next_mempool_dsentry = _magic_first_mempool_dsentry; 340 MAGIC_DSENTRY_NEXT_MEMPOOL(dsentry) = next_mempool_dsentry; 341 } while(MAGIC_CAS(&_magic_first_mempool_dsentry, next_mempool_dsentry, dsentry) != next_mempool_dsentry); 342 } 343 } 344 345 /*===========================================================================* 346 * mempool_block_alloc_template * 347 *===========================================================================*/ 348 MAGIC_FUNC void *mempool_block_alloc_template(void* addr, size_t size) 349 { 350 return NULL; 351 } 352 353 /*===========================================================================* 354 * magic_mempool_block_alloc_template * 355 *===========================================================================*/ 356 PUBLIC void *magic_mempool_block_alloc_template(__MA_ARGS__ void* addr, size_t size) 357 { 358 void *ptr, *data_ptr; 359 struct _magic_sentry* mempool_sentry; 360 struct _magic_dsentry* mempool_dsentry, *next_block_dsentry; 361 362 magic_mempool_mgmt_begin(addr); 363 /* don't set the memory wrapper flag, this function is supposed to allocate memory from a pool 364 and not using the standard allocators. it might also call other memory pool management functions */ 365 if(size > 0) { 366 /* this call should be replaced with a call to a "real" block allocation function, when generating custom wrappers */ 367 ptr = mempool_block_alloc_template(addr, MAGIC_SIZE_TO_REAL(size) + magic_asr_get_padding_size(MAGIC_STATE_HEAP)); 368 MAGIC_MEM_PRINTF("%s: ptr = malloc(size) <-> 0x%08x = malloc(%d)\n", __FUNCTION__,(unsigned) ptr, MAGIC_SIZE_TO_REAL(size)); 369 data_ptr = magic_alloc(__MA_VALUES__ ptr, size, MAGIC_STATE_HEAP | MAGIC_STATE_MEMBLOCK); 370 if(data_ptr == MAGIC_MEM_FAILED) { 371 /* cannot free individual blocks inside the pool */ 372 data_ptr = NULL; 373 errno = ENOMEM; 374 } else if (ptr) { 375 /* lookup the pool buffer dsentry from which this block was allocated */ 376 mempool_sentry = magic_mempool_sentry_lookup_by_range(ptr, NULL); 377 if (!mempool_sentry && magic_mempool_allow_external_alloc) { 378 mempool_sentry = magic_sentry_lookup_by_range(ptr, NULL); 379 if (mempool_sentry) { 380 magic_mempool_dsentry_update(MAGIC_DSENTRY_FROM_SENTRY(mempool_sentry), MAGIC_MEMPOOL_GET_NAME()); 381 } 382 } 383 384 assert(mempool_sentry && "XXX Mempool dsentry not found for this memblock dsentry: memory not allocated from a memory pool management function?"); 385 mempool_dsentry = MAGIC_DSENTRY_FROM_SENTRY(mempool_sentry); 386 387 /* Reuse of buffers across pools - propagate the new pool name */ 388 if (MAGIC_MEMPOOL_ID_IS_SET() && (mempool_sentry->name != MAGIC_MEMPOOL_GET_NAME())) { 389 assert(magic_mempool_allow_reuse && "Pool memory reuse is disabled!"); 390 magic_mempool_dsentry_set_name(mempool_dsentry, MAGIC_MEMPOOL_GET_NAME()); 391 } 392 MAGIC_DSENTRY_TO_SENTRY(MAGIC_PTR_TO_DSENTRY(MAGIC_PTR_FROM_DATA(data_ptr)))->name = mempool_sentry->name; 393 394 /* Add the new dsentry before the first block dsentry chained to the memory pool dsentry, atomically. 395 The list should be circular - the last block dsentry (first one added) points to the memory pool dsentry. */ 396 do { 397 next_block_dsentry = MAGIC_DSENTRY_NEXT_MEMBLOCK(mempool_dsentry); 398 MAGIC_DSENTRY_NEXT_MEMBLOCK(MAGIC_PTR_TO_DSENTRY(MAGIC_PTR_FROM_DATA(data_ptr))) = next_block_dsentry ? next_block_dsentry : mempool_dsentry; 399 }while(MAGIC_CAS(&(MAGIC_DSENTRY_NEXT_MEMBLOCK(mempool_dsentry)), next_block_dsentry, MAGIC_PTR_TO_DSENTRY(MAGIC_PTR_FROM_DATA(data_ptr))) != next_block_dsentry); 400 401 /* First write to this pool buffer, potential reuse */ 402 if (next_block_dsentry == NULL) { 403 MAGIC_MEM_DEBUG_REUSE((char*)mempool_dsentry, MAGIC_MEMPOOL_GET_DTYPE()); 404 } 405 } 406 } 407 else { 408 /* Some applications return a valid pointer even if size is 0... */ 409 data_ptr = mempool_block_alloc_template(addr, size); 410 } 411 magic_mempool_mgmt_end(); 412 413 return data_ptr; 414 } 415 416 /*===========================================================================* 417 * magic_create_dsentry * 418 *===========================================================================*/ 419 PUBLIC int magic_create_dsentry(struct _magic_dsentry *dsentry, 420 void *data_ptr, struct _magic_type *type, size_t size, int flags, 421 const char *name, const char *parent_name) 422 { 423 /* This function does not require any dsentry locking. */ 424 struct _magic_sentry *sentry = MAGIC_DSENTRY_TO_SENTRY(dsentry); 425 struct _magic_dsentry *next_dsentry, *next_mempool_dsentry; 426 size_t type_size; 427 int is_varsized = 0; 428 int num_vsa_elements = 0; 429 430 struct _magic_dsentry *saved_next = dsentry->next; 431 int save_linkage = ((flags & MAGIC_STATE_HEAP) && _magic_vars->fake_malloc); 432 433 MAGIC_MEM_PRINTF("Dsentry created from stacktrace:\n"); 434 if (MAGIC_MEM_PRINTF != magic_null_printf) { 435 MAGIC_MEM_WRAPPER_BEGIN(); 436 util_stacktrace_print_custom(MAGIC_MEM_PRINTF); 437 MAGIC_MEM_WRAPPER_END(); 438 } 439 440 if (!type) { 441 type = MAGIC_VOID_TYPE; 442 } 443 type_size = type->size; 444 assert(size > 0); 445 446 memcpy(dsentry, &magic_default_dsentry, sizeof(struct _magic_dsentry)); 447 448 /* Catch variable-sized struct allocation. */ 449 if (magic_type_alloc_needs_varsized_array(type, size, &num_vsa_elements)) { 450 is_varsized = 1; 451 } 452 453 if (size % type_size != 0 && !is_varsized) { 454 /* This should only happen for uncaught variable-sized struct allocations. */ 455 #if DEBUG_TYPE_SIZE_MISMATCH 456 _magic_printf("magic_create_dsentry: type <-> size mismatch, reverting to void type: size=%d, type=", size); 457 MAGIC_TYPE_PRINT(type, MAGIC_EXPAND_TYPE_STR); 458 _magic_printf("\n"); 459 #endif 460 type = MAGIC_VOID_TYPE; 461 type_size = type->size; 462 flags |= MAGIC_STATE_TYPE_SIZE_MISMATCH; 463 } 464 465 if (size == type_size && !is_varsized) { 466 sentry->type = type; 467 } 468 else { 469 struct _magic_type *array_type = &(dsentry->type); 470 MAGIC_TYPE_ARRAY_CREATE_FROM_SIZE(array_type, type, 471 MAGIC_DSENTRY_TO_TYPE_ARR(dsentry), size, num_vsa_elements); 472 array_type->id = MAGIC_FAA(&_magic_types_next_id, 1); 473 assert(_magic_types_next_id < MAGIC_ID_MAX); 474 sentry->type = array_type; 475 } 476 477 sentry->flags |= flags; 478 sentry->address = data_ptr; 479 480 if (name) { 481 sentry->name = name; 482 } 483 if (parent_name) { 484 dsentry->parent_name = parent_name; 485 } 486 sentry->id = MAGIC_FAA(&_magic_sentries_next_id, 1); 487 assert(_magic_sentries_next_id < MAGIC_ID_MAX); 488 489 /* 490 * TODO: Also add per-callsite index to handle the following: 491 * for (;;) { p = malloc(); } 492 */ 493 if (magic_mem_create_dsentry_site_id) { 494 MAGIC_MEM_WRAPPER_BEGIN(); 495 /* 496 * XXX: This is so damn ugly, but we don't want to include 497 * any magic_* functions in the stacktrace hash. 498 * This should probably be done in a much more elegant manner. 499 */ 500 dsentry->site_id = util_stacktrace_hash_skip((char *)"("MAGIC_PREFIX_STR); 501 MAGIC_MEM_WRAPPER_END(); 502 } 503 504 if (save_linkage) { 505 dsentry->next = saved_next; 506 return 0; 507 } 508 509 /* Add the new dsentry before the first dsentry atomically. 510 * Skip memblock dsentries to make pool reset/destruction faster. 511 */ 512 if (!MAGIC_STATE_FLAG(sentry, MAGIC_STATE_MEMBLOCK)) { 513 do { 514 next_dsentry = _magic_first_dsentry; 515 MAGIC_DSENTRY_NEXT(dsentry) = next_dsentry; 516 } while(MAGIC_CAS(&_magic_first_dsentry, next_dsentry, dsentry) != next_dsentry); 517 } 518 519 #if MAGIC_DSENTRY_ALLOW_PREV 520 next_dsentry = MAGIC_DSENTRY_NEXT(dsentry); 521 if (next_dsentry) { 522 MAGIC_DSENTRY_PREV(next_dsentry) = dsentry; 523 } 524 MAGIC_DSENTRY_PREV(dsentry) = NULL; 525 #endif 526 527 if (MAGIC_STATE_FLAG(sentry, MAGIC_STATE_MEMPOOL)) { 528 /* Add the new dsentry before the first mempool dsentry atomically. */ 529 do { 530 next_mempool_dsentry = _magic_first_mempool_dsentry; 531 MAGIC_DSENTRY_NEXT_MEMPOOL(dsentry) = next_mempool_dsentry; 532 } while(MAGIC_CAS(&_magic_first_mempool_dsentry, next_mempool_dsentry, dsentry) != next_mempool_dsentry); 533 } 534 magic_update_dsentry_ranges = 1; 535 536 if (magic_mem_create_dsentry_cb) 537 magic_mem_create_dsentry_cb(dsentry); 538 539 return 0; 540 } 541 542 /*===========================================================================* 543 * magic_create_obdsentry * 544 *===========================================================================*/ 545 PUBLIC struct _magic_obdsentry* magic_create_obdsentry(void *data_ptr, 546 struct _magic_type *type, size_t size, int flags, 547 const char *name, const char *parent_name) 548 { 549 struct _magic_obdsentry *obdsentry = NULL; 550 int i, ret; 551 552 /* Check name. */ 553 if(!name || !strcmp(name, "")) { 554 return NULL; 555 } 556 else if(strlen(name) >= MAGIC_MAX_OBDSENTRY_NAME_LEN) { 557 return NULL; 558 } 559 560 /* Check parent name. */ 561 if(!parent_name || !strcmp(parent_name, "")) { 562 parent_name = MAGIC_OBDSENTRY_DEFAULT_PARENT_NAME; 563 } 564 if(strlen(parent_name) >= MAGIC_MAX_OBDSENTRY_PARENT_NAME_LEN) { 565 return NULL; 566 } 567 568 MAGIC_MEM_WRAPPER_LBEGIN(); 569 570 /* Find a free slot. */ 571 for(i=0;i<MAGIC_MAX_OBDSENTRIES;i++) { 572 if(MAGIC_OBDSENTRY_IS_FREE(&_magic_obdsentries[i])) { 573 obdsentry = &_magic_obdsentries[i]; 574 break; 575 } 576 } 577 if(!obdsentry) { 578 MAGIC_MEM_WRAPPER_LEND(); 579 return NULL; 580 } 581 582 /* Create the dsentry. */ 583 strcpy(obdsentry->name, name); 584 strcpy(obdsentry->parent_name, parent_name); 585 flags |= MAGIC_STATE_OUT_OF_BAND; 586 ret = magic_create_dsentry(MAGIC_OBDSENTRY_TO_DSENTRY(obdsentry), data_ptr, type, 587 size, flags, obdsentry->name, obdsentry->parent_name); 588 589 MAGIC_MEM_WRAPPER_LEND(); 590 591 if(ret < 0) { 592 return NULL; 593 } 594 assert(!MAGIC_OBDSENTRY_IS_FREE(obdsentry)); 595 596 return obdsentry; 597 } 598 599 /*===========================================================================* 600 * magic_update_dsentry_state * 601 *===========================================================================*/ 602 PUBLIC int magic_update_dsentry_state(struct _magic_dsentry *dsentry, 603 unsigned long state) 604 { 605 int ret = 0; 606 unsigned long old_state; 607 unsigned long num_dead_dsentries; 608 unsigned long size, size_dead_dsentries; 609 size = MAGIC_DSENTRY_TO_SENTRY(dsentry)->type->size; 610 611 switch(state) { 612 case MAGIC_DSENTRY_MSTATE_FREED: 613 old_state = MAGIC_CAS(&dsentry->magic_state, MAGIC_DSENTRY_MSTATE_DEAD, 614 MAGIC_DSENTRY_MSTATE_FREED); 615 if(old_state != MAGIC_DSENTRY_MSTATE_DEAD) { 616 ret = MAGIC_EBADMSTATE; 617 break; 618 } 619 if (!MAGIC_STATE_FLAG(MAGIC_DSENTRY_TO_SENTRY(dsentry), MAGIC_STATE_MEMBLOCK)) { 620 num_dead_dsentries = MAGIC_FAS(&magic_num_dead_dsentries, 1) - 1; 621 size_dead_dsentries = MAGIC_FAS(&magic_size_dead_dsentries, size) - size; 622 MAGIC_MEM_PRINTF("magic_update_dsentry_state: --magic_num_dead_dsentries (num=%d, size=%d)\n", num_dead_dsentries, size_dead_dsentries); 623 } 624 break; 625 case MAGIC_DSENTRY_MSTATE_DEAD: 626 old_state = MAGIC_CAS(&dsentry->magic_state, MAGIC_DSENTRY_MSTATE_ALIVE, 627 MAGIC_DSENTRY_MSTATE_DEAD); 628 if(old_state != MAGIC_DSENTRY_MSTATE_ALIVE) { 629 ret = (old_state == MAGIC_DSENTRY_MSTATE_DEAD 630 || old_state == MAGIC_DSENTRY_MSTATE_FREED) 631 ? MAGIC_EBADMSTATE : MAGIC_EBADENT; 632 break; 633 } 634 MAGIC_DSENTRY_TO_SENTRY(dsentry)->id = MAGIC_FAA(&_magic_sentries_next_id, 1); 635 assert(_magic_sentries_next_id < MAGIC_ID_MAX); 636 if (!MAGIC_STATE_FLAG(MAGIC_DSENTRY_TO_SENTRY(dsentry), MAGIC_STATE_MEMBLOCK)) { 637 num_dead_dsentries = MAGIC_FAA(&magic_num_dead_dsentries, 1) + 1; 638 size_dead_dsentries = MAGIC_FAA(&magic_size_dead_dsentries, size) + size; 639 MAGIC_MEM_PRINTF("magic_update_dsentry_state: ++magic_num_dead_dsentries (num=%d, size=%d)\n", num_dead_dsentries, size_dead_dsentries); 640 if(!magic_ignore_dead_dsentries 641 && MAGIC_DEAD_DSENTRIES_NEED_FREEING()) { 642 magic_free_dead_dsentries(); 643 } 644 } 645 break; 646 default: 647 ret = MAGIC_EINVAL; 648 break; 649 } 650 651 return ret; 652 } 653 654 /*===========================================================================* 655 * magic_free_dsentry * 656 *===========================================================================*/ 657 PRIVATE int magic_free_dsentry(struct _magic_dsentry *dsentry) 658 { 659 int ret = 0; 660 struct _magic_sentry *sentry = MAGIC_DSENTRY_TO_SENTRY(dsentry); 661 int region = MAGIC_STATE_REGION(sentry); 662 void *ptr = MAGIC_PTR_FROM_DSENTRY(dsentry); 663 size_t page_size, size; 664 void *data_ptr, *aligned_ptr; 665 int from_wrapper = MAGIC_MEM_WRAPPER_IS_ACTIVE(); 666 assert(dsentry->magic_number == MAGIC_DSENTRY_MNUM_NULL); 667 668 if (!from_wrapper) { 669 MAGIC_MEM_WRAPPER_BEGIN(); 670 } 671 672 if (magic_mem_heap_free_cb) { 673 ret = magic_mem_heap_free_cb(dsentry); 674 if (ret != MAGIC_ENOENT) 675 return ret; 676 677 /* 678 * If the callback returned MAGIC_ENOENT, fallback to 679 * the default behavior. 680 */ 681 ret = 0; 682 } 683 684 /* A MAP_SHARED region will have both MAGIC_STATE_MAP and MAGIC_STATE_SHM. */ 685 if (region == (MAGIC_STATE_MAP | MAGIC_STATE_SHM)) 686 region = MAGIC_STATE_MAP; 687 switch (region) { 688 case MAGIC_STATE_HEAP: 689 MAGIC_MEM_DEBUG_FREE(ptr); 690 free(ptr); 691 break; 692 case MAGIC_STATE_MAP: 693 case MAGIC_STATE_SHM: 694 page_size = MAGIC_PAGE_SIZE; 695 size = MAGIC_DSENTRY_TO_SENTRY(dsentry)->type->size; 696 data_ptr = MAGIC_PTR_TO_DATA(ptr); 697 aligned_ptr = ((char *)data_ptr) - page_size; 698 699 if (!MAGIC_STATE_FLAG(sentry, MAGIC_STATE_DETACHED)) { 700 size_t padding_size = (size_t) dsentry->ext; 701 MAGIC_MEM_DEBUG_FREE(ptr); 702 ret = munmap((char *)aligned_ptr, page_size + size + padding_size); 703 } 704 else { 705 #ifndef __MINIX 706 if (MAGIC_STATE_FLAG(sentry, MAGIC_STATE_SHM)) 707 ret = shmdt(data_ptr); 708 else 709 #endif 710 ret = munmap(data_ptr, size); 711 MAGIC_MEM_DEBUG_FREE(ptr); 712 munmap(aligned_ptr, page_size); 713 } 714 if (ret != 0) { 715 ret = MAGIC_EBADENT; 716 } 717 break; 718 default: 719 ret = MAGIC_EBADENT; 720 break; 721 } 722 if (!from_wrapper) { 723 MAGIC_MEM_WRAPPER_END(); 724 } 725 726 return ret; 727 } 728 729 /*===========================================================================* 730 * magic_free_dead_dsentries * 731 *===========================================================================*/ 732 PUBLIC void magic_free_dead_dsentries() 733 { 734 struct _magic_dsentry *prev_dsentry, *dsentry, *next_first_dsentry, *skipped_dsentry; 735 struct _magic_sentry *sentry; 736 unsigned long num_dead_dsentries; 737 int dead_dsentries_left; 738 int ret; 739 740 MAGIC_DSENTRY_LOCK(); 741 742 skipped_dsentry = NULL; 743 num_dead_dsentries = magic_num_dead_dsentries; 744 next_first_dsentry = _magic_first_dsentry; 745 if (next_first_dsentry) { 746 /* if the first dsentry is dead, skip it to eliminate contention on the list head */ 747 if (next_first_dsentry->magic_state == MAGIC_DSENTRY_MSTATE_DEAD){ 748 num_dead_dsentries--; 749 } 750 } 751 752 if(!next_first_dsentry || num_dead_dsentries == 0) { 753 MAGIC_DSENTRY_UNLOCK(); 754 return; 755 } 756 757 MAGIC_MEM_PRINTF("magic_free_dead_dsentries: Freeing %d dead dsentries...\n", num_dead_dsentries); 758 759 /* Eliminate the dead dsentries but always skip the first one to eliminate contention on the head. */ 760 do { 761 dead_dsentries_left = 0; 762 MAGIC_DSENTRY_ITER(next_first_dsentry->next, prev_dsentry, dsentry, sentry, 763 /* normal dsentry to be freed */ 764 if ((dsentry->magic_state != MAGIC_DSENTRY_MSTATE_DEAD) || 765 (magic_update_dsentry_state(dsentry, MAGIC_DSENTRY_MSTATE_FREED) < 0)) { 766 next_first_dsentry = dsentry; 767 } else { 768 magic_destroy_dsentry(dsentry, prev_dsentry); 769 ret = magic_free_dsentry(dsentry); 770 if(ret != 0) { 771 _magic_printf("Warning: magic_free_dsentry failed with return code %d for: ", ret); 772 MAGIC_DSENTRY_PRINT(dsentry, MAGIC_EXPAND_TYPE_STR); 773 MAGIC_MEM_PRINTF("\n"); 774 } 775 num_dead_dsentries--; 776 dead_dsentries_left = 1; 777 break; 778 } 779 ); 780 } while(dead_dsentries_left && num_dead_dsentries > 0); 781 assert(num_dead_dsentries == 0); 782 783 MAGIC_DSENTRY_UNLOCK(); 784 } 785 786 /*===========================================================================* 787 * magic_destroy_dsentry * 788 *===========================================================================*/ 789 PUBLIC void magic_destroy_dsentry(struct _magic_dsentry *dsentry, 790 struct _magic_dsentry *prev_dsentry) 791 { 792 struct _magic_dsentry *next_dsentry, *next_mempool_dsentry, *prev_mempool_dsentry = NULL; 793 int dsentry_destroyed, mempool_dsentry_destroyed; 794 795 if(magic_destroy_dsentry_ext_cb && MAGIC_DSENTRY_HAS_EXT(dsentry)) { 796 magic_destroy_dsentry_ext_cb(dsentry); 797 } 798 if (MAGIC_STATE_FLAG(MAGIC_DSENTRY_TO_SENTRY(dsentry), MAGIC_STATE_MEMPOOL)) { 799 do { 800 if(!prev_mempool_dsentry) { 801 if(MAGIC_DSENTRY_NEXT_MEMPOOL(dsentry) != MAGIC_DSENTRY_NEXT_MEMPOOL(_magic_first_mempool_dsentry)) { 802 prev_mempool_dsentry = magic_mempool_dsentry_prev_lookup(dsentry); 803 assert(prev_mempool_dsentry != (struct _magic_dsentry *) MAGIC_ENOPTR && "Dsentry not found!"); 804 } 805 } 806 if(prev_mempool_dsentry) { 807 MAGIC_DSENTRY_NEXT_MEMPOOL(prev_mempool_dsentry) = MAGIC_DSENTRY_NEXT_MEMPOOL(dsentry); 808 mempool_dsentry_destroyed = 1; 809 } 810 else { 811 /* Remove the first dsentry atomically. */ 812 next_mempool_dsentry = MAGIC_DSENTRY_NEXT_MEMPOOL(dsentry); 813 mempool_dsentry_destroyed = (MAGIC_CAS(&_magic_first_mempool_dsentry, 814 dsentry, next_mempool_dsentry) == dsentry); 815 } 816 } while(!mempool_dsentry_destroyed); 817 MAGIC_DSENTRY_NEXT_MEMPOOL(dsentry) = NULL; 818 } 819 do { 820 #if MAGIC_DSENTRY_ALLOW_PREV 821 prev_dsentry = MAGIC_DSENTRY_PREV(dsentry); 822 #else 823 if(!prev_dsentry) { 824 if(MAGIC_DSENTRY_NEXT(dsentry) != MAGIC_DSENTRY_NEXT(_magic_first_dsentry)) { 825 prev_dsentry = magic_dsentry_prev_lookup(dsentry); 826 assert(prev_dsentry != (struct _magic_dsentry *) MAGIC_ENOPTR && "Dsentry not found!"); 827 } 828 } 829 #endif 830 831 if(prev_dsentry) { 832 MAGIC_DSENTRY_NEXT(prev_dsentry) = MAGIC_DSENTRY_NEXT(dsentry); 833 dsentry_destroyed = 1; 834 } 835 else { 836 /* Remove the first dsentry atomically. */ 837 next_dsentry = MAGIC_DSENTRY_NEXT(dsentry); 838 dsentry_destroyed = (MAGIC_CAS(&_magic_first_dsentry, 839 dsentry, next_dsentry) == dsentry); 840 } 841 } while(!dsentry_destroyed); 842 843 #if MAGIC_DSENTRY_ALLOW_PREV 844 next_dsentry = MAGIC_DSENTRY_NEXT(dsentry); 845 if(next_dsentry) { 846 MAGIC_DSENTRY_PREV(next_dsentry) = MAGIC_DSENTRY_PREV(dsentry); 847 } 848 MAGIC_DSENTRY_PREV(dsentry) = NULL; 849 #endif 850 851 dsentry->magic_number = MAGIC_DSENTRY_MNUM_NULL; 852 MAGIC_DSENTRY_NEXT(dsentry) = NULL; 853 } 854 855 /*===========================================================================* 856 * magic_destroy_obdsentry_by_addr * 857 *===========================================================================*/ 858 PUBLIC int magic_destroy_obdsentry_by_addr(void *data_ptr) 859 { 860 struct _magic_sentry *sentry; 861 struct _magic_dsentry *dsentry; 862 struct _magic_obdsentry *obdsentry; 863 int obflags = (MAGIC_STATE_DYNAMIC|MAGIC_STATE_OUT_OF_BAND); 864 865 MAGIC_MEM_WRAPPER_LBEGIN(); 866 867 /* Lookup the obdsentry. */ 868 sentry = magic_sentry_lookup_by_addr(data_ptr, NULL); 869 if(!sentry || ((sentry->flags & obflags) != obflags)) { 870 MAGIC_MEM_WRAPPER_LEND(); 871 return MAGIC_EINVAL; 872 } 873 dsentry = MAGIC_DSENTRY_FROM_SENTRY(sentry); 874 obdsentry = MAGIC_OBDSENTRY_FROM_DSENTRY(dsentry); 875 876 /* Destroy it and free obdsentry slot. */ 877 magic_destroy_dsentry(dsentry, NULL); 878 MAGIC_OBDSENTRY_FREE(obdsentry); 879 880 MAGIC_MEM_WRAPPER_LEND(); 881 882 return 0; 883 } 884 885 /*===========================================================================* 886 * magic_destroy_dsentry_set_ext_cb * 887 *===========================================================================*/ 888 PUBLIC void magic_destroy_dsentry_set_ext_cb(const magic_dsentry_cb_t cb) 889 { 890 magic_destroy_dsentry_ext_cb = cb; 891 } 892 893 /*===========================================================================* 894 * magic_update_dsentry * 895 *===========================================================================*/ 896 PUBLIC int magic_update_dsentry(void* addr, struct _magic_type *type) 897 { 898 struct _magic_dsentry *prev_dsentry, *dsentry; 899 struct _magic_sentry* sentry; 900 size_t size, type_size; 901 int is_varsized = 0; 902 int num_vsa_elements = 0; 903 904 MAGIC_DSENTRY_LOCK(); 905 MAGIC_DSENTRY_ALIVE_BLOCK_ITER(_magic_first_dsentry, prev_dsentry, dsentry, sentry, 906 if(sentry->address == addr) { 907 size = sentry->type->size; 908 type_size = type->size; 909 910 /* Catch variable-sized struct allocation. */ 911 if(magic_type_alloc_needs_varsized_array(type, size, &num_vsa_elements)) { 912 is_varsized = 1; 913 } 914 915 if(size % type_size != 0 && !is_varsized) { 916 return MAGIC_EBADENT; 917 } 918 if(size == type_size && !is_varsized) { 919 sentry->type = type; 920 } 921 else { 922 struct _magic_type *array_type = &(dsentry->type); 923 MAGIC_TYPE_ARRAY_CREATE_FROM_SIZE(array_type, type, 924 MAGIC_DSENTRY_TO_TYPE_ARR(dsentry), size, num_vsa_elements); 925 array_type->id = MAGIC_FAA(&_magic_types_next_id, 1); 926 assert(_magic_types_next_id < MAGIC_ID_MAX); 927 sentry->type = array_type; 928 } 929 return 0; 930 } 931 ); 932 MAGIC_DSENTRY_UNLOCK(); 933 934 return MAGIC_ENOENT; 935 } 936 937 /*===========================================================================* 938 * magic_stack_init * 939 *===========================================================================*/ 940 PUBLIC void magic_stack_init() 941 { 942 struct _magic_obdsentry *obdsentry; 943 char **ptr; 944 size_t size; 945 void *initial_stack_bottom, *initial_stack_top; 946 unsigned long* word_ptr; 947 int argc; 948 char **argv; 949 950 assert(!_magic_first_stack_dsentry && !_magic_last_stack_dsentry); 951 952 /* Find initial stack bottom and top, this should be portable enough */ 953 for (ptr = environ ; *ptr ; ptr++); 954 if (ptr == environ){ 955 /* the environment is empty, and ptr still points to environ. 956 * decrement ptr twice: once to point at the argv terminator, 957 * and once to point to point at the last argument, which will be the stack bottom 958 */ 959 ptr -= 2; 960 } else { 961 /* environment is not empty. decrement the pointer, 962 * because the for loop walked past the last env variable pointer. 963 */ 964 ptr--; 965 } 966 967 if (*ptr) { 968 initial_stack_bottom = *ptr+strlen(*ptr)+1; 969 word_ptr = (unsigned long*) environ; 970 word_ptr--; 971 assert(*word_ptr == 0); /* argv terminator */ 972 word_ptr--; 973 argc = 0; 974 while(*word_ptr != (unsigned long) argc) { 975 argc++; 976 word_ptr--; 977 } 978 argv = (char**) (word_ptr+1); 979 initial_stack_top = argv; 980 } else { 981 /* Environ and argv empty?. Resort to defaults. */ 982 initial_stack_top = ptr; 983 initial_stack_bottom = environ; 984 } 985 size = (size_t)initial_stack_bottom - (size_t)initial_stack_top + 1; 986 987 /* Create the first stack dsentry. */ 988 obdsentry = magic_create_obdsentry(initial_stack_top, MAGIC_VOID_TYPE, 989 size, MAGIC_STATE_STACK, MAGIC_ALLOC_INITIAL_STACK_NAME, NULL); 990 assert(obdsentry); 991 _magic_first_stack_dsentry = _magic_last_stack_dsentry = MAGIC_OBDSENTRY_TO_DSENTRY(obdsentry); 992 } 993 994 /*===========================================================================* 995 * magic_stack_dsentries_create * 996 *===========================================================================*/ 997 PUBLIC void magic_stack_dsentries_create( 998 struct _magic_dsentry **prev_last_stack_dsentry, int num_dsentries, 999 /* struct _magic_dsentry *dsentry, struct _magic_type *type, void* data_ptr, const char* function_name, const char* name, */ ...) 1000 { 1001 int i; 1002 struct _magic_dsentry *dsentry; 1003 struct _magic_type *type; 1004 void* data_ptr; 1005 const char* function_name; 1006 const char* name; 1007 char *min_data_ptr = NULL, *max_data_ptr = NULL; 1008 va_list va; 1009 1010 assert(num_dsentries > 0); 1011 1012 MAGIC_DSENTRY_LOCK(); 1013 assert(_magic_first_stack_dsentry && "First stack dsentry not found!"); 1014 va_start(va, num_dsentries); 1015 *prev_last_stack_dsentry = _magic_last_stack_dsentry; 1016 for (i = 0 ; i < num_dsentries ; i++) { 1017 dsentry = va_arg(va, struct _magic_dsentry *); 1018 type = va_arg(va, struct _magic_type *); 1019 data_ptr = va_arg(va, void *); 1020 function_name = va_arg(va, const char *); 1021 name = va_arg(va, const char *); 1022 if (i == num_dsentries - 1) { 1023 /* Return address. */ 1024 int *value_set = (void*) type; 1025 data_ptr = MAGIC_FRAMEADDR_TO_RETADDR_PTR(data_ptr); 1026 type = &(dsentry->type); 1027 magic_create_dsentry(dsentry, data_ptr, MAGIC_VOID_TYPE, MAGIC_VOID_TYPE->size, 1028 MAGIC_STATE_STACK | MAGIC_STATE_CONSTANT | MAGIC_STATE_ADDR_NOT_TAKEN, 1029 name, function_name); 1030 memcpy(type, &magic_default_ret_addr_type, sizeof(struct _magic_type)); 1031 type->contained_types = MAGIC_DSENTRY_TO_TYPE_ARR(dsentry); 1032 type->contained_types[0] = MAGIC_VOID_TYPE; 1033 type->value_set = value_set; 1034 value_set[0] = 1; 1035 value_set[1] = *((int *)data_ptr); 1036 1037 /* Safe to override the type non-atomically. 1038 * The new type is only more restrictive, and nobody could 1039 * have touched this stack dsentry in the meantime. 1040 */ 1041 MAGIC_DSENTRY_TO_SENTRY(dsentry)->type = type; 1042 } else { 1043 /* Local variable. */ 1044 magic_create_dsentry(dsentry, data_ptr, type, type->size, 1045 MAGIC_STATE_STACK, name, function_name); 1046 if (!min_data_ptr || min_data_ptr > (char *) data_ptr) { 1047 min_data_ptr = (char *) data_ptr; 1048 } 1049 if (!max_data_ptr || max_data_ptr < (char *) data_ptr) { 1050 max_data_ptr = (char *) data_ptr; 1051 } 1052 } 1053 } 1054 1055 #if MAGIC_FORCE_DYN_MEM_ZERO_INIT 1056 if (min_data_ptr && max_data_ptr) { 1057 memset(min_data_ptr, 0, max_data_ptr - min_data_ptr + 1); 1058 } 1059 #endif 1060 1061 _magic_last_stack_dsentry = dsentry; 1062 MAGIC_DSENTRY_UNLOCK(); 1063 1064 va_end(va); 1065 } 1066 1067 /*===========================================================================* 1068 * magic_stack_dsentries_destroy * 1069 *===========================================================================*/ 1070 PUBLIC void magic_stack_dsentries_destroy( 1071 struct _magic_dsentry **prev_last_stack_dsentry, int num_dsentries, 1072 /* struct _magic_dsentry *dsentry, */ ...) 1073 { 1074 int i; 1075 struct _magic_dsentry *dsentry; 1076 va_list va; 1077 1078 assert(num_dsentries > 0); 1079 1080 MAGIC_MEM_WRAPPER_LBEGIN(); 1081 1082 va_start(va, num_dsentries); 1083 _magic_last_stack_dsentry = *prev_last_stack_dsentry; 1084 for (i = 0 ; i < num_dsentries ; i++) { 1085 dsentry = va_arg(va, struct _magic_dsentry *); 1086 magic_destroy_dsentry(dsentry, NULL); 1087 } 1088 va_end(va); 1089 1090 MAGIC_MEM_WRAPPER_LEND(); 1091 } 1092 1093 /*===========================================================================* 1094 * magic_create_dfunction * 1095 *===========================================================================*/ 1096 PUBLIC int magic_create_dfunction(struct _magic_dfunction *dfunction, 1097 void *data_ptr, struct _magic_type *type, int flags, 1098 const char *name, const char *parent_name) 1099 { 1100 struct _magic_function *function = MAGIC_DFUNCTION_TO_FUNCTION(dfunction); 1101 1102 if(!type) { 1103 type = MAGIC_VOID_TYPE; 1104 } 1105 1106 memcpy(dfunction, &magic_default_dfunction, sizeof(struct _magic_dfunction)); 1107 1108 assert(!(type->flags & MAGIC_TYPE_DYNAMIC) && "bad type!"); 1109 1110 function->type = type; 1111 function->flags |= flags; 1112 function->address = data_ptr; 1113 if(name) { 1114 function->name = name; 1115 } 1116 if(parent_name) { 1117 dfunction->parent_name = parent_name; 1118 } 1119 function->id = MAGIC_FAA(&_magic_functions_next_id, 1); 1120 assert(_magic_functions_next_id < MAGIC_ID_MAX); 1121 1122 if(_magic_first_dfunction) { 1123 assert(_magic_last_dfunction); 1124 MAGIC_DFUNCTION_NEXT(_magic_last_dfunction) = dfunction; 1125 } 1126 else { 1127 assert(!_magic_last_dfunction); 1128 assert(_magic_dfunctions_num == 0); 1129 _magic_first_dfunction = dfunction; 1130 } 1131 MAGIC_DFUNCTION_PREV(dfunction) = _magic_last_dfunction; 1132 MAGIC_DFUNCTION_NEXT(dfunction) = NULL; 1133 _magic_last_dfunction = dfunction; 1134 _magic_dfunctions_num++; 1135 1136 assert(magic_check_dfunction(dfunction, 0) && "Bad magic dfunction created!"); 1137 magic_update_dfunction_ranges = 1; 1138 1139 return 0; 1140 } 1141 1142 /*===========================================================================* 1143 * magic_destroy_dfunction * 1144 *===========================================================================*/ 1145 PUBLIC void magic_destroy_dfunction(struct _magic_dfunction *dfunction) 1146 { 1147 dfunction->magic_number = MAGIC_DFUNCTION_MNUM_NULL; 1148 if(MAGIC_DFUNCTION_HAS_NEXT(dfunction)) { 1149 MAGIC_DFUNCTION_PREV(MAGIC_DFUNCTION_NEXT(dfunction)) = MAGIC_DFUNCTION_PREV(dfunction); 1150 } 1151 else { 1152 _magic_last_dfunction = MAGIC_DFUNCTION_PREV(dfunction); 1153 } 1154 if(MAGIC_DFUNCTION_HAS_PREV(dfunction)) { 1155 MAGIC_DFUNCTION_NEXT(MAGIC_DFUNCTION_PREV(dfunction)) = MAGIC_DFUNCTION_NEXT(dfunction); 1156 } 1157 else { 1158 _magic_first_dfunction = MAGIC_DFUNCTION_NEXT(dfunction); 1159 } 1160 MAGIC_DFUNCTION_NEXT(dfunction) = NULL; 1161 MAGIC_DFUNCTION_PREV(dfunction) = NULL; 1162 _magic_dfunctions_num--; 1163 if(_magic_dfunctions_num == 0) { 1164 assert(!_magic_first_dfunction && !_magic_last_dfunction); 1165 } 1166 else { 1167 assert(_magic_first_dfunction && _magic_last_dfunction); 1168 } 1169 } 1170 1171 /*===========================================================================* 1172 * magic_create_sodesc * 1173 *===========================================================================*/ 1174 PUBLIC int magic_create_sodesc(struct _magic_sodesc *sodesc) 1175 { 1176 if(_magic_first_sodesc) { 1177 assert(_magic_last_sodesc); 1178 MAGIC_SODESC_NEXT(_magic_last_sodesc) = sodesc; 1179 } 1180 else { 1181 assert(!_magic_last_sodesc); 1182 assert(_magic_sodescs_num == 0); 1183 _magic_first_sodesc = sodesc; 1184 } 1185 MAGIC_SODESC_PREV(sodesc) = _magic_last_sodesc; 1186 MAGIC_SODESC_NEXT(sodesc) = NULL; 1187 _magic_last_sodesc = sodesc; 1188 _magic_sodescs_num++; 1189 1190 return 0; 1191 } 1192 1193 /*===========================================================================* 1194 * magic_destroy_sodesc * 1195 *===========================================================================*/ 1196 PUBLIC int magic_destroy_sodesc(struct _magic_sodesc *sodesc) 1197 { 1198 /* 1199 * NB!: This function requires the calling thread to already 1200 * hold the DSENTRY and DFUNCTION locks. 1201 */ 1202 int ret; 1203 const char *name; 1204 struct _magic_dsentry *prev_dsentry, *dsentry, *last_dsentry; 1205 struct _magic_sentry *sentry; 1206 struct _magic_dfunction *dfunction, *last_dfunction; 1207 1208 /* 1209 * Time to destroy all the dsentries and dfunctions 1210 * linked to the descriptor. 1211 */ 1212 name = sodesc->lib.name; 1213 last_dsentry = NULL; 1214 MAGIC_DSENTRY_ALIVE_ITER(_magic_first_dsentry, prev_dsentry, 1215 dsentry, sentry, 1216 if (last_dsentry) 1217 magic_destroy_dsentry(last_dsentry, NULL); 1218 last_dsentry = dsentry->parent_name == name ? dsentry : NULL; 1219 ); 1220 if (last_dsentry) 1221 magic_destroy_dsentry(last_dsentry, NULL); 1222 last_dfunction = NULL; 1223 MAGIC_DFUNCTION_ITER(_magic_first_dfunction, dfunction, 1224 if (last_dfunction) 1225 magic_destroy_dfunction(last_dfunction); 1226 last_dfunction = dfunction->parent_name == name ? dfunction : NULL; 1227 ); 1228 if(last_dfunction) magic_destroy_dfunction(last_dfunction); 1229 1230 /* Now get rid of the descriptor. */ 1231 if (MAGIC_SODESC_HAS_NEXT(sodesc)) { 1232 MAGIC_SODESC_PREV(MAGIC_SODESC_NEXT(sodesc)) = 1233 MAGIC_SODESC_PREV(sodesc); 1234 } 1235 else { 1236 _magic_last_sodesc = MAGIC_SODESC_PREV(sodesc); 1237 } 1238 if (MAGIC_SODESC_HAS_PREV(sodesc)) { 1239 MAGIC_SODESC_NEXT(MAGIC_SODESC_PREV(sodesc)) = 1240 MAGIC_SODESC_NEXT(sodesc); 1241 } 1242 else { 1243 _magic_first_sodesc = MAGIC_SODESC_NEXT(sodesc); 1244 } 1245 MAGIC_SODESC_NEXT(sodesc) = NULL; 1246 MAGIC_SODESC_PREV(sodesc) = NULL; 1247 _magic_sodescs_num--; 1248 if (_magic_sodescs_num == 0) { 1249 assert(!_magic_first_sodesc && !_magic_last_sodesc); 1250 } 1251 else { 1252 assert(_magic_first_sodesc && _magic_last_sodesc); 1253 } 1254 1255 /* 1256 * Unmap the memory area that contained the dsentries and dfunctions 1257 * of this descriptor. 1258 */ 1259 ret = munmap(sodesc->lib.alloc_address, sodesc->lib.alloc_size); 1260 assert(ret == 0 && "Unable to unmap SODESC memory segment!"); 1261 1262 return 0; 1263 } 1264 1265 /*===========================================================================* 1266 * magic_create_dsodesc * 1267 *===========================================================================*/ 1268 PUBLIC int magic_create_dsodesc(struct _magic_dsodesc *dsodesc) 1269 { 1270 /* 1271 * NB!: This function requires the calling thread to already 1272 * hold the DSODESC lock. 1273 */ 1274 if (_magic_first_dsodesc) { 1275 assert(_magic_last_dsodesc); 1276 MAGIC_DSODESC_NEXT(_magic_last_dsodesc) = dsodesc; 1277 } 1278 else { 1279 assert(!_magic_last_dsodesc); 1280 assert(_magic_dsodescs_num == 0); 1281 _magic_first_dsodesc = dsodesc; 1282 } 1283 MAGIC_DSODESC_PREV(dsodesc) = _magic_last_dsodesc; 1284 MAGIC_DSODESC_NEXT(dsodesc) = NULL; 1285 _magic_last_dsodesc = dsodesc; 1286 _magic_dsodescs_num++; 1287 1288 return 0; 1289 } 1290 1291 /*===========================================================================* 1292 * magic_destroy_dsodesc * 1293 *===========================================================================*/ 1294 PUBLIC int magic_destroy_dsodesc(struct _magic_dsodesc *dsodesc) 1295 { 1296 /* 1297 * NB!: This function requires the calling thread to already 1298 * hold the DSENTRY, DFUNCTION and DSODESC locks. 1299 */ 1300 int ret; 1301 const char *name; 1302 struct _magic_dsentry *prev_dsentry, *dsentry, *last_dsentry; 1303 struct _magic_sentry *sentry; 1304 struct _magic_dfunction *dfunction, *last_dfunction; 1305 1306 dsodesc->ref_count--; 1307 /* Don't destroy the DSO descriptor quite yet, we still have references. */ 1308 if (dsodesc->ref_count > 0) { 1309 return dsodesc->ref_count; 1310 } 1311 1312 /* 1313 * Time to destroy all the dsentries and dfunctions 1314 * linked to the descriptor. 1315 */ 1316 name = dsodesc->lib.name; 1317 last_dsentry = NULL; 1318 MAGIC_DSENTRY_ALIVE_ITER(_magic_first_dsentry, prev_dsentry, 1319 dsentry, sentry, 1320 if (last_dsentry) 1321 magic_destroy_dsentry(last_dsentry, NULL); 1322 last_dsentry = dsentry->parent_name == name ? dsentry : NULL; 1323 ); 1324 if (last_dsentry) 1325 magic_destroy_dsentry(last_dsentry, NULL); 1326 last_dfunction = NULL; 1327 MAGIC_DFUNCTION_ITER(_magic_first_dfunction, dfunction, 1328 if (last_dfunction) 1329 magic_destroy_dfunction(last_dfunction); 1330 last_dfunction = dfunction->parent_name == name ? dfunction : NULL; 1331 ); 1332 if (last_dfunction) 1333 magic_destroy_dfunction(last_dfunction); 1334 1335 /* Now get rid of the descriptor. */ 1336 if (MAGIC_DSODESC_HAS_NEXT(dsodesc)) { 1337 MAGIC_DSODESC_PREV(MAGIC_DSODESC_NEXT(dsodesc)) = 1338 MAGIC_DSODESC_PREV(dsodesc); 1339 } 1340 else { 1341 _magic_last_dsodesc = MAGIC_DSODESC_PREV(dsodesc); 1342 } 1343 if (MAGIC_DSODESC_HAS_PREV(dsodesc)) { 1344 MAGIC_DSODESC_NEXT(MAGIC_DSODESC_PREV(dsodesc)) = 1345 MAGIC_DSODESC_NEXT(dsodesc); 1346 } 1347 else { 1348 _magic_first_dsodesc = MAGIC_DSODESC_NEXT(dsodesc); 1349 } 1350 MAGIC_DSODESC_NEXT(dsodesc) = NULL; 1351 MAGIC_DSODESC_PREV(dsodesc) = NULL; 1352 _magic_dsodescs_num--; 1353 if (_magic_dsodescs_num == 0) { 1354 assert(!_magic_first_dsodesc && !_magic_last_dsodesc); 1355 } 1356 else { 1357 assert(_magic_first_dsodesc && _magic_last_dsodesc); 1358 } 1359 1360 /* 1361 * Unmap the memory area that contained the dsentries and dfunctions 1362 * of this descriptor. 1363 */ 1364 ret = munmap(dsodesc->lib.alloc_address, dsodesc->lib.alloc_size); 1365 assert(ret == 0 && "Unable to unmap DSODESC memory segment!"); 1366 1367 return 0; /* no more references, descriptor is gone. */ 1368 } 1369 1370 /*===========================================================================* 1371 * magic_alloc * 1372 *===========================================================================*/ 1373 PUBLIC void *magic_alloc(__MA_ARGS__ void *ptr, size_t size, int flags) 1374 { 1375 int ret; 1376 void *data_ptr; 1377 struct _magic_dsentry *dsentry; 1378 1379 if(ptr == NULL) { 1380 return NULL; 1381 } 1382 data_ptr = MAGIC_PTR_TO_DATA(ptr); 1383 dsentry = MAGIC_PTR_TO_DSENTRY(ptr); 1384 /* Catch pool allocations and update the name & flags */ 1385 if (MAGIC_MEMPOOL_MGMT_IS_ACTIVE() && !(flags & MAGIC_STATE_MEMBLOCK)) { 1386 flags |= MAGIC_STATE_MEMPOOL; 1387 name = MAGIC_MEMPOOL_GET_NAME(); 1388 } 1389 ret = magic_create_dsentry(dsentry, data_ptr, type, size, flags, name, parent_name); 1390 MAGIC_MEM_PRINTF("magic_alloc: ret = magic_create_dsentry(dsentry, data_ptr, type, size, flags, NULL, NULL) <-> %d = magic_create_dsentry(0x%08x, 0x%08x, 0x%08x, %d, 0x%08x, NULL, NULL)\n", ret, (unsigned) dsentry, (unsigned) data_ptr, type, size, flags); 1391 if(ret < 0) { 1392 return MAGIC_MEM_FAILED; 1393 } 1394 1395 /* this way we skip the memory pool blocks -they are not real allocations and should not be logged */ 1396 if (!(flags & MAGIC_STATE_MEMBLOCK)) { 1397 MAGIC_MEM_DEBUG_ALLOC(ptr, (MAGIC_SIZE_TO_REAL(size))); 1398 } 1399 1400 #if DEBUG 1401 MAGIC_MEM_PRINTF("magic_alloc: magic_create_dsentry created sentry: "); 1402 MAGIC_DSENTRY_PRINT(dsentry, MAGIC_EXPAND_TYPE_STR); 1403 MAGIC_MEM_PRINTF("\n"); 1404 #endif 1405 1406 MAGIC_MEM_PRINTF("magic_alloc: return 0x%08x\n", (unsigned) data_ptr); 1407 1408 return data_ptr; 1409 } 1410 1411 /*===========================================================================* 1412 * magic_malloc_positioned * 1413 *===========================================================================*/ 1414 PUBLIC void *magic_malloc_positioned(__MA_ARGS__ size_t size, void *ptr) 1415 { 1416 void *data_ptr; 1417 int dsentry_flags = MAGIC_STATE_HEAP; 1418 1419 #if MAGIC_FORCE_DYN_MEM_ZERO_INIT 1420 assert(!_magic_vars->fake_malloc); 1421 do { 1422 return magic_calloc(__MA_VALUES__ size, 1); 1423 } while(0); 1424 #endif 1425 1426 MAGIC_MEM_WRAPPER_BEGIN(); 1427 1428 if(size > 0) { 1429 if (!ptr || !_magic_vars->fake_malloc) { 1430 /* 1431 * Check the external callback first. 1432 */ 1433 if (magic_mem_heap_alloc_cb) 1434 ptr = magic_mem_heap_alloc_cb(MAGIC_SIZE_TO_REAL(size) + magic_asr_get_padding_size(MAGIC_STATE_HEAP), name, parent_name); 1435 1436 if (!ptr) 1437 ptr = malloc(MAGIC_SIZE_TO_REAL(size) + magic_asr_get_padding_size(MAGIC_STATE_HEAP)); 1438 MAGIC_MEM_PRINTF("magic_malloc: ptr = malloc(size) <-> 0x%08x = malloc(%d)\n", (unsigned) ptr, MAGIC_SIZE_TO_REAL(size)); 1439 } 1440 data_ptr = magic_alloc(__MA_VALUES__ ptr, size, dsentry_flags); 1441 if (data_ptr == MAGIC_MEM_FAILED) { 1442 /* 1443 * XXX: This doesn't seem likely to happen. However, if it does, 1444 * we need to distinguish between regular malloc() memory 1445 * and super-objects. See llvm/shared/libst/include/heap.h for 1446 * more information. 1447 */ 1448 free(ptr); 1449 data_ptr = NULL; 1450 errno = ENOMEM; 1451 } 1452 magic_heap_end = ((char *)sbrk(0)) - 1; 1453 } 1454 else { 1455 data_ptr = NULL; 1456 } 1457 1458 MAGIC_MEM_WRAPPER_END(); 1459 1460 return data_ptr; 1461 } 1462 1463 /*===========================================================================* 1464 * magic_malloc * 1465 *===========================================================================*/ 1466 PUBLIC void *magic_malloc(__MA_ARGS__ size_t size) 1467 { 1468 return magic_malloc_positioned(__MA_VALUES__ size, NULL); 1469 } 1470 1471 /*===========================================================================* 1472 * magic_calloc * 1473 *===========================================================================*/ 1474 PUBLIC void *magic_calloc(__MA_ARGS__ size_t nmemb, size_t size) 1475 { 1476 void *ptr = NULL, *data_ptr; 1477 size_t real_size; 1478 int dsentry_flags = MAGIC_STATE_HEAP; 1479 1480 MAGIC_MEM_WRAPPER_BEGIN(); 1481 1482 if(size > 0) { 1483 real_size = MAGIC_SIZE_TO_REAL(size*nmemb); 1484 /* 1485 * Check the external callback first. 1486 */ 1487 if (magic_mem_heap_alloc_cb) 1488 ptr = magic_mem_heap_alloc_cb(real_size + magic_asr_get_padding_size(MAGIC_STATE_HEAP), name, parent_name); 1489 1490 if (!ptr) 1491 ptr = calloc(real_size + magic_asr_get_padding_size(MAGIC_STATE_HEAP), 1); 1492 MAGIC_MEM_PRINTF("magic_calloc: ptr = calloc(nmemb, size) <-> 0x%08x = calloc(%d, %d)\n", (unsigned) ptr, nmemb, real_size); 1493 data_ptr = magic_alloc(__MA_VALUES__ ptr, size*nmemb, dsentry_flags); 1494 if(data_ptr == MAGIC_MEM_FAILED) { 1495 /* 1496 * XXX: This doesn't seem likely to happen. However, if it does, 1497 * we need to distinguish between regular malloc() memory 1498 * and super-objects. See llvm/shared/libst/include/heap.h for 1499 * more information. 1500 */ 1501 free(ptr); 1502 data_ptr = NULL; 1503 errno = ENOMEM; 1504 } 1505 magic_heap_end = ((char*)sbrk(0))-1; 1506 } 1507 else { 1508 data_ptr = NULL; 1509 } 1510 1511 MAGIC_MEM_WRAPPER_END(); 1512 1513 return data_ptr; 1514 } 1515 1516 /*===========================================================================* 1517 * magic_free * 1518 *===========================================================================*/ 1519 PUBLIC void magic_free(__MD_ARGS__ void *data_ptr) 1520 { 1521 void *ptr; 1522 int ret; 1523 1524 MAGIC_MEM_WRAPPER_BEGIN(); 1525 1526 if(data_ptr) { 1527 ptr = MAGIC_PTR_FROM_DATA(data_ptr); 1528 1529 /* Check for legitimate non-indexed chunks of memory and skip. */ 1530 if((!magic_libcommon_active || !MAGIC_USE_DYN_MEM_WRAPPERS) 1531 && !MAGIC_DSENTRY_MNUM_OK(MAGIC_PTR_TO_DSENTRY(ptr))) { 1532 MAGIC_MEM_WRAPPER_END(); 1533 free(data_ptr); 1534 return; 1535 } 1536 1537 MAGIC_MEM_PRINTF("magic_free: magic_free(0x%08x) / free(0x%08x)\n", (unsigned) data_ptr, (unsigned) ptr); 1538 assert(magic_check_dsentry(MAGIC_PTR_TO_DSENTRY(ptr), MAGIC_STATE_HEAP) && "XXX Bad magic dsentry: corruption or memory not allocated from a magic wrapper?"); 1539 1540 if(magic_allow_dead_dsentries) { 1541 ret = magic_update_dsentry_state(MAGIC_PTR_TO_DSENTRY(ptr), MAGIC_DSENTRY_MSTATE_DEAD); 1542 assert(ret == 0 && "Bad free!"); 1543 } 1544 else { 1545 MAGIC_DSENTRY_LOCK(); 1546 magic_destroy_dsentry(MAGIC_PTR_TO_DSENTRY(ptr), NULL); 1547 ret = magic_free_dsentry(MAGIC_PTR_TO_DSENTRY(ptr)); 1548 assert(ret == 0 && "Bad free!"); 1549 MAGIC_DSENTRY_UNLOCK(); 1550 } 1551 } 1552 1553 MAGIC_MEM_WRAPPER_END(); 1554 } 1555 1556 /*===========================================================================* 1557 * magic_realloc * 1558 *===========================================================================*/ 1559 PUBLIC void *magic_realloc(__MA_ARGS__ void *data_ptr, size_t size) 1560 { 1561 void *ptr, *new_ptr, *new_data_ptr; 1562 size_t old_size; 1563 1564 if(!data_ptr) { 1565 return magic_malloc(__MA_VALUES__ size); 1566 } 1567 if(size == 0) { 1568 magic_free(__MD_VALUES_DEFAULT__ data_ptr); 1569 return NULL; 1570 } 1571 1572 ptr = MAGIC_PTR_FROM_DATA(data_ptr); 1573 new_data_ptr = magic_malloc(__MA_VALUES__ size); 1574 if(!new_data_ptr) { 1575 return NULL; 1576 } 1577 new_ptr = MAGIC_PTR_FROM_DATA(new_data_ptr); 1578 assert(magic_check_dsentry(MAGIC_PTR_TO_DSENTRY(ptr), MAGIC_STATE_HEAP) && "XXX Bad magic dsentry: corruption or memory not allocated from a magic wrapper?"); 1579 MAGIC_MEM_PRINTF("magic_realloc: ptr = realloc(ptr, size) <-> 0x%08x = realloc(0x%08x, %d)\n", (unsigned) new_ptr, (unsigned) ptr, MAGIC_SIZE_TO_REAL(size)); 1580 1581 old_size = MAGIC_DSENTRY_TO_SENTRY(MAGIC_PTR_TO_DSENTRY(ptr))->type->size; 1582 memcpy(new_data_ptr, data_ptr, old_size < size ? old_size : size); 1583 magic_free(__MD_VALUES_DEFAULT__ data_ptr); 1584 1585 return new_data_ptr; 1586 } 1587 1588 /*===========================================================================* 1589 * magic_posix_memalign * 1590 *===========================================================================*/ 1591 PUBLIC int magic_posix_memalign(__MA_ARGS__ void **memptr, size_t alignment, size_t size) 1592 { 1593 int ret = 0; 1594 void *ptr = NULL, *data_ptr; 1595 int dsentry_flags = MAGIC_STATE_HEAP; 1596 1597 MAGIC_MEM_WRAPPER_BEGIN(); 1598 1599 if(size > 0) { 1600 /* 1601 * Check the external callback first. 1602 */ 1603 if (magic_mem_heap_alloc_cb) 1604 ptr = magic_mem_heap_alloc_cb(MAGIC_SIZE_TO_REAL(size), name, parent_name); 1605 1606 if (!ptr) 1607 ret = posix_memalign(&ptr, alignment, MAGIC_SIZE_TO_REAL(size)); 1608 MAGIC_MEM_PRINTF("magic_posix_memalign: ret = posix_memalign(ptr, alignment, size) <-> %d = posix_memalign(%p, %d, %d)\n", ret, ptr, alignment, MAGIC_SIZE_TO_REAL(size)); 1609 if(ret == 0) { 1610 data_ptr = magic_alloc(__MA_VALUES__ ptr, size, dsentry_flags); 1611 if(data_ptr == MAGIC_MEM_FAILED) { 1612 /* 1613 * XXX: This doesn't seem likely to happen. However, if it does, 1614 * we need to distinguish between regular malloc() memory 1615 * and super-objects. See llvm/shared/libst/include/heap.h for 1616 * more information. 1617 */ 1618 free(ptr); 1619 ret = ENOMEM; 1620 } 1621 else { 1622 *memptr = data_ptr; 1623 #if MAGIC_FORCE_DYN_MEM_ZERO_INIT 1624 memset(data_ptr, 0, size); 1625 #endif 1626 } 1627 magic_heap_end = ((char*)sbrk(0))-1; 1628 } 1629 } 1630 else { 1631 ret = EINVAL; 1632 } 1633 1634 MAGIC_MEM_WRAPPER_END(); 1635 1636 return ret; 1637 } 1638 1639 #ifndef __MINIX 1640 /*===========================================================================* 1641 * magic_valloc * 1642 *===========================================================================*/ 1643 PUBLIC void *magic_valloc(__MA_ARGS__ size_t size) 1644 { 1645 return magic_memalign(__MA_VALUES__ MAGIC_PAGE_SIZE, size); 1646 } 1647 1648 /*===========================================================================* 1649 * magic_memalign * 1650 *===========================================================================*/ 1651 PUBLIC void *magic_memalign(__MA_ARGS__ size_t boundary, size_t size) 1652 { 1653 void *ptr; 1654 int ret = magic_posix_memalign(__MA_VALUES__ &ptr, boundary, size); 1655 if(ret != 0) { 1656 return NULL; 1657 } 1658 return ptr; 1659 } 1660 1661 #endif 1662 1663 /*===========================================================================* 1664 * magic_mmap_positioned * 1665 *===========================================================================*/ 1666 PUBLIC void *magic_mmap_positioned(__MA_ARGS__ void *start, size_t length, int prot, int flags, 1667 int fd, off_t offset, struct _magic_dsentry *cached_dsentry) 1668 { 1669 void *ptr, *data_ptr, *aligned_start, *aligned_ptr; 1670 void *new_ptr, *new_start; 1671 int dsentry_flags = MAGIC_STATE_MAP; 1672 size_t alloc_length; 1673 size_t page_size = MAGIC_PAGE_SIZE; 1674 int padding_type, padding_size; 1675 static THREAD_LOCAL int magic_is_first_mmap = 1; 1676 1677 MAGIC_MEM_WRAPPER_BEGIN(); 1678 1679 if (flags & MAP_FIXED) { 1680 /* Allow safe overmapping. */ 1681 struct _magic_sentry *sentry = magic_sentry_lookup_by_range(start, NULL); 1682 if (sentry && sentry == magic_sentry_lookup_by_range((char*)start+length-1, NULL)) 1683 return mmap(start, length, prot, flags, fd, offset); 1684 } 1685 assert(!(flags & MAP_FIXED) && "MAP_FIXED may override existing mapping, currently not implemented!"); 1686 if (length > 0) { 1687 if (magic_is_first_mmap) { 1688 magic_is_first_mmap = 0; 1689 padding_type = MAGIC_STATE_MAP | MAGIC_ASR_FLAG_INIT; 1690 } else { 1691 padding_type = MAGIC_STATE_MAP; 1692 } 1693 padding_size = start ? 0 : magic_asr_get_padding_size(padding_type); 1694 1695 assert(MAGIC_SIZE_TO_REAL(length) <= page_size + length); 1696 aligned_start = start ? ((char *)start) - page_size : NULL; 1697 alloc_length = length + (length % page_size == 0 ? 0 : page_size - (length % page_size)); 1698 #if 0 1699 if (_magic_vars->do_skip_mmap) { 1700 ptr = cached_dsentry ? ((char *)cached_dsentry) - (padding_size + page_size - MAGIC_SIZE_TO_REAL(0)) : NULL; 1701 } else 1702 #endif 1703 if (!(flags & MAP_ANONYMOUS) && !(flags & MAP_SHARED) && ((prot & magic_mmap_dsentry_header_prot) == magic_mmap_dsentry_header_prot)) { 1704 ptr = mmap(aligned_start, page_size + alloc_length + padding_size, prot, flags, fd, offset); 1705 } 1706 else { 1707 /* Preallocate memory for metadata + data. */ 1708 ptr = mmap(aligned_start, page_size + alloc_length + padding_size, magic_mmap_dsentry_header_prot, MAP_ANONYMOUS | MAP_PRIVATE | (flags & MAP_FIXED), -1, 0); 1709 1710 /* Remap the data part the way the caller wants us to. */ 1711 if (ptr != MAP_FAILED) { 1712 new_start = ((char *)ptr) + page_size; 1713 new_ptr = mmap(new_start, length, prot, flags | MAP_FIXED, fd, offset); 1714 if (new_ptr == MAP_FAILED) { 1715 munmap(ptr, page_size + alloc_length + padding_size); 1716 ptr = MAP_FAILED; 1717 } 1718 } 1719 } 1720 aligned_ptr = ptr; 1721 MAGIC_MEM_PRINTF("magic_mmap: ptr = mmap(start, length, prot, flags, fd, offset) <-> 0x%08x = mmap(0x%08x, %d, 0x%08x, 0x%08x, %d, %d)\n", (unsigned) aligned_ptr, aligned_start, page_size + length, prot, flags, fd, offset); 1722 if (ptr != MAP_FAILED) { 1723 ptr = ((char *)ptr) + page_size - MAGIC_SIZE_TO_REAL(0); 1724 } 1725 else { 1726 ptr = NULL; 1727 } 1728 if (flags & MAP_SHARED) 1729 dsentry_flags |= MAGIC_STATE_SHM; 1730 data_ptr = magic_alloc(__MA_VALUES__ ptr, alloc_length, dsentry_flags); 1731 if (data_ptr == MAGIC_MEM_FAILED) { 1732 munmap(aligned_ptr, page_size + alloc_length + padding_size); 1733 data_ptr = NULL; 1734 } 1735 if (!data_ptr) { 1736 errno = ENOMEM; 1737 data_ptr = MAP_FAILED; 1738 } else { 1739 assert(data_ptr == (char *)aligned_ptr + page_size); 1740 MAGIC_PTR_TO_DSENTRY(MAGIC_PTR_FROM_DATA(data_ptr))->alloc_mmap_flags = flags; 1741 MAGIC_PTR_TO_DSENTRY(MAGIC_PTR_FROM_DATA(data_ptr))->alloc_mmap_prot = prot; 1742 MAGIC_PTR_TO_DSENTRY(MAGIC_PTR_FROM_DATA(data_ptr))->ext = (void *) padding_size; 1743 } 1744 } 1745 else { 1746 data_ptr = MAP_FAILED; 1747 errno = EINVAL; 1748 } 1749 1750 MAGIC_MEM_WRAPPER_END(); 1751 1752 return data_ptr; 1753 } 1754 1755 /*===========================================================================* 1756 * magic_mmap * 1757 *===========================================================================*/ 1758 PUBLIC void *magic_mmap(__MA_ARGS__ void *start, size_t length, int prot, int flags, 1759 int fd, off_t offset) 1760 { 1761 return magic_mmap_positioned(__MA_VALUES__ start, length, prot, flags, fd, offset, NULL); 1762 } 1763 1764 /*===========================================================================* 1765 * magic_munmap * 1766 *===========================================================================*/ 1767 PUBLIC int magic_munmap(__MD_ARGS__ void *data_ptr, size_t length) 1768 { 1769 int ret; 1770 void *ptr, *aligned_ptr; 1771 struct _magic_sentry *sentry; 1772 size_t alloc_length, old_size; 1773 size_t page_size = MAGIC_PAGE_SIZE; 1774 1775 MAGIC_MEM_WRAPPER_BEGIN(); 1776 1777 if(data_ptr) { 1778 ptr = MAGIC_PTR_FROM_DATA(data_ptr); 1779 1780 /* Check for legitimate non-indexed chunks of memory and skip. */ 1781 if((!magic_libcommon_active || !MAGIC_USE_DYN_MEM_WRAPPERS) 1782 && !MAGIC_DSENTRY_MNUM_OK(MAGIC_PTR_TO_DSENTRY(ptr))) { 1783 MAGIC_MEM_WRAPPER_END(); 1784 return munmap(data_ptr, length); 1785 } 1786 1787 sentry = MAGIC_DSENTRY_TO_SENTRY(MAGIC_PTR_TO_DSENTRY(ptr)); 1788 aligned_ptr = ((char*)data_ptr) - page_size; 1789 MAGIC_MEM_PRINTF("magic_munmap: magic_munmap(0x%08x, %d) / unmap(0x%08x, %d)\n", (unsigned) data_ptr, length, (unsigned) aligned_ptr, page_size+length); 1790 assert(magic_check_dsentry(MAGIC_PTR_TO_DSENTRY(ptr), MAGIC_STATE_MAP) && "XXX Bad magic dsentry: corruption or memory not allocated from a magic wrapper?"); 1791 old_size = MAGIC_DSENTRY_TO_SENTRY(MAGIC_PTR_TO_DSENTRY(ptr))->type->size; 1792 alloc_length = length + (length % page_size == 0 ? 0 : page_size-(length % page_size)); 1793 1794 if(alloc_length != old_size) { 1795 assert(alloc_length >= old_size && "Partial unmapping not supported!"); 1796 ret = -1; 1797 errno = EINVAL; 1798 } 1799 else { 1800 if(magic_allow_dead_dsentries) { 1801 ret = magic_update_dsentry_state(MAGIC_PTR_TO_DSENTRY(ptr), MAGIC_DSENTRY_MSTATE_DEAD); 1802 assert(ret == 0 && "Bad munmap!"); 1803 } 1804 else { 1805 MAGIC_DSENTRY_LOCK(); 1806 magic_destroy_dsentry(MAGIC_PTR_TO_DSENTRY(ptr), NULL); 1807 ret = magic_free_dsentry(MAGIC_PTR_TO_DSENTRY(ptr)); 1808 assert(ret == 0 && "Bad munmap!"); 1809 MAGIC_DSENTRY_UNLOCK(); 1810 } 1811 } 1812 } 1813 else { 1814 ret = -1; 1815 errno = EINVAL; 1816 } 1817 1818 MAGIC_MEM_WRAPPER_END(); 1819 1820 return ret; 1821 } 1822 1823 /*===========================================================================* 1824 * magic_brk * 1825 *===========================================================================*/ 1826 PUBLIC int magic_brk(__MA_ARGS__ void *addr) 1827 { 1828 void *ptr; 1829 void *break_addr; 1830 int ret; 1831 1832 MAGIC_MEM_PRINTF("magic_brk: Warning: somebody calling magic_brk()!"); 1833 MAGIC_MEM_WRAPPER_LBLOCK( break_addr = sbrk(0); ); 1834 if(addr >= break_addr) { 1835 ptr = magic_sbrk(__MA_VALUES__ (char*)addr - (char*)break_addr); 1836 ret = (ptr == (void*) -1 ? -1 : 0); 1837 if(ret == -1) { 1838 errno = ENOMEM; 1839 } 1840 } 1841 else { 1842 magic_free(__MD_VALUES_DEFAULT__ addr); 1843 ret = 0; 1844 } 1845 1846 return ret; 1847 } 1848 1849 /*===========================================================================* 1850 * magic_sbrk * 1851 *===========================================================================*/ 1852 PUBLIC void *magic_sbrk(__MA_ARGS__ intptr_t increment) 1853 { 1854 void *ptr; 1855 1856 if(increment == 0) { 1857 MAGIC_MEM_WRAPPER_LBLOCK( ptr = sbrk(0); ); 1858 } 1859 else { 1860 MAGIC_MEM_PRINTF("magic_sbrk: Warning: somebody calling magic_sbrk(), resorting to magic_malloc()!"); 1861 ptr = magic_malloc(__MA_VALUES__ increment); 1862 } 1863 1864 return ptr; 1865 } 1866 1867 #ifndef __MINIX 1868 /*===========================================================================* 1869 * magic_shmat * 1870 *===========================================================================*/ 1871 PUBLIC void *magic_shmat(__MA_ARGS__ int shmid, const void *shmaddr, int shmflg) 1872 { 1873 void *ptr, *data_ptr, *aligned_shmaddr, *aligned_ptr; 1874 void *new_ptr, *new_shmaddr; 1875 size_t size; 1876 struct shmid_ds buf; 1877 int ret, flags; 1878 size_t page_size = MAGIC_PAGE_SIZE; 1879 1880 MAGIC_MEM_WRAPPER_BEGIN(); 1881 1882 assert(!(shmflg & SHM_REMAP) && "Linux-specific SHM_REMAP not supported!"); 1883 ret = shmctl(shmid, IPC_STAT, &buf); 1884 if (ret == -1) { 1885 MAGIC_MEM_WRAPPER_END(); 1886 return NULL; 1887 } 1888 size = buf.shm_segsz; 1889 if (size > 0) { 1890 assert(size % page_size == 0); 1891 assert(MAGIC_SIZE_TO_REAL(size) <= size + page_size); 1892 if (shmaddr && (shmflg & SHM_RND)) { 1893 unsigned long shmlba = SHMLBA; 1894 shmflg &= ~SHM_RND; 1895 shmaddr = (void *) ((((unsigned long)shmaddr) / shmlba) * shmlba); 1896 } 1897 1898 /* Preallocate memory for metadata + data. */ 1899 aligned_shmaddr = shmaddr ? ((char *)shmaddr) - page_size : NULL; 1900 flags = MAP_ANONYMOUS | MAP_PRIVATE | (aligned_shmaddr ? MAP_FIXED : 0); 1901 ptr = mmap(aligned_shmaddr, page_size + size, magic_mmap_dsentry_header_prot, flags, -1, 0); 1902 1903 /* Remap the data part the way the caller wants us to. */ 1904 if (ptr != MAP_FAILED) { 1905 new_shmaddr = ((char *)ptr) + page_size; 1906 munmap(new_shmaddr, size); 1907 new_ptr = shmat(shmid, new_shmaddr, shmflg); 1908 if(new_ptr == (void *) -1) { 1909 munmap(ptr, page_size); 1910 ptr = MAP_FAILED; 1911 } 1912 } 1913 aligned_ptr = ptr; 1914 MAGIC_MEM_PRINTF("magic_shmat: ptr = shmat(shmid, shmaddr, shmflg) <-> 0x%08x = shmat(%d, 0x%08x, 0x%08x)\n", (unsigned) aligned_ptr, shmid, aligned_shmaddr, shmflg); 1915 if (ptr != MAP_FAILED) { 1916 ptr = ((char *)ptr) + page_size - MAGIC_SIZE_TO_REAL(0); 1917 } 1918 else { 1919 ptr = NULL; 1920 } 1921 data_ptr = magic_alloc(__MA_VALUES__ ptr, size, MAGIC_STATE_SHM | MAGIC_STATE_DETACHED); 1922 if (data_ptr == MAGIC_MEM_FAILED) { 1923 munmap(aligned_ptr, page_size); 1924 munmap(new_ptr, size); 1925 data_ptr = (void *) -1; 1926 errno = ENOMEM; 1927 } 1928 else { 1929 MAGIC_PTR_TO_DSENTRY(MAGIC_PTR_FROM_DATA(data_ptr))->alloc_shmat_flags = shmflg; 1930 MAGIC_PTR_TO_DSENTRY(MAGIC_PTR_FROM_DATA(data_ptr))->alloc_shmat_shmid = shmid; 1931 } 1932 } 1933 else { 1934 data_ptr = (void *) -1; 1935 errno = EINVAL; 1936 } 1937 1938 MAGIC_MEM_WRAPPER_END(); 1939 1940 return data_ptr; 1941 } 1942 1943 /*===========================================================================* 1944 * magic_shmdt * 1945 *===========================================================================*/ 1946 PUBLIC int magic_shmdt(__MD_ARGS__ const void *data_ptr) 1947 { 1948 int ret; 1949 void *ptr, *aligned_ptr; 1950 size_t page_size = MAGIC_PAGE_SIZE; 1951 1952 MAGIC_MEM_WRAPPER_LBEGIN(); 1953 1954 if (data_ptr) { 1955 ptr = MAGIC_PTR_FROM_DATA(data_ptr); 1956 1957 /* Check for legitimate non-indexed chunks of memory and skip. */ 1958 if ((!magic_libcommon_active || !MAGIC_USE_DYN_MEM_WRAPPERS) 1959 && !MAGIC_DSENTRY_MNUM_OK(MAGIC_PTR_TO_DSENTRY(ptr))) { 1960 MAGIC_MEM_WRAPPER_LEND(); 1961 return shmdt(data_ptr); 1962 } 1963 1964 aligned_ptr = ((char*)data_ptr) - page_size; 1965 MAGIC_MEM_PRINTF("magic_shmdt: magic_shmdt(0x%08x) / shmdt(0x%08x)\n", (unsigned) data_ptr, (unsigned) aligned_ptr); 1966 assert(magic_check_dsentry(MAGIC_PTR_TO_DSENTRY(ptr), MAGIC_STATE_SHM) && "XXX Bad magic dsentry: corruption or memory not allocated from a magic wrapper?"); 1967 ret = shmdt(data_ptr); 1968 if (ret == 0) { 1969 magic_destroy_dsentry(MAGIC_PTR_TO_DSENTRY(ptr), NULL); 1970 munmap(aligned_ptr, page_size); 1971 } 1972 } 1973 else { 1974 ret = -1; 1975 errno = EINVAL; 1976 } 1977 1978 MAGIC_MEM_WRAPPER_LEND(); 1979 1980 return ret; 1981 } 1982 1983 /*===========================================================================* 1984 * magic_mmap64 * 1985 *===========================================================================*/ 1986 PUBLIC void *magic_mmap64(__MA_ARGS__ void *start, size_t length, int prot, int flags, 1987 int fd, off_t pgoffset) 1988 { 1989 void *ptr, *data_ptr, *aligned_start, *aligned_ptr; 1990 void *new_ptr, *new_start; 1991 int dsentry_flags = MAGIC_STATE_MAP; 1992 size_t alloc_length; 1993 size_t page_size = MAGIC_PAGE_SIZE; 1994 1995 MAGIC_MEM_WRAPPER_BEGIN(); 1996 1997 if (flags & MAP_FIXED) { 1998 /* Allow safe overmapping. */ 1999 struct _magic_sentry *sentry = magic_sentry_lookup_by_range(start, NULL); 2000 if (sentry && sentry == magic_sentry_lookup_by_range((char*)start+length-1, NULL)) 2001 return mmap64(start, length, prot, flags, fd, pgoffset); 2002 } 2003 assert(!(flags & MAP_FIXED) && "MAP_FIXED may override existing mapping, currently not implemented!"); 2004 if(length > 0) { 2005 assert(MAGIC_SIZE_TO_REAL(length) <= page_size+length); 2006 aligned_start = start ? ((char*)start) - page_size : NULL; 2007 alloc_length = length + (length % page_size == 0 ? 0 : page_size-(length % page_size)); 2008 if((flags & MAP_ANONYMOUS) && !(flags & MAP_SHARED) && ((prot & magic_mmap_dsentry_header_prot) == magic_mmap_dsentry_header_prot)) { 2009 ptr = mmap64(aligned_start, page_size+length, prot, flags, fd, pgoffset); 2010 } 2011 else { 2012 /* Preallocate memory for metadata + data. */ 2013 ptr = mmap64(aligned_start, page_size+alloc_length, magic_mmap_dsentry_header_prot, MAP_ANONYMOUS|MAP_PRIVATE|(flags & MAP_FIXED), -1, 0); 2014 2015 /* Remap the data part the way the caller wants us to. */ 2016 if(ptr != MAP_FAILED) { 2017 new_start = ((char*)ptr) + page_size; 2018 new_ptr = mmap64(new_start, length, prot, flags|MAP_FIXED, fd, pgoffset); 2019 if(new_ptr == MAP_FAILED) { 2020 munmap(ptr, page_size+alloc_length); 2021 ptr = MAP_FAILED; 2022 } 2023 } 2024 } 2025 aligned_ptr = ptr; 2026 MAGIC_MEM_PRINTF("magic_mmap64: ptr = mmap64(start, length, prot, flags, fd, pgoffset) <-> 0x%08x = mmap64(0x%08x, %d, 0x%08x, 0x%08x, %d, %d)\n", (unsigned) aligned_ptr, aligned_start, page_size+length, prot, flags, fd, pgoffset); 2027 if(ptr != MAP_FAILED) { 2028 ptr = ((char*)ptr) + page_size - MAGIC_SIZE_TO_REAL(0); 2029 } 2030 else { 2031 ptr = NULL; 2032 } 2033 if (flags & MAP_SHARED) 2034 dsentry_flags |= MAGIC_STATE_SHM; 2035 data_ptr = magic_alloc(__MA_VALUES__ ptr, alloc_length, dsentry_flags); 2036 if(data_ptr == MAGIC_MEM_FAILED) { 2037 munmap(aligned_ptr, page_size+length); 2038 data_ptr = NULL; 2039 errno = ENOMEM; 2040 } 2041 if(!data_ptr) { 2042 errno = ENOMEM; 2043 data_ptr = MAP_FAILED; 2044 } else { 2045 MAGIC_PTR_TO_DSENTRY(MAGIC_PTR_FROM_DATA(data_ptr))->alloc_mmap_flags = flags; 2046 MAGIC_PTR_TO_DSENTRY(MAGIC_PTR_FROM_DATA(data_ptr))->alloc_mmap_prot = prot; 2047 } 2048 } 2049 else { 2050 data_ptr = MAP_FAILED; 2051 errno = EINVAL; 2052 } 2053 2054 MAGIC_MEM_WRAPPER_END(); 2055 2056 return data_ptr; 2057 } 2058 2059 #else 2060 /*===========================================================================* 2061 * magic_vm_map_cacheblock * 2062 *===========================================================================*/ 2063 PUBLIC void *magic_vm_map_cacheblock(__MA_ARGS__ dev_t dev, off_t dev_offset, 2064 ino_t ino, off_t ino_offset, u32_t *flags, int length) 2065 { 2066 void *ptr, *data_ptr, *aligned_ptr; 2067 int dsentry_flags = MAGIC_STATE_MAP; 2068 size_t alloc_length; 2069 size_t page_size = MAGIC_PAGE_SIZE; 2070 2071 MAGIC_MEM_WRAPPER_BEGIN(); 2072 2073 if(length > 0) { 2074 assert(MAGIC_SIZE_TO_REAL(length) <= page_size+length); 2075 alloc_length = length + (length % page_size == 0 ? 0 : page_size-(length % page_size)); 2076 data_ptr = vm_map_cacheblock(dev, dev_offset, ino, ino_offset, flags, length); 2077 if (data_ptr != MAP_FAILED) { 2078 ptr = mmap((char *)data_ptr-page_size, page_size, magic_mmap_dsentry_header_prot, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); 2079 MAGIC_MEM_PRINTF("vm_map_cacheblock: ptr = mmap(start, length, prot, flags, fd, offset) <-> 0x%08x = mmap(0x%08x, %d, 0x%08x, 0x%08x, %d, %d)\n", (unsigned) ptr, (char *)data_ptr-page_size, page_size, magic_mmap_dsentry_header_prot, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); 2080 assert(ptr == (char *)data_ptr-page_size); /* Ensured by VM. */ 2081 aligned_ptr = ptr; 2082 ptr = ((char*)ptr) + page_size - MAGIC_SIZE_TO_REAL(0); 2083 } 2084 else { 2085 aligned_ptr = NULL; 2086 ptr = NULL; 2087 } 2088 data_ptr = magic_alloc(__MA_VALUES__ ptr, alloc_length, dsentry_flags); 2089 if(data_ptr == MAGIC_MEM_FAILED) { 2090 munmap(aligned_ptr, page_size+length); 2091 data_ptr = NULL; 2092 } 2093 if(!data_ptr) { 2094 data_ptr = MAP_FAILED; 2095 errno = ENOMEM; 2096 } else { 2097 MAGIC_PTR_TO_DSENTRY(MAGIC_PTR_FROM_DATA(data_ptr))->alloc_mmap_flags = MAP_ANONYMOUS | MAP_PRIVATE; 2098 MAGIC_PTR_TO_DSENTRY(MAGIC_PTR_FROM_DATA(data_ptr))->alloc_mmap_prot = magic_mmap_dsentry_header_prot; 2099 } 2100 } 2101 else { 2102 data_ptr = MAP_FAILED; 2103 errno = EINVAL; 2104 } 2105 2106 MAGIC_MEM_WRAPPER_END(); 2107 2108 return data_ptr; 2109 } 2110 2111 /*===========================================================================* 2112 * magic_nested_mmap * 2113 *===========================================================================*/ 2114 void * 2115 magic_nested_mmap(void *start, size_t length, int prot, int flags, 2116 int fd, off_t offset) 2117 { 2118 void *ptr; 2119 int i; 2120 2121 ptr = mmap(start, length, prot, flags, fd, offset); 2122 2123 if (ptr != MAP_FAILED) { 2124 MAGIC_MEM_PRINTF("MAGIC: nested mmap (%p, %zu)\n", ptr, 2125 length); 2126 2127 /* 2128 * Find a free entry. We do not expect the malloc code to have 2129 * more than two areas mapped at any time. 2130 */ 2131 for (i = 0; i < MAGIC_UNMAP_MEM_ENTRIES; i++) 2132 if (_magic_unmap_mem[i].length == 0) 2133 break; 2134 assert(i < MAGIC_UNMAP_MEM_ENTRIES); 2135 2136 /* Store the mapping in this entry. */ 2137 _magic_unmap_mem[i].start = ptr; 2138 _magic_unmap_mem[i].length = length; 2139 } 2140 2141 return ptr; 2142 } 2143 2144 /*===========================================================================* 2145 * magic_nested_munmap * 2146 *===========================================================================*/ 2147 int 2148 magic_nested_munmap(void *start, size_t length) 2149 { 2150 int i, r; 2151 2152 r = munmap(start, length); 2153 2154 if (r == 0) { 2155 MAGIC_MEM_PRINTF("MAGIC: nested munmap (%p, %zu)\n", start, 2156 length); 2157 2158 /* Find the corresponding entry. This must always succeed. */ 2159 for (i = 0; i < MAGIC_UNMAP_MEM_ENTRIES; i++) 2160 if (_magic_unmap_mem[i].start == start && 2161 _magic_unmap_mem[i].length == length) 2162 break; 2163 assert(i < MAGIC_UNMAP_MEM_ENTRIES); 2164 2165 /* Clear the entry. */ 2166 _magic_unmap_mem[i].start = NULL; 2167 _magic_unmap_mem[i].length = 0; 2168 } 2169 2170 return r; 2171 } 2172 #endif 2173 2174