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/doc/
	* 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/testsuite/
	* gdb.trace/tracecmd.exp: Add basic test of tracepoint conditions.
This commit is contained in:
Stan Shebs 2009-07-14 21:40:34 +00:00
parent f662c3bce4
commit 782b2b0784
11 changed files with 292 additions and 10 deletions

View File

@ -1,3 +1,21 @@
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.
2009-07-14 Ulrich Weigand <uweigand@de.ibm.com>
* objfiles.c (objfile_relocate): Do not relocate the same

View File

@ -3,6 +3,12 @@
*** 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."

View File

@ -1468,6 +1468,12 @@ gen_expr (struct expression *exp, union exp_element **pc,
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);
@ -1537,6 +1543,47 @@ gen_expr (struct expression *exp, union exp_element **pc,
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. */
@ -1756,6 +1803,37 @@ gen_trace_for_expr (CORE_ADDR scope, struct expression *expr)
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)
{
@ -1786,6 +1864,41 @@ agent_command (char *exp, int from_tty)
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 ();
}
/* Initialization code. */
@ -1795,6 +1908,10 @@ void
_initialize_ax_gdb (void)
{
add_cmd ("agent", class_maintenance, agent_command,
_("Translate an expression into remote agent bytecode."),
_("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);
}

View File

@ -99,4 +99,6 @@ struct axs_value
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 */

View File

@ -1,3 +1,11 @@
2009-07-14 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.
* agentexpr.texi (Using Agent Expressions): Mention eval usage.
2009-07-11 Hui Zhu <teawater@gmail.com>
* gdb.texinfo (disassemble): Add a new modifier /r

View File

@ -7,13 +7,11 @@
@c This file is part of the GDB manual.
@c
@c Copyright (C) 2003, 2004, 2005, 2006
@c Copyright (C) 2003, 2004, 2005, 2006, 2009
@c Free Software Foundation, Inc.
@c
@c See the file gdb.texinfo for copying conditions.
@c Revision: $Id$
@node Agent Expressions
@appendix The GDB Agent Expression Mechanism
@ -473,8 +471,20 @@ address, and the top of the stack is the lvalue's size, in bytes.
@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.
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

View File

@ -8932,6 +8932,7 @@ conditions and actions.
* Create and Delete Tracepoints::
* Enable and Disable Tracepoints::
* Tracepoint Passcounts::
* Tracepoint Conditions::
* Tracepoint Actions::
* Listing Tracepoints::
* Starting and Stopping Trace Experiments::
@ -8971,6 +8972,13 @@ Here are some examples of using the @code{trace} command:
@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
@ -9053,6 +9061,44 @@ Examples:
@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
@ -26534,10 +26580,19 @@ messages, see @ref{Debugging Output}.)
@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}).
(@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
@ -28415,6 +28470,11 @@ These are the currently defined stub features and their properties:
@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:
@ -28492,6 +28552,10 @@ indicated it supports them in its @samp{qSupported} request.
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::
@ -28804,11 +28868,14 @@ tracepoints (@pxref{Tracepoints}).
@table @samp
@item QTDP:@var{n}:@var{addr}:@var{ena}:@var{step}:@var{pass}@r{[}-@r{]}
@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 the trailing @samp{-} is
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.

View File

@ -294,6 +294,9 @@ struct remote_state
/* 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. */
@ -993,6 +996,7 @@ enum {
PACKET_qXfer_siginfo_read,
PACKET_qXfer_siginfo_write,
PACKET_qAttached,
PACKET_ConditionalTracepoints,
PACKET_MAX
};
@ -3015,6 +3019,15 @@ remote_non_stop_feature (const struct protocol_feature *feature,
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,
@ -3041,6 +3054,8 @@ static struct protocol_feature remote_protocol_features[] = {
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
@ -8740,6 +8755,13 @@ remote_supports_multi_process (void)
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)
{
@ -9183,6 +9205,9 @@ Show the maximum size of the address (in bits) in a memory packet."), NULL,
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

View File

@ -1,3 +1,7 @@
2009-07-14 Stan Shebs <stan@codesourcery.com>
* gdb.trace/tracecmd.exp: Add basic test of tracepoint conditions.
2009-07-14 Michael Snyder <msnyder@vmware.com>
* gdb.reverse/step-reverse.exp (stepi into function call):

View File

@ -153,7 +153,12 @@ gdb_test "trace" "No default breakpoint address now." \
# deferred to limits test module
# 1.11 tracepoint conditions
# conditions on tracepoints not implemented
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]

View File

@ -33,6 +33,7 @@
#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"
@ -1311,12 +1312,31 @@ download_tracepoint (struct breakpoint *t)
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, "-");