2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
14 #include <sys/ptrace.h>
15 #include <sys/syscall.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"
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
);
37 printf("capture_stack : clone failed - errno = %d\n", errno
);
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
));
46 printf("capture_stack : waitpid failed - errno = %d\n", errno
);
49 if(!WIFSTOPPED(status
) || (WSTOPSIG(status
) != SIGSTOP
)){
50 fprintf(stderr
, "capture_stack : Expected SIGSTOP, "
51 "got status = 0x%x\n", status
);
54 if(ptrace(PTRACE_CONT
, pid
, 0, SIGUSR1
) < 0){
55 printf("capture_stack : PTRACE_CONT failed - errno = %d\n",
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
));
66 printf("capture_stack : waitpid failed - errno = %d\n", errno
);
69 if(!WIFSTOPPED(status
) || (WSTOPSIG(status
) != SIGSTOP
)){
70 fprintf(stderr
, "capture_stack : Expected SIGSTOP, "
71 "got status = 0x%x\n", status
);
74 if(ptrace(PTRACE_GETREGS
, pid
, 0, regs
) < 0){
75 printf("capture_stack : PTRACE_GETREGS failed - errno = %d\n",
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",
86 CATCH_EINTR(n
= waitpid(pid
, &status
, 0));
88 printf("capture_stack : waitpid failed - errno = %d\n", errno
);
91 if(!WIFSIGNALED(status
) || (WTERMSIG(status
) != 9)){
92 printf("capture_stack : Expected exit signal 9, "
93 "got status = 0x%x\n", status
);
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
);
105 memcpy(*data_out
, (void *) PT_SP(regs
), len
);
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
,
135 .ss_size
= common
->size
});
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
);
149 sa
.sa_handler
= handler
;
150 sigemptyset(&sa
.sa_mask
);
151 sa
.sa_flags
= SA_ONSTACK
| flags
;
152 err
= sigaction(SIGUSR1
, &sa
, NULL
);
155 struct old_sigaction sa
;
157 sa
.handler
= handler
;
159 sa
.sa_flags
= (SA_ONSTACK
| flags
) & ~SA_RESTORER
;
160 err
= syscall(__NR_sigaction
, SIGUSR1
, &sa
, NULL
);
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
;
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
)
200 child_common(&raw_sc
->common
, (sighandler_t
) sc_handler
,
201 raw_sc
->restorer
, 0);
205 /* Changed only during early boot */
206 struct si_frame signal_frame_si
;
208 struct si_frame_raw
{
209 struct common_raw common
;
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
)
238 child_common(&raw_si
->common
, (sighandler_t
) si_handler
, 1,
243 static int relative_sr(unsigned long sr
, int sr_index
, void *stack
,
246 unsigned long *srp
= (unsigned long *) sr
;
247 unsigned long frame
= (unsigned long) framep
;
249 if((*srp
& PAGE_MASK
) == (unsigned long) stack
){
251 *((unsigned long *) (frame
+ sr_index
)) = *srp
;
257 static unsigned long capture_stack_common(int (*proc
)(void *), void *arg
,
258 struct common_raw
*common_in
,
259 void *top
, void *sigstack
,
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
,
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
,
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",
296 top
= (unsigned long) stack
+ PAGE_SIZE
- sizeof(void *);
298 /* Get the sigcontext, no sigrestorer layout */
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 */
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",
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
339 * ---------------------------------------------------------------------------
341 * c-file-style: "linux"