code: plan9front

ref: 403149d7de4dbe4cc4b1fd9cb3a164e51dbccc15
dir: /sys/lib/acid/syscall/

View raw version
// 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]);
		}
	}
}