in kernel/traps.c [77:172]
static void do_show_stack(struct task_struct *task, unsigned long *fp,
unsigned long ip, const char *loglvl)
{
int kstack_depth_to_print = 24;
unsigned long offset, size;
const char *name = NULL;
unsigned long *newfp;
unsigned long low, high;
char tmpstr[128];
char *modname;
int i;
if (task == NULL)
task = current;
printk("%sCPU#%d, %s/%d, Call Trace:\n", loglvl, raw_smp_processor_id(),
task->comm, task_pid_nr(task));
if (fp == NULL) {
if (task == current) {
asm("%0 = r30" : "=r" (fp));
} else {
fp = (unsigned long *)
((struct hexagon_switch_stack *)
task->thread.switch_sp)->fp;
}
}
if ((((unsigned long) fp) & 0x3) || ((unsigned long) fp < 0x1000)) {
printk("%s-- Corrupt frame pointer %p\n", loglvl, fp);
return;
}
/* Saved link reg is one word above FP */
if (!ip)
ip = *(fp+1);
/* Expect kernel stack to be in-bounds */
low = (unsigned long)task_stack_page(task);
high = low + THREAD_SIZE - 8;
low += sizeof(struct thread_info);
for (i = 0; i < kstack_depth_to_print; i++) {
name = kallsyms_lookup(ip, &size, &offset, &modname, tmpstr);
printk("%s[%p] 0x%lx: %s + 0x%lx", loglvl, fp, ip, name, offset);
if (((unsigned long) fp < low) || (high < (unsigned long) fp))
printk(KERN_CONT " (FP out of bounds!)");
if (modname)
printk(KERN_CONT " [%s] ", modname);
printk(KERN_CONT "\n");
newfp = (unsigned long *) *fp;
if (((unsigned long) newfp) & 0x3) {
printk("%s-- Corrupt frame pointer %p\n", loglvl, newfp);
break;
}
/* Attempt to continue past exception. */
if (0 == newfp) {
struct pt_regs *regs = (struct pt_regs *) (((void *)fp)
+ 8);
if (regs->syscall_nr != -1) {
printk("%s-- trap0 -- syscall_nr: %ld", loglvl,
regs->syscall_nr);
printk(KERN_CONT " psp: %lx elr: %lx\n",
pt_psp(regs), pt_elr(regs));
break;
} else {
/* really want to see more ... */
kstack_depth_to_print += 6;
printk("%s-- %s (0x%lx) badva: %lx\n", loglvl,
ex_name(pt_cause(regs)), pt_cause(regs),
pt_badva(regs));
}
newfp = (unsigned long *) regs->r30;
ip = pt_elr(regs);
} else {
ip = *(newfp + 1);
}
/* If link reg is null, we are done. */
if (ip == 0x0)
break;
/* If newfp isn't larger, we're tracing garbage. */
if (newfp > fp)
fp = newfp;
else
break;
}
}