MOXA linux-2.6.x / linux-2.6.9-uc0 from sdlinux-moxaart.tgz
[linux-2.6.9-moxart.git] / arch / um / kernel / frame.c
blob4b349f20795ddc7b5568829e38779616939e68f3
1 /*
2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <unistd.h>
9 #include <string.h>
10 #include <signal.h>
11 #include <wait.h>
12 #include <sched.h>
13 #include <errno.h>
14 #include <sys/ptrace.h>
15 #include <sys/syscall.h>
16 #include <sys/mman.h>
17 #include <asm/page.h>
18 #include <asm/ptrace.h>
19 #include <asm/sigcontext.h>
20 #include "sysdep/ptrace.h"
21 #include "sysdep/sigcontext.h"
22 #include "frame_user.h"
23 #include "kern_util.h"
24 #include "user_util.h"
25 #include "ptrace_user.h"
26 #include "os.h"
28 static int capture_stack(int (*child)(void *arg), void *arg, void *sp,
29 unsigned long top, void **data_out)
31 unsigned long regs[FRAME_SIZE];
32 int pid, status, n, len;
34 /* Start the child as a thread */
35 pid = clone(child, sp, CLONE_VM | SIGCHLD, arg);
36 if(pid < 0){
37 printf("capture_stack : clone failed - errno = %d\n", errno);
38 exit(1);
41 /* Wait for it to stop itself and continue it with a SIGUSR1 to force
42 * it into the signal handler.
44 CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED));
45 if(n < 0){
46 printf("capture_stack : waitpid failed - errno = %d\n", errno);
47 exit(1);
49 if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP)){
50 fprintf(stderr, "capture_stack : Expected SIGSTOP, "
51 "got status = 0x%x\n", status);
52 exit(1);
54 if(ptrace(PTRACE_CONT, pid, 0, SIGUSR1) < 0){
55 printf("capture_stack : PTRACE_CONT failed - errno = %d\n",
56 errno);
57 exit(1);
60 /* Wait for it to stop itself again and grab its registers again.
61 * At this point, the handler has stuffed the addresses of
62 * sig, sc, and SA_RESTORER in raw.
64 CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED));
65 if(n < 0){
66 printf("capture_stack : waitpid failed - errno = %d\n", errno);
67 exit(1);
69 if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP)){
70 fprintf(stderr, "capture_stack : Expected SIGSTOP, "
71 "got status = 0x%x\n", status);
72 exit(1);
74 if(ptrace(PTRACE_GETREGS, pid, 0, regs) < 0){
75 printf("capture_stack : PTRACE_GETREGS failed - errno = %d\n",
76 errno);
77 exit(1);
80 /* It has outlived its usefulness, so continue it so it can exit */
81 if(ptrace(PTRACE_CONT, pid, 0, 0) < 0){
82 printf("capture_stack : PTRACE_CONT failed - errno = %d\n",
83 errno);
84 exit(1);
86 CATCH_EINTR(n = waitpid(pid, &status, 0));
87 if(n < 0){
88 printf("capture_stack : waitpid failed - errno = %d\n", errno);
89 exit(1);
91 if(!WIFSIGNALED(status) || (WTERMSIG(status) != 9)){
92 printf("capture_stack : Expected exit signal 9, "
93 "got status = 0x%x\n", status);
94 exit(1);
97 /* The frame that we want is the top of the signal stack */
99 len = top - PT_SP(regs);
100 *data_out = malloc(len);
101 if(*data_out == NULL){
102 printf("capture_stack : malloc failed - errno = %d\n", errno);
103 exit(1);
105 memcpy(*data_out, (void *) PT_SP(regs), len);
107 return(len);
110 struct common_raw {
111 void *stack;
112 int size;
113 unsigned long sig;
114 unsigned long sr;
115 unsigned long sp;
116 struct arch_frame_data_raw arch;
119 #define SA_RESTORER (0x04000000)
121 typedef unsigned long old_sigset_t;
123 struct old_sigaction {
124 __sighandler_t handler;
125 old_sigset_t sa_mask;
126 unsigned long sa_flags;
127 void (*sa_restorer)(void);
130 static void child_common(struct common_raw *common, sighandler_t handler,
131 int restorer, int flags)
133 stack_t ss = ((stack_t) { .ss_sp = common->stack,
134 .ss_flags = 0,
135 .ss_size = common->size });
136 int err;
138 if(ptrace(PTRACE_TRACEME, 0, 0, 0) < 0){
139 printf("PTRACE_TRACEME failed, errno = %d\n", errno);
141 if(sigaltstack(&ss, NULL) < 0){
142 printf("sigaltstack failed - errno = %d\n", errno);
143 kill(getpid(), SIGKILL);
146 if(restorer){
147 struct sigaction sa;
149 sa.sa_handler = handler;
150 sigemptyset(&sa.sa_mask);
151 sa.sa_flags = SA_ONSTACK | flags;
152 err = sigaction(SIGUSR1, &sa, NULL);
154 else {
155 struct old_sigaction sa;
157 sa.handler = handler;
158 sa.sa_mask = 0;
159 sa.sa_flags = (SA_ONSTACK | flags) & ~SA_RESTORER;
160 err = syscall(__NR_sigaction, SIGUSR1, &sa, NULL);
163 if(err < 0){
164 printf("sigaction failed - errno = %d\n", errno);
165 kill(getpid(), SIGKILL);
168 os_stop_process(os_getpid());
171 /* Changed only during early boot */
172 struct sc_frame signal_frame_sc;
174 struct sc_frame signal_frame_sc_sr;
176 struct sc_frame_raw {
177 struct common_raw common;
178 unsigned long sc;
179 int restorer;
182 /* Changed only during early boot */
183 static struct sc_frame_raw *raw_sc = NULL;
185 static void sc_handler(int sig, struct sigcontext sc)
187 raw_sc->common.sig = (unsigned long) &sig;
188 raw_sc->common.sr = frame_restorer();
189 raw_sc->common.sp = frame_sp();
190 raw_sc->sc = (unsigned long) &sc;
191 setup_arch_frame_raw(&raw_sc->common.arch, &sc + 1, raw_sc->common.sr);
193 os_stop_process(os_getpid());
194 kill(getpid(), SIGKILL);
197 static int sc_child(void *arg)
199 raw_sc = arg;
200 child_common(&raw_sc->common, (sighandler_t) sc_handler,
201 raw_sc->restorer, 0);
202 return(-1);
205 /* Changed only during early boot */
206 struct si_frame signal_frame_si;
208 struct si_frame_raw {
209 struct common_raw common;
210 unsigned long sip;
211 unsigned long si;
212 unsigned long ucp;
213 unsigned long uc;
216 /* Changed only during early boot */
217 static struct si_frame_raw *raw_si = NULL;
219 static void si_handler(int sig, siginfo_t *si, struct ucontext *ucontext)
221 raw_si->common.sig = (unsigned long) &sig;
222 raw_si->common.sr = frame_restorer();
223 raw_si->common.sp = frame_sp();
224 raw_si->sip = (unsigned long) &si;
225 raw_si->si = (unsigned long) si;
226 raw_si->ucp = (unsigned long) &ucontext;
227 raw_si->uc = (unsigned long) ucontext;
228 setup_arch_frame_raw(&raw_si->common.arch,
229 ucontext->uc_mcontext.fpregs, raw_si->common.sr);
231 os_stop_process(os_getpid());
232 kill(getpid(), SIGKILL);
235 static int si_child(void *arg)
237 raw_si = arg;
238 child_common(&raw_si->common, (sighandler_t) si_handler, 1,
239 SA_SIGINFO);
240 return(-1);
243 static int relative_sr(unsigned long sr, int sr_index, void *stack,
244 void *framep)
246 unsigned long *srp = (unsigned long *) sr;
247 unsigned long frame = (unsigned long) framep;
249 if((*srp & PAGE_MASK) == (unsigned long) stack){
250 *srp -= sr;
251 *((unsigned long *) (frame + sr_index)) = *srp;
252 return(1);
254 else return(0);
257 static unsigned long capture_stack_common(int (*proc)(void *), void *arg,
258 struct common_raw *common_in,
259 void *top, void *sigstack,
260 int stack_len,
261 struct frame_common *common_out)
263 unsigned long sig_top = (unsigned long) sigstack + stack_len, base;
265 common_in->stack = (void *) sigstack;
266 common_in->size = stack_len;
267 common_out->len = capture_stack(proc, arg, top, sig_top,
268 &common_out->data);
269 base = sig_top - common_out->len;
270 common_out->sig_index = common_in->sig - base;
271 common_out->sp_index = common_in->sp - base;
272 common_out->sr_index = common_in->sr - base;
273 common_out->sr_relative = relative_sr(common_in->sr,
274 common_out->sr_index, sigstack,
275 common_out->data);
276 return(base);
279 void capture_signal_stack(void)
281 struct sc_frame_raw raw_sc;
282 struct si_frame_raw raw_si;
283 void *stack, *sigstack;
284 unsigned long top, base;
286 stack = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC,
287 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
288 sigstack = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC,
289 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
290 if((stack == MAP_FAILED) || (sigstack == MAP_FAILED)){
291 printf("capture_signal_stack : mmap failed - errno = %d\n",
292 errno);
293 exit(1);
296 top = (unsigned long) stack + PAGE_SIZE - sizeof(void *);
298 /* Get the sigcontext, no sigrestorer layout */
299 raw_sc.restorer = 0;
300 base = capture_stack_common(sc_child, &raw_sc, &raw_sc.common,
301 (void *) top, sigstack, PAGE_SIZE,
302 &signal_frame_sc.common);
304 signal_frame_sc.sc_index = raw_sc.sc - base;
305 setup_arch_frame(&raw_sc.common.arch, &signal_frame_sc.common.arch);
307 /* Ditto for the sigcontext, sigrestorer layout */
308 raw_sc.restorer = 1;
309 base = capture_stack_common(sc_child, &raw_sc, &raw_sc.common,
310 (void *) top, sigstack, PAGE_SIZE,
311 &signal_frame_sc_sr.common);
312 signal_frame_sc_sr.sc_index = raw_sc.sc - base;
313 setup_arch_frame(&raw_sc.common.arch, &signal_frame_sc_sr.common.arch);
315 /* And the siginfo layout */
317 base = capture_stack_common(si_child, &raw_si, &raw_si.common,
318 (void *) top, sigstack, PAGE_SIZE,
319 &signal_frame_si.common);
320 signal_frame_si.sip_index = raw_si.sip - base;
321 signal_frame_si.si_index = raw_si.si - base;
322 signal_frame_si.ucp_index = raw_si.ucp - base;
323 signal_frame_si.uc_index = raw_si.uc - base;
324 setup_arch_frame(&raw_si.common.arch, &signal_frame_si.common.arch);
326 if((munmap(stack, PAGE_SIZE) < 0) ||
327 (munmap(sigstack, PAGE_SIZE) < 0)){
328 printf("capture_signal_stack : munmap failed - errno = %d\n",
329 errno);
330 exit(1);
335 * Overrides for Emacs so that we follow Linus's tabbing style.
336 * Emacs will notice this stuff at the end of the file and automatically
337 * adjust the settings for this buffer only. This must remain at the end
338 * of the file.
339 * ---------------------------------------------------------------------------
340 * Local variables:
341 * c-file-style: "linux"
342 * End: