diff options
author | Ulrich Drepper <drepper@redhat.com> | 2005-12-14 08:43:25 +0000 |
---|---|---|
committer | Ulrich Drepper <drepper@redhat.com> | 2005-12-14 08:43:25 +0000 |
commit | b6ab06cef4670e02756bcdd4d2c33a49369a4346 (patch) | |
tree | b30743eb9728d890d1519f62b2d1f2b96f62547a /debug/backtrace.c | |
parent | d1dc39a44e339f9c48baa3854fffb3d68c73c8fa (diff) | |
download | glibc-b6ab06cef4670e02756bcdd4d2c33a49369a4346.tar.gz glibc-b6ab06cef4670e02756bcdd4d2c33a49369a4346.tar.xz glibc-b6ab06cef4670e02756bcdd4d2c33a49369a4346.zip |
2005-12-13 Ulrich Drepper <drepper@redhat.com>
Diffstat (limited to 'debug/backtrace.c')
-rw-r--r-- | debug/backtrace.c | 94 |
1 files changed, 94 insertions, 0 deletions
diff --git a/debug/backtrace.c b/debug/backtrace.c new file mode 100644 index 0000000000..f2d52372d5 --- /dev/null +++ b/debug/backtrace.c @@ -0,0 +1,94 @@ +/* Return backtrace of current program state. Generic version. + Copyright (C) 1998, 2000, 2002, 2004, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <execinfo.h> +#include <signal.h> +#include <frame.h> +#include <sigcontextinfo.h> +#include <bp-checks.h> +#include <ldsodefs.h> + +/* This implementation assumes a stack layout that matches the defaults + used by gcc's `__builtin_frame_address' and `__builtin_return_address' + (FP is the frame pointer register): + + +-----------------+ +-----------------+ + FP -> | previous FP --------> | previous FP ------>... + | | | | + | return address | | return address | + +-----------------+ +-----------------+ + + */ + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#ifndef CURRENT_STACK_FRAME +# define CURRENT_STACK_FRAME ({ char __csf; &__csf; }) +#endif + +/* By default we assume that the stack grows downward. */ +#ifndef INNER_THAN +# define INNER_THAN < +#endif + +/* By default assume the `next' pointer in struct layout points to the + next struct layout. */ +#ifndef ADVANCE_STACK_FRAME +# define ADVANCE_STACK_FRAME(next) BOUNDED_1 ((struct layout *) (next)) +#endif + +/* By default, the frame pointer is just what we get from gcc. */ +#ifndef FIRST_FRAME_POINTER +# define FIRST_FRAME_POINTER __builtin_frame_address (0) +#endif + +int +__backtrace (array, size) + void **array; + int size; +{ + struct layout *current; + void *__unbounded top_frame; + void *__unbounded top_stack; + int cnt = 0; + + top_frame = FIRST_FRAME_POINTER; + top_stack = CURRENT_STACK_FRAME; + + /* We skip the call to this function, it makes no sense to record it. */ + current = BOUNDED_1 ((struct layout *) top_frame); + while (cnt < size) + { + if ((void *) current INNER_THAN top_stack + || !((void *) current INNER_THAN __libc_stack_end)) + /* This means the address is out of range. Note that for the + toplevel we see a frame pointer with value NULL which clearly is + out of range. */ + break; + + array[cnt++] = current->return_address; + + current = ADVANCE_STACK_FRAME (current->next); + } + + return cnt; +} +weak_alias (__backtrace, backtrace) +libc_hidden_def (__backtrace) |