aboutsummaryrefslogtreecommitdiff
path: root/gdb/gdbserver/server.c
diff options
context:
space:
mode:
authorLuis Machado <luisgpm@br.ibm.com>2012-02-24 15:15:56 +0000
committerLuis Machado <luisgpm@br.ibm.com>2012-02-24 15:15:56 +0000
commit9f3a5c850eddd9e804c20a9c664e90b9e3d14140 (patch)
tree4beed3e5c90d5fcdf9bb8313cf056617828da55f /gdb/gdbserver/server.c
parent9f14eebc6a9d99804ad44f4f6084b7f279f488df (diff)
downloadgdb-9f3a5c850eddd9e804c20a9c664e90b9e3d14140.zip
gdb-9f3a5c850eddd9e804c20a9c664e90b9e3d14140.tar.gz
gdb-9f3a5c850eddd9e804c20a9c664e90b9e3d14140.tar.bz2
2012-02-24 Luis Machado <lgustavo@codesourcery>
* server.c (handle_query): Advertise support for target-side breakpoint condition evaluation. (process_point_options): New function. (process_serial_event): When inserting a breakpoint, check for a target-side condition that should be evaluated. * mem-break.c: Include regcache.h and ax.h. (point_cond_list_t): New data structure. (breakpoint) <cond_list>: New field. (find_gdb_breakpoint_at): Make non-static. (delete_gdb_breakpoint_at): Clear any target-side conditions. (clear_gdb_breakpoint_conditions): New function. (add_condition_to_breakpoint): Likewise. (add_breakpoint_condition): Likewise. (gdb_condition_true_at_breakpoint): Likewise. (gdb_breakpoint_here): Return result directly instead of going through a local variable. * mem-break.h (find_gdb_breakpoint_at): New prototype. (clear_gdb_breakpoint_conditions): Likewise. (add_breakpoint_condition): Likewise. (gdb_condition_true_at_breakpoint): Likewise. * linux-low.c (linux_wait_1): Evaluate target-side breakpoint condition. (need_step_over_p): Take target-side breakpoint condition into consideration.
Diffstat (limited to 'gdb/gdbserver/server.c')
-rw-r--r--gdb/gdbserver/server.c57
1 files changed, 56 insertions, 1 deletions
diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c
index 37dc8d1..e3d1f7c 100644
--- a/gdb/gdbserver/server.c
+++ b/gdb/gdbserver/server.c
@@ -1621,6 +1621,9 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
strcat (own_buf, ";tracenz+");
}
+ /* Support target-side breakpoint conditions. */
+ strcat (own_buf, ";ConditionalBreakpoints+");
+
return;
}
@@ -2825,6 +2828,43 @@ main (int argc, char *argv[])
}
}
+/* 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. */
+
+static void
+process_point_options (CORE_ADDR point_addr, char **packet)
+{
+ char *dataptr = *packet;
+
+ /* Check if data has the correct format. */
+ if (*dataptr != ';')
+ return;
+
+ dataptr++;
+
+ while (*dataptr)
+ {
+ switch (*dataptr)
+ {
+ case 'X':
+ /* Conditional expression. */
+ fprintf (stderr, "Found breakpoint condition.\n");
+ add_breakpoint_condition (point_addr, &dataptr);
+ break;
+ default:
+ /* Unrecognized token, just skip it. */
+ fprintf (stderr, "Unknown token %c, ignoring.\n",
+ *dataptr);
+ }
+
+ /* Skip tokens until we find one that we recognize. */
+ while (*dataptr && *dataptr != 'X' && *dataptr != ';')
+ dataptr++;
+ }
+ *packet = dataptr;
+}
+
/* Event loop callback that handles a serial event. The first byte in
the serial buffer gets us here. We expect characters to arrive at
a brisk pace, so we read the rest of the packet with a blocking
@@ -3147,7 +3187,22 @@ process_serial_event (void)
case '4': /* access watchpoint */
require_running (own_buf);
if (insert && the_target->insert_point != NULL)
- res = (*the_target->insert_point) (type, addr, len);
+ {
+ /* Insert the breakpoint. If it is already inserted, nothing
+ will take place. */
+ res = (*the_target->insert_point) (type, addr, len);
+
+ /* GDB may have sent us a list of *point parameters to be
+ evaluated on the target's side. Read such list here. If we
+ already have a list of parameters, GDB is telling us to drop
+ that list and use this one instead. */
+ if (!res && (type == '0' || type == '1'))
+ {
+ /* Remove previous conditions. */
+ clear_gdb_breakpoint_conditions (addr);
+ process_point_options (addr, &dataptr);
+ }
+ }
else if (!insert && the_target->remove_point != NULL)
res = (*the_target->remove_point) (type, addr, len);
break;