Commit Diff


commit - f437e56d1d5c8180ee2f93273f78393426efd5f9
commit + 9c635587071dcd7db349ec24ece1b397d24ac486
blob - /dev/null
blob + 3958e24314ed211aeaadf30a813684303624864d (mode 644)
--- /dev/null
+++ src/lib9/debugmalloc.c
@@ -0,0 +1,166 @@
+#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
@@ -1,58 +1,41 @@
+/*
+ * 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);
 }