|  | #include <u.h> | 
|  | #define NOPLAN9DEFINES | 
|  | #include <libc.h> | 
|  |  | 
|  | /* | 
|  | * The Unix libc routines cannot be trusted to do their own locking. | 
|  | * Sad but apparently true. | 
|  | */ | 
|  | static Lock malloclock; | 
|  | static int mallocpid; | 
|  |  | 
|  | /* | 
|  | * The Unix mallocs don't do nearly enough error checking | 
|  | * for my tastes.  We'll waste another 24 bytes per guy so that | 
|  | * we can.  This is severely antisocial, since now free and p9free | 
|  | * are not interchangeable. | 
|  | */ | 
|  | int debugmalloc; | 
|  |  | 
|  | #define Overhead (debugmalloc ? (6*sizeof(ulong)) : 0) | 
|  | #define MallocMagic 0xA110C09 | 
|  | #define ReallocMagic 0xB110C09 | 
|  | #define CallocMagic 0xC110C09 | 
|  | #define FreeMagic 0xF533F533 | 
|  | #define CheckMagic 0 | 
|  | #define END "\x7F\x2E\x55\x23" | 
|  |  | 
|  | static void | 
|  | whoops(void *v) | 
|  | { | 
|  | fprint(2, "bad malloc block %p\n", v); | 
|  | abort(); | 
|  | } | 
|  |  | 
|  | static void* | 
|  | mark(void *v, ulong pc, ulong n, ulong magic) | 
|  | { | 
|  | ulong *u; | 
|  | char *p; | 
|  |  | 
|  | if(!debugmalloc) | 
|  | return v; | 
|  |  | 
|  | if(v == nil) | 
|  | return nil; | 
|  |  | 
|  | if(magic == FreeMagic || magic == CheckMagic){ | 
|  | u = (ulong*)((char*)v-4*sizeof(ulong)); | 
|  | if(u[0] != MallocMagic && u[0] != ReallocMagic && u[0] != CallocMagic) | 
|  | whoops(v); | 
|  | n = u[1]; | 
|  | p = (char*)v+n; | 
|  | if(memcmp(p, END, 4) != 0) | 
|  | whoops(v); | 
|  | if(magic != CheckMagic){ | 
|  | u[0] = FreeMagic; | 
|  | u[1] = u[2] = u[3] = pc; | 
|  | if(n > 16){ | 
|  | u[4] = u[5] = u[6] = u[7] = pc; | 
|  | memset((char*)v+16, 0xFB, n-16); | 
|  | } | 
|  | } | 
|  | return u; | 
|  | }else{ | 
|  | u = v; | 
|  | u[0] = magic; | 
|  | u[1] = n; | 
|  | u[2] = 0; | 
|  | u[3] = 0; | 
|  | if(magic == ReallocMagic) | 
|  | u[3] = pc; | 
|  | else | 
|  | u[2] = pc; | 
|  | p = (char*)(u+4)+n; | 
|  | memmove(p, END, 4); | 
|  | return u+4; | 
|  | } | 
|  | } | 
|  |  | 
|  | void | 
|  | setmalloctag(void *v, ulong t) | 
|  | { | 
|  | ulong *u; | 
|  |  | 
|  | if(!debugmalloc) | 
|  | return; | 
|  |  | 
|  | if(v == nil) | 
|  | return; | 
|  | u = mark(v, 0, 0, 0); | 
|  | u[2] = t; | 
|  | } | 
|  |  | 
|  | void | 
|  | setrealloctag(void *v, ulong t) | 
|  | { | 
|  | ulong *u; | 
|  |  | 
|  | if(!debugmalloc) | 
|  | return; | 
|  |  | 
|  | if(v == nil) | 
|  | return; | 
|  | u = mark(v, 0, 0, 0); | 
|  | u[3] = t; | 
|  | } | 
|  |  | 
|  | void* | 
|  | p9malloc(ulong n) | 
|  | { | 
|  | void *v; | 
|  | if(n == 0) | 
|  | n++; | 
|  | /*fprint(2, "%s %d malloc\n", argv0, getpid()); */ | 
|  | lock(&malloclock); | 
|  | mallocpid = getpid(); | 
|  | v = malloc(n+Overhead); | 
|  | v = mark(v, getcallerpc(&n), n, MallocMagic); | 
|  | unlock(&malloclock); | 
|  | /*fprint(2, "%s %d donemalloc\n", argv0, getpid()); */ | 
|  | return v; | 
|  | } | 
|  |  | 
|  | void | 
|  | p9free(void *v) | 
|  | { | 
|  | if(v == nil) | 
|  | return; | 
|  |  | 
|  | /*fprint(2, "%s %d free\n", argv0, getpid()); */ | 
|  | lock(&malloclock); | 
|  | mallocpid = getpid(); | 
|  | v = mark(v, getcallerpc(&v), 0, FreeMagic); | 
|  | free(v); | 
|  | unlock(&malloclock); | 
|  | /*fprint(2, "%s %d donefree\n", argv0, getpid()); */ | 
|  | } | 
|  |  | 
|  | void* | 
|  | p9calloc(ulong a, ulong b) | 
|  | { | 
|  | void *v; | 
|  |  | 
|  | /*fprint(2, "%s %d calloc\n", argv0, getpid()); */ | 
|  | lock(&malloclock); | 
|  | mallocpid = getpid(); | 
|  | v = calloc(a*b+Overhead, 1); | 
|  | v = mark(v, getcallerpc(&a), a*b, CallocMagic); | 
|  | unlock(&malloclock); | 
|  | /*fprint(2, "%s %d donecalloc\n", argv0, getpid()); */ | 
|  | return v; | 
|  | } | 
|  |  | 
|  | void* | 
|  | p9realloc(void *v, ulong n) | 
|  | { | 
|  | /*fprint(2, "%s %d realloc\n", argv0, getpid()); */ | 
|  | lock(&malloclock); | 
|  | mallocpid = getpid(); | 
|  | v = mark(v, getcallerpc(&v), 0, CheckMagic); | 
|  | v = realloc(v, n+Overhead); | 
|  | v = mark(v, getcallerpc(&v), n, ReallocMagic); | 
|  | unlock(&malloclock); | 
|  | /*fprint(2, "%s %d donerealloc\n", argv0, getpid()); */ | 
|  | return v; | 
|  | } |