]> 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>
Tue, 7 Jul 2015 14:11:14 +0000 (16:11 +0200)
committerAndreas Krebbel <krebbel@linux.vnet.ibm.com>
Tue, 7 Jul 2015 14:11:14 +0000 (16:11 +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.

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 2df417ec74064126168847c89b792ad5fbf1c057..ff64fdc3c1a33eb6295b85740eb126932ae19668 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,18 @@
+2015-07-07  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.
+
 2015-07-07  Stefan Liebler  <stli@linux.vnet.ibm.com>
 
        * sysdeps/s390/fpu/libm-test-ulps: Regenerated.
diff --git a/NEWS b/NEWS
index 569a7d6acc730735b20df37edce0e7fb8b854f28..07e8bd8f8d683f583b8e350fc3039a93f80a384d 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -22,10 +22,11 @@ Version 2.22
   18211, 18217, 18219, 18220, 18221, 18234, 18244, 18245, 18247, 18287,
   18319, 18324, 18333, 18346, 18371, 18397, 18409, 18410, 18412, 18418,
   18422, 18434, 18435, 18444, 18468, 18469, 18470, 18479, 18483, 18495,
-  18496, 18497, 18498, 18502, 18507, 18512, 18513, 18519, 18520, 18522,
-  18527, 18528, 18529, 18530, 18532, 18533, 18534, 18536, 18539, 18540,
-  18542, 18544, 18545, 18546, 18547, 18549, 18553, 18558, 18569, 18583,
-  18585, 18586, 18592, 18593, 18594, 18602, 18612, 18613, 18619, 18633.
+  18496, 18497, 18498, 18502, 18507, 18508, 18512, 18513, 18519, 18520,
+  18522, 18527, 18528, 18529, 18530, 18532, 18533, 18534, 18536, 18539,
+  18540, 18542, 18544, 18545, 18546, 18547, 18549, 18553, 18558, 18569,
+  18583, 18585, 18586, 18592, 18593, 18594, 18602, 18612, 18613, 18619,
+  18633.
 
 * Cache information can be queried via sysconf() function on s390 e.g. with
   _SC_LEVEL1_ICACHE_SIZE as argument.
index 3300dd21420ca3867cae90b236a1a985e2c58f40..7fc5a807fa24c727b50e4968b96890e296e64a07 100644 (file)
@@ -164,3 +164,5 @@ $(objpfx)tst-setcontext3.out: tst-setcontext3.sh $(objpfx)tst-setcontext3
                 '$(run-program-env)' '$(test-program-prefix-after-env)' \
                 $(common-objpfx)stdlib/; \
        $(evaluate-test)
+
+$(objpfx)tst-makecontext: $(libdl)
index 29a588e5885bad9aeb02fb8e330fef4cf144e65a..8170e8aeedabefcf28e44c0fda6d16b3a3190ded 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 e1f9347f42f7f8d4723897845bb4ed1fff80a547..ad39bb843396e7d47cdd6ba023636f8d146fea9a 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 11a3cd37bb3792b8650c5dbc8d040add20e502f4..8a8665c21c6f90ae5d8f53baab67535a0e2aa280 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.  */