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 | |
parent | d1dc39a44e339f9c48baa3854fffb3d68c73c8fa (diff) | |
download | glibc-b6ab06cef4670e02756bcdd4d2c33a49369a4346.zip glibc-b6ab06cef4670e02756bcdd4d2c33a49369a4346.tar.gz glibc-b6ab06cef4670e02756bcdd4d2c33a49369a4346.tar.bz2 |
2005-12-13 Ulrich Drepper <drepper@redhat.com>
Diffstat (limited to 'debug')
-rw-r--r-- | debug/backtrace.c | 94 | ||||
-rw-r--r-- | debug/backtracesyms.c | 58 | ||||
-rw-r--r-- | debug/backtracesymsfd.c | 64 |
3 files changed, 216 insertions, 0 deletions
diff --git a/debug/backtrace.c b/debug/backtrace.c new file mode 100644 index 0000000..f2d5237 --- /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) diff --git a/debug/backtracesyms.c b/debug/backtracesyms.c new file mode 100644 index 0000000..db7ba36 --- /dev/null +++ b/debug/backtracesyms.c @@ -0,0 +1,58 @@ +/* Return list with names for address in backtrace. + Copyright (C) 1998, 2000 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 <stdlib.h> +#include <string.h> + + +/* Assume the worst for the width of an address. */ +#define WORD_WIDTH 16 + + +char ** +__backtrace_symbols (array, size) + void *const *array; + int size; +{ + int cnt; + size_t total = 0; + char **result; + + /* We can compute the text size needed for the symbols since we print + them all as "[+0x<addr>]". */ + total = size * (WORD_WIDTH + 6); + + /* Allocate memory for the result. */ + result = malloc (size * sizeof (char *) + total); + if (result != NULL) + { + char *last = (char *) (result + size); + + for (cnt = 0; cnt < size; ++cnt) + { + result[cnt] = last; + last += 1 + sprintf (last, "[+%p]", array[cnt]); + } + } + + return result; +} +weak_alias (__backtrace_symbols, backtrace_symbols) diff --git a/debug/backtracesymsfd.c b/debug/backtracesymsfd.c new file mode 100644 index 0000000..b01f8b0 --- /dev/null +++ b/debug/backtracesymsfd.c @@ -0,0 +1,64 @@ +/* Write formatted list with names for addresses in backtrace to a file. + Copyright (C) 1998, 2003, 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 <string.h> +#include <sys/uio.h> + +#include <stdio-common/_itoa.h> +#include <not-cancel.h> + +#if __ELF_NATIVE_CLASS == 32 +# define WORD_WIDTH 8 +#else +/* We assume 64bits. */ +# define WORD_WIDTH 16 +#endif + + +void +__backtrace_symbols_fd (array, size, fd) + void *const *array; + int size; + int fd; +{ + struct iovec iov[3]; + int cnt; + + for (cnt = 0; cnt < size; ++cnt) + { + char buf[WORD_WIDTH]; + + iov[0].iov_base = (void *) "[0x"; + iov[0].iov_len = 3; + + iov[1].iov_base = _itoa_word ((unsigned long int) array[cnt], + &buf[WORD_WIDTH], 16, 0); + iov[1].iov_len = &buf[WORD_WIDTH] - (char *) iov[1].iov_base; + + iov[2].iov_base = (void *) "]\n"; + iov[2].iov_len = 2; + + /* We prefer to use the non-cancelable interface if it is available. */ + writev_not_cancel_no_status (fd, iov, 3); + } +} +weak_alias (__backtrace_symbols_fd, backtrace_symbols_fd) +libc_hidden_def (__backtrace_symbols_fd) |