From: Dan Kegel <dank@kegel.com>
To: linux-kernel@vger.kernel.org
Subject: Re: [RFC] Smarter stack traces using the frame pointer
Date: Thu, 06 Nov 2003 12:08:27 -0800 [thread overview]
Message-ID: <3FAAAA3B.1000707@kegel.com> (raw)
For what it's worth, on ppc I've made stack traces
slightly smarter, too. I think the ppc stack dump
code always used the frame
pointer, but it still output a bunch of garbage at the
end of the stack dump. As a byproduct of porting the
module tracking patch to ppc, I had to check each
address printed out by the stack dumper, and fairly
often they're not legal text addresses. I print a ? after
the questionable ones now. No big deal, but it is
*slightly* smarter. Here's the bit in question:
--- patch-backup/arch/ppc/kernel/process.c Mon Oct 13 17:32:04 2003
+++ arch/ppc/kernel/process.c Tue Oct 14 00:05:29 2003
@@ -514,7 +564,11 @@
break;
if (cnt++ % 7 == 0)
printk("\n");
- printk("%08lX ", i);
+ if (kernel_text_address(i)) { /* mostly just want to mark modules */
+ printk("%08lX ", i);
+ } else { /* FIXME: should we ignore fishy adrs like x86? */
+ printk("%08lX? ", i); /* Or append a '?' (ksymoops doesn't mind) */
+ }
if (cnt > 32) break;
if (__get_user(sp, (unsigned long **)sp))
break;
And here's the whole module tracking patch, including my port of it to ppc
(the paths have the first component removed, sorry):
# Purpose: add module info to oops log
# Source http://www.kernel.org/pub/linux/kernel/people/andrea/kernels/v2.4/2.4.23pre6aa3/90_module-oops-tracking-3
# See also http://marc.theaimsgroup.com/?l=linux-kernel&m=102772338115172&w=2
# ppc port added by dank@kegel.com Oct 2003
diff -urNp z/arch/i386/kernel/traps.c 2.4.19rc3aa2/arch/i386/kernel/traps.c
--- arch/i386/kernel/traps.c Sat Jul 27 03:42:39 2002
+++ arch/i386/kernel/traps.c Sat Jul 27 03:41:56 2002
@@ -113,6 +113,7 @@ static inline int kernel_text_address(un
* module area. Of course it'd be better to test only
* for the .text subset... */
if (mod_bound(addr, 0, mod)) {
+ module_oops_tracking_mark(mod);
retval = 1;
break;
}
@@ -208,6 +209,8 @@ void show_registers(struct pt_regs *regs
esp = regs->esp;
ss = regs->xss & 0xffff;
}
+ module_oops_tracking_init();
+ kernel_text_address(regs->eip);
printk("CPU: %d\nEIP: %04x:[<%08lx>] %s\nEFLAGS: %08lx\n",
smp_processor_id(), 0xffff & regs->xcs, regs->eip, print_tainted(), regs->eflags);
printk("eax: %08lx ebx: %08lx ecx: %08lx edx: %08lx\n",
@@ -226,8 +229,9 @@ void show_registers(struct pt_regs *regs
printk("\nStack: ");
show_stack((unsigned long*)esp);
+ module_oops_tracking_print();
- printk("\nCode: ");
+ printk("Code: ");
if(regs->eip < PAGE_OFFSET)
goto bad;
@@ -288,7 +292,8 @@ void die(const char * str, struct pt_reg
spin_lock_irq(&die_lock);
bust_spinlocks(1);
handle_BUG(regs);
- printk("%s: %04lx\n", str, err & 0xffff);
+ printk("%s: %04lx ", str, err & 0xffff);
+ printk(oops_id);
show_registers(regs);
bust_spinlocks(0);
spin_unlock_irq(&die_lock);
diff -urNp z/include/linux/kernel.h 2.4.19rc3aa2/include/linux/kernel.h
--- include/linux/kernel.h Sat Jul 27 03:42:39 2002
+++ include/linux/kernel.h Sat Jul 27 04:57:04 2002
@@ -109,6 +109,8 @@ extern const char *print_tainted(void);
extern void dump_stack(void);
+extern char *oops_id;
+
#if DEBUG
#define pr_debug(fmt,arg...) \
printk(KERN_DEBUG fmt,##arg)
diff -urNp z/include/linux/module.h 2.4.19rc3aa2/include/linux/module.h
--- include/linux/module.h Sat Jul 27 03:42:39 2002
+++ include/linux/module.h Sat Jul 27 04:57:40 2002
@@ -110,6 +110,7 @@ struct module_info
#define MOD_USED_ONCE 16
#define MOD_JUST_FREED 32
#define MOD_INITIALIZING 64
+#define MOD_OOPS_PRINT 128UL
/* Values for query_module's which. */
@@ -411,4 +412,14 @@ __attribute__((section("__ksymtab"))) =
#define SET_MODULE_OWNER(some_struct) do { } while (0)
#endif
+#ifdef CONFIG_MODULES
+extern void module_oops_tracking_init(void);
+extern void module_oops_tracking_mark(struct module *);
+extern void module_oops_tracking_print(void);
+#else
+#define module_oops_tracking_init() do { } while (0)
+#define module_oops_tracking_mark(x) do { } while (0)
+#define module_oops_tracking_print() do { } while (0)
+#endif
+
#endif /* _LINUX_MODULE_H */
diff -urNp z/init/version.c 2.4.19rc3aa2/init/version.c
--- init/version.c Sat Jul 27 03:42:39 2002
+++ init/version.c Sat Jul 27 05:03:14 2002
@@ -24,3 +24,5 @@ struct new_utsname system_utsname = {
const char *linux_banner =
"Linux version " UTS_RELEASE " (" LINUX_COMPILE_BY "@"
LINUX_COMPILE_HOST ") (" LINUX_COMPILER ") " UTS_VERSION "\n";
+
+const char *oops_id = UTS_RELEASE " " UTS_VERSION "\n";
diff -urNp z/kernel/module.c 2.4.19rc3aa2/kernel/module.c
--- kernel/module.c Sat Jul 27 03:42:39 2002
+++ kernel/module.c Sat Jul 27 02:38:24 2002
@@ -1242,6 +1242,50 @@ struct seq_operations ksyms_op = {
show: s_show
};
+/*
+ * The module tracking logic assumes the module list doesn't
+ * change under the oops. In case of a race we could get not
+ * the exact information about the affected modules, but it's
+ * almost impossible to trigger and it's a not interesting case.
+ * This code runs protected by the die_lock spinlock, the arch/
+ * caller takes care of it.
+ */
+void module_oops_tracking_init(void)
+{
+ struct module * mod;
+
+ for (mod = module_list; mod != &kernel_module; mod = mod->next)
+ mod->flags &= ~MOD_OOPS_PRINT;
+}
+
+void module_oops_tracking_mark(struct module * mod)
+{
+ mod->flags |= MOD_OOPS_PRINT;
+}
+
+void module_oops_tracking_print(void)
+{
+ struct module *mod;
+ int i = 0;
+
+ for (mod = module_list; mod != &kernel_module; mod = mod->next) {
+ if (!(mod->flags & MOD_OOPS_PRINT))
+ continue;
+ if (!i)
+ printk("Modules:");
+ if (i && !(i % 2))
+ printk("\n ");
+ i++;
+
+ printk(" [(%s:<%p>:<%p>)]",
+ mod->name,
+ (char *) mod + mod->size_of_struct,
+ (char *) mod + mod->size);
+ }
+ if (i)
+ printk("\n");
+}
+
#else /* CONFIG_MODULES */
/* Dummy syscalls for people who don't want modules */
--- patch-backup/arch/ppc/kernel/process.c Mon Oct 13 17:32:04 2003
+++ arch/ppc/kernel/process.c Tue Oct 14 00:05:29 2003
@@ -60,6 +60,53 @@
#undef SHOW_TASK_SWITCHES
#undef CHECK_STACK
+/*
+ * If the address is either in the .text section of the
+ * kernel, or in the vmalloc'ed module regions, it *may*
+ * be the address of a calling routine
+ */
+
+extern char _etext[], _stext[];
+
+#ifdef CONFIG_MODULES
+#include <linux/module.h>
+
+extern struct module *module_list;
+extern struct module kernel_module;
+
+static inline int kernel_text_address(unsigned long addr)
+{
+ int retval = 0;
+ struct module *mod;
+
+ if (addr >= (unsigned long) &_stext &&
+ addr <= (unsigned long) &_etext)
+ return 1;
+
+ for (mod = module_list; mod != &kernel_module; mod = mod->next) {
+ /* mod_bound tests for addr being inside the vmalloc'ed
+ * module area. Of course it'd be better to test only
+ * for the .text subset... */
+ if (mod_bound(addr, 0, mod)) {
+ module_oops_tracking_mark(mod);
+ retval = 1;
+ break;
+ }
+ }
+
+ return retval;
+}
+
+#else
+
+static inline int kernel_text_address(unsigned long addr)
+{
+ return (addr >= (unsigned long) &_stext &&
+ addr <= (unsigned long) &_etext);
+}
+
+#endif
+
#if defined(CHECK_STACK)
unsigned long
kernel_stack_top(struct task_struct *tsk)
@@ -243,6 +290,8 @@
{
int i;
+ module_oops_tracking_init();
+ kernel_text_address(regs->nip);
printk("NIP: %08lX XER: %08lX LR: %08lX SP: %08lX REGS: %p TRAP: %04lx %s\n",
regs->nip, regs->xer, regs->link, regs->gpr[1], regs,regs->trap, print_tainted());
printk("MSR: %08lx EE: %01x PR: %01x FP: %01x ME: %01x IR/DR: %01x%01x\n",
@@ -303,6 +352,7 @@
}
out:
print_backtrace((unsigned long *)regs->gpr[1]);
+ module_oops_tracking_print();
}
void exit_thread(void)
@@ -514,7 +564,11 @@
break;
if (cnt++ % 7 == 0)
printk("\n");
- printk("%08lX ", i);
+ if (kernel_text_address(i)) { /* mostly just want to mark modules */
+ printk("%08lX ", i);
+ } else { /* FIXME: should we ignore fishy adrs like x86? */
+ printk("%08lX? ", i); /* Or append a '?' (ksymoops doesn't mind) */
+ }
if (cnt > 32) break;
if (__get_user(sp, (unsigned long **)sp))
break;
--- arch/ppc/kernel/traps.c.old Mon Oct 13 17:23:40 2003
+++ arch/ppc/kernel/traps.c Mon Oct 13 17:25:27 2003
@@ -97,7 +97,8 @@
set_backlight_enable(1);
set_backlight_level(BACKLIGHT_MAX);
#endif
- printk("Oops: %s, sig: %ld\n", str, err);
+ printk("Oops: %s, sig: %ld ", str, err);
+ printk(oops_id);
show_regs(fp);
#ifdef CONFIG_BOOTX_TEXT
force_printk_to_btext = 0;
next reply other threads:[~2003-11-06 19:54 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2003-11-06 20:08 Dan Kegel [this message]
[not found] <OhH5.6Y2.13@gated-at.bofh.it>
[not found] ` <QouH.36G.7@gated-at.bofh.it>
2003-11-10 18:06 ` [RFC] Smarter stack traces using the frame pointer Andi Kleen
-- strict thread matches above, loose matches on Subject: below --
2003-11-04 22:13 Adam Litke
2003-11-05 2:21 ` Stephen Rothwell
2003-11-05 19:56 ` Martin J. Bligh
2003-11-06 11:51 ` Stephen Rothwell
2003-11-06 15:21 ` Martin J. Bligh
2003-11-10 17:46 ` Adam Litke
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=3FAAAA3B.1000707@kegel.com \
--to=dank@kegel.com \
--cc=linux-kernel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.