
1: /* Return backtrace of current program state. Generic version. 2: Copyright (C) 1998, 2000, 2002, 2004, 2005 Free Software Foundation, Inc. 3: This file is part of the GNU C Library. 4: Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998. 5: 6: The GNU C Library is free software; you can redistribute it and/or 7: modify it under the terms of the GNU Lesser General Public 8: License as published by the Free Software Foundation; either 9: version 2.1 of the License, or (at your option) any later version. 10: 11: The GNU C Library is distributed in the hope that it will be useful, 12: but WITHOUT ANY WARRANTY; without even the implied warranty of 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14: Lesser General Public License for more details. 15: 16: You should have received a copy of the GNU Lesser General Public 17: License along with the GNU C Library; if not, write to the Free 18: Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 19: 02111-1307 USA. */ 20: 21: #include <execinfo.h> 22: #include <signal.h> 23: #include <frame.h> 24: #include <sigcontextinfo.h> 25: #include <bp-checks.h> 26: #include <ldsodefs.h> 27: 28: /* This implementation assumes a stack layout that matches the defaults 29: used by gcc's `__builtin_frame_address' and `__builtin_return_address' 30: (FP is the frame pointer register): 31: 32: +-----------------+ +-----------------+ 33: FP -> | previous FP --------> | previous FP ------>... 34: | | | | 35: | return address | | return address | 36: +-----------------+ +-----------------+ 37: 38: */ 39: 40: /* Get some notion of the current stack. Need not be exactly the top 41: of the stack, just something somewhere in the current frame. */ 42: #ifndef CURRENT_STACK_FRAME 43: # define CURRENT_STACK_FRAME ({ char __csf; &__csf; }) 44: #endif 45: 46: /* By default we assume that the stack grows downward. */ 47: #ifndef INNER_THAN 48: # define INNER_THAN < 49: #endif 50: 51: /* By default assume the `next' pointer in struct layout points to the 52: next struct layout. */ 53: #ifndef ADVANCE_STACK_FRAME 54: # define ADVANCE_STACK_FRAME(next) BOUNDED_1 ((struct layout *) (next)) 55: #endif 56: 57: /* By default, the frame pointer is just what we get from gcc. */ 58: #ifndef FIRST_FRAME_POINTER 59: # define FIRST_FRAME_POINTER __builtin_frame_address (0) 60: #endif 61: 62: int 63: __backtrace (array, size) 64: void **array; 65: int size; 66: { 67: struct layout *current; 68: void *__unbounded top_frame; 69: void *__unbounded top_stack; 70: int cnt = 0; 71: 72: top_frame = FIRST_FRAME_POINTER; 73: top_stack = CURRENT_STACK_FRAME; 74: 75: /* We skip the call to this function, it makes no sense to record it. */ 76: current = BOUNDED_1 ((struct layout *) top_frame); 77: while (cnt < size) 78: { 79: if ((void *) current INNER_THAN top_stack 80: || !((void *) current INNER_THAN __libc_stack_end)) 81: /* This means the address is out of range. Note that for the 82: toplevel we see a frame pointer with value NULL which clearly is 83: out of range. */ 84: break; 85: 86: array[cnt++] = current->return_address; 87: 88: current = ADVANCE_STACK_FRAME (current->next); 89: } 90: 91: return cnt; 92: } 93: weak_alias (__backtrace, backtrace) 94: libc_hidden_def (__backtrace)