static void do_show_stack()

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;
	}
}