1include("/sys/lib/acid/syscall"); 2 3// print various /proc files 4defn fd() { 5 rc("cat /proc/"+itoa(pid)+"/fd"); 6} 7 8defn segment() { 9 rc("cat /proc/"+itoa(pid)+"/segment"); 10} 11 12defn ns() { 13 rc("cat /proc/"+itoa(pid)+"/ns"); 14} 15 16defn qid(qid) { 17 complex Qid qid; 18 return itoa(qid.path\X)+"."+itoa(qid.vers\X); 19} 20 21defn 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// requires include("/sys/src/9/xxx/segment.acid") 31IHASHSIZE = 64; 32defn imagecacheline(h) { 33 while h != 0 do { 34 complex Image h; 35 print (h\X, " ", qid(h.qid), " type ", h.type\D, " ref ", h.ref, " next ", h.next\X, " ", path(h.c.path), "\n"); 36 h = h.hash; 37 } 38} 39 40defn imagecache() { 41 local i; 42 43 i=0; loop 1,IHASHSIZE do { 44 imagecacheline(imagealloc.free[i]); 45 i = i+1; 46 } 47} 48 49// dump channels 50defn chan(c) { 51 local d, q; 52 53 c = (Chan)c; 54 d=(Dev)(*(devtab+4*c.type)); 55 q=c.qid; 56 print("chan(", c\X, "): ref=", c.ref\D, " #", d.dc\r, c.dev\D, " (", q.path, " ", q.vers\D, " ", q.type\X, ")"); 57 print(" fid=", c.fid\D, " iounit=", c.iounit\D); 58 if c.ref != 0 then { 59 print(" ", path(c.path), " mchan=", c.mchan\X); 60 if c.mchan != 0 then { 61 print(" ", path(c.mchan.path)); 62 } 63 } 64 print("\n"); 65} 66 67defn chans() { 68 local c; 69 70 c = (Chan)chanalloc.list; 71 while c != 0 do { 72 if c.ref != 0 then 73 chan(c); 74 c=(Chan)c.link; 75 } 76} 77 78defn nchans() { 79 local c, n; 80 81 n = 0; 82 c = (Chan)chanalloc.list; 83 while c != 0 do { 84 if c.ref != 0 then 85 n++; 86 c = (Chan)c.link; 87 } 88 return n; 89} 90 91defn activechanlist() { 92 local l, n; 93 94 l = {}; 95 c = (Chan)chanalloc.list; 96 while c != 0 do { 97 if c.ref != 0 then 98 l = append l,c; 99 c = (Chan)c.link; 100 } 101 return l; 102} 103 104defn difflist(a, b) { 105 local l, x; 106 107 l = {}; 108 while a != {} do { 109 x = head a; 110 if match(x, b) == -1 then 111 l = append l, x; 112 a = tail a; 113 } 114 return l; 115} 116 117_active_chan_list = {}; 118defn newchans() { 119 local l, new; 120 121 l = activechanlist(); 122 if _active_chan_list != {} then 123 newerchans(_active_chan_list); 124 _active_chan_list = l; 125} 126 127defn newerchans(oldlist){ 128 local new; 129 130 new = difflist(activechanlist(), oldlist); 131 while new != {} do { 132 chan(head new); 133 new = tail new; 134 } 135} 136 137// look for channels that refer to themselves 138defn badchans() { 139 local bad, c, i, len, mtpt, p; 140 141 c = (Chan)chanalloc.list; 142 while c != 0 do { 143 if c.ref != 0 then { 144 bad = ""; 145 p = (Path)c.path; 146 if p != 0 then { 147 path(p); 148 mtpt = p.mtpt; 149 len = p.mlen; 150 i=0; loop 1,len do { 151 if mtpt[i] == c then 152 bad = bad+" mtpt self-ref"; 153 i = i+1; 154 } 155 } 156 if bad != "" then 157 print("chan(", c\X, "):", bad, "\n"); 158 } 159 c = (Chan)c.link; 160 } 161} 162 163// manipulate processes 164defn proctab(x) { 165 return procalloc.arena+sizeofProc*x; 166} 167 168defn proc(p) { 169 complex Proc p; 170 local s, i; 171 172 if p.state != 0 && p.pid != 0 && p.text != 0 then { // 0 is Dead 173 s = p.psstate; 174 if s == 0 then { 175 s = "kproc"; 176 } else { 177 s = *(s\s); 178 } 179 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"); 180 } 181} 182 183defn procenv(p) { 184 complex Proc p; 185 local e, v; 186 187 e = p.egrp; 188 complex Egrp e; 189 v = e.ent; 190 while v != 0 do { 191 complex Evalue v; 192 print(*(v.name\s), "="); 193 printstringn(v.value, v.len); 194 print("\n"); 195 v = v.link; 196 } 197} 198 199KSTACK=4096; 200 201defn procstksize(p) { 202 complex Proc p; 203 local top, sp; 204 205 if p.state != 0 then { // 0 is Dead 206 top = p.kstack+KSTACK; 207 sp = *p.sched; 208 print(top-sp\D, "\n"); 209 } 210} 211 212defn procstk(p) { 213 complex Proc p; 214 local l; 215 216 if p.state != 0 then { // 0 is Dead 217 l = p.sched; 218 if objtype=="386" then 219 _stk(gotolabel, *l, linkreg(0), 0); 220 else 221 _stk(*(l+4), *l, linkreg(0), 0); 222 } 223} 224 225defn procs() { 226 local i; 227 228 i=0; loop 1,conf.nproc do { 229 proc(proctab(i)); 230 i = i+1; 231 } 232} 233 234defn stacks() { 235 local i, p; 236 237 i=0; loop 1,conf.nproc do { 238 p = (Proc)proctab(i); 239 if p.state != 0 then { 240 print("=========================================================\n"); 241 proc(p); 242 procstk(p); 243 } 244 i = i+1; 245 } 246} 247 248defn stacksizes() { 249 local i; 250 251 i=0; loop 1,conf.nproc do { 252 procstksize(proctab(i)); 253 i = i+1; 254 } 255} 256 257// segment-related 258defn procsegs(p) { 259 complex Proc p; 260 local i; 261 262 i=0; loop 1,NSEG do { 263 psegment(p.seg[i]); 264 i = i+1; 265 } 266} 267 268segtypes = { "text", "data", "bss", "stack", "shared", "physical", "shdata", "map" }; 269defn psegment(s) { 270 complex Segment s; 271 272 if s != 0 then { 273 print(s\X, " ", segtypes[s.type&SG_TYPE], " ", s.base\X, "-", s.top\X, " image ", s.image\X, "\n"); 274 } 275} 276 277// find physical address for an address in a given process 278defn procaddr(p, a) { 279 complex Proc p; 280 local i, s, r; 281 282 r = 0; 283 i=0; loop 1,NSEG do { 284 s = p.seg[i]; 285 if s != 0 then { 286 complex Segment s; 287 if s.base <= a && a < s.top then { 288 r = segaddr(s, a); 289 } 290 } 291 i = i+1; 292 } 293 return r; 294} 295 296// find an address in a given segment 297defn segaddr(s, a) { 298 complex Segment s; 299 local pte, pg; 300 301 a = a - s.base; 302 if s.map == 0 || s.mapsize < a/PTEMAPMEM then { 303 return 0; 304 } 305 306 pte = s.map[a/PTEMAPMEM]; 307 if pte == 0 then { 308 return 0; 309 } 310 311 complex Pte pte; 312 pg = pte.pages[(a%PTEMAPMEM)/BY2PG]; 313 if pg == 0 then { 314 return 0; 315 } 316 317 if pg & 1 then { // swapped out, return disk address 318 return pg&~1; 319 } 320 321 complex Page pg; 322 return (KZERO|(pg.pa+(a%BY2PG)))\X; 323} 324 325defn kzero() { 326 return main - (main & 0x0FFFFFFF); 327} 328 329// PC only 330PTEMAPMEM = (1024*1024); 331BY2PG = 4096; 332PTEPERTAB = (PTEMAPMEM/BY2PG); 333defn up() { 334 local mach; 335 336 MACHADDR = KZERO+0x15000; 337 mach = MACHADDR; 338 complex Mach mach; 339 return mach.externup; 340} 341 342defn intrcount() { 343 local p, pp, t, i, j; 344 345 p = intrtimes; 346 i=0; 347 loop 1,256 do { 348 pp = p[i]; 349 i=i+1; 350 if pp != 0 then { 351 j=0; 352 t=0; 353 loop 1,1000 do { 354 t = t+pp[j]; 355 j=j+1; 356 } 357 print(itoa(i, "%5d"), " ", itoa(t, "%11d"), "\n"); 358 } 359 } 360} 361 362print("/sys/lib/acid/kernel"); 363 364defn needacid(s){ 365 print("\trc(\"cd /sys/src/9/", kdir, "; mk ", s, ".acid\")\n"); 366 print("\tinclude(\"/sys/src/9/", kdir, "/", s, ".acid\")\n"); 367} 368 369defn kinit() { 370if (map()[2]) != {} then { // map has more than two elements -> active proc 371 kdir = "unknown"; 372 KZERO = kzero(); 373 374 if objtype == "386" then { 375 map({"*data", KZERO, 0xffffffff, KZERO}); 376 kdir="pc"; 377 } 378 if (objtype == "mips" || objtype == "mips2") then { 379 kdir = "ch"; 380 } 381 if objtype == "alpha" then { 382 map({"*data", KZERO, 0xffffffff, KZERO}); 383 kdir = "alpha"; 384 } 385 needacid("proc"); 386} 387} 388