debugmalloc.c - 9base - revived minimalist port of Plan 9 userland to Unix
 (HTM) git clone git://git.suckless.org/9base
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) 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 }