aboutsummaryrefslogtreecommitdiff
path: root/gdb/gdbserver/server.c
diff options
context:
space:
mode:
authorPedro Alves <palves@redhat.com>2014-04-10 19:22:23 +0100
committerPedro Alves <palves@redhat.com>2014-04-10 17:14:12 +0100
commitd708bcd102465e520c56e8be3ca4c9097dd389cc (patch)
tree01b77a9534e8be1c4952c07f5e4a8be22a9c6ec7 /gdb/gdbserver/server.c
parente4ef1b6c3fee295ab41138bf77a82dff16f1d7c3 (diff)
downloadgdb-d708bcd102465e520c56e8be3ca4c9097dd389cc.zip
gdb-d708bcd102465e520c56e8be3ca4c9097dd389cc.tar.gz
gdb-d708bcd102465e520c56e8be3ca4c9097dd389cc.tar.bz2
Conditional Z1 breakpoint hangs GDBserver.
While trying to fix hbreak2.exp against GDBserver I noticed this... (gdb) hbreak main if 1 Sending packet: $m400580,40#2e...Packet received: e8d2ffffff5dc3554889e54883ec10c745fc00000000eb0eb800000000e8c1ffffff8345fc01817dfce70300007ee9b800000000c9c3662e0f1f840000000000 Sending packet: $m40058f,1#31...Packet received: c7 Hardware assisted breakpoint 1 at 0x40058f: file ../../../src/gdb/testsuite/gdb.base/break-idempotent.c, line 46. Sending packet: $Z1,40058f,1;X3,220127#9b... *hangs forever* The issue is that nothing advances the packet pointer if add_breakpoint_condition either fails to parse the agent expression, or fails to find the breakpoint, resulting in an infinite loop in process_point_options. The latter case should really be fixed by GDBserver tracking GDB Z1 breakpoints in its breakpoint structures like Z0 breakpoints are, but the latter case still needs handling. add_breakpoint_commands has the same issue, though at present I don't know any way to trigger it other than sending a manually cooked packet. Unbelievably, it doesn't look like we have any test that tries setting a conditional hardware breakpoint. Looking at cond-eval-mode.exp, it looks like the file was meant to actually test something, but it's mostly empty today. This patch adds tests that tries all sorts of conditional breakpoints and watchpoints. The test hangs/fails without the GDBserver fix. Tested on x86_64 Fedora 17. gdb/gdbserver/ 2014-04-10 Pedro Alves <palves@redhat.com> * mem-break.c (add_breakpoint_condition, add_breakpoint_commands): Check if the condition or command is NULL before checking if the breakpoint is known. On success, return true. * mem-break.h (add_breakpoint_condition): Document return. (add_breakpoint_commands): Add describing comment. * server.c (skip_to_semicolon): New function. (process_point_options): Use it. gdb/testsuite/ 2014-04-10 Pedro Alves <palves@redhat.com> * gdb.base/cond-eval-mode.c: New file. * gdb.base/cond-eval-mode.exp: Use standard_testfile. Adjust prepare_for_testing to build the new file. Check result of runto_main. (test_break, test_watch): New procedures. (top level): Use them.
Diffstat (limited to 'gdb/gdbserver/server.c')
-rw-r--r--gdb/gdbserver/server.c18
1 files changed, 14 insertions, 4 deletions
diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c
index 9868af6..8317ac0 100644
--- a/gdb/gdbserver/server.c
+++ b/gdb/gdbserver/server.c
@@ -3350,6 +3350,15 @@ main (int argc, char *argv[])
}
}
+/* Skip PACKET until the next semi-colon (or end of string). */
+
+static void
+skip_to_semicolon (char **packet)
+{
+ while (**packet != '\0' && **packet != ';')
+ (*packet)++;
+}
+
/* Process options coming from Z packets for *point at address
POINT_ADDR. PACKET is the packet buffer. *PACKET is updated
to point to the first char after the last processed option. */
@@ -3376,7 +3385,8 @@ process_point_options (CORE_ADDR point_addr, char **packet)
/* Conditional expression. */
if (debug_threads)
debug_printf ("Found breakpoint condition.\n");
- add_breakpoint_condition (point_addr, &dataptr);
+ if (!add_breakpoint_condition (point_addr, &dataptr))
+ skip_to_semicolon (&dataptr);
}
else if (strncmp (dataptr, "cmds:", strlen ("cmds:")) == 0)
{
@@ -3385,15 +3395,15 @@ process_point_options (CORE_ADDR point_addr, char **packet)
debug_printf ("Found breakpoint commands %s.\n", dataptr);
persist = (*dataptr == '1');
dataptr += 2;
- add_breakpoint_commands (point_addr, &dataptr, persist);
+ if (add_breakpoint_commands (point_addr, &dataptr, persist))
+ skip_to_semicolon (&dataptr);
}
else
{
fprintf (stderr, "Unknown token %c, ignoring.\n",
*dataptr);
/* Skip tokens until we find one that we recognize. */
- while (*dataptr && *dataptr != ';')
- dataptr++;
+ skip_to_semicolon (&dataptr);
}
}
*packet = dataptr;