* [PATCH] Conditional tracepoints
@ 2009-06-27 5:31 Stan Shebs
2009-06-27 12:55 ` Eli Zaretskii
` (2 more replies)
0 siblings, 3 replies; 8+ messages in thread
From: Stan Shebs @ 2009-06-27 5:31 UTC (permalink / raw)
To: gdb-patches
[-- Attachment #1: Type: text/plain, Size: 1899 bytes --]
This patch adds conditional tracepoints. Tracepoint conditions work by
being compiled into agent expressions that actually evaluate on the spot
in the target, rather than collecting blocks of trace data. As usual
for tracepoints, GDB proper doesn't have to do much, and most of the
code here revolves around checking for the "ConditionalTracepoints"
feature, so as to maintain compatibility with the two(?) existing
tracepoint implementations out there. As a bonus subpatch, I added
bytecode generation for comparison operators, other boolean ops are
coming later. I tested by exercising with CodeSourcery's target agent,
in the absence of anything usable in the GDB testsuite.
Stan
2009-06-26 Stan Shebs <stan@codesourcery.com>
Conditional tracepoints.
* ax-gdb.h (gen_eval_for_expr): Declare.
* ax-gdb.c (gen_expr): Generate bytecodes for BINOP_EQUAL
and other comparisons.
(gen_eval_for_expr): New function.
(agent_eval_command): New maintenance command.
(_initialize_ax_gdb): Define the command.
* remote.c (struct remote_state): New field cond_tracepoints.
(PACKET_ConditionalTracepoints): New packet config type.
(remote_cond_tracepoint_feature): New function.
(remote_protocol_features): Add ConditionalTracepoints.
(remote_supports_cond_tracepoints): New function.
(_initialize_remote): Add ConditionalTracepoints.
* tracepoint.c (download_tracepoint): Add conditional.
==> doc/ChangeLog <==
2009-06-26 Stan Shebs <stan@codesourcery.com>
* gdb.texinfo (Tracepoint Conditions): New section.
(General Query Packets): Describe ConditionalTracepoints.
(Tracepoint Packets): Describe condition field.
(Maintenance Commands): Describe maint agent-eval.
==> testsuite/ChangeLog <==
2009-06-26 Stan Shebs <stan@codesourcery.com>
* gdb.trace/tracecmd.exp: Add basic test of tracepoint conditions.
[-- Attachment #2: cond-tp-patch-3 --]
[-- Type: text/plain, Size: 17405 bytes --]
Index: ax-gdb.c
===================================================================
RCS file: /cvs/src/src/gdb/ax-gdb.c,v
retrieving revision 1.50
diff -p -r1.50 ax-gdb.c
*** ax-gdb.c 17 Jun 2009 18:40:53 -0000 1.50
--- ax-gdb.c 27 Jun 2009 05:17:09 -0000
*************** gen_expr (struct expression *exp, union
*** 1469,1474 ****
--- 1469,1480 ----
case BINOP_BITWISE_AND:
case BINOP_BITWISE_IOR:
case BINOP_BITWISE_XOR:
+ case BINOP_EQUAL:
+ case BINOP_NOTEQUAL:
+ case BINOP_LESS:
+ case BINOP_GTR:
+ case BINOP_LEQ:
+ case BINOP_GEQ:
(*pc)++;
gen_expr (exp, pc, ax, &value1);
gen_usual_unary (exp, ax, &value1);
*************** gen_expr (struct expression *exp, union
*** 1538,1543 ****
--- 1544,1590 ----
aop_bit_xor, aop_bit_xor, 0, "bitwise exclusive-or");
break;
+ case BINOP_EQUAL:
+ gen_binop (ax, value, &value1, &value2,
+ aop_equal, aop_equal, 0, "equal");
+ break;
+
+ case BINOP_NOTEQUAL:
+ gen_binop (ax, value, &value1, &value2,
+ aop_equal, aop_equal, 0, "equal");
+ gen_logical_not (ax, value,
+ language_bool_type (exp->language_defn,
+ exp->gdbarch));
+ break;
+
+ case BINOP_LESS:
+ gen_binop (ax, value, &value1, &value2,
+ aop_less_signed, aop_less_unsigned, 0, "less than");
+ break;
+
+ case BINOP_GTR:
+ ax_simple (ax, aop_swap);
+ gen_binop (ax, value, &value1, &value2,
+ aop_less_signed, aop_less_unsigned, 0, "less than");
+ break;
+
+ case BINOP_LEQ:
+ ax_simple (ax, aop_swap);
+ gen_binop (ax, value, &value1, &value2,
+ aop_less_signed, aop_less_unsigned, 0, "less than");
+ gen_logical_not (ax, value,
+ language_bool_type (exp->language_defn,
+ exp->gdbarch));
+ break;
+
+ case BINOP_GEQ:
+ gen_binop (ax, value, &value1, &value2,
+ aop_less_signed, aop_less_unsigned, 0, "less than");
+ gen_logical_not (ax, value,
+ language_bool_type (exp->language_defn,
+ exp->gdbarch));
+ break;
+
default:
/* We should only list operators in the outer case statement
that we actually handle in the inner case statement. */
*************** gen_trace_for_expr (CORE_ADDR scope, str
*** 1756,1761 ****
--- 1803,1833 ----
return ax;
}
+
+ struct agent_expr *
+ gen_eval_for_expr (CORE_ADDR scope, struct expression *expr)
+ {
+ struct cleanup *old_chain = 0;
+ struct agent_expr *ax = new_agent_expr (scope);
+ union exp_element *pc;
+ struct axs_value value;
+
+ old_chain = make_cleanup_free_agent_expr (ax);
+
+ pc = expr->elts;
+ trace_kludge = 0;
+ gen_expr (expr, &pc, ax, &value);
+
+ /* Oh, and terminate. */
+ ax_simple (ax, aop_end);
+
+ /* We have successfully built the agent expr, so cancel the cleanup
+ request. If we add more cleanups that we always want done, this
+ will have to get more complicated. */
+ discard_cleanups (old_chain);
+ return ax;
+ }
+
static void
agent_command (char *exp, int from_tty)
{
*************** agent_command (char *exp, int from_tty)
*** 1786,1791 ****
--- 1858,1898 ----
do_cleanups (old_chain);
dont_repeat ();
}
+
+ /* Parse the given expression, compile it into an agent expression
+ that does direct evaluation, and display the resulting
+ expression. */
+
+ static void
+ agent_eval_command (char *exp, int from_tty)
+ {
+ struct cleanup *old_chain = 0;
+ struct expression *expr;
+ struct agent_expr *agent;
+ struct frame_info *fi = get_current_frame (); /* need current scope */
+
+ /* We don't deal with overlay debugging at the moment. We need to
+ think more carefully about this. If you copy this code into
+ another command, change the error message; the user shouldn't
+ have to know anything about agent expressions. */
+ if (overlay_debugging)
+ error (_("GDB can't do agent expression translation with overlays."));
+
+ if (exp == 0)
+ error_no_arg (_("expression to translate"));
+
+ expr = parse_expression (exp);
+ old_chain = make_cleanup (free_current_contents, &expr);
+ agent = gen_eval_for_expr (get_frame_pc (fi), expr);
+ make_cleanup_free_agent_expr (agent);
+ ax_print (gdb_stdout, agent);
+
+ /* It would be nice to call ax_reqs here to gather some general info
+ about the expression, and then print out the result. */
+
+ do_cleanups (old_chain);
+ dont_repeat ();
+ }
\f
/* Initialization code. */
*************** void
*** 1795,1800 ****
_initialize_ax_gdb (void)
{
add_cmd ("agent", class_maintenance, agent_command,
! _("Translate an expression into remote agent bytecode."),
&maintenancelist);
}
--- 1902,1911 ----
_initialize_ax_gdb (void)
{
add_cmd ("agent", class_maintenance, agent_command,
! _("Translate an expression into remote agent bytecode for tracing."),
! &maintenancelist);
!
! add_cmd ("agent-eval", class_maintenance, agent_eval_command,
! _("Translate an expression into remote agent bytecode for evaluation."),
&maintenancelist);
}
Index: ax-gdb.h
===================================================================
RCS file: /cvs/src/src/gdb/ax-gdb.h,v
retrieving revision 1.11
diff -p -r1.11 ax-gdb.h
*** ax-gdb.h 3 Jan 2009 05:57:50 -0000 1.11
--- ax-gdb.h 27 Jun 2009 05:17:09 -0000
*************** struct axs_value
*** 99,102 ****
--- 99,104 ----
function to discover which registers the expression uses. */
extern struct agent_expr *gen_trace_for_expr (CORE_ADDR, struct expression *);
+ extern struct agent_expr *gen_eval_for_expr (CORE_ADDR, struct expression *);
+
#endif /* AX_GDB_H */
Index: remote.c
===================================================================
RCS file: /cvs/src/src/gdb/remote.c,v
retrieving revision 1.360
diff -p -r1.360 remote.c
*** remote.c 22 Jun 2009 16:03:33 -0000 1.360
--- remote.c 27 Jun 2009 05:17:11 -0000
*************** struct remote_state
*** 294,299 ****
--- 294,302 ----
/* True if the stub reports support for vCont;t. */
int support_vCont_t;
+
+ /* True if the stub reports support for conditional tracepoints. */
+ int cond_tracepoints;
};
/* Returns true if the multi-process extensions are in effect. */
*************** enum {
*** 993,998 ****
--- 996,1002 ----
PACKET_qXfer_siginfo_read,
PACKET_qXfer_siginfo_write,
PACKET_qAttached,
+ PACKET_ConditionalTracepoints,
PACKET_MAX
};
*************** remote_non_stop_feature (const struct pr
*** 3014,3019 ****
--- 3018,3032 ----
rs->non_stop_aware = (support == PACKET_ENABLE);
}
+ static void
+ remote_cond_tracepoint_feature (const struct protocol_feature *feature,
+ enum packet_support support,
+ const char *value)
+ {
+ struct remote_state *rs = get_remote_state ();
+ rs->cond_tracepoints = (support == PACKET_ENABLE);
+ }
+
static struct protocol_feature remote_protocol_features[] = {
{ "PacketSize", PACKET_DISABLE, remote_packet_size, -1 },
{ "qXfer:auxv:read", PACKET_DISABLE, remote_supported_packet,
*************** static struct protocol_feature remote_pr
*** 3040,3045 ****
--- 3053,3060 ----
PACKET_qXfer_siginfo_read },
{ "qXfer:siginfo:write", PACKET_DISABLE, remote_supported_packet,
PACKET_qXfer_siginfo_write },
+ { "ConditionalTracepoints", PACKET_DISABLE, remote_cond_tracepoint_feature,
+ PACKET_ConditionalTracepoints },
};
static void
*************** remote_supports_multi_process (void)
*** 8730,8735 ****
--- 8745,8757 ----
return remote_multi_process_p (rs);
}
+ int
+ remote_supports_cond_tracepoints (void)
+ {
+ struct remote_state *rs = get_remote_state ();
+ return rs->cond_tracepoints;
+ }
+
static void
init_remote_ops (void)
{
*************** Show the maximum size of the address (in
*** 9173,9178 ****
--- 9195,9203 ----
add_packet_config_cmd (&remote_protocol_packets[PACKET_qAttached],
"qAttached", "query-attached", 0);
+ add_packet_config_cmd (&remote_protocol_packets[PACKET_ConditionalTracepoints],
+ "ConditionalTracepoints", "conditional-tracepoints", 0);
+
/* Keep the old ``set remote Z-packet ...'' working. Each individual
Z sub-packet has its own set and show commands, but users may
have sets to this variable in their .gdbinit files (or in their
Index: tracepoint.c
===================================================================
RCS file: /cvs/src/src/gdb/tracepoint.c,v
retrieving revision 1.122
diff -p -r1.122 tracepoint.c
*** tracepoint.c 4 Jun 2009 12:28:39 -0000 1.122
--- tracepoint.c 27 Jun 2009 05:17:11 -0000
***************
*** 32,37 ****
--- 32,38 ----
#include "breakpoint.h"
#include "tracepoint.h"
#include "remote.h"
+ extern int remote_supports_cond_tracepoints (void);
#include "linespec.h"
#include "regcache.h"
#include "completer.h"
*************** download_tracepoint (struct breakpoint *
*** 1335,1346 ****
--- 1336,1366 ----
char **stepping_actions;
int ndx;
struct cleanup *old_chain = NULL;
+ struct agent_expr *aexpr;
+ struct cleanup *aexpr_chain = NULL;
sprintf_vma (tmp, (t->loc ? t->loc->address : 0));
sprintf (buf, "QTDP:%x:%s:%c:%lx:%x", t->number,
tmp, /* address */
(t->enable_state == bp_enabled ? 'E' : 'D'),
t->step_count, t->pass_count);
+ /* If the tracepoint has a conditional, make it into an agent
+ expression and append to the definition. */
+ if (t->loc->cond)
+ {
+ /* Only test support at download time, we may not know target
+ capabilities at definition time. */
+ if (remote_supports_cond_tracepoints ())
+ {
+ aexpr = gen_eval_for_expr (t->loc->address, t->loc->cond);
+ aexpr_chain = make_cleanup_free_agent_expr (aexpr);
+ sprintf (buf + strlen (buf), ":X%x,", aexpr->len);
+ mem2hex (aexpr->buf, buf + strlen (buf), aexpr->len);
+ do_cleanups (aexpr_chain);
+ }
+ else
+ warning (_("Target does not support conditional tracepoints, ignoring tp %d cond"), t->number);
+ }
if (t->actions)
strcat (buf, "-");
Index: doc/gdb.texinfo
===================================================================
RCS file: /cvs/src/src/gdb/doc/gdb.texinfo,v
retrieving revision 1.600
diff -p -r1.600 gdb.texinfo
*** doc/gdb.texinfo 15 Jun 2009 12:11:36 -0000 1.600
--- doc/gdb.texinfo 27 Jun 2009 05:17:17 -0000
*************** conditions and actions.
*** 8845,8850 ****
--- 8845,8851 ----
* Create and Delete Tracepoints::
* Enable and Disable Tracepoints::
* Tracepoint Passcounts::
+ * Tracepoint Conditions::
* Tracepoint Actions::
* Listing Tracepoints::
* Starting and Stopping Trace Experiments::
*************** Here are some examples of using the @cod
*** 8884,8889 ****
--- 8885,8897 ----
@noindent
You can abbreviate @code{trace} as @code{tr}.
+ @item trace @var{location} if @var{cond}
+ Set a tracepoint with condition @var{cond}; evaluate the expression
+ @var{cond} each time the tracepoint is reached, and collect data only
+ if the value is nonzero---that is, if @var{cond} evaluates as true.
+ @xref{Tracepoint Conditions, ,Tracepoint Conditions}, for more
+ information on tracepoint conditions.
+
@vindex $tpnum
@cindex last tracepoint number
@cindex recent tracepoint number
*************** Examples:
*** 8966,8971 ****
--- 8974,9017 ----
@end smallexample
@end table
+ @node Tracepoint Conditions
+ @subsection Tracepoint Conditions
+ @cindex conditional tracepoints
+ @cindex tracepoint conditions
+
+ The simplest sort of tracepoint collects data every time your program
+ reaches a specified place. You can also specify a @dfn{condition} for
+ a tracepoint. A condition is just a Boolean expression in your
+ programming language (@pxref{Expressions, ,Expressions}). A
+ tracepoint with a condition evaluates the expression each time your
+ program reaches it, and data collection happens only if the condition
+ is @emph{true}.
+
+ Tracepoint conditions can be specified when a tracepoint is set, by
+ using @samp{if} in the arguments to the @code{trace} command.
+ @xref{Create and Delete Tracepoints, ,Setting Tracepoints}. They can
+ also be set or changed at any time with the @code{condition} command,
+ just as with breakpoints.
+
+ In contrast to breakpoint conditions, @value{GDBN} does not actually
+ evaluate @var{expression} at the time the @code{condition} command (or
+ a command that sets a tracepoint with a condition, like @code{trace if
+ @dots{}}) is given, however. @xref{Expressions, ,Expressions}.
+ Instead, @value{GDBN} encodes the expression into a form suitable for
+ execution on the target, independently of @value{GDBN}. Global
+ variables become raw memory locations, locals become stack accesses,
+ and so forth.
+
+ For instance, the following tracepoint command might be useful in
+ collecting data about uses of a function that should not be called when
+ an error has occurred and is propagating through the program; an
+ unconditional tracepoint could end up collecting thousands of useless
+ frames that you would have to search through.
+
+ @smallexample
+ (@value{GDBP}) @b{trace normal_operation if errcode > 0}
+ @end smallexample
+
@node Tracepoint Actions
@subsection Tracepoint Action Lists
*************** messages, see @ref{Debugging Output}.)
*** 26393,26402 ****
@table @code
@kindex maint agent
@item maint agent @var{expression}
Translate the given @var{expression} into remote agent bytecodes.
This command is useful for debugging the Agent Expression mechanism
! (@pxref{Agent Expressions}).
@kindex maint info breakpoints
@item @anchor{maint info breakpoints}maint info breakpoints
--- 26439,26453 ----
@table @code
@kindex maint agent
+ @kindex maint agent-eval
@item maint agent @var{expression}
+ @itemx maint agent-eval @var{expression}
Translate the given @var{expression} into remote agent bytecodes.
This command is useful for debugging the Agent Expression mechanism
! (@pxref{Agent Expressions}). The @samp{agent} version produces an
! expression useful for data collection, such as by tracepoints, while
! @samp{maint agent-eval} produces an expression that evaluates directly
! to a result.
@kindex maint info breakpoints
@item @anchor{maint info breakpoints}maint info breakpoints
*************** These are the currently defined stub fea
*** 28274,28279 ****
--- 28325,28335 ----
@tab @samp{-}
@tab No
+ @item @samp{ConditionalTracepoints}
+ @tab No
+ @tab @samp{-}
+ @tab No
+
@end multitable
These are the currently defined stub features, in more detail:
*************** indicated it supports them in its @samp{
*** 28351,28356 ****
--- 28407,28416 ----
The remote stub understands the @samp{qXfer:osdata:read} packet
((@pxref{qXfer osdata read}).
+ @item ConditionalTracepoints
+ The remote stub accepts and tests conditional expressions defined for
+ tracepoints (@pxref{Tracepoint Conditions}).
+
@end table
@item qSymbol::
*************** tracepoints (@pxref{Tracepoints}).
*** 28663,28673 ****
@table @samp
! @item QTDP:@var{n}:@var{addr}:@var{ena}:@var{step}:@var{pass}@r{[}-@r{]}
Create a new tracepoint, number @var{n}, at @var{addr}. If @var{ena}
is @samp{E}, then the tracepoint is enabled; if it is @samp{D}, then
the tracepoint is disabled. @var{step} is the tracepoint's step
! count, and @var{pass} is its pass count. If the trailing @samp{-} is
present, further @samp{QTDP} packets will follow to specify this
tracepoint's actions.
--- 28723,28736 ----
@table @samp
! @item QTDP:@var{n}:@var{addr}:@var{ena}:@var{step}:@var{pass}[:X@var{len},@var{bytes}]@r{[}-@r{]}
Create a new tracepoint, number @var{n}, at @var{addr}. If @var{ena}
is @samp{E}, then the tracepoint is enabled; if it is @samp{D}, then
the tracepoint is disabled. @var{step} is the tracepoint's step
! count, and @var{pass} is its pass count. If an @samp{X} is present,
! it introduces a tracepoint condition, which consists of a hexadecimal
! length, followed by a comma and hex-encoded bytes, in a manner similar
! to action encodings as described below. If the trailing @samp{-} is
present, further @samp{QTDP} packets will follow to specify this
tracepoint's actions.
Index: testsuite/gdb.trace/tracecmd.exp
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.trace/tracecmd.exp,v
retrieving revision 1.12
diff -p -r1.12 tracecmd.exp
*** testsuite/gdb.trace/tracecmd.exp 9 Jun 2009 17:12:43 -0000 1.12
--- testsuite/gdb.trace/tracecmd.exp 27 Jun 2009 05:17:20 -0000
*************** gdb_test "trace" "No default breakpoint
*** 153,159 ****
# deferred to limits test module
# 1.11 tracepoint conditions
! # conditions on tracepoints not implemented
# 1.12 set tracepoint in prologue
# [see tfind.exp]
--- 153,164 ----
# deferred to limits test module
# 1.11 tracepoint conditions
! gdb_delete_tracepoints
! gdb_test "trace gdb_recursion_test if q1 > 0" \
! "Tracepoint $decimal at $hex: file.*$srcfile, line $testline1." \
! "1.11a: conditional tracepoint"
! gdb_test "info trace" "in gdb_recursion_test.*$srcfile:$testline1.*trace only if q1 > 0" \
! "1.11b: verify conditional tracepoint"
# 1.12 set tracepoint in prologue
# [see tfind.exp]
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] Conditional tracepoints
2009-06-27 5:31 [PATCH] Conditional tracepoints Stan Shebs
@ 2009-06-27 12:55 ` Eli Zaretskii
2009-06-29 20:29 ` Stan Shebs
2009-06-29 16:38 ` Tom Tromey
2009-07-14 23:29 ` Stan Shebs
2 siblings, 1 reply; 8+ messages in thread
From: Eli Zaretskii @ 2009-06-27 12:55 UTC (permalink / raw)
To: Stan Shebs; +Cc: gdb-patches
> Date: Fri, 26 Jun 2009 22:31:07 -0700
> From: Stan Shebs <stan@codesourcery.com>
>
> This patch adds conditional tracepoints.
Thanks.
I think we need a NEWS entry for this.
> ==> doc/ChangeLog <==
> 2009-06-26 Stan Shebs <stan@codesourcery.com>
>
> * gdb.texinfo (Tracepoint Conditions): New section.
> (General Query Packets): Describe ConditionalTracepoints.
> (Tracepoint Packets): Describe condition field.
> (Maintenance Commands): Describe maint agent-eval.
This part is okay, with the following comments:
> + programming language (@pxref{Expressions, ,Expressions}). A
> + tracepoint with a condition evaluates the expression each time your
> + program reaches it, and data collection happens only if the condition
> + is @emph{true}.
Not sure why you use the @emph markup here. I think the text is okay
without any markup at all.
> + In contrast to breakpoint conditions, @value{GDBN} does not actually
> + evaluate @var{expression} at the time the @code{condition} command (or
> + a command that sets a tracepoint with a condition, like @code{trace if
> + @dots{}}) is given, however. @xref{Expressions, ,Expressions}.
Two comments:
. The @var{expression} does not reference anything in this section,
so the reader might become confused about what expression you had
in mind.
. You seem to imply that the condition is evaluated by conditional
breakpoints when the command is given. If so, that's not true,
AFAIK: the condition is evaluated each time a breakpoint is hit.
So the "in contrast to ..." part is not really right here.
> + Instead, @value{GDBN} encodes the expression into a form suitable for
> + execution on the target, independently of @value{GDBN}. Global
^^
Only one space.
> + @smallexample
> + (@value{GDBP}) @b{trace normal_operation if errcode > 0}
> + @end smallexample
Why the @b markup here? We don't use that elsewhere in examples.
> @table @code
> @kindex maint agent
> + @kindex maint agent-eval
> @item maint agent @var{expression}
> + @itemx maint agent-eval @var{expression}
> Translate the given @var{expression} into remote agent bytecodes.
> This command is useful for debugging the Agent Expression mechanism
> ! (@pxref{Agent Expressions}). The @samp{agent} version produces an
> ! expression useful for data collection, such as by tracepoints, while
> ! @samp{maint agent-eval} produces an expression that evaluates directly
> ! to a result.
I must admit that I don't understand the description you added. What
does "expression useful for data collection" mean, and how is it
different from "expression that evaluates directly to a result"?
> + @item ConditionalTracepoints
> + The remote stub accepts and tests conditional expressions defined for
> + tracepoints (@pxref{Tracepoint Conditions}).
Don't you mean "accepts and supports" or "accepts and implements"?
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] Conditional tracepoints
2009-06-27 5:31 [PATCH] Conditional tracepoints Stan Shebs
2009-06-27 12:55 ` Eli Zaretskii
@ 2009-06-29 16:38 ` Tom Tromey
2009-06-29 20:58 ` Stan Shebs
2009-07-14 23:29 ` Stan Shebs
2 siblings, 1 reply; 8+ messages in thread
From: Tom Tromey @ 2009-06-29 16:38 UTC (permalink / raw)
To: Stan Shebs; +Cc: gdb-patches
>>>>> "Stan" == Stan Shebs <stan@codesourcery.com> writes:
Stan> This patch adds conditional tracepoints. Tracepoint conditions work
Stan> by being compiled into agent expressions that actually evaluate on the
Stan> spot in the target, rather than collecting blocks of trace data.
Very cool.
Now I'm wondering if we could use agent expressions for conditional
breakpoints somehow :-)
Stan> As usual for tracepoints, GDB proper doesn't have to do much,
Stan> and most of the code here revolves around checking for the
Stan> "ConditionalTracepoints" feature, so as to maintain
Stan> compatibility with the two(?) existing tracepoint
Stan> implementations out there.
Are either of these free software?
Stan> +
Stan> + struct agent_expr *
Stan> + gen_eval_for_expr (CORE_ADDR scope, struct expression *expr)
Could use a header comment.
Stan> Index: tracepoint.c
[...]
Stan> + extern int remote_supports_cond_tracepoints (void);
This seems fishy to me.
At the very least I think this should be in a header, not in the .c
file. But... other cases like this seem to be expressed via target
methods, not as direct calls into remote.c.
(I thought maybe remote.o was not always compiled in; there are
comments to that effect, but they appear to be stale.)
Tom
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] Conditional tracepoints
2009-06-27 12:55 ` Eli Zaretskii
@ 2009-06-29 20:29 ` Stan Shebs
2009-06-30 3:06 ` Eli Zaretskii
0 siblings, 1 reply; 8+ messages in thread
From: Stan Shebs @ 2009-06-29 20:29 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: Stan Shebs, gdb-patches
Eli Zaretskii wrote:
>> Date: Fri, 26 Jun 2009 22:31:07 -0700
>> From: Stan Shebs <stan@codesourcery.com>
>>
>> This patch adds conditional tracepoints.
>>
>
> Thanks.
>
> I think we need a NEWS entry for this.
>
OK, good idea.
>> + programming language (@pxref{Expressions, ,Expressions}). A
>> + tracepoint with a condition evaluates the expression each time your
>> + program reaches it, and data collection happens only if the condition
>> + is @emph{true}.
>>
>
> Not sure why you use the @emph markup here. I think the text is okay
> without any markup at all.
>
It's been several months since I wrote it, and now I don't remember
either. :-)
>
>> @table @code
>> @kindex maint agent
>> + @kindex maint agent-eval
>> @item maint agent @var{expression}
>> + @itemx maint agent-eval @var{expression}
>> Translate the given @var{expression} into remote agent bytecodes.
>> This command is useful for debugging the Agent Expression mechanism
>> ! (@pxref{Agent Expressions}). The @samp{agent} version produces an
>> ! expression useful for data collection, such as by tracepoints, while
>> ! @samp{maint agent-eval} produces an expression that evaluates directly
>> ! to a result.
>>
>
> I must admit that I don't understand the description you added. What
> does "expression useful for data collection" mean, and how is it
> different from "expression that evaluates directly to a result"?
>
Expressions compiled for tracing have bytecodes that cause saving of the
blocks of memory etc that would be needed back on the host to evaluate
the expression at some later date. It occurs to me that the Agent
Expressions section should say a little more about the two kind of
expressions.
>> + @item ConditionalTracepoints
>> + The remote stub accepts and tests conditional expressions defined for
>> + tracepoints (@pxref{Tracepoint Conditions}).
>>
>
> Don't you mean "accepts and supports" or "accepts and implements"?
>
"support" and "implement" seemed overused. :-)
Stan
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] Conditional tracepoints
2009-06-29 16:38 ` Tom Tromey
@ 2009-06-29 20:58 ` Stan Shebs
2009-06-29 21:50 ` Tom Tromey
0 siblings, 1 reply; 8+ messages in thread
From: Stan Shebs @ 2009-06-29 20:58 UTC (permalink / raw)
To: tromey; +Cc: Stan Shebs, gdb-patches
Tom Tromey wrote:
>>>>>> "Stan" == Stan Shebs <stan@codesourcery.com> writes:
>>>>>>
>
> Stan> This patch adds conditional tracepoints. Tracepoint conditions work
> Stan> by being compiled into agent expressions that actually evaluate on the
> Stan> spot in the target, rather than collecting blocks of trace data.
>
> Very cool.
>
> Now I'm wondering if we could use agent expressions for conditional
> breakpoints somehow :-)
>
Certainly jimb didn't want to restrict agent expressions to just
tracepoints. The messy part would be getting from trap hit to evaluator,
since the usual native debugging arrangement gives control back to GDB
right away. I suppose there is still a performance win if GDB does the
effective equivalent of an inferior call to the evaluator after the trap
is hit, 2-3 roundtrips is still better than 10-100.
> Stan> As usual for tracepoints, GDB proper doesn't have to do much,
> Stan> and most of the code here revolves around checking for the
> Stan> "ConditionalTracepoints" feature, so as to maintain
> Stan> compatibility with the two(?) existing tracepoint
> Stan> implementations out there.
>
> Are either of these free software?
>
Yes, I was thinking of Nicholas McGuire's work, and Jim's Trac project.
Probably no one would notice in real life, but I couldn't quite bring
myself to make incompatible protocol changes without adding a feature
test...
> Stan> +
> Stan> + struct agent_expr *
> Stan> + gen_eval_for_expr (CORE_ADDR scope, struct expression *expr)
>
> Could use a header comment.
>
I agree. :-)
> Stan> Index: tracepoint.c
> [...]
> Stan> + extern int remote_supports_cond_tracepoints (void);
>
> This seems fishy to me.
>
> At the very least I think this should be in a header, not in the .c
> file. But... other cases like this seem to be expressed via target
> methods, not as direct calls into remote.c.
>
I beg a little indulgence for the moment - the massive target vector
change is coming in about ten patches or so. Since it touches everything
in tracepoint.c, patches from before that change wouldn't even start to
apply, so I'm recapitulating the order in which I wrote the pieces. In
the process, we'll be seeing lots of places where the tracepoint code
knows too much about the remote protocol code.
Stan
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] Conditional tracepoints
2009-06-29 20:58 ` Stan Shebs
@ 2009-06-29 21:50 ` Tom Tromey
0 siblings, 0 replies; 8+ messages in thread
From: Tom Tromey @ 2009-06-29 21:50 UTC (permalink / raw)
To: Stan Shebs; +Cc: gdb-patches
>>>>> "Stan" == Stan Shebs <stan@codesourcery.com> writes:
Stan> I beg a little indulgence for the moment - the massive target vector
Stan> change is coming in about ten patches or so. Since it touches
Stan> everything in tracepoint.c, patches from before that change wouldn't
Stan> even start to apply, so I'm recapitulating the order in which I wrote
Stan> the pieces. In the process, we'll be seeing lots of places where the
Stan> tracepoint code knows too much about the remote protocol code.
Thanks for the explanation.
Pedro also pointed out that tracepoint.c has other direct dependencies
on remote_*, which I did not notice.
Tom
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] Conditional tracepoints
2009-06-29 20:29 ` Stan Shebs
@ 2009-06-30 3:06 ` Eli Zaretskii
0 siblings, 0 replies; 8+ messages in thread
From: Eli Zaretskii @ 2009-06-30 3:06 UTC (permalink / raw)
To: Stan Shebs; +Cc: gdb-patches
> Date: Mon, 29 Jun 2009 13:29:38 -0700
> From: Stan Shebs <stan@codesourcery.com>
> CC: Stan Shebs <stan@codesourcery.com>, gdb-patches@sourceware.org
>
> >> ! (@pxref{Agent Expressions}). The @samp{agent} version produces an
> >> ! expression useful for data collection, such as by tracepoints, while
> >> ! @samp{maint agent-eval} produces an expression that evaluates directly
> >> ! to a result.
> >>
> >
> > I must admit that I don't understand the description you added. What
> > does "expression useful for data collection" mean, and how is it
> > different from "expression that evaluates directly to a result"?
> >
> Expressions compiled for tracing have bytecodes that cause saving of the
> blocks of memory etc that would be needed back on the host to evaluate
> the expression at some later date. It occurs to me that the Agent
> Expressions section should say a little more about the two kind of
> expressions.
Fine with me; in that case, this text should use the same terminology
as "Agent Expressions" and perhaps have a cross-reference to there.
> >> + @item ConditionalTracepoints
> >> + The remote stub accepts and tests conditional expressions defined for
> >> + tracepoints (@pxref{Tracepoint Conditions}).
> >>
> >
> > Don't you mean "accepts and supports" or "accepts and implements"?
> >
> "support" and "implement" seemed overused. :-)
They are still more descriptive than "tests" in this context, IMO.
Thanks.
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] Conditional tracepoints
2009-06-27 5:31 [PATCH] Conditional tracepoints Stan Shebs
2009-06-27 12:55 ` Eli Zaretskii
2009-06-29 16:38 ` Tom Tromey
@ 2009-07-14 23:29 ` Stan Shebs
2 siblings, 0 replies; 8+ messages in thread
From: Stan Shebs @ 2009-07-14 23:29 UTC (permalink / raw)
To: gdb-patches
[-- Attachment #1: Type: text/plain, Size: 1249 bytes --]
Here's what I committed for conditional tracepoints. On to the next piece!
Stan
2009-07-14 Stan Shebs <stan@codesourcery.com>
Conditional tracepoints.
* ax-gdb.h (gen_eval_for_expr): Declare.
* ax-gdb.c (gen_expr): Generate bytecodes for BINOP_EQUAL
and other comparisons.
(gen_eval_for_expr): New function.
(agent_eval_command): New maintenance command.
(_initialize_ax_gdb): Define the command.
* remote.c (struct remote_state): New field cond_tracepoints.
(PACKET_ConditionalTracepoints): New packet config type.
(remote_cond_tracepoint_feature): New function.
(remote_protocol_features): Add ConditionalTracepoints.
(remote_supports_cond_tracepoints): New function.
(_initialize_remote): Add ConditionalTracepoints.
* tracepoint.c (download_tracepoint): Add conditional.
* NEWS: Mention conditional tracepoints.
* gdb.texinfo (Tracepoint Conditions): New section.
(General Query Packets): Describe ConditionalTracepoints.
(Tracepoint Packets): Describe condition field.
(Maintenance Commands): Describe maint agent-eval.
* agentexpr.texi (Using Agent Expressions): Mention eval usage.
* gdb.trace/tracecmd.exp: Add basic test of tracepoint conditions.
[-- Attachment #2: cond-tp-patch-4 --]
[-- Type: text/plain, Size: 20963 bytes --]
Index: NEWS
===================================================================
RCS file: /cvs/src/src/gdb/NEWS,v
retrieving revision 1.317
diff -p -r1.317 NEWS
*** NEWS 11 Jul 2009 14:04:23 -0000 1.317
--- NEWS 14 Jul 2009 21:14:15 -0000
***************
*** 3,8 ****
--- 3,14 ----
*** Changes since GDB 6.8
+ * Tracepoints may now be conditional. The syntax is as for
+ breakpoints; either an "if" clause appended to the "trace" command,
+ or the "condition" command is available. GDB sends the condition to
+ the target for evaluation using the same bytecode format as is used
+ for tracepoint actions.
+
* "disassemble" command with a /r modifier, print the raw instructions
in hex as well as in symbolic form."
Index: ax-gdb.c
===================================================================
RCS file: /cvs/src/src/gdb/ax-gdb.c,v
retrieving revision 1.52
diff -p -r1.52 ax-gdb.c
*** ax-gdb.c 2 Jul 2009 12:20:17 -0000 1.52
--- ax-gdb.c 14 Jul 2009 21:14:15 -0000
*************** gen_expr (struct expression *exp, union
*** 1468,1473 ****
--- 1468,1479 ----
case BINOP_BITWISE_AND:
case BINOP_BITWISE_IOR:
case BINOP_BITWISE_XOR:
+ case BINOP_EQUAL:
+ case BINOP_NOTEQUAL:
+ case BINOP_LESS:
+ case BINOP_GTR:
+ case BINOP_LEQ:
+ case BINOP_GEQ:
(*pc)++;
gen_expr (exp, pc, ax, &value1);
gen_usual_unary (exp, ax, &value1);
*************** gen_expr (struct expression *exp, union
*** 1537,1542 ****
--- 1543,1589 ----
aop_bit_xor, aop_bit_xor, 0, "bitwise exclusive-or");
break;
+ case BINOP_EQUAL:
+ gen_binop (ax, value, &value1, &value2,
+ aop_equal, aop_equal, 0, "equal");
+ break;
+
+ case BINOP_NOTEQUAL:
+ gen_binop (ax, value, &value1, &value2,
+ aop_equal, aop_equal, 0, "equal");
+ gen_logical_not (ax, value,
+ language_bool_type (exp->language_defn,
+ exp->gdbarch));
+ break;
+
+ case BINOP_LESS:
+ gen_binop (ax, value, &value1, &value2,
+ aop_less_signed, aop_less_unsigned, 0, "less than");
+ break;
+
+ case BINOP_GTR:
+ ax_simple (ax, aop_swap);
+ gen_binop (ax, value, &value1, &value2,
+ aop_less_signed, aop_less_unsigned, 0, "less than");
+ break;
+
+ case BINOP_LEQ:
+ ax_simple (ax, aop_swap);
+ gen_binop (ax, value, &value1, &value2,
+ aop_less_signed, aop_less_unsigned, 0, "less than");
+ gen_logical_not (ax, value,
+ language_bool_type (exp->language_defn,
+ exp->gdbarch));
+ break;
+
+ case BINOP_GEQ:
+ gen_binop (ax, value, &value1, &value2,
+ aop_less_signed, aop_less_unsigned, 0, "less than");
+ gen_logical_not (ax, value,
+ language_bool_type (exp->language_defn,
+ exp->gdbarch));
+ break;
+
default:
/* We should only list operators in the outer case statement
that we actually handle in the inner case statement. */
*************** gen_trace_for_expr (CORE_ADDR scope, str
*** 1756,1761 ****
--- 1803,1839 ----
return ax;
}
+ /* Given a GDB expression EXPR, return a bytecode sequence that will
+ evaluate and return a result. The bytecodes will do a direct
+ evaluation, using the current data on the target, rather than
+ recording blocks of memory and registers for later use, as
+ gen_trace_for_expr does. The generated bytecode sequence leaves
+ the result of expression evaluation on the top of the stack. */
+
+ struct agent_expr *
+ gen_eval_for_expr (CORE_ADDR scope, struct expression *expr)
+ {
+ struct cleanup *old_chain = 0;
+ struct agent_expr *ax = new_agent_expr (scope);
+ union exp_element *pc;
+ struct axs_value value;
+
+ old_chain = make_cleanup_free_agent_expr (ax);
+
+ pc = expr->elts;
+ trace_kludge = 0;
+ gen_expr (expr, &pc, ax, &value);
+
+ /* Oh, and terminate. */
+ ax_simple (ax, aop_end);
+
+ /* We have successfully built the agent expr, so cancel the cleanup
+ request. If we add more cleanups that we always want done, this
+ will have to get more complicated. */
+ discard_cleanups (old_chain);
+ return ax;
+ }
+
static void
agent_command (char *exp, int from_tty)
{
*************** agent_command (char *exp, int from_tty)
*** 1786,1791 ****
--- 1864,1904 ----
do_cleanups (old_chain);
dont_repeat ();
}
+
+ /* Parse the given expression, compile it into an agent expression
+ that does direct evaluation, and display the resulting
+ expression. */
+
+ static void
+ agent_eval_command (char *exp, int from_tty)
+ {
+ struct cleanup *old_chain = 0;
+ struct expression *expr;
+ struct agent_expr *agent;
+ struct frame_info *fi = get_current_frame (); /* need current scope */
+
+ /* We don't deal with overlay debugging at the moment. We need to
+ think more carefully about this. If you copy this code into
+ another command, change the error message; the user shouldn't
+ have to know anything about agent expressions. */
+ if (overlay_debugging)
+ error (_("GDB can't do agent expression translation with overlays."));
+
+ if (exp == 0)
+ error_no_arg (_("expression to translate"));
+
+ expr = parse_expression (exp);
+ old_chain = make_cleanup (free_current_contents, &expr);
+ agent = gen_eval_for_expr (get_frame_pc (fi), expr);
+ make_cleanup_free_agent_expr (agent);
+ ax_print (gdb_stdout, agent);
+
+ /* It would be nice to call ax_reqs here to gather some general info
+ about the expression, and then print out the result. */
+
+ do_cleanups (old_chain);
+ dont_repeat ();
+ }
\f
/* Initialization code. */
*************** void
*** 1795,1800 ****
_initialize_ax_gdb (void)
{
add_cmd ("agent", class_maintenance, agent_command,
! _("Translate an expression into remote agent bytecode."),
&maintenancelist);
}
--- 1908,1917 ----
_initialize_ax_gdb (void)
{
add_cmd ("agent", class_maintenance, agent_command,
! _("Translate an expression into remote agent bytecode for tracing."),
! &maintenancelist);
!
! add_cmd ("agent-eval", class_maintenance, agent_eval_command,
! _("Translate an expression into remote agent bytecode for evaluation."),
&maintenancelist);
}
Index: ax-gdb.h
===================================================================
RCS file: /cvs/src/src/gdb/ax-gdb.h,v
retrieving revision 1.11
diff -p -r1.11 ax-gdb.h
*** ax-gdb.h 3 Jan 2009 05:57:50 -0000 1.11
--- ax-gdb.h 14 Jul 2009 21:14:15 -0000
*************** struct axs_value
*** 99,102 ****
--- 99,104 ----
function to discover which registers the expression uses. */
extern struct agent_expr *gen_trace_for_expr (CORE_ADDR, struct expression *);
+ extern struct agent_expr *gen_eval_for_expr (CORE_ADDR, struct expression *);
+
#endif /* AX_GDB_H */
Index: remote.c
===================================================================
RCS file: /cvs/src/src/gdb/remote.c,v
retrieving revision 1.363
diff -p -r1.363 remote.c
*** remote.c 14 Jul 2009 14:53:41 -0000 1.363
--- remote.c 14 Jul 2009 21:14:16 -0000
*************** struct remote_state
*** 294,299 ****
--- 294,302 ----
/* True if the stub reports support for vCont;t. */
int support_vCont_t;
+
+ /* True if the stub reports support for conditional tracepoints. */
+ int cond_tracepoints;
};
/* Returns true if the multi-process extensions are in effect. */
*************** enum {
*** 993,998 ****
--- 996,1002 ----
PACKET_qXfer_siginfo_read,
PACKET_qXfer_siginfo_write,
PACKET_qAttached,
+ PACKET_ConditionalTracepoints,
PACKET_MAX
};
*************** remote_non_stop_feature (const struct pr
*** 3015,3020 ****
--- 3019,3033 ----
rs->non_stop_aware = (support == PACKET_ENABLE);
}
+ static void
+ remote_cond_tracepoint_feature (const struct protocol_feature *feature,
+ enum packet_support support,
+ const char *value)
+ {
+ struct remote_state *rs = get_remote_state ();
+ rs->cond_tracepoints = (support == PACKET_ENABLE);
+ }
+
static struct protocol_feature remote_protocol_features[] = {
{ "PacketSize", PACKET_DISABLE, remote_packet_size, -1 },
{ "qXfer:auxv:read", PACKET_DISABLE, remote_supported_packet,
*************** static struct protocol_feature remote_pr
*** 3041,3046 ****
--- 3054,3061 ----
PACKET_qXfer_siginfo_read },
{ "qXfer:siginfo:write", PACKET_DISABLE, remote_supported_packet,
PACKET_qXfer_siginfo_write },
+ { "ConditionalTracepoints", PACKET_DISABLE, remote_cond_tracepoint_feature,
+ PACKET_ConditionalTracepoints },
};
static void
*************** remote_supports_multi_process (void)
*** 8740,8745 ****
--- 8755,8767 ----
return remote_multi_process_p (rs);
}
+ int
+ remote_supports_cond_tracepoints (void)
+ {
+ struct remote_state *rs = get_remote_state ();
+ return rs->cond_tracepoints;
+ }
+
static void
init_remote_ops (void)
{
*************** Show the maximum size of the address (in
*** 9183,9188 ****
--- 9205,9213 ----
add_packet_config_cmd (&remote_protocol_packets[PACKET_qAttached],
"qAttached", "query-attached", 0);
+ add_packet_config_cmd (&remote_protocol_packets[PACKET_ConditionalTracepoints],
+ "ConditionalTracepoints", "conditional-tracepoints", 0);
+
/* Keep the old ``set remote Z-packet ...'' working. Each individual
Z sub-packet has its own set and show commands, but users may
have sets to this variable in their .gdbinit files (or in their
Index: tracepoint.c
===================================================================
RCS file: /cvs/src/src/gdb/tracepoint.c,v
retrieving revision 1.125
diff -p -r1.125 tracepoint.c
*** tracepoint.c 2 Jul 2009 17:21:07 -0000 1.125
--- tracepoint.c 14 Jul 2009 21:14:16 -0000
***************
*** 33,38 ****
--- 33,39 ----
#include "breakpoint.h"
#include "tracepoint.h"
#include "remote.h"
+ extern int remote_supports_cond_tracepoints (void);
#include "linespec.h"
#include "regcache.h"
#include "completer.h"
*************** download_tracepoint (struct breakpoint *
*** 1311,1322 ****
--- 1312,1342 ----
char **stepping_actions;
int ndx;
struct cleanup *old_chain = NULL;
+ struct agent_expr *aexpr;
+ struct cleanup *aexpr_chain = NULL;
sprintf_vma (tmp, (t->loc ? t->loc->address : 0));
sprintf (buf, "QTDP:%x:%s:%c:%lx:%x", t->number,
tmp, /* address */
(t->enable_state == bp_enabled ? 'E' : 'D'),
t->step_count, t->pass_count);
+ /* If the tracepoint has a conditional, make it into an agent
+ expression and append to the definition. */
+ if (t->loc->cond)
+ {
+ /* Only test support at download time, we may not know target
+ capabilities at definition time. */
+ if (remote_supports_cond_tracepoints ())
+ {
+ aexpr = gen_eval_for_expr (t->loc->address, t->loc->cond);
+ aexpr_chain = make_cleanup_free_agent_expr (aexpr);
+ sprintf (buf + strlen (buf), ":X%x,", aexpr->len);
+ mem2hex (aexpr->buf, buf + strlen (buf), aexpr->len);
+ do_cleanups (aexpr_chain);
+ }
+ else
+ warning (_("Target does not support conditional tracepoints, ignoring tp %d cond"), t->number);
+ }
if (t->actions)
strcat (buf, "-");
Index: doc/agentexpr.texi
===================================================================
RCS file: /cvs/src/src/gdb/doc/agentexpr.texi,v
retrieving revision 1.7
diff -p -r1.7 agentexpr.texi
*** doc/agentexpr.texi 20 Jan 2007 16:51:56 -0000 1.7
--- doc/agentexpr.texi 14 Jul 2009 21:14:17 -0000
***************
*** 7,19 ****
@c This file is part of the GDB manual.
@c
! @c Copyright (C) 2003, 2004, 2005, 2006
@c Free Software Foundation, Inc.
@c
@c See the file gdb.texinfo for copying conditions.
- @c Revision: $Id: agentexpr.texi,v 1.2 1998/12/09 21:23:46 jimb Exp $
-
@node Agent Expressions
@appendix The GDB Agent Expression Mechanism
--- 7,17 ----
@c This file is part of the GDB manual.
@c
! @c Copyright (C) 2003, 2004, 2005, 2006, 2009
@c Free Software Foundation, Inc.
@c
@c See the file gdb.texinfo for copying conditions.
@node Agent Expressions
@appendix The GDB Agent Expression Mechanism
*************** address, and the top of the stack is the
*** 473,480 ****
@node Using Agent Expressions
@section Using Agent Expressions
! Here is a sketch of a full non-stop debugging cycle, showing how agent
! expressions fit into the process.
@itemize @bullet
--- 471,490 ----
@node Using Agent Expressions
@section Using Agent Expressions
! Agent expressions can be used in several different ways by @value{GDBN},
! and the debugger can generate different bytecode sequences as appropriate.
!
! One possibility is to do expression evaluation on the target rather
! than the host, such as for the conditional of a conditional
! tracepoint. In such a case, @value{GDBN} compiles the source
! expression into a bytecode sequence that simply gets values from
! registers or memory, does arithmetic, and returns a result.
!
! Another way to use agent expressions is for tracepoint data
! collection. @value{GDBN} generates a different bytecode sequence for
! collection; in addition to bytecodes that do the calculation,
! @value{GDBN} adds @code{trace} bytecodes to save the pieces of
! memory that were used.
@itemize @bullet
Index: doc/gdb.texinfo
===================================================================
RCS file: /cvs/src/src/gdb/doc/gdb.texinfo,v
retrieving revision 1.606
diff -p -r1.606 gdb.texinfo
*** doc/gdb.texinfo 11 Jul 2009 14:09:16 -0000 1.606
--- doc/gdb.texinfo 14 Jul 2009 21:14:21 -0000
*************** conditions and actions.
*** 8932,8937 ****
--- 8932,8938 ----
* Create and Delete Tracepoints::
* Enable and Disable Tracepoints::
* Tracepoint Passcounts::
+ * Tracepoint Conditions::
* Tracepoint Actions::
* Listing Tracepoints::
* Starting and Stopping Trace Experiments::
*************** Here are some examples of using the @cod
*** 8971,8976 ****
--- 8972,8984 ----
@noindent
You can abbreviate @code{trace} as @code{tr}.
+ @item trace @var{location} if @var{cond}
+ Set a tracepoint with condition @var{cond}; evaluate the expression
+ @var{cond} each time the tracepoint is reached, and collect data only
+ if the value is nonzero---that is, if @var{cond} evaluates as true.
+ @xref{Tracepoint Conditions, ,Tracepoint Conditions}, for more
+ information on tracepoint conditions.
+
@vindex $tpnum
@cindex last tracepoint number
@cindex recent tracepoint number
*************** Examples:
*** 9053,9058 ****
--- 9061,9104 ----
@end smallexample
@end table
+ @node Tracepoint Conditions
+ @subsection Tracepoint Conditions
+ @cindex conditional tracepoints
+ @cindex tracepoint conditions
+
+ The simplest sort of tracepoint collects data every time your program
+ reaches a specified place. You can also specify a @dfn{condition} for
+ a tracepoint. A condition is just a Boolean expression in your
+ programming language (@pxref{Expressions, ,Expressions}). A
+ tracepoint with a condition evaluates the expression each time your
+ program reaches it, and data collection happens only if the condition
+ is true.
+
+ Tracepoint conditions can be specified when a tracepoint is set, by
+ using @samp{if} in the arguments to the @code{trace} command.
+ @xref{Create and Delete Tracepoints, ,Setting Tracepoints}. They can
+ also be set or changed at any time with the @code{condition} command,
+ just as with breakpoints.
+
+ Unlike breakpoint conditions, @value{GDBN} does not actually evaluate
+ the conditional expression itself. Instead, @value{GDBN} encodes the
+ expression into an agent expression (@pxref{Agent Expressions}
+ suitable for execution on the target, independently of @value{GDBN}.
+ Global variables become raw memory locations, locals become stack
+ accesses, and so forth.
+
+ For instance, suppose you have a function that is usually called
+ frequently, but should not be called after an error has occurred. You
+ could use the following tracepoint command to collect data about calls
+ of that function that happen while the error code is propagating
+ through the program; an unconditional tracepoint could end up
+ collecting thousands of useless trace frames that you would have to
+ search through.
+
+ @smallexample
+ (@value{GDBP}) @kbd{trace normal_operation if errcode > 0}
+ @end smallexample
+
@node Tracepoint Actions
@subsection Tracepoint Action Lists
*************** messages, see @ref{Debugging Output}.)
*** 26534,26543 ****
@table @code
@kindex maint agent
@item maint agent @var{expression}
Translate the given @var{expression} into remote agent bytecodes.
This command is useful for debugging the Agent Expression mechanism
! (@pxref{Agent Expressions}).
@kindex maint info breakpoints
@item @anchor{maint info breakpoints}maint info breakpoints
--- 26580,26598 ----
@table @code
@kindex maint agent
+ @kindex maint agent-eval
@item maint agent @var{expression}
+ @itemx maint agent-eval @var{expression}
Translate the given @var{expression} into remote agent bytecodes.
This command is useful for debugging the Agent Expression mechanism
! (@pxref{Agent Expressions}). The @samp{agent} version produces an
! expression useful for data collection, such as by tracepoints, while
! @samp{maint agent-eval} produces an expression that evaluates directly
! to a result. For instance, a collection expression for @code{globa +
! globb} will include bytecodes to record four bytes of memory at each
! of the addresses of @code{globa} and @code{globb}, while discarding
! the result of the addition, while an evaluation expression will do the
! addition and return the sum.
@kindex maint info breakpoints
@item @anchor{maint info breakpoints}maint info breakpoints
*************** These are the currently defined stub fea
*** 28415,28420 ****
--- 28470,28480 ----
@tab @samp{-}
@tab No
+ @item @samp{ConditionalTracepoints}
+ @tab No
+ @tab @samp{-}
+ @tab No
+
@end multitable
These are the currently defined stub features, in more detail:
*************** indicated it supports them in its @samp{
*** 28492,28497 ****
--- 28552,28561 ----
The remote stub understands the @samp{qXfer:osdata:read} packet
((@pxref{qXfer osdata read}).
+ @item ConditionalTracepoints
+ The remote stub accepts and implements conditional expressions defined
+ for tracepoints (@pxref{Tracepoint Conditions}).
+
@end table
@item qSymbol::
*************** tracepoints (@pxref{Tracepoints}).
*** 28804,28814 ****
@table @samp
! @item QTDP:@var{n}:@var{addr}:@var{ena}:@var{step}:@var{pass}@r{[}-@r{]}
Create a new tracepoint, number @var{n}, at @var{addr}. If @var{ena}
is @samp{E}, then the tracepoint is enabled; if it is @samp{D}, then
the tracepoint is disabled. @var{step} is the tracepoint's step
! count, and @var{pass} is its pass count. If the trailing @samp{-} is
present, further @samp{QTDP} packets will follow to specify this
tracepoint's actions.
--- 28868,28881 ----
@table @samp
! @item QTDP:@var{n}:@var{addr}:@var{ena}:@var{step}:@var{pass}[:X@var{len},@var{bytes}]@r{[}-@r{]}
Create a new tracepoint, number @var{n}, at @var{addr}. If @var{ena}
is @samp{E}, then the tracepoint is enabled; if it is @samp{D}, then
the tracepoint is disabled. @var{step} is the tracepoint's step
! count, and @var{pass} is its pass count. If an @samp{X} is present,
! it introduces a tracepoint condition, which consists of a hexadecimal
! length, followed by a comma and hex-encoded bytes, in a manner similar
! to action encodings as described below. If the trailing @samp{-} is
present, further @samp{QTDP} packets will follow to specify this
tracepoint's actions.
Index: testsuite/gdb.trace/tracecmd.exp
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.trace/tracecmd.exp,v
retrieving revision 1.12
diff -p -r1.12 tracecmd.exp
*** testsuite/gdb.trace/tracecmd.exp 9 Jun 2009 17:12:43 -0000 1.12
--- testsuite/gdb.trace/tracecmd.exp 14 Jul 2009 21:14:23 -0000
*************** gdb_test "trace" "No default breakpoint
*** 153,159 ****
# deferred to limits test module
# 1.11 tracepoint conditions
! # conditions on tracepoints not implemented
# 1.12 set tracepoint in prologue
# [see tfind.exp]
--- 153,164 ----
# deferred to limits test module
# 1.11 tracepoint conditions
! gdb_delete_tracepoints
! gdb_test "trace gdb_recursion_test if q1 > 0" \
! "Tracepoint $decimal at $hex: file.*$srcfile, line $testline1." \
! "1.11a: conditional tracepoint"
! gdb_test "info trace" "in gdb_recursion_test.*$srcfile:$testline1.*trace only if q1 > 0" \
! "1.11b: verify conditional tracepoint"
# 1.12 set tracepoint in prologue
# [see tfind.exp]
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2009-07-14 22:19 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-06-27 5:31 [PATCH] Conditional tracepoints Stan Shebs
2009-06-27 12:55 ` Eli Zaretskii
2009-06-29 20:29 ` Stan Shebs
2009-06-30 3:06 ` Eli Zaretskii
2009-06-29 16:38 ` Tom Tromey
2009-06-29 20:58 ` Stan Shebs
2009-06-29 21:50 ` Tom Tromey
2009-07-14 23:29 ` Stan Shebs
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox