plan9fox/sys/lib/acid/syscall
2016-05-04 16:11:48 +02:00

200 lines
5.4 KiB
Text

// 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, 'A'), ", ", 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:list)}},
{ 2, {"bind", "ssX", code(*sysbind:list)}},
{ 3, {"chdir", "s", code(*sysbind:list)}},
{ 4, {"close", "D", code(*sysclose:list)}},
{ 5, {"dup", "DD", code(*sysdup:list)}},
{ 6, {"alarm", "D", code(*sysalarm:list)}},
{ 7, {"exec", "sS", code(*sysexec:list)}},
{ 8, {"exits", "s", code(*sysexits:list)}},
{ 9, {"_fsession", "DsD", code(*sys_fsession:list)}},
{10, {"fauth", "Ds", code(*sysfauth:list)}},
{11, {"_fstat", "DA", code(*sys_fstat:list)}},
{12, {"segbrk", "AA", code(*syssegbrk:list)}},
{13, {"_mount", "DsXs", code(*sys_mount:list)}},
{14, {"open", "sD", code(*sysopen:list)}},
{15, {"_read", "DAD", code(*sys_read:list)}},
{16, {"oseek", "DDD", code(*sysoseek:list)}},
{17, {"sleep", "D", code(*syssleep:list)}},
{18, {"_stat", "sA", code(*sys_stat:list)}},
{19, {"rfork", "X", code(*sysstat:list)}},
{20, {"_write", "DTD", code(*sys_write:list)}},
{21, {"pipe", "A", code(*syspipe:list)}},
{22, {"create", "sDO", code(*syscreate:list)}},
{23, {"fd2path", "DAD", code(*sysfd2path:list)}},
{24, {"brk_", "A", code(*sysbrk_:list)}},
{25, {"remove", "s", code(*sysremove:list)}},
{26, {"_wstat", "sA", code(*sys_wstat:list)}},
{27, {"_fwstat", "DA", code(*sys_fwstat:list)}},
{28, {"notify", "A", code(*sysnotify:list)}},
{29, {"noted", "D", code(*sysnoted:list)}},
{30, {"segattach", "DsAD", code(*syssegattach:list)}},
{31, {"segdetach", "A", code(*syssegdetach:list)}},
{32, {"segfree", "AD", code(*syssegfree:list)}},
{33, {"segflush", "AD", code(*syssegflush:list)}},
{34, {"rendezvous", "AA", code(*sysrendezvous:list)}},
{35, {"unmount", "ss", code(*sysunmount:list)}},
{36, {"_wait", "A", code(*sys_wait:list)}},
{37, {"semacquire", "AD", code(*syssemacquire:list)}},
{38, {"semrelease", "AD", code(*syssemrelease:list)}},
{39, {"seek", "ADVD", code(*sysseek:list)}},
{40, {"fversion", "DDsD", code(*sysfversion:list)}},
{41, {"errstr", "TD", code(*syserrstr:list)}},
{42, {"stat", "sAD", code(*sysstat:list)}},
{43, {"fstat", "DAD", code(*sysfstat:list)}},
{44, {"wstat", "sAD", code(*syswstat:list)}},
{45, {"fwstat", "DAD", code(*sysfwstat:list)}},
{46, {"mount", "DDsXs", code(*sysmount:list)}},
{47, {"await", "TD", code(*sysawait:list)}},
{50, {"pread", "DADZ", code(*syspread:list)}},
{51, {"pwrite", "DTDZ", code(*syspwrite:list)}},
{52, {"tsemacquire", "AD", code(*systsemacquire:list)}},
{53, {"_nsec", "A", code(*sys_nsec:list)}},
};
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 == "amd64" then
return { code(*BP), code(*SP+8), 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
}
defn trapoffset() {
// return offset from entry point to trap instr
if objtype == "386" then return 5;
if objtype == "amd64" then return 12;
if objtype == "mips" then return 8;
if objtype == "mips2" then return 8;
if objtype == "arm" then return 8; // untested
}
defn trapreason() {
// return reason for trap
if objtype == "386" then return reason(*TRAP);
if objtype == "amd64" then return reason(*TYPE);
if objtype == "mips" then return reason(*CAUSE);
if objtype == "mips2" then return reason(*CAUSE);
if objtype == "arm" then return "unknown trap"; // 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]);
}
}
}