]> git.lizzy.rs Git - plan9front.git/blob - sys/lib/acid/kernel
acid/kernel: for stacktraces, try to use context from error stack when process is...
[plan9front.git] / sys / lib / acid / kernel
1 include("/sys/lib/acid/syscall");
2
3 // print various /proc files
4 defn fd() {
5         rc("cat /proc/"+itoa(pid)+"/fd");
6 }
7
8 defn segment() {
9         rc("cat /proc/"+itoa(pid)+"/segment");
10 }
11
12 defn ns() {
13         rc("cat /proc/"+itoa(pid)+"/ns");
14 }
15
16 defn qid(qid) {
17         complex Qid qid;
18         return itoa(qid.path\X)+"."+itoa(qid.vers\X);
19 }
20
21 defn path(p) {
22         complex Path p;
23         if p != 0 then {
24                 return *(p.s\s);
25         } else
26                 return "<null>";
27 }
28
29 // print Image cache contents
30 IHASHSIZE = 64;
31
32 defn imagecacheline(h) {
33         local d, p, q;
34
35         while h != 0 do {
36                 complex Image h;
37
38                 d=(Dev)devtab[h.type];
39                 p = "*closed*";
40                 if h.c != 0 then
41                         p = path(h.c.path);
42                 q = h.qid;
43                 print (h\A, " ref=", h.ref, " pgref=", h.pgref, "\t#", d.dc\r, h.dev\D, " (",
44                         q.path, " ", q.vers\D, " ", q.type\X, ") ", p, "\n");
45                 h = h.hash;
46         }
47 }
48
49 defn imagecache() {
50         local i;
51
52         i=0; loop 1,IHASHSIZE do {
53                 imagecacheline(imagealloc.hash[i]);
54                 i = i+1;
55         }
56 }
57
58 defn qiostats() {
59         print ("padblockcnt=", *padblockcnt\D, "\n");
60         print ("concatblockcnt=", *concatblockcnt\D, "\n");
61         print ("pullupblockcnt=", *pullupblockcnt\D, "\n");
62         print ("copyblockcnt=", *copyblockcnt\D, "\n");
63         print ("consumecnt=", *consumecnt\D, "\n");
64         print ("producecnt=", *producecnt\D, "\n");
65 }
66
67 // dump channels
68 defn chan(c) {
69         local d, q;
70
71         c = (Chan)c;
72         d= (Dev)devtab[c.type];
73         q=c.qid;
74         print("chan(", c\A, "): ref=", c.ref\D, " #", d.dc\r, c.dev\D, " (", q.path, " ", q.vers\D, " ", q.type\X, ")");
75         print(" fid=", c.fid\D, " iounit=", c.iounit\D);
76         if c.ref != 0 then {
77                 print(" ", path(c.path), " mchan=", c.mchan\A);
78                 if c.mchan != 0 then {
79                         print(" ", path(c.mchan.path));
80                 }
81         }
82         print("\n");
83 }
84
85 defn chans() {
86         local c;
87
88         c = (Chan)chanalloc.list;
89         while c != 0 do {
90                 if c.ref != 0 then
91                         chan(c);
92                 c=(Chan)c.link;
93         }
94 }
95
96 defn findchan(dev,type,path) {
97         local c;
98
99         c = (Chan)chanalloc.list;
100         while c != 0 do {
101                 if c.ref != 0 then {
102                         if c.dev == dev && c.type == type && c.qid.path == path then
103                                 return c;
104                 }
105                 c=(Chan)c.link;
106         }
107         return 0;
108 }
109
110 defn nchans() {
111         local c, n;
112         
113         n = 0;
114         c = (Chan)chanalloc.list;
115         while c != 0 do {
116                 if c.ref != 0 then
117                         n++;
118                 c = (Chan)c.link;
119         }
120         return n;
121 }
122
123 defn activechanlist() {
124         local l, n;
125         
126         l = {};
127         c = (Chan)chanalloc.list;
128         while c != 0 do {
129                 if c.ref != 0 then
130                         l = append l,c;
131                 c = (Chan)c.link;
132         }
133         return l;
134 }
135
136 defn difflist(a, b) {
137         local l, x;
138         
139         l = {};
140         while a != {} do {
141                 x = head a;
142                 if match(x, b) == -1 then
143                         l = append l, x;
144                 a = tail a;
145         }
146         return l;
147 }
148
149 _active_chan_list = {};
150 defn newchans() {
151         local l, new;
152         
153         l = activechanlist();
154         if _active_chan_list != {} then
155                 newerchans(_active_chan_list);
156         _active_chan_list = l;
157 }
158
159 defn newerchans(oldlist){
160         local new;
161         
162         new = difflist(activechanlist(), oldlist);
163         while new != {} do {
164                 chan(head new);
165                 new = tail new;
166         }
167 }
168
169 // look for channels that refer to themselves
170 defn badchans() {
171         local bad, c, i, len, mtpt, p;
172         
173         c = (Chan)chanalloc.list;
174         while c != 0 do {
175                 if c.ref != 0 then {
176                         bad = "";
177                         p = (Path)c.path;
178                         if p != 0 then {
179                                 path(p);
180                                 mtpt = p.mtpt;
181                                 len = p.mlen;
182                                 i=0; loop 1,len do {
183                                         if mtpt[i] == c then
184                                                 bad = bad+" mtpt self-ref";
185                                         i = i+1;
186                                 }
187                         }
188                         if bad != "" then
189                                 print("chan(", c\A, "):", bad, "\n");
190                 }
191                 c = (Chan)c.link;
192         }
193 }
194
195 NHASH=128;
196 defn mntcache() {
197         local i, m, c;
198
199         i=0; loop 1,NHASH do {
200                 m = cache.hash[i];
201                 while m != 0 do {
202                         complex Mntcache m;
203                         print(m\A, " dev ", m.dev\D, " type ", m.type, " qid (", 
204                                 m.qid.path, " ", m.qid.vers\D, ")\n");
205                         c = findchan(m.dev, m.type, m.qid.path);
206                         if c != 0 then {
207                                 print(" ");
208                                 chan(c);
209                         }
210                         m = m.hash;
211                 }
212                 i = i+1;
213         }
214 }
215
216 // manipulate processes
217 defn proctab(x) {
218         return procalloc.arena+sizeofProc*x;
219 }
220
221 defn proc(p) {
222         complex Proc p;
223         local s, i;
224
225         if p.state != 0 && p.pid != 0 && p.text != 0 then {     // 0 is Dead
226                 s = p.psstate;
227                 if s == 0 then {
228                         s = "kproc";
229                 } else {
230                         s = *(s\s);
231                 }
232                 print(p\A, " ", p.pid, ": ", *(p.text\s), " ", *(p.user\s), " pc ", p.pc, " ", s, " (", *(statename[p.state]\s), ") ut ", p.time[0]\D, " st ", p.time[1]\D, " qpc ", p.qpc, "\n");
233         }
234 }
235
236 defn procenv(p) {
237         complex Proc p;
238         local i, e, v;
239
240         e = p.egrp;
241         complex Egrp e;
242         i=0; loop 1,e.nent do {
243                 v = e.ent + i;
244                 i = i+sizeofEvalue;
245                 complex Evalue v;
246                 print(*(v.name\s), "=");
247                 printstringn(v.value, v.len);
248                 print("\n");
249         }
250 }
251 BY2PG=4096;
252 KSTACK=4096;
253 if objtype=="amd64" then {
254         KSTACK=16*1024;
255 }
256 if objtype=="arm64" then {
257         BY2PG=65536;
258         KSTACK=8*1024;
259 }
260
261 defn procstksize(p) {
262         complex Proc p;
263         local top, sp;
264
265         if p.state != 0 then {  // 0 is Dead
266                 top = p.kstack+KSTACK;
267                 sp = *p.sched;
268                 print(top-sp\D, "\n");
269         }
270 }
271
272 defn procstk(p) {
273         complex Proc p;
274         local l, n;
275
276         if p.state != 0 then {  // 0 is Dead
277                 if p.mach == 0 then {
278                         l = p.sched;
279                 } else {
280                         n = p.nerrlab;
281                         if n == 0 then {
282                                 return 0;
283                         }
284                         l = p.errlab + (n-1)*sizeofLabel;
285                 }
286                 complex Label l;
287                 if objtype=="386" || objtype=="amd64" then
288                         _stk(gotolabel, l.sp, linkreg(0), 0);
289                 else
290                         _stk(l.pc, l.sp, linkreg(0), 0);
291         }
292 }
293
294 defn procs() {
295         local i;
296
297         i=0; loop 1,conf.nproc do {
298                 proc(proctab(i));
299                 i = i+1;
300         }
301 }
302
303 defn stacks() {
304         local i, p;
305
306         i=0; loop 1,conf.nproc do {
307                 p = (Proc)proctab(i);
308                 if p.state != 0 then {
309                         print("=========================================================\n");
310                         proc(p);
311                         procstk(p);
312                 }
313                 i = i+1;
314         }
315 }
316
317 defn stacksizes() {
318         local i;
319
320         i=0; loop 1,conf.nproc do {
321                 procstksize(proctab(i));
322                 i = i+1;
323         }
324 }
325
326 // segment-related
327 defn procsegs(p) {
328         complex Proc p;
329         local i;
330
331         i=0; loop 1,NSEG do {
332                 psegment(p.seg[i]);
333                 i = i+1;
334         }
335 }
336
337 segtypes = { "text", "data", "bss", "stack", "shared", "physical", "shdata", "map" };
338 defn psegment(s) {
339         complex Segment s;
340
341         if s != 0 then {
342                 print(s\A, " ", segtypes[s.type&SG_TYPE], " ", s.base, "-", s.top, " image ", s.image, "\n");
343         }
344 }
345
346 // find physical address for an address in a given process
347 defn procaddr(p, a) {
348         complex Proc p;
349         local i, s, r;
350
351         r = 0;
352         i=0; loop 1,NSEG do {
353                 s = p.seg[i];
354                 if s != 0 then {
355                         complex Segment s;
356                         if s.base <= a && a < s.top then {
357                                 r = segaddr(s, a);
358                         }
359                 }
360                 i = i+1;
361         }
362         return r;
363 }
364
365 // find an address in a given segment
366 defn segaddr(s, a) {
367         complex Segment s;
368         local pte, pg;
369
370         a = a - s.base;
371         if s.map == 0 || s.mapsize < a/PTEMAPMEM then {
372                 return 0;
373         }
374
375         pte = s.map[a/PTEMAPMEM];
376         if pte == 0 then {
377                 return 0;
378         }
379
380         complex Pte pte;
381         pg = pte.pages[(a%PTEMAPMEM)/BY2PG];
382         if pg == 0 then {
383                 return 0;
384         }
385
386         if pg & 1 then {        // swapped out, return disk address
387                 return pg&~1;
388         }
389
390         complex Page pg;
391         return (KZERO|(pg.pa+(a%BY2PG)))\A;
392 }
393
394 defn kzero() {
395         return main - (main & 0x0FFFFFFF);
396 }
397
398 PTEMAPMEM = (1024*1024);
399 PTEPERTAB = (PTEMAPMEM/BY2PG);
400 defn up() {
401         if objtype == "386" then {
402                 local mach;
403
404                 MACHADDR = KZERO+0x15000;
405                 mach = MACHADDR;
406                 complex Mach mach;
407                 return mach.externup;
408         }
409         if objtype == "amd64" then {
410                 local proc;
411
412                 proc = *R14;
413                 complex Proc proc;
414                 return proc;
415         }
416         if objtype == "arm64" then {
417                 local proc;
418
419                 proc = *R26;
420                 complex Proc proc;
421                 return proc;
422         }
423         print("up() not implemented for", objtype, "\n");
424         return -1;
425 }
426
427 defn intrcount() {
428         local p, t, i, j;
429
430         p = intrtimes\X;
431         i=0; loop 1,256 do {
432                 t=0;
433                 j=0; loop 1,20 do {
434                         t = t+*p++;
435                         j=j+1;
436                 }
437                 if t != 0 then {
438                         print(itoa(i, "%5d"), " ", itoa(t, "%11d"), "\n");
439                 }
440                 i=i+1;
441         }
442 }
443
444 defn needacid(s){
445         print("\trc(\"cd /sys/src/9/", kdir, "; mk ", s, ".acid\")\n");
446         print("\tinclude(\"/sys/src/9/", kdir, "/", s, ".acid\")\n");
447 }
448
449 defn kinit() {
450 if (map()[2]) != {} then {      // map has more than two elements -> active proc
451         kdir = "unknown";
452         KZERO = kzero();
453         
454         if objtype == "386" then {
455                 map({"*data", KZERO, 0xffffffff, KZERO});
456                 kdir="pc";
457         }
458         if objtype == "amd64" then {
459                 map({"*data", KZERO, 0xffffffffffffffff, KZERO});
460                 kdir="pc64";
461         }
462         if (objtype == "mips" || objtype == "mips2") then {
463                 kdir = "ch";
464         }
465         if objtype == "arm" then {
466                 kdir = "bcm";
467         }
468         if objtype == "arm64" then {
469                 kdir = "bcm64";
470         }
471         needacid("proc");
472         needacid("chan");
473         needacid("segment");
474         needacid("cache");
475 }
476 }