summaryrefslogtreecommitdiff
path: root/sys/lib/acid/leak
blob: 7469287a2730c740c75fb5c808de62edbf5d2c03 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
//
// usage: acid -l pool -l leak
//
include("/sys/src/libc/port/pool.acid");

defn
dumppool(p, sum)
{
	complex Pool p;
	a = p.arenalist;

	print("A: ", p.arenalist\X, "\n");
	while a != 0 && a < 0xff000000 do {
		complex Arena a;
		dumparena(a, sum);
		a = a.down;
	}
}

defn
dumparena(arena, sum)
{
	local atail, b, nb;

	atail = A2TB(arena);
	complex Bhdr arena;
	b = a;
	print("B: ", b\X, " ", atail\X, "\n");
	while b < atail && b.magic != ARENATAIL_MAGIC do {
		dumpblock(b, sum);
		nb = B2NB(b);
		if nb == b then {
			print("B2NB(", b\X, ") = b\n");
			b = atail;	// end loop
		}
		if nb > atail then {
			b = (Bhdr)(b+4);
			print("lost at block ", (b-4)\X, ", scanning forward\n");
			while b < atail && b.magic != ALLOC_MAGIC && b.magic != FREE_MAGIC do
				b = (Bhdr)(b+4);
			print("stopped at ", b\X, " ", *b\X, "\n");
		}else
			b = nb;
	}
	if b != atail then
		print("found wrong tail to arena ", arena\X, " wanted ", atail\X, "\n");
}

defn
isptr(a)
{
	if end <= a && a < xbloc then
		return 1;
	if 0xdefff000 <= a && a < 0xdffff000 then
		return 1;
	return 0;
}

lastalloc = 0;
lastcount = 0;
lastsize = 0;
defn
emitsum()
{
	if lastalloc then
		print("summary ", lastalloc\a, " ", lastcount\D, " ", lastsize\D, "\n");
	lastalloc = 0;
	lastcount = 0;
	lastsize = 0;
}

defn
dumpblock(addr, sum)
{
	complex Bhdr addr;

	if addr.magic == ALLOC_MAGIC || (!sum && addr.magic == FREE_MAGIC) then {
		local a, x, s;

		a = addr;
		complex Alloc a;

		x = addr+8;
		if sum then {
			if *(addr+8) != lastalloc then {
				emitsum();
				lastalloc = *(addr+8);
			}
			lastcount = lastcount+1;
			lastsize = lastsize+a.size;
		}else{
			if addr.magic == ALLOC_MAGIC then
				s = "block";
			else
				s = "free";
			print(s, " ", addr\X, " ", a.size\X, " ");
			print(*(addr+8)\X, " ", *(addr+12)\X, " ",
				*(addr+8)\a, " ", *(addr+12)\a, "\n");
		}
	}
}

defn
dumprange(s, e, type)
{
	local x, y;

	print("range ", type, " ", s\X, " ", e\X, "\n");
	x = s;
	while x < e do {
		y = *(x\X);
		if isptr(y) then print("data ", x\X, " ", y\X, " ", type, "\n");
		x = x + 4;
	}
}

defn
stacktop()
{
	local e, m;
	
	m = map();
	while m != {} do {
		e = head m;
		if e[0] == "*data" then
			return e[2];
		m = tail m;
	}
	return 0xdffff000;
}
			
defn
dumpmem()
{
	local s, top;

	xbloc = *bloc;
	// assume map()[1] is "data" 
	dumprange(map()[1][1], end, "bss");	// bss
	dumprange(end, xbloc, "alloc");	// allocated

	top = stacktop() - 8;
	if top-0x01000000 < *SP && *SP < top then
		s = *SP;
	else
		s = top-32*1024;

	dumprange(s, top, "stack");
}

defn
dumpregs()
{
	dumprange(0, sizeofUreg, "reg");
}


defn
leakdump(l)
{
	print("==LEAK BEGIN==\n");
	dumppool(*mainmem, 0);
	dumpmem();
	dumpregs();
	while l != {} do {
		setproc(head l);
		dumpregs();
		l = tail l;
	}
	print("==LEAK END==\n");
}

defn
blockdump()
{
	print("==BLOCK BEGIN==\n");
	dumppool(*mainmem, 0);
	print("==BLOCK END==\n");
}

defn
blocksummary()
{
	print("==BLOCK BEGIN==\n");
	dumppool(*mainmem, 1);
	emitsum();
	print("==BLOCK END==\n");
}