📄 flower_malloc.c
字号:
size_t v = (size_t)addr_array[i]; hash_value ^= (v << (i+1)); } hash_value %= HASH_TABLE_SIZE; return (uint32_t)hash_value;}/*************************************************************************** * get_backtrace - copy the current stack backtrace onto ret_addr array * * This function uses gcc built-in function __builtin_return_address to fetch * the return addresses from the stack. Since this function only accepts * constant integers as arguments, we must use ugly preprocessor tricks to * allow for configurable backtrace depths. */static void get_backtrace(void ** ret_addr){ ret_addr[0] = __builtin_return_address(1); #if BACKTRACE_DEPTH > 1 ret_addr[1] = __builtin_return_address(2); #if BACKTRACE_DEPTH > 2 ret_addr[2] = __builtin_return_address(3); #if BACKTRACE_DEPTH > 3 ret_addr[3] = __builtin_return_address(4); #if BACKTRACE_DEPTH > 4 ret_addr[4] = __builtin_return_address(5); #if BACKTRACE_DEPTH > 5 ret_addr[5] = __builtin_return_address(6); #if BACKTRACE_DEPTH > 6 ret_addr[6] = __builtin_return_address(7); #if BACKTRACE_DEPTH > 7 ret_addr[7] = __builtin_return_address(8); #if BACKTRACE_DEPTH > 8 ret_addr[8] = __builtin_return_address(9); #if BACKTRACE_DEPTH > 9 ret_addr[9] = __builtin_return_address(10); #if BACKTRACE_DEPTH > 10#error "maximum supported BACKTRACE_DEPTH is 10"#endif /* 1 */#endif /* 2 */#endif /* 3 */#endif /* 4 */#endif /* 5 */#endif /* 6 */#endif /* 7 */#endif /* 8 */#endif /* 9 */#endif /* 10 */}static voidinit_flower_malloc(){ char procbuf[32]; char procname[20]; char prog_name[32]; int fd; static int initialized = 0; if (initialized) return; /* * Get current executable's name using proc(4) interface */ pid = (int)getpid (); (void)sprintf (procbuf, "/proc/%ld/status", (long)pid); if ((fd = open (procbuf, O_RDONLY)) != -1) { if (read (fd, procname, sizeof (procname)) == sizeof (procname)) { strtok (procname, " "); sprintf (prog_name, "%s.%d", procname, pid); } else sprintf (prog_name, "%s.%d", "unknown", pid); } else sprintf (prog_name, "%s.%d", "unknown", pid); sprintf (path, "%s%s", "./flower_report.", prog_name); if (!output) { output = fopen (path, "a"); if (!output) { fprintf(stderr, "unable to write to file %s\n", path); /* invoke original exit(), not the one we implement here */ (*((void (*) (int))dlsym (RTLD_NEXT, "exit"))) (-1); } } fprintf(output, "flower_malloc report for program %s\n\n", prog_name); fflush(output); signal(SIGUSR1, sigusr1_handler); signal(SIGUSR2, sigusr2_handler); initialized = 1; return;} /*************************************************************************** * track_alloc - track a new allocation * * This function updates the allocation tracker for this new allocation, and * marks the new memory block with the tracker index, and the size of the * requested memory block. Those two values are stored in the allocated memory * block, this is why the function requires ptr to point to a fresh memory * block of size req_size + 8 bytes. * * The function returns a pointer to the memory immediately following the marks * which should be returned to the user. * * +---------+---------+---------+---------+---------+---- * | trk_idx | size | (memory block of size req_size) ... * +---------+---------+---------+---------+---------+---- * ^ ^ * | | * ptr returned ptr */static void *track_alloc (uint8_t *ptr, size_t req_size){ uint32_t trk_idx; void * ret_addr[BACKTRACE_DEPTH]; if (no_tracking) return ptr; get_backtrace(ret_addr); trk_idx = hash(ret_addr,BACKTRACE_DEPTH); tracker_table[trk_idx].count++; tracker_table[trk_idx].total_size += req_size; if (tracker_table[trk_idx].total_size > tracker_table[trk_idx].watermark) tracker_table[trk_idx].watermark = tracker_table[trk_idx].total_size; if (tracker_table[trk_idx].count > tracker_table[trk_idx].max_count) tracker_table[trk_idx].max_count = tracker_table[trk_idx].count; if (!within_limits(trk_idx)) { fprintf(output,"\nTracker %x exceeding limits - ABORTING\n", trk_idx); print_data(); abort(); } * (uint32_t*) ptr = trk_idx; ptr += sizeof(uint32_t); * (uint32_t*) ptr = req_size; ptr += sizeof(uint32_t); return ptr;}/*************************************************************************** * track_free - track a free * * This function updates the allocation tracker for this free operation. * * The function takes the pointer to the memory passed by the user, and returns * the pointer that is to be freed * * +---------+---------+---------+---------+---------+---- * | trk_idx | size | (memory block of size req_size) ... * +---------+---------+---------+---------+---------+---- * ^ ^ * | | * returned ptr ptr */static void *track_free (uint8_t *ptr){ uint32_t trk_idx, req_size; if (no_tracking) return ptr; ptr -= sizeof(uint32_t); req_size = * (uint32_t*) ptr; ptr -= sizeof(uint32_t); trk_idx = * (uint32_t*) ptr; if (tracker_table[trk_idx].count) tracker_table[trk_idx].count--; if (tracker_table[trk_idx].total_size >= req_size) tracker_table[trk_idx].total_size -= req_size; return ptr;}void exit (int status){ /* * (Re)open the file here since the shell closes all file descriptors * before calling exit() */ output = fopen (path, "a"); if (output) print_data(); (*((void (*) (int))dlsym (RTLD_NEXT, "exit"))) (status); abort(); /* should never get here */}void *malloc (size_t size){ static void *(*func) (size_t); void *ret; if (!func) { func = (void *(*) (size_t))dlsym (RTLD_NEXT, "malloc"); init_flower_malloc(); } ret = func (size + ADMIN_DATA_SIZE); return (track_alloc (ret, size));}#if ORIGINAL_CALLOC_DOES_NOT_CALL_MALLOCvoid *calloc (size_t nelem, size_t elsize){ static void *(*func) (size_t, size_t); void *ret; int i; if (!func) { func = (void *(*) (size_t, size_t))dlsym (RTLD_NEXT, "calloc"); init_flower_malloc(); } ret = func (elsize * nelem + ADMIN_DATA_SIZE, 1); return (track_alloc(ret, elsize * nelem));}#endifvoid *realloc (void *ptr, size_t size){ static void *(*func) (void *, size_t); void *ret; if (!func) { func = (void *(*) (void *, size_t))dlsym (RTLD_NEXT, "realloc"); init_flower_malloc(); } ret = func (track_free(ptr), size + ADMIN_DATA_SIZE); return (track_alloc(ret, size));}voidfree (void *ptr){ static void (*func) (void *); if (!func) { func = (void (*) (void *))dlsym (RTLD_NEXT, "free"); init_flower_malloc(); } func (track_free(ptr)); return;}#endif /* HOST_OS_FREEBSD */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -