mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-09-23 14:14:56 +08:00
Unify actions and commands
* defs.h (read_command_lines, read_command_lines_1): New parameters validator and closure. * tracepoint.h (struct action_line): Remove. * breakpoint.h (struct breakpoint): Remove the 'actions' field. * defs.h (enum command_control_type): New value while_stepping_control. (struct command_line): Add comments. * breakpoint.c (breakoint_is_tracepoint): New. (breakpoint_set_commands): For tracepoints, verify the commands are permissible. (check_tracepoint_commands): New. (commands_command): Require that each new line is validated using check_tracepoint_command, if we set commands for a tracepoint. (create_tracepoint_from_upload): Likewise. (print_one_breakpoint_location): Remove the code to print actions specifically. (tracepoint_save_command): Relay to print_command_lines. * cli/cli-script.c (process_next_line): New parameters validator and closure. Handle 'while-stepping'. Call validator if not null. (read_command_lines, read_command_lines1): Likewise. (recurse_read_control_structure): New parameters validator and closure. Handle while_stepping_control. (print_command_lines): Handle while-stepping. (get_command_line, define_command, document_command): Adjust. * remote.c (remote_download_tracepoint): Adjust. * tracepoint.c (make_cleanup_free_actions, read_actions) (free_actions, do_free_actions_cleanup): Remove. (trace_actions_command): Use read_command_lines. (validate_actionline): Use error in one place. (encode_actions_1): New, extracted from... (encode_actions): ...this. Also use cleanups for exception safety. (trace_dump_command): Adjust. * mi/mi-cmd-break (mi_cmd_break_commands): Validate commands if it's tracepoint.
This commit is contained in:
315
gdb/tracepoint.c
315
gdb/tracepoint.c
@ -178,7 +178,6 @@ static void add_aexpr (struct collection_list *, struct agent_expr *);
|
||||
static char *mem2hex (gdb_byte *, char *, int);
|
||||
static void add_register (struct collection_list *collection,
|
||||
unsigned int regno);
|
||||
static struct cleanup *make_cleanup_free_actions (struct breakpoint *t);
|
||||
|
||||
extern void send_disconnected_tracing_value (int value);
|
||||
|
||||
@ -450,9 +449,6 @@ tvariables_info (char *args, int from_tty)
|
||||
|
||||
/* ACTIONS functions: */
|
||||
|
||||
/* Prototypes for action-parsing utility commands */
|
||||
static void read_actions (struct breakpoint *);
|
||||
|
||||
/* The three functions:
|
||||
collect_pseudocommand,
|
||||
while_stepping_pseudocommand, and
|
||||
@ -491,138 +487,23 @@ static void
|
||||
trace_actions_command (char *args, int from_tty)
|
||||
{
|
||||
struct breakpoint *t;
|
||||
char tmpbuf[128];
|
||||
char *end_msg = "End with a line saying just \"end\".";
|
||||
struct command_line *l;
|
||||
|
||||
t = get_tracepoint_by_number (&args, 0, 1);
|
||||
if (t)
|
||||
{
|
||||
sprintf (tmpbuf, "Enter actions for tracepoint %d, one per line.",
|
||||
t->number);
|
||||
char *tmpbuf =
|
||||
xstrprintf ("Enter actions for tracepoint %d, one per line.",
|
||||
t->number);
|
||||
struct cleanup *cleanups = make_cleanup (xfree, tmpbuf);
|
||||
|
||||
if (from_tty)
|
||||
{
|
||||
if (deprecated_readline_begin_hook)
|
||||
(*deprecated_readline_begin_hook) ("%s %s\n", tmpbuf, end_msg);
|
||||
else if (input_from_terminal_p ())
|
||||
printf_filtered ("%s\n%s\n", tmpbuf, end_msg);
|
||||
}
|
||||
|
||||
free_actions (t);
|
||||
t->step_count = 0; /* read_actions may set this */
|
||||
read_actions (t);
|
||||
|
||||
if (deprecated_readline_end_hook)
|
||||
(*deprecated_readline_end_hook) ();
|
||||
/* tracepoints_changed () */
|
||||
l = read_command_lines (tmpbuf, from_tty, 1, check_tracepoint_command, t);
|
||||
do_cleanups (cleanups);
|
||||
breakpoint_set_commands (t, l);
|
||||
}
|
||||
/* else just return */
|
||||
}
|
||||
|
||||
/* worker function */
|
||||
static void
|
||||
read_actions (struct breakpoint *t)
|
||||
{
|
||||
char *line;
|
||||
char *prompt1 = "> ", *prompt2 = " > ";
|
||||
char *prompt = prompt1;
|
||||
enum actionline_type linetype;
|
||||
extern FILE *instream;
|
||||
struct action_line *next = NULL, *temp;
|
||||
struct cleanup *old_chain;
|
||||
|
||||
/* Control-C quits instantly if typed while in this loop
|
||||
since it should not wait until the user types a newline. */
|
||||
immediate_quit++;
|
||||
/* FIXME: kettenis/20010823: Something is wrong here. In this file
|
||||
STOP_SIGNAL is never defined. So this code has been left out, at
|
||||
least for quite a while now. Replacing STOP_SIGNAL with SIGTSTP
|
||||
leads to compilation failures since the variable job_control
|
||||
isn't declared. Leave this alone for now. */
|
||||
#ifdef STOP_SIGNAL
|
||||
if (job_control)
|
||||
signal (STOP_SIGNAL, handle_stop_sig);
|
||||
#endif
|
||||
old_chain = make_cleanup_free_actions (t);
|
||||
while (1)
|
||||
{
|
||||
/* Make sure that all output has been output. Some machines may
|
||||
let you get away with leaving out some of the gdb_flush, but
|
||||
not all. */
|
||||
wrap_here ("");
|
||||
gdb_flush (gdb_stdout);
|
||||
gdb_flush (gdb_stderr);
|
||||
|
||||
if (deprecated_readline_hook && instream == NULL)
|
||||
line = (*deprecated_readline_hook) (prompt);
|
||||
else if (instream == stdin && ISATTY (instream))
|
||||
{
|
||||
line = gdb_readline_wrapper (prompt);
|
||||
if (line && *line) /* add it to command history */
|
||||
add_history (line);
|
||||
}
|
||||
else
|
||||
line = gdb_readline (0);
|
||||
|
||||
if (!line)
|
||||
{
|
||||
line = xstrdup ("end");
|
||||
printf_filtered ("end\n");
|
||||
}
|
||||
|
||||
linetype = validate_actionline (&line, t);
|
||||
if (linetype == BADLINE)
|
||||
continue; /* already warned -- collect another line */
|
||||
|
||||
temp = xmalloc (sizeof (struct action_line));
|
||||
temp->next = NULL;
|
||||
temp->action = line;
|
||||
|
||||
if (next == NULL) /* first action for this tracepoint? */
|
||||
t->actions = next = temp;
|
||||
else
|
||||
{
|
||||
next->next = temp;
|
||||
next = temp;
|
||||
}
|
||||
|
||||
if (linetype == STEPPING) /* begin "while-stepping" */
|
||||
{
|
||||
if (prompt == prompt2)
|
||||
{
|
||||
warning (_("Already processing 'while-stepping'"));
|
||||
continue;
|
||||
}
|
||||
else
|
||||
prompt = prompt2; /* change prompt for stepping actions */
|
||||
}
|
||||
else if (linetype == END)
|
||||
{
|
||||
if (prompt == prompt2)
|
||||
{
|
||||
prompt = prompt1; /* end of single-stepping actions */
|
||||
}
|
||||
else
|
||||
{ /* end of actions */
|
||||
if (t->actions->next == NULL)
|
||||
{
|
||||
/* An "end" all by itself with no other actions
|
||||
means this tracepoint has no actions.
|
||||
Discard empty list. */
|
||||
free_actions (t);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef STOP_SIGNAL
|
||||
if (job_control)
|
||||
signal (STOP_SIGNAL, SIG_DFL);
|
||||
#endif
|
||||
immediate_quit--;
|
||||
discard_cleanups (old_chain);
|
||||
}
|
||||
|
||||
/* worker function */
|
||||
enum actionline_type
|
||||
validate_actionline (char **line, struct breakpoint *t)
|
||||
@ -772,8 +653,7 @@ validate_actionline (char **line, struct breakpoint *t)
|
||||
if (*p == '\0' ||
|
||||
(t->step_count = strtol (p, &p, 0)) == 0)
|
||||
{
|
||||
warning (_("'%s': bad step-count; command ignored."), *line);
|
||||
return BADLINE;
|
||||
error (_("'%s': bad step-count."), *line);
|
||||
}
|
||||
return STEPPING;
|
||||
}
|
||||
@ -781,39 +661,10 @@ validate_actionline (char **line, struct breakpoint *t)
|
||||
return END;
|
||||
else
|
||||
{
|
||||
warning (_("'%s' is not a supported tracepoint action."), *line);
|
||||
return BADLINE;
|
||||
error (_("'%s' is not a supported tracepoint action."), *line);
|
||||
}
|
||||
}
|
||||
|
||||
/* worker function */
|
||||
void
|
||||
free_actions (struct breakpoint *t)
|
||||
{
|
||||
struct action_line *line, *next;
|
||||
|
||||
for (line = t->actions; line; line = next)
|
||||
{
|
||||
next = line->next;
|
||||
if (line->action)
|
||||
xfree (line->action);
|
||||
xfree (line);
|
||||
}
|
||||
t->actions = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
do_free_actions_cleanup (void *t)
|
||||
{
|
||||
free_actions (t);
|
||||
}
|
||||
|
||||
static struct cleanup *
|
||||
make_cleanup_free_actions (struct breakpoint *t)
|
||||
{
|
||||
return make_cleanup (do_free_actions_cleanup, t);
|
||||
}
|
||||
|
||||
enum {
|
||||
memrange_absolute = -1
|
||||
};
|
||||
@ -1271,70 +1122,31 @@ stringify_collection_list (struct collection_list *list, char *string)
|
||||
return *str_list;
|
||||
}
|
||||
|
||||
/* Render all actions into gdb protocol. */
|
||||
/*static*/ void
|
||||
encode_actions (struct breakpoint *t, struct bp_location *tloc,
|
||||
char ***tdp_actions, char ***stepping_actions)
|
||||
|
||||
static void
|
||||
encode_actions_1 (struct command_line *action,
|
||||
struct breakpoint *t,
|
||||
struct bp_location *tloc,
|
||||
int frame_reg,
|
||||
LONGEST frame_offset,
|
||||
struct collection_list *collect,
|
||||
struct collection_list *stepping_list)
|
||||
{
|
||||
static char tdp_buff[2048], step_buff[2048];
|
||||
char *action_exp;
|
||||
struct expression *exp = NULL;
|
||||
struct action_line *action;
|
||||
struct command_line *actions;
|
||||
int i;
|
||||
struct value *tempval;
|
||||
struct collection_list *collect;
|
||||
struct cmd_list_element *cmd;
|
||||
struct agent_expr *aexpr;
|
||||
int frame_reg;
|
||||
LONGEST frame_offset;
|
||||
char *default_collect_line = NULL;
|
||||
struct action_line *default_collect_action = NULL;
|
||||
|
||||
clear_collection_list (&tracepoint_list);
|
||||
clear_collection_list (&stepping_list);
|
||||
collect = &tracepoint_list;
|
||||
|
||||
*tdp_actions = NULL;
|
||||
*stepping_actions = NULL;
|
||||
|
||||
gdbarch_virtual_frame_pointer (t->gdbarch,
|
||||
tloc->address, &frame_reg, &frame_offset);
|
||||
|
||||
action = t->actions;
|
||||
|
||||
/* If there are default expressions to collect, make up a collect
|
||||
action and prepend to the action list to encode. Note that since
|
||||
validation is per-tracepoint (local var "xyz" might be valid for
|
||||
one tracepoint and not another, etc), we make up the action on
|
||||
the fly, and don't cache it. */
|
||||
if (*default_collect)
|
||||
{
|
||||
char *line;
|
||||
enum actionline_type linetype;
|
||||
|
||||
default_collect_line = xmalloc (12 + strlen (default_collect));
|
||||
sprintf (default_collect_line, "collect %s", default_collect);
|
||||
line = default_collect_line;
|
||||
linetype = validate_actionline (&line, t);
|
||||
if (linetype != BADLINE)
|
||||
{
|
||||
default_collect_action = xmalloc (sizeof (struct action_line));
|
||||
default_collect_action->next = t->actions;
|
||||
default_collect_action->action = line;
|
||||
action = default_collect_action;
|
||||
}
|
||||
}
|
||||
|
||||
for (; action; action = action->next)
|
||||
{
|
||||
QUIT; /* allow user to bail out with ^C */
|
||||
action_exp = action->action;
|
||||
action_exp = action->line;
|
||||
while (isspace ((int) *action_exp))
|
||||
action_exp++;
|
||||
|
||||
if (*action_exp == '#') /* comment line */
|
||||
return;
|
||||
|
||||
cmd = lookup_cmd (&action_exp, cmdlist, "", -1, 1);
|
||||
if (cmd == 0)
|
||||
error (_("Bad action list item: %s"), action_exp);
|
||||
@ -1505,26 +1317,81 @@ encode_actions (struct breakpoint *t, struct bp_location *tloc,
|
||||
} /* if */
|
||||
else if (cmd_cfunc_eq (cmd, while_stepping_pseudocommand))
|
||||
{
|
||||
collect = &stepping_list;
|
||||
}
|
||||
else if (cmd_cfunc_eq (cmd, end_actions_pseudocommand))
|
||||
{
|
||||
if (collect == &stepping_list) /* end stepping actions */
|
||||
collect = &tracepoint_list;
|
||||
else
|
||||
break; /* end tracepoint actions */
|
||||
/* We check against nested while-stepping when setting
|
||||
breakpoint action, so no way to run into nested
|
||||
here. */
|
||||
gdb_assert (stepping_list);
|
||||
|
||||
encode_actions_1 (action->body_list[0], t, tloc, frame_reg, frame_offset,
|
||||
stepping_list, NULL);
|
||||
}
|
||||
else
|
||||
error (_("Invalid tracepoint command '%s'"), action->line);
|
||||
} /* for */
|
||||
}
|
||||
|
||||
/* Render all actions into gdb protocol. */
|
||||
/*static*/ void
|
||||
encode_actions (struct breakpoint *t, struct bp_location *tloc,
|
||||
char ***tdp_actions, char ***stepping_actions)
|
||||
{
|
||||
static char tdp_buff[2048], step_buff[2048];
|
||||
char *default_collect_line = NULL;
|
||||
struct command_line *actions;
|
||||
struct command_line *default_collect_action = NULL;
|
||||
int frame_reg;
|
||||
LONGEST frame_offset;
|
||||
struct cleanup *back_to;
|
||||
|
||||
back_to = make_cleanup (null_cleanup, NULL);
|
||||
|
||||
clear_collection_list (&tracepoint_list);
|
||||
clear_collection_list (&stepping_list);
|
||||
|
||||
*tdp_actions = NULL;
|
||||
*stepping_actions = NULL;
|
||||
|
||||
gdbarch_virtual_frame_pointer (t->gdbarch,
|
||||
t->loc->address, &frame_reg, &frame_offset);
|
||||
|
||||
actions = t->commands;
|
||||
|
||||
/* If there are default expressions to collect, make up a collect
|
||||
action and prepend to the action list to encode. Note that since
|
||||
validation is per-tracepoint (local var "xyz" might be valid for
|
||||
one tracepoint and not another, etc), we make up the action on
|
||||
the fly, and don't cache it. */
|
||||
if (*default_collect)
|
||||
{
|
||||
char *line;
|
||||
enum actionline_type linetype;
|
||||
|
||||
default_collect_line = xstrprintf ("collect %s", default_collect);
|
||||
make_cleanup (xfree, default_collect_line);
|
||||
|
||||
line = default_collect_line;
|
||||
linetype = validate_actionline (&line, t);
|
||||
if (linetype != BADLINE)
|
||||
{
|
||||
default_collect_action = xmalloc (sizeof (struct command_line));
|
||||
make_cleanup (xfree, default_collect_action);
|
||||
default_collect_action->next = t->commands;
|
||||
default_collect_action->line = line;
|
||||
actions = default_collect_action;
|
||||
}
|
||||
}
|
||||
encode_actions_1 (actions, t, tloc, frame_reg, frame_offset,
|
||||
&tracepoint_list, &stepping_list);
|
||||
|
||||
memrange_sortmerge (&tracepoint_list);
|
||||
memrange_sortmerge (&stepping_list);
|
||||
|
||||
*tdp_actions = stringify_collection_list (&tracepoint_list,
|
||||
*tdp_actions = stringify_collection_list (&tracepoint_list,
|
||||
tdp_buff);
|
||||
*stepping_actions = stringify_collection_list (&stepping_list,
|
||||
*stepping_actions = stringify_collection_list (&stepping_list,
|
||||
step_buff);
|
||||
|
||||
xfree (default_collect_line);
|
||||
xfree (default_collect_action);
|
||||
do_cleanups (back_to);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -2276,7 +2143,7 @@ trace_dump_command (char *args, int from_tty)
|
||||
struct regcache *regcache;
|
||||
struct gdbarch *gdbarch;
|
||||
struct breakpoint *t;
|
||||
struct action_line *action;
|
||||
struct command_line *action;
|
||||
char *action_exp, *next_comma;
|
||||
struct cleanup *old_cleanups;
|
||||
int stepping_actions = 0;
|
||||
@ -2316,12 +2183,12 @@ trace_dump_command (char *args, int from_tty)
|
||||
if (loc->address == regcache_read_pc (regcache))
|
||||
stepping_frame = 0;
|
||||
|
||||
for (action = t->actions; action; action = action->next)
|
||||
for (action = t->commands; action; action = action->next)
|
||||
{
|
||||
struct cmd_list_element *cmd;
|
||||
|
||||
QUIT; /* allow user to bail out with ^C */
|
||||
action_exp = action->action;
|
||||
action_exp = action->line;
|
||||
while (isspace ((int) *action_exp))
|
||||
action_exp++;
|
||||
|
||||
|
Reference in New Issue
Block a user