mirror of
https://github.com/9fans/plan9port.git
synced 2025-01-12 11:10:07 +00:00
acid files
This commit is contained in:
parent
c8af1ab17b
commit
0a61c07d59
23 changed files with 4251 additions and 0 deletions
210
acid/386
Normal file
210
acid/386
Normal file
|
@ -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);
|
137
acid/68020
Normal file
137
acid/68020
Normal file
|
@ -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);
|
133
acid/acme
Normal file
133
acid/acme
Normal file
|
@ -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);
|
147
acid/alef
Normal file
147
acid/alef
Normal file
|
@ -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);
|
205
acid/alpha
Normal file
205
acid/alpha
Normal file
|
@ -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);
|
||||||
|
|
104
acid/arm
Normal file
104
acid/arm
Normal file
|
@ -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);
|
BIN
acid/core
Normal file
BIN
acid/core
Normal file
Binary file not shown.
128
acid/coverage
Normal file
128
acid/coverage
Normal file
|
@ -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);
|
54
acid/elflink
Normal file
54
acid/elflink
Normal file
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
295
acid/kernel
Normal file
295
acid/kernel
Normal file
|
@ -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 "<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");
|
||||||
|
}
|
||||||
|
|
138
acid/leak
Normal file
138
acid/leak
Normal file
|
@ -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");
|
||||||
|
}
|
217
acid/mips
Normal file
217
acid/mips
Normal file
|
@ -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);
|
169
acid/network
Normal file
169
acid/network
Normal file
|
@ -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");
|
306
acid/pool
Normal file
306
acid/pool
Normal file
|
@ -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;
|
||||||
|
}
|
||||||
|
|
599
acid/port
Normal file
599
acid/port
Normal file
|
@ -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);
|
120
acid/power
Normal file
120
acid/power
Normal file
|
@ -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);
|
218
acid/sparc
Normal file
218
acid/sparc
Normal file
|
@ -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);
|
196
acid/syscall
Normal file
196
acid/syscall
Normal file
|
@ -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]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
365
acid/thread
Normal file
365
acid/thread
Normal file
|
@ -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<empty>\n");
|
||||||
|
i=i+1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
print(acidfile);
|
33
acid/transcript
Executable file
33
acid/transcript
Executable file
|
@ -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
|
171
acid/trump
Normal file
171
acid/trump
Normal file
|
@ -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);
|
283
acid/truss
Normal file
283
acid/truss
Normal file
|
@ -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");
|
23
acid/window
Executable file
23
acid/window
Executable file
|
@ -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
|
Loading…
Reference in a new issue