[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