From 48cb2d85819efcb448e7b635e0a5da776f5bfd8c Mon Sep 17 00:00:00 2001 From: Vladimir Prus Date: Mon, 3 Aug 2009 12:39:01 +0000 Subject: [PATCH] Implement -break-commands * breakpoint.c (get_breakpoint, breakpoint_set_commands): New. (commands_command): Use breakpoint_set_commands. * breakpoint.h (get_breakpoint, breakpoint_set_commands): Declare. * mi/mi-cmds.h (mi_cmd_break_commands): New. * mi/mi-cmds.c: Register -break-commands. * mi/mi-cmd-break.c (mi_cmd_break_commands, mi_read_next_line) (mi_command_line_array, mi_command_line_array_cnt) (mi_command_line_array_ptr): New. --- gdb/ChangeLog | 15 ++++++++++ gdb/breakpoint.c | 30 ++++++++++++++++--- gdb/breakpoint.h | 5 ++++ gdb/doc/ChangeLog | 5 ++++ gdb/doc/gdb.texinfo | 32 +++++++++++++++++++- gdb/mi/mi-cmd-break.c | 50 +++++++++++++++++++++++++++++++ gdb/mi/mi-cmds.c | 1 + gdb/mi/mi-cmds.h | 1 + gdb/testsuite/ChangeLog | 6 ++++ gdb/testsuite/gdb.mi/mi-break.exp | 26 ++++++++++++++++ gdb/testsuite/lib/mi-support.exp | 13 ++++---- 11 files changed, 173 insertions(+), 11 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 57b8b9e2ea4..4bc40b4fbec 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,18 @@ +2009-08-03 Jim Ingham + Vladimir Prus + + Implement -break-commands + + * breakpoint.c (get_breakpoint, breakpoint_set_commands): New. + (commands_command): Use breakpoint_set_commands. + * breakpoint.h (get_breakpoint, breakpoint_set_commands): Declare. + + * mi/mi-cmds.h (mi_cmd_break_commands): New. + * mi/mi-cmds.c: Register -break-commands. + * mi/mi-cmd-break.c (mi_cmd_break_commands, mi_read_next_line) + (mi_command_line_array, mi_command_line_array_cnt) + (mi_command_line_array_ptr): New. + 2009-08-03 Jim Ingham Vladimir Prus diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index 2e598e421ee..f3940e1f642 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -562,6 +562,20 @@ get_number_or_range (char **pp) return last_retval; } +/* Return the breakpoint with the specified number, or NULL + if the number does not refer to an existing breakpoint. */ + +struct breakpoint * +get_breakpoint (int num) +{ + struct breakpoint *b; + + ALL_BREAKPOINTS (b) + if (b->number == num) + return b; + + return NULL; +} /* condition N EXP -- set break condition of breakpoint N to EXP. */ @@ -626,6 +640,17 @@ condition_command (char *arg, int from_tty) error (_("No breakpoint number %d."), bnum); } +/* Set the command list of B to COMMANDS. */ + +void +breakpoint_set_commands (struct breakpoint *b, struct command_line *commands) +{ + free_command_lines (&b->commands); + b->commands = commands; + breakpoints_changed (); + observer_notify_breakpoint_modified (b->number); +} + static void commands_command (char *arg, int from_tty) { @@ -655,10 +680,7 @@ commands_command (char *arg, int from_tty) struct cleanup *cleanups = make_cleanup (xfree, tmpbuf); l = read_command_lines (tmpbuf, from_tty, 1); do_cleanups (cleanups); - free_command_lines (&b->commands); - b->commands = l; - breakpoints_changed (); - observer_notify_breakpoint_modified (b->number); + breakpoint_set_commands (b, l); return; } error (_("No breakpoint number %d."), bnum); diff --git a/gdb/breakpoint.h b/gdb/breakpoint.h index d8fe047c38b..d93c6b664ab 100644 --- a/gdb/breakpoint.h +++ b/gdb/breakpoint.h @@ -840,6 +840,8 @@ extern int get_number (char **); extern int get_number_or_range (char **); +extern struct breakpoint *get_breakpoint (int num); + /* The following are for displays, which aren't really breakpoints, but here is as good a place as any for them. */ @@ -855,6 +857,9 @@ extern void disable_breakpoint (struct breakpoint *); extern void enable_breakpoint (struct breakpoint *); +extern void breakpoint_set_commands (struct breakpoint *b, + struct command_line *commands); + /* Clear the "inserted" flag in all breakpoints. */ extern void mark_breakpoints_out (void); diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog index dedf3fe11f4..91a51564989 100644 --- a/gdb/doc/ChangeLog +++ b/gdb/doc/ChangeLog @@ -1,3 +1,8 @@ +2009-08-03 Vladimir Prus + + * gdb.texinfo (GDB/MI Breakpoint Commands): Document + -break-commands. + 2009-07-31 Ulrich Weigand * gdb.texinfo (Cell Broadband Engine SPU architecture): Document the diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index fab05fced0e..f95e307d416 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -21492,11 +21492,41 @@ line="5",times="0",ignore="3"@}]@} @ignore @subheading The @code{-break-catch} Command @findex -break-catch +@end ignore @subheading The @code{-break-commands} Command @findex -break-commands -@end ignore +@subsubheading Synopsis + +@smallexample + -break-commands @var{number} [ @var{command1} ... @var{commandN} ] +@end smallexample + +Specifies the CLI commands that should be executed when breakpoint +@var{number} is hit. The parameters @var{command1} to @var{commandN} +are the commands. If no command is specified, any previously-set +commands are cleared. @xref{Break Commands}. Typical use of this +functionality is tracing a program, that is, printing of values of +some variables whenever breakpoint is hit and then continuing. + +@subsubheading @value{GDBN} Command + +The corresponding @value{GDBN} command is @samp{commands}. + +@subsubheading Example + +@smallexample +(gdb) +-break-insert main +^done,bkpt=@{number="1",type="breakpoint",disp="keep", +enabled="y",addr="0x000100d0",func="main",file="hello.c", +fullname="/home/foo/hello.c",line="5",times="0"@} +(gdb) +-break-commands 1 "print v" "continue" +^done +(gdb) +@end smallexample @subheading The @code{-break-condition} Command @findex -break-condition diff --git a/gdb/mi/mi-cmd-break.c b/gdb/mi/mi-cmd-break.c index 445c53ebeea..9ab8f2df775 100644 --- a/gdb/mi/mi-cmd-break.c +++ b/gdb/mi/mi-cmd-break.c @@ -252,3 +252,53 @@ mi_cmd_break_watch (char *command, char **argv, int argc) error (_("mi_cmd_break_watch: Unknown watchpoint type.")); } } + +/* The mi_read_next_line consults these variable to return successive + command lines. While it would be clearer to use a closure pointer, + it is not expected that any future code will use read_command_lines_1, + therefore no point of overengineering. */ + +static char **mi_command_line_array; +static int mi_command_line_array_cnt; +static int mi_command_line_array_ptr; + +static char * +mi_read_next_line () +{ + if (mi_command_line_array_ptr == mi_command_line_array_cnt) + return NULL; + else + return mi_command_line_array[mi_command_line_array_ptr++]; +} + +void +mi_cmd_break_commands (char *command, char **argv, int argc) +{ + struct command_line *break_command; + char *endptr; + int bnum; + struct breakpoint *b; + + if (argc < 1) + error ("USAGE: %s [ [...]]", command); + + bnum = strtol (argv[0], &endptr, 0); + if (endptr == argv[0]) + error ("breakpoint number argument \"%s\" is not a number.", + argv[0]); + else if (*endptr != '\0') + error ("junk at the end of breakpoint number argument \"%s\".", + argv[0]); + + b = get_breakpoint (bnum); + if (b == NULL) + error ("breakpoint %d not found.", bnum); + + mi_command_line_array = argv; + mi_command_line_array_ptr = 1; + mi_command_line_array_cnt = argc; + + break_command = read_command_lines_1 (mi_read_next_line, 0); + breakpoint_set_commands (b, break_command); +} + diff --git a/gdb/mi/mi-cmds.c b/gdb/mi/mi-cmds.c index 49111464b5c..dd3d803851b 100644 --- a/gdb/mi/mi-cmds.c +++ b/gdb/mi/mi-cmds.c @@ -35,6 +35,7 @@ struct mi_cmd mi_cmds[] = { { "break-after", { "ignore", 1 }, NULL }, { "break-condition", { "cond", 1 }, NULL }, + { "break-commands", { NULL, 0 }, mi_cmd_break_commands }, { "break-delete", { "delete breakpoint", 1 }, NULL }, { "break-disable", { "disable breakpoint", 1 }, NULL }, { "break-enable", { "enable breakpoint", 1 }, NULL }, diff --git a/gdb/mi/mi-cmds.h b/gdb/mi/mi-cmds.h index afcba1e4b42..85ad0c4c25b 100644 --- a/gdb/mi/mi-cmds.h +++ b/gdb/mi/mi-cmds.h @@ -37,6 +37,7 @@ typedef void (mi_cmd_argv_ftype) (char *command, char **argv, int argc); /* Function implementing each command */ extern mi_cmd_argv_ftype mi_cmd_break_insert; +extern mi_cmd_argv_ftype mi_cmd_break_commands; extern mi_cmd_argv_ftype mi_cmd_break_watch; extern mi_cmd_argv_ftype mi_cmd_disassemble; extern mi_cmd_argv_ftype mi_cmd_data_evaluate_expression; diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index d1e38f30ec2..32a421bcc9e 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2009-08-03 Vladimir Prus + + * lib/mi-support.exp (mi_list_breakpoints): Make it work. + * gdb.mi/mi-break.exp (test_breakpoint_commands): New. + Call it. + 2009-07-31 Ulrich Weigand * configure.ac: Run gdb.cell tests when appropriate. diff --git a/gdb/testsuite/gdb.mi/mi-break.exp b/gdb/testsuite/gdb.mi/mi-break.exp index 4b8d101b3a1..619727de240 100644 --- a/gdb/testsuite/gdb.mi/mi-break.exp +++ b/gdb/testsuite/gdb.mi/mi-break.exp @@ -197,6 +197,30 @@ proc test_disabled_creation {} { "test disabled creation: cleanup" } +proc test_breakpoint_commands {} { + global line_callee2_body + global hex + global fullname + + mi_create_breakpoint "basics.c:callee2" 7 keep callee2 ".*basics.c" $line_callee2_body $hex \ + "breakpoint commands: insert breakpoint at basics.c:callee2" + + mi_gdb_test "-break-commands 7 \"print 10\" \"continue\"" \ + "\\^done" \ + "breakpoint commands: set commands" + + mi_gdb_test "-break-info 7" \ + "\\^done,BreakpointTable=\{nr_rows=\".\",nr_cols=\".\",hdr=\\\[\{width=\".*\",alignment=\".*\",col_name=\"number\",colhdr=\"Num\"\}.*colhdr=\"Type\".*colhdr=\"Disp\".*colhdr=\"Enb\".*colhdr=\"Address\".*colhdr=\"What\".*\\\],body=\\\[bkpt=\{number=\"7\",type=\"breakpoint\",disp=\"keep\",enabled=\"y\",addr=\"$hex\",func=\"callee2\",file=\".*basics.c\",${fullname},line=\"$line_callee2_body\",times=\"0\",script=\{\"print 10\",\"continue\"\},original-location=\".*\"\}.*\\\]\}" \ + "breakpoint commands: check that commands are set" + + mi_gdb_test "-break-commands 7" \ + "\\^done" \ + "breakpoint commands: clear commands" + + mi_list_breakpoints [list [list 7 "keep" "callee2" "basics.c" "$line_callee2_body" $hex]] \ + "breakpoint commands: check that commands are cleared" +} + test_tbreak_creation_and_listing test_rbreak_creation_and_listing @@ -206,5 +230,7 @@ test_error test_disabled_creation +test_breakpoint_commands + mi_gdb_exit return 0 diff --git a/gdb/testsuite/lib/mi-support.exp b/gdb/testsuite/lib/mi-support.exp index 9b4c464abcb..e6912321d83 100644 --- a/gdb/testsuite/lib/mi-support.exp +++ b/gdb/testsuite/lib/mi-support.exp @@ -1170,21 +1170,22 @@ proc mi_list_breakpoints { expected test } { set body "" set first 1 - foreach item $children { + foreach item $expected { if {$first == 0} { set body "$body," + set first 0 } - set number disp func file line address set number [lindex $item 0] set disp [lindex $item 1] set func [lindex $item 2] - set line [lindex $item 3] - set address [lindex $item 4] - set body "$body,bkpt=\{number=\"$number\",type=\"breakpoint\",disp=\"$disp\",enabled=\"y\",addr=\"$address\",func=\"$func\",file=\"$file\",${fullname},line=\"$line\",times=\"0\",original-location=\".*\"\}" + set file [lindex $item 3] + set line [lindex $item 4] + set address [lindex $item 5] + set body "${body}bkpt=\{number=\"$number\",type=\"breakpoint\",disp=\"$disp\",enabled=\"y\",addr=\"$address\",func=\"$func\",file=\".*$file\",${fullname},line=\"$line\",times=\"0\",original-location=\".*\"\}" set first 0 } - verbose -log "Expecint: 666\\\^done,BreakpointTable=\{nr_rows=\".\",nr_cols=\".\",hdr=\\\[\{width=\".*\",alignment=\".*\",col_name=\"number\",colhdr=\"Num\"\}.*colhdr=\"Type\".*colhdr=\"Disp\".*colhdr=\"Enb\".*colhdr=\"Address\".*colhdr=\"What\".*\\\],body=\\\[$body\\\]\}" \ + verbose -log "Expecting: 666\\\^done,BreakpointTable=\{nr_rows=\".\",nr_cols=\".\",hdr=\\\[\{width=\".*\",alignment=\".*\",col_name=\"number\",colhdr=\"Num\"\}.*colhdr=\"Type\".*colhdr=\"Disp\".*colhdr=\"Enb\".*colhdr=\"Address\".*colhdr=\"What\".*\\\],body=\\\[$body\\\]\}" mi_gdb_test "666-break-list" \ "666\\\^done,BreakpointTable=\{nr_rows=\".\",nr_cols=\".\",hdr=\\\[\{width=\".*\",alignment=\".*\",col_name=\"number\",colhdr=\"Num\"\}.*colhdr=\"Type\".*colhdr=\"Disp\".*colhdr=\"Enb\".*colhdr=\"Address\".*colhdr=\"What\".*\\\],body=\\\[$body\\\]\}" \ $test -- 2.30.2