---
testsuite/Makefile.in | 2
testsuite/configure | 3
testsuite/configure.ac | 2
testsuite/gdb.remote/Makefile.in | 16
testsuite/gdb.remote/autoload-breakpoints-test.c | 543 +++++++++++++++++++++
testsuite/gdb.remote/autoload-breakpoints-test.exp | 97 +++
6 files changed, 660 insertions(+), 3 deletions(-)
--- a/testsuite/Makefile.in
+++ b/testsuite/Makefile.in
@@ -37,7 +37,7 @@ ALL_SUBDIRS = gdb.ada gdb.arch gdb.asm g
gdb.dwarf2 gdb.fortran gdb.gdb gdb.hp \
gdb.java gdb.linespec gdb.mi gdb.modula2 gdb.multi \
gdb.objc gdb.opencl gdb.opt gdb.pascal gdb.python gdb.server \
- gdb.stabs gdb.reverse gdb.threads gdb.trace gdb.xml \
+ gdb.stabs gdb.reverse gdb.threads gdb.trace gdb.xml gdb.remote \
$(SUBDIRS)
EXPECT = `if [ -f $${rootme}/../../expect/expect ] ; then \
--- a/testsuite/configure
+++ b/testsuite/configure
@@ -3448,7 +3448,7 @@ done
-ac_config_files="$ac_config_files Makefile gdb.ada/Makefile gdb.arch/Makefile gdb.asm/Makefile gdb.base/Makefile gdb.cell/Makefile gdb.cp/Makefile gdb.disasm/Makefile gdb.dwarf2/Makefile gdb.fortran/Makefile gdb.go/Makefile gdb.server/Makefile gdb.java/Makefile gdb.hp/Makefile gdb.hp/gdb.objdbg/Makefile gdb.hp/gdb.base-hp/Makefile gdb.hp/gdb.aCC/Makefile gdb.hp/gdb.compat/Makefile gdb.hp/gdb.defects/Makefile gdb.linespec/Makefile gdb.mi/Makefile gdb.modula2/Makefile gdb.multi/Makefile gdb.objc/Makefile gdb.opencl/Makefile gdb.opt/Makefile gdb.pascal/Makefile gdb.python/Makefile gdb.reverse/Makefile gdb.stabs/Makefile gdb.threads/Makefile gdb.trace/Makefile gdb.xml/Makefile"
+ac_config_files="$ac_config_files Makefile gdb.ada/Makefile gdb.arch/Makefile gdb.asm/Makefile gdb.base/Makefile gdb.cell/Makefile gdb.cp/Makefile gdb.disasm/Makefile gdb.dwarf2/Makefile gdb.fortran/Makefile gdb.go/Makefile gdb.server/Makefile gdb.java/Makefile gdb.hp/Makefile gdb.hp/gdb.objdbg/Makefile gdb.hp/gdb.base-hp/Makefile gdb.hp/gdb.aCC/Makefile gdb.hp/gdb.compat/Makefile gdb.hp/gdb.defects/Makefile gdb.linespec/Makefile gdb.mi/Makefile gdb.modula2/Makefile gdb.multi/Makefile gdb.objc/Makefile gdb.opencl/Makefile gdb.opt/Makefile gdb.pascal/Makefile gdb.python/Makefile gdb.reverse/Makefile gdb.stabs/Makefile gdb.threads/Makefile gdb.trace/Makefile gdb.xml/Makefile gdb.remote/Makefile"
cat >confcache <<\_ACEOF
# This file is a shell script that caches the results of configure
@@ -4181,6 +4181,7 @@ do
"gdb.threads/Makefile") CONFIG_FILES="$CONFIG_FILES gdb.threads/Makefile" ;;
"gdb.trace/Makefile") CONFIG_FILES="$CONFIG_FILES gdb.trace/Makefile" ;;
"gdb.xml/Makefile") CONFIG_FILES="$CONFIG_FILES gdb.xml/Makefile" ;;
+ "gdb.remote/Makefile") CONFIG_FILES="$CONFIG_FILES gdb.remote/Makefile" ;;
*) as_fn_error "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
esac
--- a/testsuite/configure.ac
+++ b/testsuite/configure.ac
@@ -98,4 +98,4 @@ AC_OUTPUT([Makefile \
gdb.mi/Makefile gdb.modula2/Makefile gdb.multi/Makefile \
gdb.objc/Makefile gdb.opencl/Makefile gdb.opt/Makefile gdb.pascal/Makefile \
gdb.python/Makefile gdb.reverse/Makefile gdb.stabs/Makefile \
- gdb.threads/Makefile gdb.trace/Makefile gdb.xml/Makefile])
+ gdb.threads/Makefile gdb.trace/Makefile gdb.xml/Makefile gdb.remote/Makefile])
--- /dev/null
+++ b/testsuite/gdb.remote/Makefile.in
@@ -0,0 +1,16 @@
+VPATH = @srcdir@
+srcdir = @srcdir@
+
+EXECUTABLES = autoload-breakpoints-test
+
+MISCELLANEOUS =
+
+all info install-info dvi install uninstall installcheck check:
+ @echo "Nothing to be done for $@..."
+
+clean mostlyclean:
+ rm -f *~ *.o *.x *.ci *.sl a.out core
+ rm -f $(EXECUTABLES) $(MISCELLANEOUS)
+
+distclean maintainer-clean realclean: clean
+ rm -f Makefile config.status config.log site.* gdb.log gdb.sum
--- /dev/null
+++ b/testsuite/gdb.remote/autoload-breakpoints-test.c
@@ -0,0 +1,543 @@
+/* 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 . */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+int listen_desc = -1;
+int remote_desc = -1;
+int loop_test_begin = 0;
+int got_pkg = 0;
+int inside_send_notificationasync_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 '$':
+ case '%':
+ bufw = buf;
+ len = 0;
+ csum = 0;
+ if (!inside_send_notificationasync_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 is_notif)
+{
+ int buf_size = strlen (buf);
+ char *send_buf = alloca(buf_size + 4);
+ unsigned char csum = 0;
+ int i;
+
+ if (is_notif)
+ send_buf[0] = '%';
+ else
+ 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);
+ }
+}
+
+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];
+ int head;
+
+ if (got_pkg)
+ return;
+
+ inside_send_notificationasync_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, 1);
+ head = readchar();
+ readchar_buffer_put (head);
+ if (head != '%')
+ {
+ printf ("Send %s, but GDB didn't answer it.\n", rspbuf);
+ return;
+ }
+ read_rsppkg (rspbuf, 4096);
+
+ if (strcmp(rspbuf, "OK") != 0)
+ {
+ printf ("Try to remove breakpoint %d got error: %s\n", e->id, rspbuf);
+ exit (-1);
+ }
+ inside_send_notificationasync_pkg = 0;
+ printf ("Done.\n");
+}
+
+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->str);
+}
+
+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", 0);
+ break;
+
+ case 'g':
+ case 'm':
+ case 'p':
+ if (sizeof (long) == 8)
+ write_rsppkg ("0000000000000000", 0);
+ else
+ write_rsppkg ("00000000", 0);
+ 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", 0);
+ break;
+
+ case 'c':
+ if (loop_test_begin)
+ {
+ got_pkg = 0;
+ b_list_remove_one ();
+ alarm (1);
+ }
+ write_rsppkg ("S05", 0);
+ break;
+
+ case 'q':
+ if (strncmp("qSupported", rspbuf, strlen ("qSupported")) == 0)
+ write_rsppkg ("NotificationAsync+;AutoloadBreakpoints+;", 0);
+ 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, 0);
+ cur_b = cur_b->prev;
+ }
+ else
+ write_rsppkg ("l", 0);
+ }
+ else if (strncmp("qBsP", rspbuf, 4) == 0)
+ {
+ if (cur_con)
+ {
+ set_autoload_b_con (rspbuf, 4096, cur_id, cur_con);
+ write_rsppkg(rspbuf, 0);
+ cur_con = NULL;
+ }
+ else if (cur_com)
+ {
+ set_autoload_b_com (rspbuf, 4096, cur_id, cur_com);
+ write_rsppkg(rspbuf, 0);
+ cur_com = cur_com->next;
+ }
+ else if (cur_b)
+ {
+ cur_id = cur_b->id;
+ set_autoload_b (rspbuf, 4096, cur_b);
+ write_rsppkg(rspbuf, 0);
+ cur_con = cur_b->condition;
+ cur_com = cur_b->commands;
+ cur_b = cur_b->prev;
+ }
+ else
+ write_rsppkg ("l", 0);
+ }
+ else
+ write_rsppkg ("", 0);
+ break;
+
+ case 'k':
+ exit (0);
+ break;
+
+ default:
+ write_rsppkg ("", 0);
+ 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 .
+
+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 notification-async\n"
+gdb_expect 10 {
+ -re "Undefined show remote command" {
+ fail "NotificationAsync support"
+ return
+ }
+ -re "Support for the `NotificationAsync' packet is auto-detected" {
+ pass "NotificationAsync 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."