From: Pedro Alves <palves@redhat.com>
To: Kevin Buettner <kevinb@redhat.com>, gdb-patches@sourceware.org
Subject: Re: [PATCH 3/8] Break at each iteration for breakpoints placed on a while statement
Date: Wed, 30 Sep 2015 12:17:00 -0000 [thread overview]
Message-ID: <560BD2B7.9010706@redhat.com> (raw)
In-Reply-To: <20150917185751.22fe2937@pinnacle.lan>
Hi Kevin,
Sorry for the delay.
On 09/18/2015 02:57 AM, Kevin Buettner wrote:
> If I place a breakpoint on the Loop 5 line, it ends up on on 0x4005cc,
> which is a nop. It appears that gcc has rewritten this code so that
> the the comparison comes first, which exactly the opposite of what
> happens when one writes a while loop.
>
> The presence of the nop means that things work as expected when we
> place a breakpoint on that line. It will stop just once on the
> statement instead of once for each time through the loop.
>
> This was an interesting exercise, but it doesn't really answer the
> question of what would happen if gcc would instead place an
> actual branch at the beginning. I would expect my patch
> to cause the breakpoint to be placed within the loop instead
> of at the beginning of the statement. I don't think this is
> desirable, but I can't think of a way (within the current work) to
> stop it from happening.
Yeah, me neither. This is always going to be brittle. :-/
Really the best would be DWARF is_stmt.
>
> Here's the new patch:
>
> Break at each iteration for breakpoints placed on a while statement.
>
> 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
"practical"
> 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 <loop_test+14>: jmp 0x4005af <loop_test+31>
> 0x00000000004005a0 <loop_test+16>: mov 0x200a8a(%rip),%eax # 0x601030 <v>
> 0x00000000004005a6 <loop_test+22>: add $0x1,%eax
> 0x00000000004005a9 <loop_test+25>: mov %eax,0x200a81(%rip) # 0x601030 <v>
> 0x00000000004005af <loop_test+31>: mov 0x200a7b(%rip),%eax # 0x601030 <v>
> 0x00000000004005b5 <loop_test+37>: cmp $0x2,%eax
> 0x00000000004005b8 <loop_test+40>: jle 0x4005a0 <loop_test+16>
>
> 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_destination, 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 destination is the same line.
> ---
> gdb/linespec.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 76 insertions(+)
>
> diff --git a/gdb/linespec.c b/gdb/linespec.c
> index 4c29c12..4b5cde9 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,59 @@ create_sals_line_offset (struct linespec_state *self,
> struct symbol *sym = (blocks[i]
> ? block_containing_function (blocks[i])
> : NULL);
> + int is_branch;
> + CORE_ADDR branch_dest;
> +
> + /* This next bit of code examines the instruction at the
> + SAL's address (pc). If the instruction is an
> + unconditional branch whose branch destination also
> + refers to the same SAL, then the branch destination is
> + used for the SAL's pc value instead.
> +
> + The pratical effect of this is that a breakpoint placed
"practical".
> + on a while loop will break at the evaluation of the
> + condition instead of at an unconditional branch which
> + transfers control to the starting address for the
> + evaluation of the condition.
> +
> + Consider the following code snippet (which is taken
> + from the test case for gdb.base/loop-break.exp.)
> +
> + while (v < 3)
> + {
> + v++;
> + }
> +
> + On x86_64, this might be compiled as follows:
> +
> + 0x40059e <loop_test+14>: jmp 0x4005af <loop_test+31>
> + 0x4005a0 <loop_test+16>: mov 0x200a8a(%rip),%eax
> + 0x4005a6 <loop_test+22>: add $0x1,%eax
> + 0x4005a9 <loop_test+25>: mov %eax,0x200a81(%rip)
> + 0x4005af <loop_test+31>: mov 0x200a7b(%rip),%eax
> + 0x4005b5 <loop_test+37>: cmp $0x2,%eax
> + 0x4005b8 <loop_test+40>: jle 0x4005a0 <loop_test+16>
> +
> + If a breakpoint is placed on the while statement line
> + which begins at loop_test+14, the following code causes
> + the breakpoint to be (instead) placed on loop_test+31, which
> + is the starting address for the evaluation of the condition. */
> +
> + is_branch = gdbarch_unconditional_branch_destination
> + (get_objfile_arch
> + (SYMTAB_OBJFILE (intermediate_results.sals[i].symtab)),
> + intermediate_results.sals[i].pc,
> + &branch_dest);
> +
> + /* Only use branch destination if it's in the same block and
> + is also within one of the sals from the initial list. */
> + if (is_branch && blocks[i]->startaddr <= branch_dest
> + && branch_dest < blocks[i]->endaddr
> + && addr_in_sals (branch_dest, intermediate_results.nelts,
> + intermediate_results.sals))
I believe intermediate_results can contain sals of different
pspaces / inferiors. Shouldn't we take that into account somehow?
> + {
> + intermediate_results.sals[i].pc = branch_dest;
> + }
Unnecessary braces.
>
> if (self->funfirstline)
> skip_prologue_sal (&intermediate_results.sals[i]);
>
Thanks,
Pedro Alves
next prev parent reply other threads:[~2015-09-30 12:17 UTC|newest]
Thread overview: 36+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-08-19 6:53 [PATCH 0/8] " Kevin Buettner
2015-08-19 6:58 ` [PATCH 1/8] Add new test, gdb.base/loop-break.exp Kevin Buettner
2015-08-25 12:10 ` Pedro Alves
2015-09-18 0:50 ` Kevin Buettner
2016-02-01 20:00 ` Kevin Buettner
2016-02-15 16:51 ` Kevin Buettner
2016-02-29 16:17 ` Kevin Buettner
2015-09-22 0:11 ` Kevin Buettner
2015-08-19 7:00 ` [PATCH 2/8] Add new gdbarch method, unconditional_branch_address Kevin Buettner
2015-08-25 12:13 ` Pedro Alves
2015-09-18 1:14 ` Kevin Buettner
2015-09-18 12:02 ` Andrew Burgess
2015-09-18 12:06 ` Andrew Burgess
2015-09-18 12:26 ` Kevin Buettner
2015-09-18 12:24 ` Kevin Buettner
2015-09-22 16:09 ` Yao Qi
2015-09-22 18:03 ` Kevin Buettner
2015-08-19 7:03 ` [PATCH 3/8] Break at each iteration for breakpoints placed on a while statement Kevin Buettner
2015-08-25 12:10 ` Pedro Alves
2015-09-18 1:57 ` Kevin Buettner
2015-09-30 12:17 ` Pedro Alves [this message]
2015-10-01 1:13 ` Kevin Buettner
2015-10-01 4:09 ` Doug Evans
2015-08-19 7:06 ` [PATCH 4/8] Implement unconditional_branch_address method for x86-64 and i386 Kevin Buettner
2015-09-18 2:03 ` Kevin Buettner
2015-08-19 7:08 ` [PATCH 5/8] Implement unconditional_branch_address method for arm and thumb Kevin Buettner
2015-08-19 7:11 ` [PATCH 6/8] Implement unconditional_branch_address method for powerpc / rs6000 Kevin Buettner
2015-08-19 7:13 ` [PATCH 7/8] Implement unconditional_branch_address method for rl78 Kevin Buettner
2015-08-19 7:15 ` [PATCH 8/8] Implement unconditional_branch_address method for rx Kevin Buettner
2016-01-18 16:48 ` [PATCH 0/8] Break at each iteration for breakpoints placed on a while statement Kevin Buettner
2016-04-04 15:56 ` Yao Qi
2016-04-14 16:31 ` Luis Machado
2016-04-15 11:59 ` Yao Qi
2016-04-15 19:48 ` Kevin Buettner
2016-04-15 22:34 ` Pedro Alves
2016-04-19 16:24 ` Kevin Buettner
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=560BD2B7.9010706@redhat.com \
--to=palves@redhat.com \
--cc=gdb-patches@sourceware.org \
--cc=kevinb@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox