blob: 8df272196d4eca471b77e75c4aea14f1f214316b [file] [log] [blame]
#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;
}