From patchwork Wed Aug 19 07:03:34 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kevin Buettner X-Patchwork-Id: 8286 Received: (qmail 63437 invoked by alias); 19 Aug 2015 07:03:40 -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 63428 invoked by uid 89); 19 Aug 2015 07:03:39 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-3.6 required=5.0 tests=AWL, BAYES_00, KAM_LAZY_DOMAIN_SECURITY, RP_MATCHES_RCVD, SPF_HELO_PASS 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 (AES256-GCM-SHA384 encrypted) ESMTPS; Wed, 19 Aug 2015 07:03:37 +0000 Received: from int-mx14.intmail.prod.int.phx2.redhat.com (int-mx14.intmail.prod.int.phx2.redhat.com [10.5.11.27]) by mx1.redhat.com (Postfix) with ESMTPS id AC227345B4A for ; Wed, 19 Aug 2015 07:03:36 +0000 (UTC) Received: from pinnacle.lan ([10.3.113.17]) by int-mx14.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id t7J73atG030253 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA256 bits=256 verify=NO) for ; Wed, 19 Aug 2015 03:03:36 -0400 Date: Wed, 19 Aug 2015 00:03:34 -0700 From: Kevin Buettner To: gdb-patches@sourceware.org Subject: [PATCH 3/8] Break at each iteration for breakpoints placed on a while statement Message-ID: <20150819000334.62f7a867@pinnacle.lan> In-Reply-To: <20150818235334.1afb0c85@pinnacle.lan> References: <20150818235334.1afb0c85@pinnacle.lan> MIME-Version: 1.0 X-IsSubscribed: yes This patch changes create_sals_line_offset() in linespec.c so that, for a given SAL, if that SAL's address (pc) refers to an unconditional branch instruction whose branch target also refers to the same SAL, then the branch target is used for the SAL instead. The pratical effect of this is that a breakpoint placed on a while loop will break at the evaluation of the condition instead of at the unconditional branch which transfers control to the starting address for the evaluation of the condition. Consider the following code snippet (which is taken from one of the new tests for this patch set): 9 while (v < 3) /* Loop 1 condition */ 10 { 11 v++; /* Loop 1 increment */ 12 } This is compiled as the following x86_64 code: 0x000000000040059e : jmp 0x4005af 0x00000000004005a0 : mov 0x200a8a(%rip),%eax # 0x601030 0x00000000004005a6 : add $0x1,%eax 0x00000000004005a9 : mov %eax,0x200a81(%rip) # 0x601030 0x00000000004005af : mov 0x200a7b(%rip),%eax # 0x601030 0x00000000004005b5 : cmp $0x2,%eax 0x00000000004005b8 : jle 0x4005a0 If a breakpoint is placed on line 9, which begins at loop_test+14, this change/patch causes the breakpoint to be placed on loop_test+31, which is the starting address for the evaluation of the condition. In order for this to work, an architecture specific method, unconditional_branch_address, was introduced in an earlier patch in the set. I've implemented this method for x86_64, i386, arm, thumb, powerpc, rx, and rl78. I've tested on each of these architectures and see no regressions. gdb/ChangeLog: * linespec.c (addr_in_sals): New function. (create_sals_line_offset): Adjust SAL whose pc refers to an unconditional branch whose target is the same line. --- gdb/linespec.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/gdb/linespec.c b/gdb/linespec.c index 00fa4ba..2e0146d 100644 --- a/gdb/linespec.c +++ b/gdb/linespec.c @@ -1808,6 +1808,29 @@ canonicalize_linespec (struct linespec_state *state, const linespec_p ls) } } +/* Return 1 if one of the SALS between 0 and NELTS contains ADDR. + Return 0 otherwise. */ + +static int +addr_in_sals (CORE_ADDR addr, int nelts, struct symtab_and_line *sals) +{ + int i; + + for (i = 0; i < nelts; i++) + { + struct symtab_and_line sal; + + if (sals[i].end == 0) + sal = find_pc_sect_line (sals[i].pc, sals[i].section, 0); + else + sal = sals[i]; + + if (sal.pc <= addr && addr < sal.end) + return 1; + } + return 0; +} + /* Given a line offset in LS, construct the relevant SALs. */ static struct symtabs_and_lines @@ -1933,6 +1956,18 @@ create_sals_line_offset (struct linespec_state *self, struct symbol *sym = (blocks[i] ? block_containing_function (blocks[i]) : NULL); + CORE_ADDR branch_addr = gdbarch_unconditional_branch_address + (get_current_arch (), intermediate_results.sals[i].pc); + + /* Only use branch if it's in the same block and is also + within one of the sals from the initial list. */ + if (branch_addr != 0 && blocks[i]->startaddr <= branch_addr + && branch_addr < blocks[i]->endaddr + && addr_in_sals (branch_addr, intermediate_results.nelts, + intermediate_results.sals)) + { + intermediate_results.sals[i].pc = branch_addr; + } if (self->funfirstline) skip_prologue_sal (&intermediate_results.sals[i]);