From patchwork Fri Apr 4 12:49:39 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pedro Alves X-Patchwork-Id: 405 Return-Path: X-Original-To: siddhesh@wilcox.dreamhost.com Delivered-To: siddhesh@wilcox.dreamhost.com Received: from homiemail-mx23.g.dreamhost.com (mx2.sub5.homie.mail.dreamhost.com [208.113.200.128]) by wilcox.dreamhost.com (Postfix) with ESMTP id DDC3036009A for ; Fri, 4 Apr 2014 05:49:49 -0700 (PDT) Received: by homiemail-mx23.g.dreamhost.com (Postfix, from userid 14314964) id 8E82F6238E782; Fri, 4 Apr 2014 05:49:49 -0700 (PDT) X-Original-To: gdb@patchwork.siddhesh.in Delivered-To: x14314964@homiemail-mx23.g.dreamhost.com Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by homiemail-mx23.g.dreamhost.com (Postfix) with ESMTPS id 7A0906238E7AB for ; Fri, 4 Apr 2014 05:49:49 -0700 (PDT) DomainKey-Signature: a=rsa-sha1; c=nofws; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:message-id:date:from:mime-version:to:cc :subject:references:in-reply-to:content-type :content-transfer-encoding; q=dns; s=default; b=iEROXN0FZ29Ilncz OZ5gKljIIe09KPmaEs8Pa/1p3j8dd/yyqpW7zX3SI+7hJXTg5wsmcXBFndZVuIEM DFoXCdWURFMYANtn4msGwa4DPKYrzbusiXBJHn3roz6MiH2U7EgHEl4ZqsN7ByNJ VjeDbMESDg+jtw5kqVglqJi++PY= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:message-id:date:from:mime-version:to:cc :subject:references:in-reply-to:content-type :content-transfer-encoding; s=default; bh=y7AQiiNevJoho9n/OtOlGt k1Jcw=; b=u4L35p6x3Q91TS97qyTLlyoD2aOVePdMnJ/YmjkZf0Eg/tXqpgXxsY npw9SUMZ/qgJm7kQPtbw2YAaRst+Dxf449Qg/D6gbXIgCvdtVxIw0+2n+TIMPVjm y4EzSUfNZlzVB61AD9lRPXYnLNcrvT9MWWRfhzmgnJrFRCzpu0Ins= Received: (qmail 9237 invoked by alias); 4 Apr 2014 12:49:47 -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 9216 invoked by uid 89); 4 Apr 2014 12:49:47 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.1 required=5.0 tests=AWL, BAYES_00, RP_MATCHES_RCVD, SPF_HELO_PASS, SPF_PASS, UNSUBSCRIBE_BODY autolearn=no version=3.3.2 X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 04 Apr 2014 12:49:45 +0000 Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id s34Cng8L007990 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 4 Apr 2014 08:49:43 -0400 Received: from [127.0.0.1] (ovpn01.gateway.prod.ext.ams2.redhat.com [10.39.146.11]) by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id s34Cnd0a028228; Fri, 4 Apr 2014 08:49:41 -0400 Message-ID: <533EAA63.5000701@redhat.com> Date: Fri, 04 Apr 2014 13:49:39 +0100 From: Pedro Alves User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:17.0) Gecko/20130625 Thunderbird/17.0.7 MIME-Version: 1.0 To: Yao Qi CC: gdb-patches@sourceware.org Subject: Re: [PATCH] Get frame after pull single-step breakpoints out References: <1396505398-23634-1-git-send-email-yao@codesourcery.com> In-Reply-To: <1396505398-23634-1-git-send-email-yao@codesourcery.com> X-DH-Original-To: gdb@patchwork.siddhesh.in On 04/03/2014 07:09 AM, Yao Qi wrote: > Hi, > I find that instruction that red by signal trampoline unwinder sniffer > is always the breakpoint instruction. I suspect that GDB tries to get > frame before pulls breakpoint out of the target. Thing is, breakpoints are supposed to be transparent to memory accesses. Say, as is, a background step + disassemble will see breakpoints instructions. E.g., stepping over this line: while (1); with s& and then "disassemble" would show sss breakpoints. It may actually not be possible to see that today, because: - in native Linux, you can't read memory while the program is running. - with Linux gdbserver, you can, but in the all-stop RSP you can't talk to the server while the program is running... - and with non-stop, on software step targets, we presently force the use of displaced-stepping for all single-steps, so no single-step breakpoints are used... I've been working towards making non-stop not force displaced stepping on sss targets, and I noticed the issue then. With that, I see this: (gdb) set remote Z-packet off (gdb) s& (gdb) disassemble main Dump of assembler code for function main: 0x000000000040049c <+0>: push %rbp 0x000000000040049d <+1>: mov %rsp,%rbp 0x00000000004004a0 <+4>: int3 0x00000000004004a1 <+5>: (bad) End of assembler dump. Instead of the correct: (gdb) disassemble main Dump of assembler code for function main: 0x000000000040049c <+0>: push %rbp 0x000000000040049d <+1>: mov %rsp,%rbp 0x00000000004004a0 <+4>: jmp 0x4004a0 This is actually one thing that my v1 of the recent "fix a bunch of run control bugs" series was fixing, because it made sss breakpoints be regular breakpoints in the breakpoint chain. But I had to drop that in v2. For all kinds of breakpoints breakpoint_xfer_memory hides the breakpoint instructions, but sss breakpoints aren't tracked like all other breakpoints. So instead of making sss breakpoints regular breakpoints, go with a simpler fix (at least for now) -- make breakpoint_xfer_memory take software single-step breakpoints into account. Something like the patch below. After the patch, I get the correct disassemble output. Tested on x86_64 Fedora 17, and also on top of my "use software single-step on x86" series. Does this work for you? ------- Subject: [PATCH] breakpoint shadowing, take single-step breakpoints into account. gdb/ 2014-04-04 Pedro Alves * breakpoint.c (single_step_breakpoints) (single_step_gdbarch): Move up in the file. (one_breakpoint_xfer_memory): New function, factored out from ... (breakpoint_xfer_memory): ... here. Also process single-step breakpoints. --- gdb/breakpoint.c | 186 ++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 117 insertions(+), 69 deletions(-) diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index 19af9df..f777a4a 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -293,6 +293,12 @@ static struct breakpoint_ops bkpt_probe_breakpoint_ops; /* Dynamic printf class type. */ struct breakpoint_ops dprintf_breakpoint_ops; +/* One (or perhaps two) breakpoints used for software single + stepping. */ + +static void *single_step_breakpoints[2]; +static struct gdbarch *single_step_gdbarch[2]; + /* The style in which to perform a dynamic printf. This is a user option because different output options have different tradeoffs; if GDB does the printing, there is better error handling if there @@ -1409,6 +1415,100 @@ bp_location_has_shadow (struct bp_location *bl) return 1; } +/* Update BUF, which is LEN bytes read from the target address + MEMADDR, by replacing a memory breakpoint with its shadowed + contents. + + If READBUF is not NULL, this buffer must not overlap with the of + the breakpoint location's shadow_contents buffer. Otherwise, a + failed assertion internal error will be raised. */ + +static void +one_breakpoint_xfer_memory (gdb_byte *readbuf, gdb_byte *writebuf, + const gdb_byte *writebuf_org, + ULONGEST memaddr, LONGEST len, + struct bp_target_info *target_info, + struct gdbarch *gdbarch) +{ + /* Now do full processing of the found relevant range of elements. */ + CORE_ADDR bp_addr = 0; + int bp_size = 0; + int bptoffset = 0; + + if (!breakpoint_address_match (target_info->placed_address_space, 0, + current_program_space->aspace, 0)) + { + /* The breakpoint is inserted in a different address space. */ + return; + } + + /* Addresses and length of the part of the breakpoint that + we need to copy. */ + bp_addr = target_info->placed_address; + bp_size = target_info->shadow_len; + + if (bp_addr + bp_size <= memaddr) + { + /* The breakpoint is entirely before the chunk of memory we are + reading. */ + return; + } + + if (bp_addr >= memaddr + len) + { + /* The breakpoint is entirely after the chunk of memory we are + reading. */ + return; + } + + /* Offset within shadow_contents. */ + if (bp_addr < memaddr) + { + /* Only copy the second part of the breakpoint. */ + bp_size -= memaddr - bp_addr; + bptoffset = memaddr - bp_addr; + bp_addr = memaddr; + } + + if (bp_addr + bp_size > memaddr + len) + { + /* Only copy the first part of the breakpoint. */ + bp_size -= (bp_addr + bp_size) - (memaddr + len); + } + + if (readbuf != NULL) + { + /* Verify that the readbuf buffer does not overlap with the + shadow_contents buffer. */ + gdb_assert (target_info->shadow_contents >= readbuf + len + || readbuf >= (target_info->shadow_contents + + target_info->shadow_len)); + + /* Update the read buffer with this inserted breakpoint's + shadow. */ + memcpy (readbuf + bp_addr - memaddr, + target_info->shadow_contents + bptoffset, bp_size); + } + else + { + const unsigned char *bp; + CORE_ADDR placed_address = target_info->placed_address; + int placed_size = target_info->placed_size; + + /* Update the shadow with what we want to write to memory. */ + memcpy (target_info->shadow_contents + bptoffset, + writebuf_org + bp_addr - memaddr, bp_size); + + /* Determine appropriate breakpoint contents and size for this + address. */ + bp = gdbarch_breakpoint_from_pc (gdbarch, &placed_address, &placed_size); + + /* Update the final write buffer with this inserted + breakpoint's INSN. */ + memcpy (writebuf + bp_addr - memaddr, bp + bptoffset, bp_size); + } +} + /* Update BUF, which is LEN bytes read from the target address MEMADDR, by replacing any memory breakpoints with their shadowed contents. @@ -1435,6 +1535,7 @@ breakpoint_xfer_memory (gdb_byte *readbuf, gdb_byte *writebuf, /* Left boundary, right boundary and median element of our binary search. */ unsigned bc_l, bc_r, bc; + size_t i; /* Find BC_L which is a leftmost element which may affect BUF content. It is safe to report lower value but a failure to @@ -1508,74 +1609,27 @@ breakpoint_xfer_memory (gdb_byte *readbuf, gdb_byte *writebuf, if (!bp_location_has_shadow (bl)) continue; - if (!breakpoint_address_match (bl->target_info.placed_address_space, 0, - current_program_space->aspace, 0)) - continue; - - /* Addresses and length of the part of the breakpoint that - we need to copy. */ - bp_addr = bl->target_info.placed_address; - bp_size = bl->target_info.shadow_len; - - if (bp_addr + bp_size <= memaddr) - /* The breakpoint is entirely before the chunk of memory we - are reading. */ - continue; - if (bp_addr >= memaddr + len) - /* The breakpoint is entirely after the chunk of memory we are - reading. */ - continue; + one_breakpoint_xfer_memory (readbuf, writebuf, writebuf_org, + memaddr, len, &bl->target_info, bl->gdbarch); + } - /* Offset within shadow_contents. */ - if (bp_addr < memaddr) - { - /* Only copy the second part of the breakpoint. */ - bp_size -= memaddr - bp_addr; - bptoffset = memaddr - bp_addr; - bp_addr = memaddr; - } + /* Now process single-step breakpoints. These are not found in the + bp_location array. */ + for (i = 0; i < 2; i++) + { + struct bp_target_info *bp_tgt = single_step_breakpoints[i]; - if (bp_addr + bp_size > memaddr + len) - { - /* Only copy the first part of the breakpoint. */ - bp_size -= (bp_addr + bp_size) - (memaddr + len); - } + if (bp_tgt != NULL) + { + struct gdbarch *gdbarch = single_step_gdbarch[i]; - if (readbuf != NULL) - { - /* Verify that the readbuf buffer does not overlap with - the shadow_contents buffer. */ - gdb_assert (bl->target_info.shadow_contents >= readbuf + len - || readbuf >= (bl->target_info.shadow_contents - + bl->target_info.shadow_len)); - - /* Update the read buffer with this inserted breakpoint's - shadow. */ - memcpy (readbuf + bp_addr - memaddr, - bl->target_info.shadow_contents + bptoffset, bp_size); - } - else - { - struct gdbarch *gdbarch = bl->gdbarch; - const unsigned char *bp; - CORE_ADDR placed_address = bl->target_info.placed_address; - int placed_size = bl->target_info.placed_size; - - /* Update the shadow with what we want to write to memory. */ - memcpy (bl->target_info.shadow_contents + bptoffset, - writebuf_org + bp_addr - memaddr, bp_size); - - /* Determine appropriate breakpoint contents and size for this - address. */ - bp = gdbarch_breakpoint_from_pc (gdbarch, &placed_address, &placed_size); - - /* Update the final write buffer with this inserted - breakpoint's INSN. */ - memcpy (writebuf + bp_addr - memaddr, bp + bptoffset, bp_size); - } - } + one_breakpoint_xfer_memory (readbuf, writebuf, writebuf_org, + memaddr, len, bp_tgt, gdbarch); + } + } } + /* Return true if BPT is either a software breakpoint or a hardware @@ -15036,12 +15090,6 @@ deprecated_remove_raw_breakpoint (struct gdbarch *gdbarch, void *bp) return ret; } -/* One (or perhaps two) breakpoints used for software single - stepping. */ - -static void *single_step_breakpoints[2]; -static struct gdbarch *single_step_gdbarch[2]; - /* Create and insert a breakpoint for software single step. */ void