From: Jeff Dike This patch makes some debug code in the system call path configurable. Signed-off-by: Jeff Dike Signed-off-by: Andrew Morton --- 25-akpm/arch/um/Kconfig.debug | 10 ++++++ 25-akpm/arch/um/defconfig | 10 ++++-- 25-akpm/arch/um/kernel/Makefile | 1 25-akpm/arch/um/kernel/skas/syscall_user.c | 9 +++++ 25-akpm/arch/um/kernel/syscall_kern.c | 16 +++++++++ 25-akpm/arch/um/kernel/syscall_user.c | 48 +++++++++++++++++++++++++++++ 25-akpm/arch/um/kernel/tt/syscall_kern.c | 2 + 25-akpm/arch/um/kernel/tt/syscall_user.c | 9 +++++ 25-akpm/arch/um/kernel/tt/tracer.c | 23 ++++++++++++- 9 files changed, 124 insertions(+), 4 deletions(-) diff -puN arch/um/defconfig~uml-make-syscall-debugging-code-configurable arch/um/defconfig --- 25/arch/um/defconfig~uml-make-syscall-debugging-code-configurable 2005-03-07 22:16:18.000000000 -0800 +++ 25-akpm/arch/um/defconfig 2005-03-07 22:16:18.000000000 -0800 @@ -52,7 +52,6 @@ CONFIG_BSD_PROCESS_ACCT=y # CONFIG_BSD_PROCESS_ACCT_V3 is not set CONFIG_SYSCTL=y # CONFIG_AUDIT is not set -CONFIG_LOG_BUF_SHIFT=14 # CONFIG_HOTPLUG is not set CONFIG_KOBJECT_UEVENT=y CONFIG_IKCONFIG=y @@ -61,9 +60,10 @@ CONFIG_IKCONFIG_PROC=y CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_ALL is not set CONFIG_KALLSYMS_EXTRA_PASS=y +CONFIG_BASE_FULL=y +CONFIG_BASE_SMALL=0 CONFIG_FUTEX=y CONFIG_EPOLL=y -# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set CONFIG_SHMEM=y CONFIG_CC_ALIGN_FUNCTIONS=0 CONFIG_CC_ALIGN_LABELS=0 @@ -241,6 +241,11 @@ CONFIG_TUN=m # CONFIG_NET_PCMCIA is not set # +# PCMCIA network device support +# +# CONFIG_NET_PCMCIA is not set + +# # Wan interfaces # # CONFIG_WAN is not set @@ -437,3 +442,4 @@ CONFIG_FRAME_POINTER=y CONFIG_PT_PROXY=y # CONFIG_GPROF is not set # CONFIG_GCOV is not set +# CONFIG_SYSCALL_DEBUG is not set diff -puN arch/um/Kconfig.debug~uml-make-syscall-debugging-code-configurable arch/um/Kconfig.debug --- 25/arch/um/Kconfig.debug~uml-make-syscall-debugging-code-configurable 2005-03-07 22:16:18.000000000 -0800 +++ 25-akpm/arch/um/Kconfig.debug 2005-03-07 22:16:18.000000000 -0800 @@ -40,4 +40,14 @@ config GCOV If you're involved in UML kernel development and want to use gcov, say Y. If you're unsure, say N. +config SYSCALL_DEBUG + bool "Enable system call debugging" + default N + depends on DEBUG_INFO + help + This adds some system debugging to UML, including keeping a ring buffer + with recent system calls and some global and per-task statistics. + + If unsure, say N + endmenu diff -puN arch/um/kernel/Makefile~uml-make-syscall-debugging-code-configurable arch/um/kernel/Makefile --- 25/arch/um/kernel/Makefile~uml-make-syscall-debugging-code-configurable 2005-03-07 22:16:18.000000000 -0800 +++ 25-akpm/arch/um/kernel/Makefile 2005-03-07 22:16:18.000000000 -0800 @@ -18,6 +18,7 @@ obj-$(CONFIG_BLK_DEV_INITRD) += initrd_k obj-$(CONFIG_GPROF) += gprof_syms.o obj-$(CONFIG_GCOV) += gmon_syms.o obj-$(CONFIG_TTY_LOG) += tty_log.o +obj-$(CONFIG_SYSCALL_DEBUG) += syscall_user.o obj-$(CONFIG_MODE_TT) += tt/ obj-$(CONFIG_MODE_SKAS) += skas/ diff -puN arch/um/kernel/skas/syscall_user.c~uml-make-syscall-debugging-code-configurable arch/um/kernel/skas/syscall_user.c --- 25/arch/um/kernel/skas/syscall_user.c~uml-make-syscall-debugging-code-configurable 2005-03-07 22:16:18.000000000 -0800 +++ 25-akpm/arch/um/kernel/skas/syscall_user.c 2005-03-07 22:16:18.000000000 -0800 @@ -6,6 +6,7 @@ #include #include #include "kern_util.h" +#include "uml-config.h" #include "syscall_user.h" #include "sysdep/ptrace.h" #include "sysdep/sigcontext.h" @@ -14,6 +15,11 @@ void handle_syscall(union uml_pt_regs *regs) { long result; +#if UML_CONFIG_SYSCALL_DEBUG + int index; + + index = record_syscall_start(UPT_SYSCALL_NR(regs)); +#endif syscall_trace(regs, 0); result = execute_syscall_skas(regs); @@ -21,6 +27,9 @@ void handle_syscall(union uml_pt_regs *r REGS_SET_SYSCALL_RETURN(regs->skas.regs, result); syscall_trace(regs, 1); +#if UML_CONFIG_SYSCALL_DEBUG + record_syscall_end(index, result); +#endif } /* diff -puN arch/um/kernel/syscall_kern.c~uml-make-syscall-debugging-code-configurable arch/um/kernel/syscall_kern.c --- 25/arch/um/kernel/syscall_kern.c~uml-make-syscall-debugging-code-configurable 2005-03-07 22:16:18.000000000 -0800 +++ 25-akpm/arch/um/kernel/syscall_kern.c 2005-03-07 22:16:18.000000000 -0800 @@ -154,6 +154,22 @@ long sys_olduname(struct oldold_utsname return error; } +DEFINE_SPINLOCK(syscall_lock); + +static int syscall_index = 0; + +int next_syscall_index(int limit) +{ + int ret; + + spin_lock(&syscall_lock); + ret = syscall_index; + if(++syscall_index == limit) + syscall_index = 0; + spin_unlock(&syscall_lock); + return(ret); +} + /* * Overrides for Emacs so that we follow Linus's tabbing style. * Emacs will notice this stuff at the end of the file and automatically diff -puN arch/um/kernel/syscall_user.c~uml-make-syscall-debugging-code-configurable arch/um/kernel/syscall_user.c --- 25/arch/um/kernel/syscall_user.c~uml-make-syscall-debugging-code-configurable 2005-03-07 22:16:18.000000000 -0800 +++ 25-akpm/arch/um/kernel/syscall_user.c 2005-03-07 22:16:18.000000000 -0800 @@ -46,3 +46,51 @@ void record_syscall_end(int index, long * c-file-style: "linux" * End: */ +/* + * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) + * Licensed under the GPL + */ + +#include +#include +#include "kern_util.h" +#include "syscall_user.h" + +struct { + int syscall; + int pid; + long result; + struct timeval start; + struct timeval end; +} syscall_record[1024]; + +int record_syscall_start(int syscall) +{ + int max, index; + + max = sizeof(syscall_record)/sizeof(syscall_record[0]); + index = next_syscall_index(max); + + syscall_record[index].syscall = syscall; + syscall_record[index].pid = current_pid(); + syscall_record[index].result = 0xdeadbeef; + gettimeofday(&syscall_record[index].start, NULL); + return(index); +} + +void record_syscall_end(int index, long result) +{ + syscall_record[index].result = result; + gettimeofday(&syscall_record[index].end, NULL); +} + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff -puN arch/um/kernel/tt/syscall_kern.c~uml-make-syscall-debugging-code-configurable arch/um/kernel/tt/syscall_kern.c --- 25/arch/um/kernel/tt/syscall_kern.c~uml-make-syscall-debugging-code-configurable 2005-03-07 22:16:18.000000000 -0800 +++ 25-akpm/arch/um/kernel/tt/syscall_kern.c 2005-03-07 22:16:18.000000000 -0800 @@ -22,8 +22,10 @@ long execute_syscall_tt(void *r) long res; int syscall; +#ifdef CONFIG_SYSCALL_DEBUG current->thread.nsyscalls++; nsyscalls++; +#endif syscall = UPT_SYSCALL_NR(®s->regs); if((syscall >= NR_syscalls) || (syscall < 0)) diff -puN arch/um/kernel/tt/syscall_user.c~uml-make-syscall-debugging-code-configurable arch/um/kernel/tt/syscall_user.c --- 25/arch/um/kernel/tt/syscall_user.c~uml-make-syscall-debugging-code-configurable 2005-03-07 22:16:18.000000000 -0800 +++ 25-akpm/arch/um/kernel/tt/syscall_user.c 2005-03-07 22:16:18.000000000 -0800 @@ -23,11 +23,17 @@ void syscall_handler_tt(int sig, union u void *sc; long result; int syscall; +#ifdef UML_CONFIG_DEBUG_SYSCALL + int index; +#endif syscall = UPT_SYSCALL_NR(regs); sc = UPT_SC(regs); SC_START_SYSCALL(sc); +#ifdef UML_CONFIG_DEBUG_SYSCALL + index = record_syscall_start(syscall); +#endif syscall_trace(regs, 0); result = execute_syscall_tt(regs); @@ -39,6 +45,9 @@ void syscall_handler_tt(int sig, union u SC_SET_SYSCALL_RETURN(sc, result); syscall_trace(regs, 1); +#ifdef UML_CONFIG_DEBUG_SYSCALL + record_syscall_end(index, result); +#endif } void do_sigtrap(void *task) diff -puN arch/um/kernel/tt/tracer.c~uml-make-syscall-debugging-code-configurable arch/um/kernel/tt/tracer.c --- 25/arch/um/kernel/tt/tracer.c~uml-make-syscall-debugging-code-configurable 2005-03-07 22:16:18.000000000 -0800 +++ 25-akpm/arch/um/kernel/tt/tracer.c 2005-03-07 22:16:18.000000000 -0800 @@ -13,7 +13,6 @@ #include #include #include -#include #include #include #include "user.h" @@ -187,7 +186,10 @@ int tracer(int (*init_proc)(void *), voi int status, pid = 0, sig = 0, cont_type, tracing = 0, op = 0; int proc_id = 0, n, err, old_tracing = 0, strace = 0; int local_using_sysemu = 0; - +#ifdef UML_CONFIG_SYSCALL_DEBUG + unsigned long eip = 0; + int last_index; +#endif signal(SIGPIPE, SIG_IGN); setup_tracer_winch(); tracing_pid = os_getpid(); @@ -278,6 +280,23 @@ int tracer(int (*init_proc)(void *), voi else if(WIFSTOPPED(status)){ proc_id = pid_to_processor_id(pid); sig = WSTOPSIG(status); +#ifdef UML_CONFIG_SYSCALL_DEBUG + if(signal_index[proc_id] == 1024){ + signal_index[proc_id] = 0; + last_index = 1023; + } + else last_index = signal_index[proc_id] - 1; + if(((sig == SIGPROF) || (sig == SIGVTALRM) || + (sig == SIGALRM)) && + (signal_record[proc_id][last_index].signal == sig)&& + (signal_record[proc_id][last_index].pid == pid)) + signal_index[proc_id] = last_index; + signal_record[proc_id][signal_index[proc_id]].pid = pid; + gettimeofday(&signal_record[proc_id][signal_index[proc_id]].time, NULL); + eip = ptrace(PTRACE_PEEKUSER, pid, PT_IP_OFFSET, 0); + signal_record[proc_id][signal_index[proc_id]].addr = eip; + signal_record[proc_id][signal_index[proc_id]++].signal = sig; +#endif if(proc_id == -1){ sleeping_process_signal(pid, sig); continue; _