189 lines
3.0 KiB
Plaintext
189 lines
3.0 KiB
Plaintext
//
|
|
// 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");
|
|
}
|