| 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 cname(c) { |
| complex Cname c; |
| if c != 0 then { |
| return *(c.s\s); |
| } else |
| return "<null>"; |
| } |
| |
| // 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, " ", cname(h.c.name), "\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(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(" ", cname(c.name), " mchan=", c.mchan\X); |
| if c.mchan != 0 then { |
| print(" ", cname(c.mchan.name)); |
| } |
| } |
| print("\n"); |
| } |
| |
| defn chans() { |
| local c; |
| |
| c = (Chan)chanalloc.list; |
| while c != 0 do { |
| chan(c); |
| 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 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.entries; |
| 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 (0x80000000|(pg.pa+(a%BY2PG)))\X; |
| } |
| |
| // PC only |
| MACHADDR = 0x80004000; |
| PTEMAPMEM = (1024*1024); |
| BY2PG = 4096; |
| PTEPERTAB = (PTEMAPMEM/BY2PG); |
| defn up() { |
| local mach; |
| |
| 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(acidfile); |
| |
| defn needacid(s){ |
| print("\trc(\"cd /sys/src/9/", kdir, "; mk ", s, ".acid\")\n"); |
| print("\tinclude(\"/sys/src/9/", kdir, "/", s, ".acid\")\n"); |
| } |
| |
| if (map()[2]) != {} then { // map has more than two elements -> active proc |
| kdir = "unknown"; |
| |
| if objtype == "386" then { |
| map({"*data", 0x80000000, 0xffffffff, 0x80000000}); |
| kdir="pc"; |
| } |
| if (objtype == "mips" || objtype == "mips2") then { |
| kdir = "ch"; |
| } |
| if objtype == "alpha" then { |
| map({"*data", 0x80000000, 0xffffffff, 0x80000000}); |
| kdir = "alpha"; |
| } |
| needacid("proc"); |
| } |
| |