Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 35992
b: refs/heads/master
c: f66686f
h: refs/heads/master
v: v3
  • Loading branch information
Atsushi Nemoto authored and Ralf Baechle committed Sep 27, 2006
1 parent cf37941 commit f5ef5cd
Show file tree
Hide file tree
Showing 3 changed files with 142 additions and 24 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 79495d876c2074af5552a0c4b7aea600c2320e83
refs/heads/master: f66686f70a2a61e53ee8c2284f75ca342e4c0dc8
66 changes: 55 additions & 11 deletions trunk/arch/mips/kernel/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,7 @@ static struct mips_frame_info {
} *schedule_frame, mfinfo[64];
static int mfinfo_num;

static int __init get_frame_info(struct mips_frame_info *info)
static int get_frame_info(struct mips_frame_info *info)
{
int i;
void *func = info->func;
Expand Down Expand Up @@ -329,14 +329,12 @@ static int __init get_frame_info(struct mips_frame_info *info)
ip->i_format.simmediate / sizeof(long);
}
}
if (info->pc_offset == -1 || info->frame_size == 0) {
if (func == schedule)
printk("Can't analyze prologue code at %p\n", func);
info->pc_offset = -1;
info->frame_size = 0;
}

return 0;
if (info->frame_size && info->pc_offset >= 0) /* nested */
return 0;
if (info->pc_offset < 0) /* leaf */
return 1;
/* prologue seems boggus... */
return -1;
}

static int __init frame_info_init(void)
Expand Down Expand Up @@ -367,8 +365,15 @@ static int __init frame_info_init(void)
mfinfo[0].func = schedule;
schedule_frame = &mfinfo[0];
#endif
for (i = 0; i < ARRAY_SIZE(mfinfo) && mfinfo[i].func; i++)
get_frame_info(&mfinfo[i]);
for (i = 0; i < ARRAY_SIZE(mfinfo) && mfinfo[i].func; i++) {
struct mips_frame_info *info = &mfinfo[i];
if (get_frame_info(info)) {
/* leaf or unknown */
if (info->func == schedule)
printk("Can't analyze prologue code at %p\n",
info->func);
}
}

mfinfo_num = i;
return 0;
Expand Down Expand Up @@ -427,6 +432,8 @@ unsigned long get_wchan(struct task_struct *p)
if (i < 0)
break;

if (mfinfo[i].pc_offset < 0)
break;
pc = ((unsigned long *)frame)[mfinfo[i].pc_offset];
if (!mfinfo[i].frame_size)
break;
Expand All @@ -437,3 +444,40 @@ unsigned long get_wchan(struct task_struct *p)
return pc;
}

#ifdef CONFIG_KALLSYMS
/* used by show_frametrace() */
unsigned long unwind_stack(struct task_struct *task,
unsigned long **sp, unsigned long pc)
{
unsigned long stack_page;
struct mips_frame_info info;
char *modname;
char namebuf[KSYM_NAME_LEN + 1];
unsigned long size, ofs;

stack_page = (unsigned long)task_stack_page(task);
if (!stack_page)
return 0;

if (!kallsyms_lookup(pc, &size, &ofs, &modname, namebuf))
return 0;
if (ofs == 0)
return 0;

info.func = (void *)(pc - ofs);
info.func_size = ofs; /* analyze from start to ofs */
if (get_frame_info(&info)) {
/* leaf or unknown */
*sp += info.frame_size / sizeof(long);
return 0;
}
if ((unsigned long)*sp < stack_page ||
(unsigned long)*sp + info.frame_size / sizeof(long) >
stack_page + THREAD_SIZE - 32)
return 0;

pc = (*sp)[info.pc_offset];
*sp += info.frame_size / sizeof(long);
return pc;
}
#endif
98 changes: 86 additions & 12 deletions trunk/arch/mips/kernel/traps.c
Original file line number Diff line number Diff line change
Expand Up @@ -98,24 +98,53 @@ static void show_trace(unsigned long *stack)
printk("\n");
}

#ifdef CONFIG_KALLSYMS
static int raw_show_trace;
static int __init set_raw_show_trace(char *str)
{
raw_show_trace = 1;
return 1;
}
__setup("raw_show_trace", set_raw_show_trace);

extern unsigned long unwind_stack(struct task_struct *task,
unsigned long **sp, unsigned long pc);
static void show_frametrace(struct task_struct *task, struct pt_regs *regs)
{
const int field = 2 * sizeof(unsigned long);
unsigned long *stack = (long *)regs->regs[29];
unsigned long pc = regs->cp0_epc;
int top = 1;

if (raw_show_trace || !__kernel_text_address(pc)) {
show_trace(stack);
return;
}
printk("Call Trace:\n");
while (__kernel_text_address(pc)) {
printk(" [<%0*lx>] ", field, pc);
print_symbol("%s\n", pc);
pc = unwind_stack(task, &stack, pc);
if (top && pc == 0)
pc = regs->regs[31]; /* leaf? */
top = 0;
}
printk("\n");
}
#else
#define show_frametrace(task, r) show_trace((long *)(r)->regs[29]);
#endif

/*
* This routine abuses get_user()/put_user() to reference pointers
* with at least a bit of error checking ...
*/
void show_stack(struct task_struct *task, unsigned long *sp)
static void show_stacktrace(struct task_struct *task, struct pt_regs *regs)
{
const int field = 2 * sizeof(unsigned long);
long stackdata;
int i;
unsigned long *stack;

if (!sp) {
if (task && task != current)
sp = (unsigned long *) task->thread.reg29;
else
sp = (unsigned long *) &sp;
}
stack = sp;
unsigned long *sp = (unsigned long *)regs->regs[29];

printk("Stack :");
i = 0;
Expand All @@ -136,7 +165,44 @@ void show_stack(struct task_struct *task, unsigned long *sp)
i++;
}
printk("\n");
show_trace(stack);
show_frametrace(task, regs);
}

static noinline void prepare_frametrace(struct pt_regs *regs)
{
__asm__ __volatile__(
"1: la $2, 1b\n\t"
#ifdef CONFIG_64BIT
"sd $2, %0\n\t"
"sd $29, %1\n\t"
"sd $31, %2\n\t"
#else
"sw $2, %0\n\t"
"sw $29, %1\n\t"
"sw $31, %2\n\t"
#endif
: "=m" (regs->cp0_epc),
"=m" (regs->regs[29]), "=m" (regs->regs[31])
: : "memory");
}

void show_stack(struct task_struct *task, unsigned long *sp)
{
struct pt_regs regs;
if (sp) {
regs.regs[29] = (unsigned long)sp;
regs.regs[31] = 0;
regs.cp0_epc = 0;
} else {
if (task && task != current) {
regs.regs[29] = task->thread.reg29;
regs.regs[31] = 0;
regs.cp0_epc = task->thread.reg31;
} else {
prepare_frametrace(&regs);
}
}
show_stacktrace(task, &regs);
}

/*
Expand All @@ -146,6 +212,14 @@ void dump_stack(void)
{
unsigned long stack;

#ifdef CONFIG_KALLSYMS
if (!raw_show_trace) {
struct pt_regs regs;
prepare_frametrace(&regs);
show_frametrace(current, &regs);
return;
}
#endif
show_trace(&stack);
}

Expand Down Expand Up @@ -265,7 +339,7 @@ void show_registers(struct pt_regs *regs)
print_modules();
printk("Process %s (pid: %d, threadinfo=%p, task=%p)\n",
current->comm, current->pid, current_thread_info(), current);
show_stack(current, (long *) regs->regs[29]);
show_stacktrace(current, regs);
show_code((unsigned int *) regs->cp0_epc);
printk("\n");
}
Expand Down

0 comments on commit f5ef5cd

Please sign in to comment.