sync hh.org
[hh.org.git] / arch / um / kernel / tt / ptproxy / ptrace.c
blob03774427d46865b37d3dffce4dd6d695d4ebb6bc
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"
23 #include "os.h"
25 long proxy_ptrace(struct debugger *debugger, int arg1, pid_t arg2,
26 long arg3, long arg4, pid_t child, int *ret)
28 sigset_t relay;
29 long result;
30 int status;
32 *ret = 0;
33 if(debugger->debugee->died) return(-ESRCH);
35 switch(arg1){
36 case PTRACE_ATTACH:
37 if(debugger->debugee->traced) return(-EPERM);
39 debugger->debugee->pid = arg2;
40 debugger->debugee->traced = 1;
42 if(is_valid_pid(arg2) && (arg2 != child)){
43 debugger->debugee->in_context = 0;
44 kill(arg2, SIGSTOP);
45 debugger->debugee->event = 1;
46 debugger->debugee->wait_status = W_STOPCODE(SIGSTOP);
48 else {
49 debugger->debugee->in_context = 1;
50 if(debugger->debugee->stopped)
51 child_proxy(child, W_STOPCODE(SIGSTOP));
52 else kill(child, SIGSTOP);
55 return(0);
57 case PTRACE_DETACH:
58 if(!debugger->debugee->traced) return(-EPERM);
60 debugger->debugee->traced = 0;
61 debugger->debugee->pid = 0;
62 if(!debugger->debugee->in_context)
63 kill(child, SIGCONT);
65 return(0);
67 case PTRACE_CONT:
68 if(!debugger->debugee->in_context) return(-EPERM);
69 *ret = PTRACE_CONT;
70 return(ptrace(PTRACE_CONT, child, arg3, arg4));
72 #ifdef UM_HAVE_GETFPREGS
73 case PTRACE_GETFPREGS:
75 long regs[FP_FRAME_SIZE];
76 int i, result;
78 result = ptrace(PTRACE_GETFPREGS, child, 0, regs);
79 if(result == -1) return(-errno);
81 for (i = 0; i < sizeof(regs)/sizeof(regs[0]); i++)
82 ptrace(PTRACE_POKEDATA, debugger->pid, arg4 + 4 * i,
83 regs[i]);
84 return(result);
86 #endif
88 #ifdef UM_HAVE_GETFPXREGS
89 case PTRACE_GETFPXREGS:
91 long regs[FPX_FRAME_SIZE];
92 int i, result;
94 result = ptrace(PTRACE_GETFPXREGS, child, 0, regs);
95 if(result == -1) return(-errno);
97 for (i = 0; i < sizeof(regs)/sizeof(regs[0]); i++)
98 ptrace(PTRACE_POKEDATA, debugger->pid, arg4 + 4 * i,
99 regs[i]);
100 return(result);
102 #endif
104 #ifdef UM_HAVE_GETREGS
105 case PTRACE_GETREGS:
107 long regs[FRAME_SIZE];
108 int i, result;
110 result = ptrace(PTRACE_GETREGS, child, 0, regs);
111 if(result == -1) return(-errno);
113 for (i = 0; i < sizeof(regs)/sizeof(regs[0]); i++)
114 ptrace (PTRACE_POKEDATA, debugger->pid,
115 arg4 + 4 * i, regs[i]);
116 return(result);
118 break;
119 #endif
121 case PTRACE_KILL:
122 result = ptrace(PTRACE_KILL, child, arg3, arg4);
123 if(result == -1) return(-errno);
125 return(result);
127 case PTRACE_PEEKDATA:
128 case PTRACE_PEEKTEXT:
129 case PTRACE_PEEKUSR:
130 /* The value being read out could be -1, so we have to
131 * check errno to see if there's an error, and zero it
132 * beforehand so we're not faked out by an old error
135 errno = 0;
136 result = ptrace(arg1, child, arg3, 0);
137 if((result == -1) && (errno != 0)) return(-errno);
139 result = ptrace(PTRACE_POKEDATA, debugger->pid, arg4, result);
140 if(result == -1) return(-errno);
142 return(result);
144 case PTRACE_POKEDATA:
145 case PTRACE_POKETEXT:
146 case PTRACE_POKEUSR:
147 result = ptrace(arg1, child, arg3, arg4);
148 if(result == -1) return(-errno);
150 if(arg1 == PTRACE_POKEUSR) ptrace_pokeuser(arg3, arg4);
151 return(result);
153 #ifdef UM_HAVE_SETFPREGS
154 case PTRACE_SETFPREGS:
156 long regs[FP_FRAME_SIZE];
157 int i;
159 for (i = 0; i < sizeof(regs)/sizeof(regs[0]); i++)
160 regs[i] = ptrace (PTRACE_PEEKDATA, debugger->pid,
161 arg4 + 4 * i, 0);
162 result = ptrace(PTRACE_SETFPREGS, child, 0, regs);
163 if(result == -1) return(-errno);
165 return(result);
167 #endif
169 #ifdef UM_HAVE_SETFPXREGS
170 case PTRACE_SETFPXREGS:
172 long regs[FPX_FRAME_SIZE];
173 int i;
175 for (i = 0; i < sizeof(regs)/sizeof(regs[0]); i++)
176 regs[i] = ptrace (PTRACE_PEEKDATA, debugger->pid,
177 arg4 + 4 * i, 0);
178 result = ptrace(PTRACE_SETFPXREGS, child, 0, regs);
179 if(result == -1) return(-errno);
181 return(result);
183 #endif
185 #ifdef UM_HAVE_SETREGS
186 case PTRACE_SETREGS:
188 long regs[FRAME_SIZE];
189 int i;
191 for (i = 0; i < sizeof(regs)/sizeof(regs[0]); i++)
192 regs[i] = ptrace(PTRACE_PEEKDATA, debugger->pid,
193 arg4 + 4 * i, 0);
194 result = ptrace(PTRACE_SETREGS, child, 0, regs);
195 if(result == -1) return(-errno);
197 return(result);
199 #endif
201 case PTRACE_SINGLESTEP:
202 if(!debugger->debugee->in_context) return(-EPERM);
203 sigemptyset(&relay);
204 sigaddset(&relay, SIGSEGV);
205 sigaddset(&relay, SIGILL);
206 sigaddset(&relay, SIGBUS);
207 result = ptrace(PTRACE_SINGLESTEP, child, arg3, arg4);
208 if(result == -1) return(-errno);
210 status = wait_for_stop(child, SIGTRAP, PTRACE_SINGLESTEP,
211 &relay);
212 child_proxy(child, status);
213 return(result);
215 case PTRACE_SYSCALL:
216 if(!debugger->debugee->in_context) return(-EPERM);
217 result = ptrace(PTRACE_SYSCALL, child, arg3, arg4);
218 if(result == -1) return(-errno);
220 *ret = PTRACE_SYSCALL;
221 return(result);
223 case PTRACE_TRACEME:
224 default:
225 return(-EINVAL);
230 * Overrides for Emacs so that we follow Linus's tabbing style.
231 * Emacs will notice this stuff at the end of the file and automatically
232 * adjust the settings for this buffer only. This must remain at the end
233 * of the file.
234 * ---------------------------------------------------------------------------
235 * Local variables:
236 * c-file-style: "linux"
237 * End: