| // |
| // usage: acid -l pool -l leak |
| // |
| include("/sys/src/libc/port/pool.acid"); |
| |
| defn |
| dumppool(p) |
| { |
| complex Pool p; |
| a = p.arenalist; |
| |
| while a != 0 && a < 0x60000000 do { |
| complex Arena a; |
| dumparena(a); |
| a = a.down; |
| } |
| } |
| |
| defn |
| dumparena(arena) |
| { |
| local atail, b, nb; |
| |
| atail = A2TB(arena); |
| complex Bhdr arena; |
| b = a; |
| while b < atail && b.magic != ARENATAIL_MAGIC do { |
| dumpblock(b); |
| 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 != KEMPT_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 0x7efff000 <= a && a < 0x7ffff000 then |
| return 1; |
| return 0; |
| } |
| |
| defn |
| dumpblock(addr) |
| { |
| complex Bhdr addr; |
| |
| if addr.magic == KEMPT_MAGIC || addr.magic == FREE_MAGIC then { |
| local a, x, s; |
| |
| a = addr; |
| complex Alloc a; |
| |
| x = addr+8; |
| if addr.magic == KEMPT_MAGIC then |
| s = "block"; |
| else |
| s = "free"; |
| print(s, " ", addr\X, " ", a.size\X, " "); |
| print(*(addr+8)\X, " ", *(addr+12)\X, "\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; |
| if isptr(y) then print("data ", x\X, " ", y\X, " ", type, "\n"); |
| x = x + 4; |
| } |
| } |
| |
| defn |
| dumpmem() |
| { |
| local s; |
| |
| xbloc = *bloc; |
| // assume map()[1] is "data" |
| dumprange(map()[1][1], end, "bss"); // bss |
| dumprange(end, xbloc, "alloc"); // allocated |
| |
| if 0x7efff000 < *SP && *SP < 0x7ffff000 then |
| s = *SP; |
| else |
| s = 0x7fff7000; // 32 k |
| |
| dumprange(s, 0x7ffff000, "stack"); |
| } |
| |
| defn |
| dumpregs() |
| { |
| dumprange(0, sizeofUreg, "reg"); |
| } |
| |
| |
| defn |
| leakdump(l) |
| { |
| print("==LEAK BEGIN==\n"); |
| dumppool(sbrkmem); |
| dumpmem(); |
| dumpregs(); |
| while l != {} do { |
| setproc(head l); |
| dumpregs(); |
| l = tail l; |
| } |
| print("==LEAK END==\n"); |
| } |
| |
| defn |
| blockdump() |
| { |
| print("==BLOCK BEGIN==\n"); |
| dumppool(sbrkmem); |
| print("==BLOCK END==\n"); |
| } |