From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 32623 invoked by alias); 22 Nov 2013 13:53:29 -0000 Mailing-List: contact gdb-prs-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-prs-owner@sourceware.org Received: (qmail 32597 invoked by uid 55); 22 Nov 2013 13:53:29 -0000 From: "cvs-commit at gcc dot gnu.org" To: gdb-prs@sourceware.org Subject: [Bug backtrace/16155] Backtraces in threads don't work on AArch64 Date: Fri, 22 Nov 2013 13:53:00 -0000 X-Bugzilla-Reason: CC X-Bugzilla-Type: changed X-Bugzilla-Watch-Reason: None X-Bugzilla-Product: gdb X-Bugzilla-Component: backtrace X-Bugzilla-Version: 7.6 X-Bugzilla-Keywords: X-Bugzilla-Severity: critical X-Bugzilla-Who: cvs-commit at gcc dot gnu.org X-Bugzilla-Status: NEW X-Bugzilla-Priority: P2 X-Bugzilla-Assigned-To: tromey at redhat dot com X-Bugzilla-Target-Milestone: --- X-Bugzilla-Flags: X-Bugzilla-Changed-Fields: Message-ID: In-Reply-To: References: Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: 7bit X-Bugzilla-URL: http://sourceware.org/bugzilla/ Auto-Submitted: auto-generated MIME-Version: 1.0 X-SW-Source: 2013-q4/txt/msg00363.txt.bz2 http://sourceware.org/bugzilla/show_bug.cgi?id=16155 --- Comment #7 from cvs-commit at gcc dot gnu.org --- This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "gdb and binutils". The branch, master has been updated via 33f8fe58b9a55a0075a90cc9080a1716221a3f81 (commit) from 1ec56e88aa9b052ab10b806d82fbdbc8d153d977 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=33f8fe58b9a55a0075a90cc9080a1716221a3f81 commit 33f8fe58b9a55a0075a90cc9080a1716221a3f81 Author: Pedro Alves Date: Fri Nov 22 11:51:59 2013 +0000 Don't let two frames with the same id end up in the frame chain. The UNWIND_SAME_ID check is done between THIS_FRAME and the next frame when we go try to unwind the previous frame. But at this point, it's already too late -- we ended up with two frames with the same ID in the frame chain. Each frame having its own ID is an invariant assumed throughout GDB. This patch applies the UNWIND_SAME_ID detection earlier, right after the previous frame is unwound, discarding the dup frame if a cycle is detected. The patch includes a new test that fails before the change. Before the patch, the test causes an infinite loop in GDB, after the patch, the UNWIND_SAME_ID logic kicks in and makes the backtrace stop with: Backtrace stopped: previous frame identical to this frame (corrupt stack?) The test uses dwarf CFI to emulate a corrupted stack with a cycle. It has a function with registers marked DW_CFA_same_value (most importantly RSP/RIP), so that GDB computes the same ID for that frame and its caller. IOW, something like this: #0 - frame_id_1 #1 - frame_id_2 #2 - frame_id_3 #3 - frame_id_4 #4 - frame_id_4 <<<< outermost (UNWIND_SAME_ID). (The test's code is just a copy of dw2-reg-undefined.S / dw2-reg-undefined.c, adjusted to use DW_CFA_same_value instead of DW_CFA_undefined, and to mark a different set of registers.) The infinite loop is here, in value_fetch_lazy: while (VALUE_LVAL (new_val) == lval_register && value_lazy (new_val)) { frame = frame_find_by_id (VALUE_FRAME_ID (new_val)); ... new_val = get_frame_register_value (frame, regnum); } get_frame_register_value can return a lazy register value pointing to the next frame. This means that the register wasn't clobbered by FRAME; the debugger should therefore retrieve its value from the next frame. To be clear, get_frame_register_value unwinds the value in question from the next frame: struct value * get_frame_register_value (struct frame_info *frame, int regnum) { return frame_unwind_register_value (frame->next, regnum); ^^^^^^^^^^^ } In other words, if we get a lazy lval_register, it should have the frame ID of the _next_ frame, never of FRAME. At this point in value_fetch_lazy, the whole relevant chunk of the stack up to frame #4 has already been unwound. The loop always "unlazies" lval_registers in the "next/innermost" direction, not in the "prev/unwind further/outermost" direction. So say we're looking at frame #4. get_frame_register_value in frame #4 can return a lazy register value of frame #3. So the next iteration, frame_find_by_id tries to read the register from frame #3. But, since frame #4 happens to have same id as frame #3, frame_find_by_id returns frame #4 instead. Rinse, repeat, and we have an infinite loop. This is an old latent problem, exposed by the recent addition of the frame stash. Before we had a stash, frame_find_by_id(frame_id_4) would walk over all frames starting at the current frame, and would always find #3 first. The stash happens to return #4 instead: struct frame_info * frame_find_by_id (struct frame_id id) { struct frame_info *frame, *prev_frame; ... /* Try using the frame stash first. Finding it there removes the need to perform the search by looping over all frames, which can be very CPU-intensive if the number of frames is very high (the loop is O(n) and get_prev_frame performs a series of checks that are relatively expensive). This optimization is particularly useful when this function is called from another function (such as value_fetch_lazy, case VALUE_LVAL (val) == lval_register) which already loops over all frames, making the overall behavior O(n^2). */ frame = frame_stash_find (id); if (frame) return frame; for (frame = get_current_frame (); ; frame = prev_frame) { gdb/ 2013-11-22 Pedro Alves PR 16155 * frame.c (get_prev_frame_1): Do the UNWIND_SAME_ID check between this frame and the new previous frame, not between this frame and the next frame. gdb/testsuite/ 2013-11-22 Pedro Alves PR 16155 * gdb.dwarf2/dw2-dup-frame.S: New file. * gdb.dwarf2/dw2-dup-frame.c: New file. * gdb.dwarf2/dw2-dup-frame.exp: New file. ----------------------------------------------------------------------- Summary of changes: gdb/ChangeLog | 7 + gdb/frame.c | 43 ++- gdb/testsuite/ChangeLog | 7 + gdb/testsuite/gdb.dwarf2/dw2-dup-frame.S | 540 ++++++++++++++++++++++++++++ gdb/testsuite/gdb.dwarf2/dw2-dup-frame.c | 36 ++ gdb/testsuite/gdb.dwarf2/dw2-dup-frame.exp | 44 +++ 6 files changed, 660 insertions(+), 17 deletions(-) create mode 100644 gdb/testsuite/gdb.dwarf2/dw2-dup-frame.S create mode 100644 gdb/testsuite/gdb.dwarf2/dw2-dup-frame.c create mode 100644 gdb/testsuite/gdb.dwarf2/dw2-dup-frame.exp -- You are receiving this mail because: You are on the CC list for the bug.