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]; ...@@ -56,9 +56,6 @@ static u_int bus_error_jmp[100];
#define setjmp xmon_setjmp #define setjmp xmon_setjmp
#define longjmp xmon_longjmp #define longjmp xmon_longjmp
/* Max number of stack frames we are willing to produce on a backtrace. */
#define MAXFRAMECOUNT 50
/* Breakpoint stuff */ /* Breakpoint stuff */
struct bpt { struct bpt {
unsigned long address; unsigned long address;
...@@ -85,7 +82,6 @@ static void dump(void); ...@@ -85,7 +82,6 @@ static void dump(void);
static void prdump(unsigned long, long); static void prdump(unsigned long, long);
static int ppc_inst_dump(unsigned long, long); static int ppc_inst_dump(unsigned long, long);
void print_address(unsigned long); void print_address(unsigned long);
static int getsp(void);
static void backtrace(struct pt_regs *); static void backtrace(struct pt_regs *);
static void excprint(struct pt_regs *); static void excprint(struct pt_regs *);
static void prregs(struct pt_regs *); static void prregs(struct pt_regs *);
...@@ -897,93 +893,75 @@ const char *getvecname(unsigned long vec) ...@@ -897,93 +893,75 @@ const char *getvecname(unsigned long vec)
return ret; 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; extern void *ret_from_syscall_1, *ret_from_syscall_2, *ret_from_except;
unsigned long lr;
unsigned long stack[3]; 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; 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) { do {
lr = excp->link; if (sp < PAGE_OFFSET) {
sp = excp->gpr[1]; printf("SP in userspace\n");
} 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))
break; 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]); if (!mread((sp + 16), &ip, sizeof(unsigned long)))
/* 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))
break; break;
printf("exception: %lx %s regs %lx\n", regs.trap, getvecname(regs.trap), sp+112);
printf(" %.16lx", regs.nip); printf("[%016lx] [%016lx] ", sp, ip);
if (regs.nip & 0xffffffff00000000UL) xmon_print_symbol("%s\n", ip);
xmon_print_symbol(" %s", regs.nip);
printf("\n"); if (exception_frame(ip)) {
if (regs.gpr[1] < sp) { if (mread(sp+112, &regs, sizeof(regs)) != sizeof(regs))
printf("<Stack drops into userspace %.16lx>\n", regs.gpr[1]);
break; break;
printf(" exception: %lx %s regs %lx\n", regs.trap,
getvecname(regs.trap), sp+112);
} }
sp = regs.gpr[1]; if (!mread(sp, &newsp, sizeof(unsigned long)))
if (mread(sp, stack, sizeof(stack)) != sizeof(stack))
break; break;
} else { if (newsp < sp)
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]);
break; break;
}
} sp = newsp;
if (framecount >= MAXFRAMECOUNT) } while (count++ < xmon_depth_to_print);
printf("<Punt. Too many stack frames>\n");
} }
int static void backtrace(struct pt_regs *excp)
getsp()
{ {
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) :); xmon_show_stack(sp);
return x;
} }
spinlock_t exception_print_lock = SPIN_LOCK_UNLOCKED; 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