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