Skip to contentSkip to conversation

2.4.21-pre5 kksymoops for i386/ia64

PATCH New Keith Owens 1 participant 1 message Mar 17, 2003 Documentation

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 2.4.21-pre5 kksymoops for i386/ia64

Automatic decoding of oops on 2.5 has been very useful, so this patch adds kksymoops support to 2.4.21-pre5. Currently only for i386 and ia64, other architectures are easy to add.

Index: 21-pre5.1/kernel/module.c

kernel/module.c Mon, 17 Mar 2003 17:22:39 +1100 kaos (linux-2.4/j/45_module.c 1.1.2.1.3.1.3.1.1.1.2.2 644) renamed from kernel/module.c Wed, 11 Dec 2002 11:38:55 +1100 kaos (linux-2.4/j/45_module.c 1.1.2.1.3.1.3.1.1.1.2.2 644) +102 -0
@@ -3,6 +3,7 @@
 #include <linux/module.h>
 #include <asm/module.h>
 #include <asm/uaccess.h>
+#include <linux/kallsyms.h>
 #include <linux/vmalloc.h>
 #include <linux/smp_lock.h>
 #include <asm/pgalloc.h>
@@ -1235,6 +1236,30 @@ struct seq_operations ksyms_op = {
 	show:	s_show
 };
 
+#define MODLIST_SIZE 4096
+
+/*
+ * this function isn't smp safe but that's not really a problem; it's
+ * called from oops context only and any locking could actually prevent
+ * the oops from going out; the line that is generated is informational
+ * only and should NEVER prevent the real oops from going out. 
+ */
+void print_modules(void)
+{
+	static char modlist[MODLIST_SIZE];
+	struct module *this_mod;
+	int pos = 0;
+
+	this_mod = module_list;
+	while (this_mod) {
+		if (this_mod->name)
+			pos += snprintf(modlist+pos, MODLIST_SIZE-pos-1, 
+					"%s ", this_mod->name);
+		this_mod = this_mod->next;
+	}
+	printk("%s\n",modlist);
+}
+
 #else		/* CONFIG_MODULES */
 
 /* Dummy syscalls for people who don't want modules */
@@ -1280,4 +1305,81 @@ int try_inc_mod_count(struct module *mod
 	return 1;
 }
 
+void print_modules(void)
+{
+}
+
 #endif	/* CONFIG_MODULES */
+
+
+#if defined(CONFIG_MODULES) || defined(CONFIG_KALLSYMS)
+
+#define MAX_SYMBOL_SIZE 512
+
+static void
+address_to_exported_symbol(unsigned long address, const char **mod_name, 
+			   const char **sym_name, unsigned long *sym_start,
+			   unsigned long *sym_end)
+{
+	struct module *this_mod;
+	int i;
+
+	for (this_mod = module_list; this_mod; this_mod = this_mod->next) {
+		/* walk the symbol list of this module. Only symbols
+		   who's address is smaller than the searched for address
+		   are relevant; and only if it's better than the best so far */
+		for (i = 0; i < this_mod->nsyms; i++)
+			if ((this_mod->syms[i].value <= address) &&
+			    (*sym_start < this_mod->syms[i].value)) {
+				*sym_start = this_mod->syms[i].value;
+				*sym_name  = this_mod->syms[i].name;
+				*mod_name  = this_mod->name;
+				if (i + 1 < this_mod->nsyms)
+					*sym_end = this_mod->syms[i+1].value;
+				else
+					*sym_end = (unsigned long) this_mod + this_mod->size;
+			}
+	}
+}
+
+void
+print_symbol(const char *fmt, unsigned long address)
+{
+	/* static to not take up stackspace; if we race here too bad */
+	static char buffer[MAX_SYMBOL_SIZE];
+
+	const char *mod_name = NULL, *sec_name = NULL, *sym_name = NULL;
+	unsigned long mod_start, mod_end, sec_start, sec_end,
+		sym_start, sym_end;
+	char *tag = "";
+	
+	memset(buffer, 0, MAX_SYMBOL_SIZE);
+
+	sym_start = 0;
+	if (!kallsyms_address_to_symbol(address, &mod_name, &mod_start, &mod_end, &sec_name, &sec_start, &sec_end, &sym_name, &sym_start, &sym_end)) {
+		tag = "E ";
+		address_to_exported_symbol(address, &mod_name, &sym_name, &sym_start, &sym_end);
+	}
+
+	if (sym_start) {
+		if (*mod_name)
+		    snprintf(buffer, MAX_SYMBOL_SIZE - 1, "%s%s+%#x/%#x [%s]",
+			 tag, sym_name,
+			 (unsigned int)(address - sym_start),
+			 (unsigned int)(sym_end - sym_start),
+			 mod_name);
+		else
+		    snprintf(buffer, MAX_SYMBOL_SIZE - 1, "%s%s+%#x/%#x",
+			 tag, sym_name,
+			 (unsigned int)(address - sym_start),
+			 (unsigned int)(sym_end - sym_start));
+		printk(fmt, buffer);
+	}
+#if 0
+ else {
+		printk(fmt, "[unresolved]");
+	}
+#endif
+}
+
+#endif

Index: 21-pre5.1/kernel/ksyms.c

kernel/ksyms.c Mon, 17 Mar 2003 17:42:52 +1100 kaos (linux-2.4/j/46_ksyms.c 1.1.2.2.1.1.2.1.1.8.2.1.2.1.1.4.1.39 644) renamed from kernel/ksyms.c Thu, 27 Feb 2003 19:36:53 +1100 kaos (linux-2.4/j/46_ksyms.c 1.1.2.2.1.1.2.1.1.8.2.1.2.1.1.4.1.39 644) +12 -0
@@ -56,6 +56,9 @@
 #ifdef CONFIG_KMOD
 #include <linux/kmod.h>
 #endif
+#ifdef CONFIG_KALLSYMS
+#include <linux/kallsyms.h>
+#endif
 
 extern void set_device_ro(kdev_t dev,int flag);
 
@@ -81,6 +84,15 @@ EXPORT_SYMBOL(inter_module_get_request);
 EXPORT_SYMBOL(inter_module_put);
 EXPORT_SYMBOL(try_inc_mod_count);
 
+#ifdef CONFIG_KALLSYMS
+extern const char __start___kallsyms[];
+extern const char __stop___kallsyms[];
+EXPORT_SYMBOL(__start___kallsyms);
+EXPORT_SYMBOL(__stop___kallsyms);
+EXPORT_SYMBOL(kallsyms_symbol_to_address);
+EXPORT_SYMBOL(kallsyms_address_to_symbol);
+#endif
+
 /* process memory management */
 EXPORT_SYMBOL(do_mmap_pgoff);
 EXPORT_SYMBOL(do_munmap);

Index: 21-pre5.1/kernel/Makefile

kernel/Makefile Mon, 17 Mar 2003 18:11:54 +1100 kaos (linux-2.4/k/3_Makefile 1.1.10.2 644) renamed from kernel/Makefile Tue, 18 Sep 2001 13:43:44 +1000 kaos (linux-2.4/k/3_Makefile 1.1.10.2 644) +1 -0
@@ -19,6 +19,7 @@ obj-y     = sched.o dma.o fork.o exec_do
 obj-$(CONFIG_UID16) += uid16.o
 obj-$(CONFIG_MODULES) += ksyms.o
 obj-$(CONFIG_PM) += pm.o
+obj-$(CONFIG_KALLSYMS) += kallsyms.o
 
 ifneq ($(CONFIG_IA64),y)
 # According to Alan Modra <[email protected]>, the -fno-omit-frame-pointer is

Index: 21-pre5.1/include/linux/module.h

include/linux/module.h Mon, 17 Mar 2003 17:55:02 +1100 kaos (linux-2.4/c/b/46_module.h 1.1.1.1.2.6.1.1.1.2.1.1 644) renamed from include/linux/module.h Thu, 01 Aug 2002 11:23:16 +1000 kaos (linux-2.4/c/b/46_module.h 1.1.1.1.2.6.1.1.1.2.1.1 644) +25 -0
@@ -412,4 +412,29 @@ __attribute__((section("__ksymtab"))) =	
 #define SET_MODULE_OWNER(some_struct) do { } while (0)
 #endif
 
+extern void print_modules(void);
+
+#if defined(CONFIG_MODULES) || defined(CONFIG_KALLSYMS)
+
+extern struct module *module_list;
+
+/*
+ * print_symbols takes a format string containing one %s.
+ * If support for resolving symbols is compiled in, the %s will
+ * be replaced by the closest symbol to the address and the entire
+ * string is printk()ed. Otherwise, nothing is printed.
+ */
+extern void print_symbol(const char *fmt, unsigned long address);
+
+#else
+
+#include <linux/errno.h>
+static inline int
+print_symbol(const char *fmt, unsigned long address)
+{
+	return -ESRCH;
+}
+
+#endif
+
 #endif /* _LINUX_MODULE_H */

Index: 21-pre5.1/arch/ia64/kernel/process.c

arch/ia64/kernel/process.c Mon, 17 Mar 2003 17:19:58 +1100 kaos (linux-2.4/r/c/50_process.c 1.1.3.1.3.1.2.2.1.2.1.2 644) renamed from arch/ia64/kernel/process.c Thu, 27 Feb 2003 19:36:53 +1100 kaos (linux-2.4/r/c/50_process.c 1.1.3.1.3.1.2.2.1.2.1.2 644) +15 -2
@@ -12,6 +12,7 @@
 #include <linux/errno.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
+#include <linux/module.h>
 #include <linux/personality.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
@@ -37,8 +38,9 @@ static void
 do_show_stack (struct unw_frame_info *info, void *arg)
 {
 	unsigned long ip, sp, bsp;
+	char buf[80];			/* don't make it so big that it overflows the stack! */
 
-	printk("\nCall Trace: ");
+	printk("\nCall Trace:\n");
 	do {
 		unw_get_ip(info, &ip);
 		if (ip = 0)
@@ -46,7 +48,9 @@ do_show_stack (struct unw_frame_info *in
 
 		unw_get_sp(info, &sp);
 		unw_get_bsp(info, &bsp);
-		printk("[<%016lx>] sp=0x%016lx bsp=0x%016lx\n", ip, sp, bsp);
+		snprintf(buf, sizeof(buf), " [<%016lx>] %%s sp=0x%016lx bsp=0x%016lx\n",
+			 ip, sp, bsp);
+		print_symbol(buf, ip);
 	} while (unw_unwind(info) >= 0);
 }
 
@@ -73,13 +77,22 @@ show_stack (struct task_struct *task)
 }
 
 void
+dump_stack (void)
+{
+	show_stack(NULL);
+}
+
+void
 show_regs (struct pt_regs *regs)
 {
 	unsigned long ip = regs->cr_iip + ia64_psr(regs)->ri;
 
 	printk("\nPid: %d, comm: %20s\n", current->pid, current->comm);
+	printk("Registers: cpu %d, sapicid 0x%04x, time %ld\n",
+	       smp_processor_id(),  hard_smp_processor_id(), jiffies);
 	printk("psr : %016lx ifs : %016lx ip  : [<%016lx>]    %s\n",
 	       regs->cr_ipsr, regs->cr_ifs, ip, print_tainted());
+	print_symbol("ip is at %s\n", ip);
 	printk("unat: %016lx pfs : %016lx rsc : %016lx\n",
 	       regs->ar_unat, regs->ar_pfs, regs->ar_rsc);
 	printk("rnat: %016lx bsps: %016lx pr  : %016lx\n",

Index: 21-pre5.1/arch/ia64/config.in

arch/ia64/config.in Mon, 17 Mar 2003 17:32:06 +1100 kaos (linux-2.4/s/c/38_config.in 1.1.2.1.2.2.3.1.1.2.1.5 644) renamed from arch/ia64/config.in Sun, 12 Jan 2003 11:14:47 +1100 kaos (linux-2.4/s/c/38_config.in 1.1.2.1.2.2.3.1.1.2.1.5 644) +1 -0
@@ -284,6 +284,7 @@ if [ "$CONFIG_DEBUG_KERNEL" != "n" ]; th
    bool '  Spinlock debugging' CONFIG_DEBUG_SPINLOCK
    bool '  Turn on compare-and-exchange bug checking (slow!)' CONFIG_IA64_DEBUG_CMPXCHG
    bool '  Turn on irq debug checks (slow!)' CONFIG_IA64_DEBUG_IRQ
+   bool '  Load all symbols for debugging/kksymoops' CONFIG_KALLSYMS
 fi
 
 endmenu

Index: 21-pre5.1/arch/i386/vmlinux.lds

arch/i386/vmlinux.lds Mon, 17 Mar 2003 17:31:24 +1100 kaos (linux-2.4/R/c/35_vmlinux.ld 1.1.4.1.2.1 644) renamed from arch/i386/vmlinux.lds Fri, 11 Jan 2002 15:36:30 +1100 kaos (linux-2.4/R/c/35_vmlinux.ld 1.1.4.1.2.1 644) +4 -0
@@ -28,6 +28,10 @@ SECTIONS
   __ksymtab : { *(__ksymtab) }
   __stop___ksymtab = .;
 
+  __start___kallsyms = .;	/* All kernel symbols */
+  __kallsyms : { *(__kallsyms) }
+  __stop___kallsyms = .;
+
   .data : {			/* Data */
 	*(.data)
 	CONSTRUCTORS

Index: 21-pre5.1/arch/i386/kernel/traps.c

arch/i386/kernel/traps.c Mon, 17 Mar 2003 17:19:00 +1100 kaos (linux-2.4/S/c/22_traps.c 1.1.2.1.1.2.1.1.1.12 644) renamed from arch/i386/kernel/traps.c Sun, 18 Aug 2002 23:16:19 +1000 kaos (linux-2.4/S/c/22_traps.c 1.1.2.1.1.2.1.1.1.12 644) +10 -6
@@ -139,15 +139,16 @@ void show_trace(unsigned long * stack)
 	if (!stack)
 		stack = (unsigned long*)&stack;
 
-	printk("Call Trace:   ");
+	printk("Call Trace:");
+#if CONFIG_KALLSYMS
+	printk("\n");
+#endif
 	i = 1;
 	while (((long) stack & (THREAD_SIZE-1)) != 0) {
 		addr = *stack++;
 		if (kernel_text_address(addr)) {
-			if (i && ((i % 6) = 0))
-				printk("\n ");
-			printk(" [<%08lx>]", addr);
-			i++;
+			printk(" [<%08lx>] ", addr);
+			print_symbol("%s\n", addr);
 		}
 	}
 	printk("\n");
@@ -208,8 +209,11 @@ void show_registers(struct pt_regs *regs
 		esp = regs->esp;
 		ss = regs->xss & 0xffff;
 	}
+	print_modules();
 	printk("CPU:    %d\nEIP:    %04x:[<%08lx>]    %s\nEFLAGS: %08lx\n",
 		smp_processor_id(), 0xffff & regs->xcs, regs->eip, print_tainted(), regs->eflags);
+
+	print_symbol("EIP is at %s\n", regs->eip);
 	printk("eax: %08lx   ebx: %08lx   ecx: %08lx   edx: %08lx\n",
 		regs->eax, regs->ebx, regs->ecx, regs->edx);
 	printk("esi: %08lx   edi: %08lx   ebp: %08lx   esp: %08lx\n",
@@ -227,7 +231,7 @@ void show_registers(struct pt_regs *regs
 		printk("\nStack: ");
 		show_stack((unsigned long*)esp);
 
-		printk("\nCode: ");
+		printk("Code: ");
 		if(regs->eip < PAGE_OFFSET)
 			goto bad;
 

Index: 21-pre5.1/arch/i386/config.in

arch/i386/config.in Mon, 17 Mar 2003 17:30:24 +1100 kaos (linux-2.4/T/c/36_config.in 1.1.2.1.2.32 644) renamed from arch/i386/config.in Wed, 29 Jan 2003 16:24:17 +1100 kaos (linux-2.4/T/c/36_config.in 1.1.2.1.2.32 644) +1 -0
@@ -471,6 +471,7 @@ if [ "$CONFIG_DEBUG_KERNEL" != "n" ]; th
    bool '  Magic SysRq key' CONFIG_MAGIC_SYSRQ
    bool '  Spinlock debugging' CONFIG_DEBUG_SPINLOCK
    bool '  Compile the kernel with frame pointers' CONFIG_FRAME_POINTER
+   bool '  Load all symbols for debugging/kksymoops' CONFIG_KALLSYMS
 fi
 
 endmenu

Index: 21-pre5.1/Makefile

Makefile Mon, 17 Mar 2003 17:37:53 +1100 kaos (linux-2.4/T/c/50_Makefile 1.1.2.15.1.2.2.25.2.2.1.17.1.4.1.29.1.40.1.51 644) renamed from Makefile Thu, 27 Feb 2003 19:36:53 +1100 kaos (linux-2.4/T/c/50_Makefile 1.1.2.15.1.2.2.25.2.2.1.17.1.4.1.29.1.40.1.51 644) +35 -9

63 lines not on this page · raw message

Index: 21-pre5.1/Documentation/Configure.help

Documentation/Configure.help Mon, 17 Mar 2003 17:34:52 +1100 kaos (linux-2.4/Z/c/10_Configure. 1.1.2.8.2.10.1.4.2.10.2.71 644) renamed from Documentation/Configure.help Thu, 27 Feb 2003 19:36:53 +1100 kaos (linux-2.4/Z/c/10_Configure. 1.1.2.8.2.10.1.4.2.10.2.71 644) +10 -0
@@ -20554,6 +20554,16 @@ CONFIG_MAGIC_SYSRQ
   keys are documented in <file:Documentation/sysrq.txt>. Don't say Y
   unless you really know what this hack does.
 
+Load all symbols for debugging/kksymoops
+CONFIG_KALLSYMS
+  Normally only exported symbols are available to modules. For
+  debugging you may want all symbols, not just the exported ones. If
+  you say Y here then extra data is added to the kernel and modules,
+  this data lists all the non-stack symbols in the kernel or module
+  and can be used by any debugger.  You need modutils >= 2.3.11 to use
+  this option. See "man kallsyms" for the data format, it adds 10-20%
+  to the size of the kernel and the loaded modules. If unsure, say N.
+
 ISDN support
 CONFIG_ISDN
   ISDN ("Integrated Services Digital Networks", called RNIS in France)

Index: 21-pre5.1/include/linux/kallsyms.h

include/linux/kallsyms.h Mon, 17 Mar 2003 17:55:02 +1100 kaos (linux-2.4/R/g/44_kallsyms.h 644) renamed from include/linux/kallsyms.h Mon, 17 Mar 2003 18:15:52 +1100 kaos () +169 -0

169 lines not on this page · raw message

Index: 21-pre5.1/kernel/kallsyms.c

kernel/kallsyms.c Mon, 17 Mar 2003 17:48:59 +1100 kaos (linux-2.4/R/g/45_kallsyms.c 644) renamed from kernel/kallsyms.c Mon, 17 Mar 2003 18:15:52 +1100 kaos () +418 -0

418 lines not on this page · raw message