From: Yao Qi Date: Fri, 18 Aug 2017 08:20:43 +0000 (+0100) Subject: GDBserver self tests X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=6d580b635f8963183540b816b20bb9c240154497;p=binutils-gdb.git GDBserver self tests This patch uses GDB self test in GDBserver. The self tests are run if GDBserver is started with option --selftest. gdb: 2017-08-18 Yao Qi * NEWS: Mention GDBserver's new option "--selftest". * Makefile.in (SFILES): Remove selftest.c, add common/selftest.c. * selftest.c: Move it to common/selftest.c. * selftest.h: Move it to common/selftest.h. * selftest-arch.c (reset): New function. (tests_with_arch): Call reset. gdb/gdbserver: 2017-08-18 Yao Qi * Makefile.in (OBS): Add selftest.o. * configure.ac: AC_DEFINE GDB_SELF_TEST if $development. * configure, config.in: Re-generated. * server.c: Include common/sefltest.h. (captured_main): Handle option --selftest. gdb/testsuite: 2017-08-18 Yao Qi * gdb.server/unittest.exp: New. gdb/doc: 2017-08-18 Yao Qi * gdb.texinfo (Server): Document "--selftest". --- diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 4a0f3e72ebd..2581935a98c 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,12 @@ +2017-08-18 Yao Qi + + * NEWS: Mention GDBserver's new option "--selftest". + * Makefile.in (SFILES): Remove selftest.c, add common/selftest.c. + * selftest.c: Move it to common/selftest.c. + * selftest.h: Move it to common/selftest.h. + * selftest-arch.c (reset): New function. + (tests_with_arch): Call reset. + 2017-08-18 Yao Qi * selftest.c (run_tests): Don't call QUIT. Call debug_printf diff --git a/gdb/Makefile.in b/gdb/Makefile.in index c6e618a5416..85de646a189 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -1178,7 +1178,6 @@ SFILES = \ reverse.c \ rust-exp.y \ rust-lang.c \ - selftest.c \ selftest-arch.c \ sentinel-frame.c \ ser-base.c \ @@ -1244,6 +1243,7 @@ SFILES = \ common/ptid.c \ common/rsp-low.c \ common/run-time-clock.c \ + common/selftest.c \ common/signals.c \ common/signals-state-save-restore.c \ common/vec.c \ diff --git a/gdb/NEWS b/gdb/NEWS index 341e93457bc..4b0a95600fe 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -3,14 +3,19 @@ *** Changes since GDB 8.0 -* On Unix systems, GDBserver now does globbing expansion and variable - substitution in inferior command line arguments. - - This is done by starting inferiors using a shell, like GDB does. - See "set startup-with-shell" in the user manual for how to disable - this from GDB when using "target extended-remote". When using - "target remote", you can disable the startup with shell by using the - new "--no-startup-with-shell" GDBserver command line option. +* New features in the GDB remote stub, GDBserver + + ** New "--selftest" command line option runs some GDBserver self + tests. These self tests are disabled in releases. + + ** On Unix systems, GDBserver now does globbing expansion and variable + substitution in inferior command line arguments. + + This is done by starting inferiors using a shell, like GDB does. + See "set startup-with-shell" in the user manual for how to disable + this from GDB when using "target extended-remote". When using + "target remote", you can disable the startup with shell by using the + new "--no-startup-with-shell" GDBserver command line option. * New remote packets diff --git a/gdb/common/selftest.c b/gdb/common/selftest.c new file mode 100644 index 00000000000..0fb8f2a42c2 --- /dev/null +++ b/gdb/common/selftest.c @@ -0,0 +1,66 @@ +/* GDB self-testing. + Copyright (C) 2016-2017 Free Software Foundation, Inc. + + This file is part of GDB. + + 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 "common-defs.h" +#include "common-exceptions.h" +#include "common-debug.h" +#include "selftest.h" +#include + +namespace selftests +{ + +/* All the tests that have been registered. */ + +static std::vector tests; + +/* See selftest.h. */ + +void +register_test (self_test_function *function) +{ + tests.push_back (function); +} + +/* See selftest.h. */ + +void +run_tests (void) +{ + int failed = 0; + + for (int i = 0; i < tests.size (); ++i) + { + TRY + { + tests[i] (); + } + CATCH (ex, RETURN_MASK_ERROR) + { + ++failed; + debug_printf ("Self test failed: %s\n", ex.message); + } + END_CATCH + + reset (); + } + + debug_printf ("Ran %lu unit tests, %d failed\n", + (long) tests.size (), failed); +} +} // namespace selftests diff --git a/gdb/common/selftest.h b/gdb/common/selftest.h new file mode 100644 index 00000000000..e211c340c1b --- /dev/null +++ b/gdb/common/selftest.h @@ -0,0 +1,52 @@ +/* GDB self-testing. + Copyright (C) 2016-2017 Free Software Foundation, Inc. + + This file is part of GDB. + + 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 . */ + +#ifndef SELFTEST_H +#define SELFTEST_H + +/* A test is just a function that does some checks and throws an + exception if something has gone wrong. */ + +typedef void self_test_function (void); + +namespace selftests +{ + +/* Register a new self-test. */ + +extern void register_test (self_test_function *function); + +/* Run all the self tests. This print a message describing the number + of test and the number of failures. */ + +extern void run_tests (void); + +/* Reset GDB or GDBserver's internal state. */ +extern void reset (); + +} + +/* Check that VALUE is true, and, if not, throw an exception. */ + +#define SELF_CHECK(VALUE) \ + do { \ + if (!(VALUE)) \ + error (_("self-test failed at %s:%d"), __FILE__, __LINE__); \ + } while (0) + +#endif /* SELFTEST_H */ diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog index 8e3e5ce0b0c..32c9425bde8 100644 --- a/gdb/doc/ChangeLog +++ b/gdb/doc/ChangeLog @@ -1,3 +1,7 @@ +2017-08-18 Yao Qi + + * gdb.texinfo (Server): Document "--selftest". + 2017-08-16 Ruslan Kabatsayev * gdb.texinfo (TUI Single Key Mode): Document the new shortcuts in diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 0d39a55656e..620d11de82b 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -20253,6 +20253,15 @@ environment: $ gdbserver --wrapper env LD_PRELOAD=libtest.so -- :2222 ./testprog @end smallexample +@cindex @option{--selftest} +The @option{--selftest} option runs the self tests in @code{gdbserver}: + +@smallexample +$ gdbserver --selftest +Ran 2 unit tests, 0 failed +@end smallexample + +These tests are disabled in release. @subsection Connecting to @code{gdbserver} The basic procedure for connecting to the remote target is: diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog index 0059b913362..04dac06fd3c 100644 --- a/gdb/gdbserver/ChangeLog +++ b/gdb/gdbserver/ChangeLog @@ -1,3 +1,11 @@ +2017-08-18 Yao Qi + + * Makefile.in (OBS): Add selftest.o. + * configure.ac: AC_DEFINE GDB_SELF_TEST if $development. + * configure, config.in: Re-generated. + * server.c: Include common/sefltest.h. + (captured_main): Handle option --selftest. + 2017-08-09 Yao Qi * configure.srv (srv_i386_regobj): Remove i386-avx.o, diff --git a/gdb/gdbserver/Makefile.in b/gdb/gdbserver/Makefile.in index 4e0080ef1e5..6cd0959e64d 100644 --- a/gdb/gdbserver/Makefile.in +++ b/gdb/gdbserver/Makefile.in @@ -258,6 +258,7 @@ OBS = \ regcache.o \ remote-utils.o \ rsp-low.o \ + selftest.o \ server.o \ signals.o \ signals-state-save-restore.o \ diff --git a/gdb/gdbserver/config.in b/gdb/gdbserver/config.in index 34a74434338..5dacbacbed2 100644 --- a/gdb/gdbserver/config.in +++ b/gdb/gdbserver/config.in @@ -8,6 +8,9 @@ /* Define to 1 if using `alloca.c'. */ #undef C_ALLOCA +/* Define if self-testing features should be enabled */ +#undef GDB_SELF_TEST + /* Define to 1 if you have `alloca', as a function or macro. */ #undef HAVE_ALLOCA diff --git a/gdb/gdbserver/configure b/gdb/gdbserver/configure index 35aeabc3141..30aa95b8f1d 100755 --- a/gdb/gdbserver/configure +++ b/gdb/gdbserver/configure @@ -5813,6 +5813,12 @@ fi fi +if $development; then + +$as_echo "#define GDB_SELF_TEST 1" >>confdefs.h + +fi + case ${build_alias} in "") build_noncanonical=${build} ;; *) build_noncanonical=${build_alias} ;; diff --git a/gdb/gdbserver/configure.ac b/gdb/gdbserver/configure.ac index 4ea7913c981..36e21c5002d 100644 --- a/gdb/gdbserver/configure.ac +++ b/gdb/gdbserver/configure.ac @@ -56,6 +56,11 @@ else fi GDB_AC_LIBMCHECK(${libmcheck_default}) +if $development; then + AC_DEFINE(GDB_SELF_TEST, 1, + [Define if self-testing features should be enabled]) +fi + ACX_NONCANONICAL_TARGET ACX_NONCANONICAL_HOST diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c index 38383510e8b..8200aa17c80 100644 --- a/gdb/gdbserver/server.c +++ b/gdb/gdbserver/server.c @@ -40,6 +40,8 @@ #include "job-control.h" #include "environ.h" +#include "common/selftest.h" + /* The environment to pass to the inferior when creating it. */ static gdb_environ our_environ; @@ -3521,6 +3523,7 @@ captured_main (int argc, char *argv[]) volatile int multi_mode = 0; volatile int attach = 0; int was_running; + bool selftest = false; while (*next_arg != NULL && **next_arg == '-') { @@ -3639,6 +3642,8 @@ captured_main (int argc, char *argv[]) startup_with_shell = false; else if (strcmp (*next_arg, "--once") == 0) run_once = 1; + else if (strcmp (*next_arg, "--selftest") == 0) + selftest = true; else { fprintf (stderr, "Unknown argument: %s\n", *next_arg); @@ -3654,7 +3659,8 @@ captured_main (int argc, char *argv[]) port = *next_arg; next_arg++; } - if (port == NULL || (!attach && !multi_mode && *next_arg == NULL)) + if ((port == NULL || (!attach && !multi_mode && *next_arg == NULL)) + && !selftest) { gdbserver_usage (stderr); exit (1); @@ -3670,7 +3676,8 @@ captured_main (int argc, char *argv[]) starting the inferior. Inferiors created in this scenario have stdin,stdout redirected. So do this here before we call start_inferior. */ - remote_prepare (port); + if (port != NULL) + remote_prepare (port); bad_attach = 0; pid = 0; @@ -3711,6 +3718,12 @@ captured_main (int argc, char *argv[]) own_buf = (char *) xmalloc (PBUFSIZ + 1); mem_buf = (unsigned char *) xmalloc (PBUFSIZ); + if (selftest) + { + selftests::run_tests (); + throw_quit ("Quit"); + } + if (pid == 0 && *next_arg != NULL) { int i, n; @@ -4507,3 +4520,14 @@ handle_target_event (int err, gdb_client_data client_data) return 0; } + +#if GDB_SELF_TEST +namespace selftests +{ + +void +reset () +{} + +} // namespace selftests +#endif /* GDB_SELF_TEST */ diff --git a/gdb/selftest-arch.c b/gdb/selftest-arch.c index dfcbe274328..9a19f7688e3 100644 --- a/gdb/selftest-arch.c +++ b/gdb/selftest-arch.c @@ -33,6 +33,14 @@ register_test_foreach_arch (self_test_foreach_arch_function *function) gdbarch_tests.push_back (function); } +void +reset () +{ + /* Clear GDB internal state. */ + registers_changed (); + reinit_frame_cache (); +} + static void tests_with_arch () { @@ -82,9 +90,7 @@ tests_with_arch () } END_CATCH - /* Clear GDB internal state. */ - registers_changed (); - reinit_frame_cache (); + reset (); } } diff --git a/gdb/selftest.c b/gdb/selftest.c deleted file mode 100644 index eb7728b0149..00000000000 --- a/gdb/selftest.c +++ /dev/null @@ -1,66 +0,0 @@ -/* GDB self-testing. - Copyright (C) 2016-2017 Free Software Foundation, Inc. - - This file is part of GDB. - - 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 "defs.h" -#include "selftest.h" -#include - -namespace selftests -{ - -/* All the tests that have been registered. */ - -static std::vector tests; - -/* See selftest.h. */ - -void -register_test (self_test_function *function) -{ - tests.push_back (function); -} - -/* See selftest.h. */ - -void -run_tests (void) -{ - int failed = 0; - - for (int i = 0; i < tests.size (); ++i) - { - TRY - { - tests[i] (); - } - CATCH (ex, RETURN_MASK_ERROR) - { - ++failed; - debug_printf ("Self test failed: %s\n", ex.message); - } - END_CATCH - - /* Clear GDB internal state. */ - registers_changed (); - reinit_frame_cache (); - } - - debug_printf ("Ran %lu unit tests, %d failed\n", - (long) tests.size (), failed); -} -} // namespace selftests diff --git a/gdb/selftest.h b/gdb/selftest.h deleted file mode 100644 index 8a01a5d3c96..00000000000 --- a/gdb/selftest.h +++ /dev/null @@ -1,49 +0,0 @@ -/* GDB self-testing. - Copyright (C) 2016-2017 Free Software Foundation, Inc. - - This file is part of GDB. - - 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 . */ - -#ifndef SELFTEST_H -#define SELFTEST_H - -/* A test is just a function that does some checks and throws an - exception if something has gone wrong. */ - -typedef void self_test_function (void); - -namespace selftests -{ - -/* Register a new self-test. */ - -extern void register_test (self_test_function *function); - -/* Run all the self tests. This print a message describing the number - of test and the number of failures. */ - -extern void run_tests (void); - -} - -/* Check that VALUE is true, and, if not, throw an exception. */ - -#define SELF_CHECK(VALUE) \ - do { \ - if (!(VALUE)) \ - error (_("self-test failed at %s:%d"), __FILE__, __LINE__); \ - } while (0) - -#endif /* SELFTEST_H */ diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 39c49b8d0ea..d188f83cca4 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2017-08-18 Yao Qi + + * gdb.server/unittest.exp: New. + 2017-08-15 Sergio Durigan Junior PR gdb/21954 diff --git a/gdb/testsuite/gdb.server/unittest.exp b/gdb/testsuite/gdb.server/unittest.exp new file mode 100644 index 00000000000..584a23d51c1 --- /dev/null +++ b/gdb/testsuite/gdb.server/unittest.exp @@ -0,0 +1,41 @@ +# This testcase is part of GDB, the GNU debugger. + +# Copyright 2017 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 + +standard_testfile + +if { [skip_gdbserver_tests] } { + return 0 +} + +global server_spawn_id + +set gdbserver [find_gdbserver] +set gdbserver_command "$gdbserver --selftest" + +set server_spawn_id [remote_spawn target $gdbserver_command] + +gdb_expect { + -i $server_spawn_id + -re "Ran $decimal unit tests, 0 failed" { + pass "unit tests" + } + default { + fail "unit tests" + } +}