xref: /plan9/sys/lib/acid/trump (revision 9a747e4fd48b9f4522c70c07e8f882a15030f964)
1*9a747e4fSDavid du Colombier// trace user malloc pool - trace malloc, realloc, and free calls
2*9a747e4fSDavid du Colombier// if trumpsbrk is set, we trace sbrkalloc and sbrkmerge too.
3*9a747e4fSDavid du Colombier
4*9a747e4fSDavid du Colombier_stoprunning = 0;
5*9a747e4fSDavid du Colombiertrumphexaddrs = 0;
6*9a747e4fSDavid du Colombiertrumpsbrk = 0;
7*9a747e4fSDavid du Colombier
8*9a747e4fSDavid du Colombierdefn stopped(pid) {
9*9a747e4fSDavid du Colombier	local l;
10*9a747e4fSDavid du Colombier	local pc;
11*9a747e4fSDavid du Colombier	pc = *PC;
12*9a747e4fSDavid du Colombier	if notes then {
13*9a747e4fSDavid du Colombier		if (notes[0]!="sys: breakpoint") then
14*9a747e4fSDavid du Colombier		{
15*9a747e4fSDavid du Colombier			print(pid,": ",reason(*TRAP),"\t");
16*9a747e4fSDavid du Colombier			print(fmt(pc,97),"\t",fmt(pc,105),"\n");
17*9a747e4fSDavid du Colombier			print("Notes pending:\n");
18*9a747e4fSDavid du Colombier			l = notes;
19*9a747e4fSDavid du Colombier			while l do
20*9a747e4fSDavid du Colombier			{
21*9a747e4fSDavid du Colombier				print("\t",head l,"\n");
22*9a747e4fSDavid du Colombier				l = tail l;
23*9a747e4fSDavid du Colombier			}
24*9a747e4fSDavid du Colombier			_stoprunning = 1;
25*9a747e4fSDavid du Colombier		}
26*9a747e4fSDavid du Colombier	}
27*9a747e4fSDavid du Colombier}
28*9a747e4fSDavid du Colombier
29*9a747e4fSDavid du Colombierdefn printstack() {
30*9a747e4fSDavid du Colombier	local frame, stk, pcs, lst, x;
31*9a747e4fSDavid du Colombier
32*9a747e4fSDavid du Colombier	pcs = {*PC};
33*9a747e4fSDavid du Colombier	stk = strace(*PC,*SP,0);
34*9a747e4fSDavid du Colombier	while stk do {
35*9a747e4fSDavid du Colombier		pcs = append pcs, stk[0][1];
36*9a747e4fSDavid du Colombier		stk = tail stk;
37*9a747e4fSDavid du Colombier	}
38*9a747e4fSDavid du Colombier
39*9a747e4fSDavid du Colombier	print(" #");
40*9a747e4fSDavid du Colombier	lst = pcs;
41*9a747e4fSDavid du Colombier	while lst do {
42*9a747e4fSDavid du Colombier		if trumphexaddrs != 0 then
43*9a747e4fSDavid du Colombier			x = lst[0]\X;
44*9a747e4fSDavid du Colombier		else
45*9a747e4fSDavid du Colombier			x = lst[0]\a;
46*9a747e4fSDavid du Colombier		print(" src(", x, ");");
47*9a747e4fSDavid du Colombier		lst = tail lst;
48*9a747e4fSDavid du Colombier	}
49*9a747e4fSDavid du Colombier	print("\n");
50*9a747e4fSDavid du Colombier}
51*9a747e4fSDavid du Colombier
52*9a747e4fSDavid du Colombierdefn setuptrump() {
53*9a747e4fSDavid du Colombier	mallocPC = malloc;
54*9a747e4fSDavid du Colombier	malloczPC = mallocz;
55*9a747e4fSDavid du Colombier	freePC = free;
56*9a747e4fSDavid du Colombier	reallocPC = realloc;
57*9a747e4fSDavid du Colombier	sbrkallocPC = sbrkalloc;
58*9a747e4fSDavid du Colombier	sbrkmergePC = sbrkmerge;
59*9a747e4fSDavid du Colombier
60*9a747e4fSDavid du Colombier	// linker might fill delay slot with first instruction
61*9a747e4fSDavid du Colombier	if objtype == "mips" then {
62*9a747e4fSDavid du Colombier		mallocPC = mallocPC+4;
63*9a747e4fSDavid du Colombier		malloczPC = malloczPC+4;
64*9a747e4fSDavid du Colombier		freePC = freePC+4;
65*9a747e4fSDavid du Colombier		reallocPC = reallocPC+4;
66*9a747e4fSDavid du Colombier		sbrkallocPC = sbrkallocPC+4;
67*9a747e4fSDavid du Colombier		sbrkmergePC = sbrkmergePC+4;
68*9a747e4fSDavid du Colombier	}
69*9a747e4fSDavid du Colombier
70*9a747e4fSDavid du Colombier	bpset(mallocPC);
71*9a747e4fSDavid du Colombier	bpset(malloczPC);
72*9a747e4fSDavid du Colombier	bpset(freePC);
73*9a747e4fSDavid du Colombier	bpset(reallocPC);
74*9a747e4fSDavid du Colombier	if trumpsbrk then {
75*9a747e4fSDavid du Colombier		bpset(sbrkallocPC);
76*9a747e4fSDavid du Colombier		bpset(sbrkmergePC);
77*9a747e4fSDavid du Colombier	}
78*9a747e4fSDavid du Colombier}
79*9a747e4fSDavid du Colombier
80*9a747e4fSDavid du Colombierdefn cleantrump() {
81*9a747e4fSDavid du Colombier	stop(pid);
82*9a747e4fSDavid du Colombier
83*9a747e4fSDavid du Colombier	bpdel(mallocPC);
84*9a747e4fSDavid du Colombier	bpdel(malloczPC);
85*9a747e4fSDavid du Colombier	bpdel(freePC);
86*9a747e4fSDavid du Colombier	bpdel(reallocPC);
87*9a747e4fSDavid du Colombier	bpdel(sbrkallocPC);
88*9a747e4fSDavid du Colombier	bpdel(sbrkmergePC);
89*9a747e4fSDavid du Colombier}
90*9a747e4fSDavid du Colombier
91*9a747e4fSDavid du Colombierdefn trumpflush() {
92*9a747e4fSDavid du Colombier	stop(pid);		// already stopped, but flushes output
93*9a747e4fSDavid du Colombier}
94*9a747e4fSDavid du Colombier
95*9a747e4fSDavid du Colombierdefn new() {
96*9a747e4fSDavid du Colombier	bplist = {};
97*9a747e4fSDavid du Colombier	newproc(progargs);
98*9a747e4fSDavid du Colombier	bpset(follow(main)[0]);
99*9a747e4fSDavid du Colombier	cont();
100*9a747e4fSDavid du Colombier	bpdel(*PC);
101*9a747e4fSDavid du Colombier	// clear the hang bit, which is left set by newproc, so programs we fork/exec don't hang
102*9a747e4fSDavid du Colombier	printto("/proc/"+itoa(pid)+"/ctl", "nohang");
103*9a747e4fSDavid du Colombier}
104*9a747e4fSDavid du Colombier
105*9a747e4fSDavid du Colombierdefn trumpfninfo() {
106*9a747e4fSDavid du Colombier	local arg0, arg1, stk, retpc, params;
107*9a747e4fSDavid du Colombier
108*9a747e4fSDavid du Colombier	stk = strace(*PC, *SP, 0);
109*9a747e4fSDavid du Colombier	retpc = stk[0][1];
110*9a747e4fSDavid du Colombier	params = stk[0][2];
111*9a747e4fSDavid du Colombier	arg0 = params[0][1];
112*9a747e4fSDavid du Colombier	arg1 = 0;
113*9a747e4fSDavid du Colombier	if tail params != {} then
114*9a747e4fSDavid du Colombier		arg1 = params[1][1];
115*9a747e4fSDavid du Colombier	return {arg0, arg1, retpc};
116*9a747e4fSDavid du Colombier}
117*9a747e4fSDavid du Colombier
118*9a747e4fSDavid du Colombierdefn trumpretval() {
119*9a747e4fSDavid du Colombier	if objtype=="386" then
120*9a747e4fSDavid du Colombier		return *AX;
121*9a747e4fSDavid du Colombier	if objtype=="mips" then
122*9a747e4fSDavid du Colombier		return *R1;
123*9a747e4fSDavid du Colombier	if objtype=="power" || objtype=="alpha" then
124*9a747e4fSDavid du Colombier		return *R0;
125*9a747e4fSDavid du Colombier}
126*9a747e4fSDavid du Colombier
127*9a747e4fSDavid du Colombierdefn trump() {
128*9a747e4fSDavid du Colombier	local arg0, arg1, pc, ret, x;
129*9a747e4fSDavid du Colombier
130*9a747e4fSDavid du Colombier	stop(pid);
131*9a747e4fSDavid du Colombier	_stoprunning = 0;
132*9a747e4fSDavid du Colombier	setuptrump();
133*9a747e4fSDavid du Colombier	while !_stoprunning do {
134*9a747e4fSDavid du Colombier		cont();
135*9a747e4fSDavid du Colombier		if notes[0]!="sys: breakpoint" then {
136*9a747e4fSDavid du Colombier			cleantrump();
137*9a747e4fSDavid du Colombier			return {};
138*9a747e4fSDavid du Colombier		}
139*9a747e4fSDavid du Colombier
140*9a747e4fSDavid du Colombier		pc = *PC;
141*9a747e4fSDavid du Colombier		x = trumpfninfo();
142*9a747e4fSDavid du Colombier		arg0 = x[0];
143*9a747e4fSDavid du Colombier		if pc == reallocPC || pc == sbrkmergePC then
144*9a747e4fSDavid du Colombier			arg1 = x[1];
145*9a747e4fSDavid du Colombier		bpset(x[2]);
146*9a747e4fSDavid du Colombier		cont();
147*9a747e4fSDavid du Colombier		bpdel(x[2]);
148*9a747e4fSDavid du Colombier		ret = trumpretval();
149*9a747e4fSDavid du Colombier		if pc == mallocPC then
150*9a747e4fSDavid du Colombier			print(ret\X, " malloc ", arg0\D);
151*9a747e4fSDavid du Colombier		if pc == malloczPC then
152*9a747e4fSDavid du Colombier			print(ret\X, " mallocz ", arg0\D);
153*9a747e4fSDavid du Colombier		if pc == freePC then
154*9a747e4fSDavid du Colombier			print(arg0\X, " free");
155*9a747e4fSDavid du Colombier		if pc == reallocPC then
156*9a747e4fSDavid du Colombier			print(ret\X, " realloc ", arg0\X, " ", arg1\D);
157*9a747e4fSDavid du Colombier		if pc == sbrkallocPC then
158*9a747e4fSDavid du Colombier			print(ret\X, " sbrkalloc ", arg0\D);
159*9a747e4fSDavid du Colombier		if pc == sbrkmergePC then
160*9a747e4fSDavid du Colombier			print("sbrkmerge ", arg0\X, " ", arg1\X, " = ", ret\D);
161*9a747e4fSDavid du Colombier		printstack();
162*9a747e4fSDavid du Colombier		trumpflush();
163*9a747e4fSDavid du Colombier	}
164*9a747e4fSDavid du Colombier}
165*9a747e4fSDavid du Colombier
166*9a747e4fSDavid du Colombierdefn untrump() {
167*9a747e4fSDavid du Colombier	cleantrump();
168*9a747e4fSDavid du Colombier	start(pid);
169*9a747e4fSDavid du Colombier}
170*9a747e4fSDavid du Colombier
171*9a747e4fSDavid du Colombierprint("/sys/lib/acid/trump");
172