include("/sys/lib/acid/syscall"); // print various /proc files defn fd() { rc("cat /proc/"+itoa(pid)+"/fd"); } defn segment() { rc("cat /proc/"+itoa(pid)+"/segment"); } defn ns() { rc("cat /proc/"+itoa(pid)+"/ns"); } defn qid(qid) { complex Qid qid; return itoa(qid.path\X)+"."+itoa(qid.vers\X); } defn path(p) { complex Path p; if p != 0 then { return *(p.s\s); } else return ""; } // print Image cache contents // requires include("/sys/src/9/xxx/segment.acid") IHASHSIZE = 64; defn imagecacheline(h) { while h != 0 do { complex Image h; print (h\X, " ", qid(h.qid), " type ", h.type\D, " ref ", h.ref, " next ", h.next\X, " ", path(h.c.path), "\n"); h = h.hash; } } defn imagecache() { local i; i=0; loop 1,IHASHSIZE do { imagecacheline(imagealloc.free[i]); i = i+1; } } // dump channels defn chan(c) { local d, q; c = (Chan)c; d=(Dev)(*(devtab+4*c.type)); q=c.qid; print("chan(", c\X, "): ref=", c.ref\D, " #", d.dc\r, c.dev\D, " (", q.path, " ", q.vers\D, " ", q.type\X, ")"); print(" fid=", c.fid\D, " iounit=", c.iounit\D); if c.ref != 0 then { print(" ", path(c.path), " mchan=", c.mchan\X); if c.mchan != 0 then { print(" ", path(c.mchan.path)); } } print("\n"); } defn chans() { local c; c = (Chan)chanalloc.list; while c != 0 do { if c.ref != 0 then chan(c); c=(Chan)c.link; } } defn nchans() { local c, n; n = 0; c = (Chan)chanalloc.list; while c != 0 do { if c.ref != 0 then n++; c = (Chan)c.link; } return n; } defn activechanlist() { local l, n; l = {}; c = (Chan)chanalloc.list; while c != 0 do { if c.ref != 0 then l = append l,c; c = (Chan)c.link; } return l; } defn difflist(a, b) { local l, x; l = {}; while a != {} do { x = head a; if match(x, b) == -1 then l = append l, x; a = tail a; } return l; } _active_chan_list = {}; defn newchans() { local l, new; l = activechanlist(); if _active_chan_list != {} then newerchans(_active_chan_list); _active_chan_list = l; } defn newerchans(oldlist){ local new; new = difflist(activechanlist(), oldlist); while new != {} do { chan(head new); new = tail new; } } // look for channels that refer to themselves defn badchans() { local bad, c, i, len, mtpt, p; c = (Chan)chanalloc.list; while c != 0 do { if c.ref != 0 then { bad = ""; p = (Path)c.path; if p != 0 then { path(p); mtpt = p.mtpt; len = p.mlen; i=0; loop 1,len do { if mtpt[i] == c then bad = bad+" mtpt self-ref"; i = i+1; } } if bad != "" then print("chan(", c\X, "):", bad, "\n"); } c = (Chan)c.link; } } // manipulate processes defn proctab(x) { return procalloc.arena+sizeofProc*x; } defn proc(p) { complex Proc p; local s, i; if p.state != 0 && p.pid != 0 && p.text != 0 then { // 0 is Dead s = p.psstate; if s == 0 then { s = "kproc"; } else { s = *(s\s); } print(p\X, " ", p.pid, ": ", *(p.text\s), " ", *(p.user\s), " pc ", p.pc\X, " ", s, " (", *(statename[p.state]\s), ") ut ", p.time[0]\D, " st ", p.time[1]\D, " qpc ", p.qpc\X, "\n"); } } defn procenv(p) { complex Proc p; local e, v; e = p.egrp; complex Egrp e; v = e.ent; while v != 0 do { complex Evalue v; print(*(v.name\s), "="); printstringn(v.value, v.len); print("\n"); v = v.link; } } KSTACK=4096; defn procstksize(p) { complex Proc p; local top, sp; if p.state != 0 then { // 0 is Dead top = p.kstack+KSTACK; sp = *p.sched; print(top-sp\D, "\n"); } } defn procstk(p) { complex Proc p; local l; if p.state != 0 then { // 0 is Dead l = p.sched; if objtype=="386" then _stk(gotolabel, *l, linkreg(0), 0); else _stk(*(l+4), *l, linkreg(0), 0); } } defn procs() { local i; i=0; loop 1,conf.nproc do { proc(proctab(i)); i = i+1; } } defn stacks() { local i, p; i=0; loop 1,conf.nproc do { p = (Proc)proctab(i); if p.state != 0 then { print("=========================================================\n"); proc(p); procstk(p); } i = i+1; } } defn stacksizes() { local i; i=0; loop 1,conf.nproc do { procstksize(proctab(i)); i = i+1; } } // segment-related defn procsegs(p) { complex Proc p; local i; i=0; loop 1,NSEG do { psegment(p.seg[i]); i = i+1; } } segtypes = { "text", "data", "bss", "stack", "shared", "physical", "shdata", "map" }; defn psegment(s) { complex Segment s; if s != 0 then { print(s\X, " ", segtypes[s.type&SG_TYPE], " ", s.base\X, "-", s.top\X, " image ", s.image\X, "\n"); } } // find physical address for an address in a given process defn procaddr(p, a) { complex Proc p; local i, s, r; r = 0; i=0; loop 1,NSEG do { s = p.seg[i]; if s != 0 then { complex Segment s; if s.base <= a && a < s.top then { r = segaddr(s, a); } } i = i+1; } return r; } // find an address in a given segment defn segaddr(s, a) { complex Segment s; local pte, pg; a = a - s.base; if s.map == 0 || s.mapsize < a/PTEMAPMEM then { return 0; } pte = s.map[a/PTEMAPMEM]; if pte == 0 then { return 0; } complex Pte pte; pg = pte.pages[(a%PTEMAPMEM)/BY2PG]; if pg == 0 then { return 0; } if pg & 1 then { // swapped out, return disk address return pg&~1; } complex Page pg; return (KZERO|(pg.pa+(a%BY2PG)))\X; } defn kzero() { return main - (main & 0x0FFFFFFF); } // PC only PTEMAPMEM = (1024*1024); BY2PG = 4096; PTEPERTAB = (PTEMAPMEM/BY2PG); defn up() { local mach; MACHADDR = KZERO+0x15000; mach = MACHADDR; complex Mach mach; return mach.externup; } defn intrcount() { local p, pp, t, i, j; p = intrtimes; i=0; loop 1,256 do { pp = p[i]; i=i+1; if pp != 0 then { j=0; t=0; loop 1,1000 do { t = t+pp[j]; j=j+1; } print(itoa(i, "%5d"), " ", itoa(t, "%11d"), "\n"); } } } print("/sys/lib/acid/kernel"); defn needacid(s){ print("\trc(\"cd /sys/src/9/", kdir, "; mk ", s, ".acid\")\n"); print("\tinclude(\"/sys/src/9/", kdir, "/", s, ".acid\")\n"); } defn kinit() { if (map()[2]) != {} then { // map has more than two elements -> active proc kdir = "unknown"; KZERO = kzero(); if objtype == "386" then { map({"*data", KZERO, 0xffffffff, KZERO}); kdir="pc"; } if (objtype == "mips" || objtype == "mips2") then { kdir = "ch"; } if objtype == "alpha" then { map({"*data", KZERO, 0xffffffff, KZERO}); kdir = "alpha"; } if objtype == "arm" then { map({"*data", KZERO, 0xffffffff, KZERO}); kdir = "arm"; } needacid("proc"); } }