plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

debugmalloc.c (2864B)


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