$NetBSD: patch-an,v 1.2 2006/03/05 08:28:29 christos Exp $

--- syscall.c	2006-01-12 05:18:53.000000000 -0500
+++ syscall.c	2006-03-05 03:27:00.000000000 -0500
@@ -38,9 +38,9 @@
 #include <signal.h>
 #include <time.h>
 #include <errno.h>
+#include <sys/param.h>
 #include <sys/user.h>
 #include <sys/syscall.h>
-#include <sys/param.h>
 
 #if HAVE_ASM_REG_H
 #if defined (SPARC) || defined (SPARC64)
@@ -56,6 +56,10 @@
 #endif
 #endif
 
+#ifdef NETBSD
+#include <machine/reg.h>
+#include <x86/psl.h>
+#endif
 #ifdef HAVE_SYS_REG_H
 #include <sys/reg.h>
 #ifndef PTRACE_PEEKUSR
@@ -634,6 +638,7 @@
 }
 #endif
 
+#ifndef NETBSD
 static void
 decode_subcall(tcp, subcall, nsubcalls, style)
 struct tcb *tcp;
@@ -719,6 +724,7 @@
 #endif /* FREEBSD */
 	}
 }
+#endif /* !NETBSD */
 #endif
 
 struct tcb *tcp_last = NULL;
@@ -855,9 +861,9 @@
        static long rax;
 #endif
 #endif /* LINUX */
-#ifdef FREEBSD
-	struct reg regs;
-#endif /* FREEBSD */
+#ifdef ALLBSD
+	static struct reg regs;
+#endif /* ALLBSD */
 
 int
 get_scno(tcp)
@@ -1318,9 +1324,9 @@
 #ifdef HAVE_PR_SYSCALL
 	scno = tcp->status.PR_SYSCALL;
 #else /* !HAVE_PR_SYSCALL */
-#ifndef FREEBSD
+#ifndef ALLBSD
 	scno = tcp->status.PR_WHAT;
-#else /* FREEBSD */
+#else /* ALLBSD */
 	if (pread(tcp->pfd_reg, &regs, sizeof(regs), 0) < 0) {
 	        perror("pread");
                 return -1;
@@ -1334,8 +1340,28 @@
 	        scno = regs.r_eax;
 	        break;
 	}
-#endif /* FREEBSD */
+#endif /* ALLBSD */
 #endif /* !HAVE_PR_SYSCALL */
+#else /* !USE_PROCFS */
+#ifdef NETBSD
+	if (ptrace(PTRACE_GETREGS,pid,(char *)&regs, 0) < 0) {
+	        perror("GETREGS");
+		return -1;
+	}
+	switch (regs.r_eax) {
+	case SYS_syscall:
+	case SYS___syscall:
+    	        if ((scno = ptrace(PTRACE_PEEKUSER, pid,
+		    (char *)regs.r_esp + sizeof(int), sizeof(int))) == -1) {
+			perror("PEEKUSER __syscall");
+			return -1;
+		}
+	        break;
+	default:
+	        scno = regs.r_eax;
+	        break;
+        }
+#endif /* NETBSD */
 #endif /* USE_PROCFS */
 	if (!(tcp->flags & TCB_INSYSCALL))
 		tcp->scno = scno;
@@ -1360,7 +1386,9 @@
 struct tcb *tcp;
 {
 #ifndef USE_PROCFS
+#ifndef NETBSD
 	int pid = tcp->pid;
+#endif
 #else /* USE_PROCFS */
 	int scno = known_scno(tcp);
 
@@ -1733,7 +1761,7 @@
 		}
 #endif /* MIPS */
 #endif /* SVR4 */
-#ifdef FREEBSD
+#ifdef ALLBSD
 		if (regs.r_eflags & PSL_C) {
  		        tcp->u_rval = -1;
 		        u_error = regs.r_eax;
@@ -1743,7 +1771,7 @@
 			  ((unsigned long long) regs.r_edx << 32) +  regs.r_eax;
 		        u_error = 0;
 		}
-#endif /* FREEBSD */
+#endif /* ALLBSD */
 	tcp->u_error = u_error;
 	return 1;
 }
@@ -1926,6 +1954,20 @@
                 return -1;
         }
 #endif /* FREEBSD */
+#ifdef NETBSD
+	if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
+		return -1;
+	if (error) {
+		regs.r_eflags |= PSL_C;
+		regs.r_eax = error;
+	}
+	else {
+		regs.r_eflags &= ~PSL_C;
+		regs.r_eax = rval;
+	}
+	if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)&regs, 0) < 0)
+		return -1;
+#endif
 
 	/* All branches reach here on success (only).  */
 	tcp->u_error = error;
@@ -1938,7 +1980,9 @@
 struct tcb *tcp;
 {
 #ifndef USE_PROCFS
+#ifndef NETBSD
 	int pid = tcp->pid;
+#endif
 #endif /* !USE_PROCFS */
 #ifdef LINUX
 #if defined(S390) || defined(S390X)
@@ -2236,6 +2280,29 @@
 	I DONT KNOW WHAT TO DO
 #endif /* !HAVE_PR_SYSCALL */
 #endif /* SVR4 */
+#ifdef NETBSD
+	if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
+		tcp->u_nargs = sysent[tcp->scno].nargs;
+	else
+		tcp->u_nargs = 5;
+	switch(regs.r_eax) {
+	case SYS___syscall:
+		umoven(tcp, regs.r_esp + sizeof(int) + sizeof(quad_t),
+		    tcp->u_nargs * sizeof(unsigned long),
+		    (char *) tcp->u_arg);
+		break;
+        case SYS_syscall:
+		umoven(tcp, regs.r_esp + 2 * sizeof(int),
+		    tcp->u_nargs * sizeof(unsigned long),
+		    (char *) tcp->u_arg);
+		break;
+        default:
+		umoven(tcp, regs.r_esp + sizeof(int),
+		    tcp->u_nargs * sizeof(unsigned long),
+		    (char *) tcp->u_arg);
+		break;
+	}
+#endif /* NETBSD */
 #ifdef FREEBSD
 	if (tcp->scno >= 0 && tcp->scno < nsyscalls &&
 	    sysent[tcp->scno].nargs > tcp->status.val)
@@ -2648,6 +2715,14 @@
 	pread(tcp->pfd_reg, &regs, sizeof(regs), 0);
 	val = regs.r_edx;
 #endif
+#ifdef NETBSD
+	struct reg regs;
+	if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, sizeof(regs)) < 0) {
+		perror("PTRACE_GETREGS get edx");
+		return -1;
+	}
+	val = regs.r_edx;
+#endif
 	return val;
 }
 
