--- testsuite/Makefile.in | 2 testsuite/configure | 3 testsuite/configure.ac | 2 testsuite/gdb.remote/Makefile.in | 17 + testsuite/gdb.remote/reportasync-test.c | 371 ++++++++++++++++++++++++++++++ testsuite/gdb.remote/reportasync-test.exp | 80 ++++++ 6 files changed, 472 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,17 @@ +VPATH = @srcdir@ +srcdir = @srcdir@ + +EXECUTABLES = reportasync-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/reportasync-test.c @@ -0,0 +1,371 @@ +/* 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_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; +} + +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"); + exit (-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) + { + if (loop_test_begin) + write (remote_desc, "^" , 1); + 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'; + return 0; + } + } + 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; + } + } + + return 0; +} + +void +write_rsppkg (unsigned char *buf) +{ + int buf_size; + char *send_buf; + unsigned char csum = 0; + int i; + + buf_size = strlen (buf); + send_buf = alloca(buf_size + 4); + + 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; +} + +int +send_reportasync_pkg (void) +{ + unsigned char rspbuf[4096]; + static int sig_count = 0; + + if (got_pkg) + return -1; + + if (shake_hands ()) + return -1; + + inside_send_reportasync_pkg = 1; + sig_count ++; + snprintf (rspbuf, 4096, "SIG from remote %d", sig_count); + write_rsppkg (rspbuf); + read_rsppkg (rspbuf, 4096); + inside_send_reportasync_pkg = 0; + return 0; +} + +static void +handle_alrm(int signo) +{ + send_reportasync_pkg (); + alarm (1); +} + +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)) + { + printf ("Remote port closed.\n"); + exit (-1); + } + + 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 'c': + sleep (1); + got_pkg = 0; + if (send_reportasync_pkg ()) + { + printf ("Try to send ReportAsync package got error.\n"); + exit (-1); + } + sleep (1); + write_rsppkg ("S05"); + alarm (1); + loop_test_begin = 1; + break; + + case 'q': + if (strncmp("qSupported", rspbuf, strlen ("qSupported")) == 0) + write_rsppkg ("ReportAsync+"); + else + { + if (loop_test_begin) + write (remote_desc, "^" , 1); + write_rsppkg (""); + } + break; + + case 'k': + exit (0); + break; + + default: + write_rsppkg (""); + break; + } + + } + + return 0; +} --- /dev/null +++ b/testsuite/gdb.remote/reportasync-test.exp @@ -0,0 +1,80 @@ +# 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 "reportasync-test" +set srcfile ${testfile}.c +set binfile ${objdir}/${subdir}/${testfile} + +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } { + untested reportasync-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" + } +} + +#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 "continue" ".*0x00000000 in ?? ().*" "Continue with AsyncReport first time" + +exec sleep 2 + +gdb_test "set debug remote 1" ".*" + +gdb_test "x 0" ".*Ignore a ReportAsync shake hands package because waiting a ack.*" "Fake shake hands package first time" + +gdb_test "set debug remote 0" ".*" + +gdb_test "continue" ".*0x00000000 in ?? ().*" "Continue with AsyncReport second time" + +gdb_test "set debug remote 1" ".*" + +gdb_test "tstatus" ".*Ignore a ReportAsync shake hands package because waiting a response.*" "Fake shake hands package second time" +