dda134763b
(note that there are no claims of making it actually work)
306 lines
6.6 KiB
Text
306 lines
6.6 KiB
Text
$NetBSD: patch-au,v 1.4 2009/12/29 22:03:41 spz Exp $
|
|
|
|
--- syscall.c.orig 2006-12-21 23:13:33.000000000 +0100
|
|
+++ syscall.c 2009-12-29 21:45:24.000000000 +0100
|
|
@@ -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 <machine/psl.h>
|
|
+#endif
|
|
#ifdef HAVE_SYS_REG_H
|
|
#include <sys/reg.h>
|
|
#ifndef PTRACE_PEEKUSR
|
|
@@ -624,6 +628,7 @@
|
|
}
|
|
#endif
|
|
|
|
+#ifndef NETBSD
|
|
static void
|
|
decode_subcall(tcp, subcall, nsubcalls, style)
|
|
struct tcb *tcp;
|
|
@@ -709,6 +714,7 @@
|
|
#endif /* FREEBSD */
|
|
}
|
|
}
|
|
+#endif /* !NETBSD */
|
|
#endif
|
|
|
|
struct tcb *tcp_last = NULL;
|
|
@@ -747,7 +753,7 @@
|
|
#endif
|
|
|
|
if ( sys_execve == func
|
|
-#if defined(SPARC) || defined(SPARC64) || defined(SUNOS4)
|
|
+#if !defined(NETBSD) && (defined(SPARC) || defined(SPARC64) || defined(SUNOS4))
|
|
|| sys_execv == func
|
|
#endif
|
|
#if UNIXWARE > 2
|
|
@@ -756,9 +762,12 @@
|
|
)
|
|
return internal_exec(tcp);
|
|
|
|
- if ( sys_waitpid == func
|
|
- || sys_wait4 == func
|
|
-#if defined(SVR4) || defined(FREEBSD) || defined(SUNOS4)
|
|
+ if (
|
|
+ sys_wait4 == func
|
|
+#ifndef NETBSD
|
|
+ || sys_waitpid == func
|
|
+#endif
|
|
+#if defined(SVR4) || defined(ALLBSD) || defined(SUNOS4)
|
|
|| sys_wait == func
|
|
#endif
|
|
#ifdef ALPHA
|
|
@@ -811,9 +820,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)
|
|
@@ -1283,9 +1292,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, ®s, sizeof(regs), 0) < 0) {
|
|
perror("pread");
|
|
return -1;
|
|
@@ -1299,8 +1308,41 @@
|
|
scno = regs.r_eax;
|
|
break;
|
|
}
|
|
-#endif /* FREEBSD */
|
|
+#endif /* ALLBSD */
|
|
#endif /* !HAVE_PR_SYSCALL */
|
|
+#else /* !USE_PROCFS */
|
|
+#ifdef NETBSD
|
|
+ if (ptrace(PTRACE_GETREGS,pid,(char *)®s, 0) < 0) {
|
|
+ perror("GETREGS");
|
|
+ return -1;
|
|
+ }
|
|
+#ifdef __i386__
|
|
+ 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
|
|
+#ifdef __x86_64__
|
|
+ switch (regs.regs[_REG_RAX]) {
|
|
+ case SYS_syscall:
|
|
+ case SYS___syscall:
|
|
+ scno = regs.regs[_REG_RDI];
|
|
+ break;
|
|
+ default:
|
|
+ scno = regs.regs[_REG_RAX];
|
|
+ break;
|
|
+ }
|
|
+#endif
|
|
+#endif /* NETBSD */
|
|
#endif /* USE_PROCFS */
|
|
if (!(tcp->flags & TCB_INSYSCALL))
|
|
tcp->scno = scno;
|
|
@@ -1325,7 +1367,9 @@
|
|
struct tcb *tcp;
|
|
{
|
|
#ifndef USE_PROCFS
|
|
+#ifndef NETBSD
|
|
int pid = tcp->pid;
|
|
+#endif
|
|
#else /* USE_PROCFS */
|
|
int scno = known_scno(tcp);
|
|
|
|
@@ -1698,17 +1742,36 @@
|
|
}
|
|
#endif /* MIPS */
|
|
#endif /* SVR4 */
|
|
-#ifdef FREEBSD
|
|
+#ifdef ALLBSD
|
|
+#ifdef __i386__
|
|
if (regs.r_eflags & PSL_C) {
|
|
tcp->u_rval = -1;
|
|
u_error = regs.r_eax;
|
|
} else {
|
|
tcp->u_rval = regs.r_eax;
|
|
+#if 0
|
|
+ /* XXX Linux only */
|
|
tcp->u_lrval =
|
|
((unsigned long long) regs.r_edx << 32) + regs.r_eax;
|
|
+#endif
|
|
u_error = 0;
|
|
}
|
|
-#endif /* FREEBSD */
|
|
+#endif
|
|
+#ifdef __x86_64__
|
|
+ if (regs.regs[_REG_RFL] & PSL_C) {
|
|
+ tcp->u_rval = -1;
|
|
+ u_error = regs.regs[_REG_RAX];
|
|
+ } else {
|
|
+ tcp->u_rval = regs.regs[_REG_RAX];
|
|
+#if 0
|
|
+ /* XXX Linux only */
|
|
+ tcp->u_lrval =
|
|
+ ((unsigned long long) regs.regs[_REG_RDX] << 64) + regs.regs[_REG_RAX];
|
|
+#endif
|
|
+ u_error = 0;
|
|
+ }
|
|
+#endif
|
|
+#endif /* ALLBSD */
|
|
tcp->u_error = u_error;
|
|
return 1;
|
|
}
|
|
@@ -1891,6 +1954,32 @@
|
|
return -1;
|
|
}
|
|
#endif /* FREEBSD */
|
|
+#ifdef NETBSD
|
|
+ if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)®s, 0) < 0)
|
|
+ return -1;
|
|
+#ifdef __i386__
|
|
+ if (error) {
|
|
+ regs.r_eflags |= PSL_C;
|
|
+ regs.r_eax = error;
|
|
+ }
|
|
+ else {
|
|
+ regs.r_eflags &= ~PSL_C;
|
|
+ regs.r_eax = rval;
|
|
+ }
|
|
+#endif
|
|
+#ifdef __x86_64__
|
|
+ if (error) {
|
|
+ regs.regs[_REG_RFL] |= PSL_C;
|
|
+ regs.regs[_REG_RAX] = error;
|
|
+ }
|
|
+ else {
|
|
+ regs.regs[_REG_RFL] &= ~PSL_C;
|
|
+ regs.regs[_REG_RAX] = rval;
|
|
+ }
|
|
+#endif
|
|
+ if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)®s, 0) < 0)
|
|
+ return -1;
|
|
+#endif /* NETBSD */
|
|
|
|
/* All branches reach here on success (only). */
|
|
tcp->u_error = error;
|
|
@@ -1903,7 +1992,9 @@
|
|
struct tcb *tcp;
|
|
{
|
|
#ifndef USE_PROCFS
|
|
+#ifndef NETBSD
|
|
int pid = tcp->pid;
|
|
+#endif
|
|
#endif /* !USE_PROCFS */
|
|
#ifdef LINUX
|
|
#if defined(S390) || defined(S390X)
|
|
@@ -2201,6 +2292,58 @@
|
|
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;
|
|
+#ifdef __i386__
|
|
+ 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
|
|
+#ifdef __x86_64__
|
|
+{
|
|
+ int bias, i;
|
|
+ static int ar[2][6] = {
|
|
+ { _REG_RDI, _REG_RSI, _REG_RDX,
|
|
+ _REG_R10, _REG_R8, _REG_R9 }, /* x86-64 ABI */
|
|
+ { _REG_RBX, _REG_RCX, _REG_RDX,
|
|
+ _REG_RSI, _REG_RDI, _REG_RBP } /* i386 ABI */
|
|
+ };
|
|
+ switch(regs.regs[_REG_RAX]) {
|
|
+ case SYS___syscall:
|
|
+ case SYS_syscall:
|
|
+ bias = 1;
|
|
+ break;
|
|
+ default:
|
|
+ bias = 0;
|
|
+ break;
|
|
+ }
|
|
+ for (i = 0; i < tcp->u_nargs; i++) {
|
|
+ tcp->u_arg[i] = regs.regs[ar[0][i + bias]];
|
|
+#if 0
|
|
+ if (upeek(tcp->pid, ar[0][i + bias] * 8, &tcp->u_arg[i]) < 0)
|
|
+ return -1;
|
|
+#endif
|
|
+ }
|
|
+}
|
|
+#endif
|
|
+#endif /* NETBSD */
|
|
#ifdef FREEBSD
|
|
if (tcp->scno >= 0 && tcp->scno < nsyscalls &&
|
|
sysent[tcp->scno].nargs > tcp->status.val)
|
|
@@ -2570,6 +2713,19 @@
|
|
pread(tcp->pfd_reg, ®s, sizeof(regs), 0);
|
|
val = regs.r_edx;
|
|
#endif
|
|
+#ifdef NETBSD
|
|
+ struct reg regs;
|
|
+ if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)®s, sizeof(regs)) < 0) {
|
|
+ perror("PTRACE_GETREGS get edx");
|
|
+ return -1;
|
|
+ }
|
|
+#ifdef __i386__
|
|
+ val = regs.r_edx;
|
|
+#endif
|
|
+#ifdef __x86_64__
|
|
+ val = regs.regs[_REG_RDX];
|
|
+#endif
|
|
+#endif /* NETBSD */
|
|
return val;
|
|
}
|
|
|