Mon Dec 1 17:13:53 1997 Michael Snyder (msnyder@cleaver.cygnus.com)
* tracepoint.c: modify error behavior of the tfind commands. Add some comments.
This commit is contained in:
parent
51b057f27b
commit
8b9c29f5cb
1 changed files with 251 additions and 169 deletions
420
gdb/tracepoint.c
420
gdb/tracepoint.c
|
@ -51,6 +51,34 @@ extern void (*readline_end_hook) PARAMS ((void));
|
|||
#define ISATTY(FP) (isatty (fileno (FP)))
|
||||
#endif
|
||||
|
||||
/*
|
||||
Tracepoint.c:
|
||||
|
||||
This module defines the following debugger commands:
|
||||
trace : set a tracepoint on a function, line, or address.
|
||||
info trace : list all debugger-defined tracepoints.
|
||||
delete trace : delete one or more tracepoints.
|
||||
enable trace : enable one or more tracepoints.
|
||||
disable trace : disable one or more tracepoints.
|
||||
actions : specify actions to be taken at a tracepoint.
|
||||
passcount : specify a pass count for a tracepoint.
|
||||
tstart : start a trace experiment.
|
||||
tstop : stop a trace experiment.
|
||||
tstatus : query the status of a trace experiment.
|
||||
tfind : find a trace frame in the trace buffer.
|
||||
tdump : print everything collected at the current tracepoint.
|
||||
save-tracepoints : write tracepoint setup into a file.
|
||||
|
||||
This module defines the following user-visible debugger variables:
|
||||
$trace_frame : sequence number of trace frame currently being debugged.
|
||||
$trace_line : source line of trace frame currently being debugged.
|
||||
$trace_file : source file of trace frame currently being debugged.
|
||||
$tracepoint : tracepoint number of trace frame currently being debugged.
|
||||
*/
|
||||
|
||||
|
||||
/* ======= Important global variables: ======= */
|
||||
|
||||
/* Chain of all tracepoints defined. */
|
||||
struct tracepoint *tracepoint_chain;
|
||||
|
||||
|
@ -69,6 +97,31 @@ static struct symbol *traceframe_fun;
|
|||
/* Symtab and line for last traceframe collected */
|
||||
static struct symtab_and_line traceframe_sal;
|
||||
|
||||
/* Tracing command lists */
|
||||
static struct cmd_list_element *tfindlist;
|
||||
static struct cmd_list_element *tracelist;
|
||||
|
||||
/* ======= Important command functions: ======= */
|
||||
static void trace_command PARAMS ((char *, int));
|
||||
static void tracepoints_info PARAMS ((char *, int));
|
||||
static void delete_trace_command PARAMS ((char *, int));
|
||||
static void enable_trace_command PARAMS ((char *, int));
|
||||
static void disable_trace_command PARAMS ((char *, int));
|
||||
static void trace_pass_command PARAMS ((char *, int));
|
||||
static void trace_actions_command PARAMS ((char *, int));
|
||||
static void trace_start_command PARAMS ((char *, int));
|
||||
static void trace_stop_command PARAMS ((char *, int));
|
||||
static void trace_status_command PARAMS ((char *, int));
|
||||
static void trace_find_command PARAMS ((char *, int));
|
||||
static void trace_find_pc_command PARAMS ((char *, int));
|
||||
static void trace_find_tracepoint_command PARAMS ((char *, int));
|
||||
static void trace_find_line_command PARAMS ((char *, int));
|
||||
static void trace_find_range_command PARAMS ((char *, int));
|
||||
static void trace_find_outside_command PARAMS ((char *, int));
|
||||
static void tracepoint_save_command PARAMS ((char *, int));
|
||||
static void trace_dump_command PARAMS ((char *, int));
|
||||
|
||||
|
||||
/* Utility: returns true if "target remote" */
|
||||
static int
|
||||
target_is_remote ()
|
||||
|
@ -102,36 +155,6 @@ trace_error (buf)
|
|||
}
|
||||
}
|
||||
|
||||
/* Obsolete: collect regs from a trace frame */
|
||||
static void
|
||||
trace_receive_regs (buf)
|
||||
char *buf;
|
||||
{
|
||||
long regno, i;
|
||||
char regbuf[MAX_REGISTER_RAW_SIZE], *tmp, *p = buf;
|
||||
|
||||
while (*p)
|
||||
{
|
||||
regno = strtol (p, &tmp, 16);
|
||||
if (p == tmp || *tmp++ != ':')
|
||||
error ("tracepoint.c: malformed 'R' packet");
|
||||
else p = tmp;
|
||||
|
||||
for (i = 0; i < REGISTER_RAW_SIZE (regno); i++)
|
||||
{
|
||||
if (p[0] == 0 || p[1] == 0)
|
||||
warning ("Remote reply is too short: %s", buf);
|
||||
regbuf[i] = fromhex (p[0]) * 16 + fromhex (p[1]);
|
||||
p += 2;
|
||||
}
|
||||
|
||||
if (*p++ != ';')
|
||||
error ("tracepoint.c: malformed 'R' packet");
|
||||
|
||||
supply_register (regno, regbuf);
|
||||
}
|
||||
}
|
||||
|
||||
/* Utility: wait for reply from stub, while accepting "O" packets */
|
||||
static char *
|
||||
remote_get_noisy_reply (buf)
|
||||
|
@ -144,13 +167,6 @@ remote_get_noisy_reply (buf)
|
|||
error ("Target does not support this command.");
|
||||
else if (buf[0] == 'E')
|
||||
trace_error (buf);
|
||||
else if (buf[0] == 'R')
|
||||
{
|
||||
flush_cached_frames ();
|
||||
registers_changed ();
|
||||
select_frame (get_current_frame (), 0);
|
||||
trace_receive_regs (buf);
|
||||
}
|
||||
else if (buf[0] == 'O' &&
|
||||
buf[1] != 'K')
|
||||
remote_console_output (buf + 1); /* 'O' message from stub */
|
||||
|
@ -334,6 +350,7 @@ set_raw_tracepoint (sal)
|
|||
return t;
|
||||
}
|
||||
|
||||
/* Set a tracepoint according to ARG (function, linenum or *address) */
|
||||
static void
|
||||
trace_command (arg, from_tty)
|
||||
char *arg;
|
||||
|
@ -393,10 +410,12 @@ trace_command (arg, from_tty)
|
|||
if (sals.nelts > 1)
|
||||
{
|
||||
printf_filtered ("Multiple tracepoints were set.\n");
|
||||
printf_filtered ("Use the \"delete\" command to delete unwanted tracepoints.\n");
|
||||
printf_filtered ("Use 'delete trace' to delete unwanted tracepoints.\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* Print information on tracepoint number TPNUM_EXP, or all if omitted. */
|
||||
|
||||
static void
|
||||
tracepoints_info (tpnum_exp, from_tty)
|
||||
char *tpnum_exp;
|
||||
|
@ -618,6 +637,7 @@ map_args_over_tracepoints (args, from_tty, opcode)
|
|||
}
|
||||
}
|
||||
|
||||
/* The 'enable trace' command enables tracepoints. Not supported by all targets. */
|
||||
static void
|
||||
enable_trace_command (args, from_tty)
|
||||
char *args;
|
||||
|
@ -627,6 +647,7 @@ enable_trace_command (args, from_tty)
|
|||
map_args_over_tracepoints (args, from_tty, enable);
|
||||
}
|
||||
|
||||
/* The 'disable trace' command enables tracepoints. Not supported by all targets. */
|
||||
static void
|
||||
disable_trace_command (args, from_tty)
|
||||
char *args;
|
||||
|
@ -636,6 +657,7 @@ disable_trace_command (args, from_tty)
|
|||
map_args_over_tracepoints (args, from_tty, disable);
|
||||
}
|
||||
|
||||
/* Remove a tracepoint (or all if no argument) */
|
||||
static void
|
||||
delete_trace_command (args, from_tty)
|
||||
char *args;
|
||||
|
@ -649,6 +671,12 @@ delete_trace_command (args, from_tty)
|
|||
map_args_over_tracepoints (args, from_tty, delete);
|
||||
}
|
||||
|
||||
/* Set passcount for tracepoint.
|
||||
|
||||
First command argument is passcount, second is tracepoint number.
|
||||
If tracepoint number omitted, apply to most recently defined.
|
||||
Also accepts special argument "all". */
|
||||
|
||||
static void
|
||||
trace_pass_command (args, from_tty)
|
||||
char *args;
|
||||
|
@ -683,11 +711,24 @@ trace_pass_command (args, from_tty)
|
|||
}
|
||||
}
|
||||
|
||||
/* ACTIONS ACTIONS ACTIONS */
|
||||
/* ACTIONS functions: */
|
||||
|
||||
static void read_actions PARAMS((struct tracepoint *));
|
||||
static void free_actions PARAMS((struct tracepoint *));
|
||||
static int validate_actionline PARAMS((char *, struct tracepoint *));
|
||||
/* Prototypes for action-parsing utility commands */
|
||||
static void read_actions PARAMS((struct tracepoint *));
|
||||
static void free_actions PARAMS((struct tracepoint *));
|
||||
static int validate_actionline PARAMS((char *, struct tracepoint *));
|
||||
static char *parse_and_eval_memrange PARAMS ((char *,
|
||||
CORE_ADDR,
|
||||
long *,
|
||||
bfd_signed_vma *,
|
||||
long *));
|
||||
|
||||
/* The three functions:
|
||||
collect_pseudocom, while_stepping_pseudocom, and end_pseudocom
|
||||
are placeholders for "commands" that are actually ONLY to be used
|
||||
within a tracepoint action list. If the actual function is ever called,
|
||||
it means that somebody issued the "command" at the top level,
|
||||
which is always an error. */
|
||||
|
||||
static void
|
||||
end_pseudocom (args, from_tty)
|
||||
|
@ -707,6 +748,7 @@ collect_pseudocom (args, from_tty)
|
|||
error ("This command can only be used in a tracepoint actions list.");
|
||||
}
|
||||
|
||||
/* Enter a list of actions for a tracepoint. */
|
||||
static void
|
||||
trace_actions_command (args, from_tty)
|
||||
char *args;
|
||||
|
@ -746,6 +788,7 @@ enum actionline_type
|
|||
STEPPING = 2,
|
||||
};
|
||||
|
||||
/* worker function */
|
||||
static void
|
||||
read_actions (t)
|
||||
struct tracepoint *t;
|
||||
|
@ -819,97 +862,7 @@ read_actions (t)
|
|||
discard_cleanups (old_chain);
|
||||
}
|
||||
|
||||
static char *
|
||||
parse_and_eval_memrange (arg, addr, typecode, offset, size)
|
||||
char *arg;
|
||||
CORE_ADDR addr;
|
||||
long *typecode, *size;
|
||||
bfd_signed_vma *offset;
|
||||
{
|
||||
char *start = arg;
|
||||
struct expression *exp;
|
||||
|
||||
if (*arg++ != '$' || *arg++ != '(')
|
||||
error ("Internal: bad argument to validate_memrange: %s", start);
|
||||
|
||||
if (*arg == '$') /* register for relative memrange? */
|
||||
{
|
||||
exp = parse_exp_1 (&arg, block_for_pc (addr), 1);
|
||||
if (exp->elts[0].opcode != OP_REGISTER)
|
||||
error ("Bad register operand for memrange: %s", start);
|
||||
if (*arg++ != ',')
|
||||
error ("missing comma for memrange: %s", start);
|
||||
*typecode = exp->elts[1].longconst;
|
||||
}
|
||||
else
|
||||
*typecode = 0;
|
||||
|
||||
#if 0
|
||||
/* While attractive, this fails for a number of reasons:
|
||||
1) parse_and_eval_address does not deal with trailing commas,
|
||||
close-parens etc.
|
||||
2) There is no safeguard against the user trying to use
|
||||
an out-of-scope variable in an address expression (for instance).
|
||||
2.5) If you are going to allow semi-arbitrary expressions, you
|
||||
would need to explain which expressions are allowed, and
|
||||
which are not (which would provoke endless questions).
|
||||
3) If you are going to allow semi-arbitrary expressions in the
|
||||
offset and size fields, then the leading "$" of a register
|
||||
name no longer disambiguates the typecode field.
|
||||
*/
|
||||
|
||||
*offset = parse_and_eval_address (arg);
|
||||
if ((arg = strchr (arg, ',')) == NULL)
|
||||
error ("missing comma for memrange: %s", start);
|
||||
else
|
||||
arg++;
|
||||
|
||||
*size = parse_and_eval_address (arg);
|
||||
if ((arg = strchr (arg, ')')) == NULL)
|
||||
error ("missing close-parenthesis for memrange: %s", start);
|
||||
else
|
||||
arg++;
|
||||
#else
|
||||
#if 0
|
||||
/* This, on the other hand, doesn't work because "-1" is an
|
||||
expression, not an OP_LONG! Fall back to using strtol for now. */
|
||||
|
||||
exp = parse_exp_1 (&arg, block_for_pc (addr), 1);
|
||||
if (exp->elts[0].opcode != OP_LONG)
|
||||
error ("Bad offset operand for memrange: %s", start);
|
||||
*offset = exp->elts[2].longconst;
|
||||
|
||||
if (*arg++ != ',')
|
||||
error ("missing comma for memrange: %s", start);
|
||||
|
||||
exp = parse_exp_1 (&arg, block_for_pc (addr), 1);
|
||||
if (exp->elts[0].opcode != OP_LONG)
|
||||
error ("Bad size operand for memrange: %s", start);
|
||||
*size = exp->elts[2].longconst;
|
||||
|
||||
if (*size <= 0)
|
||||
error ("invalid size in memrange: %s", start);
|
||||
|
||||
if (*arg++ != ')')
|
||||
error ("missing close-parenthesis for memrange: %s", start);
|
||||
#else
|
||||
*offset = strtol (arg, &arg, 0);
|
||||
if (*arg++ != ',')
|
||||
error ("missing comma for memrange: %s", start);
|
||||
*size = strtol (arg, &arg, 0);
|
||||
if (*size <= 0)
|
||||
error ("invalid size in memrange: %s", start);
|
||||
if (*arg++ != ')')
|
||||
error ("missing close-parenthesis for memrange: %s", start);
|
||||
#endif
|
||||
#endif
|
||||
if (info_verbose)
|
||||
printf_filtered ("Collecting memrange: (0x%x,0x%x,0x%x)\n",
|
||||
*typecode, *offset, *size);
|
||||
|
||||
return arg;
|
||||
}
|
||||
|
||||
/* worker function */
|
||||
static enum actionline_type
|
||||
validate_actionline (line, t)
|
||||
char *line;
|
||||
|
@ -1007,6 +960,7 @@ validate_actionline (line, t)
|
|||
}
|
||||
}
|
||||
|
||||
/* worker function */
|
||||
static void
|
||||
free_actions (t)
|
||||
struct tracepoint *t;
|
||||
|
@ -1034,6 +988,101 @@ struct collection_list {
|
|||
struct memrange *list;
|
||||
} tracepoint_list, stepping_list;
|
||||
|
||||
/* MEMRANGE functions: */
|
||||
|
||||
/* parse a memrange spec from command input */
|
||||
static char *
|
||||
parse_and_eval_memrange (arg, addr, typecode, offset, size)
|
||||
char *arg;
|
||||
CORE_ADDR addr;
|
||||
long *typecode, *size;
|
||||
bfd_signed_vma *offset;
|
||||
{
|
||||
char *start = arg;
|
||||
struct expression *exp;
|
||||
|
||||
if (*arg++ != '$' || *arg++ != '(')
|
||||
error ("Internal: bad argument to validate_memrange: %s", start);
|
||||
|
||||
if (*arg == '$') /* register for relative memrange? */
|
||||
{
|
||||
exp = parse_exp_1 (&arg, block_for_pc (addr), 1);
|
||||
if (exp->elts[0].opcode != OP_REGISTER)
|
||||
error ("Bad register operand for memrange: %s", start);
|
||||
if (*arg++ != ',')
|
||||
error ("missing comma for memrange: %s", start);
|
||||
*typecode = exp->elts[1].longconst;
|
||||
}
|
||||
else
|
||||
*typecode = 0;
|
||||
|
||||
#if 0
|
||||
/* While attractive, this fails for a number of reasons:
|
||||
1) parse_and_eval_address does not deal with trailing commas,
|
||||
close-parens etc.
|
||||
2) There is no safeguard against the user trying to use
|
||||
an out-of-scope variable in an address expression (for instance).
|
||||
2.5) If you are going to allow semi-arbitrary expressions, you
|
||||
would need to explain which expressions are allowed, and
|
||||
which are not (which would provoke endless questions).
|
||||
3) If you are going to allow semi-arbitrary expressions in the
|
||||
offset and size fields, then the leading "$" of a register
|
||||
name no longer disambiguates the typecode field.
|
||||
*/
|
||||
|
||||
*offset = parse_and_eval_address (arg);
|
||||
if ((arg = strchr (arg, ',')) == NULL)
|
||||
error ("missing comma for memrange: %s", start);
|
||||
else
|
||||
arg++;
|
||||
|
||||
*size = parse_and_eval_address (arg);
|
||||
if ((arg = strchr (arg, ')')) == NULL)
|
||||
error ("missing close-parenthesis for memrange: %s", start);
|
||||
else
|
||||
arg++;
|
||||
#else
|
||||
#if 0
|
||||
/* This, on the other hand, doesn't work because "-1" is an
|
||||
expression, not an OP_LONG! Fall back to using strtol for now. */
|
||||
|
||||
exp = parse_exp_1 (&arg, block_for_pc (addr), 1);
|
||||
if (exp->elts[0].opcode != OP_LONG)
|
||||
error ("Bad offset operand for memrange: %s", start);
|
||||
*offset = exp->elts[2].longconst;
|
||||
|
||||
if (*arg++ != ',')
|
||||
error ("missing comma for memrange: %s", start);
|
||||
|
||||
exp = parse_exp_1 (&arg, block_for_pc (addr), 1);
|
||||
if (exp->elts[0].opcode != OP_LONG)
|
||||
error ("Bad size operand for memrange: %s", start);
|
||||
*size = exp->elts[2].longconst;
|
||||
|
||||
if (*size <= 0)
|
||||
error ("invalid size in memrange: %s", start);
|
||||
|
||||
if (*arg++ != ')')
|
||||
error ("missing close-parenthesis for memrange: %s", start);
|
||||
#else
|
||||
*offset = strtol (arg, &arg, 0);
|
||||
if (*arg++ != ',')
|
||||
error ("missing comma for memrange: %s", start);
|
||||
*size = strtol (arg, &arg, 0);
|
||||
if (*size <= 0)
|
||||
error ("invalid size in memrange: %s", start);
|
||||
if (*arg++ != ')')
|
||||
error ("missing close-parenthesis for memrange: %s", start);
|
||||
#endif
|
||||
#endif
|
||||
if (info_verbose)
|
||||
printf_filtered ("Collecting memrange: (0x%x,0x%x,0x%x)\n",
|
||||
*typecode, *offset, *size);
|
||||
|
||||
return arg;
|
||||
}
|
||||
|
||||
/* compare memranges for qsort */
|
||||
static int
|
||||
memrange_cmp (a, b)
|
||||
struct memrange *a, *b;
|
||||
|
@ -1053,6 +1102,7 @@ memrange_cmp (a, b)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Sort the memrange list using qsort, and merge adjacent memranges */
|
||||
static void
|
||||
memrange_sortmerge (memranges)
|
||||
struct collection_list *memranges;
|
||||
|
@ -1081,6 +1131,7 @@ memrange_sortmerge (memranges)
|
|||
}
|
||||
}
|
||||
|
||||
/* Add a register to a collection list */
|
||||
void
|
||||
add_register (collection, regno)
|
||||
struct collection_list *collection;
|
||||
|
@ -1094,6 +1145,7 @@ add_register (collection, regno)
|
|||
collection->regs_mask [regno / 8] |= 1 << (regno % 8);
|
||||
}
|
||||
|
||||
/* Add a memrange to a collection list */
|
||||
static void
|
||||
add_memrange (memranges, type, base, len)
|
||||
struct collection_list *memranges;
|
||||
|
@ -1121,6 +1173,7 @@ add_memrange (memranges, type, base, len)
|
|||
add_register (memranges, type);
|
||||
}
|
||||
|
||||
/* Add a symbol to a collection list */
|
||||
static void
|
||||
collect_symbol (collect, sym)
|
||||
struct collection_list *collect;
|
||||
|
@ -1203,6 +1256,7 @@ collect_symbol (collect, sym)
|
|||
}
|
||||
}
|
||||
|
||||
/* Add all locals (or args) symbols to collection list */
|
||||
static void
|
||||
add_local_symbols (collect, pc, type)
|
||||
struct collection_list *collect;
|
||||
|
@ -1253,6 +1307,7 @@ add_local_symbols (collect, pc, type)
|
|||
warning ("No %s found in scope.", type == 'L' ? "locals" : "args");
|
||||
}
|
||||
|
||||
/* worker function */
|
||||
static void
|
||||
clear_collection_list (list)
|
||||
struct collection_list *list;
|
||||
|
@ -1261,6 +1316,7 @@ clear_collection_list (list)
|
|||
memset (list->regs_mask, 0, sizeof (list->regs_mask));
|
||||
}
|
||||
|
||||
/* reduce a collection list to string form (for gdb protocol) */
|
||||
static char *
|
||||
stringify_collection_list (list, string)
|
||||
struct collection_list *list;
|
||||
|
@ -1308,6 +1364,7 @@ stringify_collection_list (list, string)
|
|||
return string;
|
||||
}
|
||||
|
||||
/* render all actions into gdb protocol */
|
||||
static void
|
||||
encode_actions (t, tdp_actions, step_count, stepping_actions)
|
||||
struct tracepoint *t;
|
||||
|
@ -1431,6 +1488,13 @@ encode_actions (t, tdp_actions, step_count, stepping_actions)
|
|||
|
||||
static char target_buf[2048];
|
||||
|
||||
/* tstart command:
|
||||
|
||||
Tell target to lear any previous trace experiment.
|
||||
Walk the list of tracepoints, and send them (and their actions)
|
||||
to the target. If no errors,
|
||||
Tell target to start a new trace experiment. */
|
||||
|
||||
static void
|
||||
trace_start_command (args, from_tty)
|
||||
char *args;
|
||||
|
@ -1497,6 +1561,7 @@ trace_start_command (args, from_tty)
|
|||
printf_filtered ("Trace can only be run on remote targets.\n");
|
||||
}
|
||||
|
||||
/* tstop command */
|
||||
static void
|
||||
trace_stop_command (args, from_tty)
|
||||
char *args;
|
||||
|
@ -1513,6 +1578,7 @@ trace_stop_command (args, from_tty)
|
|||
error ("Trace can only be run on remote targets.");
|
||||
}
|
||||
|
||||
/* tstatus command */
|
||||
static void
|
||||
trace_status_command (args, from_tty)
|
||||
char *args;
|
||||
|
@ -1529,29 +1595,7 @@ trace_status_command (args, from_tty)
|
|||
error ("Trace can only be run on remote targets.");
|
||||
}
|
||||
|
||||
static void
|
||||
trace_buff_command (args, from_tty)
|
||||
char *args;
|
||||
int from_tty;
|
||||
{ /* STUB_COMM NOT_IMPLEMENTED */
|
||||
if (args == 0 || *args == 0)
|
||||
printf_filtered ("TBUFFER command requires argument (on or off)\n");
|
||||
else if (strcasecmp (args, "on") == 0)
|
||||
printf_filtered ("tbuffer overflow on.\n");
|
||||
else if (strcasecmp (args, "off") == 0)
|
||||
printf_filtered ("tbuffer overflow off.\n");
|
||||
else
|
||||
printf_filtered ("TBUFFER: unknown argument (use on or off)\n");
|
||||
}
|
||||
|
||||
static void
|
||||
trace_limit_command (args, from_tty)
|
||||
char *args;
|
||||
int from_tty;
|
||||
{ /* STUB_COMM NOT_IMPLEMENTED */
|
||||
printf_filtered ("Limit it to what?\n");
|
||||
}
|
||||
|
||||
/* Worker function for the various flavors of the tfind command */
|
||||
static void
|
||||
finish_tfind_command (reply, from_tty)
|
||||
char *reply;
|
||||
|
@ -1563,7 +1607,38 @@ finish_tfind_command (reply, from_tty)
|
|||
switch (*reply) {
|
||||
case 'F':
|
||||
if ((target_frameno = strtol (++reply, &reply, 16)) == -1)
|
||||
error ("Target failed to find requested trace frame.");
|
||||
{
|
||||
/* A request for a non-existant trace frame has failed.
|
||||
Our response will be different, depending on FROM_TTY:
|
||||
|
||||
If FROM_TTY is true, meaning that this command was
|
||||
typed interactively by the user, then give an error
|
||||
and DO NOT change the state of traceframe_number etc.
|
||||
|
||||
However if FROM_TTY is false, meaning that we're either
|
||||
in a script, a loop, or a user-defined command, then
|
||||
DON'T give an error, but DO change the state of
|
||||
traceframe_number etc. to invalid.
|
||||
|
||||
The rationalle is that if you typed the command, you
|
||||
might just have committed a typo or something, and you'd
|
||||
like to NOT lose your current debugging state. However
|
||||
if you're in a user-defined command or especially in a
|
||||
loop, then you need a way to detect that the command
|
||||
failed WITHOUT aborting. This allows you to write
|
||||
scripts that search thru the trace buffer until the end,
|
||||
and then continue on to do something else. */
|
||||
|
||||
if (from_tty)
|
||||
error ("Target failed to find requested trace frame.");
|
||||
else
|
||||
{
|
||||
if (info_verbose)
|
||||
printf_filtered ("End of trace buffer.\n");
|
||||
/* The following will not recurse, since it's special-cased */
|
||||
trace_find_command ("-1", from_tty);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'T':
|
||||
if ((target_tracept = strtol (++reply, &reply, 16)) == -1)
|
||||
|
@ -1604,6 +1679,7 @@ finish_tfind_command (reply, from_tty)
|
|||
T<hexnum> (gives the selected tracepoint number)
|
||||
*/
|
||||
|
||||
/* tfind command */
|
||||
static void
|
||||
trace_find_command (args, from_tty)
|
||||
char *args;
|
||||
|
@ -1668,6 +1744,7 @@ trace_find_command (args, from_tty)
|
|||
error ("Trace can only be run on remote targets.");
|
||||
}
|
||||
|
||||
/* tfind end */
|
||||
static void
|
||||
trace_find_end_command (args, from_tty)
|
||||
char *args;
|
||||
|
@ -1676,6 +1753,7 @@ trace_find_end_command (args, from_tty)
|
|||
trace_find_command ("-1", from_tty);
|
||||
}
|
||||
|
||||
/* tfind none */
|
||||
static void
|
||||
trace_find_none_command (args, from_tty)
|
||||
char *args;
|
||||
|
@ -1684,6 +1762,7 @@ trace_find_none_command (args, from_tty)
|
|||
trace_find_command ("-1", from_tty);
|
||||
}
|
||||
|
||||
/* tfind start */
|
||||
static void
|
||||
trace_find_start_command (args, from_tty)
|
||||
char *args;
|
||||
|
@ -1692,6 +1771,7 @@ trace_find_start_command (args, from_tty)
|
|||
trace_find_command ("0", from_tty);
|
||||
}
|
||||
|
||||
/* tfind pc command */
|
||||
static void
|
||||
trace_find_pc_command (args, from_tty)
|
||||
char *args;
|
||||
|
@ -1718,6 +1798,7 @@ trace_find_pc_command (args, from_tty)
|
|||
error ("Trace can only be run on remote targets.");
|
||||
}
|
||||
|
||||
/* tfind tracepoint command */
|
||||
static void
|
||||
trace_find_tracepoint_command (args, from_tty)
|
||||
char *args;
|
||||
|
@ -1747,13 +1828,12 @@ trace_find_tracepoint_command (args, from_tty)
|
|||
}
|
||||
|
||||
/* TFIND LINE command:
|
||||
*
|
||||
* This command will take a sourceline for argument, just like BREAK
|
||||
* or TRACE (ie. anything that "decode_line_1" can handle).
|
||||
*
|
||||
* With no argument, this command will find the next trace frame
|
||||
* corresponding to a source line OTHER THAN THE CURRENT ONE.
|
||||
*/
|
||||
|
||||
This command will take a sourceline for argument, just like BREAK
|
||||
or TRACE (ie. anything that "decode_line_1" can handle).
|
||||
|
||||
With no argument, this command will find the next trace frame
|
||||
corresponding to a source line OTHER THAN THE CURRENT ONE. */
|
||||
|
||||
static void
|
||||
trace_find_line_command (args, from_tty)
|
||||
|
@ -1846,6 +1926,7 @@ trace_find_line_command (args, from_tty)
|
|||
error ("Trace can only be run on remote targets.");
|
||||
}
|
||||
|
||||
/* tfind range command */
|
||||
static void
|
||||
trace_find_range_command (args, from_tty)
|
||||
char *args;
|
||||
|
@ -1887,6 +1968,7 @@ trace_find_range_command (args, from_tty)
|
|||
error ("Trace can only be run on remote targets.");
|
||||
}
|
||||
|
||||
/* tfind outside command */
|
||||
static void
|
||||
trace_find_outside_command (args, from_tty)
|
||||
char *args;
|
||||
|
@ -1928,6 +2010,7 @@ trace_find_outside_command (args, from_tty)
|
|||
error ("Trace can only be run on remote targets.");
|
||||
}
|
||||
|
||||
/* save-tracepoints command */
|
||||
static void
|
||||
tracepoint_save_command (args, from_tty)
|
||||
char *args;
|
||||
|
@ -1985,6 +2068,7 @@ tracepoint_save_command (args, from_tty)
|
|||
return;
|
||||
}
|
||||
|
||||
/* info scope command: list the locals for a scope. */
|
||||
static void
|
||||
scope_info (args, from_tty)
|
||||
char *args;
|
||||
|
@ -2121,6 +2205,7 @@ scope_info (args, from_tty)
|
|||
save_args);
|
||||
}
|
||||
|
||||
/* worker function (cleanup) */
|
||||
static void
|
||||
replace_comma (comma)
|
||||
char *comma;
|
||||
|
@ -2128,6 +2213,7 @@ replace_comma (comma)
|
|||
*comma = ',';
|
||||
}
|
||||
|
||||
/* tdump command */
|
||||
static void
|
||||
trace_dump_command (args, from_tty)
|
||||
char *args;
|
||||
|
@ -2224,11 +2310,7 @@ trace_dump_command (args, from_tty)
|
|||
discard_cleanups (old_cleanups);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static struct cmd_list_element *tfindlist;
|
||||
static struct cmd_list_element *tracelist;
|
||||
|
||||
/* module initialization */
|
||||
void
|
||||
_initialize_tracepoint ()
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue