debugmalloc.c (2864B)
1 #include <u.h> 2 #define NOPLAN9DEFINES 3 #include <libc.h> 4 5 /* 6 * The Unix libc routines cannot be trusted to do their own locking. 7 * Sad but apparently true. 8 */ 9 static int mallocpid; 10 11 /* 12 * The Unix mallocs don't do nearly enough error checking 13 * for my tastes. We'll waste another 24 bytes per guy so that 14 * we can. This is severely antisocial, since now free and p9free 15 * are not interchangeable. 16 */ 17 int debugmalloc; 18 19 #define Overhead (debugmalloc ? (6*sizeof(ulong)) : 0) 20 #define MallocMagic 0xA110C09 21 #define ReallocMagic 0xB110C09 22 #define CallocMagic 0xC110C09 23 #define FreeMagic 0xF533F533 24 #define CheckMagic 0 25 #define END "\x7F\x2E\x55\x23" 26 27 static void 28 whoops(void *v) 29 { 30 fprint(2, "bad malloc block %p\n", v); 31 abort(); 32 } 33 34 static void* 35 mark(void *v, ulong pc, ulong n, ulong magic) 36 { 37 ulong *u; 38 char *p; 39 40 if(!debugmalloc) 41 return v; 42 43 if(v == nil) 44 return nil; 45 46 if(magic == FreeMagic || magic == CheckMagic){ 47 u = (ulong*)((char*)v-4*sizeof(ulong)); 48 if(u[0] != MallocMagic && u[0] != ReallocMagic && u[0] != CallocMagic) 49 whoops(v); 50 n = u[1]; 51 p = (char*)v+n; 52 if(memcmp(p, END, 4) != 0) 53 whoops(v); 54 if(magic != CheckMagic){ 55 u[0] = FreeMagic; 56 u[1] = u[2] = u[3] = pc; 57 if(n > 16){ 58 u[4] = u[5] = u[6] = u[7] = pc; 59 memset((char*)v+16, 0xFB, n-16); 60 } 61 } 62 return u; 63 }else{ 64 u = v; 65 u[0] = magic; 66 u[1] = n; 67 u[2] = 0; 68 u[3] = 0; 69 if(magic == ReallocMagic) 70 u[3] = pc; 71 else 72 u[2] = pc; 73 p = (char*)(u+4)+n; 74 memmove(p, END, 4); 75 return u+4; 76 } 77 } 78 79 void 80 setmalloctag(void *v, ulong t) 81 { 82 ulong *u; 83 84 if(!debugmalloc) 85 return; 86 87 if(v == nil) 88 return; 89 u = mark(v, 0, 0, 0); 90 u[2] = t; 91 } 92 93 void 94 setrealloctag(void *v, ulong t) 95 { 96 ulong *u; 97 98 if(!debugmalloc) 99 return; 100 101 if(v == nil) 102 return; 103 u = mark(v, 0, 0, 0); 104 u[3] = t; 105 } 106 107 void* 108 p9malloc(ulong n) 109 { 110 void *v; 111 if(n == 0) 112 n++; 113 /*fprint(2, "%s %d malloc\n", argv0, getpid()); */ 114 mallocpid = getpid(); 115 v = malloc(n+Overhead); 116 v = mark(v, getcallerpc(&n), n, MallocMagic); 117 /*fprint(2, "%s %d donemalloc\n", argv0, getpid()); */ 118 return v; 119 } 120 121 void 122 p9free(void *v) 123 { 124 if(v == nil) 125 return; 126 127 /*fprint(2, "%s %d free\n", argv0, getpid()); */ 128 mallocpid = getpid(); 129 v = mark(v, getcallerpc(&v), 0, FreeMagic); 130 free(v); 131 /*fprint(2, "%s %d donefree\n", argv0, getpid()); */ 132 } 133 134 void* 135 p9calloc(ulong a, ulong b) 136 { 137 void *v; 138 139 /*fprint(2, "%s %d calloc\n", argv0, getpid()); */ 140 mallocpid = getpid(); 141 v = calloc(a*b+Overhead, 1); 142 v = mark(v, getcallerpc(&a), a*b, CallocMagic); 143 /*fprint(2, "%s %d donecalloc\n", argv0, getpid()); */ 144 return v; 145 } 146 147 void* 148 p9realloc(void *v, ulong n) 149 { 150 /*fprint(2, "%s %d realloc\n", argv0, getpid()); */ 151 mallocpid = getpid(); 152 v = mark(v, getcallerpc(&v), 0, CheckMagic); 153 v = realloc(v, n+Overhead); 154 v = mark(v, getcallerpc(&v), n, ReallocMagic); 155 /*fprint(2, "%s %d donerealloc\n", argv0, getpid()); */ 156 return v; 157 }