sh: Proper show_stack/show_trace() implementation.
This splits out some of the previous show_stack() implementation which was mostly doing the show_trace() work without actually dumping any of the stack contents. This now gets split in to two sections, where we do the fetching of the stack pointer and subsequent stack dumping in show_stack(), while moving the call trace in to show_trace(). Signed-off-by: Paul Mundt <lethal@linux-sh.org>
This commit is contained in:
parent
ce9e3d9953
commit
6b0022305f
3 changed files with 81 additions and 65 deletions
|
@ -105,7 +105,7 @@ void show_regs(struct pt_regs * regs)
|
|||
{
|
||||
printk("\n");
|
||||
printk("Pid : %d, Comm: %20s\n", current->pid, current->comm);
|
||||
print_symbol("PC is at %s\n", regs->pc);
|
||||
print_symbol("PC is at %s\n", instruction_pointer(regs));
|
||||
printk("PC : %08lx SP : %08lx SR : %08lx ",
|
||||
regs->pc, regs->regs[15], regs->sr);
|
||||
#ifdef CONFIG_MMU
|
||||
|
@ -130,15 +130,7 @@ void show_regs(struct pt_regs * regs)
|
|||
printk("MACH: %08lx MACL: %08lx GBR : %08lx PR : %08lx\n",
|
||||
regs->mach, regs->macl, regs->gbr, regs->pr);
|
||||
|
||||
/*
|
||||
* If we're in kernel mode, dump the stack too..
|
||||
*/
|
||||
if (!user_mode(regs)) {
|
||||
extern void show_task(unsigned long *sp);
|
||||
unsigned long sp = regs->regs[15];
|
||||
|
||||
show_task((unsigned long *)sp);
|
||||
}
|
||||
show_trace(NULL, (unsigned long *)regs->regs[15], regs);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -1,16 +1,15 @@
|
|||
/* $Id: traps.c,v 1.17 2004/05/02 01:46:30 sugioka Exp $
|
||||
*
|
||||
* linux/arch/sh/traps.c
|
||||
/*
|
||||
* 'traps.c' handles hardware traps and faults after we have saved some
|
||||
* state in 'entry.S'.
|
||||
*
|
||||
* SuperH version: Copyright (C) 1999 Niibe Yutaka
|
||||
* Copyright (C) 2000 Philipp Rumpf
|
||||
* Copyright (C) 2000 David Howells
|
||||
* Copyright (C) 2002, 2003 Paul Mundt
|
||||
*/
|
||||
|
||||
/*
|
||||
* 'Traps.c' handles hardware traps and faults after we have saved some
|
||||
* state in 'entry.S'.
|
||||
* Copyright (C) 2002 - 2006 Paul Mundt
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file "COPYING" in the main directory of this archive
|
||||
* for more details.
|
||||
*/
|
||||
#include <linux/sched.h>
|
||||
#include <linux/kernel.h>
|
||||
|
@ -53,13 +52,32 @@
|
|||
#define TRAP_ILLEGAL_SLOT_INST 13
|
||||
#endif
|
||||
|
||||
/*
|
||||
* These constants are for searching for possible module text
|
||||
* segments. VMALLOC_OFFSET comes from mm/vmalloc.c; MODULE_RANGE is
|
||||
* a guess of how much space is likely to be vmalloced.
|
||||
*/
|
||||
#define VMALLOC_OFFSET (8*1024*1024)
|
||||
#define MODULE_RANGE (8*1024*1024)
|
||||
static void dump_mem(const char *str, unsigned long bottom, unsigned long top)
|
||||
{
|
||||
unsigned long p;
|
||||
int i;
|
||||
|
||||
printk("%s(0x%08lx to 0x%08lx)\n", str, bottom, top);
|
||||
|
||||
for (p = bottom & ~31; p < top; ) {
|
||||
printk("%04lx: ", p & 0xffff);
|
||||
|
||||
for (i = 0; i < 8; i++, p += 4) {
|
||||
unsigned int val;
|
||||
|
||||
if (p < bottom || p >= top)
|
||||
printk(" ");
|
||||
else {
|
||||
if (__get_user(val, (unsigned int __user *)p)) {
|
||||
printk("\n");
|
||||
return;
|
||||
}
|
||||
printk("%08x ", val);
|
||||
}
|
||||
}
|
||||
printk("\n");
|
||||
}
|
||||
}
|
||||
|
||||
DEFINE_SPINLOCK(die_lock);
|
||||
|
||||
|
@ -69,14 +87,28 @@ void die(const char * str, struct pt_regs * regs, long err)
|
|||
|
||||
console_verbose();
|
||||
spin_lock_irq(&die_lock);
|
||||
bust_spinlocks(1);
|
||||
|
||||
printk("%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter);
|
||||
|
||||
CHK_REMOTE_DEBUG(regs);
|
||||
print_modules();
|
||||
show_regs(regs);
|
||||
|
||||
printk("Process: %s (pid: %d, stack limit = %p)\n",
|
||||
current->comm, current->pid, task_stack_page(current) + 1);
|
||||
|
||||
if (!user_mode(regs) || in_interrupt())
|
||||
dump_mem("Stack: ", regs->regs[15], THREAD_SIZE +
|
||||
(unsigned long)task_stack_page(current));
|
||||
|
||||
bust_spinlocks(0);
|
||||
spin_unlock_irq(&die_lock);
|
||||
do_exit(SIGSEGV);
|
||||
}
|
||||
|
||||
static inline void die_if_kernel(const char * str, struct pt_regs * regs, long err)
|
||||
static inline void die_if_kernel(const char *str, struct pt_regs *regs,
|
||||
long err)
|
||||
{
|
||||
if (!user_mode(regs))
|
||||
die(str, regs, err);
|
||||
|
@ -93,8 +125,7 @@ static int handle_unaligned_notify_count = 10;
|
|||
*/
|
||||
static int die_if_no_fixup(const char * str, struct pt_regs * regs, long err)
|
||||
{
|
||||
if (!user_mode(regs))
|
||||
{
|
||||
if (!user_mode(regs)) {
|
||||
const struct exception_table_entry *fixup;
|
||||
fixup = search_exception_tables(regs->pc);
|
||||
if (fixup) {
|
||||
|
@ -734,12 +765,31 @@ void __init trap_init(void)
|
|||
per_cpu_trap_init();
|
||||
}
|
||||
|
||||
void show_trace(struct task_struct *tsk, unsigned long *sp,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
unsigned long addr;
|
||||
|
||||
if (regs && user_mode(regs))
|
||||
return;
|
||||
|
||||
printk("\nCall trace: ");
|
||||
#ifdef CONFIG_KALLSYMS
|
||||
printk("\n");
|
||||
#endif
|
||||
|
||||
while (!kstack_end(sp)) {
|
||||
addr = *sp++;
|
||||
if (kernel_text_address(addr))
|
||||
print_ip_sym(addr);
|
||||
}
|
||||
|
||||
printk("\n");
|
||||
}
|
||||
|
||||
void show_stack(struct task_struct *tsk, unsigned long *sp)
|
||||
{
|
||||
unsigned long *stack, addr;
|
||||
unsigned long module_start = VMALLOC_START;
|
||||
unsigned long module_end = VMALLOC_END;
|
||||
int i = 1;
|
||||
unsigned long stack;
|
||||
|
||||
if (!tsk)
|
||||
tsk = current;
|
||||
|
@ -748,38 +798,10 @@ void show_stack(struct task_struct *tsk, unsigned long *sp)
|
|||
else
|
||||
sp = (unsigned long *)tsk->thread.sp;
|
||||
|
||||
stack = sp;
|
||||
|
||||
printk("\nCall trace: ");
|
||||
#ifdef CONFIG_KALLSYMS
|
||||
printk("\n");
|
||||
#endif
|
||||
|
||||
while (!kstack_end(stack)) {
|
||||
addr = *stack++;
|
||||
if (((addr >= (unsigned long)_text) &&
|
||||
(addr <= (unsigned long)_etext)) ||
|
||||
((addr >= module_start) && (addr <= module_end))) {
|
||||
/*
|
||||
* For 80-columns display, 6 entry is maximum.
|
||||
* NOTE: '[<8c00abcd>] ' consumes 13 columns .
|
||||
*/
|
||||
#ifndef CONFIG_KALLSYMS
|
||||
if (i && ((i % 6) == 0))
|
||||
printk("\n ");
|
||||
#endif
|
||||
printk("[<%08lx>] ", addr);
|
||||
print_symbol("%s\n", addr);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
printk("\n");
|
||||
}
|
||||
|
||||
void show_task(unsigned long *sp)
|
||||
{
|
||||
show_stack(NULL, sp);
|
||||
stack = (unsigned long)sp;
|
||||
dump_mem("Stack: ", stack, THREAD_SIZE +
|
||||
(unsigned long)task_stack_page(tsk));
|
||||
show_trace(tsk, sp, NULL);
|
||||
}
|
||||
|
||||
void dump_stack(void)
|
||||
|
|
|
@ -255,6 +255,8 @@ extern void save_fpu(struct task_struct *__tsk, struct pt_regs *regs);
|
|||
*/
|
||||
#define thread_saved_pc(tsk) (tsk->thread.pc)
|
||||
|
||||
void show_trace(struct task_struct *tsk, unsigned long *sp,
|
||||
struct pt_regs *regs);
|
||||
extern unsigned long get_wchan(struct task_struct *p);
|
||||
|
||||
#define KSTK_EIP(tsk) ((tsk)->thread.pc)
|
||||
|
|
Loading…
Reference in a new issue