9base

revived minimalist port of Plan 9 userland to Unix
git clone git://git.suckless.org/9base
Log | Files | Refs | README | LICENSE

debugmalloc.c (3058B)


      1 #include <u.h>
      2 #define NOPLAN9DEFINES
      3 #include <libc.h>
      4 
      5 /*
      6  * The Unix libc routines cannot be trusted to do their own locking.
      7  * Sad but apparently true.
      8  */
      9 static Lock malloclock;
     10 static int mallocpid;
     11 
     12 /*
     13  * The Unix mallocs don't do nearly enough error checking
     14  * for my tastes.  We'll waste another 24 bytes per guy so that
     15  * we can.  This is severely antisocial, since now free and p9free
     16  * are not interchangeable.
     17  */
     18 int debugmalloc;
     19 
     20 #define Overhead (debugmalloc ? (6*sizeof(ulong)) : 0)
     21 #define MallocMagic 0xA110C09
     22 #define ReallocMagic 0xB110C09
     23 #define CallocMagic 0xC110C09
     24 #define FreeMagic 0xF533F533
     25 #define CheckMagic 0
     26 #define END "\x7F\x2E\x55\x23"
     27 
     28 static void
     29 whoops(void *v)
     30 {
     31 	fprint(2, "bad malloc block %p\n", v);
     32 	abort();
     33 }
     34 
     35 static void*
     36 mark(void *v, ulong pc, ulong n, ulong magic)
     37 {
     38 	ulong *u;
     39 	char *p;
     40 
     41 	if(!debugmalloc)
     42 		return v;
     43 
     44 	if(v == nil)
     45 		return nil;
     46 
     47 	if(magic == FreeMagic || magic == CheckMagic){
     48 		u = (ulong*)((char*)v-4*sizeof(ulong));
     49 		if(u[0] != MallocMagic && u[0] != ReallocMagic && u[0] != CallocMagic)
     50 			whoops(v);
     51 		n = u[1];
     52 		p = (char*)v+n;
     53 		if(memcmp(p, END, 4) != 0)
     54 			whoops(v);
     55 		if(magic != CheckMagic){
     56 			u[0] = FreeMagic;
     57 			u[1] = u[2] = u[3] = pc;
     58 			if(n > 16){
     59 				u[4] = u[5] = u[6] = u[7] = pc;
     60 				memset((char*)v+16, 0xFB, n-16);
     61 			}
     62 		}
     63 		return u;
     64 	}else{
     65 		u = v;
     66 		u[0] = magic;
     67 		u[1] = n;
     68 		u[2] = 0;
     69 		u[3] = 0;
     70 		if(magic == ReallocMagic)
     71 			u[3] = pc;
     72 		else
     73 			u[2] = pc;
     74 		p = (char*)(u+4)+n;
     75 		memmove(p, END, 4);
     76 		return u+4;
     77 	}	
     78 }
     79 
     80 void
     81 setmalloctag(void *v, ulong t)
     82 {
     83 	ulong *u;
     84 
     85 	if(!debugmalloc)
     86 		return;
     87 
     88 	if(v == nil)
     89 		return;
     90 	u = mark(v, 0, 0, 0);
     91 	u[2] = t;
     92 }
     93 
     94 void
     95 setrealloctag(void *v, ulong t)
     96 {
     97 	ulong *u;
     98 
     99 	if(!debugmalloc)
    100 		return;
    101 
    102 	if(v == nil)
    103 		return;
    104 	u = mark(v, 0, 0, 0);
    105 	u[3] = t;
    106 }
    107 	
    108 void*
    109 p9malloc(ulong n)
    110 {
    111 	void *v;
    112 	if(n == 0)
    113 		n++;
    114 /*fprint(2, "%s %d malloc\n", argv0, getpid()); */
    115 	lock(&malloclock);
    116 	mallocpid = getpid();
    117 	v = malloc(n+Overhead);
    118 	v = mark(v, getcallerpc(&n), n, MallocMagic);
    119 	unlock(&malloclock);
    120 /*fprint(2, "%s %d donemalloc\n", argv0, getpid()); */
    121 	return v;
    122 }
    123 
    124 void
    125 p9free(void *v)
    126 {
    127 	if(v == nil)
    128 		return;
    129 
    130 /*fprint(2, "%s %d free\n", argv0, getpid()); */
    131 	lock(&malloclock);
    132 	mallocpid = getpid();
    133 	v = mark(v, getcallerpc(&v), 0, FreeMagic);
    134 	free(v);
    135 	unlock(&malloclock);
    136 /*fprint(2, "%s %d donefree\n", argv0, getpid()); */
    137 }
    138 
    139 void*
    140 p9calloc(ulong a, ulong b)
    141 {
    142 	void *v;
    143 
    144 /*fprint(2, "%s %d calloc\n", argv0, getpid()); */
    145 	lock(&malloclock);
    146 	mallocpid = getpid();
    147 	v = calloc(a*b+Overhead, 1);
    148 	v = mark(v, getcallerpc(&a), a*b, CallocMagic);
    149 	unlock(&malloclock);
    150 /*fprint(2, "%s %d donecalloc\n", argv0, getpid()); */
    151 	return v;
    152 }
    153 
    154 void*
    155 p9realloc(void *v, ulong n)
    156 {
    157 /*fprint(2, "%s %d realloc\n", argv0, getpid()); */
    158 	lock(&malloclock);
    159 	mallocpid = getpid();
    160 	v = mark(v, getcallerpc(&v), 0, CheckMagic);
    161 	v = realloc(v, n+Overhead);
    162 	v = mark(v, getcallerpc(&v), n, ReallocMagic);
    163 	unlock(&malloclock);
    164 /*fprint(2, "%s %d donerealloc\n", argv0, getpid()); */
    165 	return v;
    166 }