12 sysfatal("malloc %lud fails", sz);
18 erealloc(void *v, ulong sz)
22 sysfatal("realloc %lud fails", sz);
33 sysfatal("strdup fails");
37 typedef struct Block Block;
38 typedef struct Data Data;
68 addrcmp(void *va, void *vb)
91 if(block[m].addr < addr)
93 else if(addr < block[m].addr)
111 if(data[m].addr < addr)
113 else if(addr < data[m].addr)
118 if(0 <= lo && lo < ndata)
126 markblock(ulong from, ulong fromval, Block *b)
133 //print("trace 0x%.8lux from 0x%.8lux (%d)\n", b->addr, from, b->mark);
135 // fprint(2, "possible dangling pointer *0x%.8lux = 0x%.8lux\n", from, fromval);
143 if(d = finddata(b->addr)) {
144 assert(d->addr >= b->addr);
146 top = b->addr+b->size;
147 for(; d < edata && d->addr < top; d++) {
150 if((nb = findblock(d->val-8)) || (nb = findblock(d->val-8-8)))
151 markblock(d->addr, d->val, nb);
159 AllocColor = 2, // dark blue: completely allocated region
160 HdrColor = 54, // bright blue: region with header
161 LeakColor = 205, // dark red: region with leak
162 LeakHdrColor = 240, // bright red: region with leaked header
163 FreeColor = 252, // bright yellow: completely free region
164 NoColor = 255, // padding, white
168 rXr(int as, int ae, int bs, int be)
170 return bs < ae && as < be;
174 main(int argc, char **argv)
178 int bitmap, c, nf, resolution, n8, n16, hdr, nhdr, nlhdr, nleak, x, y, nb;
179 ulong allocstart, allocend, len, u;
191 resolution = atoi(EARGF(sysfatal("usage")));
194 x = atoi(EARGF(sysfatal("usage")));
199 allocstart = allocend = 0;
200 Binit(&bio, 0, OREAD);
201 while(p=Brdline(&bio, '\n')) {
202 p[Blinelen(&bio)-1] = '\0';
203 nf = tokenize(p, f, nelem(f));
204 if(nf >= 4 && strcmp(f[0], "data") == 0) {
209 adata += adata / 4; /* increase 25% */
210 data = erealloc(data, adata * sizeof(Data));
212 data[ndata].addr = strtoul(f[1], nil, 0);
213 data[ndata].val = strtoul(f[2], nil, 0);
214 data[ndata].type = f[3][0];
219 (strcmp(f[0], "block") == 0 || strcmp(f[0], "free") == 0)) {
220 if(nblock >= ablock){
224 ablock += ablock / 4; /* increase 25% */
225 block = erealloc(block, ablock * sizeof(Block));
227 block[nblock].addr = strtoul(f[1], nil, 0);
228 block[nblock].size = strtoul(f[2], nil, 0);
229 block[nblock].w0 = strtoul(f[3], nil, 0);
230 block[nblock].w1 = strtoul(f[4], nil, 0);
232 block[nblock].s0 = estrdup(f[5]);
233 block[nblock].s1 = estrdup(f[6]);
235 block[nblock].s0 = "";
236 block[nblock].s1 = "";
238 block[nblock].mark = 0;
240 block[nblock].free = strcmp(f[0], "free") == 0;
243 if(nf >= 4 && strcmp(f[0], "range") == 0 && strcmp(f[1], "alloc") == 0) {
244 allocstart = strtoul(f[2], 0, 0)&~15;
245 allocend = strtoul(f[3], 0, 0);
249 qsort(block, nblock, sizeof(Block), addrcmp);
250 qsort(data, ndata, sizeof(Data), addrcmp);
252 ed = edata = data+ndata;
253 for(d=data; d<ed; d++) {
256 if(b = findblock(d->val-8)) // pool header 2 words
257 n8 += markblock(d->addr, d->val, b);
258 else if(b = findblock(d->val-8-8)) // sometimes malloc header 2 words
259 n16 += markblock(d->addr, d->val, b);
261 {}//print("noblock %.8lux\n", d->val);
264 Binit(&bio, 1, OWRITE);
266 if(n8 > n16) // guess size of header
271 for(d=data; d<ed; d++)
275 sysfatal("no allocated data region");
277 len = (allocend-allocstart+resolution-1)/resolution;
279 Bprint(&bio, "%11s %11d %11d %11d %11d ", "m8", 0, 0, x, y);
281 //fprint(2, "alloc %lux %lux x %d y %d res %d\n", allocstart, allocend, x, y, resolution);
285 for(u = allocstart; u<allocend; u+=resolution){
286 //fprint(2, "u %lux %lux baddr %lux\n", u, u+resolution, b->addr);
287 while(b->addr+b->size <= u && b < eb)
289 //fprint(2, "\tskip %lux %lux\n", b->addr, b->addr+b->size);
296 if(block < b && u < (b-1)->addr+(b-1)->size)
299 for(; b->addr < u+resolution && b < eb; b++){
300 //fprint(2, "\tblock %lux %lux %d\n", b->addr, b->addr+b->size, b->mark);
301 if(rXr(b->addr, b->addr+hdr, u, u+resolution)
302 || rXr(b->addr+b->size-8, b->addr+b->size, u, u+resolution)){
303 if(b->mark == 0 && !b->free)
324 //fprint(2, "\t%d\n", c);
327 allocend = allocstart+x*y*resolution;
328 for(; u < allocend; u+=resolution)
329 Bputc(&bio, NoColor);
332 for(b=block; b<eb; b++)
333 if(b->mark == 0 && !b->free)
334 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);