[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