Version:
~ [ 0.6-2.3.46 ] ~
Architecture:
~ [ um ] ~
** Warning: Cannot open xref database.
1 #include <stdio.h>
2 #include <unistd.h>
3 #include <signal.h>
4 #include <errno.h>
5 #include <sched.h>
6 #include <sys/ptrace.h>
7 #include <sys/time.h>
8 #include <sys/wait.h>
9 #include <sys/mman.h>
10 #include <asm/page.h>
11 #include <asm/unistd.h>
12 #include <asm/ptrace.h>
13 #include "user_util.h"
14 #include "kern_util.h"
15 #include "user.h"
16
17 static void signal_segv(int sig)
18 {
19 write(2, "Seg fault in signals\n", strlen("Seg fault in signals\n"));
20 stop();
21 }
22
23 int detach(int pid)
24 {
25 return(ptrace(PTRACE_DETACH, pid, 0, SIGSTOP));
26 }
27
28 static int signal_tramp(void *arg)
29 {
30 int (*proc)(void *);
31
32 if(ptrace(PTRACE_TRACEME, 0, 0, 0) < 0)
33 panic("ptrace PTRACE_TRACEME failed");
34 signal(SIGUSR1, SIG_IGN);
35 set_timers();
36 set_cmdline("(idle thread)");
37 proc = arg;
38 return((*proc)(NULL));
39 }
40
41 static void signal_usr1(int sig)
42 {
43 }
44
45 struct {
46 unsigned long address;
47 int is_write;
48 int pid;
49 } segfault_record[1024];
50
51 int segfault_index = 0;
52
53 struct {
54 int pid;
55 int signal;
56 unsigned long addr;
57 struct timeval time;
58 } signal_record[1024];
59
60 int signal_index = 0;
61 int nsignals = 0;
62
63 int signals(void *arg)
64 {
65 struct init_thread *init_info;
66 void *task;
67 int status, pid, sig, cont_type, tracing, want_tracing, op;
68 int last_index, proc_id;
69
70 signal(SIGSEGV, signal_segv);
71 signal(SIGUSR1, signal_usr1);
72 register_pid(getpid(), 0);
73 printk("signal thread pid = %d\n", getpid());
74 init_info = arg;
75 clone(signal_tramp, init_info->sp, CLONE_FILES | SIGCHLD, init_info->proc);
76 set_cmdline("(tracing thread)");
77 while(1){
78 if((pid = linux_wait(-1, &status, WUNTRACED)) <= 0){
79 if(errno != ECHILD){
80 printk("wait failed - errno = %d\n", errno);
81 }
82 continue;
83 }
84 nsignals++;
85 if(WIFEXITED(status)) ;
86 #ifdef notdef
87 {
88 printk("Child %d exited with status %d\n", pid, WEXITSTATUS(status));
89 }
90 #endif
91 else if(WIFSIGNALED(status)){
92 sig = WTERMSIG(status);
93 if(sig != 9){
94 printk("Child %d exited with signal %d\n", pid, sig);
95 }
96 }
97 else if(WIFSTOPPED(status)){
98 sig = WSTOPSIG(status);
99 if(signal_index == 1024){
100 signal_index = 0;
101 last_index = 1023;
102 }
103 else last_index = signal_index - 1;
104 if((sig == SIGPROF) && (signal_record[last_index].signal == SIGPROF) &&
105 (signal_record[last_index].pid == pid))
106 signal_index = last_index;
107 signal_record[signal_index].pid = pid;
108 gettimeofday(&signal_record[signal_index].time, NULL);
109 signal_record[signal_index].addr = 0;
110 signal_record[signal_index++].signal = sig;
111 #ifdef __SMP__
112 proc_id = pid_to_processor_id(pid);
113 task = cpu_tasks[proc_id].task;
114 #else
115 task = get_current_task();
116 #endif
117 tracing = is_tracing(task);
118 want_tracing = get_want_tracing(task);
119 switch(sig){
120 case SIGUSR1:
121 sig = 0;
122 if((op = do_proc_op(task, proc_id)) != OP_NONE){
123 if((op == OP_EXEC) || (op == OP_SWITCH)) continue;
124 }
125 else {
126 printk("Detaching pid %d\n", pid);
127 detach(pid);
128 continue;
129 }
130 break;
131 case SIGSTOP:
132 continue;
133 case SIGBUS:
134 case SIGILL:
135 PROC_UNTESTED();
136 break;
137 case SIGTRAP:
138 sig = 0;
139 if((tracing == want_tracing) && (tracing != 0)){
140 do_syscall(task, pid);
141 continue;
142 }
143 break;
144 case SIGUSR2:
145 if(is_tracing(task)) panic("tracing in a system call");
146 break;
147 case SIGVTALRM:
148 /* XXX this causes interrupts to be lost */
149 if(sigs_blocked(task)){
150 extern int blocked_timers;
151 blocked_timers++;
152 if(tracing != 0) cont_type = PTRACE_SYSCALL;
153 else cont_type = PTRACE_CONT;
154 if(ptrace(cont_type, pid, 0, 0) < 0){
155 panic("ptrace after alarm failed");
156 }
157 continue;
158 }
159 break;
160 default:
161 break;
162 }
163 tracing = want_tracing;
164 set_tracing(task, want_tracing);
165 if(tracing != 0) cont_type = PTRACE_SYSCALL;
166 else cont_type = PTRACE_CONT;
167 if(ptrace(cont_type, pid, 0, sig) != 0){
168 PROC_UNTESTED();
169 printk("ptrace failed\n");
170 }
171 }
172 }
173 return(0);
174 }
175
176 int nsegfaults = 0;
177
178 static void segv_handler(struct sigcontext_struct *sc)
179 {
180 int index;
181
182 lock_trap();
183 index = segfault_index++;
184 if(segfault_index == 1024) segfault_index = 0;
185 unlock_trap();
186 nsegfaults++;
187 segfault_record[index].address = sc->cr2;
188 segfault_record[index].pid = getpid();
189 segfault_record[index].is_write = sc->err & 2;
190 segv(sc->cr2, sc->err & 2);
191 }
192
193 void kern_segv_handler(int sig)
194 {
195 struct sigcontext_struct *sc;
196
197 sc = (struct sigcontext_struct *) (&sig + 1);
198 segv_handler(sc);
199 }
200
201 void user_segv_handler(int sig)
202 {
203 struct sigcontext_struct *sc;
204 unsigned long addr;
205 int is_user;
206
207 sc = (struct sigcontext_struct *) (&sig + 1);
208 if((((unsigned long) &sig) & ~4095) > 0xaf000000) panic("signal on wrong stack");
209 if((addr = forced_fault()) != 0){
210 sc->cr2 = addr;
211 sc->err = 2;
212 segv_handler(sc);
213 kill(getpid(), SIGSTOP);
214 }
215 else {
216 block_signals(NULL);
217 is_user = set_user_thread(NULL, 0);
218 segv_handler(sc);
219 set_user_thread(NULL, is_user);
220 unblock_signals(NULL);
221 }
222 }
223
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.