Add fast tracepoints.
* arch-utils.h (default_fast_tracepoint_valid_at): Declare. * arch-utils.c (default_fast_tracepoint_valid_at): New function. * breakpoint.h (enum bptype): Add bp_fast_tracepoint. * breakpoint.c (tracepoint_type): New function. (ALL_TRACEPOINTS): Use it. (should_be_inserted): Ditto. (bpstat_check_location): Ditto. (print_one_breakpoint_location): Ditto. (user_settable_breakpoint): Ditto. (set_breakpoint_location_function): Ditto. (disable_breakpoints_in_shlibs): Ditto. (delete_trace_command): Ditto. (print_it_typical): Add bp_fast_tracepoint case. (bpstat_what): Ditto. (print_one_breakpoint_location): Ditto. (allocate_bp_location): Ditto. (mention): Ditto. (breakpoint_re_set_one): Ditto. (disable_command): Ditto. (enable_command): Ditto. (check_fast_tracepoint_sals): New function. (break_command_really): Call it. (ftrace_command): New function. (_initialize_breakpoint): Add ftrace command. * gdbarch.sh (fast_tracepoint_valid_at): New. * gdbarch.h, gdbarch.c: Regenerate. * i386-tdep.c (i386_fast_tracepoint_valid_at): New function. (i386_gdbarch_init): Use it. * remote.c (struct remote_state): New field fast_tracepoints. (PACKET_FastTracepoints): New packet config type. (remote_fast_tracepoint_feature): New function. (remote_protocol_features): Add FastTracepoints. (remote_supports_fast_tracepoints): New function. (_initialize_remote): Add FastTracepoints. * tracepoint.c (download_tracepoint): Add fast tracepoint option. * NEWS: Mention fast tracepoints. * gdb.texinfo (Create and Delete Tracepoints): Describe fast tracepoints. (Tracepoint Packets): Describe remote protocol for fast tracepoints. * gdb.trace/tracecmd.exp: Test ftrace.
This commit is contained in:
parent
737a160ed9
commit
7a697b8dd7
@ -1,3 +1,43 @@
|
||||
2010-01-05 Stan Shebs <stan@codesourcery.com>
|
||||
|
||||
Add fast tracepoints.
|
||||
* arch-utils.h (default_fast_tracepoint_valid_at): Declare.
|
||||
* arch-utils.c (default_fast_tracepoint_valid_at): New function.
|
||||
* breakpoint.h (enum bptype): Add bp_fast_tracepoint.
|
||||
* breakpoint.c (tracepoint_type): New function.
|
||||
(ALL_TRACEPOINTS): Use it.
|
||||
(should_be_inserted): Ditto.
|
||||
(bpstat_check_location): Ditto.
|
||||
(print_one_breakpoint_location): Ditto.
|
||||
(user_settable_breakpoint): Ditto.
|
||||
(set_breakpoint_location_function): Ditto.
|
||||
(disable_breakpoints_in_shlibs): Ditto.
|
||||
(delete_trace_command): Ditto.
|
||||
(print_it_typical): Add bp_fast_tracepoint case.
|
||||
(bpstat_what): Ditto.
|
||||
(print_one_breakpoint_location): Ditto.
|
||||
(allocate_bp_location): Ditto.
|
||||
(mention): Ditto.
|
||||
(breakpoint_re_set_one): Ditto.
|
||||
(disable_command): Ditto.
|
||||
(enable_command): Ditto.
|
||||
(check_fast_tracepoint_sals): New function.
|
||||
(break_command_really): Call it.
|
||||
(ftrace_command): New function.
|
||||
(_initialize_breakpoint): Add ftrace command.
|
||||
* gdbarch.sh (fast_tracepoint_valid_at): New.
|
||||
* gdbarch.h, gdbarch.c: Regenerate.
|
||||
* i386-tdep.c (i386_fast_tracepoint_valid_at): New function.
|
||||
(i386_gdbarch_init): Use it.
|
||||
* remote.c (struct remote_state): New field fast_tracepoints.
|
||||
(PACKET_FastTracepoints): New packet config type.
|
||||
(remote_fast_tracepoint_feature): New function.
|
||||
(remote_protocol_features): Add FastTracepoints.
|
||||
(remote_supports_fast_tracepoints): New function.
|
||||
(_initialize_remote): Add FastTracepoints.
|
||||
* tracepoint.c (download_tracepoint): Add fast tracepoint option.
|
||||
* NEWS: Mention fast tracepoints.
|
||||
|
||||
2010-01-06 Joel Brobecker <brobecker@adacore.com>
|
||||
|
||||
* gdb-gdb.py: New file.
|
||||
|
17
gdb/NEWS
17
gdb/NEWS
@ -36,7 +36,19 @@ Renesas RX rx
|
||||
tracepoint actions and condition expressions. Use the "tvariable"
|
||||
command to create, and "info tvariables" to view; see "Trace State
|
||||
Variables" in the manual for more detail.
|
||||
|
||||
|
||||
* Fast tracepoints
|
||||
|
||||
GDB now includes an option for defining fast tracepoints, which
|
||||
targets may implement more efficiently, such as by installing a jump
|
||||
into the target agent rather than a trap instruction. The resulting
|
||||
speedup can be by two orders of magnitude or more, although the
|
||||
tradeoff is that some program locations on some target architectures
|
||||
might not allow fast tracepoint installation, for instance if the
|
||||
instruction to be replaced is shorter than the jump. To request a
|
||||
fast tracepoint, use the "ftrace" command, with syntax identical to
|
||||
the regular trace command.
|
||||
|
||||
* Changed commands
|
||||
|
||||
disassemble
|
||||
@ -101,6 +113,9 @@ teval EXPR, ...
|
||||
Evaluate the given expressions without collecting anything into the
|
||||
trace buffer. (Valid in tracepoint actions only.)
|
||||
|
||||
ftrace FN / FILE:LINE / *ADDR
|
||||
Define a fast tracepoint at the given function, line, or address.
|
||||
|
||||
* New options
|
||||
|
||||
set follow-exec-mode new|same
|
||||
|
@ -765,6 +765,17 @@ default_has_shared_address_space (struct gdbarch *gdbarch)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
default_fast_tracepoint_valid_at (struct gdbarch *gdbarch,
|
||||
CORE_ADDR addr, int *isize, char **msg)
|
||||
{
|
||||
/* We don't know if maybe the target has some way to do fast
|
||||
tracepoints that doesn't need gdbarch, so always say yes. */
|
||||
if (msg)
|
||||
*msg = NULL;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* */
|
||||
|
||||
extern initialize_file_ftype _initialize_gdbarch_utils; /* -Wmissing-prototypes */
|
||||
|
@ -155,4 +155,8 @@ extern struct gdbarch *get_current_arch (void);
|
||||
|
||||
extern int default_has_shared_address_space (struct gdbarch *);
|
||||
|
||||
extern int default_fast_tracepoint_valid_at (struct gdbarch *gdbarch,
|
||||
CORE_ADDR addr,
|
||||
int *isize, char **msg);
|
||||
|
||||
#endif
|
||||
|
105
gdb/breakpoint.c
105
gdb/breakpoint.c
@ -353,7 +353,7 @@ static int overlay_events_enabled;
|
||||
|
||||
#define ALL_TRACEPOINTS(B) \
|
||||
for (B = breakpoint_chain; B; B = B->next) \
|
||||
if ((B)->type == bp_tracepoint)
|
||||
if (tracepoint_type (B))
|
||||
|
||||
/* Chains of all breakpoints defined. */
|
||||
|
||||
@ -422,6 +422,14 @@ clear_breakpoint_hit_counts (void)
|
||||
b->hit_count = 0;
|
||||
}
|
||||
|
||||
/* Encapsulate tests for different types of tracepoints. */
|
||||
|
||||
static int
|
||||
tracepoint_type (const struct breakpoint *b)
|
||||
{
|
||||
return (b->type == bp_tracepoint || b->type == bp_fast_tracepoint);
|
||||
}
|
||||
|
||||
/* Default address, symtab and line to put a breakpoint at
|
||||
for "break" command with no arg.
|
||||
if default_breakpoint_valid is zero, the other three are
|
||||
@ -1282,7 +1290,7 @@ should_be_inserted (struct bp_location *bpt)
|
||||
|
||||
/* Tracepoints are inserted by the target at a time of its choosing,
|
||||
not by us. */
|
||||
if (bpt->owner->type == bp_tracepoint)
|
||||
if (tracepoint_type (bpt->owner))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
@ -2977,6 +2985,7 @@ print_it_typical (bpstat bs)
|
||||
case bp_watchpoint_scope:
|
||||
case bp_call_dummy:
|
||||
case bp_tracepoint:
|
||||
case bp_fast_tracepoint:
|
||||
case bp_jit_event:
|
||||
default:
|
||||
result = PRINT_UNKNOWN;
|
||||
@ -3322,7 +3331,7 @@ bpstat_check_location (const struct bp_location *bl,
|
||||
|
||||
/* By definition, the inferior does not report stops at
|
||||
tracepoints. */
|
||||
if (b->type == bp_tracepoint)
|
||||
if (tracepoint_type (b))
|
||||
return 0;
|
||||
|
||||
if (b->type != bp_watchpoint
|
||||
@ -3914,11 +3923,12 @@ bpstat_what (bpstat bs)
|
||||
retval.call_dummy = 1;
|
||||
break;
|
||||
case bp_tracepoint:
|
||||
case bp_fast_tracepoint:
|
||||
/* Tracepoint hits should not be reported back to GDB, and
|
||||
if one got through somehow, it should have been filtered
|
||||
out already. */
|
||||
internal_error (__FILE__, __LINE__,
|
||||
_("bpstat_what: bp_tracepoint encountered"));
|
||||
_("bpstat_what: tracepoint encountered"));
|
||||
break;
|
||||
}
|
||||
current_action = table[(int) bs_class][(int) current_action];
|
||||
@ -4044,6 +4054,7 @@ print_one_breakpoint_location (struct breakpoint *b,
|
||||
{bp_longjmp_master, "longjmp master"},
|
||||
{bp_catchpoint, "catchpoint"},
|
||||
{bp_tracepoint, "tracepoint"},
|
||||
{bp_fast_tracepoint, "fast tracepoint"},
|
||||
{bp_jit_event, "jit events"},
|
||||
};
|
||||
|
||||
@ -4173,6 +4184,7 @@ print_one_breakpoint_location (struct breakpoint *b,
|
||||
case bp_overlay_event:
|
||||
case bp_longjmp_master:
|
||||
case bp_tracepoint:
|
||||
case bp_fast_tracepoint:
|
||||
case bp_jit_event:
|
||||
if (opts.addressprint)
|
||||
{
|
||||
@ -4258,7 +4270,7 @@ print_one_breakpoint_location (struct breakpoint *b,
|
||||
because the condition is an internal implementation detail
|
||||
that we do not want to expose to the user. */
|
||||
annotate_field (7);
|
||||
if (b->type == bp_tracepoint)
|
||||
if (tracepoint_type (b))
|
||||
ui_out_text (uiout, "\ttrace only if ");
|
||||
else
|
||||
ui_out_text (uiout, "\tstop only if ");
|
||||
@ -4451,7 +4463,7 @@ user_settable_breakpoint (const struct breakpoint *b)
|
||||
return (b->type == bp_breakpoint
|
||||
|| b->type == bp_catchpoint
|
||||
|| b->type == bp_hardware_breakpoint
|
||||
|| b->type == bp_tracepoint
|
||||
|| tracepoint_type (b)
|
||||
|| b->type == bp_watchpoint
|
||||
|| b->type == bp_read_watchpoint
|
||||
|| b->type == bp_access_watchpoint
|
||||
@ -4804,6 +4816,7 @@ allocate_bp_location (struct breakpoint *bpt)
|
||||
{
|
||||
case bp_breakpoint:
|
||||
case bp_tracepoint:
|
||||
case bp_fast_tracepoint:
|
||||
case bp_until:
|
||||
case bp_finish:
|
||||
case bp_longjmp:
|
||||
@ -4900,7 +4913,7 @@ set_breakpoint_location_function (struct bp_location *loc)
|
||||
{
|
||||
if (loc->owner->type == bp_breakpoint
|
||||
|| loc->owner->type == bp_hardware_breakpoint
|
||||
|| loc->owner->type == bp_tracepoint)
|
||||
|| tracepoint_type (loc->owner))
|
||||
{
|
||||
find_pc_partial_function (loc->address, &(loc->function_name),
|
||||
NULL, NULL);
|
||||
@ -5159,7 +5172,7 @@ disable_breakpoints_in_shlibs (void)
|
||||
to insert those breakpoints and fail. */
|
||||
if (((b->type == bp_breakpoint)
|
||||
|| (b->type == bp_hardware_breakpoint)
|
||||
|| (b->type == bp_tracepoint))
|
||||
|| (tracepoint_type (b)))
|
||||
&& loc->pspace == current_program_space
|
||||
&& !loc->shlib_disabled
|
||||
#ifdef PC_SOLIB
|
||||
@ -6091,6 +6104,16 @@ mention (struct breakpoint *b)
|
||||
printf_filtered (_(" %d"), b->number);
|
||||
say_where = 1;
|
||||
break;
|
||||
case bp_fast_tracepoint:
|
||||
if (ui_out_is_mi_like_p (uiout))
|
||||
{
|
||||
say_where = 0;
|
||||
break;
|
||||
}
|
||||
printf_filtered (_("Fast tracepoint"));
|
||||
printf_filtered (_(" %d"), b->number);
|
||||
say_where = 1;
|
||||
break;
|
||||
|
||||
case bp_until:
|
||||
case bp_finish:
|
||||
@ -6593,6 +6616,38 @@ breakpoint_sals_to_pc (struct symtabs_and_lines *sals,
|
||||
resolve_sal_pc (&sals->sals[i]);
|
||||
}
|
||||
|
||||
/* Fast tracepoints may have restrictions on valid locations. For
|
||||
instance, a fast tracepoint using a jump instead of a trap will
|
||||
likely have to overwrite more bytes than a trap would, and so can
|
||||
only be placed where the instruction is longer than the jump, or a
|
||||
multi-instruction sequence does not have a jump into the middle of
|
||||
it, etc. */
|
||||
|
||||
static void
|
||||
check_fast_tracepoint_sals (struct gdbarch *gdbarch,
|
||||
struct symtabs_and_lines *sals)
|
||||
{
|
||||
int i, rslt;
|
||||
struct symtab_and_line *sal;
|
||||
char *msg;
|
||||
struct cleanup *old_chain;
|
||||
|
||||
for (i = 0; i < sals->nelts; i++)
|
||||
{
|
||||
sal = &sals->sals[i];
|
||||
|
||||
rslt = gdbarch_fast_tracepoint_valid_at (gdbarch, sal->pc,
|
||||
NULL, &msg);
|
||||
old_chain = make_cleanup (xfree, msg);
|
||||
|
||||
if (!rslt)
|
||||
error (_("May not have a fast tracepoint at 0x%s%s"),
|
||||
paddress (gdbarch, sal->pc), (msg ? msg : ""));
|
||||
|
||||
do_cleanups (old_chain);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
do_captured_parse_breakpoint (struct ui_out *ui, void *data)
|
||||
{
|
||||
@ -6794,9 +6849,13 @@ break_command_really (struct gdbarch *gdbarch,
|
||||
breakpoint_sals_to_pc (&sals, addr_start);
|
||||
|
||||
type_wanted = (traceflag
|
||||
? bp_tracepoint
|
||||
? (hardwareflag ? bp_fast_tracepoint : bp_tracepoint)
|
||||
: (hardwareflag ? bp_hardware_breakpoint : bp_breakpoint));
|
||||
|
||||
/* Fast tracepoints may have additional restrictions on location. */
|
||||
if (type_wanted == bp_fast_tracepoint)
|
||||
check_fast_tracepoint_sals (gdbarch, &sals);
|
||||
|
||||
/* Verify that condition can be parsed, before setting any
|
||||
breakpoints. Allocate a separate condition expression for each
|
||||
breakpoint. */
|
||||
@ -8970,6 +9029,7 @@ breakpoint_re_set_one (void *bint)
|
||||
case bp_breakpoint:
|
||||
case bp_hardware_breakpoint:
|
||||
case bp_tracepoint:
|
||||
case bp_fast_tracepoint:
|
||||
/* Do not attempt to re-set breakpoints disabled during startup. */
|
||||
if (b->enable_state == bp_startup_disabled)
|
||||
return 0;
|
||||
@ -9369,6 +9429,7 @@ disable_command (char *args, int from_tty)
|
||||
continue;
|
||||
case bp_breakpoint:
|
||||
case bp_tracepoint:
|
||||
case bp_fast_tracepoint:
|
||||
case bp_catchpoint:
|
||||
case bp_hardware_breakpoint:
|
||||
case bp_watchpoint:
|
||||
@ -9462,6 +9523,7 @@ enable_command (char *args, int from_tty)
|
||||
continue;
|
||||
case bp_breakpoint:
|
||||
case bp_tracepoint:
|
||||
case bp_fast_tracepoint:
|
||||
case bp_catchpoint:
|
||||
case bp_hardware_breakpoint:
|
||||
case bp_watchpoint:
|
||||
@ -9769,6 +9831,22 @@ trace_command (char *arg, int from_tty)
|
||||
set_tracepoint_count (breakpoint_count);
|
||||
}
|
||||
|
||||
void
|
||||
ftrace_command (char *arg, int from_tty)
|
||||
{
|
||||
break_command_really (get_current_arch (),
|
||||
arg,
|
||||
NULL, 0, 1 /* parse arg */,
|
||||
0 /* tempflag */, 1 /* hardwareflag */,
|
||||
1 /* traceflag */,
|
||||
0 /* Ignore count */,
|
||||
pending_break_support,
|
||||
NULL,
|
||||
from_tty,
|
||||
1 /* enabled */);
|
||||
set_tracepoint_count (breakpoint_count);
|
||||
}
|
||||
|
||||
/* Print information on tracepoint number TPNUM_EXP, or all if
|
||||
omitted. */
|
||||
|
||||
@ -9846,7 +9924,7 @@ delete_trace_command (char *arg, int from_tty)
|
||||
{
|
||||
ALL_BREAKPOINTS_SAFE (b, temp)
|
||||
{
|
||||
if (b->type == bp_tracepoint
|
||||
if (tracepoint_type (b)
|
||||
&& b->number >= 0)
|
||||
delete_breakpoint (b);
|
||||
}
|
||||
@ -10501,6 +10579,13 @@ Do \"help tracepoints\" for info on other tracepoint commands."));
|
||||
add_com_alias ("tra", "trace", class_alias, 1);
|
||||
add_com_alias ("trac", "trace", class_alias, 1);
|
||||
|
||||
c = add_com ("ftrace", class_breakpoint, ftrace_command, _("\
|
||||
Set a fast tracepoint at specified line or function.\n\
|
||||
\n"
|
||||
BREAK_ARGS_HELP ("ftrace") "\n\
|
||||
Do \"help tracepoints\" for info on other tracepoint commands."));
|
||||
set_cmd_completer (c, location_completer);
|
||||
|
||||
add_info ("tracepoints", tracepoints_info, _("\
|
||||
Status of tracepoints, or tracepoint number NUMBER.\n\
|
||||
Convenience variable \"$tpnum\" contains the number of the\n\
|
||||
|
@ -121,6 +121,7 @@ enum bptype
|
||||
bp_catchpoint,
|
||||
|
||||
bp_tracepoint,
|
||||
bp_fast_tracepoint,
|
||||
|
||||
/* Event for JIT compiled code generation or deletion. */
|
||||
bp_jit_event,
|
||||
|
@ -1,3 +1,10 @@
|
||||
2010-01-05 Stan Shebs <stan@codesourcery.com>
|
||||
|
||||
* gdb.texinfo (Create and Delete Tracepoints): Describe fast
|
||||
tracepoints.
|
||||
(Tracepoint Packets): Describe remote protocol for fast
|
||||
tracepoints.
|
||||
|
||||
2010-01-01 Joel Brobecker <brobecker@adacore.com>
|
||||
|
||||
Update the "Start of New Year Procedure".
|
||||
|
@ -9323,6 +9323,11 @@ expressions and ignore counts on tracepoints have no effect, and
|
||||
tracepoints cannot run @value{GDBN} commands when they are
|
||||
hit. Tracepoints may not be thread-specific either.
|
||||
|
||||
@cindex fast tracepoints
|
||||
Some targets may support @dfn{fast tracepoints}, which are inserted in
|
||||
a different way (such as with a jump instead of a trap), that is
|
||||
faster but possibly restricted in where they may be installed.
|
||||
|
||||
This section describes commands to set tracepoints and associated
|
||||
conditions and actions.
|
||||
|
||||
@ -9378,6 +9383,20 @@ if the value is nonzero---that is, if @var{cond} evaluates as true.
|
||||
@xref{Tracepoint Conditions, ,Tracepoint Conditions}, for more
|
||||
information on tracepoint conditions.
|
||||
|
||||
@item ftrace @var{location} [ if @var{cond} ]
|
||||
@cindex set fast tracepoint
|
||||
@kindex ftrace
|
||||
The @code{ftrace} command sets a fast tracepoint. For targets that
|
||||
support them, fast tracepoints will use a more efficient but possibly
|
||||
less general technique to trigger data collection, such as a jump
|
||||
instruction instead of a trap, or some sort of hardware support. It
|
||||
may not be possible to create a fast tracepoint at the desired
|
||||
location, in which case the command will exit with an explanatory
|
||||
message.
|
||||
|
||||
@value{GDBN} handles arguments to @code{ftrace} exactly as for
|
||||
@code{trace}.
|
||||
|
||||
@vindex $tpnum
|
||||
@cindex last tracepoint number
|
||||
@cindex recent tracepoint number
|
||||
@ -29975,16 +29994,19 @@ tracepoints (@pxref{Tracepoints}).
|
||||
|
||||
@table @samp
|
||||
|
||||
@item QTDP:@var{n}:@var{addr}:@var{ena}:@var{step}:@var{pass}[:X@var{len},@var{bytes}]@r{[}-@r{]}
|
||||
@item QTDP:@var{n}:@var{addr}:@var{ena}:@var{step}:@var{pass}[:F@var{flen}][: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.
|
||||
count, and @var{pass} is its pass count. If an @samp{F} is present,
|
||||
then the tracepoint is to be a fast tracepoint, and the @var{flen} is
|
||||
the number of bytes that the target should copy elsewhere to make room
|
||||
for the tracepoint. 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.
|
||||
|
||||
Replies:
|
||||
@table @samp
|
||||
|
@ -250,6 +250,7 @@ struct gdbarch
|
||||
int has_global_solist;
|
||||
int has_global_breakpoints;
|
||||
gdbarch_has_shared_address_space_ftype *has_shared_address_space;
|
||||
gdbarch_fast_tracepoint_valid_at_ftype *fast_tracepoint_valid_at;
|
||||
};
|
||||
|
||||
|
||||
@ -391,6 +392,7 @@ struct gdbarch startup_gdbarch =
|
||||
0, /* has_global_solist */
|
||||
0, /* has_global_breakpoints */
|
||||
default_has_shared_address_space, /* has_shared_address_space */
|
||||
default_fast_tracepoint_valid_at, /* fast_tracepoint_valid_at */
|
||||
/* startup_gdbarch() */
|
||||
};
|
||||
|
||||
@ -475,6 +477,7 @@ gdbarch_alloc (const struct gdbarch_info *info,
|
||||
gdbarch->target_signal_from_host = default_target_signal_from_host;
|
||||
gdbarch->target_signal_to_host = default_target_signal_to_host;
|
||||
gdbarch->has_shared_address_space = default_has_shared_address_space;
|
||||
gdbarch->fast_tracepoint_valid_at = default_fast_tracepoint_valid_at;
|
||||
/* gdbarch_alloc() */
|
||||
|
||||
return gdbarch;
|
||||
@ -653,6 +656,7 @@ verify_gdbarch (struct gdbarch *gdbarch)
|
||||
/* Skip verify of has_global_solist, invalid_p == 0 */
|
||||
/* Skip verify of has_global_breakpoints, invalid_p == 0 */
|
||||
/* Skip verify of has_shared_address_space, invalid_p == 0 */
|
||||
/* Skip verify of fast_tracepoint_valid_at, invalid_p == 0 */
|
||||
buf = ui_file_xstrdup (log, &length);
|
||||
make_cleanup (xfree, buf);
|
||||
if (length > 0)
|
||||
@ -825,6 +829,9 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)
|
||||
fprintf_unfiltered (file,
|
||||
"gdbarch_dump: elf_make_msymbol_special = <%s>\n",
|
||||
host_address_to_string (gdbarch->elf_make_msymbol_special));
|
||||
fprintf_unfiltered (file,
|
||||
"gdbarch_dump: fast_tracepoint_valid_at = <%s>\n",
|
||||
host_address_to_string (gdbarch->fast_tracepoint_valid_at));
|
||||
fprintf_unfiltered (file,
|
||||
"gdbarch_dump: gdbarch_fetch_pointer_argument_p() = %d\n",
|
||||
gdbarch_fetch_pointer_argument_p (gdbarch));
|
||||
@ -3528,6 +3535,23 @@ set_gdbarch_has_shared_address_space (struct gdbarch *gdbarch,
|
||||
gdbarch->has_shared_address_space = has_shared_address_space;
|
||||
}
|
||||
|
||||
int
|
||||
gdbarch_fast_tracepoint_valid_at (struct gdbarch *gdbarch, CORE_ADDR addr, int *isize, char **msg)
|
||||
{
|
||||
gdb_assert (gdbarch != NULL);
|
||||
gdb_assert (gdbarch->fast_tracepoint_valid_at != NULL);
|
||||
if (gdbarch_debug >= 2)
|
||||
fprintf_unfiltered (gdb_stdlog, "gdbarch_fast_tracepoint_valid_at called\n");
|
||||
return gdbarch->fast_tracepoint_valid_at (gdbarch, addr, isize, msg);
|
||||
}
|
||||
|
||||
void
|
||||
set_gdbarch_fast_tracepoint_valid_at (struct gdbarch *gdbarch,
|
||||
gdbarch_fast_tracepoint_valid_at_ftype fast_tracepoint_valid_at)
|
||||
{
|
||||
gdbarch->fast_tracepoint_valid_at = fast_tracepoint_valid_at;
|
||||
}
|
||||
|
||||
|
||||
/* Keep a registry of per-architecture data-pointers required by GDB
|
||||
modules. */
|
||||
|
@ -909,6 +909,12 @@ typedef int (gdbarch_has_shared_address_space_ftype) (struct gdbarch *gdbarch);
|
||||
extern int gdbarch_has_shared_address_space (struct gdbarch *gdbarch);
|
||||
extern void set_gdbarch_has_shared_address_space (struct gdbarch *gdbarch, gdbarch_has_shared_address_space_ftype *has_shared_address_space);
|
||||
|
||||
/* True if a fast tracepoint can be set at an address. */
|
||||
|
||||
typedef int (gdbarch_fast_tracepoint_valid_at_ftype) (struct gdbarch *gdbarch, CORE_ADDR addr, int *isize, char **msg);
|
||||
extern int gdbarch_fast_tracepoint_valid_at (struct gdbarch *gdbarch, CORE_ADDR addr, int *isize, char **msg);
|
||||
extern void set_gdbarch_fast_tracepoint_valid_at (struct gdbarch *gdbarch, gdbarch_fast_tracepoint_valid_at_ftype *fast_tracepoint_valid_at);
|
||||
|
||||
/* Definition for an unknown syscall, used basically in error-cases. */
|
||||
#define UNKNOWN_SYSCALL (-1)
|
||||
|
||||
|
@ -759,6 +759,9 @@ v:int:has_global_breakpoints:::0:0::0
|
||||
|
||||
# True if inferiors share an address space (e.g., uClinux).
|
||||
m:int:has_shared_address_space:void:::default_has_shared_address_space::0
|
||||
|
||||
# True if a fast tracepoint can be set at an address.
|
||||
m:int:fast_tracepoint_valid_at:CORE_ADDR addr, int *isize, char **msg:addr, isize, msg::default_fast_tracepoint_valid_at::0
|
||||
EOF
|
||||
}
|
||||
|
||||
|
@ -43,6 +43,7 @@
|
||||
#include "target.h"
|
||||
#include "value.h"
|
||||
#include "dis-asm.h"
|
||||
#include "disasm.h"
|
||||
|
||||
#include "gdb_assert.h"
|
||||
#include "gdb_string.h"
|
||||
@ -5567,6 +5568,49 @@ static const int i386_record_regmap[] =
|
||||
I386_DS_REGNUM, I386_ES_REGNUM, I386_FS_REGNUM, I386_GS_REGNUM
|
||||
};
|
||||
|
||||
/* Check that the given address appears suitable for a fast
|
||||
tracepoint, which on x86 means that we need an instruction of at
|
||||
least 5 bytes, so that we can overwrite it with a 4-byte-offset
|
||||
jump and not have to worry about program jumps to an address in the
|
||||
middle of the tracepoint jump. Returns 1 if OK, and writes a size
|
||||
of instruction to replace, and 0 if not, plus an explanatory
|
||||
string. */
|
||||
|
||||
static int
|
||||
i386_fast_tracepoint_valid_at (struct gdbarch *gdbarch,
|
||||
CORE_ADDR addr, int *isize, char **msg)
|
||||
{
|
||||
int len, jumplen;
|
||||
static struct ui_file *gdb_null = NULL;
|
||||
|
||||
/* This is based on the target agent using a 4-byte relative jump.
|
||||
Alternate future possibilities include 8-byte offset for x86-84,
|
||||
or 3-byte jumps if the program has trampoline space close by. */
|
||||
jumplen = 5;
|
||||
|
||||
/* Dummy file descriptor for the disassembler. */
|
||||
if (!gdb_null)
|
||||
gdb_null = ui_file_new ();
|
||||
|
||||
/* Check for fit. */
|
||||
len = gdb_print_insn (gdbarch, addr, gdb_null, NULL);
|
||||
if (len < jumplen)
|
||||
{
|
||||
/* Return a bit of target-specific detail to add to the caller's
|
||||
generic failure message. */
|
||||
if (msg)
|
||||
*msg = xstrprintf (_("; instruction is only %d bytes long, need at least %d bytes for the jump"),
|
||||
len, jumplen);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (isize)
|
||||
*isize = len;
|
||||
if (msg)
|
||||
*msg = NULL;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static struct gdbarch *
|
||||
i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
|
||||
@ -5769,6 +5813,9 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
|
||||
set_gdbarch_skip_permanent_breakpoint (gdbarch,
|
||||
i386_skip_permanent_breakpoint);
|
||||
|
||||
set_gdbarch_fast_tracepoint_valid_at (gdbarch,
|
||||
i386_fast_tracepoint_valid_at);
|
||||
|
||||
return gdbarch;
|
||||
}
|
||||
|
||||
|
24
gdb/remote.c
24
gdb/remote.c
@ -298,6 +298,9 @@ struct remote_state
|
||||
/* True if the stub reports support for conditional tracepoints. */
|
||||
int cond_tracepoints;
|
||||
|
||||
/* True if the stub reports support for fast tracepoints. */
|
||||
int fast_tracepoints;
|
||||
|
||||
/* Nonzero if the user has pressed Ctrl-C, but the target hasn't
|
||||
responded to that. */
|
||||
int ctrlc_pending_p;
|
||||
@ -1066,6 +1069,7 @@ enum {
|
||||
PACKET_qXfer_siginfo_write,
|
||||
PACKET_qAttached,
|
||||
PACKET_ConditionalTracepoints,
|
||||
PACKET_FastTracepoints,
|
||||
PACKET_bc,
|
||||
PACKET_bs,
|
||||
PACKET_MAX
|
||||
@ -3136,6 +3140,15 @@ remote_cond_tracepoint_feature (const struct protocol_feature *feature,
|
||||
rs->cond_tracepoints = (support == PACKET_ENABLE);
|
||||
}
|
||||
|
||||
static void
|
||||
remote_fast_tracepoint_feature (const struct protocol_feature *feature,
|
||||
enum packet_support support,
|
||||
const char *value)
|
||||
{
|
||||
struct remote_state *rs = get_remote_state ();
|
||||
rs->fast_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,
|
||||
@ -3164,6 +3177,8 @@ static struct protocol_feature remote_protocol_features[] = {
|
||||
PACKET_qXfer_siginfo_write },
|
||||
{ "ConditionalTracepoints", PACKET_DISABLE, remote_cond_tracepoint_feature,
|
||||
PACKET_ConditionalTracepoints },
|
||||
{ "FastTracepoints", PACKET_DISABLE, remote_fast_tracepoint_feature,
|
||||
PACKET_FastTracepoints },
|
||||
{ "ReverseContinue", PACKET_DISABLE, remote_supported_packet,
|
||||
PACKET_bc },
|
||||
{ "ReverseStep", PACKET_DISABLE, remote_supported_packet,
|
||||
@ -8895,6 +8910,13 @@ remote_supports_cond_tracepoints (void)
|
||||
return rs->cond_tracepoints;
|
||||
}
|
||||
|
||||
int
|
||||
remote_supports_fast_tracepoints (void)
|
||||
{
|
||||
struct remote_state *rs = get_remote_state ();
|
||||
return rs->fast_tracepoints;
|
||||
}
|
||||
|
||||
static void
|
||||
init_remote_ops (void)
|
||||
{
|
||||
@ -9371,6 +9393,8 @@ Show the maximum size of the address (in bits) in a memory packet."), NULL,
|
||||
|
||||
add_packet_config_cmd (&remote_protocol_packets[PACKET_ConditionalTracepoints],
|
||||
"ConditionalTracepoints", "conditional-tracepoints", 0);
|
||||
add_packet_config_cmd (&remote_protocol_packets[PACKET_FastTracepoints],
|
||||
"FastTracepoints", "fast-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
|
||||
|
@ -1,3 +1,7 @@
|
||||
2010-01-05 Stan Shebs <stan@codesourcery.com>
|
||||
|
||||
* gdb.trace/tracecmd.exp: Test ftrace.
|
||||
|
||||
2010-01-04 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
|
||||
|
||||
* gdb.xml/tdesc-regs.exp: Support s390*-*-* targets.
|
||||
|
@ -164,4 +164,16 @@ gdb_test "info trace" "in gdb_recursion_test.*$srcfile:$testline1.*trace only if
|
||||
# 1.14 help trace
|
||||
gdb_test "help trace" "Set a tracepoint at .*" "1.14: help trace"
|
||||
|
||||
# 1.15 ftrace
|
||||
|
||||
gdb_delete_tracepoints
|
||||
|
||||
send_gdb "ftrace gdb_recursion_test\n"
|
||||
# Acceptance vs rejection of a location are target-specific, so allow both.
|
||||
gdb_expect {
|
||||
-re "Fast tracepoint $decimal at $hex: file.*$srcfile, line $testline1.*$gdb_prompt $"
|
||||
{ pass "Set a fast tracepoint" }
|
||||
-re ".*May not have a fast tracepoint at $hex.*$gdb_prompt $"
|
||||
{ pass "Declined to set a fast tracepoint" }
|
||||
timeout { fail "Timeout while setting fast tracepoint" }
|
||||
}
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include "tracepoint.h"
|
||||
#include "remote.h"
|
||||
extern int remote_supports_cond_tracepoints (void);
|
||||
extern int remote_supports_fast_tracepoints (void);
|
||||
extern char *unpack_varlen_hex (char *buff, ULONGEST *result);
|
||||
#include "linespec.h"
|
||||
#include "regcache.h"
|
||||
@ -1690,6 +1691,7 @@ trace_start_command (char *args, int from_tty)
|
||||
void
|
||||
download_tracepoint (struct breakpoint *t)
|
||||
{
|
||||
CORE_ADDR tpaddr;
|
||||
char tmp[40];
|
||||
char buf[2048];
|
||||
char **tdp_actions;
|
||||
@ -1699,11 +1701,38 @@ download_tracepoint (struct breakpoint *t)
|
||||
struct agent_expr *aexpr;
|
||||
struct cleanup *aexpr_chain = NULL;
|
||||
|
||||
sprintf_vma (tmp, (t->loc ? t->loc->address : 0));
|
||||
tpaddr = t->loc->address;
|
||||
sprintf_vma (tmp, (t->loc ? tpaddr : 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);
|
||||
/* Fast tracepoints are mostly handled by the target, but we can
|
||||
tell the target how big of an instruction block should be moved
|
||||
around. */
|
||||
if (t->type == bp_fast_tracepoint)
|
||||
{
|
||||
/* Only test for support at download time; we may not know
|
||||
target capabilities at definition time. */
|
||||
if (remote_supports_fast_tracepoints ())
|
||||
{
|
||||
int isize;
|
||||
|
||||
if (gdbarch_fast_tracepoint_valid_at (get_current_arch (),
|
||||
tpaddr, &isize, NULL))
|
||||
sprintf (buf + strlen (buf), ":F%x", isize);
|
||||
else
|
||||
/* If it passed validation at definition but fails now,
|
||||
something is very wrong. */
|
||||
internal_error (__FILE__, __LINE__,
|
||||
"Fast tracepoint not valid during download");
|
||||
}
|
||||
else
|
||||
/* Fast tracepoints are functionally identical to regular
|
||||
tracepoints, so don't take lack of support as a reason to
|
||||
give up on the trace run. */
|
||||
warning (_("Target does not support fast tracepoints, downloading %d as regular tracepoint"), t->number);
|
||||
}
|
||||
/* If the tracepoint has a conditional, make it into an agent
|
||||
expression and append to the definition. */
|
||||
if (t->loc->cond)
|
||||
|
Loading…
x
Reference in New Issue
Block a user