Blob


1 #include <u.h>
2 #define NOPLAN9DEFINES
3 #include <libc.h>
5 /*
6 * The Unix libc routines cannot be trusted to do their own locking.
7 * Sad but apparently true.
8 */
9 static int mallocpid;
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;
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"
27 static void
28 whoops(void *v)
29 {
30 fprint(2, "bad malloc block %p\n", v);
31 abort();
32 }
34 static void*
35 mark(void *v, ulong pc, ulong n, ulong magic)
36 {
37 ulong *u;
38 char *p;
40 if(!debugmalloc)
41 return v;
43 if(v == nil)
44 return nil;
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 }
79 void
80 setmalloctag(void *v, ulong t)
81 {
82 ulong *u;
84 if(!debugmalloc)
85 return;
87 if(v == nil)
88 return;
89 u = mark(v, 0, 0, 0);
90 u[2] = t;
91 }
93 void
94 setrealloctag(void *v, ulong t)
95 {
96 ulong *u;
98 if(!debugmalloc)
99 return;
101 if(v == nil)
102 return;
103 u = mark(v, 0, 0, 0);
104 u[3] = t;
107 void*
108 p9malloc(ulong n)
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;
121 void
122 p9free(void *v)
124 if(v == nil)
125 return;
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()); */
134 void*
135 p9calloc(ulong a, ulong b)
137 void *v;
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;
147 void*
148 p9realloc(void *v, ulong n)
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;