159cc4ca5SDavid du Colombier #include <u.h>
259cc4ca5SDavid du Colombier #include <libc.h>
359cc4ca5SDavid du Colombier #include <bio.h>
459cc4ca5SDavid du Colombier
559cc4ca5SDavid du Colombier void*
emalloc(ulong sz)659cc4ca5SDavid du Colombier emalloc(ulong sz)
759cc4ca5SDavid du Colombier {
859cc4ca5SDavid du Colombier void *v;
959cc4ca5SDavid du Colombier
1059cc4ca5SDavid du Colombier v = malloc(sz);
1159cc4ca5SDavid du Colombier if(v == nil)
1214cc0f53SDavid du Colombier sysfatal("malloc %lud fails", sz);
1359cc4ca5SDavid du Colombier memset(v, 0, sz);
1459cc4ca5SDavid du Colombier return v;
1559cc4ca5SDavid du Colombier }
1659cc4ca5SDavid du Colombier
1759cc4ca5SDavid du Colombier void*
erealloc(void * v,ulong sz)1859cc4ca5SDavid du Colombier erealloc(void *v, ulong sz)
1959cc4ca5SDavid du Colombier {
2059cc4ca5SDavid du Colombier v = realloc(v, sz);
2159cc4ca5SDavid du Colombier if(v == nil)
2214cc0f53SDavid du Colombier sysfatal("realloc %lud fails", sz);
2359cc4ca5SDavid du Colombier return v;
2459cc4ca5SDavid du Colombier }
2559cc4ca5SDavid du Colombier
26d95be1c0SDavid du Colombier char*
estrdup(char * s)27d95be1c0SDavid du Colombier estrdup(char* s)
28d95be1c0SDavid du Colombier {
29d95be1c0SDavid du Colombier char *r;
30d95be1c0SDavid du Colombier
31d95be1c0SDavid du Colombier r = strdup(s);
32d95be1c0SDavid du Colombier if(r == nil)
3314cc0f53SDavid du Colombier sysfatal("strdup fails");
34d95be1c0SDavid du Colombier return r;
35d95be1c0SDavid du Colombier }
36d95be1c0SDavid du Colombier
3759cc4ca5SDavid du Colombier typedef struct Block Block;
3859cc4ca5SDavid du Colombier typedef struct Data Data;
3959cc4ca5SDavid du Colombier struct Block {
4059cc4ca5SDavid du Colombier ulong addr;
4159cc4ca5SDavid du Colombier ulong size;
4259cc4ca5SDavid du Colombier ulong w0;
4359cc4ca5SDavid du Colombier ulong w1;
44d95be1c0SDavid du Colombier char *s0;
45d95be1c0SDavid du Colombier char *s1;
4659cc4ca5SDavid du Colombier int mark;
47fb7f0c93SDavid du Colombier int free;
4859cc4ca5SDavid du Colombier Data *d;
4959cc4ca5SDavid du Colombier };
5059cc4ca5SDavid du Colombier
5159cc4ca5SDavid du Colombier struct Data {
5259cc4ca5SDavid du Colombier ulong addr;
5359cc4ca5SDavid du Colombier ulong val;
5459cc4ca5SDavid du Colombier uchar type;
5559cc4ca5SDavid du Colombier Block *b;
5659cc4ca5SDavid du Colombier };
5759cc4ca5SDavid du Colombier
5859cc4ca5SDavid du Colombier Block *block;
59*bfb6eab9SDavid du Colombier uint nblock;
60*bfb6eab9SDavid du Colombier uint ablock;
6159cc4ca5SDavid du Colombier
6259cc4ca5SDavid du Colombier Data *data;
6359cc4ca5SDavid du Colombier Data *edata;
64*bfb6eab9SDavid du Colombier uint ndata;
65*bfb6eab9SDavid du Colombier uint adata;
6659cc4ca5SDavid du Colombier
6759cc4ca5SDavid du Colombier int
addrcmp(void * va,void * vb)6859cc4ca5SDavid du Colombier addrcmp(void *va, void *vb)
6959cc4ca5SDavid du Colombier {
7059cc4ca5SDavid du Colombier ulong *a, *b;
7159cc4ca5SDavid du Colombier
7259cc4ca5SDavid du Colombier a = va;
7359cc4ca5SDavid du Colombier b = vb;
7459cc4ca5SDavid du Colombier if(*a < *b)
7559cc4ca5SDavid du Colombier return -1;
7659cc4ca5SDavid du Colombier if(*a > *b)
7759cc4ca5SDavid du Colombier return 1;
7859cc4ca5SDavid du Colombier return 0;
7959cc4ca5SDavid du Colombier }
8059cc4ca5SDavid du Colombier
8159cc4ca5SDavid du Colombier Block*
findblock(ulong addr)8259cc4ca5SDavid du Colombier findblock(ulong addr)
8359cc4ca5SDavid du Colombier {
8459cc4ca5SDavid du Colombier int lo, hi, m;
8559cc4ca5SDavid du Colombier
8659cc4ca5SDavid du Colombier lo = 0;
8759cc4ca5SDavid du Colombier hi = nblock;
8859cc4ca5SDavid du Colombier
8959cc4ca5SDavid du Colombier while(lo < hi) {
9059cc4ca5SDavid du Colombier m = (lo+hi)/2;
9159cc4ca5SDavid du Colombier if(block[m].addr < addr)
9259cc4ca5SDavid du Colombier lo = m+1;
9359cc4ca5SDavid du Colombier else if(addr < block[m].addr)
9459cc4ca5SDavid du Colombier hi = m;
9559cc4ca5SDavid du Colombier else
9659cc4ca5SDavid du Colombier return &block[m];
9759cc4ca5SDavid du Colombier }
9859cc4ca5SDavid du Colombier return nil;
9959cc4ca5SDavid du Colombier }
10059cc4ca5SDavid du Colombier
10159cc4ca5SDavid du Colombier Data*
finddata(ulong addr)10259cc4ca5SDavid du Colombier finddata(ulong addr)
10359cc4ca5SDavid du Colombier {
10459cc4ca5SDavid du Colombier int lo, hi, m;
10559cc4ca5SDavid du Colombier
10659cc4ca5SDavid du Colombier lo = 0;
10759cc4ca5SDavid du Colombier hi = ndata;
10859cc4ca5SDavid du Colombier
10959cc4ca5SDavid du Colombier while(lo < hi) {
11059cc4ca5SDavid du Colombier m = (lo+hi)/2;
11159cc4ca5SDavid du Colombier if(data[m].addr < addr)
11259cc4ca5SDavid du Colombier lo = m+1;
11359cc4ca5SDavid du Colombier else if(addr < data[m].addr)
11459cc4ca5SDavid du Colombier hi = m;
11559cc4ca5SDavid du Colombier else
11659cc4ca5SDavid du Colombier return &data[m];
11759cc4ca5SDavid du Colombier }
11859cc4ca5SDavid du Colombier if(0 <= lo && lo < ndata)
11959cc4ca5SDavid du Colombier return &data[lo];
120ec46fab0SDavid du Colombier return nil;
12159cc4ca5SDavid du Colombier }
12259cc4ca5SDavid du Colombier
12359cc4ca5SDavid du Colombier int nmark;
12459cc4ca5SDavid du Colombier
12580ee5cbfSDavid du Colombier int
markblock(ulong from,ulong fromval,Block * b)126fb7f0c93SDavid du Colombier markblock(ulong from, ulong fromval, Block *b)
12759cc4ca5SDavid du Colombier {
12859cc4ca5SDavid du Colombier Data *d;
12959cc4ca5SDavid du Colombier ulong top;
13059cc4ca5SDavid du Colombier Block *nb;
13159cc4ca5SDavid du Colombier
13287bc2094SDavid du Colombier USED(from, fromval);
13359cc4ca5SDavid du Colombier //print("trace 0x%.8lux from 0x%.8lux (%d)\n", b->addr, from, b->mark);
134fb7f0c93SDavid du Colombier if(b->free){
135fb7f0c93SDavid du Colombier // fprint(2, "possible dangling pointer *0x%.8lux = 0x%.8lux\n", from, fromval);
136fb7f0c93SDavid du Colombier return 0;
137fb7f0c93SDavid du Colombier }
13859cc4ca5SDavid du Colombier if(b->mark)
13980ee5cbfSDavid du Colombier return 0;
14059cc4ca5SDavid du Colombier b->mark = 1;
14159cc4ca5SDavid du Colombier nmark++;
14259cc4ca5SDavid du Colombier
14359cc4ca5SDavid du Colombier if(d = finddata(b->addr)) {
14459cc4ca5SDavid du Colombier assert(d->addr >= b->addr);
14559cc4ca5SDavid du Colombier b->d = d;
14659cc4ca5SDavid du Colombier top = b->addr+b->size;
14759cc4ca5SDavid du Colombier for(; d < edata && d->addr < top; d++) {
14859cc4ca5SDavid du Colombier assert(d->b == 0);
14959cc4ca5SDavid du Colombier d->b = b;
15059cc4ca5SDavid du Colombier if((nb = findblock(d->val-8)) || (nb = findblock(d->val-8-8)))
151fb7f0c93SDavid du Colombier markblock(d->addr, d->val, nb);
15259cc4ca5SDavid du Colombier }
15380ee5cbfSDavid du Colombier return 1;
15459cc4ca5SDavid du Colombier }
15580ee5cbfSDavid du Colombier return 0;
15680ee5cbfSDavid du Colombier }
15780ee5cbfSDavid du Colombier
15880ee5cbfSDavid du Colombier enum {
15980ee5cbfSDavid du Colombier AllocColor = 2, // dark blue: completely allocated region
16080ee5cbfSDavid du Colombier HdrColor = 54, // bright blue: region with header
16180ee5cbfSDavid du Colombier LeakColor = 205, // dark red: region with leak
16280ee5cbfSDavid du Colombier LeakHdrColor = 240, // bright red: region with leaked header
16380ee5cbfSDavid du Colombier FreeColor = 252, // bright yellow: completely free region
16480ee5cbfSDavid du Colombier NoColor = 255, // padding, white
16580ee5cbfSDavid du Colombier };
16680ee5cbfSDavid du Colombier
16780ee5cbfSDavid du Colombier int
rXr(int as,int ae,int bs,int be)16880ee5cbfSDavid du Colombier rXr(int as, int ae, int bs, int be)
16980ee5cbfSDavid du Colombier {
17080ee5cbfSDavid du Colombier return bs < ae && as < be;
17159cc4ca5SDavid du Colombier }
17259cc4ca5SDavid du Colombier
17359cc4ca5SDavid du Colombier void
main(int argc,char ** argv)17480ee5cbfSDavid du Colombier main(int argc, char **argv)
17559cc4ca5SDavid du Colombier {
17659cc4ca5SDavid du Colombier Biobuf bio;
17759cc4ca5SDavid du Colombier char *p, *f[10];
17880ee5cbfSDavid du Colombier int bitmap, c, nf, resolution, n8, n16, hdr, nhdr, nlhdr, nleak, x, y, nb;
17980ee5cbfSDavid du Colombier ulong allocstart, allocend, len, u;
18059cc4ca5SDavid du Colombier Data *d, *ed;
18159cc4ca5SDavid du Colombier Block *b, *eb;
18259cc4ca5SDavid du Colombier
18380ee5cbfSDavid du Colombier bitmap = 0;
18480ee5cbfSDavid du Colombier resolution = 8;
18580ee5cbfSDavid du Colombier x = 512;
18680ee5cbfSDavid du Colombier ARGBEGIN{
18780ee5cbfSDavid du Colombier case 'b':
18880ee5cbfSDavid du Colombier bitmap=1;
18980ee5cbfSDavid du Colombier break;
19080ee5cbfSDavid du Colombier case 'r':
19180ee5cbfSDavid du Colombier resolution = atoi(EARGF(sysfatal("usage")));
19280ee5cbfSDavid du Colombier break;
19380ee5cbfSDavid du Colombier case 'x':
19480ee5cbfSDavid du Colombier x = atoi(EARGF(sysfatal("usage")));
19580ee5cbfSDavid du Colombier break;
19680ee5cbfSDavid du Colombier }ARGEND
19780ee5cbfSDavid du Colombier
19880ee5cbfSDavid du Colombier n8 = n16 = 0;
19980ee5cbfSDavid du Colombier allocstart = allocend = 0;
20059cc4ca5SDavid du Colombier Binit(&bio, 0, OREAD);
20159cc4ca5SDavid du Colombier while(p=Brdline(&bio, '\n')) {
20259cc4ca5SDavid du Colombier p[Blinelen(&bio)-1] = '\0';
20359cc4ca5SDavid du Colombier nf = tokenize(p, f, nelem(f));
20459cc4ca5SDavid du Colombier if(nf >= 4 && strcmp(f[0], "data") == 0) {
205*bfb6eab9SDavid du Colombier if(ndata >= adata){
206*bfb6eab9SDavid du Colombier if(adata == 0)
207*bfb6eab9SDavid du Colombier adata = 4096;
208*bfb6eab9SDavid du Colombier else
209*bfb6eab9SDavid du Colombier adata += adata / 4; /* increase 25% */
210*bfb6eab9SDavid du Colombier data = erealloc(data, adata * sizeof(Data));
211*bfb6eab9SDavid du Colombier }
21259cc4ca5SDavid du Colombier data[ndata].addr = strtoul(f[1], nil, 0);
21359cc4ca5SDavid du Colombier data[ndata].val = strtoul(f[2], nil, 0);
21459cc4ca5SDavid du Colombier data[ndata].type = f[3][0];
21559cc4ca5SDavid du Colombier data[ndata].b = 0;
21659cc4ca5SDavid du Colombier ndata++;
21759cc4ca5SDavid du Colombier }
218*bfb6eab9SDavid du Colombier if(nf >= 5 &&
219*bfb6eab9SDavid du Colombier (strcmp(f[0], "block") == 0 || strcmp(f[0], "free") == 0)) {
220*bfb6eab9SDavid du Colombier if(nblock >= ablock){
221*bfb6eab9SDavid du Colombier if(ablock == 0)
222*bfb6eab9SDavid du Colombier ablock = 4096;
223*bfb6eab9SDavid du Colombier else
224*bfb6eab9SDavid du Colombier ablock += ablock / 4; /* increase 25% */
225*bfb6eab9SDavid du Colombier block = erealloc(block, ablock * sizeof(Block));
226*bfb6eab9SDavid du Colombier }
22759cc4ca5SDavid du Colombier block[nblock].addr = strtoul(f[1], nil, 0);
22859cc4ca5SDavid du Colombier block[nblock].size = strtoul(f[2], nil, 0);
22959cc4ca5SDavid du Colombier block[nblock].w0 = strtoul(f[3], nil, 0);
23059cc4ca5SDavid du Colombier block[nblock].w1 = strtoul(f[4], nil, 0);
231d95be1c0SDavid du Colombier if (nf >= 7) {
232d95be1c0SDavid du Colombier block[nblock].s0 = estrdup(f[5]);
233d95be1c0SDavid du Colombier block[nblock].s1 = estrdup(f[6]);
234d95be1c0SDavid du Colombier } else {
235d95be1c0SDavid du Colombier block[nblock].s0 = "";
236d95be1c0SDavid du Colombier block[nblock].s1 = "";
237d95be1c0SDavid du Colombier }
23859cc4ca5SDavid du Colombier block[nblock].mark = 0;
23959cc4ca5SDavid du Colombier block[nblock].d = 0;
240fb7f0c93SDavid du Colombier block[nblock].free = strcmp(f[0], "free") == 0;
24159cc4ca5SDavid du Colombier nblock++;
24259cc4ca5SDavid du Colombier }
24380ee5cbfSDavid du Colombier if(nf >= 4 && strcmp(f[0], "range") == 0 && strcmp(f[1], "alloc") == 0) {
24480ee5cbfSDavid du Colombier allocstart = strtoul(f[2], 0, 0)&~15;
24580ee5cbfSDavid du Colombier allocend = strtoul(f[3], 0, 0);
24680ee5cbfSDavid du Colombier }
24759cc4ca5SDavid du Colombier }
24859cc4ca5SDavid du Colombier
24959cc4ca5SDavid du Colombier qsort(block, nblock, sizeof(Block), addrcmp);
25059cc4ca5SDavid du Colombier qsort(data, ndata, sizeof(Data), addrcmp);
25159cc4ca5SDavid du Colombier
25259cc4ca5SDavid du Colombier ed = edata = data+ndata;
25359cc4ca5SDavid du Colombier for(d=data; d<ed; d++) {
25459cc4ca5SDavid du Colombier if(d->type == 'a')
25559cc4ca5SDavid du Colombier continue;
25659cc4ca5SDavid du Colombier if(b = findblock(d->val-8)) // pool header 2 words
257fb7f0c93SDavid du Colombier n8 += markblock(d->addr, d->val, b);
25859cc4ca5SDavid du Colombier else if(b = findblock(d->val-8-8)) // sometimes malloc header 2 words
259fb7f0c93SDavid du Colombier n16 += markblock(d->addr, d->val, b);
26059cc4ca5SDavid du Colombier else
2619a747e4fSDavid du Colombier {}//print("noblock %.8lux\n", d->val);
26259cc4ca5SDavid du Colombier }
26359cc4ca5SDavid du Colombier
26459cc4ca5SDavid du Colombier Binit(&bio, 1, OWRITE);
26580ee5cbfSDavid du Colombier if(bitmap){
26680ee5cbfSDavid du Colombier if(n8 > n16) // guess size of header
26780ee5cbfSDavid du Colombier hdr = 8;
26880ee5cbfSDavid du Colombier else
26980ee5cbfSDavid du Colombier hdr = 16;
27080ee5cbfSDavid du Colombier
27180ee5cbfSDavid du Colombier for(d=data; d<ed; d++)
27280ee5cbfSDavid du Colombier if(d->type=='a')
27380ee5cbfSDavid du Colombier break;
27480ee5cbfSDavid du Colombier if(d==ed)
27580ee5cbfSDavid du Colombier sysfatal("no allocated data region");
27680ee5cbfSDavid du Colombier
27780ee5cbfSDavid du Colombier len = (allocend-allocstart+resolution-1)/resolution;
27880ee5cbfSDavid du Colombier y = (len+x-1)/x;
27980ee5cbfSDavid du Colombier Bprint(&bio, "%11s %11d %11d %11d %11d ", "m8", 0, 0, x, y);
28080ee5cbfSDavid du Colombier
28180ee5cbfSDavid du Colombier //fprint(2, "alloc %lux %lux x %d y %d res %d\n", allocstart, allocend, x, y, resolution);
28280ee5cbfSDavid du Colombier
28380ee5cbfSDavid du Colombier b = block;
28480ee5cbfSDavid du Colombier eb = block+nblock;
28580ee5cbfSDavid du Colombier for(u = allocstart; u<allocend; u+=resolution){
28680ee5cbfSDavid du Colombier //fprint(2, "u %lux %lux baddr %lux\n", u, u+resolution, b->addr);
28780ee5cbfSDavid du Colombier while(b->addr+b->size <= u && b < eb)
28880ee5cbfSDavid du Colombier //{
28980ee5cbfSDavid du Colombier //fprint(2, "\tskip %lux %lux\n", b->addr, b->addr+b->size);
29080ee5cbfSDavid du Colombier b++;
29180ee5cbfSDavid du Colombier //}
29280ee5cbfSDavid du Colombier nhdr = 0;
29380ee5cbfSDavid du Colombier nleak = 0;
29480ee5cbfSDavid du Colombier nb = 0;
29580ee5cbfSDavid du Colombier nlhdr = 0;
29680ee5cbfSDavid du Colombier if(block < b && u < (b-1)->addr+(b-1)->size)
29780ee5cbfSDavid du Colombier b--;
29880ee5cbfSDavid du Colombier
29980ee5cbfSDavid du Colombier for(; b->addr < u+resolution && b < eb; b++){
30080ee5cbfSDavid du Colombier //fprint(2, "\tblock %lux %lux %d\n", b->addr, b->addr+b->size, b->mark);
30180ee5cbfSDavid du Colombier if(rXr(b->addr, b->addr+hdr, u, u+resolution)
30280ee5cbfSDavid du Colombier || rXr(b->addr+b->size-8, b->addr+b->size, u, u+resolution)){
30341eff910SDavid du Colombier if(b->mark == 0 && !b->free)
30480ee5cbfSDavid du Colombier nlhdr++;
30580ee5cbfSDavid du Colombier else
30680ee5cbfSDavid du Colombier nhdr++;
30780ee5cbfSDavid du Colombier }
3086b8ae015SDavid du Colombier if(b->mark == 0 && !b->free)
30980ee5cbfSDavid du Colombier nleak++;
31080ee5cbfSDavid du Colombier nb++;
31180ee5cbfSDavid du Colombier }
31280ee5cbfSDavid du Colombier if(nhdr)
31380ee5cbfSDavid du Colombier c = HdrColor;
31480ee5cbfSDavid du Colombier else if(nlhdr)
31580ee5cbfSDavid du Colombier c = LeakHdrColor;
31680ee5cbfSDavid du Colombier else if(nleak)
31780ee5cbfSDavid du Colombier c = LeakColor;
31880ee5cbfSDavid du Colombier else if(nb)
31980ee5cbfSDavid du Colombier c = AllocColor;
32080ee5cbfSDavid du Colombier else
32180ee5cbfSDavid du Colombier c = FreeColor;
32280ee5cbfSDavid du Colombier //fprint(2, "\t%d\n", c);
32380ee5cbfSDavid du Colombier Bputc(&bio, c);
32480ee5cbfSDavid du Colombier }
32580ee5cbfSDavid du Colombier allocend = allocstart+x*y*resolution;
32680ee5cbfSDavid du Colombier for(; u < allocend; u+=resolution)
32780ee5cbfSDavid du Colombier Bputc(&bio, NoColor);
32880ee5cbfSDavid du Colombier }else{
32959cc4ca5SDavid du Colombier eb = block+nblock;
33059cc4ca5SDavid du Colombier for(b=block; b<eb; b++)
331fb7f0c93SDavid du Colombier if(b->mark == 0 && !b->free)
332d95be1c0SDavid du Colombier 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);
33380ee5cbfSDavid du Colombier }
33459cc4ca5SDavid du Colombier Bterm(&bio);
335*bfb6eab9SDavid du Colombier exits(nil);
33659cc4ca5SDavid du Colombier }
337