plan9fox/sys/lib/acid/leak

215 lines
3.5 KiB
Plaintext

//
// usage: acid -l pool -l leak
//
include("/sys/src/libc/port/pool." + objtype + ".acid");
defn
dumppool(p, sum)
{
complex Pool p;
a = p.arenalist;
allocsize = 0;
print("A: ", p.arenalist\A, "\n");
while a != 0 do {
complex Arena a;
dumparena(a, sum);
a = a.down;
}
if sum then {
emitsum();
}
if allocsize != p.curalloc then {
print("found alloc size mismatch ", allocsize, " != ", p.curalloc, "\n");
}
}
defn
dumparena(arena, sum)
{
local atail, b, nb;
atail = A2TB(arena);
complex Bhdr arena;
b = a;
print("B: ", b\A, " ", atail\A, "\n");
while b < atail && b.magic != ARENATAIL_MAGIC do {
dumpblock(b, sum);
nb = B2NB(b);
if nb == b then {
print("B2NB(", b\A, ") = b\n");
b = atail; // end loop
} else if nb > atail then {
b = (Bhdr)(b+4);
print("lost at block ", (b-4)\A, ", scanning forward\n");
while b < atail && b.magic != ALLOC_MAGIC && b.magic != FREE_MAGIC do
b = (Bhdr)(b+4);
print("stopped at ", b\A, " ", *b\A, "\n");
}else
b = nb;
}
if b != atail then
print("found wrong tail to arena ", arena\A, " wanted ", atail\A, "\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
sxpc(addr)
{
if objtype == "amd64" && addr & 0x80000000 then {
return addr | 0xffffffff00000000;
}
return addr;
}
defn
dumpblock(addr, sum)
{
complex Bhdr addr;
if addr.magic == ALLOC_MAGIC || (!sum && addr.magic == FREE_MAGIC) then {
local a, x, s, allocpc, reallocpc;
a = addr;
complex Alloc a;
x = fmt(addr+sizeofBhdr, 'X');
if addr.magic == ALLOC_MAGIC then {
allocsize = allocsize+a.size;
// for mallocalign()
while *x == ALIGN_MAGIC do {
x = x + 4;
}
}
allocpc=sxpc(x[0]);
reallocpc=sxpc(x[1]);
if sum then {
if allocpc != lastalloc then {
emitsum();
lastalloc = allocpc;
}
lastcount = lastcount+1;
lastsize = lastsize+a.size;
}else{
if addr.magic == ALLOC_MAGIC then {
s = "block";
} else
s = "free";
print(s, " ", addr\A, " ", a.size\X, " ");
print(x[0]\X, " ", x[1]\X, " ", allocpc\a, " ", reallocpc\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);
print("==BLOCK END==\n");
}
print("/sys/lib/acid/leak");