aboutsummaryrefslogtreecommitdiffstats
path: root/arch/um/kernel/tt/ptproxy
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 15:20:36 -0700
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 15:20:36 -0700
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /arch/um/kernel/tt/ptproxy
downloadlinux-dev-1da177e4c3f41524e886b7f1b8a0c1fc7321cac2.tar.xz
linux-dev-1da177e4c3f41524e886b7f1b8a0c1fc7321cac2.zip
Linux-2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Diffstat (limited to 'arch/um/kernel/tt/ptproxy')
-rw-r--r--arch/um/kernel/tt/ptproxy/Makefile10
-rw-r--r--arch/um/kernel/tt/ptproxy/proxy.c377
-rw-r--r--arch/um/kernel/tt/ptproxy/ptproxy.h61
-rw-r--r--arch/um/kernel/tt/ptproxy/ptrace.c237
-rw-r--r--arch/um/kernel/tt/ptproxy/sysdep.c70
-rw-r--r--arch/um/kernel/tt/ptproxy/sysdep.h25
-rw-r--r--arch/um/kernel/tt/ptproxy/wait.c86
-rw-r--r--arch/um/kernel/tt/ptproxy/wait.h15
8 files changed, 881 insertions, 0 deletions
diff --git a/arch/um/kernel/tt/ptproxy/Makefile b/arch/um/kernel/tt/ptproxy/Makefile
new file mode 100644
index 000000000000..3ad5b774de59
--- /dev/null
+++ b/arch/um/kernel/tt/ptproxy/Makefile
@@ -0,0 +1,10 @@
+#
+# Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+# Licensed under the GPL
+#
+
+obj-y = proxy.o ptrace.o sysdep.o wait.o
+
+USER_OBJS := $(obj-y)
+
+include arch/um/scripts/Makefile.rules
diff --git a/arch/um/kernel/tt/ptproxy/proxy.c b/arch/um/kernel/tt/ptproxy/proxy.c
new file mode 100644
index 000000000000..58800c50b10e
--- /dev/null
+++ b/arch/um/kernel/tt/ptproxy/proxy.c
@@ -0,0 +1,377 @@
+/**********************************************************************
+proxy.c
+
+Copyright (C) 1999 Lars Brinkhoff. See the file COPYING for licensing
+terms and conditions.
+
+Jeff Dike (jdike@karaya.com) : Modified for integration into uml
+**********************************************************************/
+
+/* XXX This file shouldn't refer to CONFIG_* */
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <signal.h>
+#include <string.h>
+#include <termios.h>
+#include <sys/wait.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <asm/unistd.h>
+#include "ptrace_user.h"
+
+#include "ptproxy.h"
+#include "sysdep.h"
+#include "wait.h"
+
+#include "user_util.h"
+#include "user.h"
+#include "os.h"
+#include "tempfile.h"
+
+static int debugger_wait(debugger_state *debugger, int *status, int options,
+ int (*syscall)(debugger_state *debugger, pid_t child),
+ int (*normal_return)(debugger_state *debugger,
+ pid_t unused),
+ int (*wait_return)(debugger_state *debugger,
+ pid_t unused))
+{
+ if(debugger->real_wait){
+ debugger->handle_trace = normal_return;
+ syscall_continue(debugger->pid);
+ debugger->real_wait = 0;
+ return(1);
+ }
+ debugger->wait_status_ptr = status;
+ debugger->wait_options = options;
+ if((debugger->debugee != NULL) && debugger->debugee->event){
+ syscall_continue(debugger->pid);
+ wait_for_stop(debugger->pid, SIGTRAP, PTRACE_SYSCALL,
+ NULL);
+ (*wait_return)(debugger, -1);
+ return(0);
+ }
+ else if(debugger->wait_options & WNOHANG){
+ syscall_cancel(debugger->pid, 0);
+ debugger->handle_trace = syscall;
+ return(0);
+ }
+ else {
+ syscall_pause(debugger->pid);
+ debugger->handle_trace = wait_return;
+ debugger->waiting = 1;
+ }
+ return(1);
+}
+
+/*
+ * Handle debugger trap, i.e. syscall.
+ */
+
+int debugger_syscall(debugger_state *debugger, pid_t child)
+{
+ long arg1, arg2, arg3, arg4, arg5, result;
+ int syscall, ret = 0;
+
+ syscall = get_syscall(debugger->pid, &arg1, &arg2, &arg3, &arg4,
+ &arg5);
+
+ switch(syscall){
+ case __NR_execve:
+ /* execve never returns */
+ debugger->handle_trace = debugger_syscall;
+ break;
+
+ case __NR_ptrace:
+ if(debugger->debugee->pid != 0) arg2 = debugger->debugee->pid;
+ if(!debugger->debugee->in_context)
+ child = debugger->debugee->pid;
+ result = proxy_ptrace(debugger, arg1, arg2, arg3, arg4, child,
+ &ret);
+ syscall_cancel(debugger->pid, result);
+ debugger->handle_trace = debugger_syscall;
+ return(ret);
+
+#ifdef __NR_waitpid
+ case __NR_waitpid:
+#endif
+ case __NR_wait4:
+ if(!debugger_wait(debugger, (int *) arg2, arg3,
+ debugger_syscall, debugger_normal_return,
+ proxy_wait_return))
+ return(0);
+ break;
+
+ case __NR_kill:
+ if(!debugger->debugee->in_context)
+ child = debugger->debugee->pid;
+ if(arg1 == debugger->debugee->pid){
+ result = kill(child, arg2);
+ syscall_cancel(debugger->pid, result);
+ debugger->handle_trace = debugger_syscall;
+ return(0);
+ }
+ else debugger->handle_trace = debugger_normal_return;
+ break;
+
+ default:
+ debugger->handle_trace = debugger_normal_return;
+ }
+
+ syscall_continue(debugger->pid);
+ return(0);
+}
+
+/* Used by the tracing thread */
+static debugger_state parent;
+static int parent_syscall(debugger_state *debugger, int pid);
+
+int init_parent_proxy(int pid)
+{
+ parent = ((debugger_state) { .pid = pid,
+ .wait_options = 0,
+ .wait_status_ptr = NULL,
+ .waiting = 0,
+ .real_wait = 0,
+ .expecting_child = 0,
+ .handle_trace = parent_syscall,
+ .debugee = NULL } );
+ return(0);
+}
+
+int parent_normal_return(debugger_state *debugger, pid_t unused)
+{
+ debugger->handle_trace = parent_syscall;
+ syscall_continue(debugger->pid);
+ return(0);
+}
+
+static int parent_syscall(debugger_state *debugger, int pid)
+{
+ long arg1, arg2, arg3, arg4, arg5;
+ int syscall;
+
+ syscall = get_syscall(pid, &arg1, &arg2, &arg3, &arg4, &arg5);
+
+ if((syscall == __NR_wait4)
+#ifdef __NR_waitpid
+ || (syscall == __NR_waitpid)
+#endif
+ ){
+ debugger_wait(&parent, (int *) arg2, arg3, parent_syscall,
+ parent_normal_return, parent_wait_return);
+ }
+ else ptrace(PTRACE_SYSCALL, pid, 0, 0);
+ return(0);
+}
+
+int debugger_normal_return(debugger_state *debugger, pid_t unused)
+{
+ debugger->handle_trace = debugger_syscall;
+ syscall_continue(debugger->pid);
+ return(0);
+}
+
+void debugger_cancelled_return(debugger_state *debugger, int result)
+{
+ debugger->handle_trace = debugger_syscall;
+ syscall_set_result(debugger->pid, result);
+ syscall_continue(debugger->pid);
+}
+
+/* Used by the tracing thread */
+static debugger_state debugger;
+static debugee_state debugee;
+
+void init_proxy (pid_t debugger_pid, int stopped, int status)
+{
+ debugger.pid = debugger_pid;
+ debugger.handle_trace = debugger_syscall;
+ debugger.debugee = &debugee;
+ debugger.waiting = 0;
+ debugger.real_wait = 0;
+ debugger.expecting_child = 0;
+
+ debugee.pid = 0;
+ debugee.traced = 0;
+ debugee.stopped = stopped;
+ debugee.event = 0;
+ debugee.zombie = 0;
+ debugee.died = 0;
+ debugee.wait_status = status;
+ debugee.in_context = 1;
+}
+
+int debugger_proxy(int status, int pid)
+{
+ int ret = 0, sig;
+
+ if(WIFSTOPPED(status)){
+ sig = WSTOPSIG(status);
+ if (sig == SIGTRAP)
+ ret = (*debugger.handle_trace)(&debugger, pid);
+
+ else if(sig == SIGCHLD){
+ if(debugger.expecting_child){
+ ptrace(PTRACE_SYSCALL, debugger.pid, 0, sig);
+ debugger.expecting_child = 0;
+ }
+ else if(debugger.waiting)
+ real_wait_return(&debugger);
+ else {
+ ptrace(PTRACE_SYSCALL, debugger.pid, 0, sig);
+ debugger.real_wait = 1;
+ }
+ }
+ else ptrace(PTRACE_SYSCALL, debugger.pid, 0, sig);
+ }
+ else if(WIFEXITED(status)){
+ tracer_panic("debugger (pid %d) exited with status %d",
+ debugger.pid, WEXITSTATUS(status));
+ }
+ else if(WIFSIGNALED(status)){
+ tracer_panic("debugger (pid %d) exited with signal %d",
+ debugger.pid, WTERMSIG(status));
+ }
+ else {
+ tracer_panic("proxy got unknown status (0x%x) on debugger "
+ "(pid %d)", status, debugger.pid);
+ }
+ return(ret);
+}
+
+void child_proxy(pid_t pid, int status)
+{
+ debugee.event = 1;
+ debugee.wait_status = status;
+
+ if(WIFSTOPPED(status)){
+ debugee.stopped = 1;
+ debugger.expecting_child = 1;
+ kill(debugger.pid, SIGCHLD);
+ }
+ else if(WIFEXITED(status) || WIFSIGNALED(status)){
+ debugee.zombie = 1;
+ debugger.expecting_child = 1;
+ kill(debugger.pid, SIGCHLD);
+ }
+ else panic("proxy got unknown status (0x%x) on child (pid %d)",
+ status, pid);
+}
+
+void debugger_parent_signal(int status, int pid)
+{
+ int sig;
+
+ if(WIFSTOPPED(status)){
+ sig = WSTOPSIG(status);
+ if(sig == SIGTRAP) (*parent.handle_trace)(&parent, pid);
+ else ptrace(PTRACE_SYSCALL, pid, 0, sig);
+ }
+}
+
+void fake_child_exit(void)
+{
+ int status, pid;
+
+ child_proxy(1, W_EXITCODE(0, 0));
+ while(debugger.waiting == 1){
+ CATCH_EINTR(pid = waitpid(debugger.pid, &status, WUNTRACED));
+ if(pid != debugger.pid){
+ printk("fake_child_exit - waitpid failed, "
+ "errno = %d\n", errno);
+ return;
+ }
+ debugger_proxy(status, debugger.pid);
+ }
+ CATCH_EINTR(pid = waitpid(debugger.pid, &status, WUNTRACED));
+ if(pid != debugger.pid){
+ printk("fake_child_exit - waitpid failed, "
+ "errno = %d\n", errno);
+ return;
+ }
+ if(ptrace(PTRACE_DETACH, debugger.pid, 0, SIGCONT) < 0)
+ printk("fake_child_exit - PTRACE_DETACH failed, errno = %d\n",
+ errno);
+}
+
+char gdb_init_string[] =
+"att 1 \n\
+b panic \n\
+b stop \n\
+handle SIGWINCH nostop noprint pass \n\
+";
+
+int start_debugger(char *prog, int startup, int stop, int *fd_out)
+{
+ int slave, child;
+
+ slave = open_gdb_chan();
+ child = fork();
+ if(child == 0){
+ char *tempname = NULL;
+ int fd;
+
+ if(setsid() < 0) perror("setsid");
+ if((dup2(slave, 0) < 0) || (dup2(slave, 1) < 0) ||
+ (dup2(slave, 2) < 0)){
+ printk("start_debugger : dup2 failed, errno = %d\n",
+ errno);
+ exit(1);
+ }
+ if(ioctl(0, TIOCSCTTY, 0) < 0){
+ printk("start_debugger : TIOCSCTTY failed, "
+ "errno = %d\n", errno);
+ exit(1);
+ }
+ if(tcsetpgrp (1, os_getpid()) < 0){
+ printk("start_debugger : tcsetpgrp failed, "
+ "errno = %d\n", errno);
+#ifdef notdef
+ exit(1);
+#endif
+ }
+ fd = make_tempfile("/tmp/gdb_init-XXXXXX", &tempname, 0);
+ if(fd < 0){
+ printk("start_debugger : make_tempfile failed,"
+ "err = %d\n", -fd);
+ exit(1);
+ }
+ os_write_file(fd, gdb_init_string, sizeof(gdb_init_string) - 1);
+ if(startup){
+ if(stop){
+ os_write_file(fd, "b start_kernel\n",
+ strlen("b start_kernel\n"));
+ }
+ os_write_file(fd, "c\n", strlen("c\n"));
+ }
+ if(ptrace(PTRACE_TRACEME, 0, 0, 0) < 0){
+ printk("start_debugger : PTRACE_TRACEME failed, "
+ "errno = %d\n", errno);
+ exit(1);
+ }
+ execlp("gdb", "gdb", "--command", tempname, prog, NULL);
+ printk("start_debugger : exec of gdb failed, errno = %d\n",
+ errno);
+ }
+ if(child < 0){
+ printk("start_debugger : fork for gdb failed, errno = %d\n",
+ errno);
+ return(-1);
+ }
+ *fd_out = slave;
+ return(child);
+}
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only. This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff --git a/arch/um/kernel/tt/ptproxy/ptproxy.h b/arch/um/kernel/tt/ptproxy/ptproxy.h
new file mode 100644
index 000000000000..5eb0285b1968
--- /dev/null
+++ b/arch/um/kernel/tt/ptproxy/ptproxy.h
@@ -0,0 +1,61 @@
+/**********************************************************************
+ptproxy.h
+
+Copyright (C) 1999 Lars Brinkhoff. See the file COPYING for licensing
+terms and conditions.
+**********************************************************************/
+
+#ifndef __PTPROXY_H
+#define __PTPROXY_H
+
+#include <sys/types.h>
+
+typedef struct debugger debugger_state;
+typedef struct debugee debugee_state;
+
+struct debugger
+{
+ pid_t pid;
+ int wait_options;
+ int *wait_status_ptr;
+ unsigned int waiting : 1;
+ unsigned int real_wait : 1;
+ unsigned int expecting_child : 1;
+ int (*handle_trace) (debugger_state *, pid_t);
+
+ debugee_state *debugee;
+};
+
+struct debugee
+{
+ pid_t pid;
+ int wait_status;
+ unsigned int died : 1;
+ unsigned int event : 1;
+ unsigned int stopped : 1;
+ unsigned int trace_singlestep : 1;
+ unsigned int trace_syscall : 1;
+ unsigned int traced : 1;
+ unsigned int zombie : 1;
+ unsigned int in_context : 1;
+};
+
+extern int debugger_syscall(debugger_state *debugger, pid_t pid);
+extern int debugger_normal_return (debugger_state *debugger, pid_t unused);
+
+extern long proxy_ptrace (struct debugger *, int, pid_t, long, long, pid_t,
+ int *strace_out);
+extern void debugger_cancelled_return(debugger_state *debugger, int result);
+
+#endif
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only. This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff --git a/arch/um/kernel/tt/ptproxy/ptrace.c b/arch/um/kernel/tt/ptproxy/ptrace.c
new file mode 100644
index 000000000000..528a5fc8d887
--- /dev/null
+++ b/arch/um/kernel/tt/ptproxy/ptrace.c
@@ -0,0 +1,237 @@
+/**********************************************************************
+ptrace.c
+
+Copyright (C) 1999 Lars Brinkhoff. See the file COPYING for licensing
+terms and conditions.
+
+Jeff Dike (jdike@karaya.com) : Modified for integration into uml
+**********************************************************************/
+
+#include <errno.h>
+#include <unistd.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/wait.h>
+
+#include "ptproxy.h"
+#include "debug.h"
+#include "user_util.h"
+#include "kern_util.h"
+#include "ptrace_user.h"
+#include "tt.h"
+
+long proxy_ptrace(struct debugger *debugger, int arg1, pid_t arg2,
+ long arg3, long arg4, pid_t child, int *ret)
+{
+ sigset_t relay;
+ long result;
+ int status;
+
+ *ret = 0;
+ if(debugger->debugee->died) return(-ESRCH);
+
+ switch(arg1){
+ case PTRACE_ATTACH:
+ if(debugger->debugee->traced) return(-EPERM);
+
+ debugger->debugee->pid = arg2;
+ debugger->debugee->traced = 1;
+
+ if(is_valid_pid(arg2) && (arg2 != child)){
+ debugger->debugee->in_context = 0;
+ kill(arg2, SIGSTOP);
+ debugger->debugee->event = 1;
+ debugger->debugee->wait_status = W_STOPCODE(SIGSTOP);
+ }
+ else {
+ debugger->debugee->in_context = 1;
+ if(debugger->debugee->stopped)
+ child_proxy(child, W_STOPCODE(SIGSTOP));
+ else kill(child, SIGSTOP);
+ }
+
+ return(0);
+
+ case PTRACE_DETACH:
+ if(!debugger->debugee->traced) return(-EPERM);
+
+ debugger->debugee->traced = 0;
+ debugger->debugee->pid = 0;
+ if(!debugger->debugee->in_context)
+ kill(child, SIGCONT);
+
+ return(0);
+
+ case PTRACE_CONT:
+ if(!debugger->debugee->in_context) return(-EPERM);
+ *ret = PTRACE_CONT;
+ return(ptrace(PTRACE_CONT, child, arg3, arg4));
+
+#ifdef UM_HAVE_GETFPREGS
+ case PTRACE_GETFPREGS:
+ {
+ long regs[FP_FRAME_SIZE];
+ int i, result;
+
+ result = ptrace(PTRACE_GETFPREGS, child, 0, regs);
+ if(result == -1) return(-errno);
+
+ for (i = 0; i < sizeof(regs)/sizeof(regs[0]); i++)
+ ptrace(PTRACE_POKEDATA, debugger->pid, arg4 + 4 * i,
+ regs[i]);
+ return(result);
+ }
+#endif
+
+#ifdef UM_HAVE_GETFPXREGS
+ case PTRACE_GETFPXREGS:
+ {
+ long regs[FPX_FRAME_SIZE];
+ int i, result;
+
+ result = ptrace(PTRACE_GETFPXREGS, child, 0, regs);
+ if(result == -1) return(-errno);
+
+ for (i = 0; i < sizeof(regs)/sizeof(regs[0]); i++)
+ ptrace(PTRACE_POKEDATA, debugger->pid, arg4 + 4 * i,
+ regs[i]);
+ return(result);
+ }
+#endif
+
+#ifdef UM_HAVE_GETREGS
+ case PTRACE_GETREGS:
+ {
+ long regs[FRAME_SIZE];
+ int i, result;
+
+ result = ptrace(PTRACE_GETREGS, child, 0, regs);
+ if(result == -1) return(-errno);
+
+ for (i = 0; i < sizeof(regs)/sizeof(regs[0]); i++)
+ ptrace (PTRACE_POKEDATA, debugger->pid,
+ arg4 + 4 * i, regs[i]);
+ return(result);
+ }
+ break;
+#endif
+
+ case PTRACE_KILL:
+ result = ptrace(PTRACE_KILL, child, arg3, arg4);
+ if(result == -1) return(-errno);
+
+ return(result);
+
+ case PTRACE_PEEKDATA:
+ case PTRACE_PEEKTEXT:
+ case PTRACE_PEEKUSR:
+ /* The value being read out could be -1, so we have to
+ * check errno to see if there's an error, and zero it
+ * beforehand so we're not faked out by an old error
+ */
+
+ errno = 0;
+ result = ptrace(arg1, child, arg3, 0);
+ if((result == -1) && (errno != 0)) return(-errno);
+
+ result = ptrace(PTRACE_POKEDATA, debugger->pid, arg4, result);
+ if(result == -1) return(-errno);
+
+ return(result);
+
+ case PTRACE_POKEDATA:
+ case PTRACE_POKETEXT:
+ case PTRACE_POKEUSR:
+ result = ptrace(arg1, child, arg3, arg4);
+ if(result == -1) return(-errno);
+
+ if(arg1 == PTRACE_POKEUSR) ptrace_pokeuser(arg3, arg4);
+ return(result);
+
+#ifdef UM_HAVE_SETFPREGS
+ case PTRACE_SETFPREGS:
+ {
+ long regs[FP_FRAME_SIZE];
+ int i;
+
+ for (i = 0; i < sizeof(regs)/sizeof(regs[0]); i++)
+ regs[i] = ptrace (PTRACE_PEEKDATA, debugger->pid,
+ arg4 + 4 * i, 0);
+ result = ptrace(PTRACE_SETFPREGS, child, 0, regs);
+ if(result == -1) return(-errno);
+
+ return(result);
+ }
+#endif
+
+#ifdef UM_HAVE_SETFPXREGS
+ case PTRACE_SETFPXREGS:
+ {
+ long regs[FPX_FRAME_SIZE];
+ int i;
+
+ for (i = 0; i < sizeof(regs)/sizeof(regs[0]); i++)
+ regs[i] = ptrace (PTRACE_PEEKDATA, debugger->pid,
+ arg4 + 4 * i, 0);
+ result = ptrace(PTRACE_SETFPXREGS, child, 0, regs);
+ if(result == -1) return(-errno);
+
+ return(result);
+ }
+#endif
+
+#ifdef UM_HAVE_SETREGS
+ case PTRACE_SETREGS:
+ {
+ long regs[FRAME_SIZE];
+ int i;
+
+ for (i = 0; i < sizeof(regs)/sizeof(regs[0]); i++)
+ regs[i] = ptrace(PTRACE_PEEKDATA, debugger->pid,
+ arg4 + 4 * i, 0);
+ result = ptrace(PTRACE_SETREGS, child, 0, regs);
+ if(result == -1) return(-errno);
+
+ return(result);
+ }
+#endif
+
+ case PTRACE_SINGLESTEP:
+ if(!debugger->debugee->in_context) return(-EPERM);
+ sigemptyset(&relay);
+ sigaddset(&relay, SIGSEGV);
+ sigaddset(&relay, SIGILL);
+ sigaddset(&relay, SIGBUS);
+ result = ptrace(PTRACE_SINGLESTEP, child, arg3, arg4);
+ if(result == -1) return(-errno);
+
+ status = wait_for_stop(child, SIGTRAP, PTRACE_SINGLESTEP,
+ &relay);
+ child_proxy(child, status);
+ return(result);
+
+ case PTRACE_SYSCALL:
+ if(!debugger->debugee->in_context) return(-EPERM);
+ result = ptrace(PTRACE_SYSCALL, child, arg3, arg4);
+ if(result == -1) return(-errno);
+
+ *ret = PTRACE_SYSCALL;
+ return(result);
+
+ case PTRACE_TRACEME:
+ default:
+ return(-EINVAL);
+ }
+}
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only. This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff --git a/arch/um/kernel/tt/ptproxy/sysdep.c b/arch/um/kernel/tt/ptproxy/sysdep.c
new file mode 100644
index 000000000000..a5f0e01e214e
--- /dev/null
+++ b/arch/um/kernel/tt/ptproxy/sysdep.c
@@ -0,0 +1,70 @@
+/**********************************************************************
+sysdep.c
+
+Copyright (C) 1999 Lars Brinkhoff. See the file COPYING for licensing
+terms and conditions.
+**********************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <linux/unistd.h>
+#include "ptrace_user.h"
+#include "user_util.h"
+#include "user.h"
+
+int get_syscall(pid_t pid, long *arg1, long *arg2, long *arg3, long *arg4,
+ long *arg5)
+{
+ *arg1 = ptrace(PTRACE_PEEKUSR, pid, PT_SYSCALL_ARG1_OFFSET, 0);
+ *arg2 = ptrace(PTRACE_PEEKUSR, pid, PT_SYSCALL_ARG2_OFFSET, 0);
+ *arg3 = ptrace(PTRACE_PEEKUSR, pid, PT_SYSCALL_ARG3_OFFSET, 0);
+ *arg4 = ptrace(PTRACE_PEEKUSR, pid, PT_SYSCALL_ARG4_OFFSET, 0);
+ *arg5 = ptrace(PTRACE_PEEKUSR, pid, PT_SYSCALL_ARG5_OFFSET, 0);
+ return(ptrace(PTRACE_PEEKUSR, pid, PT_SYSCALL_NR_OFFSET, 0));
+}
+
+void syscall_cancel(pid_t pid, int result)
+{
+ if((ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_NR_OFFSET,
+ __NR_getpid) < 0) ||
+ (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) ||
+ (wait_for_stop(pid, SIGTRAP, PTRACE_SYSCALL, NULL) < 0) ||
+ (ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_RET_OFFSET, result) < 0) ||
+ (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0))
+ printk("ptproxy: couldn't cancel syscall: errno = %d\n",
+ errno);
+}
+
+void syscall_set_result(pid_t pid, long result)
+{
+ ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_RET_OFFSET, result);
+}
+
+void syscall_continue(pid_t pid)
+{
+ ptrace(PTRACE_SYSCALL, pid, 0, 0);
+}
+
+int syscall_pause(pid_t pid)
+{
+ if(ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_NR_OFFSET, __NR_pause) < 0){
+ printk("syscall_change - ptrace failed, errno = %d\n", errno);
+ return(-1);
+ }
+ return(0);
+}
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only. This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff --git a/arch/um/kernel/tt/ptproxy/sysdep.h b/arch/um/kernel/tt/ptproxy/sysdep.h
new file mode 100644
index 000000000000..735f488049aa
--- /dev/null
+++ b/arch/um/kernel/tt/ptproxy/sysdep.h
@@ -0,0 +1,25 @@
+/**********************************************************************
+sysdep.h
+
+Copyright (C) 1999 Lars Brinkhoff.
+Copyright (C) 2001 Jeff Dike (jdike@karaya.com)
+See the file COPYING for licensing terms and conditions.
+**********************************************************************/
+
+extern int get_syscall(pid_t pid, long *arg1, long *arg2, long *arg3,
+ long *arg4, long *arg5);
+extern void syscall_cancel (pid_t pid, long result);
+extern void syscall_set_result (pid_t pid, long result);
+extern void syscall_continue (pid_t pid);
+extern int syscall_pause(pid_t pid);
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only. This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff --git a/arch/um/kernel/tt/ptproxy/wait.c b/arch/um/kernel/tt/ptproxy/wait.c
new file mode 100644
index 000000000000..12f6319d8d76
--- /dev/null
+++ b/arch/um/kernel/tt/ptproxy/wait.c
@@ -0,0 +1,86 @@
+/**********************************************************************
+wait.c
+
+Copyright (C) 1999 Lars Brinkhoff. See the file COPYING for licensing
+terms and conditions.
+
+**********************************************************************/
+
+#include <errno.h>
+#include <signal.h>
+#include <sys/wait.h>
+
+#include "ptproxy.h"
+#include "sysdep.h"
+#include "wait.h"
+#include "user_util.h"
+#include "ptrace_user.h"
+#include "sysdep/ptrace.h"
+#include "sysdep/sigcontext.h"
+
+int proxy_wait_return(struct debugger *debugger, pid_t unused)
+{
+ debugger->waiting = 0;
+
+ if(debugger->debugee->died || (debugger->wait_options & __WCLONE)){
+ debugger_cancelled_return(debugger, -ECHILD);
+ return(0);
+ }
+
+ if(debugger->debugee->zombie && debugger->debugee->event)
+ debugger->debugee->died = 1;
+
+ if(debugger->debugee->event){
+ debugger->debugee->event = 0;
+ ptrace(PTRACE_POKEDATA, debugger->pid,
+ debugger->wait_status_ptr,
+ debugger->debugee->wait_status);
+ /* if (wait4)
+ ptrace (PTRACE_POKEDATA, pid, rusage_ptr, ...); */
+ debugger_cancelled_return(debugger, debugger->debugee->pid);
+ return(0);
+ }
+
+ /* pause will return -EINTR, which happens to be right for wait */
+ debugger_normal_return(debugger, -1);
+ return(0);
+}
+
+int parent_wait_return(struct debugger *debugger, pid_t unused)
+{
+ return(debugger_normal_return(debugger, -1));
+}
+
+int real_wait_return(struct debugger *debugger)
+{
+ unsigned long ip;
+ int pid;
+
+ pid = debugger->pid;
+
+ ip = ptrace(PTRACE_PEEKUSR, pid, PT_IP_OFFSET, 0);
+ IP_RESTART_SYSCALL(ip);
+
+ if(ptrace(PTRACE_POKEUSR, pid, PT_IP_OFFSET, ip) < 0)
+ tracer_panic("real_wait_return : Failed to restart system "
+ "call, errno = %d\n", errno);
+
+ if((ptrace(PTRACE_SYSCALL, debugger->pid, 0, SIGCHLD) < 0) ||
+ (ptrace(PTRACE_SYSCALL, debugger->pid, 0, 0) < 0) ||
+ (ptrace(PTRACE_SYSCALL, debugger->pid, 0, 0) < 0) ||
+ debugger_normal_return(debugger, -1))
+ tracer_panic("real_wait_return : gdb failed to wait, "
+ "errno = %d\n", errno);
+ return(0);
+}
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only. This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff --git a/arch/um/kernel/tt/ptproxy/wait.h b/arch/um/kernel/tt/ptproxy/wait.h
new file mode 100644
index 000000000000..542e73ee2cee
--- /dev/null
+++ b/arch/um/kernel/tt/ptproxy/wait.h
@@ -0,0 +1,15 @@
+/**********************************************************************
+wait.h
+
+Copyright (C) 1999 Lars Brinkhoff. See the file COPYING for licensing
+terms and conditions.
+**********************************************************************/
+
+#ifndef __PTPROXY_WAIT_H
+#define __PTPROXY_WAIT_H
+
+extern int proxy_wait_return(struct debugger *debugger, pid_t unused);
+extern int real_wait_return(struct debugger *debugger);
+extern int parent_wait_return(struct debugger *debugger, pid_t unused);
+
+#endif