diff options
author | Ulrich Drepper <drepper@gmail.com> | 2011-05-14 10:46:17 -0400 |
---|---|---|
committer | Ulrich Drepper <drepper@gmail.com> | 2011-05-14 10:46:17 -0400 |
commit | d6f67f7d833b4e2039f832355fb0edd65522c9f4 (patch) | |
tree | 4c6f49bb0855978eb83a31b3d43134414a2ef621 /sysdeps/ia64 | |
parent | 0656e90edc091f122284b602d2d590314e40c97a (diff) | |
download | glibc-d6f67f7d833b4e2039f832355fb0edd65522c9f4.tar.gz glibc-d6f67f7d833b4e2039f832355fb0edd65522c9f4.tar.xz glibc-d6f67f7d833b4e2039f832355fb0edd65522c9f4.zip |
Handle recursive calls in backtrace better
Diffstat (limited to 'sysdeps/ia64')
-rw-r--r-- | sysdeps/ia64/backtrace.c | 27 |
1 files changed, 23 insertions, 4 deletions
diff --git a/sysdeps/ia64/backtrace.c b/sysdeps/ia64/backtrace.c index 5cefb86ae4..d4ff291022 100644 --- a/sysdeps/ia64/backtrace.c +++ b/sysdeps/ia64/backtrace.c @@ -1,5 +1,5 @@ /* Return backtrace of current program state. - Copyright (C) 2003, 2004, 2005, 2007, 2009 Free Software Foundation, Inc. + Copyright (C) 2003-2005, 2007, 2009, 2011 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Jakub Jelinek <jakub@redhat.com>, 2003. @@ -27,14 +27,26 @@ struct trace_arg { void **array; - int cnt, size; + _Unwind_Word cfa; + int cnt; + int size; }; #ifdef SHARED static _Unwind_Reason_Code (*unwind_backtrace) (_Unwind_Trace_Fn, void *); static _Unwind_Ptr (*unwind_getip) (struct _Unwind_Context *); +static _Unwind_Word (*unwind_getcfa) (struct _Unwind_Context *); static void *libgcc_handle; + +/* Dummy version in case libgcc_s does not contain the real code. */ +static _Unwind_Word +dummy_getcfa (struct _Unwind_Context *ctx __attribute__ ((unused))) +{ + return 0; +} + + static void init (void) { @@ -47,10 +59,13 @@ init (void) unwind_getip = __libc_dlsym (libgcc_handle, "_Unwind_GetIP"); if (unwind_getip == NULL) unwind_backtrace = NULL; + unwind_getcfa = (__libc_dlsym (libgcc_handle, "_Unwind_GetCFA") + ?: dummy_getcfa); } #else # define unwind_backtrace _Unwind_Backtrace # define unwind_getip _Unwind_GetIP +# define unwind_getcfa _Unwind_GetCFA #endif static _Unwind_Reason_Code @@ -65,8 +80,12 @@ backtrace_helper (struct _Unwind_Context *ctx, void *a) arg->array[arg->cnt] = (void *) unwind_getip (ctx); /* Check whether we make any progress. */ - if (arg->cnt > 0 && arg->array[arg->cnt - 1] == arg->array[arg->cnt]) + _Unwind_Word cfa = unwind_getcfa (ctx); + + if (arg->cnt > 0 && arg->array[arg->cnt - 1] == arg->array[arg->cnt] + && cfa == arg->cfa) return _URC_END_OF_STACK; + arg->cfa = cfa; } if (++arg->cnt == arg->size) return _URC_END_OF_STACK; @@ -78,7 +97,7 @@ __backtrace (array, size) void **array; int size; { - struct trace_arg arg = { .array = array, .size = size, .cnt = -1 }; + struct trace_arg arg = { .array = array, .cfa = 0, .size = size, .cnt = -1 }; #ifdef SHARED __libc_once_define (static, once); |