Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include <u.h>
2
#include <libc.h>
3
#include <bio.h>
4
 
5
void*
6
emalloc(ulong sz)
7
{
8
	void *v;
9
 
10
	v = malloc(sz);
11
	if(v == nil)
12
		sysfatal("malloc %lud fails", sz);
13
	memset(v, 0, sz);
14
	return v;
15
}
16
 
17
void*
18
erealloc(void *v, ulong sz)
19
{
20
	v = realloc(v, sz);
21
	if(v == nil)
22
		sysfatal("realloc %lud fails", sz);
23
	return v;
24
}
25
 
26
char*
27
estrdup(char* s)
28
{
29
	char *r;
30
 
31
	r = strdup(s);
32
	if(r == nil)
33
		sysfatal("strdup fails");
34
	return r;
35
}
36
 
37
typedef struct Block Block;
38
typedef struct Data Data;
39
struct Block {
40
	ulong addr;
41
	ulong size;
42
	ulong w0;
43
	ulong w1;
44
	char *s0;
45
	char *s1;
46
	int mark;
47
	int free;
48
	Data *d;
49
};
50
 
51
struct Data {
52
	ulong addr;
53
	ulong val;
54
	uchar type;
55
	Block *b;
56
};
57
 
58
Block *block;
59
uint nblock;
60
uint ablock;
61
 
62
Data *data;
63
Data *edata;
64
uint ndata;
65
uint adata;
66
 
67
int
68
addrcmp(void *va, void *vb)
69
{
70
	ulong *a, *b;
71
 
72
	a = va;
73
	b = vb;
74
	if(*a < *b)
75
		return -1;
76
	if(*a > *b)
77
		return 1;
78
	return 0;
79
}
80
 
81
Block*
82
findblock(ulong addr)
83
{
84
	int lo, hi, m;
85
 
86
	lo = 0;
87
	hi = nblock;
88
 
89
	while(lo < hi) {
90
		m = (lo+hi)/2;
91
		if(block[m].addr < addr)
92
			lo = m+1;
93
		else if(addr < block[m].addr)
94
			hi = m;
95
		else
96
			return &block[m];
97
	}
98
	return nil;
99
}
100
 
101
Data*
102
finddata(ulong addr)
103
{
104
	int lo, hi, m;
105
 
106
	lo = 0;
107
	hi = ndata;
108
 
109
	while(lo < hi) {
110
		m = (lo+hi)/2;
111
		if(data[m].addr < addr)
112
			lo = m+1;
113
		else if(addr < data[m].addr)
114
			hi = m;
115
		else
116
			return &data[m];
117
	}
118
	if(0 <= lo && lo < ndata)
119
		return &data[lo];
120
	return nil;
121
}
122
 
123
int nmark;
124
 
125
int
126
markblock(ulong from, ulong fromval, Block *b)
127
{
128
	Data *d;
129
	ulong top;
130
	Block *nb;
131
 
132
USED(from, fromval);
133
//print("trace 0x%.8lux from 0x%.8lux (%d)\n", b->addr, from, b->mark);
134
	if(b->free){
135
	//	fprint(2, "possible dangling pointer *0x%.8lux = 0x%.8lux\n", from, fromval);
136
		return 0;
137
	}
138
	if(b->mark)
139
		return 0;
140
	b->mark = 1;
141
	nmark++;
142
 
143
	if(d = finddata(b->addr)) {
144
		assert(d->addr >= b->addr);
145
		b->d = d;
146
		top = b->addr+b->size;
147
		for(; d < edata && d->addr < top; d++) {
148
			assert(d->b == 0);
149
			d->b = b;
150
			if((nb = findblock(d->val-8)) || (nb = findblock(d->val-8-8)))
151
				markblock(d->addr, d->val, nb);
152
		}
153
		return 1;
154
	}
155
	return 0;
156
}
157
 
158
enum {
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
165
};
166
 
167
int
168
rXr(int as, int ae, int bs, int be)
169
{
170
	return bs < ae && as < be;
171
}
172
 
173
void
174
main(int argc, char **argv)
175
{
176
	Biobuf bio;
177
	char *p, *f[10];
178
	int bitmap, c, nf, resolution, n8, n16, hdr, nhdr, nlhdr, nleak, x, y, nb;
179
	ulong allocstart, allocend, len, u;
180
	Data *d, *ed;
181
	Block *b, *eb;
182
 
183
	bitmap = 0;
184
	resolution = 8;
185
	x = 512;
186
	ARGBEGIN{
187
	case 'b':
188
		bitmap=1;
189
		break;
190
	case 'r':
191
		resolution = atoi(EARGF(sysfatal("usage")));
192
		break;
193
	case 'x':
194
		x = atoi(EARGF(sysfatal("usage")));
195
		break;
196
	}ARGEND
197
 
198
	n8 = n16 = 0;
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) {
205
			if(ndata >= adata){
206
				if(adata == 0)
207
					adata = 4096;
208
				else
209
					adata += adata / 4;  /* increase 25% */
210
				data = erealloc(data, adata * sizeof(Data));
211
			}
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];
215
			data[ndata].b = 0;
216
			ndata++;
217
		}
218
		if(nf >= 5 &&
219
		    (strcmp(f[0], "block") == 0 || strcmp(f[0], "free") == 0)) {
220
			if(nblock >= ablock){
221
				if(ablock == 0)
222
					ablock = 4096;
223
				else
224
					ablock += ablock / 4; /* increase 25% */
225
				block = erealloc(block, ablock * sizeof(Block));
226
			}
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);
231
			if (nf >= 7) {
232
				block[nblock].s0 = estrdup(f[5]);
233
				block[nblock].s1 = estrdup(f[6]);
234
			} else {
235
				block[nblock].s0 = "";
236
				block[nblock].s1 = "";
237
			}
238
			block[nblock].mark = 0;
239
			block[nblock].d = 0;
240
			block[nblock].free = strcmp(f[0], "free") == 0;
241
			nblock++;
242
		}
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);
246
		}
247
	}
248
 
249
	qsort(block, nblock, sizeof(Block), addrcmp);
250
	qsort(data, ndata, sizeof(Data), addrcmp);
251
 
252
	ed = edata = data+ndata;
253
	for(d=data; d<ed; d++) {
254
		if(d->type == 'a')
255
			continue;
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);
260
		else
261
			{}//print("noblock %.8lux\n", d->val);
262
	}
263
 
264
	Binit(&bio, 1, OWRITE);
265
	if(bitmap){
266
		if(n8 > n16)		// guess size of header
267
			hdr = 8;
268
		else
269
			hdr = 16;
270
 
271
		for(d=data; d<ed; d++)
272
			if(d->type=='a')
273
				break;
274
		if(d==ed)
275
			sysfatal("no allocated data region");
276
 
277
		len = (allocend-allocstart+resolution-1)/resolution;
278
		y = (len+x-1)/x;
279
		Bprint(&bio, "%11s %11d %11d %11d %11d ", "m8", 0, 0, x, y);
280
 
281
//fprint(2, "alloc %lux %lux x %d y %d res %d\n", allocstart, allocend, x, y, resolution);
282
 
283
		b = block;
284
		eb = block+nblock;
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)
288
//{
289
//fprint(2, "\tskip %lux %lux\n", b->addr, b->addr+b->size);
290
				b++;
291
//}
292
			nhdr = 0;
293
			nleak = 0;
294
			nb = 0;
295
			nlhdr = 0;
296
			if(block < b && u < (b-1)->addr+(b-1)->size)
297
				b--;
298
 
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)
304
						nlhdr++;
305
					else
306
						nhdr++;
307
				}
308
				if(b->mark == 0 && !b->free)
309
					nleak++;
310
				nb++;
311
			}
312
			if(nhdr)
313
				c = HdrColor;
314
			else if(nlhdr)
315
				c = LeakHdrColor;
316
			else if(nleak)
317
				c = LeakColor;
318
			else if(nb)
319
				c = AllocColor;
320
			else
321
				c = FreeColor;
322
//fprint(2, "\t%d\n", c);
323
			Bputc(&bio, c);
324
		}
325
		allocend = allocstart+x*y*resolution;
326
		for(; u < allocend; u+=resolution)
327
			Bputc(&bio, NoColor);
328
	}else{
329
		eb = block+nblock;
330
		for(b=block; b<eb; b++)
331
			if(b->mark == 0 && !b->free)
332
				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);
333
	}
334
	Bterm(&bio);
335
	exits(nil);
336
}