#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 voidwhoops(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; } } voidsetmalloctag(void *v, ulong t){ ulong *u; if(!debugmalloc) return; if(v == nil) return; u = mark(v, 0, 0, 0); u[2] = t;} voidsetrealloctag(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;} voidp9free(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;}
#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;
}