diff options
author | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
---|---|---|
committer | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
commit | e5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch) | |
tree | d8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/cmd/aux/acidleak.c |
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/cmd/aux/acidleak.c')
-rwxr-xr-x | sys/src/cmd/aux/acidleak.c | 336 |
1 files changed, 336 insertions, 0 deletions
diff --git a/sys/src/cmd/aux/acidleak.c b/sys/src/cmd/aux/acidleak.c new file mode 100755 index 000000000..44eec30af --- /dev/null +++ b/sys/src/cmd/aux/acidleak.c @@ -0,0 +1,336 @@ +#include <u.h> +#include <libc.h> +#include <bio.h> + +void* +emalloc(ulong sz) +{ + void *v; + + v = malloc(sz); + if(v == nil) + sysfatal("malloc %lud fails", sz); + memset(v, 0, sz); + return v; +} + +void* +erealloc(void *v, ulong sz) +{ + v = realloc(v, sz); + if(v == nil) + sysfatal("realloc %lud fails", sz); + return v; +} + +char* +estrdup(char* s) +{ + char *r; + + r = strdup(s); + if(r == nil) + sysfatal("strdup fails"); + return r; +} + +typedef struct Block Block; +typedef struct Data Data; +struct Block { + ulong addr; + ulong size; + ulong w0; + ulong w1; + char *s0; + char *s1; + int mark; + int free; + Data *d; +}; + +struct Data { + ulong addr; + ulong val; + uchar type; + Block *b; +}; + +Block *block; +uint nblock; +uint ablock; + +Data *data; +Data *edata; +uint ndata; +uint adata; + +int +addrcmp(void *va, void *vb) +{ + ulong *a, *b; + + a = va; + b = vb; + if(*a < *b) + return -1; + if(*a > *b) + return 1; + return 0; +} + +Block* +findblock(ulong addr) +{ + int lo, hi, m; + + lo = 0; + hi = nblock; + + while(lo < hi) { + m = (lo+hi)/2; + if(block[m].addr < addr) + lo = m+1; + else if(addr < block[m].addr) + hi = m; + else + return &block[m]; + } + return nil; +} + +Data* +finddata(ulong addr) +{ + int lo, hi, m; + + lo = 0; + hi = ndata; + + while(lo < hi) { + m = (lo+hi)/2; + if(data[m].addr < addr) + lo = m+1; + else if(addr < data[m].addr) + hi = m; + else + return &data[m]; + } + if(0 <= lo && lo < ndata) + return &data[lo]; + return nil; +} + +int nmark; + +int +markblock(ulong from, ulong fromval, Block *b) +{ + Data *d; + ulong top; + Block *nb; + +USED(from, fromval); +//print("trace 0x%.8lux from 0x%.8lux (%d)\n", b->addr, from, b->mark); + if(b->free){ + // fprint(2, "possible dangling pointer *0x%.8lux = 0x%.8lux\n", from, fromval); + return 0; + } + if(b->mark) + return 0; + b->mark = 1; + nmark++; + + if(d = finddata(b->addr)) { + assert(d->addr >= b->addr); + b->d = d; + top = b->addr+b->size; + for(; d < edata && d->addr < top; d++) { + assert(d->b == 0); + d->b = b; + if((nb = findblock(d->val-8)) || (nb = findblock(d->val-8-8))) + markblock(d->addr, d->val, nb); + } + return 1; + } + return 0; +} + +enum { + AllocColor = 2, // dark blue: completely allocated region + HdrColor = 54, // bright blue: region with header + LeakColor = 205, // dark red: region with leak + LeakHdrColor = 240, // bright red: region with leaked header + FreeColor = 252, // bright yellow: completely free region + NoColor = 255, // padding, white +}; + +int +rXr(int as, int ae, int bs, int be) +{ + return bs < ae && as < be; +} + +void +main(int argc, char **argv) +{ + Biobuf bio; + char *p, *f[10]; + int bitmap, c, nf, resolution, n8, n16, hdr, nhdr, nlhdr, nleak, x, y, nb; + ulong allocstart, allocend, len, u; + Data *d, *ed; + Block *b, *eb; + + bitmap = 0; + resolution = 8; + x = 512; + ARGBEGIN{ + case 'b': + bitmap=1; + break; + case 'r': + resolution = atoi(EARGF(sysfatal("usage"))); + break; + case 'x': + x = atoi(EARGF(sysfatal("usage"))); + break; + }ARGEND + + n8 = n16 = 0; + allocstart = allocend = 0; + Binit(&bio, 0, OREAD); + while(p=Brdline(&bio, '\n')) { + p[Blinelen(&bio)-1] = '\0'; + nf = tokenize(p, f, nelem(f)); + if(nf >= 4 && strcmp(f[0], "data") == 0) { + if(ndata >= adata){ + if(adata == 0) + adata = 4096; + else + adata += adata / 4; /* increase 25% */ + data = erealloc(data, adata * sizeof(Data)); + } + data[ndata].addr = strtoul(f[1], nil, 0); + data[ndata].val = strtoul(f[2], nil, 0); + data[ndata].type = f[3][0]; + data[ndata].b = 0; + ndata++; + } + if(nf >= 5 && + (strcmp(f[0], "block") == 0 || strcmp(f[0], "free") == 0)) { + if(nblock >= ablock){ + if(ablock == 0) + ablock = 4096; + else + ablock += ablock / 4; /* increase 25% */ + block = erealloc(block, ablock * sizeof(Block)); + } + block[nblock].addr = strtoul(f[1], nil, 0); + block[nblock].size = strtoul(f[2], nil, 0); + block[nblock].w0 = strtoul(f[3], nil, 0); + block[nblock].w1 = strtoul(f[4], nil, 0); + if (nf >= 7) { + block[nblock].s0 = estrdup(f[5]); + block[nblock].s1 = estrdup(f[6]); + } else { + block[nblock].s0 = ""; + block[nblock].s1 = ""; + } + block[nblock].mark = 0; + block[nblock].d = 0; + block[nblock].free = strcmp(f[0], "free") == 0; + nblock++; + } + if(nf >= 4 && strcmp(f[0], "range") == 0 && strcmp(f[1], "alloc") == 0) { + allocstart = strtoul(f[2], 0, 0)&~15; + allocend = strtoul(f[3], 0, 0); + } + } + + qsort(block, nblock, sizeof(Block), addrcmp); + qsort(data, ndata, sizeof(Data), addrcmp); + + ed = edata = data+ndata; + for(d=data; d<ed; d++) { + if(d->type == 'a') + continue; + if(b = findblock(d->val-8)) // pool header 2 words + n8 += markblock(d->addr, d->val, b); + else if(b = findblock(d->val-8-8)) // sometimes malloc header 2 words + n16 += markblock(d->addr, d->val, b); + else + {}//print("noblock %.8lux\n", d->val); + } + + Binit(&bio, 1, OWRITE); + if(bitmap){ + if(n8 > n16) // guess size of header + hdr = 8; + else + hdr = 16; + + for(d=data; d<ed; d++) + if(d->type=='a') + break; + if(d==ed) + sysfatal("no allocated data region"); + + len = (allocend-allocstart+resolution-1)/resolution; + y = (len+x-1)/x; + Bprint(&bio, "%11s %11d %11d %11d %11d ", "m8", 0, 0, x, y); + +//fprint(2, "alloc %lux %lux x %d y %d res %d\n", allocstart, allocend, x, y, resolution); + + b = block; + eb = block+nblock; + for(u = allocstart; u<allocend; u+=resolution){ +//fprint(2, "u %lux %lux baddr %lux\n", u, u+resolution, b->addr); + while(b->addr+b->size <= u && b < eb) +//{ +//fprint(2, "\tskip %lux %lux\n", b->addr, b->addr+b->size); + b++; +//} + nhdr = 0; + nleak = 0; + nb = 0; + nlhdr = 0; + if(block < b && u < (b-1)->addr+(b-1)->size) + b--; + + for(; b->addr < u+resolution && b < eb; b++){ +//fprint(2, "\tblock %lux %lux %d\n", b->addr, b->addr+b->size, b->mark); + if(rXr(b->addr, b->addr+hdr, u, u+resolution) + || rXr(b->addr+b->size-8, b->addr+b->size, u, u+resolution)){ + if(b->mark == 0 && !b->free) + nlhdr++; + else + nhdr++; + } + if(b->mark == 0 && !b->free) + nleak++; + nb++; + } + if(nhdr) + c = HdrColor; + else if(nlhdr) + c = LeakHdrColor; + else if(nleak) + c = LeakColor; + else if(nb) + c = AllocColor; + else + c = FreeColor; +//fprint(2, "\t%d\n", c); + Bputc(&bio, c); + } + allocend = allocstart+x*y*resolution; + for(; u < allocend; u+=resolution) + Bputc(&bio, NoColor); + }else{ + eb = block+nblock; + for(b=block; b<eb; b++) + if(b->mark == 0 && !b->free) + Bprint(&bio, "block 0x%.8lux 0x%.8lux 0x%.8lux 0x%.8lux %s %s\n", b->addr, b->size, b->w0, b->w1, b->s0, b->s1); + } + Bterm(&bio); + exits(nil); +} |