1*ac6e1abfSNicholas Piggin #include <libcflat.h> 2*ac6e1abfSNicholas Piggin #include <asm/ptrace.h> 3*ac6e1abfSNicholas Piggin #include <stack.h> 4*ac6e1abfSNicholas Piggin 5*ac6e1abfSNicholas Piggin extern char do_handle_exception_return[]; 6*ac6e1abfSNicholas Piggin arch_backtrace_frame(const void * frame,const void ** return_addrs,int max_depth,bool current_frame)7*ac6e1abfSNicholas Pigginint arch_backtrace_frame(const void *frame, const void **return_addrs, 8*ac6e1abfSNicholas Piggin int max_depth, bool current_frame) 9*ac6e1abfSNicholas Piggin { 10*ac6e1abfSNicholas Piggin static int walking; 11*ac6e1abfSNicholas Piggin int depth = 0; 12*ac6e1abfSNicholas Piggin const unsigned long *bp = (unsigned long *)frame; 13*ac6e1abfSNicholas Piggin void *return_addr; 14*ac6e1abfSNicholas Piggin 15*ac6e1abfSNicholas Piggin asm volatile("" ::: "lr"); /* Force it to save LR */ 16*ac6e1abfSNicholas Piggin 17*ac6e1abfSNicholas Piggin if (walking) { 18*ac6e1abfSNicholas Piggin printf("RECURSIVE STACK WALK!!!\n"); 19*ac6e1abfSNicholas Piggin return 0; 20*ac6e1abfSNicholas Piggin } 21*ac6e1abfSNicholas Piggin walking = 1; 22*ac6e1abfSNicholas Piggin 23*ac6e1abfSNicholas Piggin if (current_frame) 24*ac6e1abfSNicholas Piggin bp = __builtin_frame_address(0); 25*ac6e1abfSNicholas Piggin 26*ac6e1abfSNicholas Piggin bp = (unsigned long *)bp[0]; 27*ac6e1abfSNicholas Piggin return_addr = (void *)bp[2]; 28*ac6e1abfSNicholas Piggin 29*ac6e1abfSNicholas Piggin for (depth = 0; bp && depth < max_depth; depth++) { 30*ac6e1abfSNicholas Piggin return_addrs[depth] = return_addr; 31*ac6e1abfSNicholas Piggin if (return_addrs[depth] == 0) 32*ac6e1abfSNicholas Piggin break; 33*ac6e1abfSNicholas Piggin if (return_addrs[depth] == do_handle_exception_return) { 34*ac6e1abfSNicholas Piggin struct pt_regs *regs; 35*ac6e1abfSNicholas Piggin 36*ac6e1abfSNicholas Piggin regs = (void *)bp + STACK_FRAME_OVERHEAD; 37*ac6e1abfSNicholas Piggin bp = (unsigned long *)bp[0]; 38*ac6e1abfSNicholas Piggin /* Represent interrupt frame with vector number */ 39*ac6e1abfSNicholas Piggin return_addr = (void *)regs->trap; 40*ac6e1abfSNicholas Piggin if (depth + 1 < max_depth) { 41*ac6e1abfSNicholas Piggin depth++; 42*ac6e1abfSNicholas Piggin return_addrs[depth] = return_addr; 43*ac6e1abfSNicholas Piggin return_addr = (void *)regs->nip; 44*ac6e1abfSNicholas Piggin } 45*ac6e1abfSNicholas Piggin } else { 46*ac6e1abfSNicholas Piggin bp = (unsigned long *)bp[0]; 47*ac6e1abfSNicholas Piggin return_addr = (void *)bp[2]; 48*ac6e1abfSNicholas Piggin } 49*ac6e1abfSNicholas Piggin } 50*ac6e1abfSNicholas Piggin 51*ac6e1abfSNicholas Piggin walking = 0; 52*ac6e1abfSNicholas Piggin return depth; 53*ac6e1abfSNicholas Piggin } 54