From patchwork Fri Jun 12 14:27:51 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Liebler X-Patchwork-Id: 7144 Received: (qmail 51703 invoked by alias); 12 Jun 2015 14:28:12 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 51691 invoked by uid 89); 12 Jun 2015 14:28:11 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.5 required=5.0 tests=AWL, BAYES_00, RCVD_IN_DNSWL_LOW, SPF_HELO_PASS, SPF_PASS, T_RP_MATCHES_RCVD autolearn=ham version=3.3.2 X-HELO: plane.gmane.org To: libc-alpha@sourceware.org From: Stefan Liebler Subject: Re: [PATCH][BZ #18508] S390: Fix "backtrace() returns infinitely deep stack frames with makecontext()". Date: Fri, 12 Jun 2015 16:27:51 +0200 Lines: 106 Message-ID: References: <557AA306.4090208@redhat.com> Mime-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Thunderbird/31.7.0 In-Reply-To: <557AA306.4090208@redhat.com> On 06/12/2015 11:14 AM, Florian Weimer wrote: > On 06/09/2015 05:42 PM, Stefan Liebler wrote: > >> 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?)" > > Is it possible to extract a test case from the Go program, by calling > makecontext and backtrace in the same way to Go run time does? > > I think this would be a useful addition to the glibc test suite. > Yes, i can make a testcase like stdlib/tst-makecontext.c or extend it - see below. Can i call _Unwind_Backtrace directly on all architectures? Or does it exist on all architectures? The diff below uses dlopen to load libgcc, but e.g. s390 needs libgcc_s.so.1 and others like m68k needs libgcc_s.so.2. Is there a way to load the correct libgcc_s.so on all architectures? As an alternative i could use the glibc backtrace() method. But at least for the x86_64 version and all others who simply includes it, this testcase would not fail, because the backtrace_helper function has a check, if the address has changed in two consecutively calls. The go runtime hasn't such a check and would fail like reported by the mentioned go-bug. Any ideas? Bye Stefan terminate the process normally after this function returns. */ } diff --git a/stdlib/tst-makecontext.c b/stdlib/tst-makecontext.c index 29a588e..33f9d9e 100644 --- a/stdlib/tst-makecontext.c +++ b/stdlib/tst-makecontext.c @@ -19,23 +19,62 @@ #include #include #include +#include +#include +#include ucontext_t ucp; -char st1[8192]; +char st1[16384]; __thread int thr; +struct trace_arg +{ + int cnt, size; +}; + int somevar = -76; long othervar = -78L; +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 + /libbacktrace/backtrace.c, which uses _Unwind_Backtrace(). */ + handle = __libc_dlopen ("libgcc_s.so.1"); + if (handle != NULL) + { + unwind_backtrace = __libc_dlsym (handle, "_Unwind_Backtrace"); + if (unwind_backtrace != NULL) + { + unwind_backtrace (backtrace_helper, &arg); + assert (arg.cnt != -1 && arg.cnt < 100); + } + __libc_dlclose (handle); + } + /* Since uc_link below has been set to NULL, setcontext is supposed to