diff options
-rw-r--r-- | gdb/ChangeLog | 11 | ||||
-rw-r--r-- | gdb/breakpoint.c | 23 | ||||
-rw-r--r-- | gdb/cli/cli-script.c | 5 | ||||
-rw-r--r-- | gdb/cli/cli-script.h | 2 |
4 files changed, 34 insertions, 7 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index a7c08e9..985ec69 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,14 @@ +2003-12-21 Jim Blandy <jimb@redhat.com> + + * breakpoint.c (bpstat_do_actions): To ensure that + clear_proceed_status doesn't free the command tree we're + evaluating out from under us, zero the bpstat's pointer to it, and + take care of freeing it ourselves. + * cli/cli-script.c (make_cleanup_free_command_lines): Make this + function externally visible. + * cli/cli-script.h (make_cleanup_free_command_lines): New + declaration. + 2003-12-20 Mark Kettenis <kettenis@gnu.org> * x86-64-tdep.c (x86_64_dwarf_regmap): Map the Return Address to diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index c535add..6a17368 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -1992,7 +1992,6 @@ bpstat_do_actions (bpstat *bsp) { bpstat bs; struct cleanup *old_chain; - struct command_line *cmd; /* Avoid endless recursion if a `source' command is contained in bs->commands. */ @@ -2017,7 +2016,23 @@ top: breakpoint_proceeded = 0; for (; bs != NULL; bs = bs->next) { + struct command_line *cmd; + struct cleanup *this_cmd_tree_chain; + + /* Take ownership of the BSP's command tree, if it has one. + + The command tree could legitimately contain commands like + 'step' and 'next', which call clear_proceed_status, which + frees stop_bpstat's command tree. To make sure this doesn't + free the tree we're executing out from under us, we need to + take ownership of the tree ourselves. Since a given bpstat's + commands are only executed once, we don't need to copy it; we + can clear the pointer in the bpstat, and make sure we free + the tree when we're done. */ cmd = bs->commands; + bs->commands = 0; + this_cmd_tree_chain = make_cleanup_free_command_lines (&cmd); + while (cmd != NULL) { execute_control_command (cmd); @@ -2027,14 +2042,16 @@ top: else cmd = cmd->next; } + + /* We can free this command tree now. */ + do_cleanups (this_cmd_tree_chain); + if (breakpoint_proceeded) /* The inferior is proceeded by the command; bomb out now. The bpstat chain has been blown away by wait_for_inferior. But since execution has stopped again, there is a new bpstat to look at, so start over. */ goto top; - else - free_command_lines (&bs->commands); } do_cleanups (old_chain); } diff --git a/gdb/cli/cli-script.c b/gdb/cli/cli-script.c index cac5408..a8375a3 100644 --- a/gdb/cli/cli-script.c +++ b/gdb/cli/cli-script.c @@ -36,9 +36,6 @@ /* Prototypes for local functions */ -static struct cleanup * - make_cleanup_free_command_lines (struct command_line **arg); - static enum command_control_type recurse_read_control_structure (struct command_line *current_cmd); @@ -1001,7 +998,7 @@ do_free_command_lines_cleanup (void *arg) free_command_lines (arg); } -static struct cleanup * +struct cleanup * make_cleanup_free_command_lines (struct command_line **arg) { return make_cleanup (do_free_command_lines_cleanup, arg); diff --git a/gdb/cli/cli-script.h b/gdb/cli/cli-script.h index 03cb841..fc5c203 100644 --- a/gdb/cli/cli-script.h +++ b/gdb/cli/cli-script.h @@ -47,6 +47,8 @@ extern void print_command_lines (struct ui_out *, extern struct command_line * copy_command_lines (struct command_line *cmds); +struct cleanup *make_cleanup_free_command_lines (struct command_line **arg); + /* Exported to gdb/infrun.c */ extern void execute_user_command (struct cmd_list_element *c, char *args); |