1*4b6da826SThomas Huth /* 2*4b6da826SThomas Huth * stack related functions 3*4b6da826SThomas Huth * 4*4b6da826SThomas Huth * This code is free software; you can redistribute it and/or modify it 5*4b6da826SThomas Huth * under the terms of the GNU Library General Public License version 2. 6*4b6da826SThomas Huth */ 7*4b6da826SThomas Huth 852266791SPeter Feiner #include <libcflat.h> 952266791SPeter Feiner #include <stack.h> 1052266791SPeter Feiner 1152266791SPeter Feiner #define MAX_DEPTH 20 1252266791SPeter Feiner 1352266791SPeter Feiner static void print_stack(const void **return_addrs, int depth, 1452266791SPeter Feiner bool top_is_return_address) 1552266791SPeter Feiner { 1652266791SPeter Feiner int i = 0; 1752266791SPeter Feiner 1852266791SPeter Feiner printf("\tSTACK:"); 1952266791SPeter Feiner 2052266791SPeter Feiner /* @addr indicates a non-return address, as expected by the stack 2152266791SPeter Feiner * pretty printer script. */ 2252266791SPeter Feiner if (depth > 0 && !top_is_return_address) { 2352266791SPeter Feiner printf(" @%lx", (unsigned long) return_addrs[0]); 2452266791SPeter Feiner i++; 2552266791SPeter Feiner } 2652266791SPeter Feiner 2752266791SPeter Feiner for (; i < depth; i++) { 2852266791SPeter Feiner printf(" %lx", (unsigned long) return_addrs[i]); 2952266791SPeter Feiner } 3052266791SPeter Feiner printf("\n"); 3152266791SPeter Feiner } 3252266791SPeter Feiner 3352266791SPeter Feiner void dump_stack(void) 3452266791SPeter Feiner { 3552266791SPeter Feiner const void *return_addrs[MAX_DEPTH]; 3652266791SPeter Feiner int depth; 3752266791SPeter Feiner 3852266791SPeter Feiner depth = backtrace(return_addrs, MAX_DEPTH); 3952266791SPeter Feiner print_stack(&return_addrs[1], depth ? depth - 1 : 0, true); 4052266791SPeter Feiner } 4152266791SPeter Feiner 4252266791SPeter Feiner void dump_frame_stack(const void *instruction, const void *frame) 4352266791SPeter Feiner { 4452266791SPeter Feiner const void *return_addrs[MAX_DEPTH]; 4552266791SPeter Feiner int depth; 4652266791SPeter Feiner 4752266791SPeter Feiner return_addrs[0] = instruction; 4852266791SPeter Feiner depth = backtrace_frame(frame, &return_addrs[1], MAX_DEPTH - 1); 4952266791SPeter Feiner print_stack(return_addrs, depth + 1, false); 5052266791SPeter Feiner } 5152266791SPeter Feiner 5252266791SPeter Feiner #ifndef HAVE_ARCH_BACKTRACE 5352266791SPeter Feiner int backtrace(const void **return_addrs, int max_depth) 5452266791SPeter Feiner { 5552266791SPeter Feiner static int walking; 5652266791SPeter Feiner int depth = 0; 5752266791SPeter Feiner void *addr; 5852266791SPeter Feiner 5952266791SPeter Feiner if (walking) { 6052266791SPeter Feiner printf("RECURSIVE STACK WALK!!!\n"); 6152266791SPeter Feiner return 0; 6252266791SPeter Feiner } 6352266791SPeter Feiner walking = 1; 6452266791SPeter Feiner 6552266791SPeter Feiner /* __builtin_return_address requires a compile-time constant argument */ 6652266791SPeter Feiner #define GET_RETURN_ADDRESS(i) \ 6752266791SPeter Feiner if (max_depth == i) \ 6852266791SPeter Feiner goto done; \ 6952266791SPeter Feiner addr = __builtin_return_address(i); \ 7052266791SPeter Feiner if (!addr) \ 7152266791SPeter Feiner goto done; \ 7252266791SPeter Feiner return_addrs[i] = __builtin_extract_return_addr(addr); \ 7352266791SPeter Feiner depth = i + 1; \ 7452266791SPeter Feiner 7552266791SPeter Feiner GET_RETURN_ADDRESS(0) 7652266791SPeter Feiner GET_RETURN_ADDRESS(1) 7752266791SPeter Feiner GET_RETURN_ADDRESS(2) 7852266791SPeter Feiner GET_RETURN_ADDRESS(3) 7952266791SPeter Feiner GET_RETURN_ADDRESS(4) 8052266791SPeter Feiner GET_RETURN_ADDRESS(5) 8152266791SPeter Feiner GET_RETURN_ADDRESS(6) 8252266791SPeter Feiner GET_RETURN_ADDRESS(7) 8352266791SPeter Feiner GET_RETURN_ADDRESS(8) 8452266791SPeter Feiner GET_RETURN_ADDRESS(9) 8552266791SPeter Feiner GET_RETURN_ADDRESS(10) 8652266791SPeter Feiner GET_RETURN_ADDRESS(11) 8752266791SPeter Feiner GET_RETURN_ADDRESS(12) 8852266791SPeter Feiner GET_RETURN_ADDRESS(13) 8952266791SPeter Feiner GET_RETURN_ADDRESS(14) 9052266791SPeter Feiner GET_RETURN_ADDRESS(15) 9152266791SPeter Feiner GET_RETURN_ADDRESS(16) 9252266791SPeter Feiner GET_RETURN_ADDRESS(17) 9352266791SPeter Feiner GET_RETURN_ADDRESS(18) 9452266791SPeter Feiner GET_RETURN_ADDRESS(19) 9552266791SPeter Feiner GET_RETURN_ADDRESS(20) 9652266791SPeter Feiner 9752266791SPeter Feiner #undef GET_RETURN_ADDRESS 9852266791SPeter Feiner 9952266791SPeter Feiner done: 10052266791SPeter Feiner walking = 0; 10152266791SPeter Feiner return depth; 10252266791SPeter Feiner } 10352266791SPeter Feiner #endif /* HAVE_ARCH_BACKTRACE */ 104