about summary refs log tree commit diff
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@gmail.com>2011-05-14 10:46:17 -0400
committerUlrich Drepper <drepper@gmail.com>2011-05-14 10:46:17 -0400
commitd6f67f7d833b4e2039f832355fb0edd65522c9f4 (patch)
tree4c6f49bb0855978eb83a31b3d43134414a2ef621
parent0656e90edc091f122284b602d2d590314e40c97a (diff)
downloadglibc-d6f67f7d833b4e2039f832355fb0edd65522c9f4.tar.gz
glibc-d6f67f7d833b4e2039f832355fb0edd65522c9f4.tar.xz
glibc-d6f67f7d833b4e2039f832355fb0edd65522c9f4.zip
Handle recursive calls in backtrace better
-rw-r--r--ChangeLog7
-rw-r--r--NEWS12
-rw-r--r--sysdeps/ia64/backtrace.c27
3 files changed, 36 insertions, 10 deletions
diff --git a/ChangeLog b/ChangeLog
index 36a37087b1..43726ca8a5 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,12 @@
 2011-05-14  Ulrich Drepper  <drepper@gmail.com>
 
+	[BZ #12432]
+	* sysdeps/ia64/backtrace.c (struct trace_reg): Add cfa element.
+	(dummy_getcfa): New function.
+	(init): Get _Unwind_GetCFA address, use dummy if not found.
+	(backtrace_helper): In recursion check, also check whether CFA changes.
+	(__backtrace): Completely initialize arg.
+
 	* iconv/loop.c (SINGLE) [STORE_REST]: Add input bytes to bytebuf before
 	storing incomplete byte sequence in state object.  Avoid testing for
 	guaranteed too small input if we know there is enough data available.
diff --git a/NEWS b/NEWS
index 2fc193cf23..55932448e7 100644
--- a/NEWS
+++ b/NEWS
@@ -1,4 +1,4 @@
-GNU C Library NEWS -- history of user-visible changes.  2011-5-13
+GNU C Library NEWS -- history of user-visible changes.  2011-5-14
 Copyright (C) 1992-2009, 2010, 2011 Free Software Foundation, Inc.
 See the end for copying conditions.
 
@@ -10,11 +10,11 @@ Version 2.14
 * The following bugs are resolved with this release:
 
   386, 11257, 11258, 11487, 11532, 11578, 11653, 11668, 11724, 11945, 11947,
-  12052, 12158, 12178, 12200, 12346, 12393, 12420, 12445, 12449, 12454,
-  12460, 12469, 12489, 12509, 12510, 12511, 12518, 12527, 12541, 12545,
-  12551, 12583, 12587, 12597, 12611, 12625, 12631, 12650, 12653, 12655,
-  12660, 12681, 12685, 12711, 12713, 12714, 12717, 12723, 12724, 12734,
-  12738
+  12052, 12158, 12178, 12200, 12346, 12393, 12420, 12432, 12445, 12449,
+  12454, 12460, 12469, 12489, 12509, 12510, 12511, 12518, 12527, 12541,
+  12545, 12551, 12583, 12587, 12597, 12611, 12625, 12631, 12650, 12653,
+  12655, 12660, 12681, 12685, 12711, 12713, 12714, 12717, 12723, 12724,
+  12734, 12738
 
 * The RPC implementation in libc is obsoleted.  Old programs keep working
   but new programs cannot be linked with the routines in libc anymore.
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);