Commit 824315d9 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] Clean up xmon backtrace code.

From: Anton Blanchard <anton@samba.org>

Clean up xmon backtrace code, it was doing all manner of scary things.
parent 30ffc51d
......@@ -56,9 +56,6 @@ static u_int bus_error_jmp[100];
#define setjmp xmon_setjmp
#define longjmp xmon_longjmp
/* Max number of stack frames we are willing to produce on a backtrace. */
#define MAXFRAMECOUNT 50
/* Breakpoint stuff */
struct bpt {
unsigned long address;
......@@ -85,7 +82,6 @@ static void dump(void);
static void prdump(unsigned long, long);
static int ppc_inst_dump(unsigned long, long);
void print_address(unsigned long);
static int getsp(void);
static void backtrace(struct pt_regs *);
static void excprint(struct pt_regs *);
static void prregs(struct pt_regs *);
......@@ -897,93 +893,75 @@ const char *getvecname(unsigned long vec)
return ret;
}
static void
backtrace(struct pt_regs *excp)
/*
* Most of our exceptions are in the form:
* bl handler
* b .ret_from_exception
* and this currently fails to catch them.
*/
static inline int exception_frame(unsigned long ip)
{
unsigned long sp;
unsigned long lr;
unsigned long stack[3];
extern void *ret_from_syscall_1, *ret_from_syscall_2, *ret_from_except;
if ((ip == (unsigned long)ret_from_syscall_1) ||
(ip == (unsigned long)ret_from_syscall_2) ||
(ip == (unsigned long)ret_from_except))
return 1;
return 0;
}
static int xmon_depth_to_print = 64;
static void xmon_show_stack(unsigned long sp)
{
unsigned long ip;
unsigned long newsp;
int count = 0;
struct pt_regs regs;
int framecount;
char *funcname;
/* declare these as raw ptrs so we don't get func descriptors */
extern void *ret_from_except, *ret_from_syscall_1;
if (excp != NULL) {
lr = excp->link;
sp = excp->gpr[1];
} else {
/* Use care not to call any function before this point
so the saved lr has a chance of being good. */
asm volatile ("mflr %0" : "=r" (lr) :);
sp = getsp();
}
scanhex(&sp);
scannl();
for (framecount = 0;
sp != 0 && framecount < MAXFRAMECOUNT;
sp = stack[0], framecount++) {
if (mread(sp, stack, sizeof(stack)) != sizeof(stack))
do {
if (sp < PAGE_OFFSET) {
printf("SP in userspace\n");
break;
#if 0
if (lr != 0) {
stack[2] = lr; /* fake out the first saved lr. It may not be saved yet. */
lr = 0;
}
#endif
printf("%.16lx %.16lx", sp, stack[2]);
/* TAI -- for now only the ones cast to unsigned long will match.
* Need to test the rest...
*/
if ((stack[2] == (unsigned long)ret_from_except &&
(funcname = "ret_from_except"))
|| (stack[2] == (unsigned long)ret_from_syscall_1 &&
(funcname = "ret_from_syscall_1"))
#if 0
|| stack[2] == (unsigned) &ret_from_syscall_2
|| stack[2] == (unsigned) &do_signal_ret
#endif
) {
printf(" %s\n", funcname);
if (mread(sp+112, &regs, sizeof(regs)) != sizeof(regs))
if (!mread((sp + 16), &ip, sizeof(unsigned long)))
break;
printf("exception: %lx %s regs %lx\n", regs.trap, getvecname(regs.trap), sp+112);
printf(" %.16lx", regs.nip);
if (regs.nip & 0xffffffff00000000UL)
xmon_print_symbol(" %s", regs.nip);
printf("\n");
if (regs.gpr[1] < sp) {
printf("<Stack drops into userspace %.16lx>\n", regs.gpr[1]);
printf("[%016lx] [%016lx] ", sp, ip);
xmon_print_symbol("%s\n", ip);
if (exception_frame(ip)) {
if (mread(sp+112, &regs, sizeof(regs)) != sizeof(regs))
break;
printf(" exception: %lx %s regs %lx\n", regs.trap,
getvecname(regs.trap), sp+112);
}
sp = regs.gpr[1];
if (mread(sp, stack, sizeof(stack)) != sizeof(stack))
if (!mread(sp, &newsp, sizeof(unsigned long)))
break;
} else {
if (stack[2])
xmon_print_symbol(" %s", stack[2]);
printf("\n");
}
if (stack[0] && stack[0] <= sp) {
if ((stack[0] & 0xffffffff00000000UL) == 0)
printf("<Stack drops into 32-bit userspace %.16lx>\n", stack[0]);
else
printf("<Corrupt stack. Next backchain is %.16lx>\n", stack[0]);
if (newsp < sp)
break;
}
}
if (framecount >= MAXFRAMECOUNT)
printf("<Punt. Too many stack frames>\n");
sp = newsp;
} while (count++ < xmon_depth_to_print);
}
int
getsp()
static void backtrace(struct pt_regs *excp)
{
int x;
unsigned long sp;
if (excp == NULL)
sp = __get_SP();
else
sp = excp->gpr[1];
scanhex(&sp);
scannl();
asm("mr %0,1" : "=r" (x) :);
return x;
xmon_show_stack(sp);
}
spinlock_t exception_print_lock = SPIN_LOCK_UNLOCKED;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment