* [RFC] PR 15075 dprintf interferes with "next"
@ 2013-02-18 13:09 Yao Qi
2013-02-18 21:36 ` Joel Brobecker
` (3 more replies)
0 siblings, 4 replies; 45+ messages in thread
From: Yao Qi @ 2013-02-18 13:09 UTC (permalink / raw)
To: gdb-patches
Hi,
I'd like to get your comments on this patch, as I think my patch is
hacky but I am unable to figure out a correct one. This patch fixes more
problems than PR 15075 mentioned, they are,
- When step a source line by "next" command, and there is a dprintf
on that line, "next" command will behave like "continue".
- Two dprintf are set on the same address. Only one printf is
executed.
- dprintf and regular breakpoint are set on the same address,
inferior doesn't stop.
In order to fix these problems, I don't append "continue" command to
dprintf breakpoint, and after all commands of all breakpoints (caused
the stop) are executed, execute "continue" command if
1) the inferior is not proceeded by these commands
2) and the stop is only caused by dprintf (no other types of
breakpoint)
3) the inferior is not in the state of stepping a source line or
an instruction (to fix PR 15075).
My patch fixes all the three known problems, but I think it is still
hacky.
The printf stuff is implemented as command, it is convenient to move
them to the target side. I tried to change the bpstat saying that
"don't stop", but the command can't be executed. We have to keep
bpstat saying that "stop" for dprintf. I also thought about Tom's
suggestion about Python "Breakpoint.stop" API, but "Breakpoint.stop"
acts as condition instead of command, so I don't go that way.
Known issue: from the user's perspective, inferior stops at the dprintf
breakpoint if dprintf breakpoint and regular breakpoint are set at
the same address. I'll fix it if my patch is on the right track.
gdb:
2013-02-18 Yao Qi <yao@codesourcery.com>
* breakpoint.c (bpstat_do_actions_1): Change argument from
"bpstat *" to "struc thread_info *".
(bpstat_do_actions_1): Execute "continue" command if BS has
dprintf breakpoint only.
(bpstat_do_actions): Caller update.
(update_dprintf_command_list): Don't append "continue" command
to the command of dprintf breakpoint.
---
gdb/breakpoint.c | 68 ++++++++++++++++++++++++++++++++++++++---------------
1 files changed, 49 insertions(+), 19 deletions(-)
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index fb57a57..878ab08 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -4263,20 +4263,26 @@ command_line_is_silent (struct command_line *cmd)
}
/* Execute all the commands associated with all the breakpoints at
- this location. Any of these commands could cause the process to
- proceed beyond this point, etc. We look out for such changes by
- checking the global "breakpoint_proceeded" after each command.
+ the location where THREAD stops. Any of these commands could cause
+ the process to proceed beyond this point, etc. We look out for
+ such changes by checking the global "breakpoint_proceeded" after
+ each command.
Returns true if a breakpoint command resumed the inferior. In that
case, it is the caller's responsibility to recall it again with the
bpstat of the current thread. */
static int
-bpstat_do_actions_1 (bpstat *bsp)
+bpstat_do_actions_1 (struct thread_info *thread)
{
+ bpstat *bsp = &thread->control.stop_bpstat;
bpstat bs;
struct cleanup *old_chain;
int again = 0;
+ /* Breakpoint dprintf in list BS. */
+ int bkpt_dprintf = 0;
+ /* Breakpoint other than dprintf in list BS. */
+ int bkpt_other_than_dprintf = 0;
/* Avoid endless recursion if a `source' command is contained
in bs->commands. */
@@ -4298,6 +4304,13 @@ bpstat_do_actions_1 (bpstat *bsp)
struct command_line *cmd;
struct cleanup *this_cmd_tree_chain;
+ if (bs->breakpoint_at != NULL)
+ {
+ if (bs->breakpoint_at->type == bp_dprintf)
+ bkpt_dprintf = 1;
+ else
+ bkpt_other_than_dprintf = 1;
+ }
/* Take ownership of the BSP's command tree, if it has one.
The command tree could legitimately contain commands like
@@ -4356,6 +4369,33 @@ bpstat_do_actions_1 (bpstat *bsp)
break;
}
}
+
+ /* Inferior is not proceed by commands. */
+ if (!breakpoint_proceeded
+ /* No breakpoint of type other than dprintf. If there is
+ breakpoint of other types in BS, the inferior really needs
+ stopped. Don't execute command "continue". */
+ && !bkpt_other_than_dprintf && bkpt_dprintf
+ && (0 != strcmp (dprintf_style, dprintf_style_agent))
+ /* GDB is not stepping a line. When GDB is stepping a source
+ line, don't execute command "continue", otherwise "next" will
+ behave like "continue", which is not expected. */
+ && !(thread->control.step_range_start >= 1
+ && thread->control.step_range_end >= 1))
+ {
+ struct command_line *cont_cmd_line
+ = xmalloc (sizeof (struct command_line));
+
+ cont_cmd_line->control_type = simple_control;
+ cont_cmd_line->body_count = 0;
+ cont_cmd_line->body_list = NULL;
+ cont_cmd_line->next = NULL;
+ cont_cmd_line->line = xstrdup ("continue");;
+
+ execute_control_command (cont_cmd_line);
+ if (!target_can_async_p ())
+ again = 1;
+ }
do_cleanups (old_chain);
return again;
}
@@ -4374,7 +4414,7 @@ bpstat_do_actions (void)
and only return when it is stopped at the next breakpoint, we
keep doing breakpoint actions until it returns false to
indicate the inferior was not resumed. */
- if (!bpstat_do_actions_1 (&inferior_thread ()->control.stop_bpstat))
+ if (!bpstat_do_actions_1 (inferior_thread ()))
break;
discard_cleanups (cleanup_if_error);
@@ -8947,25 +8987,15 @@ update_dprintf_command_list (struct breakpoint *b)
_("Invalid dprintf style."));
gdb_assert (printf_line != NULL);
- /* Manufacture a printf/continue sequence. */
+ /* Manufacture a printf command. */
{
- struct command_line *printf_cmd_line, *cont_cmd_line = NULL;
-
- if (strcmp (dprintf_style, dprintf_style_agent) != 0)
- {
- cont_cmd_line = xmalloc (sizeof (struct command_line));
- cont_cmd_line->control_type = simple_control;
- cont_cmd_line->body_count = 0;
- cont_cmd_line->body_list = NULL;
- cont_cmd_line->next = NULL;
- cont_cmd_line->line = xstrdup ("continue");
- }
+ struct command_line *printf_cmd_line
+ = xmalloc (sizeof (struct command_line));
- printf_cmd_line = xmalloc (sizeof (struct command_line));
printf_cmd_line->control_type = simple_control;
printf_cmd_line->body_count = 0;
printf_cmd_line->body_list = NULL;
- printf_cmd_line->next = cont_cmd_line;
+ printf_cmd_line->next = NULL;
printf_cmd_line->line = printf_line;
breakpoint_set_commands (b, printf_cmd_line);
--
1.7.7.6
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [RFC] PR 15075 dprintf interferes with "next"
2013-02-18 13:09 [RFC] PR 15075 dprintf interferes with "next" Yao Qi
@ 2013-02-18 21:36 ` Joel Brobecker
2013-02-21 16:36 ` Tom Tromey
` (2 subsequent siblings)
3 siblings, 0 replies; 45+ messages in thread
From: Joel Brobecker @ 2013-02-18 21:36 UTC (permalink / raw)
To: Yao Qi; +Cc: gdb-patches
> I'd like to get your comments on this patch, as I think my patch is
> hacky but I am unable to figure out a correct one. This patch fixes more
> problems than PR 15075 mentioned, they are,
>
> - When step a source line by "next" command, and there is a dprintf
> on that line, "next" command will behave like "continue".
> - Two dprintf are set on the same address. Only one printf is
> executed.
> - dprintf and regular breakpoint are set on the same address,
> inferior doesn't stop.
>
> In order to fix these problems, I don't append "continue" command to
> dprintf breakpoint, and after all commands of all breakpoints (caused
> the stop) are executed, execute "continue" command if
> 1) the inferior is not proceeded by these commands
> 2) and the stop is only caused by dprintf (no other types of
> breakpoint)
> 3) the inferior is not in the state of stepping a source line or
> an instruction (to fix PR 15075).
>
> My patch fixes all the three known problems, but I think it is still
> hacky.
My first reaction is that we'd better just byte the bullet, and
implement this properly. In my opinion, something at the infrun/
handle_inferior_event level... Pedro is a specialist of the dreaded
handle_inferior_event function, so he might have a more precise
suggestion.
Interestingly enough, I did point out these limitations, but we still
went ahead, as we thought that the feature would be useful...
--
Joel
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [RFC] PR 15075 dprintf interferes with "next"
2013-02-18 13:09 [RFC] PR 15075 dprintf interferes with "next" Yao Qi
2013-02-18 21:36 ` Joel Brobecker
@ 2013-02-21 16:36 ` Tom Tromey
2013-04-24 1:24 ` Hui Zhu
2013-02-22 17:39 ` DPrintf feedback (was: [RFC] PR 15075 dprintf interferes with "next") Marc Khouzam
2013-02-28 15:32 ` [PATCH 1/4] Fix dprintf bugs Yao Qi
3 siblings, 1 reply; 45+ messages in thread
From: Tom Tromey @ 2013-02-21 16:36 UTC (permalink / raw)
To: Yao Qi; +Cc: gdb-patches
>>>>> "Yao" == Yao Qi <yao@codesourcery.com> writes:
Yao> The printf stuff is implemented as command, it is convenient to move
Yao> them to the target side. I tried to change the bpstat saying that
Yao> "don't stop", but the command can't be executed. We have to keep
Yao> bpstat saying that "stop" for dprintf. I also thought about Tom's
Yao> suggestion about Python "Breakpoint.stop" API, but "Breakpoint.stop"
Yao> acts as condition instead of command, so I don't go that way.
Pedro pointed out that 'stop' runs too early -- it makes "cond" not work
on a dprintf. (BTW if there is no test for this, there should be... )
But, why not just do the work just after the condition is evaluated?
For example, it could be done with special handling in
bpstat_check_breakpoint_conditions, or by introducing a new
check_condition breakpoint_ops method, with the dprintf method calling
the super method before proceeding to "printf" and then returning 0.
I tend to think that the "commands" approach is just not a good one.
Tom
^ permalink raw reply [flat|nested] 45+ messages in thread
* DPrintf feedback (was: [RFC] PR 15075 dprintf interferes with "next")
2013-02-18 13:09 [RFC] PR 15075 dprintf interferes with "next" Yao Qi
2013-02-18 21:36 ` Joel Brobecker
2013-02-21 16:36 ` Tom Tromey
@ 2013-02-22 17:39 ` Marc Khouzam
2013-02-22 19:32 ` DPrintf feedback Tom Tromey
2013-02-28 15:32 ` [PATCH 1/4] Fix dprintf bugs Yao Qi
3 siblings, 1 reply; 45+ messages in thread
From: Marc Khouzam @ 2013-02-22 17:39 UTC (permalink / raw)
To: 'Yao Qi', 'gdb-patches@sourceware.org'
Cc: 'tromey@redhat.com', 'Pedro Alves',
'Joel Brobecker', 'Stan Shebs'
Hi,
Yao posting a patch for dprintf was good timing.
I've been working on integrating the dprintf feature
into Eclipse and I ran into some issues.
I think the main point to discuss is the fact that
dprintf use breakpoint commands. This has been put in question,
a couple of times on the mailing list I believe. An impact
of that approach is that although in CLI, dprintf are silent
breakpoints, they don't seem to be in MI. When I put a dprintf
in a loop and run over it, I get a bunch of *stopped/*running
events and =breakpoint-modified events.
I'm not sure how I feel about the =break-modified event just yet
and your expert opinion would be appreciated. However, the
*stopped/*running events seem like they shouldn't be there.
They cause a lot of un-needed communication between Eclipse and GDB.
This gives me the feeling that it would be better to have dprintf
behave like an active tracepoint instead of a breakpoint. I believe
Joel had suggested that at one point.
Such an approach may also help fix the "continue" problem
that Yao is trying to address. I seem to recall that Hui had posted
patches to add some kind of 'printf' tracepoint command. Maybe that
would be something that can help?
Also, as pointed out by Pedro, the user is able to modify the
dprintf breakpoint commands, which can suddenly turn a dprintf
into something else, although GDB still has it tagged as 'dprintf'.
The fact that GDB has a new type 'dprintf', implies that dprintf
should keep their 'dprintf' properties, and not be turned into
a standard bp.
Other issues I ran across are below. I wasn't sure opening PRs was
the way to do since those issues may disappear if the current
implementation is amended:
- If I set a condition on a dprintf, things don't behave right.
When the condition is false, the printout is not shown, but the
dprintf causes the inferior to stop and not continue.
- Setting the dprintf-style to 'agent' for a local session defaults
to 'gdb' style, but the 'continue' command is not added in that
case (easy to fix)
- Pagination is triggered for dprintf in CLI mode, at least when
using dprintf-style 'gdb'. I think this is a problem because:
a) when pagination is triggered, inferior execution will be
interrupted until the user answers the pagination prompt
b) pagination is triggered by the dprintf but not by real
inferior output. So, as dprintf and inferior printouts
appear interleaved on the screen, the pagination prompt
will be triggered when the dprintfs add up to too many,
which will seem random to the user, since the other
printouts are also visible.
- In Eclipse, the dprintf-style that makes sense is either
'call' or 'agent'. 'call' will call 'printf' in the inferior.
With GDB 7.5, GDB cannot call an inferior method on Ubuntu,
which is a serious limitation for eclipse/dprintf.
http://sourceware.org/ml/gdb-patches/2012-07/msg00037.html
- Updating the dprintf-style to 'agent' for existing dprintfs
will cause: "May only run agent-printf on the target" when
it is time to print.
- The fact that there is no expression checking on the validity
of the dprintf string can be a user-friendliness problem
- Output buffering is not behaving as a real printf. For
example, if my program does
printf("hello");
printf("friend\n");
and I put a dprintf " my " on the second line,
I would expect to see
"hello my friend"
but instead I see
" my hellofriend"
which shows that the dprintf string does not go to the same
buffer as the real printfs, and is flushed earlier.
This also happens with the dprintf-style "agent"
Thanks
Marc
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: DPrintf feedback
2013-02-22 17:39 ` DPrintf feedback (was: [RFC] PR 15075 dprintf interferes with "next") Marc Khouzam
@ 2013-02-22 19:32 ` Tom Tromey
2013-02-22 20:37 ` Marc Khouzam
0 siblings, 1 reply; 45+ messages in thread
From: Tom Tromey @ 2013-02-22 19:32 UTC (permalink / raw)
To: Marc Khouzam
Cc: 'Yao Qi', 'gdb-patches@sourceware.org',
'Pedro Alves', 'Joel Brobecker',
'Stan Shebs'
>>>>> "Marc" == Marc Khouzam <marc.khouzam@ericsson.com> writes:
Marc> Such an approach may also help fix the "continue" problem
Marc> that Yao is trying to address. I seem to recall that Hui had posted
Marc> patches to add some kind of 'printf' tracepoint command. Maybe that
Marc> would be something that can help?
I thought this was subsumed by "set dprintf-style agent"?
Marc> Other issues I ran across are below. I wasn't sure opening PRs was
Marc> the way to do since those issues may disappear if the current
Marc> implementation is amended:
I think it is best to file PRs. If a patch fixes them all, then that is
fine. But if not, then this the only way to avoid losing track.
Marc> - Pagination is triggered for dprintf in CLI mode, at least when
Marc> using dprintf-style 'gdb'.
Maybe we need a new "gdb-unfiltered" setting? Or we could disable
pagination entirely here, but that maybe leads to other issues.
Marc> - In Eclipse, the dprintf-style that makes sense is either
Marc> 'call' or 'agent'.
I was surprised to hear this. Could you say why?
Marc> - Output buffering is not behaving as a real printf. For
Marc> example, if my program does
Marc> printf("hello");
Marc> printf("friend\n");
Marc> and I put a dprintf " my " on the second line,
Marc> I would expect to see
Marc> "hello my friend"
Marc> but instead I see
Marc> " my hellofriend"
Marc> which shows that the dprintf string does not go to the same
Marc> buffer as the real printfs, and is flushed earlier.
Marc> This also happens with the dprintf-style "agent"
Which other setting does this happen with?
I would expect it to work with "call" but not with "gdb".
You could hack around this by disabling buffering for stdout.
I'm not totally sure it is a bug for it to work the current way by
default.
Tom
^ permalink raw reply [flat|nested] 45+ messages in thread
* RE: DPrintf feedback
2013-02-22 19:32 ` DPrintf feedback Tom Tromey
@ 2013-02-22 20:37 ` Marc Khouzam
2013-02-26 21:12 ` Marc Khouzam
0 siblings, 1 reply; 45+ messages in thread
From: Marc Khouzam @ 2013-02-22 20:37 UTC (permalink / raw)
To: 'Tom Tromey'
Cc: 'Yao Qi', 'gdb-patches@sourceware.org',
'Pedro Alves', 'Joel Brobecker',
'Stan Shebs'
> -----Original Message-----
> From: Tom Tromey [mailto:tromey@redhat.com]
> Sent: Friday, February 22, 2013 2:32 PM
> To: Marc Khouzam
> Cc: 'Yao Qi'; 'gdb-patches@sourceware.org'; 'Pedro Alves';
> 'Joel Brobecker'; 'Stan Shebs'
> Subject: Re: DPrintf feedback
>
> >>>>> "Marc" == Marc Khouzam <marc.khouzam@ericsson.com> writes:
>
> Marc> Such an approach may also help fix the "continue" problem
> Marc> that Yao is trying to address. I seem to recall that
> Hui had posted
> Marc> patches to add some kind of 'printf' tracepoint
> command. Maybe that
> Marc> would be something that can help?
>
> I thought this was subsumed by "set dprintf-style agent"?
I haven't followed the details, so I can't be sure.
"set dprintf-style agent" makes the dprintf breakpoint
command be "agent-printf <string>".
I didn't expect that to be something that could be re-used
by a tracepoint command. But that makes me realize the
bigger limitation of using tracepoints; tracepoints are
only supported with gdbserver. I thought a tracepoint
doing the printf would be nice for each case, not just
with gdbserver. I guess there's a lot more work
needed to first support tracepoints in GDB alone, and
then use them for dprintf. I missed that detail.
I wonder if you guys feel tracepoints would be a nicer
way to handle dprintf?
> Marc> Other issues I ran across are below. I wasn't sure
> opening PRs was
> Marc> the way to do since those issues may disappear if the current
> Marc> implementation is amended:
>
> I think it is best to file PRs. If a patch fixes them all,
> then that is
> fine. But if not, then this the only way to avoid losing track.
Will do.
> Marc> - Pagination is triggered for dprintf in CLI mode, at least when
> Marc> using dprintf-style 'gdb'.
>
> Maybe we need a new "gdb-unfiltered" setting? Or we could disable
> pagination entirely here, but that maybe leads to other issues.
>
> Marc> - In Eclipse, the dprintf-style that makes sense is either
> Marc> 'call' or 'agent'.
>
> I was surprised to hear this. Could you say why?
On Linux, Eclipse uses the -inferior-tty-set command to tell GDB
to send the inferior's output to a different console. So we have
a gdb console and an inferior console. If we want dprintf to look
like a real printf, its output needs to be shown in the inferior
console, so it requires GDB to send it to the same tty. That is
not what "dprintf-style gdb" does, as it sends it to the gdb console.
> Marc> - Output buffering is not behaving as a real printf. For
> Marc> example, if my program does
> Marc> printf("hello");
> Marc> printf("friend\n");
> Marc> and I put a dprintf " my " on the second line,
> Marc> I would expect to see
> Marc> "hello my friend"
> Marc> but instead I see
> Marc> " my hellofriend"
> Marc> which shows that the dprintf string does not go to the same
> Marc> buffer as the real printfs, and is flushed earlier.
> Marc> This also happens with the dprintf-style "agent"
>
> Which other setting does this happen with?
> I would expect it to work with "call" but not with "gdb".
>
> You could hack around this by disabling buffering for stdout.
> I'm not totally sure it is a bug for it to work the current way by
> default.
I hadn't tried it with "call" because my machine is an Ubuntu,
so the "call" setting does not work. I managed to get my hands
on a Suse machine and tried it; you are right, "call" prints
things nicely. I guess the problem is only that "agent" style
does not do that properly. I'll specify this important point
in the PR.
Thanks for the quick answer.
Marc
^ permalink raw reply [flat|nested] 45+ messages in thread
* RE: DPrintf feedback
2013-02-22 20:37 ` Marc Khouzam
@ 2013-02-26 21:12 ` Marc Khouzam
0 siblings, 0 replies; 45+ messages in thread
From: Marc Khouzam @ 2013-02-26 21:12 UTC (permalink / raw)
To: 'gdb-patches@sourceware.org'
Cc: 'Yao Qi', 'Tom Tromey', 'Pedro Alves',
'Joel Brobecker', 'Stan Shebs'
> > I think it is best to file PRs. If a patch fixes them all,
> > then that is
> > fine. But if not, then this the only way to avoid losing track.
>
> Will do.
I've opened the following 8 PRs for tracking:
http://sourceware.org/bugzilla/show_bug.cgi?id=15181
Missing continue on dprintf that defaults to "gdb" style from "agent"
http://sourceware.org/bugzilla/show_bug.cgi?id=15186
Agent style dprintf does not buffer output properly
http://sourceware.org/bugzilla/show_bug.cgi?id=15182
Pagination is triggered for dprintf
http://sourceware.org/bugzilla/show_bug.cgi?id=15187
Dprintf does not work for Eclipse on Ubuntu
http://sourceware.org/bugzilla/show_bug.cgi?id=15179
Dprintf interrupts execution when condition is false
http://sourceware.org/bugzilla/show_bug.cgi?id=15184
Cannot change dprintf style to agent for existing dprintfs
http://sourceware.org/bugzilla/show_bug.cgi?id=15180
Agent style dprintf does not respect conditions
http://sourceware.org/bugzilla/show_bug.cgi?id=15185
Dprintf should parse its string for validity right away
BR,
Marc
^ permalink raw reply [flat|nested] 45+ messages in thread
* [PATCH 3/4] Test dprintf breakpoint works correctly with other breakpoints
2013-02-28 15:32 ` [PATCH 1/4] Fix dprintf bugs Yao Qi
@ 2013-02-28 13:17 ` Yao Qi
2013-02-28 13:17 ` [PATCH 2/4] Test case of conditional dprintf Yao Qi
` (3 subsequent siblings)
4 siblings, 0 replies; 45+ messages in thread
From: Yao Qi @ 2013-02-28 13:17 UTC (permalink / raw)
To: gdb-patches
gdb/testsuite:
2013-02-28 Yao Qi <yao@codesourcery.com>
* gdb.base/dprintf.exp: Test dprintf breakpoints works correctly
with other breakpoints setting on the same address.
---
gdb/testsuite/gdb.base/dprintf.exp | 49 ++++++++++++++++++++++++++++++-----
1 files changed, 42 insertions(+), 7 deletions(-)
diff --git a/gdb/testsuite/gdb.base/dprintf.exp b/gdb/testsuite/gdb.base/dprintf.exp
index ffbd3f2..22c740a 100644
--- a/gdb/testsuite/gdb.base/dprintf.exp
+++ b/gdb/testsuite/gdb.base/dprintf.exp
@@ -40,8 +40,11 @@ gdb_breakpoint "main"
gdb_test "dprintf foo,\"At foo entry\\n\"" \
"Dprintf .*"
+# Set two dprintf breakpoints at the same location.
gdb_test "dprintf $dp_location1,\"arg=%d, g=%d\\n\", arg, g" \
- "Dprintf .*"
+ "Dprintf .*"
+gdb_test "dprintf $dp_location1,\"g=%d, arg=%d\\n\", g, arg" \
+ "Dprintf .*"
gdb_test_sequence "info breakpoints" "dprintf info 1" {
"\[\r\n\]Num Type Disp Enb Address +What"
@@ -50,6 +53,8 @@ gdb_test_sequence "info breakpoints" "dprintf info 1" {
"\[\r\n\] printf \"At foo entry\\\\n\""
"\[\r\n\]4 dprintf"
"\[\r\n\] printf \"arg=%d, g=%d\\\\n\", arg, g"
+ "\[\r\n\]5 dprintf"
+ "\[\r\n\] printf \"g=%d, arg=%d\\\\n\", g, arg"
}
gdb_test "break $bp_location1" \
@@ -76,22 +81,52 @@ if ![target_info exists gdb,noinferiorio] {
gdb_test "" "Breakpoint"
- gdb_test "continue" "At foo entry.*arg=1234, g=1234.*" "1st dprintf, call"
+ # Test two dprintf breakpoints on the same location are executed.
+ gdb_test "continue" \
+ "At foo entry.*arg=1234, g=1234\\r\\n.*g=1234, arg=1234\\r\\n.*" \
+ "1st dprintf, call"
- gdb_test "continue" "At foo entry.*arg=1235, g=2222.*" "2nd dprintf, call"
+ gdb_test "continue" \
+ "At foo entry.*arg=1235, g=2222\\r\\n.*g=2222, arg=1235\\r\\n.*" \
+ "2nd dprintf, call"
gdb_test_no_output "set dprintf-function fprintf" "Set dprintf function"
gdb_test_no_output "set dprintf-channel stderr" "Set dprintf channel"
+ # Set breakpoint on foo, and test dprintf set at the same address
+ # behaves correctly.
+ gdb_test "break foo" "Note: breakpoint ${decimal} also set at pc ${hex}.*"
+ gdb_test_no_output "set \$foo_breakpoint_number = \$bpnum"
+ # Hit the breakpoint on foo, and the command of dprintf
+ # breakpoint on foo is executed as well.
+ gdb_test "continue" \
+ "Continuing\.\\r\\nAt foo entry\\r.*Breakpoint .*" \
+ "continue"
+ gdb_test "delete \$foo_breakpoint_number"
+
gdb_run_cmd
gdb_test "" "Breakpoint"
- gdb_test "continue" "At foo entry.*arg=1234, g=1234.*" \
+ gdb_test "continue" \
+ "At foo entry.*arg=1234, g=1234\\r\\n.*g=1234, arg=1234\\r\\n.*" \
"1st dprintf, fprintf"
- gdb_test "continue" "At foo entry.*arg=1235, g=2222.*" \
+ gdb_test "continue" \
+ "At foo entry.*arg=1235, g=2222\\r\\n.*g=2222, arg=1235\\r\\n.*" \
"2nd dprintf, fprintf"
+
+ gdb_test_sequence "info breakpoints" "dprintf info 2" {
+ "\[\r\n\]Num Type Disp Enb Address +What"
+ "\[\r\n\]2 breakpoint"
+ "\[\r\n\]\tbreakpoint already hit 1 time"
+ "\[\r\n\]3 dprintf"
+ "\[\r\n\]\tbreakpoint already hit 2 times"
+ "\[\r\n\] call \\(void\\\) fprintf \\(stderr,\"At foo entry\\\\n\"\\)"
+ "\[\r\n\]4 dprintf"
+ "\[\r\n\]\tbreakpoint already hit 2 times"
+ "\[\r\n\] call \\(void\\) fprintf \\(stderr,\"arg=%d, g=%d\\\\n\", arg, g\\)"
+ }
}
set target_can_dprintf 1
@@ -116,8 +151,8 @@ if $target_can_dprintf {
gdb_test "continue" "Breakpoint \[0-9\]+, foo .*" "2nd dprintf, agent"
- gdb_test_sequence "info breakpoints" "dprintf info 2" {
- "\[\r\n\]Num Type Disp Enb Address What"
+ gdb_test_sequence "info breakpoints" "dprintf info 3" {
+ "\[\r\n\]Num Type Disp Enb Address +What"
"\[\r\n\]2 breakpoint"
"\[\r\n\]\tbreakpoint already hit 2 times"
"\[\r\n\]3 dprintf"
--
1.7.7.6
^ permalink raw reply [flat|nested] 45+ messages in thread
* [PATCH 2/4] Test case of conditional dprintf
2013-02-28 15:32 ` [PATCH 1/4] Fix dprintf bugs Yao Qi
2013-02-28 13:17 ` [PATCH 3/4] Test dprintf breakpoint works correctly with other breakpoints Yao Qi
@ 2013-02-28 13:17 ` Yao Qi
2013-02-28 14:48 ` [PATCH 4/4] Test case on setting dprintf commands Yao Qi
` (2 subsequent siblings)
4 siblings, 0 replies; 45+ messages in thread
From: Yao Qi @ 2013-02-28 13:17 UTC (permalink / raw)
To: gdb-patches
This is to test that dprintf works well with condition. Since print
stuff in dprintf is implemented as commands, so there should be no
FAIL without patch 1/5 applied.
Note that this case is similar to
PR 15179 - Dprintf interrupts execution when condition is false
but I am still unable to reproduce this PR. dprintf-cond.exp can easily
extended to reproduce PR 15180 in next step.
gdb/testsuite:
2013-02-28 Yao Qi <yao@codesourcery.com>
* gdb.base/dprintf-cond.exp: New.
---
gdb/testsuite/gdb.base/dprintf-cond.exp | 75 +++++++++++++++++++++++++++++++
1 files changed, 75 insertions(+), 0 deletions(-)
create mode 100644 gdb/testsuite/gdb.base/dprintf-cond.exp
diff --git a/gdb/testsuite/gdb.base/dprintf-cond.exp b/gdb/testsuite/gdb.base/dprintf-cond.exp
new file mode 100644
index 0000000..b692124
--- /dev/null
+++ b/gdb/testsuite/gdb.base/dprintf-cond.exp
@@ -0,0 +1,75 @@
+# Copyright 2013 Free Software Foundation, Inc.
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+standard_testfile pr15075.c
+
+set executable $testfile
+set expfile $testfile.exp
+
+set dp_location [gdb_get_line_number "set dprintf here"]
+set bp_location [expr $dp_location + 1]
+
+if [prepare_for_testing $expfile $executable $srcfile {debug}] {
+ untested "failed to prepare for trace tests"
+ return -1
+}
+
+proc test_dprintf { style } { with_test_prefix "$style" {
+
+ global executable
+ global dp_location bp_location
+
+ # Start with a fresh gdb.
+ clean_restart ${executable}
+ if ![runto_main] {
+ fail "Can't run to main"
+ return -1
+ }
+
+ gdb_test_no_output "set dprintf-style ${style}" \
+ "Set dprintf style"
+ gdb_test "dprintf $dp_location, \"false, %d\\n\", x" \
+ "Dprintf 2 at .*" "dprintf 1"
+ gdb_test "cond 2 x == 5"
+
+ gdb_test "dprintf $dp_location, \"true, %d\\n\", x" \
+ "Dprintf 3 at .*" "dprintf 2"
+ gdb_test "cond 3 x > 5"
+
+ gdb_test "break $bp_location" "Breakpoint .*"
+
+ gdb_test "continue" "true, 6\\r\\n\\r\\n.*" "continue"
+
+ # Test program stops on the right breakpoint.
+ gdb_test "p x" ".* = 7"
+
+ # Test the hit count of dprintf breakpoints.
+ gdb_test_sequence "info breakpoints" "dprintf info" {
+ "\[\r\n\]Num Type Disp Enb Address +What"
+ "\[\r\n\]1 breakpoint"
+ "\[\r\n\]2 dprintf"
+ "\[\r\n\]\tstop only if x == 5"
+ "\[\r\n\]"
+ "\[\r\n\]3 dprintf"
+ "\[\r\n\]\tstop only if x > 5"
+ "\[\r\n\]\tbreakpoint already hit 1 time"
+ "\[\r\n\]"
+ }
+}}
+
+test_dprintf "gdb"
+
+if ![target_info exists gdb,noinferiorio] {
+ test_dprintf "call"
+}
--
1.7.7.6
^ permalink raw reply [flat|nested] 45+ messages in thread
* [PATCH 4/4] Test case on setting dprintf commands.
2013-02-28 15:32 ` [PATCH 1/4] Fix dprintf bugs Yao Qi
2013-02-28 13:17 ` [PATCH 3/4] Test dprintf breakpoint works correctly with other breakpoints Yao Qi
2013-02-28 13:17 ` [PATCH 2/4] Test case of conditional dprintf Yao Qi
@ 2013-02-28 14:48 ` Yao Qi
2013-02-28 16:30 ` [PATCH 1/4] Fix dprintf bugs Eli Zaretskii
2013-03-03 2:21 ` Marc Khouzam
4 siblings, 0 replies; 45+ messages in thread
From: Yao Qi @ 2013-02-28 14:48 UTC (permalink / raw)
To: gdb-patches
Test that GDB doesn't allow setting commands for dprintf breakpoint.
gdb/testsuite:
2013-02-28 Yao Qi <yao@codesourcery.com>
* gdb.base/dprintf.exp: Test commands are not allowed to set
for dprintf breakpoint.
---
gdb/testsuite/gdb.base/dprintf.exp | 14 ++++++++++++++
1 files changed, 14 insertions(+), 0 deletions(-)
diff --git a/gdb/testsuite/gdb.base/dprintf.exp b/gdb/testsuite/gdb.base/dprintf.exp
index 22c740a..aa0108d 100644
--- a/gdb/testsuite/gdb.base/dprintf.exp
+++ b/gdb/testsuite/gdb.base/dprintf.exp
@@ -40,6 +40,20 @@ gdb_breakpoint "main"
gdb_test "dprintf foo,\"At foo entry\\n\"" \
"Dprintf .*"
+# Test that GDB doesn't allow setting commands for dprintf.
+set test "set commands for dprintf"
+gdb_test_multiple "commands \$bpnum" "${test}" {
+ -re "End with a line saying just \"end\".*>" {
+ send_gdb "silent\n"
+ send_gdb "end\n"
+
+ fail $test
+ }
+ -re "Setting commands for dprintf breakpoint is not allowed.*\r\n$gdb_prompt $" {
+ pass $test
+ }
+}
+
# Set two dprintf breakpoints at the same location.
gdb_test "dprintf $dp_location1,\"arg=%d, g=%d\\n\", arg, g" \
"Dprintf .*"
--
1.7.7.6
^ permalink raw reply [flat|nested] 45+ messages in thread
* [PATCH 1/4] Fix dprintf bugs
2013-02-18 13:09 [RFC] PR 15075 dprintf interferes with "next" Yao Qi
` (2 preceding siblings ...)
2013-02-22 17:39 ` DPrintf feedback (was: [RFC] PR 15075 dprintf interferes with "next") Marc Khouzam
@ 2013-02-28 15:32 ` Yao Qi
2013-02-28 13:17 ` [PATCH 3/4] Test dprintf breakpoint works correctly with other breakpoints Yao Qi
` (4 more replies)
3 siblings, 5 replies; 45+ messages in thread
From: Yao Qi @ 2013-02-28 15:32 UTC (permalink / raw)
To: gdb-patches
Hi,
This patch fixes PR15075. Besides this bug, this patch also fixes
some other problems:
- Two dprintf are set on the same address. Only one printf is
executed.
- dprintf and regular breakpoint are set on the same address,
inferior doesn't stop.
In order to fix these problems, I don't append "continue" command to
dprintf breakpoint, and execute commands of dprintf after
bpstat_check_breakpoint_conditions if condition is true. The reason I
choose this place (after bpstat_check_breakpoint_conditions instead of
in bpstat_check_breakpoint_conditions) to handle dprintf is that we
have to set BS->stop to zero, but have to update hit count if
condition is true, so we have to do two things together.
With this patch, GDB executes dprintf commands after
bpstat_check_breakpoint_conditions, the different place where
breakpoint commands are executed. I propose to disable setting
command for dprintf, or disallow user setting commands for dprintf.
If we believe it is important to allow user setting commands for
dprintf (a good use case?), we need a new design like creating struct
dprintf as a 'sub-class' of breakpoint and adding its own field for
printf commands. The code on sending commands to the remote should be
adjusted as well.
Running gdb.base/pr15075.exp on mainline GDB (unpatched) will get the
following FAIL,
FAIL: gdb.base/pr15075.exp: p x
and this patch fixes this FAIL.
gdb:
2013-02-28 Yao Qi <yao@codesourcery.com>
PR breakpoints/15075
* breakpoint.c (bpstat_stop_status): Execute commands of
dprintf if BS->stop is true. Update hit count and set
BS->stop to zero.
(bpstat_what): Set 'this_action' to BPSTAT_WHAT_SINGLE if
breakpoint is dprintf.
(update_dprintf_command_list): Don't append "continue" command
to the commands of dprintf.
(do_map_commands_command): If breakpoint is dprintf, throw an
error.
* NEWS: Mention that GDB disallows setting commands for dprintf.
gdb/testsuite:
2013-02-28 Yao Qi <yao@codesourcery.com>
* gdb.base/dprintf.exp: DOn't check "continue" in the output
of "info breakpoints".
* gdb.mi/mi-breakpoint-changed.exp (test_insert_delete_modify):
Don't check "continue" in script field.
* gdb.base/pr15075.c: New.
* gdb.base/pr15075.exp: New.
---
gdb/NEWS | 2 +
gdb/breakpoint.c | 43 +++++++++++++++--------
gdb/testsuite/gdb.base/dprintf.exp | 2 -
gdb/testsuite/gdb.base/pr15075.c | 26 ++++++++++++++
gdb/testsuite/gdb.base/pr15075.exp | 38 +++++++++++++++++++++
gdb/testsuite/gdb.mi/mi-breakpoint-changed.exp | 2 +-
6 files changed, 95 insertions(+), 18 deletions(-)
create mode 100644 gdb/testsuite/gdb.base/pr15075.c
create mode 100644 gdb/testsuite/gdb.base/pr15075.exp
diff --git a/gdb/NEWS b/gdb/NEWS
index 0877aa2..2f0a157 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -70,6 +70,8 @@ Lynx 178 PowerPC powerpc-*-lynx*178
* The command 'info tracepoints' can now display 'installed on target'
or 'not installed on target' for each non-pending location of tracepoint.
+* GDB now disallows setting commands for dynamic printf breakpoint.
+
* New configure options
--enable-libmcheck/--disable-libmcheck
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index fb57a57..d4c3690 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -1295,6 +1295,10 @@ do_map_commands_command (struct breakpoint *b, void *data)
{
struct commands_info *info = data;
+ if (b->type == bp_dprintf)
+ error (_("Setting commands for dprintf breakpoint is not "
+ "allowed"));
+
if (info->cmd == NULL)
{
struct command_line *l;
@@ -5272,6 +5276,25 @@ bpstat_stop_status (struct address_space *aspace,
{
bpstat_check_breakpoint_conditions (bs, ptid);
+ if (bs->stop && b->type == bp_dprintf)
+ {
+ struct counted_command_line * ccmd = b->commands;
+ struct command_line *cmd = ccmd ? ccmd->commands : NULL;
+
+ while (cmd != NULL)
+ {
+ execute_control_command (cmd);
+ cmd = cmd->next;
+ }
+
+ /* Update the hit count of dprintf breakpoint, although
+ we set BS->stop zero. */
+ ++(b->hit_count);
+ observer_notify_breakpoint_modified (b);
+
+ bs->stop = 0;
+ }
+
if (bs->stop)
{
++(b->hit_count);
@@ -5519,7 +5542,7 @@ bpstat_what (bpstat bs_head)
break;
case bp_dprintf:
- this_action = BPSTAT_WHAT_STOP_SILENT;
+ this_action = BPSTAT_WHAT_SINGLE;
break;
default:
@@ -8947,25 +8970,15 @@ update_dprintf_command_list (struct breakpoint *b)
_("Invalid dprintf style."));
gdb_assert (printf_line != NULL);
- /* Manufacture a printf/continue sequence. */
+ /* Manufacture a printf command. */
{
- struct command_line *printf_cmd_line, *cont_cmd_line = NULL;
-
- if (strcmp (dprintf_style, dprintf_style_agent) != 0)
- {
- cont_cmd_line = xmalloc (sizeof (struct command_line));
- cont_cmd_line->control_type = simple_control;
- cont_cmd_line->body_count = 0;
- cont_cmd_line->body_list = NULL;
- cont_cmd_line->next = NULL;
- cont_cmd_line->line = xstrdup ("continue");
- }
+ struct command_line *printf_cmd_line
+ = xmalloc (sizeof (struct command_line));
- printf_cmd_line = xmalloc (sizeof (struct command_line));
printf_cmd_line->control_type = simple_control;
printf_cmd_line->body_count = 0;
printf_cmd_line->body_list = NULL;
- printf_cmd_line->next = cont_cmd_line;
+ printf_cmd_line->next = NULL;
printf_cmd_line->line = printf_line;
breakpoint_set_commands (b, printf_cmd_line);
diff --git a/gdb/testsuite/gdb.base/dprintf.exp b/gdb/testsuite/gdb.base/dprintf.exp
index 2b00c24..ffbd3f2 100644
--- a/gdb/testsuite/gdb.base/dprintf.exp
+++ b/gdb/testsuite/gdb.base/dprintf.exp
@@ -48,10 +48,8 @@ gdb_test_sequence "info breakpoints" "dprintf info 1" {
"\[\r\n\]2 breakpoint"
"\[\r\n\]3 dprintf"
"\[\r\n\] printf \"At foo entry\\\\n\""
- "\[\r\n\] continue"
"\[\r\n\]4 dprintf"
"\[\r\n\] printf \"arg=%d, g=%d\\\\n\", arg, g"
- "\[\r\n\] continue"
}
gdb_test "break $bp_location1" \
diff --git a/gdb/testsuite/gdb.base/pr15075.c b/gdb/testsuite/gdb.base/pr15075.c
new file mode 100644
index 0000000..60fe8cf
--- /dev/null
+++ b/gdb/testsuite/gdb.base/pr15075.c
@@ -0,0 +1,26 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright (C) 2013 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+int
+main(void)
+ {
+ int x = 5;
+
+ ++x;
+ ++x; /* set dprintf here */
+ return x - 7;
+ }
diff --git a/gdb/testsuite/gdb.base/pr15075.exp b/gdb/testsuite/gdb.base/pr15075.exp
new file mode 100644
index 0000000..86b24cc
--- /dev/null
+++ b/gdb/testsuite/gdb.base/pr15075.exp
@@ -0,0 +1,38 @@
+# Copyright 2013 Free Software Foundation, Inc.
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+standard_testfile
+
+set executable $testfile
+set expfile $testfile.exp
+
+set dp_location [gdb_get_line_number "set dprintf here"]
+
+if [prepare_for_testing $expfile $executable $srcfile {debug}] {
+ untested "failed to prepare for trace tests"
+ return -1
+}
+
+if ![runto_main] {
+ fail "Can't run to main"
+ return -1
+}
+
+gdb_test "dprintf $dp_location, \"%d\\n\", x" \
+ "Dprintf .*"
+
+gdb_test "next" ".*" "next 1"
+gdb_test "next" ".*" "next 2"
+# Test inferior doesn't exit.
+gdb_test "p x" ".* = 6"
diff --git a/gdb/testsuite/gdb.mi/mi-breakpoint-changed.exp b/gdb/testsuite/gdb.mi/mi-breakpoint-changed.exp
index fd32698..24ff55b 100644
--- a/gdb/testsuite/gdb.mi/mi-breakpoint-changed.exp
+++ b/gdb/testsuite/gdb.mi/mi-breakpoint-changed.exp
@@ -96,7 +96,7 @@ proc test_insert_delete_modify { } {
$test
set test "dprintf marker, \"arg\" \""
mi_gdb_test $test \
- {.*=breakpoint-created,bkpt=\{number="6",type="dprintf".*,script=\{\"printf \\\\\"arg\\\\\" \\\\\"\",\"continue\"\}.*\}\r\n\^done} \
+ {.*=breakpoint-created,bkpt=\{number="6",type="dprintf".*,script=\{\"printf \\\\\"arg\\\\\" \\\\\"\"\}.*\}\r\n\^done} \
$test
# 2. when modifying condition
--
1.7.7.6
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH 1/4] Fix dprintf bugs
2013-02-28 15:32 ` [PATCH 1/4] Fix dprintf bugs Yao Qi
` (2 preceding siblings ...)
2013-02-28 14:48 ` [PATCH 4/4] Test case on setting dprintf commands Yao Qi
@ 2013-02-28 16:30 ` Eli Zaretskii
2013-03-07 7:45 ` Yao Qi
2013-03-03 2:21 ` Marc Khouzam
4 siblings, 1 reply; 45+ messages in thread
From: Eli Zaretskii @ 2013-02-28 16:30 UTC (permalink / raw)
To: Yao Qi; +Cc: gdb-patches
> From: Yao Qi <yao@codesourcery.com>
> Date: Thu, 28 Feb 2013 21:15:59 +0800
>
> This patch fixes PR15075. Besides this bug, this patch also fixes
> some other problems:
>
> - Two dprintf are set on the same address. Only one printf is
> executed.
> - dprintf and regular breakpoint are set on the same address,
> inferior doesn't stop.
>
> In order to fix these problems, I don't append "continue" command to
> dprintf breakpoint, and execute commands of dprintf after
> bpstat_check_breakpoint_conditions if condition is true. The reason I
> choose this place (after bpstat_check_breakpoint_conditions instead of
> in bpstat_check_breakpoint_conditions) to handle dprintf is that we
> have to set BS->stop to zero, but have to update hit count if
> condition is true, so we have to do two things together.
>
> With this patch, GDB executes dprintf commands after
> bpstat_check_breakpoint_conditions, the different place where
> breakpoint commands are executed. I propose to disable setting
> command for dprintf, or disallow user setting commands for dprintf.
I don't understand: if you are disallowing commands for dprintf, then
why do you also fix the handling of these commands?
^ permalink raw reply [flat|nested] 45+ messages in thread
* RE: [PATCH 1/4] Fix dprintf bugs
2013-02-28 15:32 ` [PATCH 1/4] Fix dprintf bugs Yao Qi
` (3 preceding siblings ...)
2013-02-28 16:30 ` [PATCH 1/4] Fix dprintf bugs Eli Zaretskii
@ 2013-03-03 2:21 ` Marc Khouzam
2013-03-07 6:47 ` Yao Qi
4 siblings, 1 reply; 45+ messages in thread
From: Marc Khouzam @ 2013-03-03 2:21 UTC (permalink / raw)
To: yao; +Cc: gdb-patches
> -----Original Message-----
> From: gdb-patches-owner@sourceware.org
> [mailto:gdb-patches-owner@sourceware.org] On Behalf Of Yao Qi
> Sent: Thursday, February 28, 2013 8:16 AM
> To: gdb-patches@sourceware.org
> Subject: [PATCH 1/4] Fix dprintf bugs
>
> Hi,
> This patch fixes PR15075. Besides this bug, this patch also fixes
> some other problems:
>
> - Two dprintf are set on the same address. Only one printf is
> executed.
> - dprintf and regular breakpoint are set on the same address,
> inferior doesn't stop.
>
> In order to fix these problems, I don't append "continue" command to
> dprintf breakpoint, and execute commands of dprintf after
> bpstat_check_breakpoint_conditions if condition is true. The reason I
> choose this place (after bpstat_check_breakpoint_conditions instead of
> in bpstat_check_breakpoint_conditions) to handle dprintf is that we
> have to set BS->stop to zero, but have to update hit count if
> condition is true, so we have to do two things together.
>
> With this patch, GDB executes dprintf commands after
> bpstat_check_breakpoint_conditions, the different place where
> breakpoint commands are executed. I propose to disable setting
> command for dprintf, or disallow user setting commands for dprintf.
> If we believe it is important to allow user setting commands for
> dprintf (a good use case?), we need a new design like creating struct
> dprintf as a 'sub-class' of breakpoint and adding its own field for
> printf commands. The code on sending commands to the remote should be
> adjusted as well.
I've played around with this patch and I like the solution a lot!
I like the fact that a user cannot modify the list of commands for dprintf.
If they want to use commands, they should use a breakpoint, not
a dprintf. It is no longer possible to update the dprintf string
without having to create a new dprintf though; but if this is to be
supported, I think it should be a specific dprintf operation.
I no longer see *stopped/*running events in MI, which is great.
I'm still hesitant about the -break-modified event in that case
though. I believe the event is triggered because the hit count
has changed. For a normal bp, it makes sense to have this event
in this case, since execution has stopped and only a single
event will be seen (not exactly true for non-stop, but still
makes sense, I think). However, for dprintf which is meant to
let the inferior continue to run, there could be quite many
hit events very quickly. Since we already have some feeback
that the dprintf has hit through the actual printf string, I'm
leaning towards not having that event for dprintf hits.
Furthermore, this event is not being sent when using dprintf-style
"agent" anyway.
I also saw that conditions are now properly respected for dprintf-style
"gdb" and "call". That is great. Conditions are still not respected for
style "agent" but that is a separate issue I believe (PR 15180).
I did notice that although commands cannot be set for dprintf from
the CLI they are not blocked for MI:
(gdb) interpreter-exec mi "-break-commands 1 hello"
^done
(gdb) info b
Num Type Disp Enb Address What
1 dprintf keep y 0x0000000000400570 in main() at loopfirst.cc:8
hello
Finally, it would be nice to have MI commands to deal with dprintf :)
Re-using the breakpoint MI commands sound best, although I wonder about
two cases:
a) Would we be able to specify the printf string in the -break-insert command?
b) How could we change the printf command after a dprintf is created? Will we
need to delete it and create a new one, or would we be able to update it?
All that being said, I'm impressed at how many improvements this
relatively small patch provides. Nice work.
Marc
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH 1/4] Fix dprintf bugs
2013-03-03 2:21 ` Marc Khouzam
@ 2013-03-07 6:47 ` Yao Qi
2013-03-07 14:06 ` Marc Khouzam
0 siblings, 1 reply; 45+ messages in thread
From: Yao Qi @ 2013-03-07 6:47 UTC (permalink / raw)
To: Marc Khouzam; +Cc: gdb-patches
Marc, thanks for playing with dprintf and giving a lot useful comments
and suggestions.
On 03/03/2013 10:21 AM, Marc Khouzam wrote:
> I'm still hesitant about the -break-modified event in that case
> though. I believe the event is triggered because the hit count
> has changed. For a normal bp, it makes sense to have this event
> in this case, since execution has stopped and only a single
> event will be seen (not exactly true for non-stop, but still
> makes sense, I think). However, for dprintf which is meant to
> let the inferior continue to run, there could be quite many
> hit events very quickly. Since we already have some feeback
> that the dprintf has hit through the actual printf string, I'm
> leaning towards not having that event for dprintf hits.
Right, the "hit count" is not very meaningful to dprintf. I am fine not
to update hit count for dprintf.
> Furthermore, this event is not being sent when using dprintf-style
> "agent" anyway.
>
> I also saw that conditions are now properly respected for dprintf-style
> "gdb" and "call". That is great. Conditions are still not respected for
> style "agent" but that is a separate issue I believe (PR 15180).
>
Right, PR 15180 is a separate problem. It is not dprintf specific, in
fact. It is about target side commands execution respected for the
target side conditions.
> I did notice that although commands cannot be set for dprintf from
> the CLI they are not blocked for MI:
>
> (gdb) interpreter-exec mi "-break-commands 1 hello"
> ^done
> (gdb) info b
> Num Type Disp Enb Address What
> 1 dprintf keep y 0x0000000000400570 in main() at loopfirst.cc:8
> hello
>
I'll handle this in the new version.
--
Yao (é½å°§)
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH 1/4] Fix dprintf bugs
2013-02-28 16:30 ` [PATCH 1/4] Fix dprintf bugs Eli Zaretskii
@ 2013-03-07 7:45 ` Yao Qi
0 siblings, 0 replies; 45+ messages in thread
From: Yao Qi @ 2013-03-07 7:45 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: gdb-patches
On 02/28/2013 11:54 PM, Eli Zaretskii wrote:
> I don't understand: if you are disallowing commands for dprintf, then
> why do you also fix the handling of these commands?
Internally, dprintf breakpoint still uses 'print' command, but we
disallow users setting commands for it in CLI and MI.
--
Yao (é½å°§)
^ permalink raw reply [flat|nested] 45+ messages in thread
* RE: [PATCH 1/4] Fix dprintf bugs
2013-03-07 6:47 ` Yao Qi
@ 2013-03-07 14:06 ` Marc Khouzam
2013-03-07 14:36 ` Yao Qi
0 siblings, 1 reply; 45+ messages in thread
From: Marc Khouzam @ 2013-03-07 14:06 UTC (permalink / raw)
To: Yao Qi; +Cc: gdb-patches
From: Yao Qi [yao@codesourcery.com]
Sent: March 7, 2013 1:46 AM
>
> On 03/03/2013 10:21 AM, Marc Khouzam wrote:
> > I'm still hesitant about the -break-modified event in that case
> > though. I believe the event is triggered because the hit count
> > has changed. For a normal bp, it makes sense to have this event
> > in this case, since execution has stopped and only a single
> > event will be seen (not exactly true for non-stop, but still
> > makes sense, I think). However, for dprintf which is meant to
> > let the inferior continue to run, there could be quite many
> > hit events very quickly. Since we already have some feeback
> > that the dprintf has hit through the actual printf string, I'm
> > leaning towards not having that event for dprintf hits.
>
> Right, the "hit count" is not very meaningful to dprintf. I am fine not
> to update hit count for dprintf.
I was actually thinking of keeping the hit count being updated but
simply not sending the MI event for it. I'm under the impression
that updating the hit count is not expensive, so having that information
available can be useful. What bothers me is the very many MI
events being sent to the frontend. If the hit count is not reported
by an MI event for dprintf, its value can still be obtained by
the frontend through -break-list for example.
For the agent-style dprintf though, I'm guessing that the hit count
is not being updated to avoid communication with GDB? This
scenario already had to be handled for normal breakpoints and
I suggest using whatever scheme is already being used.
Thanks for the nice improvements
Marc
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH 1/4] Fix dprintf bugs
2013-03-07 14:06 ` Marc Khouzam
@ 2013-03-07 14:36 ` Yao Qi
2013-03-07 14:49 ` Marc Khouzam
0 siblings, 1 reply; 45+ messages in thread
From: Yao Qi @ 2013-03-07 14:36 UTC (permalink / raw)
To: Marc Khouzam; +Cc: gdb-patches
On 03/07/2013 10:05 PM, Marc Khouzam wrote:
> I was actually thinking of keeping the hit count being updated but
> simply not sending the MI event for it. I'm under the impression
> that updating the hit count is not expensive, so having that information
> available can be useful. What bothers me is the very many MI
> events being sent to the frontend. If the hit count is not reported
> by an MI event for dprintf, its value can still be obtained by
> the frontend through -break-list for example.
FAOD, are you suggesting that we still update hit count, but don't have
to notify breakpoint-modified observer?
>
> For the agent-style dprintf though, I'm guessing that the hit count
> is not being updated to avoid communication with GDB? This
> scenario already had to be handled for normal breakpoints and
> I suggest using whatever scheme is already being used.
We can use async remote notification here, to notify GDB that the hit
count or other attributes of breakpoint/tracepoint are modified. I've
had some local patches to report to GDB that the hit count and
traceframe usage of tracepoint is updated. After pending async remote
notification are patches approved, I'll post them out.
--
Yao (é½å°§)
^ permalink raw reply [flat|nested] 45+ messages in thread
* RE: [PATCH 1/4] Fix dprintf bugs
2013-03-07 14:36 ` Yao Qi
@ 2013-03-07 14:49 ` Marc Khouzam
2013-03-07 14:59 ` Yao Qi
0 siblings, 1 reply; 45+ messages in thread
From: Marc Khouzam @ 2013-03-07 14:49 UTC (permalink / raw)
To: Yao Qi; +Cc: gdb-patches
> On 03/07/2013 10:05 PM, Marc Khouzam wrote:
> > I was actually thinking of keeping the hit count being updated but
> > simply not sending the MI event for it. I'm under the impression
> > that updating the hit count is not expensive, so having that information
> > available can be useful. What bothers me is the very many MI
> > events being sent to the frontend. If the hit count is not reported
> > by an MI event for dprintf, its value can still be obtained by
> > the frontend through -break-list for example.
>
> FAOD, are you suggesting that we still update hit count, but don't have
> to notify breakpoint-modified observer?
That is right. Of course, I'm just making a suggestion. I don't know
GDB well enough to know all the implications, but from a frontend
point-of-view I believe this solution is best.
> > For the agent-style dprintf though, I'm guessing that the hit count
> > is not being updated to avoid communication with GDB? This
> > scenario already had to be handled for normal breakpoints and
> > I suggest using whatever scheme is already being used.
>
> We can use async remote notification here, to notify GDB that the hit
> count or other attributes of breakpoint/tracepoint are modified. I've
> had some local patches to report to GDB that the hit count and
> traceframe usage of tracepoint is updated. After pending async remote
> notification are patches approved, I'll post them out.
So, I'm suggesting that sending an MI event from GDB to the frontend for
every dprintf hit is too much. Does the same argument hold for async
remote notifications? For efficiency, I'm thinking that agent dprintf should
not report every hit to GDB; instead, when GDB wants to know the hit
count (e.g, because of a -break-list command), it would ask the agent
for the current hit count. This would cut down on the communication
from agent to GDB when using dprintf.
Does that make sense?
Marc
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [PATCH 1/4] Fix dprintf bugs
2013-03-07 14:49 ` Marc Khouzam
@ 2013-03-07 14:59 ` Yao Qi
2013-03-08 15:49 ` Marc Khouzam
0 siblings, 1 reply; 45+ messages in thread
From: Yao Qi @ 2013-03-07 14:59 UTC (permalink / raw)
To: Marc Khouzam; +Cc: gdb-patches
On 03/07/2013 10:48 PM, Marc Khouzam wrote:
> So, I'm suggesting that sending an MI event from GDB to the frontend for
> every dprintf hit is too much. Does the same argument hold for async
> remote notifications? For efficiency, I'm thinking that agent dprintf should
> not report every hit to GDB; instead, when GDB wants to know the hit
> count (e.g, because of a -break-list command), it would ask the agent
> for the current hit count. This would cut down on the communication
> from agent to GDB when using dprintf.
If we use async remote notification for hit count update, of course,
GDBserver can't report *every* hit count update to GDB, which is
relatively expensive. GDBserver shouldn't send new async remote
notification to GDB until the previous notification is ack'ed by GDB.
--
Yao (é½å°§)
^ permalink raw reply [flat|nested] 45+ messages in thread
* RE: [PATCH 1/4] Fix dprintf bugs
2013-03-07 14:59 ` Yao Qi
@ 2013-03-08 15:49 ` Marc Khouzam
0 siblings, 0 replies; 45+ messages in thread
From: Marc Khouzam @ 2013-03-08 15:49 UTC (permalink / raw)
To: 'Yao Qi'; +Cc: 'gdb-patches@sourceware.org'
> -----Original Message-----
> From: Yao Qi [mailto:yao@codesourcery.com]
> Sent: Thursday, March 07, 2013 9:58 AM
> To: Marc Khouzam
> Cc: gdb-patches@sourceware.org
> Subject: Re: [PATCH 1/4] Fix dprintf bugs
>
> On 03/07/2013 10:48 PM, Marc Khouzam wrote:
> > So, I'm suggesting that sending an MI event from GDB to the
> frontend for
> > every dprintf hit is too much. Does the same argument hold
> for async
> > remote notifications? For efficiency, I'm thinking that
> agent dprintf should
> > not report every hit to GDB; instead, when GDB wants to know the hit
> > count (e.g, because of a -break-list command), it would ask
> the agent
> > for the current hit count. This would cut down on the communication
> > from agent to GDB when using dprintf.
>
> If we use async remote notification for hit count update, of course,
> GDBserver can't report *every* hit count update to GDB, which is
> relatively expensive. GDBserver shouldn't send new async remote
> notification to GDB until the previous notification is ack'ed by GDB.
Again, I don't know the details of this communication so I might
be missing an important point. Sending a new async notification
for a hit count change for dprintf, even if some of those will be
skipped when waiting for a GDB ack, sounds like a lot to me.
If I set a dprintf into a loop, there will be many printouts on
the target, but do we want to have so many async notifs sent
to GDB from the target? Since we won't be sending MI events for
hit count changes for dprintf, do we need GDB to know dprintf
hit count 'live' or can we ask the target whenever that information
is actually needed?
Marc
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [RFC] PR 15075 dprintf interferes with "next"
2013-02-21 16:36 ` Tom Tromey
@ 2013-04-24 1:24 ` Hui Zhu
2013-04-24 6:06 ` Keith Seitz
0 siblings, 1 reply; 45+ messages in thread
From: Hui Zhu @ 2013-04-24 1:24 UTC (permalink / raw)
To: Tom Tromey; +Cc: Yao Qi, gdb-patches
[-- Attachment #1: Type: text/plain, Size: 2141 bytes --]
On Fri, Feb 22, 2013 at 12:35 AM, Tom Tromey <tromey@redhat.com> wrote:
>>>>>> "Yao" == Yao Qi <yao@codesourcery.com> writes:
>
> Yao> The printf stuff is implemented as command, it is convenient to move
> Yao> them to the target side. I tried to change the bpstat saying that
> Yao> "don't stop", but the command can't be executed. We have to keep
> Yao> bpstat saying that "stop" for dprintf. I also thought about Tom's
> Yao> suggestion about Python "Breakpoint.stop" API, but "Breakpoint.stop"
> Yao> acts as condition instead of command, so I don't go that way.
>
> Pedro pointed out that 'stop' runs too early -- it makes "cond" not work
> on a dprintf. (BTW if there is no test for this, there should be... )
>
> But, why not just do the work just after the condition is evaluated?
> For example, it could be done with special handling in
> bpstat_check_breakpoint_conditions, or by introducing a new
> check_condition breakpoint_ops method, with the dprintf method calling
> the super method before proceeding to "printf" and then returning 0.
>
> I tend to think that the "commands" approach is just not a good one.
>
> Tom
Hi Tom,
I update this patch according to your comments:
Add after_cond to breakpoint_ops and let bpstat_stop_status call it
after cond check.
Then add normal code to base_breakpoint_after_cond handle setup of
other breakpoints and set dprintf special code to dprintf_after_cond
that do print work.
And I also updated test for this change.
Please help me review it.
Thanks,
Hui
2013-04-23 Yao Qi <yao@codesourcery.com>
Hui Zhu <hui@codesourcery.com>
PR gdb/15075
* breakpoint.c (bpstat_stop_status): Call b->ops->after_cond.
(update_dprintf_command_list): Don't append "continue" command
to the command of dprintf breakpoint.
(base_breakpoint_after_cond): New.
(base_breakpoint_ops): Add base_breakpoint_after_cond.
(dprintf_after_cond): New.
(initialize_breakpoint_ops): Set dprintf_after_cond.
* breakpoint.h (breakpoint_ops): Add after_cond.
2013-04-23 Hui Zhu <hui@codesourcery.com>
PR gdb/15075
* gdb.base/dprintf.exp: Remove "continue" from "info breakpoint"
test.
[-- Attachment #2: dprintf-continue.txt --]
[-- Type: text/plain, Size: 3728 bytes --]
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -5296,13 +5296,7 @@ bpstat_stop_status (struct address_space
b->enable_state = bp_disabled;
removed_any = 1;
}
- if (b->silent)
- bs->print = 0;
- bs->commands = b->commands;
- incref_counted_command_line (bs->commands);
- if (command_line_is_silent (bs->commands
- ? bs->commands->commands : NULL))
- bs->print = 0;
+ b->ops->after_cond (bs);
}
}
@@ -8960,25 +8954,16 @@ update_dprintf_command_list (struct brea
_("Invalid dprintf style."));
gdb_assert (printf_line != NULL);
- /* Manufacture a printf/continue sequence. */
+ /* Manufacture a printf sequence. */
{
- struct command_line *printf_cmd_line, *cont_cmd_line = NULL;
-
- if (strcmp (dprintf_style, dprintf_style_agent) != 0)
- {
- cont_cmd_line = xmalloc (sizeof (struct command_line));
- cont_cmd_line->control_type = simple_control;
- cont_cmd_line->body_count = 0;
- cont_cmd_line->body_list = NULL;
- cont_cmd_line->next = NULL;
- cont_cmd_line->line = xstrdup ("continue");
- }
+ struct command_line *printf_cmd_line
+ = xmalloc (sizeof (struct command_line));
printf_cmd_line = xmalloc (sizeof (struct command_line));
printf_cmd_line->control_type = simple_control;
printf_cmd_line->body_count = 0;
printf_cmd_line->body_list = NULL;
- printf_cmd_line->next = cont_cmd_line;
+ printf_cmd_line->next = NULL;
printf_cmd_line->line = printf_line;
breakpoint_set_commands (b, printf_cmd_line);
@@ -12764,6 +12749,22 @@ base_breakpoint_explains_signal (struct
return BPSTAT_SIGNAL_HIDE;
}
+/* The default 'after_cond' method. */
+
+static void
+base_breakpoint_after_cond (struct bpstats *bs)
+{
+ struct breakpoint *b = bs->breakpoint_at;
+
+ if (b->silent)
+ bs->print = 0;
+ bs->commands = b->commands;
+ incref_counted_command_line (bs->commands);
+ if (command_line_is_silent (bs->commands
+ ? bs->commands->commands : NULL))
+ bs->print = 0;
+}
+
struct breakpoint_ops base_breakpoint_ops =
{
base_breakpoint_dtor,
@@ -12783,7 +12784,8 @@ struct breakpoint_ops base_breakpoint_op
base_breakpoint_create_sals_from_address,
base_breakpoint_create_breakpoints_sal,
base_breakpoint_decode_linespec,
- base_breakpoint_explains_signal
+ base_breakpoint_explains_signal,
+ base_breakpoint_after_cond,
};
/* Default breakpoint_ops methods. */
@@ -13377,6 +13379,23 @@ dprintf_print_recreate (struct breakpoin
print_recreate_thread (tp, fp);
}
+/* Implement the "after_cond" breakpoint_ops method for dprintf. */
+
+static void
+dprintf_after_cond (struct bpstats *bs)
+{
+ bpstat tmp;
+
+ bs->stop = 0;
+ bs->print = 0;
+ bs->commands = b->commands;
+ tmp = bs->next;
+ bs->next = tmp;
+ incref_counted_command_line (bs->commands);
+ bpstat_do_actions_1 (&bs);
+ bs->next = tmp;
+}
+
/* The breakpoint_ops structure to be used on static tracepoints with
markers (`-m'). */
@@ -15873,6 +15892,7 @@ initialize_breakpoint_ops (void)
ops->print_it = bkpt_print_it;
ops->print_mention = bkpt_print_mention;
ops->print_recreate = dprintf_print_recreate;
+ ops->after_cond = dprintf_after_cond;
}
/* Chain containing all defined "enable breakpoint" subcommands. */
--- a/gdb/breakpoint.h
+++ b/gdb/breakpoint.h
@@ -614,6 +614,9 @@ struct breakpoint_ops
'catch signal' interact properly with 'handle'; see
bpstat_explains_signal. */
enum bpstat_signal_value (*explains_signal) (struct breakpoint *);
+
+ /* Do some setup after check condition is true. */
+ void (*after_cond) (struct bpstats *bs);
};
/* Helper for breakpoint_ops->print_recreate implementations. Prints
[-- Attachment #3: dprintf-continue-test.txt --]
[-- Type: text/plain, Size: 453 bytes --]
--- a/gdb/testsuite/gdb.base/dprintf.exp
+++ b/gdb/testsuite/gdb.base/dprintf.exp
@@ -50,10 +50,8 @@ gdb_test_sequence "info breakpoints" "dp
"\[\r\n\]2 breakpoint"
"\[\r\n\]3 dprintf"
"\[\r\n\] printf \"At foo entry\\\\n\""
- "\[\r\n\] continue"
"\[\r\n\]4 dprintf"
"\[\r\n\] printf \"arg=%d, g=%d\\\\n\", arg, g"
- "\[\r\n\] continue"
}
gdb_test "break $bp_location1" \
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [RFC] PR 15075 dprintf interferes with "next"
2013-04-24 1:24 ` Hui Zhu
@ 2013-04-24 6:06 ` Keith Seitz
2013-04-24 13:30 ` Hui Zhu
0 siblings, 1 reply; 45+ messages in thread
From: Keith Seitz @ 2013-04-24 6:06 UTC (permalink / raw)
To: Hui Zhu; +Cc: gdb-patches
On 04/23/2013 08:44 AM, Hui Zhu wrote:
> --- a/gdb/breakpoint.c
> +++ b/gdb/breakpoint.c
> +/* Implement the "after_cond" breakpoint_ops method for dprintf. */
> +
> +static void
> +dprintf_after_cond (struct bpstats *bs)
> +{
> + bpstat tmp;
> +
> + bs->stop = 0;
> + bs->print = 0;
> + bs->commands = b->commands;
> + tmp = bs->next;
> + bs->next = tmp;
> + incref_counted_command_line (bs->commands);
> + bpstat_do_actions_1 (&bs);
> + bs->next = tmp;
> +}
This function must be incomplete. What is 'tmp' for? It is superfluous
as written. 'b' is undefined, too.
Keith
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [RFC] PR 15075 dprintf interferes with "next"
2013-04-24 6:06 ` Keith Seitz
@ 2013-04-24 13:30 ` Hui Zhu
2013-04-24 14:03 ` Yao Qi
0 siblings, 1 reply; 45+ messages in thread
From: Hui Zhu @ 2013-04-24 13:30 UTC (permalink / raw)
To: Keith Seitz, Tom Tromey, Yao Qi; +Cc: gdb-patches
[-- Attachment #1: Type: text/plain, Size: 1391 bytes --]
On Wed, Apr 24, 2013 at 1:13 AM, Keith Seitz <keiths@redhat.com> wrote:
> On 04/23/2013 08:44 AM, Hui Zhu wrote:
>>
>> --- a/gdb/breakpoint.c
>> +++ b/gdb/breakpoint.c
>> +/* Implement the "after_cond" breakpoint_ops method for dprintf. */
>> +
>> +static void
>> +dprintf_after_cond (struct bpstats *bs)
>> +{
>> + bpstat tmp;
>> +
>> + bs->stop = 0;
>> + bs->print = 0;
>> + bs->commands = b->commands;
>> + tmp = bs->next;
>> + bs->next = tmp;
>> + incref_counted_command_line (bs->commands);
>> + bpstat_do_actions_1 (&bs);
>> + bs->next = tmp;
>> +}
>
>
> This function must be incomplete. What is 'tmp' for? It is superfluous as
> written. 'b' is undefined, too.
>
> Keith
Oops, I post a wrong patch. This is the new one.
Sorry for that.
Thanks,
Hui
2013-04-23 Yao Qi <yao@codesourcery.com>
Hui Zhu <hui@codesourcery.com>
PR gdb/15075
* breakpoint.c (bpstat_stop_status): Call b->ops->after_cond.
(update_dprintf_command_list): Don't append "continue" command
to the command of dprintf breakpoint.
(base_breakpoint_after_cond): New.
(base_breakpoint_ops): Add base_breakpoint_after_cond.
(dprintf_after_cond): New.
(initialize_breakpoint_ops): Set dprintf_after_cond.
* breakpoint.h (breakpoint_ops): Add after_cond.
2013-04-23 Hui Zhu <hui@codesourcery.com>
PR gdb/15075
* gdb.base/dprintf.exp: Remove "continue" from "info breakpoint"
test.
[-- Attachment #2: dprintf-continue.txt --]
[-- Type: text/plain, Size: 3773 bytes --]
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -5296,13 +5296,7 @@ bpstat_stop_status (struct address_space
b->enable_state = bp_disabled;
removed_any = 1;
}
- if (b->silent)
- bs->print = 0;
- bs->commands = b->commands;
- incref_counted_command_line (bs->commands);
- if (command_line_is_silent (bs->commands
- ? bs->commands->commands : NULL))
- bs->print = 0;
+ b->ops->after_cond (bs);
}
}
@@ -8960,25 +8954,16 @@ update_dprintf_command_list (struct brea
_("Invalid dprintf style."));
gdb_assert (printf_line != NULL);
- /* Manufacture a printf/continue sequence. */
+ /* Manufacture a printf sequence. */
{
- struct command_line *printf_cmd_line, *cont_cmd_line = NULL;
-
- if (strcmp (dprintf_style, dprintf_style_agent) != 0)
- {
- cont_cmd_line = xmalloc (sizeof (struct command_line));
- cont_cmd_line->control_type = simple_control;
- cont_cmd_line->body_count = 0;
- cont_cmd_line->body_list = NULL;
- cont_cmd_line->next = NULL;
- cont_cmd_line->line = xstrdup ("continue");
- }
+ struct command_line *printf_cmd_line
+ = xmalloc (sizeof (struct command_line));
printf_cmd_line = xmalloc (sizeof (struct command_line));
printf_cmd_line->control_type = simple_control;
printf_cmd_line->body_count = 0;
printf_cmd_line->body_list = NULL;
- printf_cmd_line->next = cont_cmd_line;
+ printf_cmd_line->next = NULL;
printf_cmd_line->line = printf_line;
breakpoint_set_commands (b, printf_cmd_line);
@@ -12764,6 +12749,22 @@ base_breakpoint_explains_signal (struct
return BPSTAT_SIGNAL_HIDE;
}
+/* The default 'after_cond' method. */
+
+static void
+base_breakpoint_after_cond (struct bpstats *bs)
+{
+ struct breakpoint *b = bs->breakpoint_at;
+
+ if (b->silent)
+ bs->print = 0;
+ bs->commands = b->commands;
+ incref_counted_command_line (bs->commands);
+ if (command_line_is_silent (bs->commands
+ ? bs->commands->commands : NULL))
+ bs->print = 0;
+}
+
struct breakpoint_ops base_breakpoint_ops =
{
base_breakpoint_dtor,
@@ -12783,7 +12784,8 @@ struct breakpoint_ops base_breakpoint_op
base_breakpoint_create_sals_from_address,
base_breakpoint_create_breakpoints_sal,
base_breakpoint_decode_linespec,
- base_breakpoint_explains_signal
+ base_breakpoint_explains_signal,
+ base_breakpoint_after_cond,
};
/* Default breakpoint_ops methods. */
@@ -13377,6 +13379,24 @@ dprintf_print_recreate (struct breakpoin
print_recreate_thread (tp, fp);
}
+/* Implement the "after_cond" breakpoint_ops method for dprintf. */
+
+static void
+dprintf_after_cond (struct bpstats *bs)
+{
+ bpstat tmp;
+ struct breakpoint *b = bs->breakpoint_at;
+
+ bs->stop = 0;
+ bs->print = 0;
+ bs->commands = b->commands;
+ tmp = bs->next;
+ bs->next = tmp;
+ incref_counted_command_line (bs->commands);
+ bpstat_do_actions_1 (&bs);
+ bs->next = tmp;
+}
+
/* The breakpoint_ops structure to be used on static tracepoints with
markers (`-m'). */
@@ -15873,6 +15893,7 @@ initialize_breakpoint_ops (void)
ops->print_it = bkpt_print_it;
ops->print_mention = bkpt_print_mention;
ops->print_recreate = dprintf_print_recreate;
+ ops->after_cond = dprintf_after_cond;
}
/* Chain containing all defined "enable breakpoint" subcommands. */
--- a/gdb/breakpoint.h
+++ b/gdb/breakpoint.h
@@ -614,6 +614,9 @@ struct breakpoint_ops
'catch signal' interact properly with 'handle'; see
bpstat_explains_signal. */
enum bpstat_signal_value (*explains_signal) (struct breakpoint *);
+
+ /* Do some setup after check condition is true. */
+ void (*after_cond) (struct bpstats *bs);
};
/* Helper for breakpoint_ops->print_recreate implementations. Prints
[-- Attachment #3: dprintf-continue-test.txt --]
[-- Type: text/plain, Size: 453 bytes --]
--- a/gdb/testsuite/gdb.base/dprintf.exp
+++ b/gdb/testsuite/gdb.base/dprintf.exp
@@ -50,10 +50,8 @@ gdb_test_sequence "info breakpoints" "dp
"\[\r\n\]2 breakpoint"
"\[\r\n\]3 dprintf"
"\[\r\n\] printf \"At foo entry\\\\n\""
- "\[\r\n\] continue"
"\[\r\n\]4 dprintf"
"\[\r\n\] printf \"arg=%d, g=%d\\\\n\", arg, g"
- "\[\r\n\] continue"
}
gdb_test "break $bp_location1" \
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [RFC] PR 15075 dprintf interferes with "next"
2013-04-24 13:30 ` Hui Zhu
@ 2013-04-24 14:03 ` Yao Qi
2013-04-24 14:09 ` Hui Zhu
0 siblings, 1 reply; 45+ messages in thread
From: Yao Qi @ 2013-04-24 14:03 UTC (permalink / raw)
To: Hui Zhu; +Cc: Keith Seitz, Tom Tromey, gdb-patches
On 04/24/2013 07:59 AM, Hui Zhu wrote:
> 2013-04-23 Yao Qi<yao@codesourcery.com>
> Hui Zhu<hui@codesourcery.com>
>
> PR gdb/15075
^^^^^^^^^^^^ "PR breakpoints/15075"
>
> * breakpoint.c (bpstat_stop_status): Call b->ops->after_cond.
> (update_dprintf_command_list): Don't append "continue" command
> to the command of dprintf breakpoint.
> (base_breakpoint_after_cond): New.
> (base_breakpoint_ops): Add base_breakpoint_after_cond.
> (dprintf_after_cond): New.
> (initialize_breakpoint_ops): Set dprintf_after_cond.
> * breakpoint.h (breakpoint_ops): Add after_cond.
>
> 2013-04-23 Hui Zhu<hui@codesourcery.com>
>
> PR gdb/15075
>
> * gdb.base/dprintf.exp: Remove "continue" from "info breakpoint"
> test.
We also need to stop checking "continue" in
gdb.mi/mi-breakpoint-changed.exp also, as what patch [1] does. B.T.W,
why don't you add gdb.base/pr15075.[c,exp] from patch [1]?
--
Yao (é½å°§)
[1] http://sourceware.org/ml/gdb-patches/2013-02/msg00736.html
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [RFC] PR 15075 dprintf interferes with "next"
2013-04-24 14:03 ` Yao Qi
@ 2013-04-24 14:09 ` Hui Zhu
2013-05-16 7:29 ` Hui Zhu
0 siblings, 1 reply; 45+ messages in thread
From: Hui Zhu @ 2013-04-24 14:09 UTC (permalink / raw)
To: Yao Qi; +Cc: Keith Seitz, Tom Tromey, gdb-patches
[-- Attachment #1: Type: text/plain, Size: 2295 bytes --]
On Wed, Apr 24, 2013 at 10:44 AM, Yao Qi <yao@codesourcery.com> wrote:
> On 04/24/2013 07:59 AM, Hui Zhu wrote:
>>
>> 2013-04-23 Yao Qi<yao@codesourcery.com>
>> Hui Zhu<hui@codesourcery.com>
>>
>> PR gdb/15075
>
> ^^^^^^^^^^^^ "PR breakpoints/15075"
>
>
>>
>> * breakpoint.c (bpstat_stop_status): Call b->ops->after_cond.
>> (update_dprintf_command_list): Don't append "continue" command
>> to the command of dprintf breakpoint.
>> (base_breakpoint_after_cond): New.
>> (base_breakpoint_ops): Add base_breakpoint_after_cond.
>> (dprintf_after_cond): New.
>> (initialize_breakpoint_ops): Set dprintf_after_cond.
>> * breakpoint.h (breakpoint_ops): Add after_cond.
>>
>> 2013-04-23 Hui Zhu<hui@codesourcery.com>
>>
>> PR gdb/15075
>>
>> * gdb.base/dprintf.exp: Remove "continue" from "info breakpoint"
>> test.
>
> We also need to stop checking "continue" in gdb.mi/mi-breakpoint-changed.exp
> also, as what patch [1] does. B.T.W, why don't you add
> gdb.base/pr15075.[c,exp] from patch [1]?
>
> --
> Yao (齐尧)
>
> [1] http://sourceware.org/ml/gdb-patches/2013-02/msg00736.html
Oops, I am sorry that the discussion threads confused me. Post a new
version for it.
And I didn't include the "disallows setting commands for dprintf"
patch because looks it is still in discussion.
Thanks,
Hui
2013-04-23 Yao Qi <yao@codesourcery.com>
Hui Zhu <hui@codesourcery.com>
PR breakpoints/15075
* breakpoint.c (bpstat_stop_status): Call b->ops->after_cond.
(update_dprintf_command_list): Don't append "continue" command
to the command of dprintf breakpoint.
(base_breakpoint_after_cond): New.
(base_breakpoint_ops): Add base_breakpoint_after_cond.
(dprintf_after_cond): New.
(initialize_breakpoint_ops): Set dprintf_after_cond.
* breakpoint.h (breakpoint_ops): Add after_cond.
2013-04-23 Yao Qi <yao@codesourcery.com>
PR breakpoints/15075
* gdb.base/dprintf.exp: DOn't check "continue" in the output
of "info breakpoints".
* gdb.mi/mi-breakpoint-changed.exp (test_insert_delete_modify):
Don't check "continue" in script field.
* gdb.base/pr15075.c: New.
* gdb.base/pr15075.exp: New.
[-- Attachment #2: dprintf-continue.txt --]
[-- Type: text/plain, Size: 3773 bytes --]
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -5296,13 +5296,7 @@ bpstat_stop_status (struct address_space
b->enable_state = bp_disabled;
removed_any = 1;
}
- if (b->silent)
- bs->print = 0;
- bs->commands = b->commands;
- incref_counted_command_line (bs->commands);
- if (command_line_is_silent (bs->commands
- ? bs->commands->commands : NULL))
- bs->print = 0;
+ b->ops->after_cond (bs);
}
}
@@ -8960,25 +8954,16 @@ update_dprintf_command_list (struct brea
_("Invalid dprintf style."));
gdb_assert (printf_line != NULL);
- /* Manufacture a printf/continue sequence. */
+ /* Manufacture a printf sequence. */
{
- struct command_line *printf_cmd_line, *cont_cmd_line = NULL;
-
- if (strcmp (dprintf_style, dprintf_style_agent) != 0)
- {
- cont_cmd_line = xmalloc (sizeof (struct command_line));
- cont_cmd_line->control_type = simple_control;
- cont_cmd_line->body_count = 0;
- cont_cmd_line->body_list = NULL;
- cont_cmd_line->next = NULL;
- cont_cmd_line->line = xstrdup ("continue");
- }
+ struct command_line *printf_cmd_line
+ = xmalloc (sizeof (struct command_line));
printf_cmd_line = xmalloc (sizeof (struct command_line));
printf_cmd_line->control_type = simple_control;
printf_cmd_line->body_count = 0;
printf_cmd_line->body_list = NULL;
- printf_cmd_line->next = cont_cmd_line;
+ printf_cmd_line->next = NULL;
printf_cmd_line->line = printf_line;
breakpoint_set_commands (b, printf_cmd_line);
@@ -12764,6 +12749,22 @@ base_breakpoint_explains_signal (struct
return BPSTAT_SIGNAL_HIDE;
}
+/* The default 'after_cond' method. */
+
+static void
+base_breakpoint_after_cond (struct bpstats *bs)
+{
+ struct breakpoint *b = bs->breakpoint_at;
+
+ if (b->silent)
+ bs->print = 0;
+ bs->commands = b->commands;
+ incref_counted_command_line (bs->commands);
+ if (command_line_is_silent (bs->commands
+ ? bs->commands->commands : NULL))
+ bs->print = 0;
+}
+
struct breakpoint_ops base_breakpoint_ops =
{
base_breakpoint_dtor,
@@ -12783,7 +12784,8 @@ struct breakpoint_ops base_breakpoint_op
base_breakpoint_create_sals_from_address,
base_breakpoint_create_breakpoints_sal,
base_breakpoint_decode_linespec,
- base_breakpoint_explains_signal
+ base_breakpoint_explains_signal,
+ base_breakpoint_after_cond,
};
/* Default breakpoint_ops methods. */
@@ -13377,6 +13379,24 @@ dprintf_print_recreate (struct breakpoin
print_recreate_thread (tp, fp);
}
+/* Implement the "after_cond" breakpoint_ops method for dprintf. */
+
+static void
+dprintf_after_cond (struct bpstats *bs)
+{
+ bpstat tmp;
+ struct breakpoint *b = bs->breakpoint_at;
+
+ bs->stop = 0;
+ bs->print = 0;
+ bs->commands = b->commands;
+ tmp = bs->next;
+ bs->next = tmp;
+ incref_counted_command_line (bs->commands);
+ bpstat_do_actions_1 (&bs);
+ bs->next = tmp;
+}
+
/* The breakpoint_ops structure to be used on static tracepoints with
markers (`-m'). */
@@ -15873,6 +15893,7 @@ initialize_breakpoint_ops (void)
ops->print_it = bkpt_print_it;
ops->print_mention = bkpt_print_mention;
ops->print_recreate = dprintf_print_recreate;
+ ops->after_cond = dprintf_after_cond;
}
/* Chain containing all defined "enable breakpoint" subcommands. */
--- a/gdb/breakpoint.h
+++ b/gdb/breakpoint.h
@@ -614,6 +614,9 @@ struct breakpoint_ops
'catch signal' interact properly with 'handle'; see
bpstat_explains_signal. */
enum bpstat_signal_value (*explains_signal) (struct breakpoint *);
+
+ /* Do some setup after check condition is true. */
+ void (*after_cond) (struct bpstats *bs);
};
/* Helper for breakpoint_ops->print_recreate implementations. Prints
[-- Attachment #3: dprintf-continue-test.txt --]
[-- Type: text/plain, Size: 3231 bytes --]
--- a/gdb/testsuite/gdb.base/dprintf.exp
+++ b/gdb/testsuite/gdb.base/dprintf.exp
@@ -50,10 +50,8 @@ gdb_test_sequence "info breakpoints" "dp
"\[\r\n\]2 breakpoint"
"\[\r\n\]3 dprintf"
"\[\r\n\] printf \"At foo entry\\\\n\""
- "\[\r\n\] continue"
"\[\r\n\]4 dprintf"
"\[\r\n\] printf \"arg=%d, g=%d\\\\n\", arg, g"
- "\[\r\n\] continue"
}
gdb_test "break $bp_location1" \
--- /dev/null
+++ b/gdb/testsuite/gdb.base/pr15075.c
@@ -0,0 +1,26 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright (C) 2013 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+int
+main(void)
+ {
+ int x = 5;
+
+ ++x;
+ ++x; /* set dprintf here */
+ return x - 7;
+ }
--- /dev/null
+++ b/gdb/testsuite/gdb.base/pr15075.exp
@@ -0,0 +1,38 @@
+# Copyright 2013 Free Software Foundation, Inc.
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+standard_testfile
+
+set executable $testfile
+set expfile $testfile.exp
+
+set dp_location [gdb_get_line_number "set dprintf here"]
+
+if [prepare_for_testing $expfile $executable $srcfile {debug}] {
+ untested "failed to prepare for trace tests"
+ return -1
+}
+
+if ![runto_main] {
+ fail "Can't run to main"
+ return -1
+}
+
+gdb_test "dprintf $dp_location, \"%d\\n\", x" \
+ "Dprintf .*"
+
+gdb_test "next" ".*" "next 1"
+gdb_test "next" ".*" "next 2"
+# Test inferior doesn't exit.
+gdb_test "p x" ".* = 6"
--- a/gdb/testsuite/gdb.mi/mi-breakpoint-changed.exp
+++ b/gdb/testsuite/gdb.mi/mi-breakpoint-changed.exp
@@ -96,7 +96,7 @@ proc test_insert_delete_modify { } {
$test
set test "dprintf marker, \"arg\" \""
mi_gdb_test $test \
- {.*=breakpoint-created,bkpt=\{number="6",type="dprintf".*,script=\{\"printf \\\\\"arg\\\\\" \\\\\"\",\"continue\"\}.*\}\r\n\^done} \
+ {.*=breakpoint-created,bkpt=\{number="6",type="dprintf".*,script=\{\"printf \\\\\"arg\\\\\" \\\\\"\"\}.*\}\r\n\^done} \
$test
# 2. when modifying condition
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [RFC] PR 15075 dprintf interferes with "next"
2013-04-24 14:09 ` Hui Zhu
@ 2013-05-16 7:29 ` Hui Zhu
2013-05-17 21:01 ` Pedro Alves
0 siblings, 1 reply; 45+ messages in thread
From: Hui Zhu @ 2013-05-16 7:29 UTC (permalink / raw)
To: gdb-patches; +Cc: Keith Seitz, Tom Tromey, Yao Qi
[-- Attachment #1: Type: text/plain, Size: 3753 bytes --]
Hi,
Because this patch also can handle bug 15434, I updated the test
patches to add test dprintf with non-stop mode.
Thanks,
Hui
2013-05-16 Yao Qi <yao@codesourcery.com>
Hui Zhu <hui@codesourcery.com>
PR breakpoints/15075
PR breakpoints/15434
* breakpoint.c (bpstat_stop_status): Call b->ops->after_cond.
(update_dprintf_command_list): Don't append "continue" command
to the command of dprintf breakpoint.
(base_breakpoint_after_cond): New.
(base_breakpoint_ops): Add base_breakpoint_after_cond.
(dprintf_after_cond): New.
(initialize_breakpoint_ops): Set dprintf_after_cond.
* breakpoint.h (breakpoint_ops): Add after_cond.
2013-05-16 Yao Qi <yao@codesourcery.com>
Hui Zhu <hui@codesourcery.com>
PR breakpoints/15075
PR breakpoints/15434
* gdb.base/dprintf.exp: Don't check "continue" in the output
of "info breakpoints".
Add test dprintf with non-stop mode.
* gdb.base/dprintf.c: Add a sleep for test dprintf with non-stop
mode.
* gdb.mi/mi-breakpoint-changed.exp (test_insert_delete_modify):
Don't check "continue" in script field.
* gdb.base/pr15075.c: New.
* gdb.base/pr15075.exp: New.
On Wed, Apr 24, 2013 at 11:18 AM, Hui Zhu <teawater@gmail.com> wrote:
> On Wed, Apr 24, 2013 at 10:44 AM, Yao Qi <yao@codesourcery.com> wrote:
>> On 04/24/2013 07:59 AM, Hui Zhu wrote:
>>>
>>> 2013-04-23 Yao Qi<yao@codesourcery.com>
>>> Hui Zhu<hui@codesourcery.com>
>>>
>>> PR gdb/15075
>>
>> ^^^^^^^^^^^^ "PR breakpoints/15075"
>>
>>
>>>
>>> * breakpoint.c (bpstat_stop_status): Call b->ops->after_cond.
>>> (update_dprintf_command_list): Don't append "continue" command
>>> to the command of dprintf breakpoint.
>>> (base_breakpoint_after_cond): New.
>>> (base_breakpoint_ops): Add base_breakpoint_after_cond.
>>> (dprintf_after_cond): New.
>>> (initialize_breakpoint_ops): Set dprintf_after_cond.
>>> * breakpoint.h (breakpoint_ops): Add after_cond.
>>>
>>> 2013-04-23 Hui Zhu<hui@codesourcery.com>
>>>
>>> PR gdb/15075
>>>
>>> * gdb.base/dprintf.exp: Remove "continue" from "info breakpoint"
>>> test.
>>
>> We also need to stop checking "continue" in gdb.mi/mi-breakpoint-changed.exp
>> also, as what patch [1] does. B.T.W, why don't you add
>> gdb.base/pr15075.[c,exp] from patch [1]?
>>
>> --
>> Yao (齐尧)
>>
>> [1] http://sourceware.org/ml/gdb-patches/2013-02/msg00736.html
>
> Oops, I am sorry that the discussion threads confused me. Post a new
> version for it.
>
> And I didn't include the "disallows setting commands for dprintf"
> patch because looks it is still in discussion.
>
> Thanks,
> Hui
>
> 2013-04-23 Yao Qi <yao@codesourcery.com>
> Hui Zhu <hui@codesourcery.com>
>
> PR breakpoints/15075
>
> * breakpoint.c (bpstat_stop_status): Call b->ops->after_cond.
> (update_dprintf_command_list): Don't append "continue" command
> to the command of dprintf breakpoint.
> (base_breakpoint_after_cond): New.
> (base_breakpoint_ops): Add base_breakpoint_after_cond.
> (dprintf_after_cond): New.
> (initialize_breakpoint_ops): Set dprintf_after_cond.
> * breakpoint.h (breakpoint_ops): Add after_cond.
>
> 2013-04-23 Yao Qi <yao@codesourcery.com>
>
> PR breakpoints/15075
>
> * gdb.base/dprintf.exp: DOn't check "continue" in the output
> of "info breakpoints".
> * gdb.mi/mi-breakpoint-changed.exp (test_insert_delete_modify):
> Don't check "continue" in script field.
> * gdb.base/pr15075.c: New.
> * gdb.base/pr15075.exp: New.
[-- Attachment #2: dprintf-continue.txt --]
[-- Type: text/plain, Size: 3773 bytes --]
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -5283,13 +5283,7 @@ bpstat_stop_status (struct address_space
b->enable_state = bp_disabled;
removed_any = 1;
}
- if (b->silent)
- bs->print = 0;
- bs->commands = b->commands;
- incref_counted_command_line (bs->commands);
- if (command_line_is_silent (bs->commands
- ? bs->commands->commands : NULL))
- bs->print = 0;
+ b->ops->after_cond (bs);
}
}
@@ -8939,25 +8933,16 @@ update_dprintf_command_list (struct brea
_("Invalid dprintf style."));
gdb_assert (printf_line != NULL);
- /* Manufacture a printf/continue sequence. */
+ /* Manufacture a printf sequence. */
{
- struct command_line *printf_cmd_line, *cont_cmd_line = NULL;
-
- if (strcmp (dprintf_style, dprintf_style_agent) != 0)
- {
- cont_cmd_line = xmalloc (sizeof (struct command_line));
- cont_cmd_line->control_type = simple_control;
- cont_cmd_line->body_count = 0;
- cont_cmd_line->body_list = NULL;
- cont_cmd_line->next = NULL;
- cont_cmd_line->line = xstrdup ("continue");
- }
+ struct command_line *printf_cmd_line
+ = xmalloc (sizeof (struct command_line));
printf_cmd_line = xmalloc (sizeof (struct command_line));
printf_cmd_line->control_type = simple_control;
printf_cmd_line->body_count = 0;
printf_cmd_line->body_list = NULL;
- printf_cmd_line->next = cont_cmd_line;
+ printf_cmd_line->next = NULL;
printf_cmd_line->line = printf_line;
breakpoint_set_commands (b, printf_cmd_line);
@@ -12743,6 +12728,22 @@ base_breakpoint_explains_signal (struct
return BPSTAT_SIGNAL_HIDE;
}
+/* The default 'after_cond' method. */
+
+static void
+base_breakpoint_after_cond (struct bpstats *bs)
+{
+ struct breakpoint *b = bs->breakpoint_at;
+
+ if (b->silent)
+ bs->print = 0;
+ bs->commands = b->commands;
+ incref_counted_command_line (bs->commands);
+ if (command_line_is_silent (bs->commands
+ ? bs->commands->commands : NULL))
+ bs->print = 0;
+}
+
struct breakpoint_ops base_breakpoint_ops =
{
base_breakpoint_dtor,
@@ -12762,7 +12763,8 @@ struct breakpoint_ops base_breakpoint_op
base_breakpoint_create_sals_from_address,
base_breakpoint_create_breakpoints_sal,
base_breakpoint_decode_linespec,
- base_breakpoint_explains_signal
+ base_breakpoint_explains_signal,
+ base_breakpoint_after_cond,
};
/* Default breakpoint_ops methods. */
@@ -13356,6 +13358,24 @@ dprintf_print_recreate (struct breakpoin
print_recreate_thread (tp, fp);
}
+/* Implement the "after_cond" breakpoint_ops method for dprintf. */
+
+static void
+dprintf_after_cond (struct bpstats *bs)
+{
+ bpstat tmp;
+ struct breakpoint *b = bs->breakpoint_at;
+
+ bs->stop = 0;
+ bs->print = 0;
+ bs->commands = b->commands;
+ tmp = bs->next;
+ bs->next = tmp;
+ incref_counted_command_line (bs->commands);
+ bpstat_do_actions_1 (&bs);
+ bs->next = tmp;
+}
+
/* The breakpoint_ops structure to be used on static tracepoints with
markers (`-m'). */
@@ -15852,6 +15872,7 @@ initialize_breakpoint_ops (void)
ops->print_it = bkpt_print_it;
ops->print_mention = bkpt_print_mention;
ops->print_recreate = dprintf_print_recreate;
+ ops->after_cond = dprintf_after_cond;
}
/* Chain containing all defined "enable breakpoint" subcommands. */
--- a/gdb/breakpoint.h
+++ b/gdb/breakpoint.h
@@ -614,6 +614,9 @@ struct breakpoint_ops
'catch signal' interact properly with 'handle'; see
bpstat_explains_signal. */
enum bpstat_signal_value (*explains_signal) (struct breakpoint *);
+
+ /* Do some setup after check condition is true. */
+ void (*after_cond) (struct bpstats *bs);
};
/* Helper for breakpoint_ops->print_recreate implementations. Prints
[-- Attachment #3: dprintf-continue-test.txt --]
[-- Type: text/plain, Size: 4808 bytes --]
--- a/gdb/testsuite/gdb.base/dprintf.c
+++ b/gdb/testsuite/gdb.base/dprintf.c
@@ -39,6 +39,9 @@ main (int argc, char *argv[])
foo (loc++);
foo (loc++);
foo (loc++);
+
+ sleep (3);
+
return g;
}
--- a/gdb/testsuite/gdb.base/dprintf.exp
+++ b/gdb/testsuite/gdb.base/dprintf.exp
@@ -50,10 +50,8 @@ gdb_test_sequence "info breakpoints" "dp
"\[\r\n\]2 breakpoint"
"\[\r\n\]3 dprintf"
"\[\r\n\] printf \"At foo entry\\\\n\""
- "\[\r\n\] continue"
"\[\r\n\]4 dprintf"
"\[\r\n\] printf \"arg=%d, g=%d\\\\n\", arg, g"
- "\[\r\n\] continue"
}
gdb_test "break $bp_location1" \
@@ -136,3 +134,41 @@ if $target_can_dprintf {
gdb_test "set dprintf-style foobar" "Undefined item: \"foobar\"." \
"Set dprintf style to an unrecognized type"
+
+# Test dprintf with non-stop mode.
+# The testfile uses "run". The real bug happened only for ![is_remote target].
+if [target_info exists use_gdb_stub] {
+ unsupported "dprintf with non-stop mode"
+ return 0
+}
+gdb_test_no_output "delete 2 5"
+send_gdb "kill\n"
+gdb_expect 120 {
+ -re "Kill the program being debugged. .y or n. $" {
+ send_gdb "y\n"
+ verbose "\t\tKilling previous program being debugged"
+ exp_continue
+ }
+ -re "$gdb_prompt $" {
+ # OK.
+ }
+}
+gdb_test_no_output "set dprintf-style gdb" "Set dprintf style to gdb"
+gdb_test_no_output "set target-async on"
+gdb_test_no_output "set non-stop on"
+set gdbindex_warning_re "warning: Skipping \[^\r\n\]+ \\.gdb_index section \[^\r\n\]*\r\nDo \"set use-deprecated-index-sections on\" before the file is read\r\nto use the section anyway\\."
+
+gdb_test "run &" "Starting program: \[^\r\n\]*(\r\n$gdbindex_warning_re)?"
+gdb_test "shell echo foo" "foo"
+set test "interrupt"
+gdb_test_multiple $test $test {
+ -re "interrupt\r\n$gdb_prompt " {
+ pass $test
+ }
+}
+set test "process stopped"
+gdb_test_multiple "" $test {
+ -re "\r\n\\\[process \[0-9\]+\\\] #1 stopped\\\.\r\n" {
+ pass $test
+ }
+}
--- /dev/null
+++ b/gdb/testsuite/gdb.base/pr15075.c
@@ -0,0 +1,26 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright (C) 2013 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+int
+main(void)
+ {
+ int x = 5;
+
+ ++x;
+ ++x; /* set dprintf here */
+ return x - 7;
+ }
--- /dev/null
+++ b/gdb/testsuite/gdb.base/pr15075.exp
@@ -0,0 +1,38 @@
+# Copyright 2013 Free Software Foundation, Inc.
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+standard_testfile
+
+set executable $testfile
+set expfile $testfile.exp
+
+set dp_location [gdb_get_line_number "set dprintf here"]
+
+if [prepare_for_testing $expfile $executable $srcfile {debug}] {
+ untested "failed to prepare for trace tests"
+ return -1
+}
+
+if ![runto_main] {
+ fail "Can't run to main"
+ return -1
+}
+
+gdb_test "dprintf $dp_location, \"%d\\n\", x" \
+ "Dprintf .*"
+
+gdb_test "next" ".*" "next 1"
+gdb_test "next" ".*" "next 2"
+# Test inferior doesn't exit.
+gdb_test "p x" ".* = 6"
--- a/gdb/testsuite/gdb.mi/mi-breakpoint-changed.exp
+++ b/gdb/testsuite/gdb.mi/mi-breakpoint-changed.exp
@@ -96,7 +96,7 @@ proc test_insert_delete_modify { } {
$test
set test "dprintf marker, \"arg\" \""
mi_gdb_test $test \
- {.*=breakpoint-created,bkpt=\{number="6",type="dprintf".*,script=\{\"printf \\\\\"arg\\\\\" \\\\\"\",\"continue\"\}.*\}\r\n\^done} \
+ {.*=breakpoint-created,bkpt=\{number="6",type="dprintf".*,script=\{\"printf \\\\\"arg\\\\\" \\\\\"\"\}.*\}\r\n\^done} \
$test
# 2. when modifying condition
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [RFC] PR 15075 dprintf interferes with "next"
2013-05-16 7:29 ` Hui Zhu
@ 2013-05-17 21:01 ` Pedro Alves
2013-05-22 10:22 ` Hui Zhu
0 siblings, 1 reply; 45+ messages in thread
From: Pedro Alves @ 2013-05-17 21:01 UTC (permalink / raw)
To: Hui Zhu; +Cc: gdb-patches, Keith Seitz, Tom Tromey, Yao Qi
On 05/16/2013 08:28 AM, Hui Zhu wrote:
> Hi,
>
> Because this patch also can handle bug 15434, I updated the test
> patches to add test dprintf with non-stop mode.
Looks like the test is racy. :-/ I got:
At foo entry
arg=1235, g=2222
iAt foo entry
ntarg=1236, g=3013
errupt
(gdb) FAIL: gdb.base/dprintf.exp: interrupt
This will need to be sorted out.
I also saw:
(gdb) At foo entry
arg=1235, g=2222
At foo entry
arg=1236, g=3013
[Inferior 1 (process 30651) exited with code 0152]
FAIL: gdb.base/dprintf.exp: shell echo foo (timeout)
interrupt
../../src/gdb/thread.c:694: internal-error: set_stop_requested: Assertion `tp' failed.
A problem internal to GDB has been detected,
further debugging may prove unreliable.
Quit this debugging session? (y or n) FAIL: gdb.base/dprintf.exp: interrupt (GDB internal error)
Resyncing due to internal error.
n
../../src/gdb/thread.c:694: internal-error: set_stop_requested: Assertion `tp' failed.
A problem internal to GDB has been detected,
further debugging may prove unreliable.
Create a core file of GDB? (y or n) n
(gdb) FAIL: gdb.base/dprintf.exp: process stopped (timeout)
testcase ../../../src/gdb/testsuite/gdb.base/dprintf.exp completed in 20 seconds
:-( Though that's likely unrelated.
> 2013-05-16 Yao Qi <yao@codesourcery.com>
> Hui Zhu <hui@codesourcery.com>
>
> PR breakpoints/15075
> PR breakpoints/15434
> * breakpoint.c (bpstat_stop_status): Call b->ops->after_cond.
> (update_dprintf_command_list): Don't append "continue" command
> to the command of dprintf breakpoint.
"to the command list."
> (base_breakpoint_after_cond): New.
> (base_breakpoint_ops): Add base_breakpoint_after_cond.
> (dprintf_after_cond): New.
Say "New function."
> (initialize_breakpoint_ops): Set dprintf_after_cond.
> * breakpoint.h (breakpoint_ops): Add after_cond.
>
> 2013-05-16 Yao Qi <yao@codesourcery.com>
> Hui Zhu <hui@codesourcery.com>
>
> PR breakpoints/15075
> PR breakpoints/15434
> * gdb.base/dprintf.exp: Don't check "continue" in the output
> of "info breakpoints".
> Add test dprintf with non-stop mode.
Add test for dprintf in non-stop mode.
> * gdb.base/dprintf.c: Add a sleep for test dprintf with non-stop
for testing.
> mode.
> * gdb.mi/mi-breakpoint-changed.exp (test_insert_delete_modify):
> Don't check "continue" in script field.
> * gdb.base/pr15075.c: New.
> * gdb.base/pr15075.exp: New.
>
>
>
> --- a/gdb/breakpoint.c
> +++ b/gdb/breakpoint.c
> @@ -5283,13 +5283,7 @@ bpstat_stop_status (struct address_space
> b->enable_state = bp_disabled;
> removed_any = 1;
> }
> - if (b->silent)
> - bs->print = 0;
> - bs->commands = b->commands;
> - incref_counted_command_line (bs->commands);
> - if (command_line_is_silent (bs->commands
> - ? bs->commands->commands : NULL))
> - bs->print = 0;
> + b->ops->after_cond (bs);
> }
>
> }
> @@ -8939,25 +8933,16 @@ update_dprintf_command_list (struct brea
> _("Invalid dprintf style."));
>
> gdb_assert (printf_line != NULL);
> - /* Manufacture a printf/continue sequence. */
> + /* Manufacture a printf sequence. */
> {
> - struct command_line *printf_cmd_line, *cont_cmd_line = NULL;
> -
> - if (strcmp (dprintf_style, dprintf_style_agent) != 0)
> - {
> - cont_cmd_line = xmalloc (sizeof (struct command_line));
> - cont_cmd_line->control_type = simple_control;
> - cont_cmd_line->body_count = 0;
> - cont_cmd_line->body_list = NULL;
> - cont_cmd_line->next = NULL;
> - cont_cmd_line->line = xstrdup ("continue");
> - }
> + struct command_line *printf_cmd_line
> + = xmalloc (sizeof (struct command_line));
>
> printf_cmd_line = xmalloc (sizeof (struct command_line));
> printf_cmd_line->control_type = simple_control;
> printf_cmd_line->body_count = 0;
> printf_cmd_line->body_list = NULL;
> - printf_cmd_line->next = cont_cmd_line;
> + printf_cmd_line->next = NULL;
> printf_cmd_line->line = printf_line;
>
> breakpoint_set_commands (b, printf_cmd_line);
> @@ -12743,6 +12728,22 @@ base_breakpoint_explains_signal (struct
> return BPSTAT_SIGNAL_HIDE;
> }
>
> +/* The default 'after_cond' method. */
You used '' here.
> +
> +static void
> +base_breakpoint_after_cond (struct bpstats *bs)
> +{
> + struct breakpoint *b = bs->breakpoint_at;
> +
> + if (b->silent)
> + bs->print = 0;
> + bs->commands = b->commands;
> + incref_counted_command_line (bs->commands);
> + if (command_line_is_silent (bs->commands
> + ? bs->commands->commands : NULL))
> + bs->print = 0;
Indentation is wrong here.
I think we can keep all these where it was.
> +}
> +
> +/* Implement the "after_cond" breakpoint_ops method for dprintf. */
You used "" here. :-) Spurious double space before breakpoint_ops.
> +
> +static void
> +dprintf_after_cond (struct bpstats *bs)
> +{
> + bpstat tmp;
> + struct breakpoint *b = bs->breakpoint_at;
> +
> + bs->stop = 0;
> + bs->print = 0;
If we make dprintf's silent (b->silent = 0), then bs->print will
end up 0 for them too, given the:
if (b->silent)
bs->print = 0;
bit.
Not sure even that is necessary, given bs->stop==0 and:
/* Print nothing for this entry if we don't stop or don't
print. */
if (!bs->stop || !bs->print)
bs->print_it = print_it_noop;
> + bs->commands = b->commands;
> + tmp = bs->next;
> + bs->next = tmp;
A = B;
B = A;
?
Was this supposed to be:
A = B;
B = NULL;
?
> + incref_counted_command_line (bs->commands);
If copying all this code here really is necessary, then keep the
incref close to the commands copy, like in the original code.
> + bpstat_do_actions_1 (&bs);
> + bs->next = tmp;
> +}
Could you add some comments explaining what this is
doing, and why?
> +
> /* The breakpoint_ops structure to be used on static tracepoints with
> markers (`-m'). */
>
> @@ -15852,6 +15872,7 @@ initialize_breakpoint_ops (void)
> ops->print_it = bkpt_print_it;
> ops->print_mention = bkpt_print_mention;
> ops->print_recreate = dprintf_print_recreate;
> + ops->after_cond = dprintf_after_cond;
> }
>
> /* Chain containing all defined "enable breakpoint" subcommands. */
> --- a/gdb/breakpoint.h
> +++ b/gdb/breakpoint.h
> @@ -614,6 +614,9 @@ struct breakpoint_ops
> 'catch signal' interact properly with 'handle'; see
> bpstat_explains_signal. */
> enum bpstat_signal_value (*explains_signal) (struct breakpoint *);
> +
> + /* Do some setup after check condition is true. */
/* Called after evaluating the breakpoint's condition,
and only if it evaluated true. */
> + void (*after_cond) (struct bpstats *bs);
I'd rather spell out "cond". I suggest:
void (*after_condition_true) (...);
To be a bit more self descriptive.
> };
>
> /* Helper for breakpoint_ops->print_recreate implementations. Prints
>
>
> dprintf-continue-test.txt
>
>
> --- a/gdb/testsuite/gdb.base/dprintf.c
> +++ b/gdb/testsuite/gdb.base/dprintf.c
> @@ -39,6 +39,9 @@ main (int argc, char *argv[])
> foo (loc++);
> foo (loc++);
> foo (loc++);
> +
> + sleep (3);
> +
> return g;
> }
>
> --- a/gdb/testsuite/gdb.base/dprintf.exp
> +++ b/gdb/testsuite/gdb.base/dprintf.exp
> @@ -50,10 +50,8 @@ gdb_test_sequence "info breakpoints" "dp
> "\[\r\n\]2 breakpoint"
> "\[\r\n\]3 dprintf"
> "\[\r\n\] printf \"At foo entry\\\\n\""
> - "\[\r\n\] continue"
> "\[\r\n\]4 dprintf"
> "\[\r\n\] printf \"arg=%d, g=%d\\\\n\", arg, g"
> - "\[\r\n\] continue"
> }
>
> gdb_test "break $bp_location1" \
> @@ -136,3 +134,41 @@ if $target_can_dprintf {
> gdb_test "set dprintf-style foobar" "Undefined item: \"foobar\"." \
> "Set dprintf style to an unrecognized type"
>
> +
> +# Test dprintf with non-stop mode.
> +# The testfile uses "run". The real bug happened only for ![is_remote target].
It doesn't need to use "run", AFAICS. You can run to
main as usual, and then use "c&" to get the same effect,
and then the test should pass with GDBserver too.
There are targets that don't support non-stop,
and, the call/gdb dprintf styles works on all targets.
The test should be gracefully skipped on those targets.
It might be better to split this to a separate test file.
> +if [target_info exists use_gdb_stub] {
> + unsupported "dprintf with non-stop mode"
> + return 0
> +}
> +gdb_test_no_output "delete 2 5"
> +send_gdb "kill\n"
> +gdb_expect 120 {
> + -re "Kill the program being debugged. .y or n. $" {
> + send_gdb "y\n"
> + verbose "\t\tKilling previous program being debugged"
> + exp_continue
> + }
> + -re "$gdb_prompt $" {
> + # OK.
> + }
> +}
Why do this manually?
> +gdb_test_no_output "set dprintf-style gdb" "Set dprintf style to gdb"
> +gdb_test_no_output "set target-async on"
> +gdb_test_no_output "set non-stop on"
> +set gdbindex_warning_re "warning: Skipping \[^\r\n\]+ \\.gdb_index section \[^\r\n\]*\r\nDo \"set use-deprecated-index-sections on\" before the file is read\r\nto use the section anyway\\."
I don't under why do we need to explicitly check for this warning?
> +gdb_test "run &" "Starting program: \[^\r\n\]*(\r\n$gdbindex_warning_re)?"
> +gdb_test "shell echo foo" "foo"
What's this shell echo for?
> +set test "interrupt"
> +gdb_test_multiple $test $test {
> + -re "interrupt\r\n$gdb_prompt " {
> + pass $test
> + }
> +}
> +set test "process stopped"
> +gdb_test_multiple "" $test {
> + -re "\r\n\\\[process \[0-9\]+\\\] #1 stopped\\\.\r\n" {
> + pass $test
> + }
> +}
> --- /dev/null
> +++ b/gdb/testsuite/gdb.base/pr15075.c
We prefer that test files are named for something that suggests what they
contain, rather than bug numbers. Please call it something
like dprintf-next.exp.
> @@ -0,0 +1,26 @@
> +/* This testcase is part of GDB, the GNU debugger.
> +
> + Copyright (C) 2013 Free Software Foundation, Inc.
> +
> + This program is free software; you can redistribute it and/or modify
> + it under the terms of the GNU General Public License as published by
> + the Free Software Foundation; either version 3 of the License, or
> + (at your option) any later version.
> +
> + This program is distributed in the hope that it will be useful,
> + but WITHOUT ANY WARRANTY; without even the implied warranty of
> + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + GNU General Public License for more details.
> +
> + You should have received a copy of the GNU General Public License
> + along with this program. If not, see <http://www.gnu.org/licenses/>. */
> +
> +int
> +main(void)
Missing space.
> + {
> + int x = 5;
Wrong indentation.
> +
> + ++x;
> + ++x; /* set dprintf here */
> + return x - 7;
> + }
> --- /dev/null
> +++ b/gdb/testsuite/gdb.base/pr15075.exp
> @@ -0,0 +1,38 @@
> +# Copyright 2013 Free Software Foundation, Inc.
> +# This program is free software; you can redistribute it and/or modify
> +# it under the terms of the GNU General Public License as published by
> +# the Free Software Foundation; either version 3 of the License, or
> +# (at your option) any later version.
> +#
> +# This program is distributed in the hope that it will be useful,
> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> +# GNU General Public License for more details.
> +#
> +# You should have received a copy of the GNU General Public License
> +# along with this program. If not, see <http://www.gnu.org/licenses/>.
> +
> +standard_testfile
> +
> +set executable $testfile
> +set expfile $testfile.exp
> +
> +set dp_location [gdb_get_line_number "set dprintf here"]
> +
> +if [prepare_for_testing $expfile $executable $srcfile {debug}] {
> + untested "failed to prepare for trace tests"
This is not a trace test. Actually, prepare_for_testing
already calls untested with whatever we pass it as first argument.
I think it'd be the first such call in the testsuite, but I
think this would be better:
if [prepare_for_testing "failed to prepare for trace tests" \
$executable $srcfile {debug}] {
return -1
}
> +
> +if ![runto_main] {
> + fail "Can't run to main"
> + return -1
> +}
> +
> +gdb_test "dprintf $dp_location, \"%d\\n\", x" \
> + "Dprintf .*"
> +
> +gdb_test "next" ".*" "next 1"
> +gdb_test "next" ".*" "next 2"
Please use more string regexes for these, that confirm the next stopped
at the right lines.
> +# Test inferior doesn't exit.
Check that the inferior didn't exit.
> +gdb_test "p x" ".* = 6"
With the stricter regexes, I don't think this test would be
necessary though.
--
Pedro Alves
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [RFC] PR 15075 dprintf interferes with "next"
2013-05-17 21:01 ` Pedro Alves
@ 2013-05-22 10:22 ` Hui Zhu
2013-05-22 12:46 ` Pedro Alves
2013-05-22 14:04 ` Tom Tromey
0 siblings, 2 replies; 45+ messages in thread
From: Hui Zhu @ 2013-05-22 10:22 UTC (permalink / raw)
To: Pedro Alves; +Cc: gdb-patches, Keith Seitz, Tom Tromey, Yao Qi
[-- Attachment #1: Type: text/plain, Size: 17421 bytes --]
Hi Pedro,
Thanks for your review.
On Sat, May 18, 2013 at 5:01 AM, Pedro Alves <palves@redhat.com> wrote:
> On 05/16/2013 08:28 AM, Hui Zhu wrote:
>> Hi,
>>
>> Because this patch also can handle bug 15434, I updated the test
>> patches to add test dprintf with non-stop mode.
>
> Looks like the test is racy. :-/ I got:
>
> At foo entry
> arg=1235, g=2222
> iAt foo entry
> ntarg=1236, g=3013
> errupt
> (gdb) FAIL: gdb.base/dprintf.exp: interrupt
>
> This will need to be sorted out.
>
> I also saw:
>
> (gdb) At foo entry
> arg=1235, g=2222
> At foo entry
> arg=1236, g=3013
> [Inferior 1 (process 30651) exited with code 0152]
> FAIL: gdb.base/dprintf.exp: shell echo foo (timeout)
> interrupt
> ../../src/gdb/thread.c:694: internal-error: set_stop_requested: Assertion `tp' failed.
> A problem internal to GDB has been detected,
> further debugging may prove unreliable.
> Quit this debugging session? (y or n) FAIL: gdb.base/dprintf.exp: interrupt (GDB internal error)
> Resyncing due to internal error.
> n
> ../../src/gdb/thread.c:694: internal-error: set_stop_requested: Assertion `tp' failed.
> A problem internal to GDB has been detected,
> further debugging may prove unreliable.
> Create a core file of GDB? (y or n) n
> (gdb) FAIL: gdb.base/dprintf.exp: process stopped (timeout)
> testcase ../../../src/gdb/testsuite/gdb.base/dprintf.exp completed in 20 seconds
>
> :-( Though that's likely unrelated.
I updated this part and put it to dpintf-non-stop.exp.
I tried it on fedora and looks it works OK most of times. I only got
trouble is when run this test with remote, [runto main] with
"non-stop" is open will fail sometime.
>
>
>> 2013-05-16 Yao Qi <yao@codesourcery.com>
>> Hui Zhu <hui@codesourcery.com>
>>
>> PR breakpoints/15075
>> PR breakpoints/15434
>> * breakpoint.c (bpstat_stop_status): Call b->ops->after_cond.
>> (update_dprintf_command_list): Don't append "continue" command
>> to the command of dprintf breakpoint.
>
> "to the command list."
Fixed.
>
>> (base_breakpoint_after_cond): New.
>> (base_breakpoint_ops): Add base_breakpoint_after_cond.
>> (dprintf_after_cond): New.
>
> Say "New function."
Fixed.
>
>> (initialize_breakpoint_ops): Set dprintf_after_cond.
>> * breakpoint.h (breakpoint_ops): Add after_cond.
>>
>> 2013-05-16 Yao Qi <yao@codesourcery.com>
>> Hui Zhu <hui@codesourcery.com>
>>
>> PR breakpoints/15075
>> PR breakpoints/15434
>> * gdb.base/dprintf.exp: Don't check "continue" in the output
>> of "info breakpoints".
>> Add test dprintf with non-stop mode.
>
> Add test for dprintf in non-stop mode.
>
>> * gdb.base/dprintf.c: Add a sleep for test dprintf with non-stop
>
> for testing.
Fixed.
>
>> mode.
>> * gdb.mi/mi-breakpoint-changed.exp (test_insert_delete_modify):
>> Don't check "continue" in script field.
>> * gdb.base/pr15075.c: New.
>> * gdb.base/pr15075.exp: New.
>>
>
>
>
>>
>>
>> --- a/gdb/breakpoint.c
>> +++ b/gdb/breakpoint.c
>> @@ -5283,13 +5283,7 @@ bpstat_stop_status (struct address_space
>> b->enable_state = bp_disabled;
>> removed_any = 1;
>> }
>> - if (b->silent)
>> - bs->print = 0;
>> - bs->commands = b->commands;
>> - incref_counted_command_line (bs->commands);
>> - if (command_line_is_silent (bs->commands
>> - ? bs->commands->commands : NULL))
>> - bs->print = 0;
>> + b->ops->after_cond (bs);
>> }
>>
>> }
>> @@ -8939,25 +8933,16 @@ update_dprintf_command_list (struct brea
>> _("Invalid dprintf style."));
>>
>> gdb_assert (printf_line != NULL);
>> - /* Manufacture a printf/continue sequence. */
>> + /* Manufacture a printf sequence. */
>> {
>> - struct command_line *printf_cmd_line, *cont_cmd_line = NULL;
>> -
>> - if (strcmp (dprintf_style, dprintf_style_agent) != 0)
>> - {
>> - cont_cmd_line = xmalloc (sizeof (struct command_line));
>> - cont_cmd_line->control_type = simple_control;
>> - cont_cmd_line->body_count = 0;
>> - cont_cmd_line->body_list = NULL;
>> - cont_cmd_line->next = NULL;
>> - cont_cmd_line->line = xstrdup ("continue");
>> - }
>> + struct command_line *printf_cmd_line
>> + = xmalloc (sizeof (struct command_line));
>>
>> printf_cmd_line = xmalloc (sizeof (struct command_line));
>> printf_cmd_line->control_type = simple_control;
>> printf_cmd_line->body_count = 0;
>> printf_cmd_line->body_list = NULL;
>> - printf_cmd_line->next = cont_cmd_line;
>> + printf_cmd_line->next = NULL;
>> printf_cmd_line->line = printf_line;
>>
>> breakpoint_set_commands (b, printf_cmd_line);
>> @@ -12743,6 +12728,22 @@ base_breakpoint_explains_signal (struct
>> return BPSTAT_SIGNAL_HIDE;
>> }
>>
>
>
>
>> +/* The default 'after_cond' method. */
>
> You used '' here.
Fixed.
>
>> +
>> +static void
>> +base_breakpoint_after_cond (struct bpstats *bs)
>> +{
>> + struct breakpoint *b = bs->breakpoint_at;
>> +
>> + if (b->silent)
>> + bs->print = 0;
>> + bs->commands = b->commands;
>> + incref_counted_command_line (bs->commands);
>> + if (command_line_is_silent (bs->commands
>> + ? bs->commands->commands : NULL))
>> + bs->print = 0;
>
> Indentation is wrong here.
>
> I think we can keep all these where it was.
Fixed.
>
>> +}
>> +
>
>
>> +/* Implement the "after_cond" breakpoint_ops method for dprintf. */
>
> You used "" here. :-) Spurious double space before breakpoint_ops.
Fixed. :)
>
>> +
>> +static void
>> +dprintf_after_cond (struct bpstats *bs)
>> +{
>> + bpstat tmp;
>> + struct breakpoint *b = bs->breakpoint_at;
>> +
>> + bs->stop = 0;
>> + bs->print = 0;
>
> If we make dprintf's silent (b->silent = 0), then bs->print will
> end up 0 for them too, given the:
>
> if (b->silent)
> bs->print = 0;
>
> bit.
>
> Not sure even that is necessary, given bs->stop==0 and:
>
> /* Print nothing for this entry if we don't stop or don't
> print. */
> if (!bs->stop || !bs->print)
> bs->print_it = print_it_noop;
I am not sure about this part.
If my understanding about Tom's review in before is right, the action
of dprintf command should be handled when GDB check the condition.
And after that, dprintf not need be handled.
So dprintf_after_cond just clear the bs->stop and bs->print because
dprintf not need be handled after this function.
And call command of this dprintf because the its condition is true.
I added some comments for that.
>
>> + bs->commands = b->commands;
>> + tmp = bs->next;
>> + bs->next = tmp;
>
> A = B;
> B = A;
>
> ?
>
> Was this supposed to be:
>
> A = B;
> B = NULL;
>
> ?
I think this "bs->next = tmp;" is duplicate line after
bpstat_do_actions_1. Fixed.
>
>> + incref_counted_command_line (bs->commands);
>
> If copying all this code here really is necessary, then keep the
> incref close to the commands copy, like in the original code.
Fixed.
>
>> + bpstat_do_actions_1 (&bs);
>> + bs->next = tmp;
>> +}
>
> Could you add some comments explaining what this is
> doing, and why?
I update this function to following part:
/* Implement the "after_cond" breakpoint_ops method for dprintf. */
static void
dprintf_after_cond (struct bpstats *bs)
{
struct cleanup *old_chain;
struct breakpoint *b = bs->breakpoint_at;
bs->commands = b->commands;
incref_counted_command_line (bs->commands);
/* Because function bpstat_do_actions_1 will execute all the command
list of BS and follow it by BS->NEXT, temporarily set BS->NEXT to
NULL. */
old_chain = make_cleanup_restore_ptr ((void **)&bs->next);
bs->next = NULL;
bpstat_do_actions_1 (&bs);
do_cleanups (old_chain);
/* This dprintf need not be handled after this function
because its command list is executed by bpstat_do_actions_1.
Clear STOP and PRINT for that. */
bs->stop = 0;
bs->print = 0;
}
>
>> +
>> /* The breakpoint_ops structure to be used on static tracepoints with
>> markers (`-m'). */
>>
>> @@ -15852,6 +15872,7 @@ initialize_breakpoint_ops (void)
>> ops->print_it = bkpt_print_it;
>> ops->print_mention = bkpt_print_mention;
>> ops->print_recreate = dprintf_print_recreate;
>> + ops->after_cond = dprintf_after_cond;
>> }
>>
>> /* Chain containing all defined "enable breakpoint" subcommands. */
>> --- a/gdb/breakpoint.h
>> +++ b/gdb/breakpoint.h
>> @@ -614,6 +614,9 @@ struct breakpoint_ops
>> 'catch signal' interact properly with 'handle'; see
>> bpstat_explains_signal. */
>> enum bpstat_signal_value (*explains_signal) (struct breakpoint *);
>> +
>> + /* Do some setup after check condition is true. */
>
> /* Called after evaluating the breakpoint's condition,
> and only if it evaluated true. */
Fixed.
>
>> + void (*after_cond) (struct bpstats *bs);
>
> I'd rather spell out "cond". I suggest:
>
> void (*after_condition_true) (...);
>
> To be a bit more self descriptive.
>
Fixed.
>> };
>>
>> /* Helper for breakpoint_ops->print_recreate implementations. Prints
>>
>>
>> dprintf-continue-test.txt
>>
>>
>> --- a/gdb/testsuite/gdb.base/dprintf.c
>> +++ b/gdb/testsuite/gdb.base/dprintf.c
>> @@ -39,6 +39,9 @@ main (int argc, char *argv[])
>> foo (loc++);
>> foo (loc++);
>> foo (loc++);
>> +
>> + sleep (3);
>> +
>> return g;
>> }
>>
>> --- a/gdb/testsuite/gdb.base/dprintf.exp
>> +++ b/gdb/testsuite/gdb.base/dprintf.exp
>> @@ -50,10 +50,8 @@ gdb_test_sequence "info breakpoints" "dp
>> "\[\r\n\]2 breakpoint"
>> "\[\r\n\]3 dprintf"
>> "\[\r\n\] printf \"At foo entry\\\\n\""
>> - "\[\r\n\] continue"
>> "\[\r\n\]4 dprintf"
>> "\[\r\n\] printf \"arg=%d, g=%d\\\\n\", arg, g"
>> - "\[\r\n\] continue"
>> }
>>
>> gdb_test "break $bp_location1" \
>> @@ -136,3 +134,41 @@ if $target_can_dprintf {
>> gdb_test "set dprintf-style foobar" "Undefined item: \"foobar\"." \
>> "Set dprintf style to an unrecognized type"
>>
>> +
>> +# Test dprintf with non-stop mode.
>> +# The testfile uses "run". The real bug happened only for ![is_remote target].
>
> It doesn't need to use "run", AFAICS. You can run to
> main as usual, and then use "c&" to get the same effect,
> and then the test should pass with GDBserver too.
>
> There are targets that don't support non-stop,
> and, the call/gdb dprintf styles works on all targets.
> The test should be gracefully skipped on those targets.
> It might be better to split this to a separate test file.
Add dprintf-non-stop.exp and dprintf-non-stop.c for it.
>
>> +if [target_info exists use_gdb_stub] {
>> + unsupported "dprintf with non-stop mode"
>> + return 0
>> +}
>> +gdb_test_no_output "delete 2 5"
>> +send_gdb "kill\n"
>> +gdb_expect 120 {
>> + -re "Kill the program being debugged. .y or n. $" {
>> + send_gdb "y\n"
>> + verbose "\t\tKilling previous program being debugged"
>> + exp_continue
>> + }
>> + -re "$gdb_prompt $" {
>> + # OK.
>> + }
>> +}
>
> Why do this manually?
This part was removed.
>
>> +gdb_test_no_output "set dprintf-style gdb" "Set dprintf style to gdb"
>> +gdb_test_no_output "set target-async on"
>> +gdb_test_no_output "set non-stop on"
>> +set gdbindex_warning_re "warning: Skipping \[^\r\n\]+ \\.gdb_index section \[^\r\n\]*\r\nDo \"set use-deprecated-index-sections on\" before the file is read\r\nto use the section anyway\\."
>
> I don't under why do we need to explicitly check for this warning?
Removed too.
>
>> +gdb_test "run &" "Starting program: \[^\r\n\]*(\r\n$gdbindex_warning_re)?"
>> +gdb_test "shell echo foo" "foo"
>
> What's this shell echo for?
This part copy from other test of non-stop. It let test wait some
time then dprintf execution can complete. Now I changed it to exec
sleep 1.
>
>> +set test "interrupt"
>> +gdb_test_multiple $test $test {
>> + -re "interrupt\r\n$gdb_prompt " {
>> + pass $test
>> + }
>> +}
>> +set test "process stopped"
>> +gdb_test_multiple "" $test {
>> + -re "\r\n\\\[process \[0-9\]+\\\] #1 stopped\\\.\r\n" {
>> + pass $test
>> + }
>> +}
>> --- /dev/null
>> +++ b/gdb/testsuite/gdb.base/pr15075.c
>
> We prefer that test files are named for something that suggests what they
> contain, rather than bug numbers. Please call it something
> like dprintf-next.exp.
Fixed.
>
>> @@ -0,0 +1,26 @@
>> +/* This testcase is part of GDB, the GNU debugger.
>> +
>> + Copyright (C) 2013 Free Software Foundation, Inc.
>> +
>> + This program is free software; you can redistribute it and/or modify
>> + it under the terms of the GNU General Public License as published by
>> + the Free Software Foundation; either version 3 of the License, or
>> + (at your option) any later version.
>> +
>> + This program is distributed in the hope that it will be useful,
>> + but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
>> + GNU General Public License for more details.
>> +
>> + You should have received a copy of the GNU General Public License
>> + along with this program. If not, see <http://www.gnu.org/licenses/>. */
>> +
>> +int
>> +main(void)
>
> Missing space.
Fixed.
>
>> + {
>> + int x = 5;
>
> Wrong indentation.
Fixed.
>
>> +
>> + ++x;
>> + ++x; /* set dprintf here */
>> + return x - 7;
>> + }
>> --- /dev/null
>> +++ b/gdb/testsuite/gdb.base/pr15075.exp
>> @@ -0,0 +1,38 @@
>> +# Copyright 2013 Free Software Foundation, Inc.
>> +# This program is free software; you can redistribute it and/or modify
>> +# it under the terms of the GNU General Public License as published by
>> +# the Free Software Foundation; either version 3 of the License, or
>> +# (at your option) any later version.
>> +#
>> +# This program is distributed in the hope that it will be useful,
>> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
>> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
>> +# GNU General Public License for more details.
>> +#
>> +# You should have received a copy of the GNU General Public License
>> +# along with this program. If not, see <http://www.gnu.org/licenses/>.
>> +
>> +standard_testfile
>> +
>> +set executable $testfile
>> +set expfile $testfile.exp
>> +
>> +set dp_location [gdb_get_line_number "set dprintf here"]
>> +
>> +if [prepare_for_testing $expfile $executable $srcfile {debug}] {
>> + untested "failed to prepare for trace tests"
>
> This is not a trace test. Actually, prepare_for_testing
> already calls untested with whatever we pass it as first argument.
> I think it'd be the first such call in the testsuite, but I
> think this would be better:
>
> if [prepare_for_testing "failed to prepare for trace tests" \
> $executable $srcfile {debug}] {
> return -1
> }
After I use this part of code, I got:
ERROR: tcl error sourcing ../../../src/gdb/testsuite/gdb.base/dprintf-next.exp.
ERROR: wrong # args: should be "prepare_for_testing testname
executable ?sources? ?options?"
while executing
"prepare_for_testing "failed to prepare for dprintf next tests""
invoked from within
"if [prepare_for_testing "failed to prepare for dprintf next tests"
$executable $srcfile {debug}] {
return -1
}"
So I change this part to:
if { [prepare_for_testing dprintf-next.exp "dprintf-next" {} {debug}] } {
return -1
}
>
>> +
>> +if ![runto_main] {
>> + fail "Can't run to main"
>> + return -1
>> +}
>> +
>> +gdb_test "dprintf $dp_location, \"%d\\n\", x" \
>> + "Dprintf .*"
>> +
>> +gdb_test "next" ".*" "next 1"
>> +gdb_test "next" ".*" "next 2"
>
> Please use more string regexes for these, that confirm the next stopped
> at the right lines.
Fixed.
>
>> +# Test inferior doesn't exit.
>
> Check that the inferior didn't exit.
>
>> +gdb_test "p x" ".* = 6"
>
> With the stricter regexes, I don't think this test would be
> necessary though.
Removed.
Post new patches according to your comments.
Best,
Hui
2013-05-22 Yao Qi <yao@codesourcery.com>
Hui Zhu <hui@codesourcery.com>
PR breakpoints/15075
PR breakpoints/15434
* utils.c (restore_ptr_closure): New struct.
(restore_ptr, make_cleanup_restore_ptr): New functions.
* utils.h (make_cleanup_restore_ptr): New extern.
* breakpoint.c (bpstat_stop_status): Call
b->ops->after_condition_true.
(update_dprintf_command_list): Don't append "continue" command
to the command list of dprintf breakpoint.
(base_breakpoint_after_condition_true): New function.
(base_breakpoint_ops): Add base_breakpoint_after_condition_true.
(dprintf_after_condition_true): New function.
(initialize_breakpoint_ops): Set dprintf_after_condition_true.
* breakpoint.h (breakpoint_ops): Add after_condition_true.
2013-05-22 Yao Qi <yao@codesourcery.com>
Hui Zhu <hui@codesourcery.com>
PR breakpoints/15075
PR breakpoints/15434
* gdb.base/dprintf-next.c: New file.
* gdb.base/dprintf-next.exp: New file.
* gdb.base/dprintf-non-stop.c: New file.
* gdb.base/dprintf-non-stop.exp: New file.
* gdb.base/dprintf.exp: Don't check "continue" in the output
of "info breakpoints".
* gdb.mi/mi-breakpoint-changed.exp (test_insert_delete_modify):
Don't check "continue" in script field.
[-- Attachment #2: clean_ptr.txt --]
[-- Type: text/plain, Size: 1217 bytes --]
--- a/gdb/utils.c
+++ b/gdb/utils.c
@@ -385,6 +385,35 @@ make_cleanup_restore_uinteger (unsigned
return make_cleanup_restore_integer ((int *) variable);
}
+struct restore_ptr_closure
+{
+ void **variable;
+ void *value;
+};
+
+static void
+restore_ptr (void *p)
+{
+ struct restore_ptr_closure *closure = p;
+
+ *(closure->variable) = closure->value;
+}
+
+/* Remember the current value of *VARIABLE and make it restored when
+ the cleanup is run. */
+
+struct cleanup *
+make_cleanup_restore_ptr (void **variable)
+{
+ struct restore_ptr_closure *c =
+ xmalloc (sizeof (struct restore_ptr_closure));
+
+ c->variable = variable;
+ c->value = *variable;
+
+ return make_cleanup_dtor (restore_ptr, (void *) c, xfree);
+}
+
/* Helper for make_cleanup_unpush_target. */
static void
--- a/gdb/utils.h
+++ b/gdb/utils.h
@@ -97,6 +97,7 @@ extern struct cleanup *make_cleanup_obst
extern struct cleanup *make_cleanup_restore_integer (int *variable);
extern struct cleanup *make_cleanup_restore_uinteger (unsigned int *variable);
+extern struct cleanup *make_cleanup_restore_ptr (void **variable);
struct target_ops;
extern struct cleanup *make_cleanup_unpush_target (struct target_ops *ops);
[-- Attachment #3: dprintf-continue.txt --]
[-- Type: text/plain, Size: 4312 bytes --]
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -5283,13 +5283,7 @@ bpstat_stop_status (struct address_space
b->enable_state = bp_disabled;
removed_any = 1;
}
- if (b->silent)
- bs->print = 0;
- bs->commands = b->commands;
- incref_counted_command_line (bs->commands);
- if (command_line_is_silent (bs->commands
- ? bs->commands->commands : NULL))
- bs->print = 0;
+ b->ops->after_condition_true (bs);
}
}
@@ -8939,25 +8933,16 @@ update_dprintf_command_list (struct brea
_("Invalid dprintf style."));
gdb_assert (printf_line != NULL);
- /* Manufacture a printf/continue sequence. */
+ /* Manufacture a printf sequence. */
{
- struct command_line *printf_cmd_line, *cont_cmd_line = NULL;
-
- if (strcmp (dprintf_style, dprintf_style_agent) != 0)
- {
- cont_cmd_line = xmalloc (sizeof (struct command_line));
- cont_cmd_line->control_type = simple_control;
- cont_cmd_line->body_count = 0;
- cont_cmd_line->body_list = NULL;
- cont_cmd_line->next = NULL;
- cont_cmd_line->line = xstrdup ("continue");
- }
+ struct command_line *printf_cmd_line
+ = xmalloc (sizeof (struct command_line));
printf_cmd_line = xmalloc (sizeof (struct command_line));
printf_cmd_line->control_type = simple_control;
printf_cmd_line->body_count = 0;
printf_cmd_line->body_list = NULL;
- printf_cmd_line->next = cont_cmd_line;
+ printf_cmd_line->next = NULL;
printf_cmd_line->line = printf_line;
breakpoint_set_commands (b, printf_cmd_line);
@@ -12743,6 +12728,22 @@ base_breakpoint_explains_signal (struct
return BPSTAT_SIGNAL_HIDE;
}
+/* The default "after_condition_true" method. */
+
+static void
+base_breakpoint_after_condition_true (struct bpstats *bs)
+{
+ struct breakpoint *b = bs->breakpoint_at;
+
+ if (b->silent)
+ bs->print = 0;
+ bs->commands = b->commands;
+ incref_counted_command_line (bs->commands);
+ if (command_line_is_silent (bs->commands
+ ? bs->commands->commands : NULL))
+ bs->print = 0;
+}
+
struct breakpoint_ops base_breakpoint_ops =
{
base_breakpoint_dtor,
@@ -12762,7 +12763,8 @@ struct breakpoint_ops base_breakpoint_op
base_breakpoint_create_sals_from_address,
base_breakpoint_create_breakpoints_sal,
base_breakpoint_decode_linespec,
- base_breakpoint_explains_signal
+ base_breakpoint_explains_signal,
+ base_breakpoint_after_condition_true,
};
/* Default breakpoint_ops methods. */
@@ -13356,6 +13358,33 @@ dprintf_print_recreate (struct breakpoin
print_recreate_thread (tp, fp);
}
+/* Implement the "after_condition_true" breakpoint_ops method for
+ dprintf. */
+
+static void
+dprintf_after_condition_true (struct bpstats *bs)
+{
+ struct cleanup *old_chain;
+ struct breakpoint *b = bs->breakpoint_at;
+
+ bs->commands = b->commands;
+ incref_counted_command_line (bs->commands);
+
+ /* Because function bpstat_do_actions_1 will execute all the command
+ list of BS and follow it by BS->NEXT, temporarily set BS->NEXT to
+ NULL. */
+ old_chain = make_cleanup_restore_ptr ((void **)&bs->next);
+ bs->next = NULL;
+ bpstat_do_actions_1 (&bs);
+ do_cleanups (old_chain);
+
+ /* This dprintf need not be handled after this function
+ because its command list is executed by bpstat_do_actions_1.
+ Clear STOP and PRINT for that. */
+ bs->stop = 0;
+ bs->print = 0;
+}
+
/* The breakpoint_ops structure to be used on static tracepoints with
markers (`-m'). */
@@ -15852,6 +15881,7 @@ initialize_breakpoint_ops (void)
ops->print_it = bkpt_print_it;
ops->print_mention = bkpt_print_mention;
ops->print_recreate = dprintf_print_recreate;
+ ops->after_condition_true = dprintf_after_condition_true;
}
/* Chain containing all defined "enable breakpoint" subcommands. */
--- a/gdb/breakpoint.h
+++ b/gdb/breakpoint.h
@@ -614,6 +614,10 @@ struct breakpoint_ops
'catch signal' interact properly with 'handle'; see
bpstat_explains_signal. */
enum bpstat_signal_value (*explains_signal) (struct breakpoint *);
+
+ /* Called after evaluating the breakpoint's condition,
+ and only if it evaluated true. */
+ void (*after_condition_true) (struct bpstats *bs);
};
/* Helper for breakpoint_ops->print_recreate implementations. Prints
[-- Attachment #4: dprintf-continue-test.txt --]
[-- Type: text/plain, Size: 5784 bytes --]
--- /dev/null
+++ b/gdb/testsuite/gdb.base/dprintf-next.c
@@ -0,0 +1,26 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright (C) 2013 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+int
+main (void)
+{
+ int x = 5;
+
+ ++x;
+ ++x; /* set dprintf here */
+ return x - 7;
+}
--- /dev/null
+++ b/gdb/testsuite/gdb.base/dprintf-next.exp
@@ -0,0 +1,35 @@
+# Copyright 2013 Free Software Foundation, Inc.
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+standard_testfile
+
+set executable $testfile
+set expfile $testfile.exp
+
+set dp_location [gdb_get_line_number "set dprintf here"]
+
+if { [prepare_for_testing dprintf-next.exp "dprintf-next" {} {debug}] } {
+ return -1
+}
+
+if ![runto_main] {
+ fail "Can't run to main"
+ return -1
+}
+
+gdb_test "dprintf $dp_location, \"%d\\n\", x" \
+ "Dprintf .*"
+
+gdb_test "next" "23.*\\+\\+x.*" "next 1"
+gdb_test "next" "24.*\\+\\+x.*" "next 2"
--- /dev/null
+++ b/gdb/testsuite/gdb.base/dprintf-non-stop.c
@@ -0,0 +1,30 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright (C) 2013 Free Software Foundation, Inc.
+ Contributed by Hui Zhu <hui@codesourcery.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+void
+foo ()
+{
+}
+
+int
+main ()
+{
+ foo ();
+ while (1);
+ return 0;
+}
\ No newline at end of file
--- /dev/null
+++ b/gdb/testsuite/gdb.base/dprintf-non-stop.exp
@@ -0,0 +1,45 @@
+# Copyright (C) 2013 Free Software Foundation, Inc.
+# Contributed by Hui Zhu <hui@codesourcery.com>
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+if { [prepare_for_testing dprintf-non-stop.exp "dprintf-non-stop" {} {debug}] } {
+ return -1
+}
+
+gdb_test_no_output "set target-async on"
+gdb_test_no_output "set non-stop on"
+
+if ![runto main] {
+ fail "Can't run to main"
+ return -1
+}
+
+gdb_test "dprintf foo,\"At foo entry\\n\"" "Dprintf .*"
+
+send_gdb "continue &\n"
+exec sleep 1
+set test "interrupt"
+gdb_test_multiple $test $test {
+ -re "interrupt\r\n$gdb_prompt " {
+ pass $test
+ }
+}
+
+set test "inferior stopped"
+gdb_test_multiple "" $test {
+ -re "\r\n\\\[.* \[0-9\]+\\\] #1 stopped\\\.\r\n" {
+ pass $test
+ }
+}
--- a/gdb/testsuite/gdb.base/dprintf.exp
+++ b/gdb/testsuite/gdb.base/dprintf.exp
@@ -50,10 +50,8 @@ gdb_test_sequence "info breakpoints" "dp
"\[\r\n\]2 breakpoint"
"\[\r\n\]3 dprintf"
"\[\r\n\] printf \"At foo entry\\\\n\""
- "\[\r\n\] continue"
"\[\r\n\]4 dprintf"
"\[\r\n\] printf \"arg=%d, g=%d\\\\n\", arg, g"
- "\[\r\n\] continue"
}
gdb_test "break $bp_location1" \
@@ -135,4 +133,3 @@ if $target_can_dprintf {
gdb_test "set dprintf-style foobar" "Undefined item: \"foobar\"." \
"Set dprintf style to an unrecognized type"
-
--- a/gdb/testsuite/gdb.mi/mi-breakpoint-changed.exp
+++ b/gdb/testsuite/gdb.mi/mi-breakpoint-changed.exp
@@ -96,7 +96,7 @@ proc test_insert_delete_modify { } {
$test
set test "dprintf marker, \"arg\" \""
mi_gdb_test $test \
- {.*=breakpoint-created,bkpt=\{number="6",type="dprintf".*,script=\{\"printf \\\\\"arg\\\\\" \\\\\"\",\"continue\"\}.*\}\r\n\^done} \
+ {.*=breakpoint-created,bkpt=\{number="6",type="dprintf".*,script=\{\"printf \\\\\"arg\\\\\" \\\\\"\"\}.*\}\r\n\^done} \
$test
# 2. when modifying condition
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [RFC] PR 15075 dprintf interferes with "next"
2013-05-22 10:22 ` Hui Zhu
@ 2013-05-22 12:46 ` Pedro Alves
2013-05-28 0:02 ` Hui Zhu
2013-05-22 14:04 ` Tom Tromey
1 sibling, 1 reply; 45+ messages in thread
From: Pedro Alves @ 2013-05-22 12:46 UTC (permalink / raw)
To: Hui Zhu; +Cc: gdb-patches, Keith Seitz, Tom Tromey, Yao Qi
On 05/22/2013 11:21 AM, Hui Zhu wrote:
> I tried it on fedora and looks it works OK most of times. I only got
> trouble is when run this test with remote, [runto main] with
> "non-stop" is open will fail sometime.
Sorry, but "most of the times" is not acceptable. Can you please
figure out why that is so? This should never fail.
>> > Not sure even that is necessary, given bs->stop==0 and:
>> >
>> > /* Print nothing for this entry if we don't stop or don't
>> > print. */
>> > if (!bs->stop || !bs->print)
>> > bs->print_it = print_it_noop;
> I am not sure about this part.
> If my understanding about Tom's review in before is right, the action
> of dprintf command should be handled when GDB check the condition.
> And after that, dprintf not need be handled.
Yes, but I don't see how that counters my suggestion.
>> >
>>> >> + bpstat_do_actions_1 (&bs);
>>> >> + bs->next = tmp;
>>> >> +}
>> >
>> > Could you add some comments explaining what this is
>> > doing, and why?
> I update this function to following part:
> /* Implement the "after_cond" breakpoint_ops method for dprintf. */
>
> static void
> dprintf_after_cond (struct bpstats *bs)
> {
> struct cleanup *old_chain;
> struct breakpoint *b = bs->breakpoint_at;
>
> bs->commands = b->commands;
> incref_counted_command_line (bs->commands);
I still think there's no point in moving this to the
after_condition_true hook, if both existing implementations
end up doing it themselves. See below.
>
> /* Because function bpstat_do_actions_1 will execute all the command
> list of BS and follow it by BS->NEXT, temporarily set BS->NEXT to
> NULL. */
> old_chain = make_cleanup_restore_ptr ((void **)&bs->next);
That cast is invalid actually. Older gcc's will complain about
the aliasing violation. I think we can get away without this, by
passing a separate list with only one entry to bpstat_do_actions_1.
> bs->next = NULL;
> bpstat_do_actions_1 (&bs);
> do_cleanups (old_chain);
>
> /* This dprintf need not be handled after this function
> because its command list is executed by bpstat_do_actions_1.
> Clear STOP and PRINT for that. */
> bs->stop = 0;
> bs->print = 0;
Thanks. I was more looking for general design comments on why we
run the command list here. This also should explain why clear stop
here, instead of on the more natural check_status.
So all in all, if it works for you (seems to work fine for me), I'd
rather do as this patch on top of yours does:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
gdb/breakpoint.c | 62 ++++++++++++++++++++++++++++++++----------------------
1 file changed, 37 insertions(+), 25 deletions(-)
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index 7ef5703..181aecc 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -5292,6 +5292,15 @@ bpstat_stop_status (struct address_space *aspace,
b->enable_state = bp_disabled;
removed_any = 1;
}
+
+ if (b->silent)
+ bs->print = 0;
+ bs->commands = b->commands;
+ incref_counted_command_line (bs->commands);
+ if (command_line_is_silent (bs->commands
+ ? bs->commands->commands : NULL))
+ bs->print = 0;
+
b->ops->after_condition_true (bs);
}
@@ -12742,15 +12751,7 @@ base_breakpoint_explains_signal (struct breakpoint *b)
static void
base_breakpoint_after_condition_true (struct bpstats *bs)
{
- struct breakpoint *b = bs->breakpoint_at;
-
- if (b->silent)
- bs->print = 0;
- bs->commands = b->commands;
- incref_counted_command_line (bs->commands);
- if (command_line_is_silent (bs->commands
- ? bs->commands->commands : NULL))
- bs->print = 0;
+ /* Nothing to do. */
}
struct breakpoint_ops base_breakpoint_ops =
@@ -13368,30 +13369,41 @@ dprintf_print_recreate (struct breakpoint *tp, struct ui_file *fp)
}
/* Implement the "after_condition_true" breakpoint_ops method for
- dprintf. */
+ dprintf.
+
+ dprintf's are implemented with regular commands in their command
+ list, but we run the commands here instead of before presenting the
+ stop to the user, as dprintf's don't actually cause a stop. This
+ also makes it so that the commands of multiple dprintfs at the same
+ address are all handled. */
static void
dprintf_after_condition_true (struct bpstats *bs)
{
struct cleanup *old_chain;
- struct breakpoint *b = bs->breakpoint_at;
+ struct bpstats tmp_bs = { NULL };
+ struct bpstats *tmp_bs_p = &tmp_bs;
- bs->commands = b->commands;
- incref_counted_command_line (bs->commands);
+ /* dprintf's never cause a stop. This wasn't set in the
+ check_status hook instead because that would make the dprintf's
+ condition not be evaluated. */
+ bs->stop = 0;
- /* Because function bpstat_do_actions_1 will execute all the command
- list of BS and follow it by BS->NEXT, temporarily set BS->NEXT to
- NULL. */
- old_chain = make_cleanup_restore_ptr ((void **)&bs->next);
- bs->next = NULL;
- bpstat_do_actions_1 (&bs);
- do_cleanups (old_chain);
+ /* Run the command list here. Take ownership of it instead of
+ copying. We never want these commands to run later in
+ bpstat_do_actions, if a breakpoint that causes a stop happens to
+ be set at same address as this dprintf, or even if running the
+ commands here throws. */
+ tmp_bs.commands = bs->commands;
+ bs->commands = NULL;
+ old_chain = make_cleanup_decref_counted_command_line (&tmp_bs.commands);
- /* This dprintf need not be handled after this function
- because its command list is executed by bpstat_do_actions_1.
- Clear STOP and PRINT for that. */
- bs->stop = 0;
- bs->print = 0;
+ bpstat_do_actions_1 (&tmp_bs_p);
+
+ /* 'tmp_bs.commands' will usually be NULL by now, but
+ bpstat_do_actions_1 may return early without processing the whole
+ list. */
+ do_cleanups (old_chain);
}
/* The breakpoint_ops structure to be used on static tracepoints with
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>>> >> +if [prepare_for_testing $expfile $executable $srcfile {debug}] {
>>> >> + untested "failed to prepare for trace tests"
>> >
>> > This is not a trace test. Actually, prepare_for_testing
>> > already calls untested with whatever we pass it as first argument.
>> > I think it'd be the first such call in the testsuite, but I
>> > think this would be better:
>> >
>> > if [prepare_for_testing "failed to prepare for trace tests" \
>> > $executable $srcfile {debug}] {
>> > return -1
>> > }
> After I use this part of code, I got:
> ERROR: tcl error sourcing ../../../src/gdb/testsuite/gdb.base/dprintf-next.exp.
> ERROR: wrong # args: should be "prepare_for_testing testname
> executable ?sources? ?options?"
> while executing
> "prepare_for_testing "failed to prepare for dprintf next tests""
> invoked from within
> "if [prepare_for_testing "failed to prepare for dprintf next tests"
> $executable $srcfile {debug}] {
> return -1
> }"
Hmm? Oh, it looks like you forgot the '\' at the end of the line.
Please try again.
> So I change this part to:
> if { [prepare_for_testing dprintf-next.exp "dprintf-next" {} {debug}] } {
'dprintf-next.exp' really isn't magical. It's just a string. :-)
> return -1
> }
>>> >> +gdb_test "next" ".*" "next 1"
>>> >> +gdb_test "next" ".*" "next 2"
>> >
>> > Please use more string regexes for these, that confirm the next stopped
>> > at the right lines.
> Fixed.
Sorry, I should have been clearer. Don't do that by checking
line numbers though, as those change when more functions are
added to the test. Just make each line look different instead.
> +
> +gdb_test "dprintf $dp_location, \"%d\\n\", x" \
> + "Dprintf .*"
Please add an explicit 3rd parameter to gdb_test, so that
the line number doesn't appear in gdb.sum.
> +
> +gdb_test "next" "23.*\\+\\+x.*" "next 1"
> +gdb_test "next" "24.*\\+\\+x.*" "next 2"
Do something like this:
gdb_test "next" "\\+\\+x;" "next 1"
gdb_test "next" "\\+\\+x; /* set dprintf here" "next 2"
You could add a comment to the first stepped line to
make that clearer:
gdb_test "next" "\\+\\+x; /* step here.*" "next 1"
gdb_test "next" "\\+\\+x; /* set dprintf here" "next 2"
> --- /dev/null
> +++ b/gdb/testsuite/gdb.base/dprintf-non-stop.c
> @@ -0,0 +1,30 @@
> +/* This testcase is part of GDB, the GNU debugger.
> +
> + Copyright (C) 2013 Free Software Foundation, Inc.
> + Contributed by Hui Zhu <hui@codesourcery.com>
> +
> + This program is free software; you can redistribute it and/or modify
> + it under the terms of the GNU General Public License as published by
> + the Free Software Foundation; either version 3 of the License, or
> + (at your option) any later version.
> +
> + This program is distributed in the hope that it will be useful,
> + but WITHOUT ANY WARRANTY; without even the implied warranty of
> + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + GNU General Public License for more details.
> +
> + You should have received a copy of the GNU General Public License
> + along with this program. If not, see <http://www.gnu.org/licenses/>. */
> +
> +void
> +foo ()
> +{
> +}
> +
> +int
> +main ()
> +{
> + foo ();
> + while (1);
If something goes wrong, like GDB crashing, this could leave the test
running forever, pegging the CPU. Just make it sleep for some
time instead.
> + return 0;
> +}
> \ No newline at end of file
Please watch out for these, and add a newline.
> +gdb_test "dprintf foo,\"At foo entry\\n\"" "Dprintf .*"
> +
> +send_gdb "continue &\n"
> +exec sleep 1
> +set test "interrupt"
> +gdb_test_multiple $test $test {
> + -re "interrupt\r\n$gdb_prompt " {
> + pass $test
> + }
> +}
> +
> +set test "inferior stopped"
> +gdb_test_multiple "" $test {
> + -re "\r\n\\\[.* \[0-9\]+\\\] #1 stopped\\\.\r\n" {
> + pass $test
> + }
> +}
This leaves the prompt in the expect buffer. I think
this is likely to confuse the following test that runs.
--
Pedro Alves
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [RFC] PR 15075 dprintf interferes with "next"
2013-05-22 10:22 ` Hui Zhu
2013-05-22 12:46 ` Pedro Alves
@ 2013-05-22 14:04 ` Tom Tromey
1 sibling, 0 replies; 45+ messages in thread
From: Tom Tromey @ 2013-05-22 14:04 UTC (permalink / raw)
To: Hui Zhu; +Cc: Pedro Alves, gdb-patches, Keith Seitz, Yao Qi
>>>>> "Hui" == Hui Zhu <teawater@gmail.com> writes:
Hui> So I change this part to:
Hui> if { [prepare_for_testing dprintf-next.exp "dprintf-next" {} {debug}] } {
Hui> return -1
Hui> }
I think it is better to use the variables created by standard_testfile.
Tom
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [RFC] PR 15075 dprintf interferes with "next"
2013-05-22 12:46 ` Pedro Alves
@ 2013-05-28 0:02 ` Hui Zhu
2013-05-28 3:36 ` Yao Qi
2013-06-03 4:07 ` Hui Zhu
0 siblings, 2 replies; 45+ messages in thread
From: Hui Zhu @ 2013-05-28 0:02 UTC (permalink / raw)
To: Pedro Alves, Tom Tromey; +Cc: gdb-patches, Keith Seitz, Yao Qi
[-- Attachment #1: Type: text/plain, Size: 13273 bytes --]
Hi Pedro and Tom,
Thanks for your review.
On Wed, May 22, 2013 at 8:46 PM, Pedro Alves <palves@redhat.com> wrote:
> On 05/22/2013 11:21 AM, Hui Zhu wrote:
>
>> I tried it on fedora and looks it works OK most of times. I only got
>> trouble is when run this test with remote, [runto main] with
>> "non-stop" is open will fail sometime.
>
> Sorry, but "most of the times" is not acceptable. Can you please
> figure out why that is so? This should never fail.
I found a issue about remote test and non-stop. Because it doesn't
have a lot of relation with dprintf, I will post a separate patch for
that later.
>
>>> > Not sure even that is necessary, given bs->stop==0 and:
>>> >
>>> > /* Print nothing for this entry if we don't stop or don't
>>> > print. */
>>> > if (!bs->stop || !bs->print)
>>> > bs->print_it = print_it_noop;
>> I am not sure about this part.
>> If my understanding about Tom's review in before is right, the action
>> of dprintf command should be handled when GDB check the condition.
>> And after that, dprintf not need be handled.
>
> Yes, but I don't see how that counters my suggestion.
Added dprintf_create_breakpoints_sal. When dprintf is created, auto
set silent to 0.
>
>>> >
>>>> >> + bpstat_do_actions_1 (&bs);
>>>> >> + bs->next = tmp;
>>>> >> +}
>>> >
>>> > Could you add some comments explaining what this is
>>> > doing, and why?
>> I update this function to following part:
>> /* Implement the "after_cond" breakpoint_ops method for dprintf. */
>>
>> static void
>> dprintf_after_cond (struct bpstats *bs)
>
>
>> {
>> struct cleanup *old_chain;
>> struct breakpoint *b = bs->breakpoint_at;
>>
>> bs->commands = b->commands;
>> incref_counted_command_line (bs->commands);
>
> I still think there's no point in moving this to the
> after_condition_true hook, if both existing implementations
> end up doing it themselves. See below.
>
>>
>> /* Because function bpstat_do_actions_1 will execute all the command
>> list of BS and follow it by BS->NEXT, temporarily set BS->NEXT to
>> NULL. */
>> old_chain = make_cleanup_restore_ptr ((void **)&bs->next);
>
> That cast is invalid actually. Older gcc's will complain about
> the aliasing violation. I think we can get away without this, by
> passing a separate list with only one entry to bpstat_do_actions_1.
>
>> bs->next = NULL;
>> bpstat_do_actions_1 (&bs);
>> do_cleanups (old_chain);
>>
>> /* This dprintf need not be handled after this function
>> because its command list is executed by bpstat_do_actions_1.
>> Clear STOP and PRINT for that. */
>> bs->stop = 0;
>> bs->print = 0;
>
> Thanks. I was more looking for general design comments on why we
> run the command list here. This also should explain why clear stop
> here, instead of on the more natural check_status.
>
> So all in all, if it works for you (seems to work fine for me), I'd
> rather do as this patch on top of yours does:
>
Thanks for this patch. I merged it to dprintf-continue patch.
> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> gdb/breakpoint.c | 62 ++++++++++++++++++++++++++++++++----------------------
> 1 file changed, 37 insertions(+), 25 deletions(-)
>
> diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
> index 7ef5703..181aecc 100644
> --- a/gdb/breakpoint.c
> +++ b/gdb/breakpoint.c
> @@ -5292,6 +5292,15 @@ bpstat_stop_status (struct address_space *aspace,
> b->enable_state = bp_disabled;
> removed_any = 1;
> }
> +
> + if (b->silent)
> + bs->print = 0;
> + bs->commands = b->commands;
> + incref_counted_command_line (bs->commands);
> + if (command_line_is_silent (bs->commands
> + ? bs->commands->commands : NULL))
> + bs->print = 0;
> +
> b->ops->after_condition_true (bs);
> }
>
> @@ -12742,15 +12751,7 @@ base_breakpoint_explains_signal (struct breakpoint *b)
> static void
> base_breakpoint_after_condition_true (struct bpstats *bs)
> {
> - struct breakpoint *b = bs->breakpoint_at;
> -
> - if (b->silent)
> - bs->print = 0;
> - bs->commands = b->commands;
> - incref_counted_command_line (bs->commands);
> - if (command_line_is_silent (bs->commands
> - ? bs->commands->commands : NULL))
> - bs->print = 0;
> + /* Nothing to do. */
> }
>
> struct breakpoint_ops base_breakpoint_ops =
> @@ -13368,30 +13369,41 @@ dprintf_print_recreate (struct breakpoint *tp, struct ui_file *fp)
> }
>
> /* Implement the "after_condition_true" breakpoint_ops method for
> - dprintf. */
> + dprintf.
> +
> + dprintf's are implemented with regular commands in their command
> + list, but we run the commands here instead of before presenting the
> + stop to the user, as dprintf's don't actually cause a stop. This
> + also makes it so that the commands of multiple dprintfs at the same
> + address are all handled. */
>
> static void
> dprintf_after_condition_true (struct bpstats *bs)
> {
> struct cleanup *old_chain;
> - struct breakpoint *b = bs->breakpoint_at;
> + struct bpstats tmp_bs = { NULL };
> + struct bpstats *tmp_bs_p = &tmp_bs;
>
> - bs->commands = b->commands;
> - incref_counted_command_line (bs->commands);
> + /* dprintf's never cause a stop. This wasn't set in the
> + check_status hook instead because that would make the dprintf's
> + condition not be evaluated. */
> + bs->stop = 0;
>
> - /* Because function bpstat_do_actions_1 will execute all the command
> - list of BS and follow it by BS->NEXT, temporarily set BS->NEXT to
> - NULL. */
> - old_chain = make_cleanup_restore_ptr ((void **)&bs->next);
> - bs->next = NULL;
> - bpstat_do_actions_1 (&bs);
> - do_cleanups (old_chain);
> + /* Run the command list here. Take ownership of it instead of
> + copying. We never want these commands to run later in
> + bpstat_do_actions, if a breakpoint that causes a stop happens to
> + be set at same address as this dprintf, or even if running the
> + commands here throws. */
> + tmp_bs.commands = bs->commands;
> + bs->commands = NULL;
> + old_chain = make_cleanup_decref_counted_command_line (&tmp_bs.commands);
>
> - /* This dprintf need not be handled after this function
> - because its command list is executed by bpstat_do_actions_1.
> - Clear STOP and PRINT for that. */
> - bs->stop = 0;
> - bs->print = 0;
> + bpstat_do_actions_1 (&tmp_bs_p);
> +
> + /* 'tmp_bs.commands' will usually be NULL by now, but
> + bpstat_do_actions_1 may return early without processing the whole
> + list. */
> + do_cleanups (old_chain);
> }
>
> /* The breakpoint_ops structure to be used on static tracepoints with
> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>
>>>> >> +if [prepare_for_testing $expfile $executable $srcfile {debug}] {
>>>> >> + untested "failed to prepare for trace tests"
>>> >
>>> > This is not a trace test. Actually, prepare_for_testing
>>> > already calls untested with whatever we pass it as first argument.
>>> > I think it'd be the first such call in the testsuite, but I
>>> > think this would be better:
>>> >
>>> > if [prepare_for_testing "failed to prepare for trace tests" \
>>> > $executable $srcfile {debug}] {
>>> > return -1
>>> > }
>> After I use this part of code, I got:
>> ERROR: tcl error sourcing ../../../src/gdb/testsuite/gdb.base/dprintf-next.exp.
>> ERROR: wrong # args: should be "prepare_for_testing testname
>> executable ?sources? ?options?"
>> while executing
>> "prepare_for_testing "failed to prepare for dprintf next tests""
>> invoked from within
>> "if [prepare_for_testing "failed to prepare for dprintf next tests"
>> $executable $srcfile {debug}] {
>> return -1
>> }"
>
> Hmm? Oh, it looks like you forgot the '\' at the end of the line.
> Please try again.
Fixed both dprintf-next.exp and dprintf-non-stop.exp.
>
>> So I change this part to:
>> if { [prepare_for_testing dprintf-next.exp "dprintf-next" {} {debug}] } {
>
> 'dprintf-next.exp' really isn't magical. It's just a string. :-)
>
>> return -1
>> }
>
>>>> >> +gdb_test "next" ".*" "next 1"
>>>> >> +gdb_test "next" ".*" "next 2"
>>> >
>>> > Please use more string regexes for these, that confirm the next stopped
>>> > at the right lines.
>> Fixed.
>
> Sorry, I should have been clearer. Don't do that by checking
> line numbers though, as those change when more functions are
> added to the test. Just make each line look different instead.
>
>> +
>> +gdb_test "dprintf $dp_location, \"%d\\n\", x" \
>> + "Dprintf .*"
>
> Please add an explicit 3rd parameter to gdb_test, so that
> the line number doesn't appear in gdb.sum.
>
>> +
>> +gdb_test "next" "23.*\\+\\+x.*" "next 1"
>> +gdb_test "next" "24.*\\+\\+x.*" "next 2"
>
> Do something like this:
>
> gdb_test "next" "\\+\\+x;" "next 1"
> gdb_test "next" "\\+\\+x; /* set dprintf here" "next 2"
>
> You could add a comment to the first stepped line to
> make that clearer:
>
> gdb_test "next" "\\+\\+x; /* step here.*" "next 1"
> gdb_test "next" "\\+\\+x; /* set dprintf here" "next 2"
This part is fixed.
>
>
>> --- /dev/null
>> +++ b/gdb/testsuite/gdb.base/dprintf-non-stop.c
>> @@ -0,0 +1,30 @@
>> +/* This testcase is part of GDB, the GNU debugger.
>> +
>> + Copyright (C) 2013 Free Software Foundation, Inc.
>> + Contributed by Hui Zhu <hui@codesourcery.com>
>> +
>> + This program is free software; you can redistribute it and/or modify
>> + it under the terms of the GNU General Public License as published by
>> + the Free Software Foundation; either version 3 of the License, or
>> + (at your option) any later version.
>> +
>> + This program is distributed in the hope that it will be useful,
>> + but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
>> + GNU General Public License for more details.
>> +
>> + You should have received a copy of the GNU General Public License
>> + along with this program. If not, see <http://www.gnu.org/licenses/>. */
>> +
>> +void
>> +foo ()
>> +{
>> +}
>> +
>> +int
>> +main ()
>> +{
>> + foo ();
>> + while (1);
>
> If something goes wrong, like GDB crashing, this could leave the test
> running forever, pegging the CPU. Just make it sleep for some
> time instead.
Changed this part to sleep(3)
>
>> + return 0;
>
>> +}
>> \ No newline at end of file
>
> Please watch out for these, and add a newline.
>
Fixed.
>> +gdb_test "dprintf foo,\"At foo entry\\n\"" "Dprintf .*"
>> +
>> +send_gdb "continue &\n"
>> +exec sleep 1
>> +set test "interrupt"
>> +gdb_test_multiple $test $test {
>> + -re "interrupt\r\n$gdb_prompt " {
>> + pass $test
>> + }
>> +}
>> +
>> +set test "inferior stopped"
>> +gdb_test_multiple "" $test {
>> + -re "\r\n\\\[.* \[0-9\]+\\\] #1 stopped\\\.\r\n" {
>> + pass $test
>> + }
>> +}
>
> This leaves the prompt in the expect buffer. I think
> this is likely to confuse the following test that runs.
>
After change this part to:
gdb_test_multiple "" $test {
-re "\r\n\\\[.* \[0-9\]+\\\] #1 stopped\\\.\r\n$gdb_prompt" {
pass $test
}
}
I got:
Running ../../../src/gdb/testsuite/gdb.base/dprintf-non-stop.exp ...
FAIL: gdb.base/dprintf-non-stop.exp: inferior stopped (timeout)
I thought the reason is:
(gdb) PASS: gdb.base/dprintf-non-stop.exp: interrupt
[process 24118] #1 stopped.
0x00002aaaaad8f830 in nanosleep () from /lib/x86_64-linux-gnu/libc.so.6
FAIL: gdb.base/dprintf-non-stop.exp: inferior stopped (timeout)
There is not $gdb_prompt.
On Wed, May 22, 2013 at 10:04 PM, Tom Tromey <tromey@redhat.com> wrote:
>>>>>> "Hui" == Hui Zhu <teawater@gmail.com> writes:
>
> Hui> So I change this part to:
> Hui> if { [prepare_for_testing dprintf-next.exp "dprintf-next" {} {debug}] } {
> Hui> return -1
> Hui> }
>
> I think it is better to use the variables created by standard_testfile.
Fixed.
The attachments are the new patches.
Best,
Hui
2013-05-28 Yao Qi <yao@codesourcery.com>
Hui Zhu <hui@codesourcery.com>
Pedro Alves <palves@redhat.com>
PR breakpoints/15075
PR breakpoints/15434
* breakpoint.c (bpstat_stop_status): Call
b->ops->after_condition_true.
(update_dprintf_command_list): Don't append "continue" command
to the command list of dprintf breakpoint.
(base_breakpoint_after_condition_true): New function.
(base_breakpoint_ops): Add base_breakpoint_after_condition_true.
(dprintf_create_breakpoints_sal,
dprintf_after_condition_true): New functions.
(initialize_breakpoint_ops): Set dprintf_create_breakpoints_sal
and dprintf_after_condition_true.
* breakpoint.h (breakpoint_ops): Add after_condition_true.
2013-05-28 Yao Qi <yao@codesourcery.com>
Hui Zhu <hui@codesourcery.com>
PR breakpoints/15075
PR breakpoints/15434
* gdb.base/dprintf-next.c: New file.
* gdb.base/dprintf-next.exp: New file.
* gdb.base/dprintf-non-stop.c: New file.
* gdb.base/dprintf-non-stop.exp: New file.
* gdb.base/dprintf.exp: Don't check "continue" in the output
of "info breakpoints".
* gdb.mi/mi-breakpoint-changed.exp (test_insert_delete_modify):
Don't check "continue" in script field.
[-- Attachment #2: dprintf-continue.txt --]
[-- Type: text/plain, Size: 5391 bytes --]
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -5299,6 +5299,8 @@ bpstat_stop_status (struct address_space
if (command_line_is_silent (bs->commands
? bs->commands->commands : NULL))
bs->print = 0;
+
+ b->ops->after_condition_true (bs);
}
}
@@ -8948,25 +8950,16 @@ update_dprintf_command_list (struct brea
_("Invalid dprintf style."));
gdb_assert (printf_line != NULL);
- /* Manufacture a printf/continue sequence. */
+ /* Manufacture a printf sequence. */
{
- struct command_line *printf_cmd_line, *cont_cmd_line = NULL;
-
- if (strcmp (dprintf_style, dprintf_style_agent) != 0)
- {
- cont_cmd_line = xmalloc (sizeof (struct command_line));
- cont_cmd_line->control_type = simple_control;
- cont_cmd_line->body_count = 0;
- cont_cmd_line->body_list = NULL;
- cont_cmd_line->next = NULL;
- cont_cmd_line->line = xstrdup ("continue");
- }
+ struct command_line *printf_cmd_line
+ = xmalloc (sizeof (struct command_line));
printf_cmd_line = xmalloc (sizeof (struct command_line));
printf_cmd_line->control_type = simple_control;
printf_cmd_line->body_count = 0;
printf_cmd_line->body_list = NULL;
- printf_cmd_line->next = cont_cmd_line;
+ printf_cmd_line->next = NULL;
printf_cmd_line->line = printf_line;
breakpoint_set_commands (b, printf_cmd_line);
@@ -12752,6 +12745,14 @@ base_breakpoint_explains_signal (struct
return BPSTAT_SIGNAL_HIDE;
}
+/* The default "after_condition_true" method. */
+
+static void
+base_breakpoint_after_condition_true (struct bpstats *bs)
+{
+ /* Nothing to do. */
+}
+
struct breakpoint_ops base_breakpoint_ops =
{
base_breakpoint_dtor,
@@ -12771,7 +12772,8 @@ struct breakpoint_ops base_breakpoint_op
base_breakpoint_create_sals_from_address,
base_breakpoint_create_breakpoints_sal,
base_breakpoint_decode_linespec,
- base_breakpoint_explains_signal
+ base_breakpoint_explains_signal,
+ base_breakpoint_after_condition_true,
};
/* Default breakpoint_ops methods. */
@@ -13365,6 +13367,76 @@ dprintf_print_recreate (struct breakpoin
print_recreate_thread (tp, fp);
}
+/* Implement the "create_breakpoints_sal" breakpoint_ops method for
+ dprintf. */
+
+static void
+dprintf_create_breakpoints_sal (struct gdbarch *gdbarch,
+ struct linespec_result *canonical,
+ struct linespec_sals *lsal,
+ char *cond_string,
+ char *extra_string,
+ enum bptype type_wanted,
+ enum bpdisp disposition,
+ int thread,
+ int task, int ignore_count,
+ const struct breakpoint_ops *ops,
+ int from_tty, int enabled,
+ int internal, unsigned flags)
+{
+ struct breakpoint *b;
+
+ create_breakpoints_sal_default (gdbarch, canonical, lsal,
+ cond_string, extra_string,
+ type_wanted,
+ disposition, thread, task,
+ ignore_count, ops, from_tty,
+ enabled, internal, flags);
+
+ b = get_breakpoint (breakpoint_count);
+ gdb_assert (b != NULL);
+
+ breakpoint_set_silent (b, 0);
+}
+
+/* Implement the "after_condition_true" breakpoint_ops method for
+ dprintf.
+
+ dprintf's are implemented with regular commands in their command
+ list, but we run the commands here instead of before presenting the
+ stop to the user, as dprintf's don't actually cause a stop. This
+ also makes it so that the commands of multiple dprintfs at the same
+ address are all handled. */
+
+static void
+dprintf_after_condition_true (struct bpstats *bs)
+{
+ struct cleanup *old_chain;
+ struct bpstats tmp_bs = { NULL };
+ struct bpstats *tmp_bs_p = &tmp_bs;
+
+ /* dprintf's never cause a stop. This wasn't set in the
+ check_status hook instead because that would make the dprintf's
+ condition not be evaluated. */
+ bs->stop = 0;
+
+ /* Run the command list here. Take ownership of it instead of
+ copying. We never want these commands to run later in
+ bpstat_do_actions, if a breakpoint that causes a stop happens to
+ be set at same address as this dprintf, or even if running the
+ commands here throws. */
+ tmp_bs.commands = bs->commands;
+ bs->commands = NULL;
+ old_chain = make_cleanup_decref_counted_command_line (&tmp_bs.commands);
+
+ bpstat_do_actions_1 (&tmp_bs_p);
+
+ /* 'tmp_bs.commands' will usually be NULL by now, but
+ bpstat_do_actions_1 may return early without processing the whole
+ list. */
+ do_cleanups (old_chain);
+}
+
/* The breakpoint_ops structure to be used on static tracepoints with
markers (`-m'). */
@@ -15861,6 +15933,8 @@ initialize_breakpoint_ops (void)
ops->print_it = bkpt_print_it;
ops->print_mention = bkpt_print_mention;
ops->print_recreate = dprintf_print_recreate;
+ ops->create_breakpoints_sal = dprintf_create_breakpoints_sal;
+ ops->after_condition_true = dprintf_after_condition_true;
}
/* Chain containing all defined "enable breakpoint" subcommands. */
--- a/gdb/breakpoint.h
+++ b/gdb/breakpoint.h
@@ -614,6 +614,10 @@ struct breakpoint_ops
'catch signal' interact properly with 'handle'; see
bpstat_explains_signal. */
enum bpstat_signal_value (*explains_signal) (struct breakpoint *);
+
+ /* Called after evaluating the breakpoint's condition,
+ and only if it evaluated true. */
+ void (*after_condition_true) (struct bpstats *bs);
};
/* Helper for breakpoint_ops->print_recreate implementations. Prints
[-- Attachment #3: dprintf-continue-test.txt --]
[-- Type: text/plain, Size: 5914 bytes --]
--- /dev/null
+++ b/gdb/testsuite/gdb.base/dprintf-next.c
@@ -0,0 +1,26 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright (C) 2013 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+int
+main (void)
+{
+ int x = 5;
+
+ ++x; /* Next without dprintf. */
+ ++x; /* Set dprintf here. */
+ return x - 7;
+}
--- /dev/null
+++ b/gdb/testsuite/gdb.base/dprintf-next.exp
@@ -0,0 +1,36 @@
+# Copyright 2013 Free Software Foundation, Inc.
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+standard_testfile
+
+set executable $testfile
+set expfile $testfile.exp
+
+set dp_location [gdb_get_line_number "Set dprintf here"]
+
+if [prepare_for_testing "failed to prepare for dprintf with next" \
+ ${testfile} ${srcfile} {debug}] {
+ return -1
+}
+
+if ![runto_main] {
+ fail "Can't run to main"
+ return -1
+}
+
+gdb_test "dprintf $dp_location, \"%d\\n\", x" \
+ "Dprintf .*"
+
+gdb_test "next" "\\+\\+x\;.*\/\* Next without dprintf.*" "next 1"
+gdb_test "next" "\\+\\+x\;.*\/\* Set dprintf here.*" "next 2"
--- /dev/null
+++ b/gdb/testsuite/gdb.base/dprintf-non-stop.c
@@ -0,0 +1,30 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright (C) 2013 Free Software Foundation, Inc.
+ Contributed by Hui Zhu <hui@codesourcery.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+void
+foo ()
+{
+}
+
+int
+main ()
+{
+ foo ();
+ sleep (3);
+ return 0;
+}
--- /dev/null
+++ b/gdb/testsuite/gdb.base/dprintf-non-stop.exp
@@ -0,0 +1,48 @@
+# Copyright (C) 2013 Free Software Foundation, Inc.
+# Contributed by Hui Zhu <hui@codesourcery.com>
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+standard_testfile
+
+if [prepare_for_testing "failed to prepare for dprintf with non-stop" \
+ ${testfile} ${srcfile} {debug}] {
+ return -1
+}
+
+gdb_test_no_output "set target-async on"
+gdb_test_no_output "set non-stop on"
+
+if ![runto main] {
+ fail "Can't run to main"
+ return -1
+}
+
+gdb_test "dprintf foo,\"At foo entry\\n\"" "Dprintf .*"
+
+send_gdb "continue &\n"
+exec sleep 1
+set test "interrupt"
+gdb_test_multiple $test $test {
+ -re "interrupt\r\n$gdb_prompt " {
+ pass $test
+ }
+}
+
+set test "inferior stopped"
+gdb_test_multiple "" $test {
+ -re "\r\n\\\[.* \[0-9\]+\\\] #1 stopped\\\.\r\n" {
+ pass $test
+ }
+}
--- a/gdb/testsuite/gdb.base/dprintf.exp
+++ b/gdb/testsuite/gdb.base/dprintf.exp
@@ -50,10 +50,8 @@ gdb_test_sequence "info breakpoints" "dp
"\[\r\n\]2 breakpoint"
"\[\r\n\]3 dprintf"
"\[\r\n\] printf \"At foo entry\\\\n\""
- "\[\r\n\] continue"
"\[\r\n\]4 dprintf"
"\[\r\n\] printf \"arg=%d, g=%d\\\\n\", arg, g"
- "\[\r\n\] continue"
}
gdb_test "break $bp_location1" \
@@ -135,4 +133,3 @@ if $target_can_dprintf {
gdb_test "set dprintf-style foobar" "Undefined item: \"foobar\"." \
"Set dprintf style to an unrecognized type"
-
--- a/gdb/testsuite/gdb.mi/mi-breakpoint-changed.exp
+++ b/gdb/testsuite/gdb.mi/mi-breakpoint-changed.exp
@@ -96,7 +96,7 @@ proc test_insert_delete_modify { } {
$test
set test "dprintf marker, \"arg\" \""
mi_gdb_test $test \
- {.*=breakpoint-created,bkpt=\{number="6",type="dprintf".*,script=\{\"printf \\\\\"arg\\\\\" \\\\\"\",\"continue\"\}.*\}\r\n\^done} \
+ {.*=breakpoint-created,bkpt=\{number="6",type="dprintf".*,script=\{\"printf \\\\\"arg\\\\\" \\\\\"\"\}.*\}\r\n\^done} \
$test
# 2. when modifying condition
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [RFC] PR 15075 dprintf interferes with "next"
2013-05-28 0:02 ` Hui Zhu
@ 2013-05-28 3:36 ` Yao Qi
2013-05-29 10:08 ` Hui Zhu
2013-06-03 4:07 ` Hui Zhu
1 sibling, 1 reply; 45+ messages in thread
From: Yao Qi @ 2013-05-28 3:36 UTC (permalink / raw)
To: Hui Zhu; +Cc: Pedro Alves, Tom Tromey, gdb-patches, Keith Seitz
On 05/28/2013 08:01 AM, Hui Zhu wrote:
>>> +gdb_test_multiple $test $test {
>>> >>+ -re "interrupt\r\n$gdb_prompt " {
>>> >>+ pass $test
>>> >>+ }
>>> >>+}
>>> >>+
>>> >>+set test "inferior stopped"
>>> >>+gdb_test_multiple "" $test {
>>> >>+ -re "\r\n\\\[.* \[0-9\]+\\\] #1 stopped\\\.\r\n" {
>>> >>+ pass $test
>>> >>+ }
>>> >>+}
>> >
>> >This leaves the prompt in the expect buffer. I think
>> >this is likely to confuse the following test that runs.
>> >
> After change this part to:
> gdb_test_multiple "" $test {
> -re "\r\n\\\[.* \[0-9\]+\\\] #1 stopped\\\.\r\n$gdb_prompt" {
> pass $test
> }
> }
> I got:
> Running ../../../src/gdb/testsuite/gdb.base/dprintf-non-stop.exp ...
> FAIL: gdb.base/dprintf-non-stop.exp: inferior stopped (timeout)
>
because the gdb_prompt has been consumed by the previous matching:
gdb_test_multiple $test $test {
-re "interrupt\r\n$gdb_prompt " {
^^^^^^^^^^^^
pass $test
}
}
> +set test "interrupt"
> +gdb_test_multiple $test $test {
> + -re "interrupt\r\n$gdb_prompt " {
> + pass $test
> + }
> +}
> +
> +set test "inferior stopped"
> +gdb_test_multiple "" $test {
> + -re "\r\n\\\[.* \[0-9\]+\\\] #1 stopped\\\.\r\n" {
> + pass $test
> + }
> +}
I raise a question here that no one asked before, why don't combine
these two gdb_test_multiple into one? like:
set test "interrupt inferior"
gdb_test_multiple "interrupt" $test {
-re "interrupt\r\n.*\\\[.* \[0-9\]+\\\] #1 stopped\\\." {
pass $test
}
}
--
Yao (é½å°§)
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [RFC] PR 15075 dprintf interferes with "next"
2013-05-28 3:36 ` Yao Qi
@ 2013-05-29 10:08 ` Hui Zhu
0 siblings, 0 replies; 45+ messages in thread
From: Hui Zhu @ 2013-05-29 10:08 UTC (permalink / raw)
To: Yao Qi; +Cc: Pedro Alves, Tom Tromey, gdb-patches, Keith Seitz
On Tue, May 28, 2013 at 11:36 AM, Yao Qi <yao@codesourcery.com> wrote:
> On 05/28/2013 08:01 AM, Hui Zhu wrote:
>>>>
>>>> +gdb_test_multiple $test $test {
>>>> >>+ -re "interrupt\r\n$gdb_prompt " {
>>>> >>+ pass $test
>>>> >>+ }
>>>> >>+}
>>>> >>+
>>>> >>+set test "inferior stopped"
>>>> >>+gdb_test_multiple "" $test {
>>>> >>+ -re "\r\n\\\[.* \[0-9\]+\\\] #1 stopped\\\.\r\n" {
>>>> >>+ pass $test
>>>> >>+ }
>>>> >>+}
>>>
>>> >
>>> >This leaves the prompt in the expect buffer. I think
>>> >this is likely to confuse the following test that runs.
>>> >
>>
>> After change this part to:
>> gdb_test_multiple "" $test {
>> -re "\r\n\\\[.* \[0-9\]+\\\] #1 stopped\\\.\r\n$gdb_prompt" {
>> pass $test
>> }
>> }
>> I got:
>> Running ../../../src/gdb/testsuite/gdb.base/dprintf-non-stop.exp ...
>> FAIL: gdb.base/dprintf-non-stop.exp: inferior stopped (timeout)
>>
>
> because the gdb_prompt has been consumed by the previous matching:
>
> gdb_test_multiple $test $test {
> -re "interrupt\r\n$gdb_prompt " {
> ^^^^^^^^^^^^
> pass $test
>
> }
> }
I tried move $gdb_prompt to other part but still not work.
>
>> +set test "interrupt"
>> +gdb_test_multiple $test $test {
>> + -re "interrupt\r\n$gdb_prompt " {
>> + pass $test
>> + }
>> +}
>> +
>> +set test "inferior stopped"
>> +gdb_test_multiple "" $test {
>> + -re "\r\n\\\[.* \[0-9\]+\\\] #1 stopped\\\.\r\n" {
>> + pass $test
>> + }
>> +}
>
>
> I raise a question here that no one asked before, why don't combine these
> two gdb_test_multiple into one? like:
>
> set test "interrupt inferior"
> gdb_test_multiple "interrupt" $test {
> -re "interrupt\r\n.*\\\[.* \[0-9\]+\\\] #1 stopped\\\." {
> pass $test
> }
> }
This cannot pass test with gdbserver. I think that is why
async-shell.exp do something like it.
Thanks,
Hui
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [RFC] PR 15075 dprintf interferes with "next"
2013-05-28 0:02 ` Hui Zhu
2013-05-28 3:36 ` Yao Qi
@ 2013-06-03 4:07 ` Hui Zhu
2013-06-03 17:48 ` Pedro Alves
1 sibling, 1 reply; 45+ messages in thread
From: Hui Zhu @ 2013-06-03 4:07 UTC (permalink / raw)
To: Pedro Alves, Tom Tromey; +Cc: gdb-patches, Keith Seitz, Yao Qi
Ping http://sourceware.org/ml/gdb-patches/2013-05/msg00958.html
Thanks,
Hui
On Tue, May 28, 2013 at 8:01 AM, Hui Zhu <teawater@gmail.com> wrote:
> Hi Pedro and Tom,
>
> Thanks for your review.
>
> On Wed, May 22, 2013 at 8:46 PM, Pedro Alves <palves@redhat.com> wrote:
>> On 05/22/2013 11:21 AM, Hui Zhu wrote:
>>
>>> I tried it on fedora and looks it works OK most of times. I only got
>>> trouble is when run this test with remote, [runto main] with
>>> "non-stop" is open will fail sometime.
>>
>> Sorry, but "most of the times" is not acceptable. Can you please
>> figure out why that is so? This should never fail.
>
> I found a issue about remote test and non-stop. Because it doesn't
> have a lot of relation with dprintf, I will post a separate patch for
> that later.
>
>>
>>>> > Not sure even that is necessary, given bs->stop==0 and:
>>>> >
>>>> > /* Print nothing for this entry if we don't stop or don't
>>>> > print. */
>>>> > if (!bs->stop || !bs->print)
>>>> > bs->print_it = print_it_noop;
>>> I am not sure about this part.
>>> If my understanding about Tom's review in before is right, the action
>>> of dprintf command should be handled when GDB check the condition.
>>> And after that, dprintf not need be handled.
>>
>> Yes, but I don't see how that counters my suggestion.
>
> Added dprintf_create_breakpoints_sal. When dprintf is created, auto
> set silent to 0.
>
>>
>>>> >
>>>>> >> + bpstat_do_actions_1 (&bs);
>>>>> >> + bs->next = tmp;
>>>>> >> +}
>>>> >
>>>> > Could you add some comments explaining what this is
>>>> > doing, and why?
>>> I update this function to following part:
>>> /* Implement the "after_cond" breakpoint_ops method for dprintf. */
>>>
>>> static void
>>> dprintf_after_cond (struct bpstats *bs)
>>
>>
>>> {
>>> struct cleanup *old_chain;
>>> struct breakpoint *b = bs->breakpoint_at;
>>>
>>> bs->commands = b->commands;
>>> incref_counted_command_line (bs->commands);
>>
>> I still think there's no point in moving this to the
>> after_condition_true hook, if both existing implementations
>> end up doing it themselves. See below.
>>
>>>
>>> /* Because function bpstat_do_actions_1 will execute all the command
>>> list of BS and follow it by BS->NEXT, temporarily set BS->NEXT to
>>> NULL. */
>>> old_chain = make_cleanup_restore_ptr ((void **)&bs->next);
>>
>> That cast is invalid actually. Older gcc's will complain about
>> the aliasing violation. I think we can get away without this, by
>> passing a separate list with only one entry to bpstat_do_actions_1.
>>
>>> bs->next = NULL;
>>> bpstat_do_actions_1 (&bs);
>>> do_cleanups (old_chain);
>>>
>>> /* This dprintf need not be handled after this function
>>> because its command list is executed by bpstat_do_actions_1.
>>> Clear STOP and PRINT for that. */
>>> bs->stop = 0;
>>> bs->print = 0;
>>
>> Thanks. I was more looking for general design comments on why we
>> run the command list here. This also should explain why clear stop
>> here, instead of on the more natural check_status.
>>
>> So all in all, if it works for you (seems to work fine for me), I'd
>> rather do as this patch on top of yours does:
>>
>
> Thanks for this patch. I merged it to dprintf-continue patch.
>
>> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>> gdb/breakpoint.c | 62 ++++++++++++++++++++++++++++++++----------------------
>> 1 file changed, 37 insertions(+), 25 deletions(-)
>>
>> diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
>> index 7ef5703..181aecc 100644
>> --- a/gdb/breakpoint.c
>> +++ b/gdb/breakpoint.c
>> @@ -5292,6 +5292,15 @@ bpstat_stop_status (struct address_space *aspace,
>> b->enable_state = bp_disabled;
>> removed_any = 1;
>> }
>> +
>> + if (b->silent)
>> + bs->print = 0;
>> + bs->commands = b->commands;
>> + incref_counted_command_line (bs->commands);
>> + if (command_line_is_silent (bs->commands
>> + ? bs->commands->commands : NULL))
>> + bs->print = 0;
>> +
>> b->ops->after_condition_true (bs);
>> }
>>
>> @@ -12742,15 +12751,7 @@ base_breakpoint_explains_signal (struct breakpoint *b)
>> static void
>> base_breakpoint_after_condition_true (struct bpstats *bs)
>> {
>> - struct breakpoint *b = bs->breakpoint_at;
>> -
>> - if (b->silent)
>> - bs->print = 0;
>> - bs->commands = b->commands;
>> - incref_counted_command_line (bs->commands);
>> - if (command_line_is_silent (bs->commands
>> - ? bs->commands->commands : NULL))
>> - bs->print = 0;
>> + /* Nothing to do. */
>> }
>>
>> struct breakpoint_ops base_breakpoint_ops =
>> @@ -13368,30 +13369,41 @@ dprintf_print_recreate (struct breakpoint *tp, struct ui_file *fp)
>> }
>>
>> /* Implement the "after_condition_true" breakpoint_ops method for
>> - dprintf. */
>> + dprintf.
>> +
>> + dprintf's are implemented with regular commands in their command
>> + list, but we run the commands here instead of before presenting the
>> + stop to the user, as dprintf's don't actually cause a stop. This
>> + also makes it so that the commands of multiple dprintfs at the same
>> + address are all handled. */
>>
>> static void
>> dprintf_after_condition_true (struct bpstats *bs)
>> {
>> struct cleanup *old_chain;
>> - struct breakpoint *b = bs->breakpoint_at;
>> + struct bpstats tmp_bs = { NULL };
>> + struct bpstats *tmp_bs_p = &tmp_bs;
>>
>> - bs->commands = b->commands;
>> - incref_counted_command_line (bs->commands);
>> + /* dprintf's never cause a stop. This wasn't set in the
>> + check_status hook instead because that would make the dprintf's
>> + condition not be evaluated. */
>> + bs->stop = 0;
>>
>> - /* Because function bpstat_do_actions_1 will execute all the command
>> - list of BS and follow it by BS->NEXT, temporarily set BS->NEXT to
>> - NULL. */
>> - old_chain = make_cleanup_restore_ptr ((void **)&bs->next);
>> - bs->next = NULL;
>> - bpstat_do_actions_1 (&bs);
>> - do_cleanups (old_chain);
>> + /* Run the command list here. Take ownership of it instead of
>> + copying. We never want these commands to run later in
>> + bpstat_do_actions, if a breakpoint that causes a stop happens to
>> + be set at same address as this dprintf, or even if running the
>> + commands here throws. */
>> + tmp_bs.commands = bs->commands;
>> + bs->commands = NULL;
>> + old_chain = make_cleanup_decref_counted_command_line (&tmp_bs.commands);
>>
>> - /* This dprintf need not be handled after this function
>> - because its command list is executed by bpstat_do_actions_1.
>> - Clear STOP and PRINT for that. */
>> - bs->stop = 0;
>> - bs->print = 0;
>> + bpstat_do_actions_1 (&tmp_bs_p);
>> +
>> + /* 'tmp_bs.commands' will usually be NULL by now, but
>> + bpstat_do_actions_1 may return early without processing the whole
>> + list. */
>> + do_cleanups (old_chain);
>> }
>>
>> /* The breakpoint_ops structure to be used on static tracepoints with
>> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>>
>>>>> >> +if [prepare_for_testing $expfile $executable $srcfile {debug}] {
>>>>> >> + untested "failed to prepare for trace tests"
>>>> >
>>>> > This is not a trace test. Actually, prepare_for_testing
>>>> > already calls untested with whatever we pass it as first argument.
>>>> > I think it'd be the first such call in the testsuite, but I
>>>> > think this would be better:
>>>> >
>>>> > if [prepare_for_testing "failed to prepare for trace tests" \
>>>> > $executable $srcfile {debug}] {
>>>> > return -1
>>>> > }
>>> After I use this part of code, I got:
>>> ERROR: tcl error sourcing ../../../src/gdb/testsuite/gdb.base/dprintf-next.exp.
>>> ERROR: wrong # args: should be "prepare_for_testing testname
>>> executable ?sources? ?options?"
>>> while executing
>>> "prepare_for_testing "failed to prepare for dprintf next tests""
>>> invoked from within
>>> "if [prepare_for_testing "failed to prepare for dprintf next tests"
>>> $executable $srcfile {debug}] {
>>> return -1
>>> }"
>>
>> Hmm? Oh, it looks like you forgot the '\' at the end of the line.
>> Please try again.
>
> Fixed both dprintf-next.exp and dprintf-non-stop.exp.
>
>>
>>> So I change this part to:
>>> if { [prepare_for_testing dprintf-next.exp "dprintf-next" {} {debug}] } {
>>
>> 'dprintf-next.exp' really isn't magical. It's just a string. :-)
>>
>>> return -1
>>> }
>>
>>>>> >> +gdb_test "next" ".*" "next 1"
>>>>> >> +gdb_test "next" ".*" "next 2"
>>>> >
>>>> > Please use more string regexes for these, that confirm the next stopped
>>>> > at the right lines.
>>> Fixed.
>>
>> Sorry, I should have been clearer. Don't do that by checking
>> line numbers though, as those change when more functions are
>> added to the test. Just make each line look different instead.
>>
>>> +
>>> +gdb_test "dprintf $dp_location, \"%d\\n\", x" \
>>> + "Dprintf .*"
>>
>> Please add an explicit 3rd parameter to gdb_test, so that
>> the line number doesn't appear in gdb.sum.
>>
>>> +
>>> +gdb_test "next" "23.*\\+\\+x.*" "next 1"
>>> +gdb_test "next" "24.*\\+\\+x.*" "next 2"
>>
>> Do something like this:
>>
>> gdb_test "next" "\\+\\+x;" "next 1"
>> gdb_test "next" "\\+\\+x; /* set dprintf here" "next 2"
>>
>> You could add a comment to the first stepped line to
>> make that clearer:
>>
>> gdb_test "next" "\\+\\+x; /* step here.*" "next 1"
>> gdb_test "next" "\\+\\+x; /* set dprintf here" "next 2"
>
> This part is fixed.
>
>>
>>
>>> --- /dev/null
>>> +++ b/gdb/testsuite/gdb.base/dprintf-non-stop.c
>>> @@ -0,0 +1,30 @@
>>> +/* This testcase is part of GDB, the GNU debugger.
>>> +
>>> + Copyright (C) 2013 Free Software Foundation, Inc.
>>> + Contributed by Hui Zhu <hui@codesourcery.com>
>>> +
>>> + This program is free software; you can redistribute it and/or modify
>>> + it under the terms of the GNU General Public License as published by
>>> + the Free Software Foundation; either version 3 of the License, or
>>> + (at your option) any later version.
>>> +
>>> + This program is distributed in the hope that it will be useful,
>>> + but WITHOUT ANY WARRANTY; without even the implied warranty of
>>> + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
>>> + GNU General Public License for more details.
>>> +
>>> + You should have received a copy of the GNU General Public License
>>> + along with this program. If not, see <http://www.gnu.org/licenses/>. */
>>> +
>>> +void
>>> +foo ()
>>> +{
>>> +}
>>> +
>>> +int
>>> +main ()
>>> +{
>>> + foo ();
>>> + while (1);
>>
>> If something goes wrong, like GDB crashing, this could leave the test
>> running forever, pegging the CPU. Just make it sleep for some
>> time instead.
>
> Changed this part to sleep(3)
>
>>
>>> + return 0;
>>
>>> +}
>>> \ No newline at end of file
>>
>> Please watch out for these, and add a newline.
>>
>
> Fixed.
>
>>> +gdb_test "dprintf foo,\"At foo entry\\n\"" "Dprintf .*"
>>> +
>>> +send_gdb "continue &\n"
>>> +exec sleep 1
>>> +set test "interrupt"
>>> +gdb_test_multiple $test $test {
>>> + -re "interrupt\r\n$gdb_prompt " {
>>> + pass $test
>>> + }
>>> +}
>>> +
>>> +set test "inferior stopped"
>>> +gdb_test_multiple "" $test {
>>> + -re "\r\n\\\[.* \[0-9\]+\\\] #1 stopped\\\.\r\n" {
>>> + pass $test
>>> + }
>>> +}
>>
>> This leaves the prompt in the expect buffer. I think
>> this is likely to confuse the following test that runs.
>>
>
> After change this part to:
> gdb_test_multiple "" $test {
> -re "\r\n\\\[.* \[0-9\]+\\\] #1 stopped\\\.\r\n$gdb_prompt" {
> pass $test
> }
> }
> I got:
> Running ../../../src/gdb/testsuite/gdb.base/dprintf-non-stop.exp ...
> FAIL: gdb.base/dprintf-non-stop.exp: inferior stopped (timeout)
>
> I thought the reason is:
> (gdb) PASS: gdb.base/dprintf-non-stop.exp: interrupt
>
> [process 24118] #1 stopped.
> 0x00002aaaaad8f830 in nanosleep () from /lib/x86_64-linux-gnu/libc.so.6
> FAIL: gdb.base/dprintf-non-stop.exp: inferior stopped (timeout)
>
> There is not $gdb_prompt.
>
>
> On Wed, May 22, 2013 at 10:04 PM, Tom Tromey <tromey@redhat.com> wrote:
>>>>>>> "Hui" == Hui Zhu <teawater@gmail.com> writes:
>>
>> Hui> So I change this part to:
>> Hui> if { [prepare_for_testing dprintf-next.exp "dprintf-next" {} {debug}] } {
>> Hui> return -1
>> Hui> }
>>
>> I think it is better to use the variables created by standard_testfile.
>
> Fixed.
>
> The attachments are the new patches.
>
> Best,
> Hui
>
> 2013-05-28 Yao Qi <yao@codesourcery.com>
> Hui Zhu <hui@codesourcery.com>
> Pedro Alves <palves@redhat.com>
>
> PR breakpoints/15075
> PR breakpoints/15434
> * breakpoint.c (bpstat_stop_status): Call
> b->ops->after_condition_true.
> (update_dprintf_command_list): Don't append "continue" command
> to the command list of dprintf breakpoint.
> (base_breakpoint_after_condition_true): New function.
> (base_breakpoint_ops): Add base_breakpoint_after_condition_true.
> (dprintf_create_breakpoints_sal,
> dprintf_after_condition_true): New functions.
> (initialize_breakpoint_ops): Set dprintf_create_breakpoints_sal
> and dprintf_after_condition_true.
> * breakpoint.h (breakpoint_ops): Add after_condition_true.
>
> 2013-05-28 Yao Qi <yao@codesourcery.com>
> Hui Zhu <hui@codesourcery.com>
>
> PR breakpoints/15075
> PR breakpoints/15434
> * gdb.base/dprintf-next.c: New file.
> * gdb.base/dprintf-next.exp: New file.
> * gdb.base/dprintf-non-stop.c: New file.
> * gdb.base/dprintf-non-stop.exp: New file.
> * gdb.base/dprintf.exp: Don't check "continue" in the output
> of "info breakpoints".
> * gdb.mi/mi-breakpoint-changed.exp (test_insert_delete_modify):
> Don't check "continue" in script field.
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [RFC] PR 15075 dprintf interferes with "next"
2013-06-03 4:07 ` Hui Zhu
@ 2013-06-03 17:48 ` Pedro Alves
2013-06-07 3:16 ` Hui Zhu
0 siblings, 1 reply; 45+ messages in thread
From: Pedro Alves @ 2013-06-03 17:48 UTC (permalink / raw)
To: Hui Zhu; +Cc: Tom Tromey, gdb-patches, Keith Seitz, Yao Qi
On 06/03/2013 05:06 AM, Hui Zhu wrote:
> Ping http://sourceware.org/ml/gdb-patches/2013-05/msg00958.html
>
As this exposes the non-stop racy failure, we should fix it that one
first. Failing that, we should kfail or skip the test with
remote targets. Let's consider the latter option later if we don't
manage to address the race timely. As I said on:
http://sourceware.org/ml/gdb-patches/2013-05/msg01111.html
I'm investigating this. I have a prototype patch, but I need
a bit more to handle some details, like what to do with
signal catchpoints when we find threads had been stopped with
a signal (I'm currently thinking of skipping the catchpoints).
I'm composing a test to exercise/expose this kind of stuff,
for a better RFC.
--
Pedro Alves
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [RFC] PR 15075 dprintf interferes with "next"
2013-06-03 17:48 ` Pedro Alves
@ 2013-06-07 3:16 ` Hui Zhu
2013-06-17 7:36 ` Hui Zhu
2013-06-18 18:16 ` Pedro Alves
0 siblings, 2 replies; 45+ messages in thread
From: Hui Zhu @ 2013-06-07 3:16 UTC (permalink / raw)
To: Pedro Alves; +Cc: Tom Tromey, gdb-patches, Keith Seitz, Yao Qi
[-- Attachment #1: Type: text/plain, Size: 2216 bytes --]
Hi Pedro,
Thanks for your review.
On Tue, Jun 4, 2013 at 1:48 AM, Pedro Alves <palves@redhat.com> wrote:
> On 06/03/2013 05:06 AM, Hui Zhu wrote:
>> Ping http://sourceware.org/ml/gdb-patches/2013-05/msg00958.html
>>
>
> As this exposes the non-stop racy failure, we should fix it that one
> first. Failing that, we should kfail or skip the test with
> remote targets. Let's consider the latter option later if we don't
> manage to address the race timely. As I said on:
>
> http://sourceware.org/ml/gdb-patches/2013-05/msg01111.html
>
> I'm investigating this. I have a prototype patch, but I need
> a bit more to handle some details, like what to do with
> signal catchpoints when we find threads had been stopped with
> a signal (I'm currently thinking of skipping the catchpoints).
> I'm composing a test to exercise/expose this kind of stuff,
> for a better RFC.
I add a check in the begin of dprintf-non-stop.exp. Then if the
target in remote, this test will not support.
Please help me review it.
Thanks,
Hui
2013-06-07 Yao Qi <yao@codesourcery.com>
Hui Zhu <hui@codesourcery.com>
Pedro Alves <palves@redhat.com>
PR breakpoints/15075
PR breakpoints/15434
* breakpoint.c (bpstat_stop_status): Call
b->ops->after_condition_true.
(update_dprintf_command_list): Don't append "continue" command
to the command list of dprintf breakpoint.
(base_breakpoint_after_condition_true): New function.
(base_breakpoint_ops): Add base_breakpoint_after_condition_true.
(dprintf_create_breakpoints_sal,
dprintf_after_condition_true): New functions.
(initialize_breakpoint_ops): Set dprintf_create_breakpoints_sal
and dprintf_after_condition_true.
* breakpoint.h (breakpoint_ops): Add after_condition_true.
2013-06-07 Yao Qi <yao@codesourcery.com>
Hui Zhu <hui@codesourcery.com>
PR breakpoints/15075
PR breakpoints/15434
* gdb.base/dprintf-next.c: New file.
* gdb.base/dprintf-next.exp: New file.
* gdb.base/dprintf-non-stop.c: New file.
* gdb.base/dprintf-non-stop.exp: New file.
* gdb.base/dprintf.exp: Don't check "continue" in the output
of "info breakpoints".
* gdb.mi/mi-breakpoint-changed.exp (test_insert_delete_modify):
Don't check "continue" in script field.
[-- Attachment #2: dprintf-continue.txt --]
[-- Type: text/plain, Size: 5391 bytes --]
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -5299,6 +5299,8 @@ bpstat_stop_status (struct address_space
if (command_line_is_silent (bs->commands
? bs->commands->commands : NULL))
bs->print = 0;
+
+ b->ops->after_condition_true (bs);
}
}
@@ -8934,25 +8936,16 @@ update_dprintf_command_list (struct brea
_("Invalid dprintf style."));
gdb_assert (printf_line != NULL);
- /* Manufacture a printf/continue sequence. */
+ /* Manufacture a printf sequence. */
{
- struct command_line *printf_cmd_line, *cont_cmd_line = NULL;
-
- if (strcmp (dprintf_style, dprintf_style_agent) != 0)
- {
- cont_cmd_line = xmalloc (sizeof (struct command_line));
- cont_cmd_line->control_type = simple_control;
- cont_cmd_line->body_count = 0;
- cont_cmd_line->body_list = NULL;
- cont_cmd_line->next = NULL;
- cont_cmd_line->line = xstrdup ("continue");
- }
+ struct command_line *printf_cmd_line
+ = xmalloc (sizeof (struct command_line));
printf_cmd_line = xmalloc (sizeof (struct command_line));
printf_cmd_line->control_type = simple_control;
printf_cmd_line->body_count = 0;
printf_cmd_line->body_list = NULL;
- printf_cmd_line->next = cont_cmd_line;
+ printf_cmd_line->next = NULL;
printf_cmd_line->line = printf_line;
breakpoint_set_commands (b, printf_cmd_line);
@@ -12738,6 +12731,14 @@ base_breakpoint_explains_signal (struct
return BPSTAT_SIGNAL_HIDE;
}
+/* The default "after_condition_true" method. */
+
+static void
+base_breakpoint_after_condition_true (struct bpstats *bs)
+{
+ /* Nothing to do. */
+}
+
struct breakpoint_ops base_breakpoint_ops =
{
base_breakpoint_dtor,
@@ -12757,7 +12758,8 @@ struct breakpoint_ops base_breakpoint_op
base_breakpoint_create_sals_from_address,
base_breakpoint_create_breakpoints_sal,
base_breakpoint_decode_linespec,
- base_breakpoint_explains_signal
+ base_breakpoint_explains_signal,
+ base_breakpoint_after_condition_true,
};
/* Default breakpoint_ops methods. */
@@ -13351,6 +13353,76 @@ dprintf_print_recreate (struct breakpoin
print_recreate_thread (tp, fp);
}
+/* Implement the "create_breakpoints_sal" breakpoint_ops method for
+ dprintf. */
+
+static void
+dprintf_create_breakpoints_sal (struct gdbarch *gdbarch,
+ struct linespec_result *canonical,
+ struct linespec_sals *lsal,
+ char *cond_string,
+ char *extra_string,
+ enum bptype type_wanted,
+ enum bpdisp disposition,
+ int thread,
+ int task, int ignore_count,
+ const struct breakpoint_ops *ops,
+ int from_tty, int enabled,
+ int internal, unsigned flags)
+{
+ struct breakpoint *b;
+
+ create_breakpoints_sal_default (gdbarch, canonical, lsal,
+ cond_string, extra_string,
+ type_wanted,
+ disposition, thread, task,
+ ignore_count, ops, from_tty,
+ enabled, internal, flags);
+
+ b = get_breakpoint (breakpoint_count);
+ gdb_assert (b != NULL);
+
+ breakpoint_set_silent (b, 0);
+}
+
+/* Implement the "after_condition_true" breakpoint_ops method for
+ dprintf.
+
+ dprintf's are implemented with regular commands in their command
+ list, but we run the commands here instead of before presenting the
+ stop to the user, as dprintf's don't actually cause a stop. This
+ also makes it so that the commands of multiple dprintfs at the same
+ address are all handled. */
+
+static void
+dprintf_after_condition_true (struct bpstats *bs)
+{
+ struct cleanup *old_chain;
+ struct bpstats tmp_bs = { NULL };
+ struct bpstats *tmp_bs_p = &tmp_bs;
+
+ /* dprintf's never cause a stop. This wasn't set in the
+ check_status hook instead because that would make the dprintf's
+ condition not be evaluated. */
+ bs->stop = 0;
+
+ /* Run the command list here. Take ownership of it instead of
+ copying. We never want these commands to run later in
+ bpstat_do_actions, if a breakpoint that causes a stop happens to
+ be set at same address as this dprintf, or even if running the
+ commands here throws. */
+ tmp_bs.commands = bs->commands;
+ bs->commands = NULL;
+ old_chain = make_cleanup_decref_counted_command_line (&tmp_bs.commands);
+
+ bpstat_do_actions_1 (&tmp_bs_p);
+
+ /* 'tmp_bs.commands' will usually be NULL by now, but
+ bpstat_do_actions_1 may return early without processing the whole
+ list. */
+ do_cleanups (old_chain);
+}
+
/* The breakpoint_ops structure to be used on static tracepoints with
markers (`-m'). */
@@ -15847,6 +15919,8 @@ initialize_breakpoint_ops (void)
ops->print_it = bkpt_print_it;
ops->print_mention = bkpt_print_mention;
ops->print_recreate = dprintf_print_recreate;
+ ops->create_breakpoints_sal = dprintf_create_breakpoints_sal;
+ ops->after_condition_true = dprintf_after_condition_true;
}
/* Chain containing all defined "enable breakpoint" subcommands. */
--- a/gdb/breakpoint.h
+++ b/gdb/breakpoint.h
@@ -614,6 +614,10 @@ struct breakpoint_ops
'catch signal' interact properly with 'handle'; see
bpstat_explains_signal. */
enum bpstat_signal_value (*explains_signal) (struct breakpoint *);
+
+ /* Called after evaluating the breakpoint's condition,
+ and only if it evaluated true. */
+ void (*after_condition_true) (struct bpstats *bs);
};
/* Helper for breakpoint_ops->print_recreate implementations. Prints
[-- Attachment #3: dprintf-continue-test.txt --]
[-- Type: text/plain, Size: 6024 bytes --]
--- /dev/null
+++ b/gdb/testsuite/gdb.base/dprintf-next.c
@@ -0,0 +1,26 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright (C) 2013 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+int
+main (void)
+{
+ int x = 5;
+
+ ++x; /* Next without dprintf. */
+ ++x; /* Set dprintf here. */
+ return x - 7;
+}
--- /dev/null
+++ b/gdb/testsuite/gdb.base/dprintf-next.exp
@@ -0,0 +1,36 @@
+# Copyright 2013 Free Software Foundation, Inc.
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+standard_testfile
+
+set executable $testfile
+set expfile $testfile.exp
+
+set dp_location [gdb_get_line_number "Set dprintf here"]
+
+if [prepare_for_testing "failed to prepare for dprintf with next" \
+ ${testfile} ${srcfile} {debug}] {
+ return -1
+}
+
+if ![runto_main] {
+ fail "Can't run to main"
+ return -1
+}
+
+gdb_test "dprintf $dp_location, \"%d\\n\", x" \
+ "Dprintf .*"
+
+gdb_test "next" "\\+\\+x\;.*\/\* Next without dprintf.*" "next 1"
+gdb_test "next" "\\+\\+x\;.*\/\* Set dprintf here.*" "next 2"
--- /dev/null
+++ b/gdb/testsuite/gdb.base/dprintf-non-stop.c
@@ -0,0 +1,30 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright (C) 2013 Free Software Foundation, Inc.
+ Contributed by Hui Zhu <hui@codesourcery.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+void
+foo ()
+{
+}
+
+int
+main ()
+{
+ foo ();
+ sleep (3);
+ return 0;
+}
--- /dev/null
+++ b/gdb/testsuite/gdb.base/dprintf-non-stop.exp
@@ -0,0 +1,54 @@
+# Copyright (C) 2013 Free Software Foundation, Inc.
+# Contributed by Hui Zhu <hui@codesourcery.com>
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+if [is_remote target] then {
+ unsupported "Dprintf with non-stop is not supported."
+ return 0
+}
+
+standard_testfile
+
+if [prepare_for_testing "failed to prepare for dprintf with non-stop" \
+ ${testfile} ${srcfile} {debug}] {
+ return -1
+}
+
+gdb_test_no_output "set target-async on"
+gdb_test_no_output "set non-stop on"
+
+if ![runto main] {
+ fail "Can't run to main"
+ return -1
+}
+
+gdb_test "dprintf foo,\"At foo entry\\n\"" "Dprintf .*"
+
+send_gdb "continue &\n"
+exec sleep 1
+
+set test "interrupt"
+gdb_test_multiple $test $test {
+ -re "interrupt\r\n$gdb_prompt " {
+ pass $test
+ }
+}
+
+set test "inferior stopped"
+gdb_test_multiple "" $test {
+ -re "\r\n\\\[.* \[0-9\]+\\\] #1 stopped\\\.\r\n" {
+ pass $test
+ }
+}
--- a/gdb/testsuite/gdb.base/dprintf.exp
+++ b/gdb/testsuite/gdb.base/dprintf.exp
@@ -50,10 +50,8 @@ gdb_test_sequence "info breakpoints" "dp
"\[\r\n\]2 breakpoint"
"\[\r\n\]3 dprintf"
"\[\r\n\] printf \"At foo entry\\\\n\""
- "\[\r\n\] continue"
"\[\r\n\]4 dprintf"
"\[\r\n\] printf \"arg=%d, g=%d\\\\n\", arg, g"
- "\[\r\n\] continue"
}
gdb_test "break $bp_location1" \
@@ -135,4 +133,3 @@ if $target_can_dprintf {
gdb_test "set dprintf-style foobar" "Undefined item: \"foobar\"." \
"Set dprintf style to an unrecognized type"
-
--- a/gdb/testsuite/gdb.mi/mi-breakpoint-changed.exp
+++ b/gdb/testsuite/gdb.mi/mi-breakpoint-changed.exp
@@ -96,7 +96,7 @@ proc test_insert_delete_modify { } {
$test
set test "dprintf marker, \"arg\" \""
mi_gdb_test $test \
- {.*=breakpoint-created,bkpt=\{number="6",type="dprintf".*,script=\{\"printf \\\\\"arg\\\\\" \\\\\"\",\"continue\"\}.*\}\r\n\^done} \
+ {.*=breakpoint-created,bkpt=\{number="6",type="dprintf".*,script=\{\"printf \\\\\"arg\\\\\" \\\\\"\"\}.*\}\r\n\^done} \
$test
# 2. when modifying condition
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [RFC] PR 15075 dprintf interferes with "next"
2013-06-07 3:16 ` Hui Zhu
@ 2013-06-17 7:36 ` Hui Zhu
2013-06-18 18:16 ` Pedro Alves
1 sibling, 0 replies; 45+ messages in thread
From: Hui Zhu @ 2013-06-17 7:36 UTC (permalink / raw)
To: Pedro Alves; +Cc: Tom Tromey, gdb-patches, Keith Seitz, Yao Qi
Ping http://sourceware.org/ml/gdb-patches/2013-06/msg00139.html
Thanks,
Hui
On Fri, Jun 7, 2013 at 11:15 AM, Hui Zhu <teawater@gmail.com> wrote:
> Hi Pedro,
>
> Thanks for your review.
>
> On Tue, Jun 4, 2013 at 1:48 AM, Pedro Alves <palves@redhat.com> wrote:
>> On 06/03/2013 05:06 AM, Hui Zhu wrote:
>>> Ping http://sourceware.org/ml/gdb-patches/2013-05/msg00958.html
>>>
>>
>> As this exposes the non-stop racy failure, we should fix it that one
>> first. Failing that, we should kfail or skip the test with
>> remote targets. Let's consider the latter option later if we don't
>> manage to address the race timely. As I said on:
>>
>> http://sourceware.org/ml/gdb-patches/2013-05/msg01111.html
>>
>> I'm investigating this. I have a prototype patch, but I need
>> a bit more to handle some details, like what to do with
>> signal catchpoints when we find threads had been stopped with
>> a signal (I'm currently thinking of skipping the catchpoints).
>> I'm composing a test to exercise/expose this kind of stuff,
>> for a better RFC.
>
> I add a check in the begin of dprintf-non-stop.exp. Then if the
> target in remote, this test will not support.
>
> Please help me review it.
>
> Thanks,
> Hui
>
> 2013-06-07 Yao Qi <yao@codesourcery.com>
> Hui Zhu <hui@codesourcery.com>
> Pedro Alves <palves@redhat.com>
>
> PR breakpoints/15075
> PR breakpoints/15434
> * breakpoint.c (bpstat_stop_status): Call
> b->ops->after_condition_true.
> (update_dprintf_command_list): Don't append "continue" command
> to the command list of dprintf breakpoint.
> (base_breakpoint_after_condition_true): New function.
> (base_breakpoint_ops): Add base_breakpoint_after_condition_true.
> (dprintf_create_breakpoints_sal,
> dprintf_after_condition_true): New functions.
> (initialize_breakpoint_ops): Set dprintf_create_breakpoints_sal
> and dprintf_after_condition_true.
> * breakpoint.h (breakpoint_ops): Add after_condition_true.
>
> 2013-06-07 Yao Qi <yao@codesourcery.com>
> Hui Zhu <hui@codesourcery.com>
>
> PR breakpoints/15075
> PR breakpoints/15434
> * gdb.base/dprintf-next.c: New file.
> * gdb.base/dprintf-next.exp: New file.
> * gdb.base/dprintf-non-stop.c: New file.
> * gdb.base/dprintf-non-stop.exp: New file.
> * gdb.base/dprintf.exp: Don't check "continue" in the output
> of "info breakpoints".
> * gdb.mi/mi-breakpoint-changed.exp (test_insert_delete_modify):
> Don't check "continue" in script field.
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [RFC] PR 15075 dprintf interferes with "next"
2013-06-07 3:16 ` Hui Zhu
2013-06-17 7:36 ` Hui Zhu
@ 2013-06-18 18:16 ` Pedro Alves
2013-06-24 8:36 ` Hui Zhu
1 sibling, 1 reply; 45+ messages in thread
From: Pedro Alves @ 2013-06-18 18:16 UTC (permalink / raw)
To: Hui Zhu; +Cc: Tom Tromey, gdb-patches, Keith Seitz, Yao Qi
On 06/07/2013 04:15 AM, Hui Zhu wrote:
> 2013-06-07 Yao Qi <yao@codesourcery.com>
> Hui Zhu <hui@codesourcery.com>
> Pedro Alves <palves@redhat.com>
>
> PR breakpoints/15075
> PR breakpoints/15434
> * breakpoint.c (bpstat_stop_status): Call
> b->ops->after_condition_true.
> (update_dprintf_command_list): Don't append "continue" command
> to the command list of dprintf breakpoint.
> (base_breakpoint_after_condition_true): New function.
> (base_breakpoint_ops): Add base_breakpoint_after_condition_true.
> (dprintf_create_breakpoints_sal,
> dprintf_after_condition_true): New functions.
Context is split in multiple lines with '()'s, not ','s:
(dprintf_create_breakpoints_sal)
(dprintf_after_condition_true): New functions.
> (initialize_breakpoint_ops): Set dprintf_create_breakpoints_sal
> and dprintf_after_condition_true.
> * breakpoint.h (breakpoint_ops): Add after_condition_true.
>
> };
>
> /* Default breakpoint_ops methods. */
> @@ -13351,6 +13353,76 @@ dprintf_print_recreate (struct breakpoin
> print_recreate_thread (tp, fp);
> }
>
> +/* Implement the "create_breakpoints_sal" breakpoint_ops method for
> + dprintf. */
> +
> +static void
> +dprintf_create_breakpoints_sal (struct gdbarch *gdbarch,
> + struct linespec_result *canonical,
> + struct linespec_sals *lsal,
> + char *cond_string,
> + char *extra_string,
> + enum bptype type_wanted,
> + enum bpdisp disposition,
> + int thread,
> + int task, int ignore_count,
> + const struct breakpoint_ops *ops,
> + int from_tty, int enabled,
> + int internal, unsigned flags)
> +{
> + struct breakpoint *b;
> +
> + create_breakpoints_sal_default (gdbarch, canonical, lsal,
> + cond_string, extra_string,
> + type_wanted,
> + disposition, thread, task,
> + ignore_count, ops, from_tty,
> + enabled, internal, flags);
> +
> + b = get_breakpoint (breakpoint_count);
> + gdb_assert (b != NULL);
> +
> + breakpoint_set_silent (b, 0);
> +}
When I tried it last, I didn't find making the dprintf
explicitly silent necessary, given:
/* Print nothing for this entry if we don't stop or don't
print. */
if (!bs->stop || !bs->print)
bs->print_it = print_it_noop;
So did it turn out really necessary for some reason? Please
don't leave such changes between revisions unexplained.
> +gdb_test "next" "\\+\\+x\;.*\/\* Next without dprintf.*" "next 1"
> +gdb_test "next" "\\+\\+x\;.*\/\* Set dprintf here.*" "next 2"
> --- /dev/null
> +++ b/gdb/testsuite/gdb.base/dprintf-non-stop.c
> @@ -0,0 +1,30 @@
> +/* This testcase is part of GDB, the GNU debugger.
> +
> + Copyright (C) 2013 Free Software Foundation, Inc.
> + Contributed by Hui Zhu <hui@codesourcery.com>
(
IMO, we should stop adding these (like glibc has done so too):
http://sourceware.org/ml/gdb-patches/2013-05/msg00253.html
)
> --- /dev/null
> +++ b/gdb/testsuite/gdb.base/dprintf-non-stop.exp
> @@ -0,0 +1,54 @@
> +# Copyright (C) 2013 Free Software Foundation, Inc.
> +# Contributed by Hui Zhu <hui@codesourcery.com>
> +
> +# This program is free software; you can redistribute it and/or modify
> +# it under the terms of the GNU General Public License as published by
> +# the Free Software Foundation; either version 3 of the License, or
> +# (at your option) any later version.
> +#
> +# This program is distributed in the hope that it will be useful,
> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> +# GNU General Public License for more details.
> +#
> +# You should have received a copy of the GNU General Public License
> +# along with this program. If not, see <http://www.gnu.org/licenses/>.
> +
> +if [is_remote target] then {
> + unsupported "Dprintf with non-stop is not supported."
That's not exactly true. It's supported, but testing is racy at the moment.
Write instead:
if [is_remote target] then {
# Testing with remote/non-stop is racy at the moment.
unsupported "Testing dprintf with remote/non-stop is not supported."
return 0
}
> + return 0
> +}
> +
> +standard_testfile
> +
> +if [prepare_for_testing "failed to prepare for dprintf with non-stop" \
> + ${testfile} ${srcfile} {debug}] {
> + return -1
> +}
> +
> +gdb_test_no_output "set target-async on"
> +gdb_test_no_output "set non-stop on"
> +
> +if ![runto main] {
> + fail "Can't run to main"
> + return -1
> +}
> +
> +gdb_test "dprintf foo,\"At foo entry\\n\"" "Dprintf .*"
> +
> +send_gdb "continue &\n"
> +exec sleep 1
> +
> +set test "interrupt"
> +gdb_test_multiple $test $test {
> + -re "interrupt\r\n$gdb_prompt " {
> + pass $test
Hmm, this still looks racy to me, even on native targets.
"continue &" produces a gdb prompt. gdb_test_multiple
inside has a match for the prompt:
-re "\r\n$gdb_prompt $" {
if ![string match "" $message] then {
fail "$message"
}
set result 1
}
So if the expect happens to read
continue &
(gdb)
from the buffer, we'll hit the fail. Doesn't the read1 hack catch this?
We need to consume the prompt after that "continue&".
> + }
> +}
> +
> +set test "inferior stopped"
> +gdb_test_multiple "" $test {
> + -re "\r\n\\\[.* \[0-9\]+\\\] #1 stopped\\\.\r\n" {
> + pass $test
> + }
> +}
Likewise?
--
Pedro Alves
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [RFC] PR 15075 dprintf interferes with "next"
2013-06-18 18:16 ` Pedro Alves
@ 2013-06-24 8:36 ` Hui Zhu
2013-06-24 22:06 ` Pedro Alves
0 siblings, 1 reply; 45+ messages in thread
From: Hui Zhu @ 2013-06-24 8:36 UTC (permalink / raw)
To: Pedro Alves, Hui Zhu; +Cc: Tom Tromey, gdb-patches, Keith Seitz, Yao Qi
[-- Attachment #1: Type: text/plain, Size: 5989 bytes --]
Hi Pedro,
Thanks for your review.
On 06/19/13 02:09, Pedro Alves wrote:
> On 06/07/2013 04:15 AM, Hui Zhu wrote:
>
>> 2013-06-07 Yao Qi <yao@codesourcery.com>
>> Hui Zhu <hui@codesourcery.com>
>> Pedro Alves <palves@redhat.com>
>>
>> PR breakpoints/15075
>> PR breakpoints/15434
>> * breakpoint.c (bpstat_stop_status): Call
>> b->ops->after_condition_true.
>> (update_dprintf_command_list): Don't append "continue" command
>> to the command list of dprintf breakpoint.
>> (base_breakpoint_after_condition_true): New function.
>> (base_breakpoint_ops): Add base_breakpoint_after_condition_true.
>> (dprintf_create_breakpoints_sal,
>> dprintf_after_condition_true): New functions.
>
> Context is split in multiple lines with '()'s, not ','s:
Fixed.
>
> (dprintf_create_breakpoints_sal)
> (dprintf_after_condition_true): New functions.
>
>
>> (initialize_breakpoint_ops): Set dprintf_create_breakpoints_sal
>> and dprintf_after_condition_true.
>> * breakpoint.h (breakpoint_ops): Add after_condition_true.
>>
>> };
>>
>> /* Default breakpoint_ops methods. */
>> @@ -13351,6 +13353,76 @@ dprintf_print_recreate (struct breakpoin
>> print_recreate_thread (tp, fp);
>> }
>>
>> +/* Implement the "create_breakpoints_sal" breakpoint_ops method for
>> + dprintf. */
>> +
>> +static void
>> +dprintf_create_breakpoints_sal (struct gdbarch *gdbarch,
>> + struct linespec_result *canonical,
>> + struct linespec_sals *lsal,
>> + char *cond_string,
>> + char *extra_string,
>> + enum bptype type_wanted,
>> + enum bpdisp disposition,
>> + int thread,
>> + int task, int ignore_count,
>> + const struct breakpoint_ops *ops,
>> + int from_tty, int enabled,
>> + int internal, unsigned flags)
>> +{
>> + struct breakpoint *b;
>> +
>> + create_breakpoints_sal_default (gdbarch, canonical, lsal,
>> + cond_string, extra_string,
>> + type_wanted,
>> + disposition, thread, task,
>> + ignore_count, ops, from_tty,
>> + enabled, internal, flags);
>> +
>> + b = get_breakpoint (breakpoint_count);
>> + gdb_assert (b != NULL);
>> +
>> + breakpoint_set_silent (b, 0);
>> +}
>
> When I tried it last, I didn't find making the dprintf
> explicitly silent necessary, given:
>
> /* Print nothing for this entry if we don't stop or don't
> print. */
> if (!bs->stop || !bs->print)
> bs->print_it = print_it_noop;
>
> So did it turn out really necessary for some reason? Please
> don't leave such changes between revisions unexplained.
Sorry for my misunderstand your comments. They were removed.
>
>> +gdb_test "next" "\\+\\+x\;.*\/\* Next without dprintf.*" "next 1"
>> +gdb_test "next" "\\+\\+x\;.*\/\* Set dprintf here.*" "next 2"
>
>> --- /dev/null
>> +++ b/gdb/testsuite/gdb.base/dprintf-non-stop.c
>> @@ -0,0 +1,30 @@
>> +/* This testcase is part of GDB, the GNU debugger.
>> +
>> + Copyright (C) 2013 Free Software Foundation, Inc.
>> + Contributed by Hui Zhu <hui@codesourcery.com>
>
> (
> IMO, we should stop adding these (like glibc has done so too):
> http://sourceware.org/ml/gdb-patches/2013-05/msg00253.html
> )
Removed.
>
>> --- /dev/null
>> +++ b/gdb/testsuite/gdb.base/dprintf-non-stop.exp
>> @@ -0,0 +1,54 @@
>> +# Copyright (C) 2013 Free Software Foundation, Inc.
>> +# Contributed by Hui Zhu <hui@codesourcery.com>
>> +
>> +# This program is free software; you can redistribute it and/or modify
>> +# it under the terms of the GNU General Public License as published by
>> +# the Free Software Foundation; either version 3 of the License, or
>> +# (at your option) any later version.
>> +#
>> +# This program is distributed in the hope that it will be useful,
>> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
>> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
>> +# GNU General Public License for more details.
>> +#
>> +# You should have received a copy of the GNU General Public License
>> +# along with this program. If not, see <http://www.gnu.org/licenses/>.
>> +
>> +if [is_remote target] then {
>> + unsupported "Dprintf with non-stop is not supported."
>
> That's not exactly true. It's supported, but testing is racy at the moment.
> Write instead:
>
> if [is_remote target] then {
> # Testing with remote/non-stop is racy at the moment.
> unsupported "Testing dprintf with remote/non-stop is not supported."
> return 0
> }
Fixed.
>
>> + return 0
>> +}
>> +
>> +standard_testfile
>> +
>> +if [prepare_for_testing "failed to prepare for dprintf with non-stop" \
>> + ${testfile} ${srcfile} {debug}] {
>> + return -1
>> +}
>> +
>> +gdb_test_no_output "set target-async on"
>> +gdb_test_no_output "set non-stop on"
>> +
>> +if ![runto main] {
>> + fail "Can't run to main"
>> + return -1
>> +}
>> +
>> +gdb_test "dprintf foo,\"At foo entry\\n\"" "Dprintf .*"
>> +
>> +send_gdb "continue &\n"
>> +exec sleep 1
>> +
>> +set test "interrupt"
>> +gdb_test_multiple $test $test {
>> + -re "interrupt\r\n$gdb_prompt " {
>> + pass $test
>
> Hmm, this still looks racy to me, even on native targets.
> "continue &" produces a gdb prompt. gdb_test_multiple
> inside has a match for the prompt:
>
> -re "\r\n$gdb_prompt $" {
> if ![string match "" $message] then {
> fail "$message"
> }
> set result 1
> }
>
> So if the expect happens to read
>
> continue &
> (gdb)
>
> from the buffer, we'll hit the fail. Doesn't the read1 hack catch this?
EXPECT=../contrib/expect-read1.sh make check RUNTESTFLAGS="dprintf-non-stop.exp" is OK in my part.
>
> We need to consume the prompt after that "continue&".
>
>> + }
>> +}
>> +
>> +set test "inferior stopped"
>> +gdb_test_multiple "" $test {
>> + -re "\r\n\\\[.* \[0-9\]+\\\] #1 stopped\\\.\r\n" {
>> + pass $test
>> + }
>> +}
>
> Likewise?
>
I just copy this part of code from "gdb.base/async-shell.exp".
Could you give me some help about how to consume the prompt after that "continue&"?
Thanks,
Hui
[-- Attachment #2: dprintf-continue.txt --]
[-- Type: text/plain, Size: 4469 bytes --]
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -5299,6 +5299,8 @@ bpstat_stop_status (struct address_space
if (command_line_is_silent (bs->commands
? bs->commands->commands : NULL))
bs->print = 0;
+
+ b->ops->after_condition_true (bs);
}
}
@@ -8934,25 +8936,16 @@ update_dprintf_command_list (struct brea
_("Invalid dprintf style."));
gdb_assert (printf_line != NULL);
- /* Manufacture a printf/continue sequence. */
+ /* Manufacture a printf sequence. */
{
- struct command_line *printf_cmd_line, *cont_cmd_line = NULL;
-
- if (strcmp (dprintf_style, dprintf_style_agent) != 0)
- {
- cont_cmd_line = xmalloc (sizeof (struct command_line));
- cont_cmd_line->control_type = simple_control;
- cont_cmd_line->body_count = 0;
- cont_cmd_line->body_list = NULL;
- cont_cmd_line->next = NULL;
- cont_cmd_line->line = xstrdup ("continue");
- }
+ struct command_line *printf_cmd_line
+ = xmalloc (sizeof (struct command_line));
printf_cmd_line = xmalloc (sizeof (struct command_line));
printf_cmd_line->control_type = simple_control;
printf_cmd_line->body_count = 0;
printf_cmd_line->body_list = NULL;
- printf_cmd_line->next = cont_cmd_line;
+ printf_cmd_line->next = NULL;
printf_cmd_line->line = printf_line;
breakpoint_set_commands (b, printf_cmd_line);
@@ -12738,6 +12731,14 @@ base_breakpoint_explains_signal (struct
return BPSTAT_SIGNAL_HIDE;
}
+/* The default "after_condition_true" method. */
+
+static void
+base_breakpoint_after_condition_true (struct bpstats *bs)
+{
+ /* Nothing to do. */
+}
+
struct breakpoint_ops base_breakpoint_ops =
{
base_breakpoint_dtor,
@@ -12757,7 +12758,8 @@ struct breakpoint_ops base_breakpoint_op
base_breakpoint_create_sals_from_address,
base_breakpoint_create_breakpoints_sal,
base_breakpoint_decode_linespec,
- base_breakpoint_explains_signal
+ base_breakpoint_explains_signal,
+ base_breakpoint_after_condition_true,
};
/* Default breakpoint_ops methods. */
@@ -13351,6 +13353,44 @@ dprintf_print_recreate (struct breakpoin
print_recreate_thread (tp, fp);
}
+/* Implement the "after_condition_true" breakpoint_ops method for
+ dprintf.
+
+ dprintf's are implemented with regular commands in their command
+ list, but we run the commands here instead of before presenting the
+ stop to the user, as dprintf's don't actually cause a stop. This
+ also makes it so that the commands of multiple dprintfs at the same
+ address are all handled. */
+
+static void
+dprintf_after_condition_true (struct bpstats *bs)
+{
+ struct cleanup *old_chain;
+ struct bpstats tmp_bs = { NULL };
+ struct bpstats *tmp_bs_p = &tmp_bs;
+
+ /* dprintf's never cause a stop. This wasn't set in the
+ check_status hook instead because that would make the dprintf's
+ condition not be evaluated. */
+ bs->stop = 0;
+
+ /* Run the command list here. Take ownership of it instead of
+ copying. We never want these commands to run later in
+ bpstat_do_actions, if a breakpoint that causes a stop happens to
+ be set at same address as this dprintf, or even if running the
+ commands here throws. */
+ tmp_bs.commands = bs->commands;
+ bs->commands = NULL;
+ old_chain = make_cleanup_decref_counted_command_line (&tmp_bs.commands);
+
+ bpstat_do_actions_1 (&tmp_bs_p);
+
+ /* 'tmp_bs.commands' will usually be NULL by now, but
+ bpstat_do_actions_1 may return early without processing the whole
+ list. */
+ do_cleanups (old_chain);
+}
+
/* The breakpoint_ops structure to be used on static tracepoints with
markers (`-m'). */
@@ -15847,6 +15887,7 @@ initialize_breakpoint_ops (void)
ops->print_it = bkpt_print_it;
ops->print_mention = bkpt_print_mention;
ops->print_recreate = dprintf_print_recreate;
+ ops->after_condition_true = dprintf_after_condition_true;
}
/* Chain containing all defined "enable breakpoint" subcommands. */
--- a/gdb/breakpoint.h
+++ b/gdb/breakpoint.h
@@ -614,6 +614,10 @@ struct breakpoint_ops
'catch signal' interact properly with 'handle'; see
bpstat_explains_signal. */
enum bpstat_signal_value (*explains_signal) (struct breakpoint *);
+
+ /* Called after evaluating the breakpoint's condition,
+ and only if it evaluated true. */
+ void (*after_condition_true) (struct bpstats *bs);
};
/* Helper for breakpoint_ops->print_recreate implementations. Prints
[-- Attachment #3: dprintf-continue-test.txt --]
[-- Type: text/plain, Size: 6138 bytes --]
--- /dev/null
+++ b/gdb/testsuite/gdb.base/dprintf-next.c
@@ -0,0 +1,26 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright (C) 2013 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+int
+main (void)
+{
+ int x = 5;
+
+ ++x; /* Next without dprintf. */
+ ++x; /* Set dprintf here. */
+ return x - 7;
+}
--- /dev/null
+++ b/gdb/testsuite/gdb.base/dprintf-next.exp
@@ -0,0 +1,36 @@
+# Copyright 2013 Free Software Foundation, Inc.
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+standard_testfile
+
+set executable $testfile
+set expfile $testfile.exp
+
+set dp_location [gdb_get_line_number "Set dprintf here"]
+
+if [prepare_for_testing "failed to prepare for dprintf with next" \
+ ${testfile} ${srcfile} {debug}] {
+ return -1
+}
+
+if ![runto_main] {
+ fail "Can't run to main"
+ return -1
+}
+
+gdb_test "dprintf $dp_location, \"%d\\n\", x" \
+ "Dprintf .*"
+
+gdb_test "next" "\\+\\+x\;.*\/\* Next without dprintf.*" "next 1"
+gdb_test "next" "\\+\\+x\;.*\/\* Set dprintf here.*" "next 2"
--- /dev/null
+++ b/gdb/testsuite/gdb.base/dprintf-non-stop.c
@@ -0,0 +1,29 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright (C) 2013 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+void
+foo ()
+{
+}
+
+int
+main ()
+{
+ foo ();
+ sleep (3);
+ return 0;
+}
--- /dev/null
+++ b/gdb/testsuite/gdb.base/dprintf-non-stop.exp
@@ -0,0 +1,54 @@
+# Copyright (C) 2013 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+if [is_remote target] then {
+ # Testing with remote/non-stop is racy at the moment.
+ unsupported "Testing dprintf with remote/non-stop is not supported."
+ return 0
+}
+
+standard_testfile
+
+if [prepare_for_testing "failed to prepare for dprintf with non-stop" \
+ ${testfile} ${srcfile} {debug}] {
+ return -1
+}
+
+gdb_test_no_output "set target-async on"
+gdb_test_no_output "set non-stop on"
+
+if ![runto main] {
+ fail "Can't run to main"
+ return -1
+}
+
+gdb_test "dprintf foo,\"At foo entry\\n\"" "Dprintf .*"
+
+send_gdb "continue &\n"
+exec sleep 1
+
+set test "interrupt"
+gdb_test_multiple $test $test {
+ -re "interrupt\r\n$gdb_prompt " {
+ pass $test
+ }
+}
+
+set test "inferior stopped"
+gdb_test_multiple "" $test {
+ -re "\r\n\\\[.* \[0-9\]+\\\] #1 stopped\\\.\r\n" {
+ pass $test
+ }
+}
--- a/gdb/testsuite/gdb.base/dprintf.exp
+++ b/gdb/testsuite/gdb.base/dprintf.exp
@@ -50,10 +50,8 @@ gdb_test_sequence "info breakpoints" "dp
"\[\r\n\]2 breakpoint"
"\[\r\n\]3 dprintf"
"\[\r\n\] printf \"At foo entry\\\\n\""
- "\[\r\n\] continue"
"\[\r\n\]4 dprintf"
"\[\r\n\] printf \"arg=%d, g=%d\\\\n\", arg, g"
- "\[\r\n\] continue"
}
gdb_test "break $bp_location1" \
@@ -111,7 +109,6 @@ gdb_test_multiple "set dprintf-style age
}
if $target_can_dprintf {
-
gdb_run_cmd
gdb_test "" "Breakpoint"
@@ -135,4 +132,3 @@ if $target_can_dprintf {
gdb_test "set dprintf-style foobar" "Undefined item: \"foobar\"." \
"Set dprintf style to an unrecognized type"
-
--- a/gdb/testsuite/gdb.mi/mi-breakpoint-changed.exp
+++ b/gdb/testsuite/gdb.mi/mi-breakpoint-changed.exp
@@ -96,7 +96,7 @@ proc test_insert_delete_modify { } {
$test
set test "dprintf marker, \"arg\" \""
mi_gdb_test $test \
- {.*=breakpoint-created,bkpt=\{number="6",type="dprintf".*,script=\{\"printf \\\\\"arg\\\\\" \\\\\"\",\"continue\"\}.*\}\r\n\^done} \
+ {.*=breakpoint-created,bkpt=\{number="6",type="dprintf".*,script=\{\"printf \\\\\"arg\\\\\" \\\\\"\"\}.*\}\r\n\^done} \
$test
# 2. when modifying condition
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [RFC] PR 15075 dprintf interferes with "next"
2013-06-24 8:36 ` Hui Zhu
@ 2013-06-24 22:06 ` Pedro Alves
2013-06-25 9:14 ` Hui Zhu
0 siblings, 1 reply; 45+ messages in thread
From: Pedro Alves @ 2013-06-24 22:06 UTC (permalink / raw)
To: Hui Zhu; +Cc: Hui Zhu, Tom Tromey, gdb-patches, Keith Seitz, Yao Qi
On 06/24/2013 05:24 AM, Hui Zhu wrote:
>> Hmm, this still looks racy to me, even on native targets.
>> "continue &" produces a gdb prompt. gdb_test_multiple
>> inside has a match for the prompt:
>>
>> -re "\r\n$gdb_prompt $" {
>> if ![string match "" $message] then {
>> fail "$message"
>> }
>> set result 1
>> }
>>
>> So if the expect happens to read
>>
>> continue &
>> (gdb)
>>
>> from the buffer, we'll hit the fail. Doesn't the read1 hack catch this?
>
> EXPECT=../contrib/expect-read1.sh make check RUNTESTFLAGS="dprintf-non-stop.exp" is OK in my part.
I suspect the "exec sleep 1" is masking it. If you remove the sleep,
then the test fails.
>
>>
>> We need to consume the prompt after that "continue&".
>>
>>> + }
>>> +}
>>> +
>>> +set test "inferior stopped"
>>> +gdb_test_multiple "" $test {
>>> + -re "\r\n\\\[.* \[0-9\]+\\\] #1 stopped\\\.\r\n" {
>>> + pass $test
>>> + }
>>> +}
>>
>> Likewise?
>>
>
> I just copy this part of code from "gdb.base/async-shell.exp".
> Could you give me some help about how to consume the prompt after that "continue&"?
Just doing:
-send_gdb "continue &\n"
+gdb_test "continue &" "Continuing\\."
will consume the prompt. Otherwise, we'd do like
e.g., completion.exp does:
# Eat the prompt
gdb_expect {
-re "$gdb_prompt " {
pass "$test (eat prompt)"
}
timeout {
fail "(timeout) $test (eat prompt)"
}
}
We still need the sleep, but for different a reason -- be sure
to wait for the dprintf to trigger -- we need GDB to print the
prompt before the program reaches the dprintf. I think it's slightly
better to do the sleep on the inferior program side. We can expect
the "At foo entry" output from the dprintf, as the default "set dprintf-style"
is "gdb".
I see now that the
set test "inferior stopped"
gdb_test_multiple "" $test {
-re "\r\n\\\[.* \[0-9\]+\\\] #1 stopped\\\.\r\n" {
pass $test
}
}
case doesn't need to eat the prompt, as that output appears
after the prompt:
(gdb) PASS: gdb.base/dprintf-non-stop.exp: continue &
At foo entry
PASS: gdb.base/dprintf-non-stop.exp: dprintf triggered
interrupt
(gdb)
[process 6106] #1 stopped.
PASS: gdb.base/dprintf-non-stop.exp: interrupt
PASS: gdb.base/dprintf-non-stop.exp: inferior stopped
and the "interrupt" test already eats it.
See patchlet on top of yours below. Please merge it with
yours, and push the result in (and post it, for the archives).
Thanks,
Pedro Alves
---
gdb/testsuite/gdb.base/dprintf-non-stop.c | 1 +
gdb/testsuite/gdb.base/dprintf-non-stop.exp | 17 +++++++++++++++--
2 files changed, 16 insertions(+), 2 deletions(-)
diff --git a/gdb/testsuite/gdb.base/dprintf-non-stop.c b/gdb/testsuite/gdb.base/dprintf-non-stop.c
index 2198848..2d25d9e 100644
--- a/gdb/testsuite/gdb.base/dprintf-non-stop.c
+++ b/gdb/testsuite/gdb.base/dprintf-non-stop.c
@@ -23,6 +23,7 @@ foo ()
int
main ()
{
+ sleep (1);
foo ();
sleep (3);
return 0;
diff --git a/gdb/testsuite/gdb.base/dprintf-non-stop.exp b/gdb/testsuite/gdb.base/dprintf-non-stop.exp
index c3fb85e..707f913 100644
--- a/gdb/testsuite/gdb.base/dprintf-non-stop.exp
+++ b/gdb/testsuite/gdb.base/dprintf-non-stop.exp
@@ -36,9 +36,22 @@ if ![runto main] {
gdb_test "dprintf foo,\"At foo entry\\n\"" "Dprintf .*"
-send_gdb "continue &\n"
-exec sleep 1
+gdb_test "continue &" "Continuing\\."
+# Wait for the dprintf to trigger.
+set test "dprintf triggered"
+gdb_expect {
+ -re "At foo entry" {
+ pass "$test"
+ }
+ timeout {
+ fail "$test (timeout)"
+ }
+}
+
+# Now test that we're still able to issue commands. GDB used to
+# implement re-resuming from dprintfs with a synchronous "continue" in
+# the dprintf's command list, which stole the prompt from the user.
set test "interrupt"
gdb_test_multiple $test $test {
-re "interrupt\r\n$gdb_prompt " {
--
1.7.11.7
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [RFC] PR 15075 dprintf interferes with "next"
2013-06-24 22:06 ` Pedro Alves
@ 2013-06-25 9:14 ` Hui Zhu
2013-06-25 11:47 ` Pedro Alves
0 siblings, 1 reply; 45+ messages in thread
From: Hui Zhu @ 2013-06-25 9:14 UTC (permalink / raw)
To: Pedro Alves; +Cc: Hui Zhu, Tom Tromey, gdb-patches, Keith Seitz, Yao Qi
[-- Attachment #1: Type: text/plain, Size: 5408 bytes --]
On 06/25/13 04:20, Pedro Alves wrote:
> On 06/24/2013 05:24 AM, Hui Zhu wrote:
>
>>> Hmm, this still looks racy to me, even on native targets.
>>> "continue &" produces a gdb prompt. gdb_test_multiple
>>> inside has a match for the prompt:
>>>
>>> -re "\r\n$gdb_prompt $" {
>>> if ![string match "" $message] then {
>>> fail "$message"
>>> }
>>> set result 1
>>> }
>>>
>>> So if the expect happens to read
>>>
>>> continue &
>>> (gdb)
>>>
>>> from the buffer, we'll hit the fail. Doesn't the read1 hack catch this?
>>
>> EXPECT=../contrib/expect-read1.sh make check RUNTESTFLAGS="dprintf-non-stop.exp" is OK in my part.
>
> I suspect the "exec sleep 1" is masking it. If you remove the sleep,
> then the test fails.
>
>>
>>>
>>> We need to consume the prompt after that "continue&".
>>>
>>>> + }
>>>> +}
>>>> +
>>>> +set test "inferior stopped"
>>>> +gdb_test_multiple "" $test {
>>>> + -re "\r\n\\\[.* \[0-9\]+\\\] #1 stopped\\\.\r\n" {
>>>> + pass $test
>>>> + }
>>>> +}
>>>
>>> Likewise?
>>>
>>
>> I just copy this part of code from "gdb.base/async-shell.exp".
>> Could you give me some help about how to consume the prompt after that "continue&"?
>
> Just doing:
>
> -send_gdb "continue &\n"
> +gdb_test "continue &" "Continuing\\."
>
> will consume the prompt. Otherwise, we'd do like
> e.g., completion.exp does:
>
> # Eat the prompt
> gdb_expect {
> -re "$gdb_prompt " {
> pass "$test (eat prompt)"
> }
> timeout {
> fail "(timeout) $test (eat prompt)"
> }
> }
>
> We still need the sleep, but for different a reason -- be sure
> to wait for the dprintf to trigger -- we need GDB to print the
> prompt before the program reaches the dprintf. I think it's slightly
> better to do the sleep on the inferior program side. We can expect
> the "At foo entry" output from the dprintf, as the default "set dprintf-style"
> is "gdb".
>
> I see now that the
>
> set test "inferior stopped"
> gdb_test_multiple "" $test {
> -re "\r\n\\\[.* \[0-9\]+\\\] #1 stopped\\\.\r\n" {
> pass $test
> }
> }
>
> case doesn't need to eat the prompt, as that output appears
> after the prompt:
>
> (gdb) PASS: gdb.base/dprintf-non-stop.exp: continue &
> At foo entry
> PASS: gdb.base/dprintf-non-stop.exp: dprintf triggered
> interrupt
> (gdb)
> [process 6106] #1 stopped.
> PASS: gdb.base/dprintf-non-stop.exp: interrupt
> PASS: gdb.base/dprintf-non-stop.exp: inferior stopped
>
> and the "interrupt" test already eats it.
>
> See patchlet on top of yours below. Please merge it with
> yours, and push the result in (and post it, for the archives).
Hi Pedro,
Thanks for your patch.
I merged it with old patch together.
Please help me review it.
Thanks,
Hui
2013-06-25 Yao Qi <yao@codesourcery.com>
Hui Zhu <hui@codesourcery.com>
Pedro Alves <palves@redhat.com>
PR breakpoints/15075
PR breakpoints/15434
* breakpoint.c (bpstat_stop_status): Call
b->ops->after_condition_true.
(update_dprintf_command_list): Don't append "continue" command
to the command list of dprintf breakpoint.
(base_breakpoint_after_condition_true): New function.
(base_breakpoint_ops): Add base_breakpoint_after_condition_true.
(dprintf_after_condition_true): New function.
(initialize_breakpoint_ops): Set dprintf_after_condition_true.
* breakpoint.h (breakpoint_ops): Add after_condition_true.
2013-06-25 Yao Qi <yao@codesourcery.com>
Hui Zhu <hui@codesourcery.com>
Pedro Alves <palves@redhat.com>
PR breakpoints/15075
PR breakpoints/15434
* gdb.base/dprintf-next.c: New file.
* gdb.base/dprintf-next.exp: New file.
* gdb.base/dprintf-non-stop.c: New file.
* gdb.base/dprintf-non-stop.exp: New file.
* gdb.base/dprintf.exp: Don't check "continue" in the output
of "info breakpoints".
* gdb.mi/mi-breakpoint-changed.exp (test_insert_delete_modify):
Don't check "continue" in script field.
>
> Thanks,
> Pedro Alves
>
> ---
> gdb/testsuite/gdb.base/dprintf-non-stop.c | 1 +
> gdb/testsuite/gdb.base/dprintf-non-stop.exp | 17 +++++++++++++++--
> 2 files changed, 16 insertions(+), 2 deletions(-)
>
> diff --git a/gdb/testsuite/gdb.base/dprintf-non-stop.c b/gdb/testsuite/gdb.base/dprintf-non-stop.c
> index 2198848..2d25d9e 100644
> --- a/gdb/testsuite/gdb.base/dprintf-non-stop.c
> +++ b/gdb/testsuite/gdb.base/dprintf-non-stop.c
> @@ -23,6 +23,7 @@ foo ()
> int
> main ()
> {
> + sleep (1);
> foo ();
> sleep (3);
> return 0;
> diff --git a/gdb/testsuite/gdb.base/dprintf-non-stop.exp b/gdb/testsuite/gdb.base/dprintf-non-stop.exp
> index c3fb85e..707f913 100644
> --- a/gdb/testsuite/gdb.base/dprintf-non-stop.exp
> +++ b/gdb/testsuite/gdb.base/dprintf-non-stop.exp
> @@ -36,9 +36,22 @@ if ![runto main] {
>
> gdb_test "dprintf foo,\"At foo entry\\n\"" "Dprintf .*"
>
> -send_gdb "continue &\n"
> -exec sleep 1
> +gdb_test "continue &" "Continuing\\."
>
> +# Wait for the dprintf to trigger.
> +set test "dprintf triggered"
> +gdb_expect {
> + -re "At foo entry" {
> + pass "$test"
> + }
> + timeout {
> + fail "$test (timeout)"
> + }
> +}
> +
> +# Now test that we're still able to issue commands. GDB used to
> +# implement re-resuming from dprintfs with a synchronous "continue" in
> +# the dprintf's command list, which stole the prompt from the user.
> set test "interrupt"
> gdb_test_multiple $test $test {
> -re "interrupt\r\n$gdb_prompt " {
>
[-- Attachment #2: dprintf-continue.txt --]
[-- Type: text/plain, Size: 4469 bytes --]
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -5299,6 +5299,8 @@ bpstat_stop_status (struct address_space
if (command_line_is_silent (bs->commands
? bs->commands->commands : NULL))
bs->print = 0;
+
+ b->ops->after_condition_true (bs);
}
}
@@ -8934,25 +8936,16 @@ update_dprintf_command_list (struct brea
_("Invalid dprintf style."));
gdb_assert (printf_line != NULL);
- /* Manufacture a printf/continue sequence. */
+ /* Manufacture a printf sequence. */
{
- struct command_line *printf_cmd_line, *cont_cmd_line = NULL;
-
- if (strcmp (dprintf_style, dprintf_style_agent) != 0)
- {
- cont_cmd_line = xmalloc (sizeof (struct command_line));
- cont_cmd_line->control_type = simple_control;
- cont_cmd_line->body_count = 0;
- cont_cmd_line->body_list = NULL;
- cont_cmd_line->next = NULL;
- cont_cmd_line->line = xstrdup ("continue");
- }
+ struct command_line *printf_cmd_line
+ = xmalloc (sizeof (struct command_line));
printf_cmd_line = xmalloc (sizeof (struct command_line));
printf_cmd_line->control_type = simple_control;
printf_cmd_line->body_count = 0;
printf_cmd_line->body_list = NULL;
- printf_cmd_line->next = cont_cmd_line;
+ printf_cmd_line->next = NULL;
printf_cmd_line->line = printf_line;
breakpoint_set_commands (b, printf_cmd_line);
@@ -12738,6 +12731,14 @@ base_breakpoint_explains_signal (struct
return BPSTAT_SIGNAL_HIDE;
}
+/* The default "after_condition_true" method. */
+
+static void
+base_breakpoint_after_condition_true (struct bpstats *bs)
+{
+ /* Nothing to do. */
+}
+
struct breakpoint_ops base_breakpoint_ops =
{
base_breakpoint_dtor,
@@ -12757,7 +12758,8 @@ struct breakpoint_ops base_breakpoint_op
base_breakpoint_create_sals_from_address,
base_breakpoint_create_breakpoints_sal,
base_breakpoint_decode_linespec,
- base_breakpoint_explains_signal
+ base_breakpoint_explains_signal,
+ base_breakpoint_after_condition_true,
};
/* Default breakpoint_ops methods. */
@@ -13351,6 +13353,44 @@ dprintf_print_recreate (struct breakpoin
print_recreate_thread (tp, fp);
}
+/* Implement the "after_condition_true" breakpoint_ops method for
+ dprintf.
+
+ dprintf's are implemented with regular commands in their command
+ list, but we run the commands here instead of before presenting the
+ stop to the user, as dprintf's don't actually cause a stop. This
+ also makes it so that the commands of multiple dprintfs at the same
+ address are all handled. */
+
+static void
+dprintf_after_condition_true (struct bpstats *bs)
+{
+ struct cleanup *old_chain;
+ struct bpstats tmp_bs = { NULL };
+ struct bpstats *tmp_bs_p = &tmp_bs;
+
+ /* dprintf's never cause a stop. This wasn't set in the
+ check_status hook instead because that would make the dprintf's
+ condition not be evaluated. */
+ bs->stop = 0;
+
+ /* Run the command list here. Take ownership of it instead of
+ copying. We never want these commands to run later in
+ bpstat_do_actions, if a breakpoint that causes a stop happens to
+ be set at same address as this dprintf, or even if running the
+ commands here throws. */
+ tmp_bs.commands = bs->commands;
+ bs->commands = NULL;
+ old_chain = make_cleanup_decref_counted_command_line (&tmp_bs.commands);
+
+ bpstat_do_actions_1 (&tmp_bs_p);
+
+ /* 'tmp_bs.commands' will usually be NULL by now, but
+ bpstat_do_actions_1 may return early without processing the whole
+ list. */
+ do_cleanups (old_chain);
+}
+
/* The breakpoint_ops structure to be used on static tracepoints with
markers (`-m'). */
@@ -15847,6 +15887,7 @@ initialize_breakpoint_ops (void)
ops->print_it = bkpt_print_it;
ops->print_mention = bkpt_print_mention;
ops->print_recreate = dprintf_print_recreate;
+ ops->after_condition_true = dprintf_after_condition_true;
}
/* Chain containing all defined "enable breakpoint" subcommands. */
--- a/gdb/breakpoint.h
+++ b/gdb/breakpoint.h
@@ -614,6 +614,10 @@ struct breakpoint_ops
'catch signal' interact properly with 'handle'; see
bpstat_explains_signal. */
enum bpstat_signal_value (*explains_signal) (struct breakpoint *);
+
+ /* Called after evaluating the breakpoint's condition,
+ and only if it evaluated true. */
+ void (*after_condition_true) (struct bpstats *bs);
};
/* Helper for breakpoint_ops->print_recreate implementations. Prints
[-- Attachment #3: dprintf-continue-test.txt --]
[-- Type: text/plain, Size: 6539 bytes --]
--- /dev/null
+++ b/gdb/testsuite/gdb.base/dprintf-next.c
@@ -0,0 +1,26 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright (C) 2013 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+int
+main (void)
+{
+ int x = 5;
+
+ ++x; /* Next without dprintf. */
+ ++x; /* Set dprintf here. */
+ return x - 7;
+}
--- /dev/null
+++ b/gdb/testsuite/gdb.base/dprintf-next.exp
@@ -0,0 +1,36 @@
+# Copyright 2013 Free Software Foundation, Inc.
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+standard_testfile
+
+set executable $testfile
+set expfile $testfile.exp
+
+set dp_location [gdb_get_line_number "Set dprintf here"]
+
+if [prepare_for_testing "failed to prepare for dprintf with next" \
+ ${testfile} ${srcfile} {debug}] {
+ return -1
+}
+
+if ![runto_main] {
+ fail "Can't run to main"
+ return -1
+}
+
+gdb_test "dprintf $dp_location, \"%d\\n\", x" \
+ "Dprintf .*"
+
+gdb_test "next" "\\+\\+x\;.*\/\* Next without dprintf.*" "next 1"
+gdb_test "next" "\\+\\+x\;.*\/\* Set dprintf here.*" "next 2"
--- /dev/null
+++ b/gdb/testsuite/gdb.base/dprintf-non-stop.c
@@ -0,0 +1,30 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright (C) 2013 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+void
+foo ()
+{
+}
+
+int
+main ()
+{
+ sleep (1);
+ foo ();
+ sleep (3);
+ return 0;
+}
--- /dev/null
+++ b/gdb/testsuite/gdb.base/dprintf-non-stop.exp
@@ -0,0 +1,67 @@
+# Copyright (C) 2013 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+if [is_remote target] then {
+ # Testing with remote/non-stop is racy at the moment.
+ unsupported "Testing dprintf with remote/non-stop is not supported."
+ return 0
+}
+
+standard_testfile
+
+if [prepare_for_testing "failed to prepare for dprintf with non-stop" \
+ ${testfile} ${srcfile} {debug}] {
+ return -1
+}
+
+gdb_test_no_output "set target-async on"
+gdb_test_no_output "set non-stop on"
+
+if ![runto main] {
+ fail "Can't run to main"
+ return -1
+}
+
+gdb_test "dprintf foo,\"At foo entry\\n\"" "Dprintf .*"
+
+gdb_test "continue &" "Continuing\\."
+
+# Wait for the dprintf to trigger.
+set test "dprintf triggered"
+gdb_expect {
+ -re "At foo entry" {
+ pass "$test"
+ }
+ timeout {
+ fail "$test (timeout)"
+ }
+}
+
+# Now test that we're still able to issue commands. GDB used to
+# implement re-resuming from dprintfs with a synchronous "continue" in
+# the dprintf's command list, which stole the prompt from the user.
+set test "interrupt"
+gdb_test_multiple $test $test {
+ -re "interrupt\r\n$gdb_prompt " {
+ pass $test
+ }
+}
+
+set test "inferior stopped"
+gdb_test_multiple "" $test {
+ -re "\r\n\\\[.* \[0-9\]+\\\] #1 stopped\\\.\r\n" {
+ pass $test
+ }
+}
--- a/gdb/testsuite/gdb.base/dprintf.exp
+++ b/gdb/testsuite/gdb.base/dprintf.exp
@@ -50,10 +50,8 @@ gdb_test_sequence "info breakpoints" "dp
"\[\r\n\]2 breakpoint"
"\[\r\n\]3 dprintf"
"\[\r\n\] printf \"At foo entry\\\\n\""
- "\[\r\n\] continue"
"\[\r\n\]4 dprintf"
"\[\r\n\] printf \"arg=%d, g=%d\\\\n\", arg, g"
- "\[\r\n\] continue"
}
gdb_test "break $bp_location1" \
@@ -111,7 +109,6 @@ gdb_test_multiple "set dprintf-style age
}
if $target_can_dprintf {
-
gdb_run_cmd
gdb_test "" "Breakpoint"
@@ -135,4 +132,3 @@ if $target_can_dprintf {
gdb_test "set dprintf-style foobar" "Undefined item: \"foobar\"." \
"Set dprintf style to an unrecognized type"
-
--- a/gdb/testsuite/gdb.mi/mi-breakpoint-changed.exp
+++ b/gdb/testsuite/gdb.mi/mi-breakpoint-changed.exp
@@ -96,7 +96,7 @@ proc test_insert_delete_modify { } {
$test
set test "dprintf marker, \"arg\" \""
mi_gdb_test $test \
- {.*=breakpoint-created,bkpt=\{number="6",type="dprintf".*,script=\{\"printf \\\\\"arg\\\\\" \\\\\"\",\"continue\"\}.*\}\r\n\^done} \
+ {.*=breakpoint-created,bkpt=\{number="6",type="dprintf".*,script=\{\"printf \\\\\"arg\\\\\" \\\\\"\"\}.*\}\r\n\^done} \
$test
# 2. when modifying condition
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [RFC] PR 15075 dprintf interferes with "next"
2013-06-25 9:14 ` Hui Zhu
@ 2013-06-25 11:47 ` Pedro Alves
2013-06-25 13:02 ` Hui Zhu
0 siblings, 1 reply; 45+ messages in thread
From: Pedro Alves @ 2013-06-25 11:47 UTC (permalink / raw)
To: Hui Zhu; +Cc: Hui Zhu, Tom Tromey, gdb-patches, Keith Seitz, Yao Qi
On 06/25/2013 09:53 AM, Hui Zhu wrote:
> On 06/25/13 04:20, Pedro Alves wrote:
>> See patchlet on top of yours below. Please merge it with
>> yours, and push the result in (and post it, for the archives).
>
> Hi Pedro,
>
> Thanks for your patch.
>
> I merged it with old patch together.
>
> Please help me review it.
OK.
Thanks,
--
Pedro Alves
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [RFC] PR 15075 dprintf interferes with "next"
2013-06-25 11:47 ` Pedro Alves
@ 2013-06-25 13:02 ` Hui Zhu
2013-06-25 14:06 ` Pedro Alves
0 siblings, 1 reply; 45+ messages in thread
From: Hui Zhu @ 2013-06-25 13:02 UTC (permalink / raw)
To: Pedro Alves; +Cc: Hui Zhu, Tom Tromey, gdb-patches, Keith Seitz, Yao Qi
On 06/25/13 17:57, Pedro Alves wrote:
> On 06/25/2013 09:53 AM, Hui Zhu wrote:
>> On 06/25/13 04:20, Pedro Alves wrote:
>
>>> See patchlet on top of yours below. Please merge it with
>>> yours, and push the result in (and post it, for the archives).
>>
>> Hi Pedro,
>>
>> Thanks for your patch.
>>
>> I merged it with old patch together.
>>
>> Please help me review it.
>
> OK.
>
> Thanks,
>
Thanks for your help. Checked in to http://sourceware.org/ml/gdb-cvs/2013-06/msg00156.html
Can I commit the patch to 7.6 branch?
Thanks,
Hui
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [RFC] PR 15075 dprintf interferes with "next"
2013-06-25 13:02 ` Hui Zhu
@ 2013-06-25 14:06 ` Pedro Alves
2013-06-26 2:54 ` Hui Zhu
0 siblings, 1 reply; 45+ messages in thread
From: Pedro Alves @ 2013-06-25 14:06 UTC (permalink / raw)
To: Hui Zhu; +Cc: Hui Zhu, Tom Tromey, gdb-patches, Keith Seitz, Yao Qi
On 06/25/2013 12:47 PM, Hui Zhu wrote:
> Thanks for your help. Checked in to http://sourceware.org/ml/gdb-cvs/2013-06/msg00156.html
>
> Can I commit the patch to 7.6 branch?
Fine with me. This is pretty isolated to dprintf, so should
be safe enough. Please add a reference to the PRs at:
<http://sourceware.org/gdb/wiki/GDB_7.6_Release>.
--
Pedro Alves
^ permalink raw reply [flat|nested] 45+ messages in thread
* Re: [RFC] PR 15075 dprintf interferes with "next"
2013-06-25 14:06 ` Pedro Alves
@ 2013-06-26 2:54 ` Hui Zhu
0 siblings, 0 replies; 45+ messages in thread
From: Hui Zhu @ 2013-06-26 2:54 UTC (permalink / raw)
To: Pedro Alves; +Cc: Hui Zhu, Tom Tromey, gdb-patches, Keith Seitz, Yao Qi
On Tue, Jun 25, 2013 at 9:56 PM, Pedro Alves <palves@redhat.com> wrote:
> On 06/25/2013 12:47 PM, Hui Zhu wrote:
>
>> Thanks for your help. Checked in to http://sourceware.org/ml/gdb-cvs/2013-06/msg00156.html
>>
>> Can I commit the patch to 7.6 branch?
>
> Fine with me. This is pretty isolated to dprintf, so should
> be safe enough. Please add a reference to the PRs at:
> <http://sourceware.org/gdb/wiki/GDB_7.6_Release>.
>
Thanks. Checked in to 7.6 branch.
http://sourceware.org/ml/gdb-cvs/2013-06/msg00161.html
http://sourceware.org/ml/gdb-cvs/2013-06/msg00162.html
And I updated <http://sourceware.org/gdb/wiki/GDB_7.6_Release> for this fix.
Best,
Hui
> --
> Pedro Alves
>
^ permalink raw reply [flat|nested] 45+ messages in thread
end of thread, other threads:[~2013-06-26 2:48 UTC | newest]
Thread overview: 45+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-02-18 13:09 [RFC] PR 15075 dprintf interferes with "next" Yao Qi
2013-02-18 21:36 ` Joel Brobecker
2013-02-21 16:36 ` Tom Tromey
2013-04-24 1:24 ` Hui Zhu
2013-04-24 6:06 ` Keith Seitz
2013-04-24 13:30 ` Hui Zhu
2013-04-24 14:03 ` Yao Qi
2013-04-24 14:09 ` Hui Zhu
2013-05-16 7:29 ` Hui Zhu
2013-05-17 21:01 ` Pedro Alves
2013-05-22 10:22 ` Hui Zhu
2013-05-22 12:46 ` Pedro Alves
2013-05-28 0:02 ` Hui Zhu
2013-05-28 3:36 ` Yao Qi
2013-05-29 10:08 ` Hui Zhu
2013-06-03 4:07 ` Hui Zhu
2013-06-03 17:48 ` Pedro Alves
2013-06-07 3:16 ` Hui Zhu
2013-06-17 7:36 ` Hui Zhu
2013-06-18 18:16 ` Pedro Alves
2013-06-24 8:36 ` Hui Zhu
2013-06-24 22:06 ` Pedro Alves
2013-06-25 9:14 ` Hui Zhu
2013-06-25 11:47 ` Pedro Alves
2013-06-25 13:02 ` Hui Zhu
2013-06-25 14:06 ` Pedro Alves
2013-06-26 2:54 ` Hui Zhu
2013-05-22 14:04 ` Tom Tromey
2013-02-22 17:39 ` DPrintf feedback (was: [RFC] PR 15075 dprintf interferes with "next") Marc Khouzam
2013-02-22 19:32 ` DPrintf feedback Tom Tromey
2013-02-22 20:37 ` Marc Khouzam
2013-02-26 21:12 ` Marc Khouzam
2013-02-28 15:32 ` [PATCH 1/4] Fix dprintf bugs Yao Qi
2013-02-28 13:17 ` [PATCH 3/4] Test dprintf breakpoint works correctly with other breakpoints Yao Qi
2013-02-28 13:17 ` [PATCH 2/4] Test case of conditional dprintf Yao Qi
2013-02-28 14:48 ` [PATCH 4/4] Test case on setting dprintf commands Yao Qi
2013-02-28 16:30 ` [PATCH 1/4] Fix dprintf bugs Eli Zaretskii
2013-03-07 7:45 ` Yao Qi
2013-03-03 2:21 ` Marc Khouzam
2013-03-07 6:47 ` Yao Qi
2013-03-07 14:06 ` Marc Khouzam
2013-03-07 14:36 ` Yao Qi
2013-03-07 14:49 ` Marc Khouzam
2013-03-07 14:59 ` Yao Qi
2013-03-08 15:49 ` Marc Khouzam
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox