⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 yamd.c

📁 很好用的内存泄漏检测工具。要配合linux的gcc使用,安装后将你的编译器gcc命令换成yamd-gcc就行了
💻 C
📖 第 1 页 / 共 4 页
字号:
/* Yet Another Malloc Debugger *//* For now, error checking mostly causes bombs.  Later, it will handle   things gracefully. *//*  This file and the rest of YAMD is copyright (C) 1999 by Nate Eldredge. *//*  There is no warranty whatever; I disclaim responsibility for any *//*  damage caused.  Released under the GNU General Public License (see the *//*  file COPYING). *//* Headers */#define _GNU_SOURCE#include <stdio.h>#include <stdlib.h>#include <string.h>#include <stdarg.h>#include <unistd.h>#include <fcntl.h>#include <signal.h>#include <malloc.h>#include <errno.h>#include <assert.h>#include <limits.h>#include <sys/time.h>#include <sys/resource.h>#include <sys/mman.h>#include <sys/wait.h>#include <math.h>/* Configuration info */#if ((defined(__GLIBC__)) && (__GLIBC__ >= 2))#define GLIBC2 42#endif #if (defined(GLIBC2) && (__GLIBC_MINOR__ >= 1))#define GLIBC21#endif#ifdef GLIBC2#define HAVE_MEMALIGN#endif#ifdef GLIBC21#define HAVE_BACKTRACE_SYMBOLS#include <execinfo.h>#endif#ifdef __linux__#define HAVE_VALLOC#ifndef GLIBC2/* Might define sigcontext_struct instead.  Deal with it. */#define sigcontext_struct sigcontext#include <asm/sigcontext.h>#endif#endif#ifdef __DJGPP__#undef HAVE_VALLOC#undef HAVE_MEMALIGN#include <dpmi.h>#include <sys/nearptr.h>#include <sys/segments.h>#include <crt0.h>#include <setjmp.h>#include <sys/exceptn.h>#undef DJGPP_SIGNAL /* See comment at the #ifdef. */#endif/* #define DEBUG *//* #define HASH_PROFILE *//* Traceback stuff. *//* Integer type which is like a pointer, and can be cast to and from. */typedef unsigned long addr;/* Shorthand. */typedef unsigned char uchar;/* Doesn't point at anything, but is distinct from NULL. */#define BAD_POINTER ((void *)-1)#define MAX_TRACEBACK_LEVELS 50typedef addr TRACEBACK[MAX_TRACEBACK_LEVELS];#define ENVIRONMENT_PREFIX "YAMD_"/* Keeping track of which entry points did what. */#define BY_NONE 0#define BY_MALLOC 1#define BY_REALLOC 2#define BY_FREE 3#define BY_MEMALIGN 4#define BY_ALLOCA 5#define BY_AUTO 6 /* Automatic freeing of alloca'ed blocks-- unimplemented */#define BY_LITE 7#define BYBITS 3/* New algorithm.  We have several interlocking structures:   - Hash table.  Chained with the hash_next field.   - Linked list of all blocks, chained by all_next.   - Linked lists of blocks allocated by malloc or memalign, chained   by alignment_next.    - The realloc backlink. */ /* This thing is now rather large, but it's easier if it contains all   the allocations we need to do. */typedef struct block {  /* Some of these may be redundant */  addr block_addr; /* The address of the first page of the block */  size_t block_size; /* Number of bytes we got, altogether */  addr user_addr; /* Address we told the user */  size_t user_size; /* Size the user is allowed */  addr suffix_addr; /* Where the unmapped suffix pages start */  size_t alignment;  TRACEBACK where_alloced; /* Address of the function that allocated it. */  TRACEBACK where_freed; /* Address where it was freed, or NULL */  struct block *realloc_backlink;  struct block *hash_next;  struct block *all_next;  struct block *alignment_next;  unsigned who_alloced : BYBITS;  unsigned who_freed : BYBITS;} block; /* Should maybe be BLOCK or something? */#define HASH_SIZE 499 /* Probably should be a large prime. */static block *hash[HASH_SIZE];static block *all_blocks = NULL;static block *aligned_blocks = NULL; /* Those with non-default alignment */static block *unaligned_blocks = NULL; /* With default alignment. */#define HAS_DEFAULT_ALIGNMENT(b) ((b)->who_alloced != BY_MEMALIGN)/* Magic. */#define MAGIC_SIZE 8static uchar magic[MAGIC_SIZE] = { 0xde, 0xad, 0xbe, 0xef,				   0xba, 0xad, 0xca, 0xfe };#ifdef __i386__#define PGSZ 4096UL#else /* well, maybe it'll happen someday */#define PGSZ ((unsigned long)getpagesize())  /* Shorthand */#endif#define PAGEMASK (PGSZ - 1)/* Variables corresponding to options. *//* Alignment requirement for user blocks; should be a power of 2.   One could even make it 1; that would give a speed penalty for   the unaligned accesses, but should catch all overruns. */static int default_alignment = 1; static int check_front = 0; /* as opposed to end */#ifdef COMPLETE_MAGIC/* At present, we just magic-fill the bytes between the end we're   interested in (dependent on check_front) and the unmapped page.   This option will magic-fill the bytes at the other end as well.   But there are a lot of them, and so this is slow and involves some   tedious arithmetic.  Implement it later if there seems to be a need   for it. */static int complete_magic = 0;#endif/* Fix corrupted blocks? */static int repair_corrupted = 0;/* Die if a corrupted block is found? */static int die_on_corrupted = 1;/* Filename to which we output. */static const char *logfile_name = "-";/* Logging */#define LOG_INFO 1#define LOG_WARN 2#define LOG_ERR 3static int min_log_level = LOG_INFO;/* Ugly way to make lack of snprintf a little safer */#define MAX_PRINTF (PATH_MAX + 1024) /* let's be liberal */#define LOG_BUF_SIZE (MAX_PRINTF * 4)static char log_buf[LOG_BUF_SIZE];static int log_buf_pos = 0;static int log_fd = -1;/* Some statistics. */static size_t user_currently_allocated = 0; /* and not freed */static size_t max_user_allocated = 0; /* max value of the above */static size_t user_allocated = 0; /* whether freed or not */static unsigned long n_allocations = 0;static size_t internal_allocated = 0;static size_t internal_mapped = 0;static size_t max_internal_mapped = 0;/* Anything much bigger than this becomes a negative int, which   confuses the libc allocators.  It probably should never happen   anyway.  */#define WAY_TOO_BIG ((unsigned long)(2 * 1000 * 1000 * 1000))#define YAMD_SO_NAME "yamd.so"#define LD_PRELOAD_ENV "LD_PRELOAD"#define CAST_ASSIGN(d,s) ((d) = ((typeof (d))(s)))#define POINTER_FORMAT "%#08lx"/* Symbol control */#ifdef USE_LIBC_HOOKS#define WRAPPER_LINKAGE static#define WRAP(name) wrap_ ## name#define REAL(name) name#endif#ifdef USE_LD_PRELOAD#define WRAPPER_LINKAGE /* global */#define WRAP(name) name #define REAL(name) __libc_ ## name#endif#ifdef USE_LD_WRAP#define WRAPPER_LINKAGE /* global */#define WRAP(name) __wrap_ ## name #define REAL(name) __real_ ## name#endifextern void * REAL(malloc) (size_t s);WRAPPER_LINKAGE void * WRAP(malloc) (size_t s);extern void * REAL(realloc) (void *p, size_t s);WRAPPER_LINKAGE void * WRAP(realloc) (void * p, size_t s);extern void REAL(free) (void *p);WRAPPER_LINKAGE void WRAP(free) (void * p);#ifdef HAVE_MEMALIGNextern void * REAL(memalign) (size_t align, size_t size);WRAPPER_LINKAGE void * WRAP(memalign) (size_t align, size_t size);#endif/* Hook to ensure we get linked.  The asm is to avoid underscore   troubles. */int __yamd_hook_1 asm ("__yamd_hook_1") = 0;/* Perhaps someday we can use this to check a binary for containing   YAMD.  In the meantime it's just a few bytes. */static char some_text[] __attribute__((unused));static char some_text[] = "YAMD version " YAMD_VERSION " was here";/* Declarations */static void die(void);static int zap(addr p, size_t nb);static addr do_valloc(size_t n);static void mem_fill(uchar *dest, size_t dest_size, const uchar *src, size_t src_size);static addr magic_check_range(addr start, addr end);static void magic_fill_range(addr start, addr end);static void insert_block(block *b);static block *find_block_by_user_addr(addr a);static block *find_block_by_any_addr(addr a);static const char *get_entry_name(unsigned by_who);static void log_flush(void);static void log_vprintf(const char *fmt, va_list va);static void log_printf(const char *fmt, ...);static void log_event(int level, const char *desc);static void log_detail(int level, const char *fmt, ...);static void generate_any_traceback(TRACEBACK tb, addr start_eip, addr start_ebp, int eip_on_stack);static void generate_traceback(TRACEBACK tb, addr eip);static void dump_traceback(int level, TRACEBACK tb);static void do_any_traceback(int level, addr eip, addr ebp, int eip_os);static void do_traceback(int level, addr eip);static void describe_block(int level, block *b);static void check_block(block *b);static void check_heap(void);static void *do_malloc(size_t nbytes, size_t alignment, addr orig_caller, unsigned by_who, block *backlink);static block *block_to_free(void *user, addr orig_caller, unsigned by_who);static void do_free_block(block *b, addr orig_caller, unsigned by_who);static void print_footer(void);static void print_header(void);static void handle_page_fault(addr address, int write, addr eip, addr ebp);static void describe_address(int level, addr a);static void *lite_malloc(size_t n);static void lite_free(void *p);static void lite_free_block(block *b);/* --------------------------END DECLS------------------------------ *//* Number of times we call __yamd_maybe_finish. */#define TRIES_FOR_FINISH 3static void startup(void);static void finish(void);void __yamd_maybe_startup(void);void __yamd_maybe_finish(void);static void die(void){  log_flush();  abort();}#ifdef USE_LIBC_HOOKStypedef struct {  void * (*malloc_hook)(size_t s);  void * (*realloc_hook)(void *p , size_t s );  void (*free_hook)(void *p );  void * (*memalign_hook)(size_t al, size_t s );} hookset;static hookset yamd_hooks = {  WRAP(malloc),  WRAP(realloc),  WRAP(free),  WRAP(memalign)};static hookset old_hooks = { NULL, NULL, NULL, NULL };static void set_hooks(hookset *h){  CAST_ASSIGN(__malloc_hook, h->malloc_hook);  CAST_ASSIGN(__realloc_hook, h->realloc_hook);  CAST_ASSIGN(__free_hook, h->free_hook);  CAST_ASSIGN(__memalign_hook, h->memalign_hook);}static void get_hooks(hookset *h){  CAST_ASSIGN(h->malloc_hook, __malloc_hook);  CAST_ASSIGN(h->realloc_hook, __realloc_hook);  CAST_ASSIGN(h->free_hook, __free_hook);  CAST_ASSIGN(h->memalign_hook, __memalign_hook);}#elsetypedef int hookset; /* should never be used */#define set_hooks(h)#define get_hooks(h)#endif#define FULL_MODE 1#define LITE_MODE 2#define NOCATCH_MODE 3static int mode = LITE_MODE;static int old_mode = LITE_MODE; /* so we can call OK_CATCH at first. */#define NO_CATCH() do { 			\  old_mode = mode;				\  mode = NOCATCH_MODE;				\  set_hooks(&old_hooks);			\} while (0)#define OK_CATCH() do {			\  mode = old_mode;				\  get_hooks(&old_hooks);			\  set_hooks(&yamd_hooks);			\} while (0)/* Am I trying too hard to make this transparently changeable? */#define MODE_VAR int __yamd_temp_mode#define ENTER() do { __yamd_temp_mode = mode; mode = LITE_MODE; } while (0)#define LEAVE() do { 			\  mode = __yamd_temp_mode;			\  if (mode == FULL_MODE) log_flush();           \} while (0)#define WAS_LITE_MODE (__yamd_temp_mode == LITE_MODE)#define SHOULD_NOT_CATCH (mode == NOCATCH_MODE)/* Utility. */static inline unsigned longround_down(unsigned long x, unsigned long mul){  return x - (x % mul);}static inline unsigned longround_up(unsigned long x, unsigned long mul){  return round_down(x + (mul - 1), mul);}/* Make region untouchable. */static intzap(addr p, size_t nbytes){  int v;  /*  fprintf(stderr, "Doing mprotect(%p, %u, PROT_NONE)\n", p, nb); */  v = mprotect((void *)p, nbytes, PROT_NONE);  if (v != 0)    perror("unmap: mprotect");  return v;}#if 0  /* Not used now. */static intremap_pages(void *p, size_t np){  int v;  v = mprotect(p, np * PGSZ, PROT_READ | PROT_WRITE);  if (v != 0)    perror("unmap: mprotect");  return v;}#endif/* The low-level routines we use to get memory.   FIXME: The naming has become misleading. */#if defined(__linux__)/* We know Linux has a good, fast mmap.  Use it, so as not to incur   malloc's memory overhead. */static void *system_valloc(size_t nbytes){  void *p;  p = mmap(NULL, round_up(nbytes, PGSZ), PROT_READ | PROT_WRITE,	   MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);  if (p == MAP_FAILED)    return NULL;  else    return p;}#elif defined(HAVE_VALLOC)#define system_valloc valloc#else /* generic implementation */static void *system_valloc(size_t nbytes){  addr a;  a = (addr)REAL(malloc)(nbytes + PGSZ);  return (void *)((a + PAGEMASK) & ~PAGEMASK);}#endifstatic addrdo_valloc(size_t nbytes){  void *p;  NO_CATCH();  p = system_valloc(nbytes);  OK_CATCH();

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -