Linux-2.6.12-rc2
[linux-2.6/next.git] / arch / um / kernel / tt / ptproxy / ptrace.c
blob528a5fc8d8879e85eb641bd5f0e84ea7aaca45f2
1 /**********************************************************************
2 ptrace.c
4 Copyright (C) 1999 Lars Brinkhoff. See the file COPYING for licensing
5 terms and conditions.
7 Jeff Dike (jdike@karaya.com) : Modified for integration into uml
8 **********************************************************************/
10 #include <errno.h>
11 #include <unistd.h>
12 #include <signal.h>
13 #include <sys/types.h>
14 #include <sys/time.h>
15 #include <sys/wait.h>
17 #include "ptproxy.h"
18 #include "debug.h"
19 #include "user_util.h"
20 #include "kern_util.h"
21 #include "ptrace_user.h"
22 #include "tt.h"
24 long proxy_ptrace(struct debugger *debugger, int arg1, pid_t arg2,
25 long arg3, long arg4, pid_t child, int *ret)
27 sigset_t relay;
28 long result;
29 int status;
31 *ret = 0;
32 if(debugger->debugee->died) return(-ESRCH);
34 switch(arg1){
35 case PTRACE_ATTACH:
36 if(debugger->debugee->traced) return(-EPERM);
38 debugger->debugee->pid = arg2;
39 debugger->debugee->traced = 1;
41 if(is_valid_pid(arg2) && (arg2 != child)){
42 debugger->debugee->in_context = 0;
43 kill(arg2, SIGSTOP);
44 debugger->debugee->event = 1;
45 debugger->debugee->wait_status = W_STOPCODE(SIGSTOP);
47 else {
48 debugger->debugee->in_context = 1;
49 if(debugger->debugee->stopped)
50 child_proxy(child, W_STOPCODE(SIGSTOP));
51 else kill(child, SIGSTOP);
54 return(0);
56 case PTRACE_DETACH:
57 if(!debugger->debugee->traced) return(-EPERM);
59 debugger->debugee->traced = 0;
60 debugger->debugee->pid = 0;
61 if(!debugger->debugee->in_context)
62 kill(child, SIGCONT);
64 return(0);
66 case PTRACE_CONT:
67 if(!debugger->debugee->in_context) return(-EPERM);
68 *ret = PTRACE_CONT;
69 return(ptrace(PTRACE_CONT, child, arg3, arg4));
71 #ifdef UM_HAVE_GETFPREGS
72 case PTRACE_GETFPREGS:
74 long regs[FP_FRAME_SIZE];
75 int i, result;
77 result = ptrace(PTRACE_GETFPREGS, child, 0, regs);
78 if(result == -1) return(-errno);
80 for (i = 0; i < sizeof(regs)/sizeof(regs[0]); i++)
81 ptrace(PTRACE_POKEDATA, debugger->pid, arg4 + 4 * i,
82 regs[i]);
83 return(result);
85 #endif
87 #ifdef UM_HAVE_GETFPXREGS
88 case PTRACE_GETFPXREGS:
90 long regs[FPX_FRAME_SIZE];
91 int i, result;
93 result = ptrace(PTRACE_GETFPXREGS, child, 0, regs);
94 if(result == -1) return(-errno);
96 for (i = 0; i < sizeof(regs)/sizeof(regs[0]); i++)
97 ptrace(PTRACE_POKEDATA, debugger->pid, arg4 + 4 * i,
98 regs[i]);
99 return(result);
101 #endif
103 #ifdef UM_HAVE_GETREGS
104 case PTRACE_GETREGS:
106 long regs[FRAME_SIZE];
107 int i, result;
109 result = ptrace(PTRACE_GETREGS, child, 0, regs);
110 if(result == -1) return(-errno);
112 for (i = 0; i < sizeof(regs)/sizeof(regs[0]); i++)
113 ptrace (PTRACE_POKEDATA, debugger->pid,
114 arg4 + 4 * i, regs[i]);
115 return(result);
117 break;
118 #endif
120 case PTRACE_KILL:
121 result = ptrace(PTRACE_KILL, child, arg3, arg4);
122 if(result == -1) return(-errno);
124 return(result);
126 case PTRACE_PEEKDATA:
127 case PTRACE_PEEKTEXT:
128 case PTRACE_PEEKUSR:
129 /* The value being read out could be -1, so we have to
130 * check errno to see if there's an error, and zero it
131 * beforehand so we're not faked out by an old error
134 errno = 0;
135 result = ptrace(arg1, child, arg3, 0);
136 if((result == -1) && (errno != 0)) return(-errno);
138 result = ptrace(PTRACE_POKEDATA, debugger->pid, arg4, result);
139 if(result == -1) return(-errno);
141 return(result);
143 case PTRACE_POKEDATA:
144 case PTRACE_POKETEXT:
145 case PTRACE_POKEUSR:
146 result = ptrace(arg1, child, arg3, arg4);
147 if(result == -1) return(-errno);
149 if(arg1 == PTRACE_POKEUSR) ptrace_pokeuser(arg3, arg4);
150 return(result);
152 #ifdef UM_HAVE_SETFPREGS
153 case PTRACE_SETFPREGS:
155 long regs[FP_FRAME_SIZE];
156 int i;
158 for (i = 0; i < sizeof(regs)/sizeof(regs[0]); i++)
159 regs[i] = ptrace (PTRACE_PEEKDATA, debugger->pid,
160 arg4 + 4 * i, 0);
161 result = ptrace(PTRACE_SETFPREGS, child, 0, regs);
162 if(result == -1) return(-errno);
164 return(result);
166 #endif
168 #ifdef UM_HAVE_SETFPXREGS
169 case PTRACE_SETFPXREGS:
171 long regs[FPX_FRAME_SIZE];
172 int i;
174 for (i = 0; i < sizeof(regs)/sizeof(regs[0]); i++)
175 regs[i] = ptrace (PTRACE_PEEKDATA, debugger->pid,
176 arg4 + 4 * i, 0);
177 result = ptrace(PTRACE_SETFPXREGS, child, 0, regs);
178 if(result == -1) return(-errno);
180 return(result);
182 #endif
184 #ifdef UM_HAVE_SETREGS
185 case PTRACE_SETREGS:
187 long regs[FRAME_SIZE];
188 int i;
190 for (i = 0; i < sizeof(regs)/sizeof(regs[0]); i++)
191 regs[i] = ptrace(PTRACE_PEEKDATA, debugger->pid,
192 arg4 + 4 * i, 0);
193 result = ptrace(PTRACE_SETREGS, child, 0, regs);
194 if(result == -1) return(-errno);
196 return(result);
198 #endif
200 case PTRACE_SINGLESTEP:
201 if(!debugger->debugee->in_context) return(-EPERM);
202 sigemptyset(&relay);
203 sigaddset(&relay, SIGSEGV);
204 sigaddset(&relay, SIGILL);
205 sigaddset(&relay, SIGBUS);
206 result = ptrace(PTRACE_SINGLESTEP, child, arg3, arg4);
207 if(result == -1) return(-errno);
209 status = wait_for_stop(child, SIGTRAP, PTRACE_SINGLESTEP,
210 &relay);
211 child_proxy(child, status);
212 return(result);
214 case PTRACE_SYSCALL:
215 if(!debugger->debugee->in_context) return(-EPERM);
216 result = ptrace(PTRACE_SYSCALL, child, arg3, arg4);
217 if(result == -1) return(-errno);
219 *ret = PTRACE_SYSCALL;
220 return(result);
222 case PTRACE_TRACEME:
223 default:
224 return(-EINVAL);
229 * Overrides for Emacs so that we follow Linus's tabbing style.
230 * Emacs will notice this stuff at the end of the file and automatically
231 * adjust the settings for this buffer only. This must remain at the end
232 * of the file.
233 * ---------------------------------------------------------------------------
234 * Local variables:
235 * c-file-style: "linux"
236 * End: