From: Jeff Dike <jdike@addtoit.com>

This patch makes some debug code in the system call path configurable.

Signed-off-by: Jeff Dike <jdike@addtoit.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 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 <stdlib.h>
 #include <signal.h>
 #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 <stdlib.h>
+#include <sys/time.h>
+#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(&regs->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 <string.h>
 #include <sys/mman.h>
 #include <sys/ptrace.h>
-#include <linux/ptrace.h>
 #include <sys/time.h>
 #include <sys/wait.h>
 #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;
_