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