commit 0a61c07d591273b76da21fb8386b669989da3707 from: rsc date: Mon Apr 19 18:18:37 2004 UTC acid files commit - c8af1ab17b72f500c27688598dbb893f09f62c53 commit + 0a61c07d591273b76da21fb8386b669989da3707 blob - /dev/null blob + 252ece8ee490a83e07c847baba33db18201c6482 (mode 644) --- /dev/null +++ acid/386 @@ -0,0 +1,210 @@ +// 386 support + +defn acidinit() // Called after all the init modules are loaded +{ + bplist = {}; + bpfmt = 'b'; + + srcpath = { + "./", + "/sys/src/libc/port/", + "/sys/src/libc/9sys/", + "/sys/src/libc/386/" + }; + + srcfiles = {}; // list of loaded files + srctext = {}; // the text of the files +} + +defn linkreg(addr) +{ + return {}; +} + +defn stk() // trace +{ + _stk({"PC", *PC, "SP", *SP}, 0); +} + +defn lstk() // trace with locals +{ + _stk({"PC", *PC, "SP", *SP}, 1); +} + +defn gpr() // print general(hah hah!) purpose registers +{ + print("AX\t", *AX, " BX\t", *BX, " CX\t", *CX, " DX\t", *DX, "\n"); + print("DI\t", *DI, " SI\t", *SI, " BP\t", *BP, "\n"); +} + +defn spr() // print special processor registers +{ + local pc; + local cause; + + pc = *PC; + print("PC\t", pc, " ", fmt(pc, 'a'), " "); + pfl(pc); + print("SP\t", *SP, " ECODE ", *ECODE, " EFLAG ", *EFLAGS, "\n"); + print("CS\t", *CS, " DS\t ", *DS, " SS\t", *SS, "\n"); + print("GS\t", *GS, " FS\t ", *FS, " ES\t", *ES, "\n"); + + cause = *TRAP; + print("TRAP\t", cause, " ", reason(cause), "\n"); +} + +defn regs() // print all registers +{ + spr(); + gpr(); +} + +defn mmregs() +{ + print("MM0\t", *MM0, " MM1\t", *MM1, "\n"); + print("MM2\t", *MM2, " MM3\t", *MM3, "\n"); + print("MM4\t", *MM4, " MM5\t", *MM5, "\n"); + print("MM6\t", *MM6, " MM7\t", *MM7, "\n"); +} + +defn pstop(pid) +{ + local l; + local pc; + + pc = *PC; + + print(pid,": ", reason(*TRAP), "\t"); + print(fmt(pc, 'a'), "\t", *fmt(pc, 'i'), "\n"); + + if notes then { + if notes[0] != "sys: breakpoint" then { + print("Notes pending:\n"); + l = notes; + while l do { + print("\t", head l, "\n"); + l = tail l; + } + } + } +} + +aggr Ureg +{ + 'U' 0 di; + 'U' 4 si; + 'U' 8 bp; + 'U' 12 nsp; + 'U' 16 bx; + 'U' 20 dx; + 'U' 24 cx; + 'U' 28 ax; + 'U' 32 gs; + 'U' 36 fs; + 'U' 40 es; + 'U' 44 ds; + 'U' 48 trap; + 'U' 52 ecode; + 'U' 56 pc; + 'U' 60 cs; + 'U' 64 flags; + { + 'U' 68 usp; + 'U' 68 sp; + }; + 'U' 72 ss; +}; + +defn +Ureg(addr) { + complex Ureg addr; + print(" di ", addr.di, "\n"); + print(" si ", addr.si, "\n"); + print(" bp ", addr.bp, "\n"); + print(" nsp ", addr.nsp, "\n"); + print(" bx ", addr.bx, "\n"); + print(" dx ", addr.dx, "\n"); + print(" cx ", addr.cx, "\n"); + print(" ax ", addr.ax, "\n"); + print(" gs ", addr.gs, "\n"); + print(" fs ", addr.fs, "\n"); + print(" es ", addr.es, "\n"); + print(" ds ", addr.ds, "\n"); + print(" trap ", addr.trap, "\n"); + print(" ecode ", addr.ecode, "\n"); + print(" pc ", addr.pc, "\n"); + print(" cs ", addr.cs, "\n"); + print(" flags ", addr.flags, "\n"); + print(" sp ", addr.sp, "\n"); + print(" ss ", addr.ss, "\n"); +}; +sizeofUreg = 76; + +aggr Linkdebug +{ + 'X' 0 version; + 'X' 4 map; +}; + +aggr Linkmap +{ + 'X' 0 addr; + 'X' 4 name; + 'X' 8 dynsect; + 'X' 12 next; + 'X' 16 prev; +}; + +defn +linkdebug() +{ + local a; + + if !havesymbol("_DYNAMIC") then + return 0; + + a = _DYNAMIC; + while *a != 0 do { + if *a == 21 then // 21 == DT_DEBUG + return *(a+4); + a = a+8; + } + return 0; +} + +defn +acidmap() +{ + if systype == "linux" then { + local r, m, n; + + r = linkdebug(); + if r then { + complex Linkdebug r; + m = r.map; + n = 0; + while m != 0 && n < 100 do { + complex Linkmap m; + if m.name && *(m.name\b) then + textfile({*(m.name\s), m.addr\X}); + m = m.next; + n = n+1; + } + } + } + + local syms; + local l; + + l = textfile(); + if l != {} then { + syms = "acidtypes"; + while l != {} do { + syms = syms + " " + ((head l)[0]); + l = tail l; + } + includepipe(syms); + } +} + +print(acidfile); blob - /dev/null blob + f57da9f9d2bc11dbef4c82eaa0ee17072b4aaa69 (mode 644) --- /dev/null +++ acid/68020 @@ -0,0 +1,137 @@ +// 68020 support + +defn acidinit() // Called after all the init modules are loaded +{ + bplist = {}; + bpfmt = 'x'; + + srcpath = { + "./", + "/sys/src/libc/port/", + "/sys/src/libc/9sys/", + "/sys/src/libc/68020/" + }; + + srcfiles = {}; // list of loaded files + srctext = {}; // the text of the files +} + +defn linkreg(addr) +{ + return 0; +} + +defn stk() // trace +{ + _stk(*PC, *A7, 0, 0); +} + +defn lstk() // trace with locals +{ + _stk(*PC, *A7, 0, 1); +} + +defn gpr() // print general purpose registers +{ + print("R0\t", *R0, "R1\t", *R1, "R2\t", *R2, "R3\t", *R3, "\n"); + print("R4\t", *R4, "R5\t", *R5, "R6\t", *R6, "R7\t", *R7, "\n"); + print("A0\t", *A0, "A1\t", *A1, "A2\t", *A2, "A3\t", *A3, "\n"); + print("A4\t", *A4, "A5\t", *A5, "A6\t", *A6, "A7\t", *A7, "\n"); +} + +defn spr() // print special processor registers +{ + local pc; + local cause; + + pc = *PC; + print("PC\t", pc, " ", fmt(pc, 'a'), " "); + pfl(pc); + print("SP\t", *A7, " MAGIC\t", *MAGIC, "\n"); + + cause = *VO; + print("SR\t", *SR, "VO ", cause, " ", reason(cause), "\n"); +} + +defn regs() // print all registers +{ + spr(); + gpr(); +} + +defn pstop(pid) +{ + local l; + local pc; + + pc = *PC; + + print(pid,": ", reason(*VO), "\t"); + print(fmt(pc, 'a'), "\t", fmt(pc, 'i'), "\n"); + + if notes then { + if notes[0] != "sys: breakpoint" then { + print("Notes pending:\n"); + l = notes; + while l do { + print("\t", head l, "\n"); + l = tail l; + } + } + } +} + +aggr Ureg +{ + 'U' 0 r0; + 'U' 4 r1; + 'U' 8 r2; + 'U' 12 r3; + 'U' 16 r4; + 'U' 20 r5; + 'U' 24 r6; + 'U' 28 r7; + 'U' 32 a0; + 'U' 36 a1; + 'U' 40 a2; + 'U' 44 a3; + 'U' 48 a4; + 'U' 52 a5; + 'U' 56 a6; + 'U' 60 sp; + 'U' 64 usp; + 'U' 68 magic; + 'u' 72 sr; + 'U' 74 pc; + 'u' 78 vo; + 'a' 80 microstate; +}; + +defn +Ureg(addr) { + complex Ureg addr; + print(" r0 ", addr.r0, "\n"); + print(" r1 ", addr.r1, "\n"); + print(" r2 ", addr.r2, "\n"); + print(" r3 ", addr.r3, "\n"); + print(" r4 ", addr.r4, "\n"); + print(" r5 ", addr.r5, "\n"); + print(" r6 ", addr.r6, "\n"); + print(" r7 ", addr.r7, "\n"); + print(" a0 ", addr.a0, "\n"); + print(" a1 ", addr.a1, "\n"); + print(" a2 ", addr.a2, "\n"); + print(" a3 ", addr.a3, "\n"); + print(" a4 ", addr.a4, "\n"); + print(" a5 ", addr.a5, "\n"); + print(" a6 ", addr.a6, "\n"); + print(" sp ", addr.sp, "\n"); + print(" usp ", addr.usp, "\n"); + print(" magic ", addr.magic, "\n"); + print(" sr ", addr.sr, "\n"); + print(" pc ", addr.pc, "\n"); + print(" vo ", addr.vo, "\n"); + print(" microstate ", addr.microstate, "\n"); +}; + +print(acidfile); blob - /dev/null blob + 1cce6eb8a503400ecc7664b2fc9874acfeb2160e (mode 644) --- /dev/null +++ acid/acme @@ -0,0 +1,133 @@ +// support for acme; acid must be run with /acme/acid/$cputype/Acid + + +defn w(*code) +{ + local dir; + + printto("/tmp/acme.acid", eval code); + rc("cat /tmp/acme.acid | wnew -d "+"Acid/-stk'("+itoa(pid)+")'"); +} + +defn procstk(pid, name) +{ + local dir; + + printto("/tmp/acme.acid", stk()); + rc("cat /tmp/acme.acid | wnew -d "+"Acid/-'"+name+"("+itoa(pid)+")'"); +} + +defn taskstk(tid, name) +{ + local dir; + + printto("/tmp/acme.acid", threadstk(tid)); + rc("cat /tmp/acme.acid | wnew -d "+"Acid/-"+name+"'("+itoa(pid)+")'"); +} + +defn _stk(pc, sp, link, dolocals) +{ + local stk; + + print("At pc:", pc, ":", fmt(pc, 'a'), " "); + pfl(pc); + + stk = strace(pc, sp, link); + + while stk do { + frame = head stk; + print(fmt(frame[0], 'a'), "("); + params(frame[2], frame[0]); + print(") "); + print("\n\tcalled from ", fmt(frame[1], 'a'), " "); + pfl(frame[1]); + stk = tail stk; + if dolocals then + locals(frame[3], frame[0]); + } +} + +//defn _stk(pc, sp, dolocals) +//{ +// w(__stk(pc, sp, dolocals)); +//} + + +defn params(param, name) +{ + while param do { + sym = head param; + print("*", fmt(name, 'a'), ":", sym[0], "=", sym[1]); + param = tail param; + if param then + print (","); + } +} + +defn locals(l, name) +{ + local sym; + + while l do { + sym = head l; + print("\t*", fmt(name, 'a'), ":", sym[0], "=", sym[1], "\n"); + l = tail l; + } +} + +defn bptab() // print a table of breakpoints +{ + local lst, addr; + + lst = bplist; + while lst do { + addr = head lst; + print("\tbpdel(", fmt(addr, 'a'), ")\n"); + lst = tail lst; + } +} + +defn procs() // print status of processes +{ + local c, lst, cpid; + + cpid = pid; + lst = proclist; + while lst do { + np = head lst; + setproc(np); + if np == cpid then + print(">"); + print("\t", "setproc(", np, ")\t", status(np), " at ", fmt(*PC, 'a'), "\n"); + lst = tail lst; + } + pid = cpid; + if pid != 0 then + setproc(pid); +} + +defn allstacks() // print stacks of processes and threads +{ + complex Proc P; + local T, Tq; + local c, lst, cpid; + + cpid = pid; + P = (Proc)pq.$head; + while P != 0 do{ + Tq = (Tqueue)P.threads; + T = (Thread)Tq.$head; + setproc(P.pid); + while T != 0 do{ + if(T.cmdname == 0) then taskstk(T, "unknown"); + else taskstk(T, *(T.cmdname\s)); + T = T.nextt; + } + P = P.next; + } + pid = cpid; + if pid != 0 then + setproc(pid); +} + +print(acidfile); blob - /dev/null blob + 323a0ffa42aee6f655b0f1b5b74abcc4fa063adc (mode 644) --- /dev/null +++ acid/alef @@ -0,0 +1,147 @@ +// runtime library definitions +if objtype=="mips2" then objtype="mips"; + +include("/sys/src/alef/lib/"+objtype+"/acid"); + +defn +pchan(addr) +{ + local l, n; + + complex Chan addr; + + if addr.sva then + print("Sender waiting: buffer ", addr.sva, "\n"); + else + print("No sender\n"); + + if addr.rva then + print("Receiver waiting: buffer ", addr.rva, "\n"); + else + print("No receiver\n"); + + if addr.async then { + n = 0; + l = addr.qh; + while l do { + n = n+1; + l = l.next; + } + print("Async channel\n\t", n\D, " messsages queued\n\t"); + l = addr.free; + while l do { + n = n+1; + l = l.next; + } + print(n\D, " free buffers\n"); + } + + if addr.selt then { + l = "send"; + if addr.selt then + l = "receive"; + print("In select ", l, ": task ", addr.selt\X, "\n"); + labstk(addr.selt); + } +} + +defn +tdb() +{ + local ta, tq; + + // Private proc tdb pointer + ta = *{ 0x7fffe000, + 0x0ffdf000, + 0xbfff5000 }[match(objtype, {"mips", "sparc", "386"})]; + + complex Tdb ta; + + print("tdb ", ta.ntask, " tasks:"); + if *ta then + print("locked\n"); + else + print("unlocked\n"); + + if ta.ctask then { + print("current task ", ta.ctask, "\n"); + Task(ta.ctask); + } + else + print("proc is idle\n"); + + tq = (Task)ta.runhd; + if tq == 0 then + return {}; + + print("Tasks ready to run:\n"); + while tq != 0 do { + print("Task(", tq, ")\n"); + tq = tq.link; + } +} + +defn +lselect(addr) +{ + local c; + + complex Task addr; + complex Chan c; + + c = addr.slist; + if c == 0 then { + print("No select pending\n"); + return {}; + } + while c do { + print("pchan(", c\X, ")\n"); + c = c.sellink; + } +} + +defn +pqlock(addr) +{ + local t; + + complex QLock addr; + + if *addr then + print("QLock is under modification\n"); + if addr.used == 0 then + return {}; + + print("QLock is held\n"); + t = addr.queue; + complex Task t; + if t == 0 then { + print("No tasks waiting\n"); + return {}; + } + print("Tasks waiting:\n"); + while t do { + print("Task(", t, ")\n"); + tq = tq.qlink; + } +} + +srcpath = { + "./", + "/sys/src/alef/lib/port/", + "/sys/src/alef/lib/p9/", + "/sys/src/alef/lib/"+objtype+"/" +}; + +defn labstk(l) +{ + if objtype == "386" then + _stk(ALEF_switch, *l, linkreg(0), 0); + else + _stk(*(l+4), *l, linkreg(0), 0); +} + +print(acidfile); + +include("/sys/src/alef/lib/port/acid."+objtype); +include("/sys/src/alef/lib/p9/acid."+objtype); blob - /dev/null blob + 5912271d76e793098547e25ffbdf380f2e184b4d (mode 644) --- /dev/null +++ acid/alpha @@ -0,0 +1,205 @@ +// Alpha support + +defn acidinit() // Called after all the init modules are loaded +{ + bplist = {}; + bpfmt = 'X'; + + srcpath = { + "./", + "/sys/src/libc/port/", + "/sys/src/libc/9sys/", + "/sys/src/libc/alpha/" + }; + + srcfiles = {}; // list of loaded files + srctext = {}; // the text of the files +} + +defn stk() // trace +{ + _stk(*PC, *SP, linkreg(0), 0); +} + +defn lstk() // trace with locals +{ + _stk(*PC, *SP, linkreg(0), 1); +} + +defn gpr() // print general purpose registers +{ + print("R0\t", *R0, "\n"); + print("R1\t", *R1, " R2\t", *R2, " R3\t", *R3, "\n"); + print("R4\t", *R4, " R5\t", *R5, " R6\t", *R6, "\n"); + print("R7\t", *R7, " R8\t", *R8, " R9\t", *R9, "\n"); + print("R10\t", *R10, " R11\t", *R11, " R12\t", *R12, "\n"); + print("R13\t", *R13, " R14\t", *R14, " R15\t", *R15, "\n"); + print("R16\t", *R16, " R17\t", *R17, " R18\t", *R18, "\n"); + print("R19\t", *R19, " R20\t", *R20, " R21\t", *R21, "\n"); + print("R22\t", *R22, " R23\t", *R23, " R24\t", *R24, "\n"); + print("R25\t", *R25, " R26\t", *R26, " R27\t", *R27, "\n"); + print("R28\t", *R28, " R29\t", *R29, " R30\t", *SP\Y, "\n"); +} + +defn fpr() +{ + print("F0\t", *fmt(F0, 'G'), "\tF1\t", *fmt(F1, 'G'), "\n"); + print("F2\t", *fmt(F2, 'G'), "\tF3\t", *fmt(F3, 'G'), "\n"); + print("F4\t", *fmt(F4, 'G'), "\tF5\t", *fmt(F5, 'G'), "\n"); + print("F6\t", *fmt(F6, 'G'), "\tF7\t", *fmt(F7, 'G'), "\n"); + print("F8\t", *fmt(F8, 'G'), "\tF9\t", *fmt(F9, 'G'), "\n"); + print("F10\t", *fmt(F10, 'G'), "\tF11\t", *fmt(F11, 'G'), "\n"); + print("F12\t", *fmt(F12, 'G'), "\tF13\t", *fmt(F13, 'G'), "\n"); + print("F14\t", *fmt(F14, 'G'), "\tF15\t", *fmt(F15, 'G'), "\n"); + print("F16\t", *fmt(F16, 'G'), "\tF17\t", *fmt(F17, 'G'), "\n"); + print("F18\t", *fmt(F18, 'G'), "\tF19\t", *fmt(F19, 'G'), "\n"); + print("F20\t", *fmt(F20, 'G'), "\tF21\t", *fmt(F21, 'G'), "\n"); + print("F22\t", *fmt(F22, 'G'), "\tF23\t", *fmt(F23, 'G'), "\n"); + print("F24\t", *fmt(F24, 'G'), "\tF25\t", *fmt(F25, 'G'), "\n"); + print("F26\t", *fmt(F26, 'G'), "\tF27\t", *fmt(F27, 'G'), "\n"); + print("F28\t", *fmt(F28, 'G'), "\tF29\t", *fmt(F29, 'G'), "\n"); + print("F30\t", *fmt(F30, 'G'), "\tF31\t", *fmt(F31, 'G'), "\n"); +} + +defn spr() // print special processor registers +{ + local pc, link, cause; + + pc = *PC; + print("PC\t", pc, " ", fmt(pc, 'a'), " "); + pfl(pc); + + link = *R26; + print("SP\t", *SP, "\tLINK\t", link, " ", fmt(link, 'a'), " "); + pfl(link); + + cause = *TYPE; + print("STATUS\t", *STATUS, "\tTYPE\t", cause, " ", reason(cause), "\n"); + print("A0\t", *A0, " A1\t", *A1, " A2\t", *A2, "\n"); +} + +defn regs() // print all registers +{ + spr(); + gpr(); +} + +defn pstop(pid) +{ + local l, pc; + + pc = *PC; + + print(pid,": ", reason(*TYPE), "\t"); + print(fmt(pc, 'a'), "\t", fmt(pc, 'i'), "\n"); + + if notes then { + if notes[0] != "sys: breakpoint" then { + print("Notes pending:\n"); + l = notes; + while l do { + print("\t", head l, "\n"); + l = tail l; + } + } + } +} + +sizeofUreg = 296; +aggr Ureg +{ + 'W' 0 type; + 'W' 8 a0; + 'W' 16 a1; + 'W' 24 a2; + 'W' 32 r0; + 'W' 40 r1; + 'W' 48 r2; + 'W' 56 r3; + 'W' 64 r4; + 'W' 72 r5; + 'W' 80 r6; + 'W' 88 r7; + 'W' 96 r8; + 'W' 104 r9; + 'W' 112 r10; + 'W' 120 r11; + 'W' 128 r12; + 'W' 136 r13; + 'W' 144 r14; + 'W' 152 r15; + 'W' 160 r19; + 'W' 168 r20; + 'W' 176 r21; + 'W' 184 r22; + 'W' 192 r23; + 'W' 200 r24; + 'W' 208 r25; + 'W' 216 r26; + 'W' 224 r27; + 'W' 232 r28; + { + 'W' 240 r30; + 'W' 240 usp; + 'W' 240 sp; + }; + 'W' 248 status; + 'W' 256 pc; + 'W' 264 r29; + 'W' 272 r16; + 'W' 280 r17; + 'W' 288 r18; +}; + +defn +Ureg(addr) { + complex Ureg addr; + print(" type ", addr.type, "\n"); + print(" a0 ", addr.a0, "\n"); + print(" a1 ", addr.a1, "\n"); + print(" a2 ", addr.a2, "\n"); + print(" r0 ", addr.r0, "\n"); + print(" r1 ", addr.r1, "\n"); + print(" r2 ", addr.r2, "\n"); + print(" r3 ", addr.r3, "\n"); + print(" r4 ", addr.r4, "\n"); + print(" r5 ", addr.r5, "\n"); + print(" r6 ", addr.r6, "\n"); + print(" r7 ", addr.r7, "\n"); + print(" r8 ", addr.r8, "\n"); + print(" r9 ", addr.r9, "\n"); + print(" r10 ", addr.r10, "\n"); + print(" r11 ", addr.r11, "\n"); + print(" r12 ", addr.r12, "\n"); + print(" r13 ", addr.r13, "\n"); + print(" r14 ", addr.r14, "\n"); + print(" r15 ", addr.r15, "\n"); + print(" r19 ", addr.r19, "\n"); + print(" r20 ", addr.r20, "\n"); + print(" r21 ", addr.r21, "\n"); + print(" r22 ", addr.r22, "\n"); + print(" r23 ", addr.r23, "\n"); + print(" r24 ", addr.r24, "\n"); + print(" r25 ", addr.r25, "\n"); + print(" r26 ", addr.r26, "\n"); + print(" r27 ", addr.r27, "\n"); + print(" r28 ", addr.r28, "\n"); + print("_12_ {\n"); + _12_(addr+240); + print("}\n"); + print(" status ", addr.status, "\n"); + print(" pc ", addr.pc, "\n"); + print(" r29 ", addr.r29, "\n"); + print(" r16 ", addr.r16, "\n"); + print(" r17 ", addr.r17, "\n"); + print(" r18 ", addr.r18, "\n"); +}; + +defn linkreg(addr) +{ + complex Ureg addr; + return addr.r26\X; +} + +print(acidfile); + blob - /dev/null blob + 01599978e015a2f71a5dd2219af03f7996b81dee (mode 644) --- /dev/null +++ acid/arm @@ -0,0 +1,104 @@ +// ARM7500 support + +defn acidinit() // Called after all the init modules are loaded +{ + bplist = {}; + bpfmt = 'b'; + + srcpath = { + "./", + "/sys/src/libc/port/", + "/sys/src/libc/9sys/", + "/sys/src/libc/arm/" + }; + + srcfiles = {}; // list of loaded files + srctext = {}; // the text of the files +} + +defn linkreg(addr) +{ + return 0; +} + +defn stk() // trace +{ + _stk(*PC, *SP, 0, 0); +} + +defn lstk() // trace with locals +{ + _stk(*PC, *SP, 0, 1); +} + +defn gpr() // print general purpose registers +{ + print("R0\t", *R0, " R1\t", *R1, " R2\t", *R2, "\n"); + print("R3\t", *R3, " R4\t", *R4, " R5\t", *R5, "\n"); + print("R6\t", *R6, " R7\t", *R7, " R8\t", *R8, "\n"); + print("R9\t", *R9, " R10\t", *R10, " R11\t", *R11, "\n"); + print("R12\t", *R12, " R13\t", *R13, " R14\t", *R14, "\n"); + print("R15\t", *R15, "\n"); +} + +defn regs() // print all registers +{ + gpr(); +} + +defn pstop(pid) +{ + return 0; +} + +aggr Ureg +{ + 'U' 0 r0; + 'U' 4 r1; + 'U' 8 r2; + 'U' 12 r3; + 'U' 16 r4; + 'U' 20 r5; + 'U' 24 r6; + 'U' 28 r7; + 'U' 32 r8; + 'U' 36 r9; + 'U' 40 r10; + 'U' 44 r11; + 'U' 48 r12; + 'U' 52 r13; + 'U' 56 r14; + 'U' 60 type; + 'U' 64 psr; + 'U' 68 pc; +}; + +defn +Ureg(addr) { + complex Ureg addr; + print(" r0 ", addr.r0, "\n"); + print(" r1 ", addr.r1, "\n"); + print(" r2 ", addr.r2, "\n"); + print(" r3 ", addr.r3, "\n"); + print(" r4 ", addr.r4, "\n"); + print(" r5 ", addr.r5, "\n"); + print(" r6 ", addr.r6, "\n"); + print(" r7 ", addr.r7, "\n"); + print(" r8 ", addr.r8, "\n"); + print(" r9 ", addr.r9, "\n"); + print(" r10 ", addr.r10, "\n"); + print(" r11 ", addr.r11, "\n"); + print(" r12 ", addr.r12, "\n"); + print(" r13 ", addr.r13, "\n"); + print(" r14 ", addr.r14, "\n"); + print(" type ", addr.type, "\n"); + print(" psr ", addr.psr, "\n"); + print(" pc ", addr.pc, "\n"); +}; + +defn acornmap() +{ + map({"text", _startup, end, 0x20}); +} + +print(acidfile); blob - /dev/null blob + 16b613a7a97489c61244d3c7807e9ebca0bd2d64 (mode 644) Binary files /dev/null and acid/core differ blob - /dev/null blob + 3436bd1c84849e56d4bce6d91ce608d45b6312d4 (mode 644) --- /dev/null +++ acid/coverage @@ -0,0 +1,128 @@ +// Coverage library + +defn coverage() +{ + local lmap, lp, e, pc, n, l; + + new(); + + bblock = {}; + + // find the first location in the text + e = (map()[0][1])\i; + + while e < etext-4 do { + l = follow(e); + if tail l != {} then { + if match(l[0], bblock) < 0 then + bblock = append bblock, l[0]; + if match(l[1], bblock) < 0 then + bblock = append bblock, l[1]; + } + e++; + } + + l = bblock; + while l != {} do { + *fmt(head l, bpfmt) = bpinst; + l = tail l; + } + + while 1 do { + cont(); + pc = *PC; + n = match(pc, bblock); + if n >= 0 then { + pc = fmt(pc, bpfmt); + *pc = @pc; + bblock = delete bblock, n; + } + else { + pstop(pid); + return {}; + } + } +} + +defn eblock(addr) +{ + addr = addr\i; + + while addr < etext do { + if (tail follow(addr)) != {} then + return pcline(addr); + addr++; + } + return 0; +} + +defn basic(stsrc, ensrc, file) +{ + local src, text; + + if stsrc >= ensrc then + return {}; + + print(file, ":", stsrc, ",", ensrc, "\n"); + src = match(file, srcfiles); + + if src >= 0 then + src = srctext[src]; + else + src = findsrc(file); + + if src == {} then + print("no source for ", file, "\n"); + else { + while stsrc <= ensrc do { + text = src[stsrc]; + if text != {} then + print("\t", stsrc, ":", text, "\n"); + stsrc = stsrc+1; + } + } +} + +defn analyse(fnaddr) +{ + local addr, l, tfn; + + new(); + + tfn = fnbound(fnaddr); + + l = bblock; + while l do { + addr = head l; + + if addr >= tfn[0] && addr < tfn[1] then + basic(pcline(addr), eblock(addr), pcfile(addr)); + + l = tail l; + } + kill(pid); +} + +defn report() +{ + local addr, l; + + new(); + + l = bblock; + while l do { + addr = head l; + + basic(pcline(addr), eblock(addr), pcfile(addr)); + + l = tail l; + } + kill(pid); +} + +defn stopped(pid) +{ + return {}; +} + +print(acidfile); blob - /dev/null blob + 8e9f2e76f8ac2a72bc5ff26c18f3a287084883c0 (mode 644) --- /dev/null +++ acid/elflink @@ -0,0 +1,54 @@ +aggr Rdebug +{ + 'X' 0 version; + 'X' 4 map; +}; + +aggr Rmap +{ + 'X' 0 addr; + 'X' 4 name; + 'X' 8 dynsect; + 'X' 12 next; + 'X' 16 prev; +}; + +defn +rdebug() +{ + local a; + + a = _DYNAMIC; + while *a != 0 do { + if *a == 21 then // 21 == DT_DEBUG + return *(a+4); + a = a+8; + } + return 0; +} + +defn +rlink() +{ + local r, m, n; + + r = rdebug(); + if r == 0 then + return {}; + complex Rdebug r; + print("version ", r.version, "\n"); + + m = r.map; + n = 0; + while m != 0 && n < 100 do { + complex Rmap m; + print("map ", m\X, " base ", m.addr\X, " next ", m.next\X, " name "); + if m.name then + print(*(m.name\s)); + else + print("''"); + print("\n"); + m = m.next; + n = n+1; + } +} blob - /dev/null blob + 494ab9c348914bbdac3e2e03b6a3dc4c185f8404 (mode 644) --- /dev/null +++ acid/kernel @@ -0,0 +1,295 @@ +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 ""; +} + +// 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"); +} + blob - /dev/null blob + 6231f950f025cfb44f545916cf9fadea6aa27994 (mode 644) --- /dev/null +++ acid/leak @@ -0,0 +1,138 @@ +// +// usage: acid -l pool -l leak +// +include("/sys/src/libc/port/pool.acid"); + +defn +dumppool(p) +{ + complex Pool p; + a = p.arenalist; + + while a != 0 && a < 0x60000000 do { + complex Arena a; + dumparena(a); + a = a.down; + } +} + +defn +dumparena(arena) +{ + local atail, b, nb; + + atail = A2TB(arena); + complex Bhdr arena; + b = a; + while b < atail && b.magic != ARENATAIL_MAGIC do { + dumpblock(b); + nb = B2NB(b); + if nb == b then { + print("B2NB(", b\X, ") = b\n"); + b = atail; // end loop + } + if nb > atail then { + b = (Bhdr)(b+4); + print("lost at block ", (b-4)\X, ", scanning forward\n"); + while b < atail && b.magic != KEMPT_MAGIC && b.magic != FREE_MAGIC do + b = (Bhdr)(b+4); + print("stopped at ", b\X, " ", *b\X, "\n"); + }else + b = nb; + } + if b != atail then + print("found wrong tail to arena ", arena\X, " wanted ", atail\X, "\n"); +} + +defn +isptr(a) +{ + if end <= a && a < xbloc then + return 1; + if 0x7efff000 <= a && a < 0x7ffff000 then + return 1; + return 0; +} + +defn +dumpblock(addr) +{ + complex Bhdr addr; + + if addr.magic == KEMPT_MAGIC || addr.magic == FREE_MAGIC then { + local a, x, s; + + a = addr; + complex Alloc a; + + x = addr+8; + if addr.magic == KEMPT_MAGIC then + s = "block"; + else + s = "free"; + print(s, " ", addr\X, " ", a.size\X, " "); + print(*(addr+8)\X, " ", *(addr+12)\X, "\n"); + } +} + +defn +dumprange(s, e, type) +{ + local x, y; + + print("range ", type, " ", s\X, " ", e\X, "\n"); + x = s; + while x < e do { + y = *x; + if isptr(y) then print("data ", x\X, " ", y\X, " ", type, "\n"); + x = x + 4; + } +} + +defn +dumpmem() +{ + local s; + + xbloc = *bloc; + // assume map()[1] is "data" + dumprange(map()[1][1], end, "bss"); // bss + dumprange(end, xbloc, "alloc"); // allocated + + if 0x7efff000 < *SP && *SP < 0x7ffff000 then + s = *SP; + else + s = 0x7fff7000; // 32 k + + dumprange(s, 0x7ffff000, "stack"); +} + +defn +dumpregs() +{ + dumprange(0, sizeofUreg, "reg"); +} + + +defn +leakdump(l) +{ + print("==LEAK BEGIN==\n"); + dumppool(sbrkmem); + dumpmem(); + dumpregs(); + while l != {} do { + setproc(head l); + dumpregs(); + l = tail l; + } + print("==LEAK END==\n"); +} + +defn +blockdump() +{ + print("==BLOCK BEGIN==\n"); + dumppool(sbrkmem); + print("==BLOCK END==\n"); +} blob - /dev/null blob + 6ce15e75097eb4469b1e4c1c79c7a9538f1d3c36 (mode 644) --- /dev/null +++ acid/mips @@ -0,0 +1,217 @@ +// Mips support + +defn acidinit() // Called after all the init modules are loaded +{ + bplist = {}; + bpfmt = 'X'; + + srcpath = { + "./", + "/sys/src/libc/port/", + "/sys/src/libc/9sys/", + "/sys/src/libc/mips/" + }; + + srcfiles = {}; // list of loaded files + srctext = {}; // the text of the files +} + +defn stk() // trace +{ + _stk(*PC, *SP, linkreg(0), 0); +} + +defn lstk() // trace with locals +{ + _stk(*PC, *SP, linkreg(0), 1); +} + +defn gpr() // print general purpose registers +{ + print("R1\t", *R1, " R2\t", *R2, " R3\t", *R3, "\n"); + print("R4\t", *R4, " R5\t", *R5, " R6\t", *R6, "\n"); + print("R7\t", *R7, " R8\t", *R8, " R9\t", *R9, "\n"); + print("R10\t", *R10, " R11\t", *R11, " R12\t", *R12, "\n"); + print("R13\t", *R13, " R14\t", *R14, " R15\t", *R15, "\n"); + print("R16\t", *R16, " R17\t", *R17, " R18\t", *R18, "\n"); + print("R19\t", *R19, " R20\t", *R20, " R21\t", *R21, "\n"); + print("R22\t", *R22, " R23\t", *R23, " R24\t", *R24, "\n"); + print("R25\t", *R25, " R26\t", *R26, " R27\t", *R27, "\n"); + print("R28\t", *R28, " R29\t", *SP, " R30\t", *R30, "\n"); + print("R31\t", *R31, "\n"); +} + +defn Fpr() +{ + print("F0\t", *fmt(F0, 'G'), "\tF2\t", *fmt(F2, 'G'), "\n"); + print("F4\t", *fmt(F4, 'G'), "\tF6\t", *fmt(F6, 'G'), "\n"); + print("F8\t", *fmt(F8, 'G'), "\tF10\t", *fmt(F10, 'G'), "\n"); + print("F12\t", *fmt(F12, 'G'), "\tF14\t", *fmt(F14, 'G'), "\n"); + print("F16\t", *fmt(F16, 'G'), "\tF18\t", *fmt(F18, 'G'), "\n"); + print("F20\t", *fmt(F20, 'G'), "\tF22\t", *fmt(F22, 'G'), "\n"); + print("F24\t", *fmt(F24, 'G'), "\tF26\t", *fmt(F26, 'G'), "\n"); + print("F28\t", *fmt(F28, 'G'), "\tF30\t", *fmt(F30, 'G'), "\n"); +} + +defn fpr() +{ + print("F0\t", *fmt(F0, 'g'), "\tF1\t", *fmt(F1, 'g'), "\n"); + print("F2\t", *fmt(F2, 'g'), "\tF3\t", *fmt(F3, 'g'), "\n"); + print("F4\t", *fmt(F4, 'g'), "\tF5\t", *fmt(F5, 'g'), "\n"); + print("F6\t", *fmt(F6, 'g'), "\tF7\t", *fmt(F7, 'g'), "\n"); + print("F8\t", *fmt(F8, 'g'), "\tF9\t", *fmt(F9, 'g'), "\n"); + print("F10\t", *fmt(F10, 'g'), "\tF11\t", *fmt(F11, 'g'), "\n"); + print("F12\t", *fmt(F12, 'g'), "\tF13\t", *fmt(F13, 'g'), "\n"); + print("F14\t", *fmt(F14, 'g'), "\tF15\t", *fmt(F15, 'g'), "\n"); + print("F16\t", *fmt(F16, 'g'), "\tF17\t", *fmt(F17, 'g'), "\n"); + print("F18\t", *fmt(F18, 'g'), "\tF19\t", *fmt(F19, 'g'), "\n"); + print("F20\t", *fmt(F20, 'g'), "\tF21\t", *fmt(F21, 'g'), "\n"); + print("F22\t", *fmt(F22, 'g'), "\tF23\t", *fmt(F23, 'g'), "\n"); + print("F24\t", *fmt(F24, 'g'), "\tF25\t", *fmt(F25, 'g'), "\n"); + print("F26\t", *fmt(F26, 'g'), "\tF27\t", *fmt(F27, 'g'), "\n"); + print("F28\t", *fmt(F28, 'g'), "\tF29\t", *fmt(F29, 'g'), "\n"); + print("F30\t", *fmt(F30, 'g'), "\tF31\t", *fmt(F31, 'g'), "\n"); +} + +defn spr() // print special processor registers +{ + local pc, link, cause; + + pc = *PC; + print("PC\t", pc, " ", fmt(pc, 'a'), " "); + pfl(pc); + + link = *R31; + print("SP\t", *SP, "\tLINK\t", link, " ", fmt(link, 'a'), " "); + pfl(link); + + cause = *CAUSE; + print("STATUS\t", *STATUS, "\tCAUSE\t", cause, " ", reason(cause), "\n"); + print("TLBVIR\t", *TLBVIRT, "\tBADVADR\t", *BADVADDR, "\n"); + + print("HI\t", *HI, "\tLO\t", *LO, "\n"); +} + +defn regs() // print all registers +{ + spr(); + gpr(); +} + +defn pstop(pid) +{ + local l, pc; + + pc = *PC; + + print(pid,": ", reason(*CAUSE), "\t"); + print(fmt(pc, 'a'), "\t", fmt(pc, 'i'), "\n"); + + if notes then { + if notes[0] != "sys: breakpoint" then { + print("Notes pending:\n"); + l = notes; + while l do { + print("\t", head l, "\n"); + l = tail l; + } + } + } +} + +sizeofUreg = 152; +aggr Ureg +{ + 'X' 0 status; + 'X' 4 pc; + { + 'X' 8 sp; + 'X' 8 usp; + }; + 'X' 12 cause; + 'X' 16 badvaddr; + 'X' 20 tlbvirt; + 'X' 24 hi; + 'X' 28 lo; + 'X' 32 r31; + 'X' 36 r30; + 'X' 40 r28; + 'X' 44 r27; + 'X' 48 r26; + 'X' 52 r25; + 'X' 56 r24; + 'X' 60 r23; + 'X' 64 r22; + 'X' 68 r21; + 'X' 72 r20; + 'X' 76 r19; + 'X' 80 r18; + 'X' 84 r17; + 'X' 88 r16; + 'X' 92 r15; + 'X' 96 r14; + 'X' 100 r13; + 'X' 104 r12; + 'X' 108 r11; + 'X' 112 r10; + 'X' 116 r9; + 'X' 120 r8; + 'X' 124 r7; + 'X' 128 r6; + 'X' 132 r5; + 'X' 136 r4; + 'X' 140 r3; + 'X' 144 r2; + 'X' 148 r1; +}; + +defn +Ureg(addr) { + complex Ureg addr; + print(" status ", addr.status, "\n"); + print(" pc ", addr.pc, "\n"); + print(" sp ", addr.sp, "\n"); + print(" cause ", addr.cause, "\n"); + print(" badvaddr ", addr.badvaddr, "\n"); + print(" tlbvirt ", addr.tlbvirt, "\n"); + print(" hi ", addr.hi, "\n"); + print(" lo ", addr.lo, "\n"); + print(" r31 ", addr.r31, "\n"); + print(" r30 ", addr.r30, "\n"); + print(" r28 ", addr.r28, "\n"); + print(" r27 ", addr.r27, "\n"); + print(" r26 ", addr.r26, "\n"); + print(" r25 ", addr.r25, "\n"); + print(" r24 ", addr.r24, "\n"); + print(" r23 ", addr.r23, "\n"); + print(" r22 ", addr.r22, "\n"); + print(" r21 ", addr.r21, "\n"); + print(" r20 ", addr.r20, "\n"); + print(" r19 ", addr.r19, "\n"); + print(" r18 ", addr.r18, "\n"); + print(" r17 ", addr.r17, "\n"); + print(" r16 ", addr.r16, "\n"); + print(" r15 ", addr.r15, "\n"); + print(" r14 ", addr.r14, "\n"); + print(" r13 ", addr.r13, "\n"); + print(" r12 ", addr.r12, "\n"); + print(" r11 ", addr.r11, "\n"); + print(" r10 ", addr.r10, "\n"); + print(" r9 ", addr.r9, "\n"); + print(" r8 ", addr.r8, "\n"); + print(" r7 ", addr.r7, "\n"); + print(" r6 ", addr.r6, "\n"); + print(" r5 ", addr.r5, "\n"); + print(" r4 ", addr.r4, "\n"); + print(" r3 ", addr.r3, "\n"); + print(" r2 ", addr.r2, "\n"); + print(" r1 ", addr.r1, "\n"); +}; + +defn linkreg(addr) +{ + complex Ureg addr; + return addr.r31\X; +} + +print(acidfile); blob - /dev/null blob + ea6f992209c071f5e7bfbec4fcf27198d665fa65 (mode 644) --- /dev/null +++ acid/network @@ -0,0 +1,169 @@ +_ni=0; // network indent level + +defn +_ni() { + loop 1,_ni do { + print("\t"); + } +} + +defn +ipdev(n) { + _ipfs(*(ipfs+4*n)); +} + +// the funny _foo/foo pairs exist so that if we get +// interrupted in the middle of one of these, _ni will +// get reset to 0 next time an external call happens. + +defn +_ipfs(fs) { + complex Fs fs; + local i; + + print("ipfs(", fs\X, ") #I", fs.dev\D, "\n"); + i=0; + _ni = _ni+1; + while i < fs.np do { + _proto(*(fs.p+i*4)); + i = i + 1; + } + _ni = _ni-1; +} + +defn +ipfs(fs) { + _ni = 0; + _ipfs(fs); +} + +defn +_proto(p) { + local c; + complex Proto p; + _ni(); + print("proto(", p\X, ") ", *(p.name\s), "\n"); + _ni = _ni+1; + local i; + i = 0; + while i < p.nc do { + c = *(p.conv+i*4); + complex Conv c; + if c != 0 && c.inuse then + _conv(*(p.conv+i*4)); + i = i + 1; + } + _ni = _ni - 1; +} + +defn +proto(p) { + _ni = 0; + _proto(p); +} + +defn +_conv(c) { + complex Conv c; + _ni(); + local p; + p = c.p; + complex Proto p; + print("conv(", c\X, ") ", *(p.name\s), "/", c.x\D, " ", + iptostr(*(c.laddr+12)), "!", c.lport\D, " ", iptostr(*(c.raddr+12)), + "!", c.rport\D, " rq ", qtostr(c.rq), " wq ", qtostr(c.wq), + " eq ", qtostr(c.eq), "\n"); +} + +defn +conv(c) { + _ni = 0; + _conv(c); +} + +defn +iptostr(a) +{ + // BUG: little endian + return itoa(a&0xFF)+"."+itoa((a>>8)&0xFF)+"."+itoa((a>>16)&0xFF)+"."+itoa((a>>24)&0xFF); +} + +defn +qtostr(q) +{ + complex Queue q; + + return "queue("+itoa(q, "%lux")+") ["+itoa(q.len, "%d")+","+itoa(q.dlen, "%d")+","+itoa(qblocks(q), "%d")+"]"; +} + +defn +qblocks(q) +{ + complex Queue q; + local b, n; + + b = q.bfirst; + n = 0; + while b != 0 do { + n = n + 1; + complex Block b; + b = b.next; + } + return n; +} + +defn +_queue(q) +{ + complex Queue q; + local b; + + print("queue(", q\X, ") len ", q.len\D, " dlen ", q.dlen\D, " limit ", q.limit\D, " nblocks ", qblocks(q)\D); + if q.state & Qstarve then + print(" starve"); + if q.state & Qmsg then + print(" msg"); + if q.state & Qclosed then + print(" closed"); + if q.state & Qflow then + print(" flow"); + if q.state & Qcoalesce then + print(" coalesce"); + print("\n"); + + b = q.bfirst; + _ni = _ni+1; + while b != 0 do { + _block(b); + complex Block b; + b = b.next; + } + _ni = _ni - 1; +} + +defn +queue(q) +{ + _ni = 0; + _queue(q); +} + +defn +_block(b) +{ + complex Block b; + + _ni(); + print("block(", b\X, ") base ", b.base\X, " rp ", b.rp\X, "/", b.rp-b.base\D, " wp ", b.wp\X, "/", b.wp-b.base\D, " lim ", b.lim\X, "/", b.lim-b.base\D, "\n"); +} + +defn +block(b) +{ + _ni = 0; + block(b); +} + +print(acidfile); +needacid("tcp"); +needacid("qio"); blob - /dev/null blob + d49c4ea1338dee9109a5733ebef99c1e05e52fd9 (mode 644) --- /dev/null +++ acid/pool @@ -0,0 +1,306 @@ +include("/sys/src/libc/port/pool.acid"); + +aggr Byte { + 'b' 0 byte; +}; + +defn +byteat(addr) +{ + local x; + complex Byte addr; + x = addr.byte; + return x\d; +} + +defn +B2T(addr) { + complex Bhdr addr; + addr = addr+addr.size-sizeofBtail; + complex Btail addr; + return addr; +} + +defn +B2D(addr) { + local x; + x = addr+sizeofBhdr; + return x\X; +} + +defn +D2B(addr) { + local x; + x = addr-sizeofBhdr; + complex Bhdr x; + return x; +} + +defn +B2NB(addr) { + complex Bhdr addr; + addr = addr+addr.size; + complex Bhdr addr; + return addr; +} + +defn +A2TB(addr) { + local b; + complex Arena addr; + b = addr+addr.asize-sizeofBhdr; + complex Bhdr b; + return b; +} + +defn +A2B(addr) { + return B2NB(addr); +} + +defn +B2PT(addr) { + complex Bhdr addr; + addr = addr-sizeofBtail; + complex Btail addr; + return addr; +} + +defn +SHORT(addr) { + local hi, lo; + + hi = byteat(addr); + lo = byteat(addr+1); + return lo+hi*256; +} + +defn +Btail(addr) { + complex Btail addr; + print(" magic0 ", addr.magic0, "\n"); + print(" datadiff ", SHORT(addr.datasize), "\n"); + print(" magic1 ", addr.magic1, "\n"); + print(" size ", addr.size\X, "\n"); + print(" hdr ", addr+sizeofBtail-addr.size\X, "\n"); +}; + +defn +Tail(addr) +{ + print(" ", B2T(addr)\X, "\n"); + Btail(B2T(addr)); +} + +defn +Magic(m) +{ + if m == FREE_MAGIC then + return "free"; + if m == ARENA_MAGIC then + return "arena"; + if m == UNKEMPT_MAGIC then + return "unkempt"; + if m == KEMPT_MAGIC then + return "kempt"; + if m == ARENATAIL_MAGIC then + return "arenatail"; + if m == DEAD_MAGIC then + return "dead"; + return "unknown magic"; +} + +defn +Block(addr) +{ + complex Bhdr addr; + print(" ", Magic(addr.magic), "\n"); + print(" data ", B2D(addr), "\n"); + print(" datasize ", getdsize(addr), "\n"); + Bhdr(addr); + Tail(addr); +} + +defn +getdsize(addr) +{ + complex Bhdr addr; + local x; + + x = addr.size\d; + x = x-SHORT(B2T(addr).datasize); + return x\d; +} + +defn +datamagic(x) +{ + x = x%4; + if x == 0 then return 0xFE; + if x == 1 then return 0xF1; + if x == 2 then return 0xF0; + if x == 3 then return 0xFA; +} + +defn +checkblock(addr) +{ + local badmagic, datamagic, a, b, t, q, n, dsize, taddr, checked; + complex Bhdr addr; + taddr = B2T(addr); + complex Btail taddr; + + if addr.magic == FREE_MAGIC || addr.magic == UNKEMPT_MAGIC then { + if taddr.magic0 != TAIL_MAGIC0 || taddr.magic1 != TAIL_MAGIC1 then + print(addr\X, " corrupt tail magic\n"); + if taddr.size != addr.size then + print(addr\X, " corrupt tail header pointer\n"); + } + + if addr.magic == ARENA_MAGIC then { + taddr = A2TB(addr); + if taddr.magic != ARENATAIL_MAGIC then + print(addr\X, " arena with bad tail block\n"); + else + addr = taddr; + } + + if addr.magic == ARENATAIL_MAGIC then { + if addr.size != 0 then + print(addr\X, " bad size in arena tail\n"); + } + + if addr.magic == KEMPT_MAGIC then { + a = addr; + complex Alloc a; + if a.size > 1024*1024*1024 then + print(addr\X, " block ridiculously large\n"); + t = B2T(addr); + if t.magic0 != TAIL_MAGIC0 || t.magic1 != TAIL_MAGIC1 then + print(addr\X, " bad tail magic\n"); + if t.size != addr.size then + print(addr\X, " bad tail pointer\n"); + dsize = getdsize(a); + if dsize > a.size then + print(addr\X, " too much data in block\n"); + q = B2D(a)\X+dsize; + n = 4; + if q+4 > t then + n = t-q; + badmagic = 0; + loop 0,n-1 do { + if byteat(q) != datamagic(q) then { + badmagic=1; + } + q = q+1; + } + if badmagic then + print(addr\X, " size ", dsize, " user has overwritten boundary\n"); + } +} + +defn +checkarena(arena) +{ + local atail, b; + + atail = A2TB(arena); + complex Bhdr arena; + b = arena; + while b.magic != ARENATAIL_MAGIC && b < atail do { + checkblock(b); + if B2NB(b) == b then { + print("B2NB(", b\X, ") = b\n"); + b = atail; // end loop + } + b = B2NB(b); + } + + checkblock(b); + if b != atail then + print("found wrong tail to arena ", arena\X, "\n"); +} + +defn +checkpool(p) +{ + complex Pool p; + local a; + a = p.arenalist; + + while a != 0 do { + complex Arena a; + checkarena(a); + a = a.down; + } +} + +defn +gendumptree(f, in, s) +{ + complex Free f; + + loop 1,in do {print(" ");} + print(s, " size ", f.size\D, " left ", f.left\X, " right ", f.right\X, "\n"); + if f.left != 0 && f.left < 0x7FFFFFFF then + gendumptree(f.left, in+1, "l"); + if f.right != 0 && f.right < 0x7FFFFFFF then + gendumptree(f.right, in+1, "r"); +} + +defn +dumptree(f) +{ + gendumptree(f, 0, "*"); +} + +defn +poolwhopointsat(p, addr) +{ + complex Pool p; + local a; + + a = p.arenalist; + while a != 0 do { + complex Arena a; + arenawhopointsat(a, addr); + a = a.down; + } +} + +defn +arenawhopointsat(arena, addr) +{ + local atail, b; + + atail = A2TB(arena); + complex Bhdr arena; + b = arena; + while b < atail do { + if *b == addr then + print(b\X, "\n"); + b = b+4; + } +} + +defn +whopointsat(addr) +{ + poolwhopointsat(*mainmem, addr); +} + +defn +blockhdr(addr) +{ + addr = addr & ~3; + + while *addr != FREE_MAGIC + && *addr != ARENA_MAGIC + && *addr != UNKEMPT_MAGIC + && *addr != KEMPT_MAGIC + && *addr != ARENATAIL_MAGIC + do + addr = addr-4; + return addr; +} + blob - /dev/null blob + d0d9107d0e6892b5f58f51bcfc4f1d5505c942cf (mode 644) --- /dev/null +++ acid/port @@ -0,0 +1,599 @@ +// portable acid for all architectures + +defn pfl(addr) +{ + print(pcfile(addr), ":", pcline(addr), "\n"); +} + +defn +notestk(addr) +{ + local pc, sp; + complex Ureg addr; + + pc = addr.pc\X; + sp = addr.sp\X; + + print("Note pc:", pc, " sp:", sp, " ", fmt(pc, 'a'), " "); + pfl(pc); + _stk({"PC", pc, "SP", sp, linkreg(addr)}, 1); +} + +defn +notelstk(addr) +{ + local pc, sp; + complex Ureg addr; + + pc = addr.pc\X; + sp = addr.sp\X; + + print("Note pc:", pc, " sp:", sp, " ", fmt(pc, 'a'), " "); + pfl(pc); + _stk({"PC", pc, "SP", sp, linkreg(addr)}, 1); +} + +defn labstk(l) // trace from a label +{ + _stk({"PC", *(l+4), "SP", *l, linkreg(0)}, 0); +} + +defn params(param) +{ + while param do { + sym = head param; + print(sym[0], "=", itoa(sym[1], "%ux")); + param = tail param; + if param then + print (","); + } +} + +stkprefix = ""; +stkignore = {}; +stkend = 0; + +defn locals(l) +{ + local sym; + + while l do { + sym = head l; + print(stkprefix, "\t", sym[0], "=", itoa(sym[1], "%ux"), "\n"); + l = tail l; + } +} + +defn _stkign(file) +{ + s = stkignore; + while s do { + if regexp(head s, file) then + return 1; + s = tail s; + } + return 0; +} + +// print a stack trace +// +// in a run of leading frames in files matched by regexps in stkignore, +// only print the last one. +defn _stk(regs, dolocals) +{ + local stk, pc, fn, callerpc, paramlist, locallist; + + stk = strace(regs); + if stkignore then { + while stk && tail stk && _stkign((head tail stk)[1]) do + stk = tail stk; + } + + callerpc = 0; + while stk do { + frame = head stk; + stk = tail stk; + fn = frame[0]; + pc = frame[1]; + callerpc = frame[2]; + paramlist = frame[3]; + locallist = frame[4]; + + print(stkprefix, fmt(fn, 'a'), "("); + params(paramlist); + print(")"); + if pc != fn then + print("+", itoa(pc-fn, "%ux")); + print(" "); + pfl(pc); + if dolocals then + locals(locallist); + } + + if callerpc then { + print(stkprefix, fmt(callerpc, 'a'), " "); + pfl(callerpc); + } +} + +defn findsrc(file) +{ + local lst, src; + + if file[0] == '/' then { + src = file(file); + if src != {} then { + srcfiles = append srcfiles, file; + srctext = append srctext, src; + return src; + } + return {}; + } + + lst = srcpath; + while head lst do { + src = file(head lst+file); + if src != {} then { + srcfiles = append srcfiles, file; + srctext = append srctext, src; + return src; + } + lst = tail lst; + } +} + +defn line(addr) +{ + local src, file; + + file = pcfile(addr); + src = match(file, srcfiles); + + if src >= 0 then + src = srctext[src]; + else + src = findsrc(file); + + if src == {} then { + print("no source for ", file, "\n"); + return {}; + } + line = pcline(addr)-1; + print(file, ":", src[line], "\n"); +} + +defn addsrcdir(dir) +{ + dir = dir+"/"; + + if match(dir, srcpath) >= 0 then { + print("already in srcpath\n"); + return {}; + } + + srcpath = {dir}+srcpath; +} + +defn source() +{ + local l; + + l = srcpath; + while l do { + print(head l, "\n"); + l = tail l; + } + l = srcfiles; + + while l do { + print("\t", head l, "\n"); + l = tail l; + } +} + +defn Bsrc(addr) +{ + local lst; + + lst = srcpath; + file = pcfile(addr); + if file[0] == '/' && access(file) then { + rc("B "+file+":"+itoa(pcline(addr))); + return {}; + } + while head lst do { + name = head lst+file; + if access(name) then { + rc("B "+name+":"+itoa(pcline(addr))); + return {}; + } + lst = tail lst; + } + print("no source for ", file, "\n"); +} + +defn srcline(addr) +{ + local text, cline, line, file, src; + file = pcfile(addr); + src = match(file,srcfiles); + if (src>=0) then + src = srctext[src]; + else + src = findsrc(file); + if (src=={}) then + { + return "(no source)"; + } + return src[pcline(addr)-1]; +} + +defn src(addr) +{ + local src, file, line, cline, text; + + file = pcfile(addr); + src = match(file, srcfiles); + + if src >= 0 then + src = srctext[src]; + else + src = findsrc(file); + + if src == {} then { + print("no source for ", file, "\n"); + return {}; + } + + cline = pcline(addr)-1; + print(file, ":", cline+1, "\n"); + line = cline-5; + loop 0,10 do { + if line >= 0 then { + if line == cline then + print(">"); + else + print(" "); + text = src[line]; + if text == {} then + return {}; + print(line+1, "\t", text, "\n"); + } + line = line+1; + } +} + +defn step() // single step the process +{ + local lst, lpl, addr, bput; + + bput = 0; + if match(*PC, bplist) >= 0 then { // Sitting on a breakpoint + bput = fmt(*PC, bpfmt); + *bput = @bput; + } + + lst = follow(*PC); + + lpl = lst; + while lpl do { // place break points + *(head lpl) = bpinst; + lpl = tail lpl; + } + + startstop(pid); // do the step + + while lst do { // remove the breakpoints + addr = fmt(head lst, bpfmt); + *addr = @addr; + lst = tail lst; + } + if bput != 0 then + *bput = bpinst; +} + +defn bpset(addr) // set a breakpoint +{ + if status(pid) != "Stopped" then { + print("Waiting...\n"); + stop(pid); + } + if match(addr, bplist) >= 0 then + print("breakpoint already set at ", fmt(addr, 'a'), "\n"); + else { + *fmt(addr, bpfmt) = bpinst; + bplist = append bplist, addr; + } +} + +defn bptab() // print a table of breakpoints +{ + local lst, addr; + + lst = bplist; + while lst do { + addr = head lst; + print("\t", fmt(addr, 'X'), " ", fmt(addr, 'a'), " ", fmt(addr, 'i'), "\n"); + lst = tail lst; + } +} + +defn bpdel(addr) // delete a breakpoint +{ + local n, pc, nbplist; + + n = match(addr, bplist); + if n < 0 then { + print("no breakpoint at ", fmt(addr, 'a'), "\n"); + return {}; + } + + addr = fmt(addr, bpfmt); + *addr = @addr; + + nbplist = {}; // delete from list + while bplist do { + pc = head bplist; + if pc != addr then + nbplist = append nbplist, pc; + bplist = tail bplist; + } + bplist = nbplist; // delete from memory +} + +defn cont() // continue execution +{ + local addr; + + addr = fmt(*PC, bpfmt); + if match(addr, bplist) >= 0 then { // Sitting on a breakpoint + *addr = @addr; + step(); // Step over + *addr = bpinst; + } + startstop(pid); // Run +} + +defn stopped(pid) // called from acid when a process changes state +{ + pstop(pid); // stub so this is easy to replace +} + +defn procs() // print status of processes +{ + local c, lst, cpid; + + cpid = pid; + lst = proclist; + while lst do { + np = head lst; + setproc(np); + if np == cpid then + c = '>'; + else + c = ' '; + print(fmt(c, 'c'), np, ": ", status(np), " at ", fmt(*PC, 'a'), " setproc(", np, ")\n"); + lst = tail lst; + } + pid = cpid; + if pid != 0 then + setproc(pid); +} + +_asmlines = 30; + +defn asm(addr) +{ + local bound; + + bound = fnbound(addr); + + addr = fmt(addr, 'i'); + loop 1,_asmlines do { + print(fmt(addr, 'a'), " ", fmt(addr, 'X')); + print("\t", @addr++, "\n"); + if bound != {} && addr > bound[1] then { + lasmaddr = addr; + return {}; + } + } + lasmaddr = addr; +} + +defn casm() +{ + asm(lasmaddr); +} + +defn win() +{ + local npid, estr; + + bplist = {}; + notes = {}; + + estr = "/sys/lib/acid/window '0 0 600 400' "+textfile; + if progargs != "" then + estr = estr+" "+progargs; + + npid = rc(estr); + npid = atoi(npid); + if npid == 0 then + error("win failed to create process"); + + setproc(npid); + stopped(npid); +} + +defn win2() +{ + local npid, estr; + + bplist = {}; + notes = {}; + + estr = "/sys/lib/acid/transcript '0 0 600 400' '100 100 700 500' "+textfile; + if progargs != "" then + estr = estr+" "+progargs; + + npid = rc(estr); + npid = atoi(npid); + if npid == 0 then + error("win failed to create process"); + + setproc(npid); + stopped(npid); +} + +defn new() +{ + bplist = {}; + newproc(progargs); + // Dont miss the delay slot calls + bpset(follow(main)[0]); + cont(); + bpdel(*PC); +} + +defn stmnt() // step one statement +{ + local line; + + line = pcline(*PC); + while 1 do { + step(); + if line != pcline(*PC) then { + src(*PC); + return {}; + } + } +} + +defn func() // step until we leave the current function +{ + local bound, end, start, pc; + + bound = fnbound(*PC); + if bound == {} then { + print("cannot locate text symbol\n"); + return {}; + } + + pc = *PC; + start = bound[0]; + end = bound[1]; + while pc >= start && pc < end do { + step(); + pc = *PC; + } +} + +defn next() +{ + local sp, bound; + + sp = *SP; + bound = fnbound(*PC); + stmnt(); + pc = *PC; + if pc >= bound[0] && pc < bound[1] then + return {}; + + while (pc < bound[0] || pc > bound[1]) && sp >= *SP do { + step(); + pc = *PC; + } + src(*PC); +} + +defn maps() +{ + local m, mm; + + m = map(); + while m != {} do { + mm = head m; + m = tail m; + print(mm[2]\X, " ", mm[3]\X, " ", mm[4]\X, " ", mm[0], " ", mm[1], "\n"); + } +} + +defn dump(addr, n, fmt) +{ + loop 0, n do { + print(fmt(addr, 'X'), ": "); + addr = mem(addr, fmt); + } +} + +defn mem(addr, fmt) +{ + + local i, c, n; + + i = 0; + while fmt[i] != 0 do { + c = fmt[i]; + n = 0; + while '0' <= fmt[i] && fmt[i] <= '9' do { + n = 10*n + fmt[i]-'0'; + i = i+1; + } + if n <= 0 then n = 1; + addr = fmt(addr, fmt[i]); + while n > 0 do { + print(*addr++, " "); + n = n-1; + } + i = i+1; + } + print("\n"); + return addr; +} + +defn symbols(pattern) +{ + local l, s; + + l = symbols; + while l do { + s = head l; + if regexp(pattern, s[0]) then + print(s[0], "\t", s[1], "\t", s[2], "\t", s[3], "\n"); + l = tail l; + } +} + +defn havesymbol(name) +{ + local l, s; + + l = symbols; + while l do { + s = head l; + l = tail l; + if s[0] == name then + return 1; + } + return 0; +} + +defn spsrch(len) +{ + local addr, a, s, e; + + addr = *SP; + s = origin & 0x7fffffff; + e = etext & 0x7fffffff; + loop 1, len do { + a = *addr++; + c = a & 0x7fffffff; + if c > s && c < e then { + print("src(", a, ")\n"); + pfl(a); + } + } +} + +progargs=""; +print(acidfile); blob - /dev/null blob + caa5aa488dbd530bf306ef510cfcc3239114fa6d (mode 644) --- /dev/null +++ acid/power @@ -0,0 +1,120 @@ +// Power PC support + +defn acidinit() // Called after all the init modules are loaded +{ + bplist = {}; + bpfmt = 'X'; + + srcpath = { + "./", + "/sys/src/libc/port/", + "/sys/src/libc/9sys/", + "/sys/src/libc/power/" + }; + + srcfiles = {}; // list of loaded files + srctext = {}; // the text of the files +} + +defn stk() // trace +{ + _stk(*PC, *SP, linkreg(0), 0); +} + +defn lstk() // trace with locals +{ + _stk(*PC, *SP, linkreg(0), 1); +} + +defn gpr() // print general purpose registers +{ + print("SP\t", *SP, " R2\t", *R2, " R3\t", *R3, "\n"); + print("R4\t", *R4, " R5\t", *R5, " R6\t", *R6, "\n"); + print("R7\t", *R7, " R8\t", *R8, " R9\t", *R9, "\n"); + print("R10\t", *R10, " R11\t", *R11, " R12\t", *R12, "\n"); + print("R13\t", *R13, " R14\t", *R14, " R15\t", *R15, "\n"); + print("R16\t", *R16, " R17\t", *R17, " R18\t", *R18, "\n"); + print("R19\t", *R19, " R20\t", *R20, " R21\t", *R21, "\n"); + print("R22\t", *R22, " R23\t", *R23, " R24\t", *R24, "\n"); + print("R25\t", *R25, " R26\t", *R26, " R27\t", *R27, "\n"); + print("R28\t", *R28, " R29\t", *R29, " R30\t", *R30, "\n"); + print("R31\t", *R31, "\n"); +} + +defn Fpr() +{ + fpr(); +} + +defn fpr() +{ + print("F0\t", *fmt(F0, 'G'), "\tF1\t", *fmt(F1, 'G'), "\n"); + print("F2\t", *fmt(F2, 'G'), "\tF3\t", *fmt(F3, 'G'), "\n"); + print("F4\t", *fmt(F4, 'G'), "\tF5\t", *fmt(F5, 'G'), "\n"); + print("F6\t", *fmt(F6, 'G'), "\tF7\t", *fmt(F7, 'G'), "\n"); + print("F8\t", *fmt(F8, 'G'), "\tF9\t", *fmt(F9, 'G'), "\n"); + print("F10\t", *fmt(F10, 'G'), "\tF11\t", *fmt(F11, 'G'), "\n"); + print("F12\t", *fmt(F12, 'G'), "\tF13\t", *fmt(F13, 'G'), "\n"); + print("F14\t", *fmt(F14, 'G'), "\tF15\t", *fmt(F15, 'G'), "\n"); + print("F16\t", *fmt(F16, 'G'), "\tF17\t", *fmt(F17, 'G'), "\n"); + print("F18\t", *fmt(F18, 'G'), "\tF19\t", *fmt(F19, 'G'), "\n"); + print("F20\t", *fmt(F20, 'G'), "\tF21\t", *fmt(F21, 'G'), "\n"); + print("F22\t", *fmt(F22, 'G'), "\tF23\t", *fmt(F23, 'G'), "\n"); + print("F24\t", *fmt(F24, 'G'), "\tF25\t", *fmt(F25, 'G'), "\n"); + print("F26\t", *fmt(F26, 'G'), "\tF27\t", *fmt(F27, 'G'), "\n"); + print("F28\t", *fmt(F28, 'G'), "\tF29\t", *fmt(F29, 'G'), "\n"); + print("F30\t", *fmt(F30, 'G'), "\tF31\t", *fmt(F31, 'G'), "\n"); +} + +defn spr() // print special processor registers +{ + local pc, link, cause; + + pc = *PC; + print("PC\t", pc, " ", fmt(pc, 'a'), " "); + pfl(pc); + + link = *R31; + print("SP\t", *SP, "\tLINK\t", link, " ", fmt(link, 'a'), " "); + pfl(link); + + cause = *CAUSE; + print("SRR1\t", *SRR1, "\tCAUSE\t", cause, " ", reason(cause), "\n"); + print("LR\t", *LR, "\tCR\t", *CR, "\n"); + + print("XER\t", *XER, "\tCTR\t", *CTR, "\n"); +} + +defn regs() // print all registers +{ + spr(); + gpr(); +} + +defn pstop(pid) +{ + local l, pc; + + pc = *PC; + + print(pid,": ", reason(*CAUSE), "\t"); + print(fmt(pc, 'a'), "\t", fmt(pc, 'i'), "\n"); + + if notes then { + if notes[0] != "sys: breakpoint" then { + print("Notes pending:\n"); + l = notes; + while l do { + print("\t", head l, "\n"); + l = tail l; + } + } + } +} + +defn linkreg(addr) +{ + return *LR; +} + +print(acidfile); blob - /dev/null blob + 9f6d496f1991a1d5884a27b0cc0f0b52875af356 (mode 644) --- /dev/null +++ acid/sparc @@ -0,0 +1,218 @@ +// Sparc support + +defn acidinit() // Called after all the init modules are loaded +{ + bplist = {}; + bpfmt = 'X'; + + srcpath = { + "./", + "/sys/src/libc/port/", + "/sys/src/libc/9sys/", + "/sys/src/libc/sparc/" + }; + + srcfiles = {}; // list of loaded files + srctext = {}; // the text of the files +} + +defn stk() // trace +{ + _stk(*PC, *R1, linkreg(0), 0); +} + +defn lstk() // trace with locals +{ + _stk(*PC, *R1, linkreg(0), 1); +} + +defn gpr() // print general purpose registers +{ + print("R1\t", *R1, "R2\t", *R2, "R3\t", *R3, "\n"); + print("R4\t", *R4, "R5\t", *R5, "R6\t", *R6, "\n"); + print("R7\t", *R7, "R8\t", *R8, "R9\t", *R9, "\n"); + print("R10\t", *R10, "R11\t", *R11, "R12\t", *R12, "\n"); + print("R13\t", *R13, "R14\t", *R14, "R15\t", *R15, "\n"); + print("R16\t", *R16, "R17\t", *R17, "R18\t", *R18, "\n"); + print("R19\t", *R19, "R20\t", *R20, "R21\t", *R21, "\n"); + print("R22\t", *R22, "R23\t", *R23, "R24\t", *R24, "\n"); + print("R25\t", *R25, "R26\t", *R26, "R27\t", *R27, "\n"); + print("R28\t", *R28, "R29\t", *R29, "R30\t", *R30, "\n"); + print("R31\t", *R31, "\n"); +} + +defn spr() // print special processor registers +{ + local pc; + local link; + local cause; + + pc = *PC; + print("PC\t", pc, " ", fmt(pc, 'a'), " "); + pfl(pc); + print("PSR\t", *PSR, "\n"); + + link = *R15; + print("SP\t", *R1, "\tLINK\t\t", link, " ", fmt(link, 'a')); + pfl(link); + + cause = *TBR; + print("Y\t", *Y, "\tCAUSE\t", *Y, cause, " ", reason(cause), "\n"); +} + +defn Fpr() +{ + print("F0\t", *fmt(F0, 'G'), "\tF2\t", *fmt(F2, 'G'), "\n"); + print("F4\t", *fmt(F4, 'G'), "\tF6\t", *fmt(F6, 'G'), "\n"); + print("F8\t", *fmt(F8, 'G'), "\tF10\t", *fmt(F10, 'G'), "\n"); + print("F12\t", *fmt(F12, 'G'), "\tF14\t", *fmt(F14, 'G'), "\n"); + print("F16\t", *fmt(F16, 'G'), "\tF18\t", *fmt(F18, 'G'), "\n"); + print("F20\t", *fmt(F20, 'G'), "\tF22\t", *fmt(F22, 'G'), "\n"); + print("F24\t", *fmt(F24, 'G'), "\tF26\t", *fmt(F26, 'G'), "\n"); + print("F28\t", *fmt(F28, 'G'), "\tF30\t", *fmt(F30, 'G'), "\n"); +} + +defn fpr() +{ + print("F0\t", *fmt(F0, 'g'), "\tF1\t", *fmt(F1, 'g'), "\n"); + print("F2\t", *fmt(F2, 'g'), "\tF3\t", *fmt(F3, 'g'), "\n"); + print("F4\t", *fmt(F4, 'g'), "\tF5\t", *fmt(F5, 'g'), "\n"); + print("F6\t", *fmt(F6, 'g'), "\tF7\t", *fmt(F7, 'g'), "\n"); + print("F8\t", *fmt(F8, 'g'), "\tF9\t", *fmt(F9, 'g'), "\n"); + print("F10\t", *fmt(F10, 'g'), "\tF11\t", *fmt(F11, 'g'), "\n"); + print("F12\t", *fmt(F12, 'g'), "\tF13\t", *fmt(F13, 'g'), "\n"); + print("F14\t", *fmt(F14, 'g'), "\tF15\t", *fmt(F15, 'g'), "\n"); + print("F16\t", *fmt(F16, 'g'), "\tF17\t", *fmt(F17, 'g'), "\n"); + print("F18\t", *fmt(F18, 'g'), "\tF19\t", *fmt(F19, 'g'), "\n"); + print("F20\t", *fmt(F20, 'g'), "\tF21\t", *fmt(F21, 'g'), "\n"); + print("F22\t", *fmt(F22, 'g'), "\tF23\t", *fmt(F23, 'g'), "\n"); + print("F24\t", *fmt(F24, 'g'), "\tF25\t", *fmt(F25, 'g'), "\n"); + print("F26\t", *fmt(F26, 'g'), "\tF27\t", *fmt(F27, 'g'), "\n"); + print("F28\t", *fmt(F28, 'g'), "\tF29\t", *fmt(F29, 'g'), "\n"); + print("F30\t", *fmt(F30, 'g'), "\tF31\t", *fmt(F31, 'g'), "\n"); +} + +defn regs() // print all registers +{ + spr(); + gpr(); +} + +defn pstop(pid) +{ + local l; + local pc; + + pc = *PC; + + print(pid,": ", reason(*TBR), "\t"); + print(fmt(pc, 'a'), "\t", fmt(pc, 'i'), "\n"); + + if notes then { + if notes[0] != "sys: breakpoint" then { + print("Notes pending:\n"); + l = notes; + while l do { + print("\t", head l, "\n"); + l = tail l; + } + } + } +} + +aggr Ureg +{ + 'U' 0 r0; + { + 'U' 4 sp; + 'U' 4 usp; + 'U' 4 r1; + }; + 'U' 8 r2; + 'U' 12 r3; + 'U' 16 r4; + 'U' 20 r5; + 'U' 24 r6; + 'U' 28 r7; + 'U' 32 r8; + 'U' 36 r9; + 'U' 40 r10; + 'U' 44 r11; + 'U' 48 r12; + 'U' 52 r13; + 'U' 56 r14; + 'U' 60 r15; + 'U' 64 r16; + 'U' 68 r17; + 'U' 72 r18; + 'U' 76 r19; + 'U' 80 r20; + 'U' 84 r21; + 'U' 88 r22; + 'U' 92 r23; + 'U' 96 r24; + 'U' 100 r25; + 'U' 104 r26; + 'U' 108 r27; + 'U' 112 r28; + 'U' 116 r29; + 'U' 120 r30; + 'U' 124 r31; + 'U' 128 y; + 'U' 132 tbr; + 'U' 136 psr; + 'U' 140 npc; + 'U' 144 pc; + 'U' 148 pad; +}; + +defn +Ureg(addr) { + complex Ureg addr; + print(" r0 ", addr.r0, "\n"); + print(" sp ", addr.sp, "\n"); + print(" r2 ", addr.r2, "\n"); + print(" r3 ", addr.r3, "\n"); + print(" r4 ", addr.r4, "\n"); + print(" r5 ", addr.r5, "\n"); + print(" r6 ", addr.r6, "\n"); + print(" r7 ", addr.r7, "\n"); + print(" r8 ", addr.r8, "\n"); + print(" r9 ", addr.r9, "\n"); + print(" r10 ", addr.r10, "\n"); + print(" r11 ", addr.r11, "\n"); + print(" r12 ", addr.r12, "\n"); + print(" r13 ", addr.r13, "\n"); + print(" r14 ", addr.r14, "\n"); + print(" r15 ", addr.r15, "\n"); + print(" r16 ", addr.r16, "\n"); + print(" r17 ", addr.r17, "\n"); + print(" r18 ", addr.r18, "\n"); + print(" r19 ", addr.r19, "\n"); + print(" r20 ", addr.r20, "\n"); + print(" r21 ", addr.r21, "\n"); + print(" r22 ", addr.r22, "\n"); + print(" r23 ", addr.r23, "\n"); + print(" r24 ", addr.r24, "\n"); + print(" r25 ", addr.r25, "\n"); + print(" r26 ", addr.r26, "\n"); + print(" r27 ", addr.r27, "\n"); + print(" r28 ", addr.r28, "\n"); + print(" r29 ", addr.r29, "\n"); + print(" r30 ", addr.r30, "\n"); + print(" r31 ", addr.r31, "\n"); + print(" y ", addr.y, "\n"); + print(" tbr ", addr.tbr, "\n"); + print(" psr ", addr.psr, "\n"); + print(" npc ", addr.npc, "\n"); + print(" pc ", addr.pc, "\n"); + print(" pad ", addr.pad, "\n"); +}; + +defn linkreg(addr) +{ + complex Ureg addr; + return addr.r15\X; +} + +print(acidfile); blob - /dev/null blob + 754b4449a774f4a3c46f792fa6294a4c9c804a5e (mode 644) --- /dev/null +++ acid/syscall @@ -0,0 +1,196 @@ +// print system calls +defn printstring(s) +{ + print("\"", s, "\""); +} + +defn printtextordata(addr, n) +{ + local a, i; + + a = addr\c; + i = 0; + loop 1, n do { + if (a[i]>=127) then { + print(fmt(addr, 'X'), ", ", n\D); + return {}; + } + i = i+1; + } + + print("\""); + printstringn(addr, n); + print("\""); +} + +defn printstringn(s, n) +{ + local m; + + m = n; + if (m > 100) then m = 100; + loop 1,m do { + print(*(s\c)); s=s+1; + } + if(m != n) then print("..."); +} + +defn printsyscall(name, fmt, arg) { + local f, i, a, argp, sl; + + print(name, "("); + i = 0; + a = eval arg; + while fmt[i] != 0 do { + if fmt[i] == 's' then { + if *a == 0 then + print("nil"); + else + printstring(*(*a\s)); + } else if fmt[i] == 'S' then { + argp = *a; + argl = {}; + while *argp != 0 do { + argl = append argl, *(*argp\s); + argp++; + } + print(argl); + } else if (fmt[i] == 'Z') && (~*a == 0) then { + print("-1"); + a++; // advance extra word for quadword + } else if (fmt[i] == 'Y') || (fmt[i] == 'V') then { + print(fmt(*a, fmt[i])); + a++; // advance extra word for quadword + } else if (fmt[i] == 'T') then { + if *a == 0 then + print("nil"); + else + printtextordata(*a, a[1]); + } else + print(fmt(*a, fmt[i])); + if fmt[i+1] != 0 then + print(", "); + i = i+1; + a++; + } + print(")\n"); +} + +defn code(*e) { return e; } + +syscalls = { + { 0, {"sysr1", "s", code(0)}}, + { 1, {"_errstr", "s", code(*sys_errstr:arg)}}, + { 2, {"bind", "ssX", code(*sysbind:arg)}}, + { 3, {"chdir", "s", code(*sysbind:arg)}}, + { 4, {"close", "D", code(*sysclose:arg)}}, + { 5, {"dup", "DD", code(*sysdup:arg)}}, + { 6, {"alarm", "D", code(*sysalarm:arg)}}, + { 7, {"exec", "sS", code(*sysexec:arg)}}, + { 8, {"exits", "s", code(*sysexits:arg)}}, + { 9, {"_fsession", "DX", code(*sys_fsession:arg)}}, + {10, {"fauth", "DX", code(*sysfauth:arg)}}, + {11, {"_fstat", "DX", code(*sys_fstat:arg)}}, + {12, {"segbrk", "XX", code(*syssegbrk:arg)}}, + {13, {"_mount", "DsXs", code(*sys_mount:arg)}}, + {14, {"open", "sD", code(*sysopen:arg)}}, + {15, {"_read", "DXD", code(*sys_read:arg)}}, + {16, {"oseek", "DDD", code(*sysoseek:arg)}}, + {17, {"sleep", "D", code(*syssleep:arg)}}, + {18, {"_stat", "sX", code(*sys_stat:arg)}}, + {19, {"rfork", "X", code(*sysstat:arg)}}, + {20, {"_write", "DXD", code(*sys_write:arg)}}, + {21, {"pipe", "X", code(*syspipe:arg)}}, + {22, {"create", "sDO", code(*syscreate:arg)}}, + {23, {"fd2path", "DXD", code(*sysfd2path:arg)}}, + {24, {"brk_", "X", code(*sysbrk_:arg)}}, + {25, {"remove", "s", code(*sysremove:arg)}}, + {26, {"_wstat", "sX", code(*sys_wstat:arg)}}, + {27, {"_fwstat", "DX", code(*sys_fwstat:arg)}}, + {28, {"notify", "X", code(*sysnotify:arg)}}, + {29, {"noted", "D", code(*sysnoted:arg)}}, + {30, {"segattach", "DsXD", code(*syssegattach:arg)}}, + {31, {"segdetach", "X", code(*syssegdetach:arg)}}, + {32, {"segfree", "XD", code(*syssegfree:arg)}}, + {33, {"segflush", "XD", code(*syssegflush:arg)}}, + {34, {"rendezvous", "XX", code(*sysrendezvous:arg)}}, + {35, {"unmount", "ss", code(*sysunmount:arg)}}, + {36, {"_wait", "X", code(*sys_wait:arg)}}, + {39, {"seek", "XDVD", code(*sysseek:arg)}}, + {40, {"fversion", "DDsD", code(*sysfversion:arg)}}, + {41, {"errstr", "TD", code(*syserrstr:arg)}}, + {42, {"stat", "sXD", code(*sysstat:arg)}}, + {43, {"fstat", "DXD", code(*sysfstat:arg)}}, + {44, {"wstat", "sXD", code(*syswstat:arg)}}, + {45, {"fwstat", "DXD", code(*sysfwstat:arg)}}, + {46, {"mount", "DDsXs", code(*sysmount:arg)}}, + {47, {"await", "TD", code(*sysawait:arg)}}, + {50, {"pread", "DXDZ", code(*syspread:arg)}}, + {51, {"pwrite", "DTDZ", code(*syspwrite:arg)}}, +}; + +defn syscall() { + local n, sl, h, p; + + map({"*data", 0, 0xffffffff, 0}); + n = *syscall:scallnr; + sl = syscalls; + while sl != {} do { + h = head sl; + sl = tail sl; + + if n == h[0] then { + p = h[1]; + printsyscall(p[0], p[1], p[2]); + } + } +} + +defn UPCSPRET() { + // return sys call number, address of first argument, location of syscall return value + if objtype == "386" then + return { code(*(*PC-4)), code(*SP+4), code(*AX) }; + if (objtype == "mips") || (objtype == "mips2") then + return { code(*(*PC-4) & 0xffff), code(*SP+4), code(*R1) }; + if objtype == "arm" then + return { code(*(*PC-4) & 0xffff), code(*SP+4), code(*R0) }; // untested + if objtype == "alpha" then + return { code(*(*PC-4) & 0xffff), code(*SP+4), code(*R0) }; // untested +} + +defn trapoffset() { + // return offset from entry point to trap instr + if objtype == "386" then return 5; + if objtype == "mips" then return 8; + if objtype == "mips2" then return 8; + if objtype == "arm" then return 8; // untested + if objtype == "alpha" then return 8; // untested +} + +defn trapreason() { + // return reason for trap + if objtype == "386" then return reason(*TRAP); + if objtype == "mips" then return reason(*CAUSE); + if objtype == "mips2" then return reason(*CAUSE); + if objtype == "arm" then return "unknown trap"; // untested + if objtype == "alpha" then return reason(cause); // untested +} + + +defn usyscall() { // gives args for system call in user level; not useful with -k + local n, sl, h, p; + + // stopped at TRAP instruction in system call library + pcsp = UPCSPRET(); + n = eval pcsp[0]; + sl = syscalls; + while sl != {} do { + h = head sl; + sl = tail sl; + + if n == h[0] then { + p = h[1]; + printsyscall(p[0], p[1], pcsp[1]); + } + } +} blob - /dev/null blob + ac4cce8a9b3d3d9f20332de40c98eed5e2f058c5 (mode 644) --- /dev/null +++ acid/thread @@ -0,0 +1,365 @@ + +defn labpc(l) +{ + if objtype == "386" then + return longjmp; + return *(l+4); +} + +defn labsp(l) +{ + return *l; +} + +defn labstk(l) +{ + _stk(labpc(l), labsp(l), 0, 0); +} + +defn lablstk(l) +{ + _stk(labpc(l), labsp(l), 0, 1); +} + +defn altfmt(A){ + local i, s, yes; + complex Alt A; + + s = "alt("; + s = s + "tag(*" + itoa(A.tag, "%x") + "=" + itoa(*A.tag, "%x") + ") "; + i = 0; + yes = 0; + while A.op != CHANEND && A.op != CHANNOBLK do{ + if A.op != CHANNOP then{ + if yes then s = s + " "; + s = s + itoa(i, "%d"); + s = s + ":"; + if A.op == CHANSND then s = s + "send"; + if A.op == CHANRCV then s = s + "recv"; + s = s + "(channel("; + s = s + itoa(A.c, "%x"); + s = s + "))"; + yes = 1; + } + i = i + 1; + A = (Alt)(A + sizeofAlt); + } + if A.op==CHANNOBLK then{ + if yes then s = s + " "; + s = s + "noblock"; + } + s = s + ")"; + return s; +} + +defn alt(A){ + print(altfmt(A), "\n"); +} + +threadignsrc = { + "^/sys/src/libc", + "^/sys/src/libthread", +}; + +defn fnname(a){ + local sym, s; + + s = symbols; + while s do { + sym = head s; + if sym[2] == a then + return sym[0]; + s = tail s; + } + return itoa(a, "%x"); +} + +stkignorelist = {}; + +defn stkignore(s){ + append stkignorelist, s; +} + +defn threadstkline(T){ + local stk, frame, pc, pc0, file, lastpc0, s, sym, i, stop; + + if T.state == Running then{ + pc = *PC; + stk = strace(*PC, *SP, linkreg(0)); + }else{ + pc = labpc(T.sched); + stk = strace(labpc(T.sched), labsp(T.sched), 0); + } + lastpc0 = 0; + pc0 = 0; + stop = 0; + while stk && !stop do { + file = pcfile(pc); + if !regexp("^/sys/src/libc/", file) + && !regexp("^/sys/src/libthread/", file) + && match(file, stkignore)==-1 then + stop = 1; + else{ + lastpc0 = pc0; + frame = head stk; + stk = tail stk; + nextframe = head stk; + pc = frame[1]; + pc0 = nextframe[0]; + } + } + file = pcfile(pc); + s = file+":"+itoa(pcline(pc), "%d"); + if pc0 != 0 then + s = s + " "+fnname(pc0); + return s; +} + +defn threadfmt(T){ + complex Thread T; + local A, yes, i, P, s; + + P = (Proc)T.proc; + s = "t=(Thread)"+itoa(T, "%-10x")+" "; + + if T.state == Running then + s = s + "Running "; + else if T.state == Ready then + s = s + "Ready "; + else if T.state == Rendezvous then + s = s + "Rendez "; + else + s = s + "Bad state "+itoa(T.state, "%x")+" "; + + A = (Alt)T.alt; + if 1 then + s = s + threadstkline(T); + else if T.chan == Chanalt then + s = s + altfmt(T.alt); + else if T.chan == Chansend then + s = s + "send(Channel("+itoa(A.c, "%x")+"))"; + else if T.chan == Chanrecv then + s = s + "recv(Channel("+itoa(A.c, "%x")+"))"; + else + s = s + threadstkline(T); + + if T.moribund == 1 then + s = s + " Moribund"; + if T.cmdname != 0 then + s = s + " ["+*(T.cmdname\s)+"]"; + return s; +} + +defn thread(T){ + print(threadfmt(T), "\n"); +} + +defn pthreads(P){ + complex Proc P; + local T, Tq, mainpid; + + mainpid = pid; + setproc(P.pid); + Tq = (Tqueue)P.threads; + T = (Thread)Tq.$head; + while T != 0 do{ + print("\t"); + thread(T); + T = T.nextt; + } + setproc(mainpid); +} + +defn threads(){ + local P; + + P = (Proc)_threadpq.$head; + while P != 0 do{ + if P != (Proc)_threadpq.$head then print("\n"); + lproc(P); + P = P.next; + } +} + +defn stacks(){ + local P, mainpid; + + mainpid = pid; + P = (Proc)_threadpq.$head; + while P != 0 do{ + proc(P); + // setproc(P.pid); + // if P.thread==0 then{ + // print("=== thread scheduler stack\n"); + // stk(); + // } + // print("threadstks(", P\X, ")\n"); + threadstks(P); + P = P.next; + print("\n"); + } + setproc(mainpid); +} + +defn stacksizes(){ + local P, T, Tq, top, sp, mainpid; + + mainpid = pid; + P = (Proc)_threadpq.$head; + while P != 0 do{ + P = (Proc)P; + Tq = (Tqueue)P.threads; + T = (Thread)Tq.$head; + while T != 0 do{ + top = T.stk+T.stksize; + if T.state==Running then { + sp = *SP; + }else{ + sp = *(T.sched); + } + sp = *(T.sched); + print(top-sp\D, "\n"); + T = T.nextt; + } + P = P.next; + } + setproc(mainpid); +} + +defn lproc(P){ + proc(P); + pthreads(P); +} + +defn threadstks(P){ + complex Proc P; + local T, Tq, mainpid, pref, ign; + + mainpid = pid; + pref = stkprefix; + stkprefix = pref+"\t\t"; + ign = stkignore; + stkignore = { + "^/sys/src/libthread/", + "^/sys/src/libc/(386|arm|alpha|sparc|power|mips)/" + }; + setproc(P.pid); + Tq = (Tqueue)P.threads; + T = (Thread)Tq.$head; + while T != 0 do{ + // print("=============================\n"); + // print(" thread(", T\X, ")\n"); + print("\t"); + thread(T); + threadstk(T); + T = T.nextt; + print("\n"); + } + setproc(mainpid); + stkprefix = pref; + stkignore = ign; +} + +defn proc(P){ + complex Proc P; + + print("p=(Proc)", itoa(P, "%-10x"), " pid ", P.pid\D, " "); + if P.thread==0 then + print(" Sched"); + else + print(" Running"); + print("\n"); +} + +defn procs(){ + local P; + + P = (Proc)_threadpq.$head; + while P != 0 do{ + proc(P); + P = P.next; + } +} + +defn threadlstk(T){ + complex Thread T; + local P, mainpid; + + P = (Proc)T.proc; + mainpid = pid; + setproc(P.pid); + + if T.state == Running then{ + lstk(); + } else { + lablstk(T.sched); + } + setproc(mainpid); +} + +defn threadstk(T){ + complex Thread T; + local P, mainpid; + + P = (Proc)T.proc; + mainpid = pid; + setproc(P.pid); + + if T.state == Running then{ + stk(); + } else { + labstk(T.sched); + } + setproc(mainpid); +} + +defn tqueue(Q) { + complex Tqueue Q; + + while Q != 0 do { + print(Q.$head\X, " "); + Q = *(Q.$tail); + + } + print("#\n"); +} + +defn channel(C) { + complex Channel C; + local i, p; + + print("channel ", C\X); + if C.freed then { + print(" (moribund)"); + } + print("\n"); + print("\telementsize=", C.e\D, " buffersize=", C.s, "\n"); + if C.s then { + print("\t", C.n\D, " values in channel:\n"); + print("\t"); + p = C.v+C.e*(C.f%C.s); + loop 1,C.n do { + if C.e==4 then { + print((*p)\X, " "); + }else { + print("data(", (*p)\X, ") "); + } + p = p+C.e; + if p == C.v+C.s*C.e then { + p = C.v; + } + } + } + print("\n"); + print(C.nentry\D, " queue slots:\n"); + i=0; + loop 1,C.nentry do { + if C.qentry[i] then + print("\t", altfmt(C.qentry[i]), "\n"); + else + print("\t\n"); + i=i+1; + } +} + +print(acidfile); blob - /dev/null blob + 023dabda01c0ac003b9f1e15359da4cc7b261d5b (mode 755) --- /dev/null +++ acid/transcript @@ -0,0 +1,33 @@ +#!/bin/rc +switch($#*){ +case 0 1 2 + echo usage: window '''minx miny maxx maxy''' '''minx miny maxx maxy''' cmd args ... + exit usage +} + +rfork ns + +if(mount $wsys /mnt/acid N`{{echo $pid $1 }| sed 's/^ //g;s/ +/,/g'}){ + winid=`{cat /dev/winid} + echo transcript > /mnt/acid/label + echo transcript > /mnt/acid/cons + shift +} +if not exit 0 + +if(mount $wsys /mnt/wsys N`{{echo $pid $1 }| sed 's/^ //g;s/ +/,/g'}){ + shift + bind -b /mnt/wsys /dev +} +if not exit 0 + +echo -n `{basename $1} > /dev/label >[2] /dev/null +@{ + echo hang > /proc/^`{cat /dev/ppid}^/ctl + $* < /dev/$winid/cons > /dev/$winid/cons >[2] /dev/$winid/cons & + exit $apid +} +ostatus = `{echo $status | sed 's/.*://'} +echo waitstop > /proc/$ostatus/ctl +echo nohang > /proc/$ostatus/ctl +exit $ostatus blob - /dev/null blob + 4921bfce620d39cdbcdd46822dd3de18877effa0 (mode 644) --- /dev/null +++ acid/trump @@ -0,0 +1,171 @@ +// trace user malloc pool - trace malloc, realloc, and free calls +// if trumpsbrk is set, we trace sbrkalloc and sbrkmerge too. + +_stoprunning = 0; +trumphexaddrs = 0; +trumpsbrk = 0; + +defn stopped(pid) { + local l; + local pc; + pc = *PC; + if notes then { + if (notes[0]!="sys: breakpoint") then + { + print(pid,": ",reason(*TRAP),"\t"); + print(fmt(pc,97),"\t",fmt(pc,105),"\n"); + print("Notes pending:\n"); + l = notes; + while l do + { + print("\t",head l,"\n"); + l = tail l; + } + _stoprunning = 1; + } + } +} + +defn printstack() { + local frame, stk, pcs, lst, x; + + pcs = {*PC}; + stk = strace(*PC,*SP,0); + while stk do { + pcs = append pcs, stk[0][1]; + stk = tail stk; + } + + print(" #"); + lst = pcs; + while lst do { + if trumphexaddrs != 0 then + x = lst[0]\X; + else + x = lst[0]\a; + print(" src(", x, ");"); + lst = tail lst; + } + print("\n"); +} + +defn setuptrump() { + mallocPC = malloc; + malloczPC = mallocz; + freePC = free; + reallocPC = realloc; + sbrkallocPC = sbrkalloc; + sbrkmergePC = sbrkmerge; + + // linker might fill delay slot with first instruction + if objtype == "mips" then { + mallocPC = mallocPC+4; + malloczPC = malloczPC+4; + freePC = freePC+4; + reallocPC = reallocPC+4; + sbrkallocPC = sbrkallocPC+4; + sbrkmergePC = sbrkmergePC+4; + } + + bpset(mallocPC); + bpset(malloczPC); + bpset(freePC); + bpset(reallocPC); + if trumpsbrk then { + bpset(sbrkallocPC); + bpset(sbrkmergePC); + } +} + +defn cleantrump() { + stop(pid); + + bpdel(mallocPC); + bpdel(malloczPC); + bpdel(freePC); + bpdel(reallocPC); + bpdel(sbrkallocPC); + bpdel(sbrkmergePC); +} + +defn trumpflush() { + stop(pid); // already stopped, but flushes output +} + +defn new() { + bplist = {}; + newproc(progargs); + bpset(follow(main)[0]); + cont(); + bpdel(*PC); + // clear the hang bit, which is left set by newproc, so programs we fork/exec don't hang + printto("/proc/"+itoa(pid)+"/ctl", "nohang"); +} + +defn trumpfninfo() { + local arg0, arg1, stk, retpc, params; + + stk = strace(*PC, *SP, 0); + retpc = stk[0][1]; + params = stk[0][2]; + arg0 = params[0][1]; + arg1 = 0; + if tail params != {} then + arg1 = params[1][1]; + return {arg0, arg1, retpc}; +} + +defn trumpretval() { + if objtype=="386" then + return *AX; + if objtype=="mips" then + return *R1; + if objtype=="power" || objtype=="alpha" then + return *R0; +} + +defn trump() { + local arg0, arg1, pc, ret, x; + + stop(pid); + _stoprunning = 0; + setuptrump(); + while !_stoprunning do { + cont(); + if notes[0]!="sys: breakpoint" then { + cleantrump(); + return {}; + } + + pc = *PC; + x = trumpfninfo(); + arg0 = x[0]; + if pc == reallocPC || pc == sbrkmergePC then + arg1 = x[1]; + bpset(x[2]); + cont(); + bpdel(x[2]); + ret = trumpretval(); + if pc == mallocPC then + print(ret\X, " malloc ", arg0\D); + if pc == malloczPC then + print(ret\X, " mallocz ", arg0\D); + if pc == freePC then + print(arg0\X, " free"); + if pc == reallocPC then + print(ret\X, " realloc ", arg0\X, " ", arg1\D); + if pc == sbrkallocPC then + print(ret\X, " sbrkalloc ", arg0\D); + if pc == sbrkmergePC then + print("sbrkmerge ", arg0\X, " ", arg1\X, " = ", ret\D); + printstack(); + trumpflush(); + } +} + +defn untrump() { + cleantrump(); + start(pid); +} + +print(acidfile); blob - /dev/null blob + 5c4731f1e2b4da5bfcd4d5001f85b340e2c6b70b (mode 644) --- /dev/null +++ acid/truss @@ -0,0 +1,283 @@ +// poor emulation of SVR5 truss command - traces system calls + +include(acidfile); + +_stoprunning = 0; + +defn stopped(pid) { + local l; + local pc; + pc = *PC; + if notes then { + if (notes[0]!="sys: breakpoint") then + { + print(pid,": ",trapreason(),"\t"); + print(fmt(pc,97),"\t",fmt(pc,105),"\n"); + print("Notes pending:\n"); + l = notes; + while l do + { + print("\t",head l,"\n"); + l = tail l; + } + _stoprunning = 1; + } + } +} + +defn _addressof(pattern) { + local s, l; + l = symbols; + pattern = "^\\$*"+pattern+"$"; + while l do + { + s = head l; + if regexp(pattern, s[0]) && ((s[1] == 'T') || (s[1] == 'L')) then + return s[2]; + l = tail l; + } + return 0; +} + +stopPC = {}; +readPC = {}; +fd2pathPC = {}; +errstrPC = {}; +awaitPC = {}; +_waitPC = {}; +_errstrPC = {}; +trusscalls = { + "sysr1", + "_errstr", + "bind", + "chdir", + "close", + "dup", + "alarm", + "exec", + "_exits", + "_fsession", + "fauth", + "_fstat", + "segbrk", + "_mount", + "open", + "_read", + "oseek", + "sleep", + "_stat", + "rfork", + "_write", + "pipe", + "create", + "fd2path", + "brk_", + "remove", + "_wstat", + "_fwstat", + "notify", + "noted", + "segattach", + "segdetach", + "segfree", + "segflush", + "rendezvous", + "unmount", + "_wait", + "seek", + "fversion", + "errstr", + "stat", + "fstat", + "wstat", + "fwstat", + "mount", + "await", + "pread", + "pwrite", + }; + +trussapecalls = { + "_SYSR1", + "__ERRSTR", + "_BIND", + "_CHDIR", + "_CLOSE", + "_DUP", + "_ALARM", + "_EXEC", + "_EXITS", + "__FSESSION", + "_FAUTH", + "__FSTAT", + "_SEGBRK", + "__MOUNT", + "_OPEN", + "__READ", + "_OSEEK", + "_SLEEP", + "__STAT", + "_RFORK", + "__WRITE", + "_PIPE", + "_CREATE", + "_FD2PATH", + "_BRK_", + "_REMOVE", + "__WSTAT", + "__FWSTAT", + "_NOTIFY", + "_NOTED", + "_SEGATTACH", + "_SEGDETACH", + "_SEGFREE", + "_SEGFLUSH", + "_RENDEZVOUS", + "_UNMOUNT", + "__WAIT", + "_SEEK", + "__NFVERSION", + "__NERRSTR", + "_STAT", + "__NFSTAT", + "__NWSTAT", + "__NFWSTAT", + "__NMOUNT", + "__NAWAIT", + "_PREAD", + "_PWRITE", + }; + +defn addressof(pattern) { + // translate to ape system calls if we have an ape binary + if _addressof("_EXITS") == 0 then + return _addressof(pattern); + return _addressof(trussapecalls[match(pattern, trusscalls)]); +} + +defn setuptruss() { + local lst, offset, name, addr; + + trussbpt = {}; + offset = trapoffset(); + lst = trusscalls; + while lst do + { + name = head lst; + lst = tail lst; + addr = addressof(name); + if addr then + { + bpset(addr+offset); + trussbpt = append trussbpt, (addr+offset); + // sometimes _exits is renamed $_exits + if(regexp("exits|exec", name)) then stopPC = append stopPC, (addr+offset); + if(regexp("read", name)) then readPC = append readPC, (addr+offset); + if(regexp("fd2path", name)) then fd2pathPC = append fd2pathPC, (addr+offset); + if(regexp("^\\$*await", name)) then awaitPC = append awaitPC, (addr+offset); + if(regexp("^\\$*errstr", name)) then errstrPC = append errstrPC, (addr+offset); + // compatibility hacks for old kernel + if(regexp("_wait", name)) then _waitPC = append _waitPC, (addr+offset); + if(regexp("_errstr", name)) then _errstrPC = append _errstrPC, (addr+offset); + } + } +} + +defn trussflush() { + stop(pid); // already stopped, but flushes output +} + +defn new() { + bplist = {}; + newproc(progargs); + bpset(follow(main)[0]); + cont(); + bpdel(*PC); + // clear the hang bit, which is left set by newproc, so programs we fork/exec don't hang + printto("/proc/"+itoa(pid)+"/ctl", "nohang"); +} + +defn truss() { + local pc, lst, offset, prevpc, pcspret, ret; + + offset = trapoffset(); + + stop(pid); + _stoprunning = 0; + setuptruss(); + pcspret = UPCSPRET(); + + while !_stoprunning do { + cont(); + if notes[0]!="sys: breakpoint" then { + cleantruss(); + return {}; + } + pc = *PC; + if match(*PC, stopPC)>=0 then { + print(pid,": ",trapreason(),"\t"); + print(fmt(pc,'a'),"\t",fmt(pc,'i'),"\n"); + cleantruss(); + return {}; + } + if match(*PC, trussbpt)>=0 then { + usyscall(); + trussflush(); + prevpc = *PC; + step(); + ret = eval pcspret[2]; + print("\treturn value: ", ret\D, "\n"); + if (ret>=0) && (match(prevpc, readPC)>=0) then { + print("\tdata: "); + printtextordata(*((eval pcspret[1])+4), ret); + print("\n"); + } + if (ret>=0) && (match(prevpc, fd2pathPC)>=0) then { + print("\tdata: \"", *(*((eval pcspret[1])+4)\s), "\"\n"); + } + if (ret>=0) && (match(prevpc, errstrPC)>=0) then { + print("\tdata: \"", *(*(eval pcspret[1])\s), "\"\n"); + } + if (ret>=0) && (match(prevpc, awaitPC)>=0) then { + print("\tdata: "); + printtextordata(*(eval pcspret[1]), ret); + print("\n"); + } + // compatibility hacks for old kernel: + if (ret>=0) && (match(prevpc, _waitPC)>=0) then { + print("\tdata: "); + printtextordata(*(eval pcspret[1]), 12+3*12+64); + print("\n"); + } + if (ret>=0) && (match(prevpc, _errstrPC)>=0) then { + print("\tdata: "); + printtextordata(*(eval pcspret[1]), 64); + print("\n"); + } + } + trussflush(); + } +} + +defn cleantruss() { + local lst, offset, addr; + + stop(pid); + offset = trapoffset(); + lst = trussbpt; + while lst do + { + addr = head lst; + lst = tail lst; + bpdel(addr); + } + trussbpt = {}; + **PC = @*PC; // repair current instruction +} + +defn untruss() { + cleantruss(); + start(pid); +} + +print("/sys/lib/acid/truss"); blob - /dev/null blob + d5c08a45c5012ebdb6fafa0d794f3731f190b995 (mode 755) --- /dev/null +++ acid/window @@ -0,0 +1,23 @@ +#!/bin/rc +switch($#*){ +case 0 1 + echo usage: window '''minx miny maxx maxy''' cmd args ... + exit usage +} + +rfork ns +if(mount $wsys /mnt/wsys N`{{echo $pid $1 }| sed 's/^ //g;s/ +/,/g'}){ + shift + bind -b /mnt/wsys /dev + echo -n `{basename $1} > /dev/label >[2] /dev/null + @{ + echo hang > /proc/^`{cat /dev/ppid}^/ctl + $* < /dev/cons > /dev/cons >[2] /dev/cons & + exit $apid + } + ostatus = `{echo $status | sed 's/.*://'} + echo waitstop > /proc/$ostatus/ctl + echo nohang > /proc/$ostatus/ctl + exit $ostatus +} +exit 0