aboutsummaryrefslogtreecommitdiffstats
path: root/arch/um/kernel/tt/tracer.c
diff options
context:
space:
mode:
authorJeff Dike <jdike@addtoit.com>2007-10-16 04:26:50 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-16 12:43:05 -0400
commit42fda66387daa53538ae13a2c858396aaf037158 (patch)
tree77955a91a958fde7be47cb0ff23ac9e1248217db /arch/um/kernel/tt/tracer.c
parenta1ff5878d2628bbe1e42821c024c96f48318f683 (diff)
uml: throw out CONFIG_MODE_TT
This patchset throws out tt mode, which has been non-functional for a while. This is done in phases, interspersed with code cleanups on the affected files. The removal is done as follows: remove all code, config options, and files which depend on CONFIG_MODE_TT get rid of the CHOOSE_MODE macro, which decided whether to call tt-mode or skas-mode code, and replace invocations with their skas portions replace all now-trivial procedures with their skas equivalents There are now a bunch of now-redundant pieces of data structures, including mode-specific pieces of the thread structure, pt_regs, and mm_context. These are all replaced with their skas-specific contents. As part of the ongoing style compliance project, I made a style pass over all files that were changed. There are three such patches, one for each phase, covering the files affected by that phase but no later ones. I noticed that we weren't freeing the LDT state associated with a process when it exited, so that's fixed in one of the later patches. The last patch is a tidying patch which I've had for a while, but which caused inexplicable crashes under tt mode. Since that is no longer a problem, this can now go in. This patch: Start getting rid of tt mode support. This patch throws out CONFIG_MODE_TT and all config options, code, and files which depend on it. CONFIG_MODE_SKAS is gone and everything that depends on it is included unconditionally. The few changed lines are in re-written Kconfig help, lines which needed something skas-related removed from them, and a few more which weren't strictly deletions. Signed-off-by: Jeff Dike <jdike@linux.intel.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'arch/um/kernel/tt/tracer.c')
-rw-r--r--arch/um/kernel/tt/tracer.c461
1 files changed, 0 insertions, 461 deletions
diff --git a/arch/um/kernel/tt/tracer.c b/arch/um/kernel/tt/tracer.c
deleted file mode 100644
index c23588393f6e..000000000000
--- a/arch/um/kernel/tt/tracer.c
+++ /dev/null
@@ -1,461 +0,0 @@
1/*
2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#include <stdio.h>
7#include <stdlib.h>
8#include <stdarg.h>
9#include <unistd.h>
10#include <signal.h>
11#include <errno.h>
12#include <sched.h>
13#include <string.h>
14#include <sys/mman.h>
15#include <sys/time.h>
16#include <sys/wait.h>
17#include "user.h"
18#include "sysdep/ptrace.h"
19#include "sigcontext.h"
20#include "sysdep/sigcontext.h"
21#include "os.h"
22#include "mem_user.h"
23#include "process.h"
24#include "kern_util.h"
25#include "chan_user.h"
26#include "ptrace_user.h"
27#include "irq_user.h"
28#include "mode.h"
29#include "tt.h"
30
31static int tracer_winch[2];
32
33int is_tracer_winch(int pid, int fd, void *data)
34{
35 if(pid != os_getpgrp())
36 return(0);
37
38 register_winch_irq(tracer_winch[0], fd, -1, data);
39 return(1);
40}
41
42static void tracer_winch_handler(int sig)
43{
44 int n;
45 char c = 1;
46
47 n = os_write_file(tracer_winch[1], &c, sizeof(c));
48 if(n != sizeof(c))
49 printk("tracer_winch_handler - write failed, err = %d\n", -n);
50}
51
52/* Called only by the tracing thread during initialization */
53
54static void setup_tracer_winch(void)
55{
56 int err;
57
58 err = os_pipe(tracer_winch, 1, 1);
59 if(err < 0){
60 printk("setup_tracer_winch : os_pipe failed, err = %d\n", -err);
61 return;
62 }
63 signal(SIGWINCH, tracer_winch_handler);
64}
65
66void attach_process(int pid)
67{
68 if((ptrace(PTRACE_ATTACH, pid, 0, 0) < 0) ||
69 (ptrace(PTRACE_CONT, pid, 0, 0) < 0))
70 tracer_panic("OP_FORK failed to attach pid");
71 wait_for_stop(pid, SIGSTOP, PTRACE_CONT, NULL);
72 if (ptrace(PTRACE_OLDSETOPTIONS, pid, 0, (void *)PTRACE_O_TRACESYSGOOD) < 0)
73 tracer_panic("OP_FORK: PTRACE_SETOPTIONS failed, errno = %d", errno);
74 if(ptrace(PTRACE_CONT, pid, 0, 0) < 0)
75 tracer_panic("OP_FORK failed to continue process");
76}
77
78void tracer_panic(char *format, ...)
79{
80 va_list ap;
81
82 va_start(ap, format);
83 vprintf(format, ap);
84 va_end(ap);
85 printf("\n");
86 while(1) pause();
87}
88
89static void tracer_segv(int sig, struct sigcontext sc)
90{
91 struct faultinfo fi;
92 GET_FAULTINFO_FROM_SC(fi, &sc);
93 printf("Tracing thread segfault at address 0x%lx, ip 0x%lx\n",
94 FAULT_ADDRESS(fi), SC_IP(&sc));
95 while(1)
96 pause();
97}
98
99/* Changed early in boot, and then only read */
100int debug = 0;
101int debug_stop = 1;
102int debug_parent = 0;
103int honeypot = 0;
104
105static int signal_tramp(void *arg)
106{
107 int (*proc)(void *);
108
109 if(honeypot && munmap((void *) (host_task_size - 0x10000000),
110 0x10000000))
111 panic("Unmapping stack failed");
112 if(ptrace(PTRACE_TRACEME, 0, 0, 0) < 0)
113 panic("ptrace PTRACE_TRACEME failed");
114 os_stop_process(os_getpid());
115 change_sig(SIGWINCH, 0);
116 signal(SIGUSR1, SIG_IGN);
117 change_sig(SIGCHLD, 0);
118 signal(SIGSEGV, (__sighandler_t) sig_handler);
119 set_cmdline("(idle thread)");
120 set_init_pid(os_getpid());
121 init_irq_signals(0);
122 proc = arg;
123 return((*proc)(NULL));
124}
125
126static void sleeping_process_signal(int pid, int sig)
127{
128 switch(sig){
129 /* These two result from UML being ^Z-ed and bg-ed. PTRACE_CONT is
130 * right because the process must be in the kernel already.
131 */
132 case SIGCONT:
133 case SIGTSTP:
134 if(ptrace(PTRACE_CONT, pid, 0, sig) < 0)
135 tracer_panic("sleeping_process_signal : Failed to "
136 "continue pid %d, signal = %d, "
137 "errno = %d\n", pid, sig, errno);
138 break;
139
140 /* This happens when the debugger (e.g. strace) is doing system call
141 * tracing on the kernel. During a context switch, the current task
142 * will be set to the incoming process and the outgoing process will
143 * hop into write and then read. Since it's not the current process
144 * any more, the trace of those will land here. So, we need to just
145 * PTRACE_SYSCALL it.
146 */
147 case (SIGTRAP + 0x80):
148 if(ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0)
149 tracer_panic("sleeping_process_signal : Failed to "
150 "PTRACE_SYSCALL pid %d, errno = %d\n",
151 pid, errno);
152 break;
153 case SIGSTOP:
154 break;
155 default:
156 tracer_panic("sleeping process %d got unexpected "
157 "signal : %d\n", pid, sig);
158 break;
159 }
160}
161
162/* Accessed only by the tracing thread */
163int debugger_pid = -1;
164int debugger_parent = -1;
165int debugger_fd = -1;
166int gdb_pid = -1;
167
168struct {
169 int pid;
170 int signal;
171 unsigned long addr;
172 struct timeval time;
173} signal_record[1024][32];
174
175int signal_index[32];
176int nsignals = 0;
177int debug_trace = 0;
178
179extern void signal_usr1(int sig);
180
181int tracing_pid = -1;
182
183int tracer(int (*init_proc)(void *), void *sp)
184{
185 void *task = NULL;
186 int status, pid = 0, sig = 0, cont_type, tracing = 0, op = 0;
187 int proc_id = 0, n, err, old_tracing = 0, strace = 0;
188 int local_using_sysemu = 0;
189
190 signal(SIGPIPE, SIG_IGN);
191 setup_tracer_winch();
192 tracing_pid = os_getpid();
193 printf("tracing thread pid = %d\n", tracing_pid);
194
195 pid = clone(signal_tramp, sp, CLONE_FILES | SIGCHLD, init_proc);
196 CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED));
197 if(n < 0){
198 printf("waitpid on idle thread failed, errno = %d\n", errno);
199 exit(1);
200 }
201 if (ptrace(PTRACE_OLDSETOPTIONS, pid, 0, (void *)PTRACE_O_TRACESYSGOOD) < 0) {
202 printf("Failed to PTRACE_SETOPTIONS for idle thread, errno = %d\n", errno);
203 exit(1);
204 }
205 if((ptrace(PTRACE_CONT, pid, 0, 0) < 0)){
206 printf("Failed to continue idle thread, errno = %d\n", errno);
207 exit(1);
208 }
209
210 signal(SIGSEGV, (sighandler_t) tracer_segv);
211 signal(SIGUSR1, signal_usr1);
212 if(debug_trace){
213 printf("Tracing thread pausing to be attached\n");
214 stop();
215 }
216 if(debug){
217 if(gdb_pid != -1)
218 debugger_pid = attach_debugger(pid, gdb_pid, 1);
219 else debugger_pid = init_ptrace_proxy(pid, 1, debug_stop);
220 if(debug_parent){
221 debugger_parent = os_process_parent(debugger_pid);
222 init_parent_proxy(debugger_parent);
223 err = attach(debugger_parent);
224 if(err){
225 printf("Failed to attach debugger parent %d, "
226 "errno = %d\n", debugger_parent, -err);
227 debugger_parent = -1;
228 }
229 else {
230 if(ptrace(PTRACE_SYSCALL, debugger_parent,
231 0, 0) < 0){
232 printf("Failed to continue debugger "
233 "parent, errno = %d\n", errno);
234 debugger_parent = -1;
235 }
236 }
237 }
238 }
239 set_cmdline("(tracing thread)");
240 while(1){
241 CATCH_EINTR(pid = waitpid(-1, &status, WUNTRACED));
242 if(pid <= 0){
243 if(errno != ECHILD){
244 printf("wait failed - errno = %d\n", errno);
245 }
246 continue;
247 }
248 if(pid == debugger_pid){
249 int cont = 0;
250
251 if(WIFEXITED(status) || WIFSIGNALED(status))
252 debugger_pid = -1;
253 /* XXX Figure out how to deal with gdb and SMP */
254 else cont = debugger_signal(status, cpu_tasks[0].pid);
255 if(cont == PTRACE_SYSCALL) strace = 1;
256 continue;
257 }
258 else if(pid == debugger_parent){
259 debugger_parent_signal(status, pid);
260 continue;
261 }
262 nsignals++;
263 if(WIFEXITED(status)) ;
264#ifdef notdef
265 {
266 printf("Child %d exited with status %d\n", pid,
267 WEXITSTATUS(status));
268 }
269#endif
270 else if(WIFSIGNALED(status)){
271 sig = WTERMSIG(status);
272 if(sig != 9){
273 printf("Child %d exited with signal %d\n", pid,
274 sig);
275 }
276 }
277 else if(WIFSTOPPED(status)){
278 proc_id = pid_to_processor_id(pid);
279 sig = WSTOPSIG(status);
280 if(proc_id == -1){
281 sleeping_process_signal(pid, sig);
282 continue;
283 }
284
285 task = cpu_tasks[proc_id].task;
286 tracing = is_tracing(task);
287 old_tracing = tracing;
288
289 /* Assume: no syscall, when coming from user */
290 if ( tracing )
291 do_sigtrap(task);
292
293 switch(sig){
294 case SIGUSR1:
295 sig = 0;
296 op = do_proc_op(task, proc_id);
297 switch(op){
298 /*
299 * This is called when entering user mode; after
300 * this, we start intercepting syscalls.
301 *
302 * In fact, a process is started in kernel mode,
303 * so with is_tracing() == 0 (and that is reset
304 * when executing syscalls, since UML kernel has
305 * the right to do syscalls);
306 */
307 case OP_TRACE_ON:
308 arch_leave_kernel(task, pid);
309 tracing = 1;
310 break;
311 case OP_REBOOT:
312 case OP_HALT:
313 unmap_physmem();
314 kmalloc_ok = 0;
315 os_kill_ptraced_process(pid, 0);
316 /* Now let's reap remaining zombies */
317 errno = 0;
318 do {
319 waitpid(-1, &status,
320 WUNTRACED);
321 } while (errno != ECHILD);
322 return(op == OP_REBOOT);
323 case OP_NONE:
324 printf("Detaching pid %d\n", pid);
325 detach(pid, SIGSTOP);
326 continue;
327 default:
328 break;
329 }
330 /* OP_EXEC switches host processes on us,
331 * we want to continue the new one.
332 */
333 pid = cpu_tasks[proc_id].pid;
334 break;
335 case (SIGTRAP + 0x80):
336 if(!tracing && (debugger_pid != -1)){
337 child_signal(pid, status & 0x7fff);
338 continue;
339 }
340 tracing = 0;
341 /* local_using_sysemu has been already set
342 * below, since if we are here, is_tracing() on
343 * the traced task was 1, i.e. the process had
344 * already run through one iteration of the
345 * loop which executed a OP_TRACE_ON request.*/
346 do_syscall(task, pid, local_using_sysemu);
347 sig = SIGUSR2;
348 break;
349 case SIGTRAP:
350 if(!tracing && (debugger_pid != -1)){
351 child_signal(pid, status);
352 continue;
353 }
354 tracing = 0;
355 break;
356 case SIGPROF:
357 if(tracing) sig = 0;
358 break;
359 case SIGCHLD:
360 case SIGHUP:
361 sig = 0;
362 break;
363 case SIGSEGV:
364 case SIGIO:
365 case SIGALRM:
366 case SIGVTALRM:
367 case SIGFPE:
368 case SIGBUS:
369 case SIGILL:
370 case SIGWINCH:
371
372 default:
373 tracing = 0;
374 break;
375 }
376 set_tracing(task, tracing);
377
378 if(!tracing && old_tracing)
379 arch_enter_kernel(task, pid);
380
381 if(!tracing && (debugger_pid != -1) && (sig != 0) &&
382 (sig != SIGALRM) && (sig != SIGVTALRM) &&
383 (sig != SIGSEGV) && (sig != SIGTRAP) &&
384 (sig != SIGUSR2) && (sig != SIGIO) &&
385 (sig != SIGFPE)){
386 child_signal(pid, status);
387 continue;
388 }
389
390 local_using_sysemu = get_using_sysemu();
391
392 if(tracing)
393 cont_type = SELECT_PTRACE_OPERATION(local_using_sysemu,
394 singlestepping(task));
395 else if((debugger_pid != -1) && strace)
396 cont_type = PTRACE_SYSCALL;
397 else
398 cont_type = PTRACE_CONT;
399
400 if(ptrace(cont_type, pid, 0, sig) != 0){
401 tracer_panic("ptrace failed to continue "
402 "process - errno = %d\n",
403 errno);
404 }
405 }
406 }
407 return(0);
408}
409
410static int __init uml_debug_setup(char *line, int *add)
411{
412 char *next;
413
414 debug = 1;
415 *add = 0;
416 if(*line != '=') return(0);
417 line++;
418
419 while(line != NULL){
420 next = strchr(line, ',');
421 if(next) *next++ = '\0';
422
423 if(!strcmp(line, "go")) debug_stop = 0;
424 else if(!strcmp(line, "parent")) debug_parent = 1;
425 else printf("Unknown debug option : '%s'\n", line);
426
427 line = next;
428 }
429 return(0);
430}
431
432__uml_setup("debug", uml_debug_setup,
433"debug\n"
434" Starts up the kernel under the control of gdb. See the \n"
435" kernel debugging tutorial and the debugging session pages\n"
436" at http://user-mode-linux.sourceforge.net/ for more information.\n\n"
437);
438
439static int __init uml_debugtrace_setup(char *line, int *add)
440{
441 debug_trace = 1;
442 return 0;
443}
444__uml_setup("debugtrace", uml_debugtrace_setup,
445"debugtrace\n"
446" Causes the tracing thread to pause until it is attached by a\n"
447" debugger and continued. This is mostly for debugging crashes\n"
448" early during boot, and should be pretty much obsoleted by\n"
449" the debug switch.\n\n"
450);
451
452/*
453 * Overrides for Emacs so that we follow Linus's tabbing style.
454 * Emacs will notice this stuff at the end of the file and automatically
455 * adjust the settings for this buffer only. This must remain at the end
456 * of the file.
457 * ---------------------------------------------------------------------------
458 * Local variables:
459 * c-file-style: "linux"
460 * End:
461 */