]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
S390: Fix "backtrace() returns infinitely deep stack frames with makecontext()" ...
authorStefan Liebler <stli@linux.vnet.ibm.com>
Thu, 28 Apr 2016 08:21:58 +0000 (10:21 +0200)
committerStefan Liebler <stli@linux.vnet.ibm.com>
Thu, 28 Apr 2016 08:21:58 +0000 (10:21 +0200)
On s390/s390x backtrace(buffer, size) returns the series of called functions until
"makecontext_ret" and additional entries (up to "size") with "makecontext_ret".
GDB-backtrace is also warning:
"Backtrace stopped: previous frame identical to this frame (corrupt stack?)"

To reproduce this scenario you have to setup a new context with makecontext()
and activate it with setcontext(). See e.g. cf() function in testcase stdlib/tst-makecontext.c.
Or see bug in libgo "Bug 66303 - runtime.Caller() returns infinitely deep stack frames
on s390x " (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66303).

This patch omits the cfi_startproc/cfi_endproc directives in ENTRY/END macro of
__makecontext_ret. Thus no frame information is generated in .eh_frame and backtrace
stops after __makecontext_ret. There is also no .eh_frame info for _start or
thread_start functions.

ChangeLog:

[BZ #18508]
* stdlib/Makefile ($(objpfx)tst-makecontext3):
Depend on $(libdl).
* stdlib/tst-makecontext.c (cf): Test if _Unwind_Backtrace
is not called infinitely times.
(backtrace_helper): New function.
(trace_arg): New struct.
(st1): Enlarge stack size.
* sysdeps/unix/sysv/linux/s390/s390-32/__makecontext_ret.S:
(__makecontext_ret): Omit cfi_startproc and cfi_endproc.
* sysdeps/unix/sysv/linux/s390/s390-64/__makecontext_ret.S:
Likewise.

(cherry picked from commit 890b7a4b33d482b5c768ab47d70758b80227e9bc)

ChangeLog
NEWS
stdlib/Makefile
stdlib/tst-makecontext.c
sysdeps/unix/sysv/linux/s390/s390-32/__makecontext_ret.S
sysdeps/unix/sysv/linux/s390/s390-64/__makecontext_ret.S

index 9b6e9f54e0a679fbc2f24abc3042fa72a294bcff..ac7f870508ea49630af52ff9035209b5726aa532 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,18 @@
+2016-04-28  Stefan Liebler  <stli@linux.vnet.ibm.com>
+
+       [BZ #18508]
+       * stdlib/Makefile ($(objpfx)tst-makecontext3):
+       Depend on $(libdl).
+       * stdlib/tst-makecontext.c (cf): Test if _Unwind_Backtrace
+       is not called infinitely times.
+       (backtrace_helper): New function.
+       (trace_arg): New struct.
+       (st1): Enlarge stack size.
+       * sysdeps/unix/sysv/linux/s390/s390-32/__makecontext_ret.S:
+       (__makecontext_ret): Omit cfi_startproc and cfi_endproc.
+       * sysdeps/unix/sysv/linux/s390/s390-64/__makecontext_ret.S:
+       Likewise.
+
 2016-04-28  Stefan Liebler  <stli@linux.vnet.ibm.com>
 
        [BZ #18080]
diff --git a/NEWS b/NEWS
index 18d873e4b8d9c881c3b26d62b27ef9c350a9f24a..b2a1871389122371ba5371e31fef70237d58af11 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -12,7 +12,7 @@ Version 2.19.1
   15946, 16545, 16574, 16623, 16657, 16695, 16743, 16758, 16759, 16760,
   16878, 16882, 16885, 16916, 16932, 16943, 16958, 17048, 17062, 17069,
   17079, 17137, 17153, 17213, 17263, 17269, 17325, 17555, 17905, 18007,
-  18032, 18080, 18240, 18287, 18905, 19879.
+  18032, 18080, 18240, 18287, 18508, 18905, 19879.
 
 * A buffer overflow in gethostbyname_r and related functions performing DNS
   requests has been fixed.  If the NSS functions were called with a
index b46c4a1fea9d1171ab57499f6a1b25449f3b07ed..8a34b838b68a44cfe3ba743bf3cd784fc0d70d29 100644 (file)
@@ -164,3 +164,5 @@ tst-tls-atexit-lib.so-no-z-defs = yes
 $(objpfx)tst-tls-atexit: $(common-objpfx)nptl/libpthread.so \
                         $(common-objpfx)dlfcn/libdl.so
 $(objpfx)tst-tls-atexit.out: $(objpfx)tst-tls-atexit-lib.so
+
+$(objpfx)tst-makecontext: $(libdl)
index 7968a6d3dc58671df2ca7ef6999258127a02641f..ef1e27a634316dbb84eecec007a45da6c2c48a46 100644 (file)
 #include <stdlib.h>
 #include <stdio.h>
 #include <ucontext.h>
+#include <assert.h>
+#include <unwind.h>
+#include <dlfcn.h>
+#include <gnu/lib-names.h>
 
 ucontext_t ucp;
-char st1[8192];
+char st1[16384];
 __thread int thr;
 
 int somevar = -76;
 long othervar = -78L;
 
+struct trace_arg
+{
+  int cnt, size;
+};
+
+static _Unwind_Reason_Code
+backtrace_helper (struct _Unwind_Context *ctx, void *a)
+{
+  struct trace_arg *arg = a;
+  if (++arg->cnt == arg->size)
+    return _URC_END_OF_STACK;
+  return _URC_NO_REASON;
+}
+
 void
 cf (int i)
 {
+  struct trace_arg arg = { .size = 100, .cnt = -1 };
+  void *handle;
+  _Unwind_Reason_Code (*unwind_backtrace) (_Unwind_Trace_Fn, void *);
+
   if (i != othervar || thr != 94)
     {
       printf ("i %d thr %d\n", i, thr);
       exit (1);
     }
 
+  /* Test if callback function of _Unwind_Backtrace is not called infinitely
+     times. See Bug 18508 or gcc bug "Bug 66303 - runtime.Caller() returns
+     infinitely deep stack frames on s390x.".
+     The go runtime calls backtrace_full() in
+     <gcc-src>/libbacktrace/backtrace.c, which uses _Unwind_Backtrace().  */
+  handle = dlopen (LIBGCC_S_SO, RTLD_LAZY);
+  if (handle != NULL)
+    {
+      unwind_backtrace = dlsym (handle, "_Unwind_Backtrace");
+      if (unwind_backtrace != NULL)
+       {
+         unwind_backtrace (backtrace_helper, &arg);
+         assert (arg.cnt != -1 && arg.cnt < 100);
+       }
+      dlclose (handle);
+    }
+
   /* Since uc_link below has been set to NULL, setcontext is supposed to
      terminate the process normally after this function returns.  */
 }
index 83cf0d8ffa7ca1c463ea5bad2adc9430d6e97be8..67ea206de4bc7d7b7dda759fa743a58cd61b8bd2 100644 (file)
 
 #include <sysdep.h>
 
+/* We do not want .eh_frame info so that __makecontext_ret stops unwinding
+   if backtrace was called within a context created by makecontext. (There
+   is also no .eh_frame info for _start or thread_start.)  */
+#undef cfi_startproc
+#define cfi_startproc
+#undef cfi_endproc
+#define cfi_endproc
+
 ENTRY(__makecontext_ret)
        basr  %r14,%r7
        ltr   %r8,%r8                   /* Check whether uc_link is 0.  */
index 71ecbab08e2d2ead7392428f0257ff6e2370820c..a2bf3ca02d915cfa706c7c939aecd888d52fd90c 100644 (file)
 
 #include <sysdep.h>
 
+/* We do not want .eh_frame info so that __makecontext_ret stops unwinding
+   if backtrace was called within a context created by makecontext. (There
+   is also no .eh_frame info for _start or thread_start.)  */
+#undef cfi_startproc
+#define cfi_startproc
+#undef cfi_endproc
+#define cfi_endproc
+
 ENTRY(__makecontext_ret)
        basr    %r14,%r7
        ltgr    %r8,%r8                 /* Check whether uc_link is 0.  */