From patchwork Sun Nov 23 10:44:08 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Joel Brobecker X-Patchwork-Id: 3856 Received: (qmail 22043 invoked by alias); 23 Nov 2014 10:44:17 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 22003 invoked by uid 89); 23 Nov 2014 10:44:13 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.7 required=5.0 tests=AWL, BAYES_00 autolearn=ham version=3.3.2 X-HELO: rock.gnat.com Received: from rock.gnat.com (HELO rock.gnat.com) (205.232.38.15) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-SHA encrypted) ESMTPS; Sun, 23 Nov 2014 10:44:11 +0000 Received: from localhost (localhost.localdomain [127.0.0.1]) by filtered-rock.gnat.com (Postfix) with ESMTP id 2AD0111668B; Sun, 23 Nov 2014 05:44:10 -0500 (EST) Received: from rock.gnat.com ([127.0.0.1]) by localhost (rock.gnat.com [127.0.0.1]) (amavisd-new, port 10024) with LMTP id Hr-5fxuj11R5; Sun, 23 Nov 2014 05:44:10 -0500 (EST) Received: from joel.gnat.com (localhost.localdomain [127.0.0.1]) by rock.gnat.com (Postfix) with ESMTP id A2D0E11665B; Sun, 23 Nov 2014 05:44:09 -0500 (EST) Received: by joel.gnat.com (Postfix, from userid 1000) id E9E5D40F79; Sun, 23 Nov 2014 14:44:08 +0400 (RET) Date: Sun, 23 Nov 2014 14:44:08 +0400 From: Joel Brobecker To: Pedro Alves Cc: gdb-patches@sourceware.org, qemu-devel@nongnu.org Subject: Re: [RFA] Always consider infcall breakpoints as non-permanent. Message-ID: <20141123104408.GH5774@adacore.com> References: <54633C92.1080304@redhat.com> <1416501685-12457-1-git-send-email-brobecker@adacore.com> <546F241D.6060903@redhat.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <546F241D.6060903@redhat.com> User-Agent: Mutt/1.5.21 (2010-09-15) > > And seen from QEMU: > > > > qemu: fatal: Trap 0x02 while interrupts disabled, Error state > > [register dump removed] > > Bah. Do you know whether this happens only on SPARC QEMU, or > is this an issue for all QEMU ports? According to Fabien, one of our QEMU experts, it's related to the handling of that specific instruction: it does what the manual says it should do - when interrupts are disables, the CPU resets. So while it does not preclude from other ports from having the same sort of issue, it looks like it's mostly target-specific. > > gdb/ChangeLog: > > > > * breakpoint.c (bp_loc_is_permanent): Return 0 if LOC corresponds > > to a bp_call_dummy breakpoint type. > Patch is OK. Thanks Joel. Thank you. Attached is the patch I checked in with the corrections you pointed out. Thanks, Pedro. From e8af5d7a5cd4c58136a4733e87612f49061bf28b Mon Sep 17 00:00:00 2001 From: Joel Brobecker Date: Thu, 20 Nov 2014 20:41:25 +0400 Subject: [PATCH] Always consider infcall breakpoints as non-permanent. A recent change... commit 1a853c5224e2b8fedfac6d029365522b83080b40 Date: Wed Nov 12 10:10:49 2014 +0000 Subject: make "permanent breakpoints" per location and disableable ... broke function calls on sparc-elf when running over QEMU. Any function call should demonstrate the problem. For instance, seen from the debugger: (gdb) call pn(1234) [Inferior 1 (Remote target) exited normally] The program being debugged exited while in a function called from GDB. Evaluation of the expression containing the function And seen from QEMU: qemu: fatal: Trap 0x02 while interrupts disabled, Error state [register dump removed] What happens in this case is that GDB sets the inferior function call by not only creating the dummy frame, but also writing a breakpoint instruction at the return address for our function call. See infcall.c: /* Write a legitimate instruction at the point where the infcall breakpoint is going to be inserted. While this instruction is never going to be executed, a user investigating the memory from GDB would see this instruction instead of random uninitialized bytes. We chose the breakpoint instruction as it may look as the most logical one to the user and also valgrind 3.7.0 needs it for proper vgdb inferior calls. If software breakpoints are unsupported for this target we leave the user visible memory content uninitialized. */ bp_addr_as_address = bp_addr; bp_bytes = gdbarch_breakpoint_from_pc (gdbarch, &bp_addr_as_address, &bp_size); if (bp_bytes != NULL) write_memory (bp_addr_as_address, bp_bytes, bp_size); This instruction triggers a change introduced by the commit above, where we consider bp locations as being permanent breakpoints if there is already a breakpoint instruction at that address: + if (bp_loc_is_permanent (loc)) + { + loc->inserted = 1; + loc->permanent = 1; + } As a result, when resuming the program's execution for the inferior function call, GDB decides that it does not need to insert a breakpoint at this address, expecting the target to just report a SIGTRAP when trying to execute that instruction. But unfortunately for us, at least some versions of QEMU for SPARC just terminate the execution entirely instead of reporting a breakpoint, thus producing the behavior reported here. Although it appears like QEMU might be misbehaving and should therefore be fixed (to be verified) from the user's point of view, the recent change does introduce a regression. So this patch tries to mitigate a bit the damage by handling such infcall breakpoints as special and making sure that they are never considered permanent, thus restoring the previous behavior specifically for those breakpoints. The option of not writing the breakpoint instructions in the first place was considered, and would probably work also. But the comment associated to it seems to indicate that there is still reason to keep it. gdb/ChangeLog: * breakpoint.c (bp_loc_is_permanent): Return 0 if LOC corresponds to a bp_call_dummy breakpoint type. Tested on x86_64-linux. Also testing on sparc-elf/QEMU using AdaCore's testsuite. --- gdb/ChangeLog | 5 +++++ gdb/breakpoint.c | 14 ++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 45435fc..4e8284e 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,8 @@ +2014-11-23 Joel Brobecker + + * breakpoint.c (bp_loc_is_permanent): Return 0 if LOC corresponds + to a bp_call_dummy breakpoint type. + 2014-11-23 Patrick Palka * tui/tui-win.c (tui_initialize_win): Specify SA_RESTART when diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index 7b56260..574d06c 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -9293,6 +9293,20 @@ bp_loc_is_permanent (struct bp_location *loc) gdb_assert (loc != NULL); + /* bp_call_dummy breakpoint locations are usually memory locations + where GDB just wrote a breakpoint instruction, making it look + as if there is a permanent breakpoint at that location. Considering + it permanent makes GDB rely on that breakpoint instruction to stop + the program, thus removing the need to insert its own breakpoint + there. This is normally expected to work, except that some versions + of QEMU (Eg: QEMU 2.0.0 for SPARC) just report a fatal problem (Trap + 0x02 while interrupts disabled, Error state) instead of reporting + a SIGTRAP. QEMU should probably be fixed, but in the interest of + compatibility with versions that behave this way, we always consider + bp_call_dummy breakpoint locations as non-permanent. */ + if (loc->owner->type == bp_call_dummy) + return 0; + addr = loc->address; bpoint = gdbarch_breakpoint_from_pc (loc->gdbarch, &addr, &len); -- 1.9.1