Skip to content

Commit

Permalink
S390: Fix "backtrace() returns infinitely deep stack frames with make…
Browse files Browse the repository at this point in the history
…context()" [BZ #18508].

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.
  • Loading branch information
Stefan Liebler authored and Andreas Krebbel committed Jul 7, 2015
1 parent fa4eeac commit 890b7a4
Show file tree
Hide file tree
Showing 6 changed files with 78 additions and 5 deletions.
15 changes: 15 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
@@ -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.
Expand Down
9 changes: 5 additions & 4 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
2 changes: 2 additions & 0 deletions stdlib/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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)
41 changes: 40 additions & 1 deletion stdlib/tst-makecontext.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,23 +19,62 @@
#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. */
}
Expand Down
8 changes: 8 additions & 0 deletions sysdeps/unix/sysv/linux/s390/s390-32/__makecontext_ret.S
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,14 @@

#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. */
Expand Down
8 changes: 8 additions & 0 deletions sysdeps/unix/sysv/linux/s390/s390-64/__makecontext_ret.S
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,14 @@

#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. */
Expand Down

0 comments on commit 890b7a4

Please sign in to comment.