commit - f437e56d1d5c8180ee2f93273f78393426efd5f9
commit + 9c635587071dcd7db349ec24ece1b397d24ac486
blob - /dev/null
blob + 3958e24314ed211aeaadf30a813684303624864d (mode 644)
--- /dev/null
+++ src/lib9/debugmalloc.c
+#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;
+}
blob - 7c5b1786cdb73da2addead06a073d744fea04580
blob + 2c6731ea8171f81f4bd96bda662043a61c5272d5
--- src/lib9/malloc.c
+++ src/lib9/malloc.c
+/*
+ * These are here mainly so that I can link against
+ * debugmalloc.c instead and not recompile the world.
+ */
+
#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;
-
void*
p9malloc(ulong n)
{
void *v;
+
if(n == 0)
n++;
-//fprint(2, "%s %d malloc\n", argv0, getpid());
- lock(&malloclock);
- v = malloc(n);
- unlock(&malloclock);
-//fprint(2, "%s %d donemalloc\n", argv0, getpid());
- return v;
+ return malloc(n);
}
void
p9free(void *v)
{
-//fprint(2, "%s %d free\n", argv0, getpid());
- lock(&malloclock);
+ if(v == nil)
+ return;
free(v);
- unlock(&malloclock);
-//fprint(2, "%s %d donefree\n", argv0, getpid());
}
void*
p9calloc(ulong a, ulong b)
{
- void *v;
+ if(a*b == 0)
+ a = b = 1;
-//fprint(2, "%s %d calloc\n", argv0, getpid());
- lock(&malloclock);
- v = calloc(a, b);
- unlock(&malloclock);
-//fprint(2, "%s %d donecalloc\n", argv0, getpid());
- return v;
+ return calloc(a*b, 1);
}
void*
p9realloc(void *v, ulong n)
{
-//fprint(2, "%s %d realloc\n", argv0, getpid());
- lock(&malloclock);
- v = realloc(v, n);
- unlock(&malloclock);
-//fprint(2, "%s %d donerealloc\n", argv0, getpid());
- return v;
+ return realloc(v, n);
}