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