Subversion Repositories planix.SVN

Rev

Blame | Last modification | View Log | RSS feed

//
// 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");
}