[RFC] Target-defined breakpoints (autoload breakpoints) [7/9] target-defined breakpoint sync function
Hui Zhu
hui_zhu@mentor.com
Wed Oct 24 15:04:00 GMT 2012
This patch add the sync function to target-defined breakpoints. All this function is depend on the notification (include the extend that prev patch add).
Following is a introduce of sync process:
1) When the remote target wants to send a sync packet to GDB, it will send a notification to GDB.
2) GDB handle_notification will get this packet. Handler will get the status of GDB from argument flags. When GDB in NOTIFICATION_ASYNC and NOTIFICATION_RECV_FOREVER, handle this packet because change the breakpoints will not affect anything.
If GDB is in other status, the breakpoints cannot be changed because GDB just want to change them with itself. So just drop this packet.
3) In the remote target part, after it send the notification. It will wait
the reply packet from GDB.
If the packet is the notification packet, handle it as the reply from GDB.
If not, the packet that sent to GDB is dropped. Then the target need handle this packet as it is.
Thanks,
Hui
2012-10-24 Hui Zhu <hui_zhu@mentor.com>
* breakpoint.c (breakpoint_add_command_line_next): New variable.
(breakpoint_add_command_line, breakpoint_add_command,
handle_target_defined_breakpoint_cmd_to_breakpoints,
parse_target_defined_breakpoint_definition_to_breakpoints): New function.
* remote.c (inside_target_defined_breakpoint_handler): New variable.
(handle_notification): Handle QBDP packet.
(remote_insert_breakpoint, remote_remove_breakpoint,
remote_insert_hw_breakpoint, remote_remove_hw_breakpoint): Check
inside_target_defined_breakpoint_handler.
-------------- next part --------------
--- a/breakpoint.c
+++ b/breakpoint.c
@@ -1217,6 +1217,34 @@ static_tracepoints_here (CORE_ADDR addr)
return found;
}
+static char *breakpoint_add_command_line_next = NULL;
+
+static char *
+breakpoint_add_command_line (void)
+{
+ char *ret = breakpoint_add_command_line_next;
+ breakpoint_add_command_line_next = NULL;
+
+ return ret;
+}
+
+static void
+breakpoint_add_command (struct breakpoint *b, char *cmd)
+{
+ struct command_line *newline, *last;
+
+ breakpoint_add_command_line_next = cmd;
+ newline = read_command_lines_1 (breakpoint_add_command_line, 1, NULL, NULL);
+ if (b->commands && b->commands->commands)
+ {
+ for (last = b->commands->commands; last->next; last = last->next)
+ ;
+ last->next = newline;
+ }
+ else
+ breakpoint_set_commands (b, newline);
+}
+
/* Set the command list of B to COMMANDS. If breakpoint is tracepoint,
validate that only allowed commands are included. */
@@ -15939,6 +15967,187 @@ parse_target_defined_breakpoint_definiti
}
}
break;
+ }
+
+ return 0;
+}
+
+static void
+handle_target_defined_breakpoint_cmd_to_breakpoints (char cmd, struct breakpoint *b)
+{
+ switch (cmd)
+ {
+ case 'E':
+ enable_breakpoint (b);
+ break;
+ case 'D':
+ disable_breakpoint (b);
+ break;
+ case 'R':
+ delete_breakpoint (b);
+ break;
+ }
+}
+
+/* Get target-defined breakpoints cmd from LINE. */
+
+int
+parse_target_defined_breakpoint_definition_to_breakpoints (char *line)
+{
+ ULONGEST id;
+ char cmd;
+ struct breakpoint *b, *btmp;
+
+ /* Get id. */
+ line = unpack_varlen_hex (line, &id);
+ if (line[0] != ':')
+ return -1;
+ if (strlen (line) < 2)
+ return -1;
+ line += 1;
+
+ cmd = line[0];
+ if (line[1] == ':')
+ line += 2;
+ else
+ line += 1;
+
+ if ((cmd == 'C' || cmd == 'O') && id == 0)
+ return -1;
+
+ ALL_BREAKPOINTS_SAFE (b, btmp)
+ {
+ int loop_stop = 0;
+
+ if (b->target_defined_id == 0)
+ continue;
+
+ switch (cmd)
+ {
+ case 'E':
+ case 'D':
+ case 'R':
+ if (id == 0)
+ handle_target_defined_breakpoint_cmd_to_breakpoints (cmd, b);
+ else if (b->target_defined_id == (int)id)
+ {
+ if (line[0] != '\0' && cmd != 'R')
+ loop_stop = 1;
+ else
+ {
+ handle_target_defined_breakpoint_cmd_to_breakpoints (cmd, b);
+ return 0;
+ }
+ }
+ break;
+ case 'C':
+ case 'O':
+ if (b->target_defined_id == (int)id)
+ loop_stop = 1;
+ break;
+ default:
+ return -1;
+ break;
+ }
+
+ if (loop_stop)
+ break;
+ }
+
+ if (id == 0)
+ return 0;
+
+ switch (cmd)
+ {
+ case 'E':
+ case 'D':
+ {
+ char *b_addr_hex;
+ char *b_addr;
+ enum bptype b_type;
+ ULONGEST ignore_num;
+ int end;
+
+ b_addr_hex = line;
+ line = strchr (line, ':');
+ if (!line)
+ return -1;
+ line[0] = '\0';
+ line += 1;
+ b_addr = alloca (strlen (b_addr_hex) / 2);
+ end = hex2bin (b_addr_hex, (gdb_byte *) b_addr,
+ strlen (b_addr_hex) / 2);
+ b_addr[end] = '\0';
+
+ if (line[0] == 'S')
+ b_type = bp_breakpoint;
+ else if (line[0] == 'H')
+ b_type = bp_hardware_breakpoint;
+ else
+ return -1;
+ if (line[1] != ':' || line[2] == '\0')
+ return -1;
+ line += 2;
+
+ unpack_varlen_hex (line, &ignore_num);
+
+ if (b)
+ {
+ if (b->type == b_type && strcmp (b->addr_string, b_addr) == 0)
+ {
+ /* b is same with the breakpoint from target. */
+ handle_target_defined_breakpoint_cmd_to_breakpoints (cmd, b);
+ b->target_defined_inserted = 1;
+ return 0;
+ }
+ else
+ {
+ /* Set b to other target_defined_id. */
+ b->target_defined_id = target_defined_breakpoints_get_id ();
+ b->target_defined_inserted = 0;
+ }
+ }
+
+ /* Create new breakpoint. */
+ create_breakpoint (get_current_arch (),
+ b_addr,
+ NULL, -1, 0, 0, 0,
+ b_type,
+ (int) ignore_num,
+ pending_break_support,
+ &bkpt_breakpoint_ops,
+ 0,
+ (cmd == 'E') ? 1 : 0,
+ 0, CREATE_BREAKPOINT_FLAGS_INSERTED);
+ b = get_breakpoint (breakpoint_count);
+ b->target_defined_id = (int)id;
+ b->target_defined_inserted = 1;
+ }
+ break;
+ case 'R':
+ return -1;
+ break;
+ case 'C':
+ case 'O':
+ if (!b)
+ return -1;
+ {
+ char buf[strlen(line)/2 + 1];
+ int end;
+
+ end = hex2bin (line, (gdb_byte *) buf, strlen (line) / 2);
+ buf[end] = '\0';
+ if (cmd == 'O')
+ set_breakpoint_condition (b, buf, 0);
+ else
+ {
+ if (end == 0)
+ breakpoint_set_commands (b, NULL);
+ else
+ breakpoint_add_command (b, buf);
+ }
+ }
+ break;
}
return 0;
--- a/remote.c
+++ b/remote.c
@@ -6816,6 +6816,8 @@ remote_read_bytes (CORE_ADDR memaddr, gd
#define NOTIFICATION_RECV_FOREVER 0x4
#define NOTIFICATION_ASYNC 0x8
+static int inside_target_defined_breakpoint_handler = 0;
+
static void
handle_notification (char *buf, unsigned int flags)
{
@@ -6852,6 +6854,31 @@ handle_notification (char *buf, unsigned
fprintf_unfiltered (gdb_stdlog, "stop notification captured\n");
}
}
+ else if (strncmp (buf, "QBDP:", 5) == 0)
+ {
+ struct cleanup *old_chain;
+
+ if ((flags != NOTIFICATION_ASYNC)
+ && (flags != NOTIFICATION_RECV_FOREVER))
+ {
+ if (remote_debug)
+ fprintf_unfiltered (gdb_stdlog,
+ "drop a qbdp packet because flags is %x.\n",
+ flags);
+ return;
+ }
+
+ old_chain = make_cleanup_restore_integer
+ (&inside_target_defined_breakpoint_handler);
+
+ inside_target_defined_breakpoint_handler = 1;
+ if (parse_target_defined_breakpoint_definition_to_breakpoints
+ (buf + strlen ("QBDP:")) == 0)
+ putpkt_binary_1 ("OK", strlen ("OK"), 1);
+ else
+ putpkt_binary_1 ("E01", strlen ("E01"), 1);
+ do_cleanups (old_chain);
+ }
else
/* We ignore notifications we don't recognize, for compatibility
with newer stubs. */
@@ -8045,6 +8072,9 @@ static int
remote_insert_breakpoint (struct gdbarch *gdbarch,
struct bp_target_info *bp_tgt)
{
+ if (inside_target_defined_breakpoint_handler)
+ return 0;
+
/* Try the "Z" s/w breakpoint packet if it is not already disabled.
If it succeeds, then set the support to PACKET_ENABLE. If it
fails, and the user has explicitly requested the Z support then
@@ -8103,6 +8133,9 @@ remote_remove_breakpoint (struct gdbarch
CORE_ADDR addr = bp_tgt->placed_address;
struct remote_state *rs = get_remote_state ();
+ if (inside_target_defined_breakpoint_handler)
+ return 0;
+
if (remote_protocol_packets[PACKET_Z0].support != PACKET_DISABLE)
{
char *p = rs->buf;
@@ -8295,6 +8328,9 @@ remote_insert_hw_breakpoint (struct gdba
char *p, *endbuf;
char *message;
+ if (inside_target_defined_breakpoint_handler)
+ return 0;
+
/* The length field should be set to the size of a breakpoint
instruction, even though we aren't inserting one ourselves. */
@@ -8354,6 +8390,9 @@ remote_remove_hw_breakpoint (struct gdba
char *p = rs->buf;
char *endbuf = rs->buf + get_remote_packet_size ();
+ if (inside_target_defined_breakpoint_handler)
+ return 0;
+
if (remote_protocol_packets[PACKET_Z1].support == PACKET_DISABLE)
return -1;
More information about the Gdb-patches
mailing list