[PATCH] Add autoload-breakpoints [6/7] autoload-breakpoints test

Hui Zhu hui_zhu@mentor.com
Sat Mar 17 08:53:00 GMT 2012


Hi,

Same with ReportAsync test, I add a special gdb stub to test the 
function of autoload-breakpoints.

Thanks,
Hui

2012-03-17  Hui Zhu  <hui_zhu@mentor.com>

	* gdb.remote/Makefile.in (EXECUTABLES): Add
	autoload-breakpoints-test.
	* gdb.remote/autoload-breakpoints-test.c: New file.
	* gdb.remote/autoload-breakpoints-test.exp: New file.
-------------- next part --------------
---
 testsuite/gdb.remote/Makefile.in                   |    2 
 testsuite/gdb.remote/autoload-breakpoints-test.c   |  549 +++++++++++++++++++++
 testsuite/gdb.remote/autoload-breakpoints-test.exp |   97 +++
 3 files changed, 647 insertions(+), 1 deletion(-)

--- a/testsuite/gdb.remote/Makefile.in
+++ b/testsuite/gdb.remote/Makefile.in
@@ -1,7 +1,7 @@
 VPATH = @srcdir@
 srcdir = @srcdir@
 
-EXECUTABLES   = reportasync-test
+EXECUTABLES   = reportasync-test autoload-breakpoints-test
 
 MISCELLANEOUS =
 
--- /dev/null
+++ b/testsuite/gdb.remote/autoload-breakpoints-test.c
@@ -0,0 +1,549 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2012 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+
+int listen_desc = -1;
+int remote_desc = -1;
+int loop_test_begin = 0;
+int got_pkg = 0;
+int inside_send_reportasync_pkg = 0;
+
+#define INT2CHAR(h)	((h) > 9 ? (h) + 'a' - 10 : (h) + '0')
+
+int
+hex2int(unsigned char hex, int *i)
+{
+  if ((hex >= '0') && (hex <= '9'))
+    {
+      *i = hex - '0';
+      return 1;
+    }
+  if ((hex >= 'a') && (hex <= 'f'))
+    {
+      *i = hex - 'a' + 10;
+      return 1;
+    }
+  if ((hex >= 'A') && (hex <= 'F'))
+    {
+      *i = hex - 'A' + 10;
+      return 1;
+    }
+
+  return 0;
+}
+
+/* Convert number NIB to a hex digit.  */
+
+static int
+tohex (int nib)
+{
+  if (nib < 10)
+    return '0' + nib;
+  else
+    return 'a' + nib - 10;
+}
+
+int
+bin2hex (char *bin, char *hex, int count)
+{
+  int i;
+
+  /* May use a length, or a nul-terminated string as input.  */
+  if (count == 0)
+    count = strlen ((char *) bin);
+
+  for (i = 0; i < count; i++)
+    {
+      *hex++ = tohex ((*bin >> 4) & 0xf);
+      *hex++ = tohex (*bin++ & 0xf);
+    }
+  *hex = 0;
+  return i;
+}
+
+int readchar_buffer_ch = -1;
+
+int
+readchar (void)
+{
+  int ret;
+  unsigned char ch;
+
+  if (readchar_buffer_ch != -1)
+    {
+      ch = readchar_buffer_ch;
+      readchar_buffer_ch = -1;
+      return ch;
+    }
+
+  if (remote_desc < 0)
+    {
+      printf ("Remote socket is closed.\n");
+      return -1;
+    }
+
+  ret = read(remote_desc, &ch, 1);
+  if (ret == 0)
+    {
+      printf ("Remote socket is closed.\n");
+      close (remote_desc);
+      remote_desc = -1;
+      return -1;
+    }
+  else if (ret < 0)
+    {
+      perror ("Read got error");
+      exit (-errno);
+    }
+
+  return (int) ch;
+}
+
+void
+readchar_buffer_put (int ch)
+{
+  readchar_buffer_ch = ch;
+}
+
+void
+accept_remote (void)
+{
+  struct sockaddr_in sockaddr;
+  socklen_t tmp;
+
+  tmp = sizeof (sockaddr);
+  remote_desc = accept (listen_desc, (struct sockaddr *) &sockaddr, &tmp);
+  if (remote_desc == -1)
+    perror ("Accept failed");
+
+  /* Enable TCP keep alive process. */
+  tmp = 1;
+  setsockopt (remote_desc, SOL_SOCKET, SO_KEEPALIVE,
+	      (char *) &tmp, sizeof (tmp));
+
+  /* Tell TCP not to delay small packets.  This greatly speeds up
+     interactive response. */
+  tmp = 1;
+  setsockopt (remote_desc, IPPROTO_TCP, TCP_NODELAY,
+	      (char *) &tmp, sizeof (tmp));
+}
+
+int
+read_rsppkg(unsigned char *buf, int max_size)
+{
+  int len = 0;
+  unsigned char *bufw = NULL;
+  unsigned char	csum = 0;
+
+  while (1)
+    {
+      int ch = readchar();
+      if (ch < 0)
+	return -1;
+
+      switch (ch)
+        {
+	case '$':
+	  bufw = buf;
+	  len = 0;
+	  csum = 0;
+	  if (!inside_send_reportasync_pkg)
+	    got_pkg = 1;
+	  break;
+
+	case '#':
+	  if (bufw)
+	    {
+	      int c1, c2;
+
+	      c1 = readchar();
+	      if (c1 < 0)
+		return -1;
+	      c2 = readchar();
+	      if (c2 < 0)
+		return -1;
+	      if (!hex2int (c1, &c1) || !hex2int (c2, &c2)
+		  || csum != (c1 << 4) + c2)
+		write (remote_desc, "-" , 1);
+	      else
+		{
+		  write (remote_desc, "+" , 1);
+		  bufw[0] = '\0';
+		  goto out;
+		}
+	    }
+	  break;
+
+	default:
+	  if (bufw)
+	    {
+	      if (len >= max_size)
+	        {
+		  printf ("The GDB rsp package is too big.\n");
+		  exit (-1);
+		}
+
+	      bufw[0] = (unsigned char) ch;
+	      csum += bufw[0];
+	      len ++;
+	      bufw ++;
+	    }
+	  break;
+	}
+    }
+
+out:
+  return 0;
+}
+
+void
+write_rsppkg (unsigned char *buf)
+{
+  int buf_size = strlen (buf);
+  char *send_buf = alloca(buf_size + 4);
+  unsigned char	csum = 0;
+  int i;
+
+  send_buf[0] = '$';
+
+  memcpy(send_buf + 1, buf, buf_size);
+
+  for (i = 0; i < buf_size; i ++)
+    csum += buf[i];
+
+  send_buf[buf_size + 1] = '#';
+  send_buf[buf_size + 2] = INT2CHAR(csum >> 4);
+  send_buf[buf_size + 3] = INT2CHAR(csum & 0x0f);
+
+  if (write (remote_desc, send_buf, buf_size + 4) != buf_size + 4)
+    {
+      perror ("Write got error");
+      exit (-errno);
+    }
+}
+
+int
+shake_hands (void)
+{
+  int ch;
+
+  write (remote_desc, "^" , 1);
+  ch = readchar();
+  if (ch != '^')
+    {
+      if (ch > 0)
+	readchar_buffer_put (ch);
+      return -1;
+    }
+  return 0;
+}
+
+struct uploaded_bpcmd
+  {
+    struct uploaded_bpcmd *next;
+    char *str;
+  };
+
+struct uploaded_bp
+  {
+    struct uploaded_bp *prev;
+    int removed;
+    int id;
+    char enable;
+    char *addr_string;
+    char type;
+    char *ignore_count;
+    char *condition;
+    struct uploaded_bpcmd *commands;
+  };
+
+struct uploaded_bp *b_list = NULL;
+int cur_id;
+struct uploaded_bp *cur_b = NULL;
+char *cur_con = NULL;
+struct uploaded_bpcmd *cur_com = NULL;
+
+void
+b_list_add (char enable, char *addr, char type, char *ignore_count)
+{
+  struct uploaded_bp *new = calloc (1, sizeof (struct uploaded_bp));
+  static int id = 0;
+
+  if (!new)
+    {
+      printf ("Calloc failed\n");
+      exit (-1);
+    }
+
+  new->addr_string = malloc (3 + strlen (addr) + 1);
+  if (!new->addr_string)
+    {
+      printf ("Strudp failed\n");
+      exit (-1);
+    }
+  sprintf (new->addr_string, "*0x%s", addr);
+
+  new->ignore_count = strdup (ignore_count);
+  if (!new->ignore_count)
+    {
+      printf ("Strudp failed\n");
+      exit (-1);
+    }
+
+  id++;
+  new->id = id;
+  new->enable = enable;
+  new->type = type;
+
+  new->prev =  b_list;
+  b_list = new;
+
+  printf ("Add breakpoint %d.\n", id);
+}
+
+void
+b_list_remove_one (void)
+{
+  struct uploaded_bp *e;
+  unsigned char rspbuf[4096];
+
+  if (got_pkg)
+    return;
+
+  if (shake_hands ())
+    return;
+
+  inside_send_reportasync_pkg = 1;
+  for (e = b_list; e; e = e->prev)
+    {
+      if (!e->removed)
+	{
+	  e->removed = 1;
+	  break;
+	}
+    }
+
+  if (!e)
+    {
+      printf ("Do not have breakpoint to delete.\n");
+      exit(-1);
+    }
+
+  printf ("Try to remove breakpoint %d.\n", e->id);
+
+  snprintf (rspbuf, 4096, "QBDP%d:R", e->id);
+  write_rsppkg (rspbuf);
+  read_rsppkg (rspbuf, 4096);
+
+  if (strcmp(rspbuf, "OK"))
+    {
+      printf ("Try to remove breakpoint %d got error: %s\n", e->id, rspbuf);
+      exit (-1);
+    }
+  inside_send_reportasync_pkg = 0;
+}
+
+void
+set_autoload_b(char *buf, int size, struct uploaded_bp *b)
+{
+  char *hex = alloca (strlen (b->addr_string) * 2);
+  int end = bin2hex (b->addr_string, hex, 0);
+
+  hex[end * 2] = '\0';
+  snprintf(buf, size, "%x:%c:%s:%c:%s", b->id, b->enable, hex,
+	   b->type, b->ignore_count);
+}
+
+void
+set_autoload_b_con(char *buf, int size, int id, char *con)
+{
+  snprintf(buf, size, "%x:O:%s",id, con);
+}
+
+void
+set_autoload_b_com(char *buf, int size, int id, struct uploaded_bpcmd *com)
+{
+  snprintf(buf, size, "%x:C:%s", id, com);
+}
+
+static void
+handle_alrm(int signo)
+{
+  b_list_remove_one ();
+}
+
+int
+main(int argc, char *argv[])
+{
+  socklen_t tmp;
+  struct sockaddr_in sockaddr;
+  unsigned char rspbuf[4096];
+
+  if (signal (SIGALRM, handle_alrm) == SIG_ERR)
+    {
+      perror("Can't call signal");
+      exit(-errno);
+    }
+
+  /* Init listen_desc.  */
+  if (argc != 2)
+    {
+      printf ("Usage: %s port\n", argv[0]);
+      exit (-1);
+    }
+  listen_desc = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP);
+  if (listen_desc == -1)
+    {
+      perror ("Can't open socket");
+      exit (-errno);
+    }
+  setsockopt (listen_desc, SOL_SOCKET, SO_REUSEADDR, (char *) &tmp,
+	      sizeof (tmp));
+  sockaddr.sin_family = PF_INET;
+  sockaddr.sin_port = htons (atoi(argv[1]));
+  sockaddr.sin_addr.s_addr = INADDR_ANY;
+  if (bind (listen_desc, (struct sockaddr *) &sockaddr, sizeof (sockaddr))
+      || listen (listen_desc, 1))
+    {
+      printf ("Can't bind port\n");
+      exit (-errno);
+    }
+  else
+    printf ("Listening on %d\n", atoi(argv[1]));
+
+  accept_remote ();
+
+  while (1)
+    {
+      got_pkg = 0;
+      if (read_rsppkg (rspbuf, 4096))
+        {
+	  loop_test_begin = 1;
+	  accept_remote ();
+	  continue;
+	}
+
+      switch (rspbuf[0])
+	{
+	case '?':
+	  write_rsppkg ("S05");
+	  break;
+
+	case 'g':
+	case 'm':
+	case 'p':
+	  if (sizeof (long) == 8)
+	    write_rsppkg ("0000000000000000");
+	  else
+	    write_rsppkg ("00000000");
+	  break;
+
+	case 'Z':
+	  if (!loop_test_begin && strncmp("Z0,", rspbuf, 3) == 0)
+	    {
+	      char *addr = rspbuf + 3;
+	      int i;
+
+	      for (i = 0; addr[i] != ',' && addr[i] != '\0'; i++)
+		;
+	      addr[i] = '\0';
+	      b_list_add ('E', addr, 'S', "0");
+	    }
+	case 'z':
+	  write_rsppkg ("OK");
+	  break;
+
+	case 'c':
+	  if (loop_test_begin)
+	    {
+	      got_pkg = 0;
+	      b_list_remove_one ();
+	      alarm (1);
+	    }
+	  write_rsppkg ("S05");
+	  break;
+
+	case 'q':
+	  if (strncmp("qSupported", rspbuf, strlen ("qSupported")) == 0)
+	    write_rsppkg ("ReportAsync+;AutoloadBreakpoints+;");
+	  else if (strncmp("qBfP", rspbuf, 4) == 0)
+	    {
+	      if (b_list)
+		{
+		  cur_b = b_list;
+		  cur_con = cur_b->condition;
+		  cur_com = cur_b->commands;
+		  cur_id = cur_b->id;
+		  set_autoload_b (rspbuf, 4096, cur_b);
+		  write_rsppkg(rspbuf);
+		  cur_b = cur_b->prev;
+		}
+	      else
+		write_rsppkg ("l");
+	    }
+	  else if (strncmp("qBsP", rspbuf, 4) == 0)
+	    {
+	      if (cur_con)
+		{
+		  set_autoload_b_con (rspbuf, 4096, cur_id, cur_con);
+		  write_rsppkg(rspbuf);
+		  cur_con = NULL;
+		}
+	      else if (cur_com)
+		{
+		  set_autoload_b_com (rspbuf, 4096, cur_id, cur_com);
+		  write_rsppkg(rspbuf);
+		  cur_com = cur_com->next;
+		}
+	      else if (cur_b)
+		{
+		  cur_id = cur_b->id;
+		  set_autoload_b (rspbuf, 4096, cur_b);
+		  write_rsppkg(rspbuf);
+		  cur_con = cur_b->condition;
+		  cur_com = cur_b->commands;
+		  cur_b = cur_b->prev;
+		}
+	      else
+		write_rsppkg ("l");
+	    }
+	  else
+	    write_rsppkg ("");
+	  break;
+
+	case 'k':
+	  exit (0);
+	  break;
+
+	default:
+	  write_rsppkg ("");
+	  break;
+	}
+
+    }
+
+  return 0;
+}
--- /dev/null
+++ b/testsuite/gdb.remote/autoload-breakpoints-test.exp
@@ -0,0 +1,97 @@
+# This testcase is part of GDB, the GNU debugger.
+
+# Copyright 2012 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+load_lib gdbserver-support.exp
+
+set testfile "autoload-breakpoints-test"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+
+if  { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
+    untested autoload-breakpoints-test.exp
+    return -1
+}
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+
+# Make sure we're disconnected, in case we're testing with an
+# extended-remote board, therefore already connected.
+gdb_test "disconnect" ".*"
+
+send_gdb "show remote report-async\n"
+gdb_expect 10 {
+    -re "Undefined show remote command" {
+	fail "ReportAsync support"
+	return
+    }
+    -re "Support for the `ReportAsync' packet is auto-detected" {
+	pass "ReportAsync support"
+    }
+}
+
+send_gdb "show remote autoload-breakpoints-packet\n"
+gdb_expect 10 {
+    -re "Undefined show remote command" {
+	fail "Autoload breakpoints support"
+	return
+    }
+    -re "Support for the `AutoloadBreakpoints' packet is auto-detected" {
+	pass "Autoload breakpoints support"
+    }
+}
+
+#Let GDB connect to test server
+set portnum 2345
+while 1 {
+    set server_spawn_id [remote_spawn target "$binfile $portnum"]
+    expect {
+	    -i $server_spawn_id
+	    -notransfer
+	    -re "Listening on" {}
+	    -re "Can't bind port" {
+		incr portnum
+		continue
+	    }
+    }
+    break
+}
+gdb_target_cmd "remote" ":$portnum"
+
+gdb_test "set breakpoint autoload merge" ".*"
+
+gdb_test "b *0x10" ".*"
+gdb_test "b *0x20" ".*"
+gdb_test "continue" ".*"
+gdb_test "set confirm off" ".*"
+gdb_test "delete" ".*"
+gdb_test "disconnect" ".*"
+
+gdb_target_cmd "remote" ":$portnum"
+gdb_test "info breakpoints" ".*autoload-breakpoint 2.*autoload-breakpoint 1."
+gdb_test "disconnect" ".*"
+
+gdb_target_cmd "remote" ":$portnum"
+gdb_test "info breakpoints" ".*autoload-breakpoint 2.*autoload-breakpoint 1."
+gdb_test "disconnect" ".*"
+
+gdb_target_cmd "remote" ":$portnum"
+
+gdb_test "continue" ".*"
+exec sleep 2
+gdb_test "info breakpoints" "No breakpoints or watchpoints."


More information about the Gdb-patches mailing list