diff options
author | Doug Evans <xdje42@gmail.com> | 2014-02-09 19:40:01 -0800 |
---|---|---|
committer | Doug Evans <xdje42@gmail.com> | 2014-02-09 19:40:01 -0800 |
commit | ed3ef33944c39d9a3cea72b9a7cef3c20f0e3461 (patch) | |
tree | 4e67d95b8ea65bb36a9cade5e37df2ad6289052e /gdb/testsuite | |
parent | 7026a7c16ee82d39e84823f8cc3097a9a940ddb2 (diff) | |
download | gdb-ed3ef33944c39d9a3cea72b9a7cef3c20f0e3461.zip gdb-ed3ef33944c39d9a3cea72b9a7cef3c20f0e3461.tar.gz gdb-ed3ef33944c39d9a3cea72b9a7cef3c20f0e3461.tar.bz2 |
Add Guile as an extension language.
* NEWS: Mention Guile scripting.
* Makefile.in (SUBDIR_GUILE_OBS): New variable.
(SUBDIR_GUILE_SRCS, SUBDIR_GUILE_DEPS): New variables
(SUBDIR_GUILE_LDFLAGS, SUBDIR_GUILE_CFLAGS): New variables.
(INTERNAL_CPPFLAGS): Add GUILE_CPPFLAGS.
(CLIBS): Add GUILE_LIBS.
(install-guile): New rule.
(guile.o): New rule.
(scm-arch.o, scm-auto-load.o, scm-block.o): New rules.
(scm-breakpoint.o, scm-disasm.o, scm-exception.o): New rules.
(scm-frame.o, scm-iterator.o, scm-lazy-string.o): New rules.
(scm-math.o, scm-objfile.o, scm-ports.o): New rules.
(scm-pretty-print.o, scm-safe-call.o, scm-gsmob.o): New rules.
(scm-string.o, scm-symbol.o, scm-symtab.o): New rules.
(scm-type.o, scm-utils.o, scm-value.o): New rules.
* configure.ac: New option --with-guile.
* configure: Regenerate.
* config.in: Regenerate.
* auto-load.c: Remove #include "python/python.h". Add #include
"gdb/section-scripts.h".
(source_section_scripts): Handle Guile scripts.
(_initialize_auto_load): Add name of Guile objfile script to
scripts-directory help text.
* breakpoint.c (condition_command): Tweak comment to include Scheme.
* breakpoint.h (gdbscm_breakpoint_object): Add forward decl.
(struct breakpoint): New member scm_bp_object.
* defs.h (enum command_control_type): New value guile_control.
* cli/cli-cmds.c: Remove #include "python/python.h". Add #include
"extension.h".
(show_user): Update comment.
(_initialize_cli_cmds): Update help text for "show user". Update help
text for max-user-call-depth.
* cli/cli-script.c: Remove #include "python/python.h". Add #include
"extension.h".
(multi_line_command_p): Add guile_control.
(print_command_lines): Handle guile_control.
(execute_control_command, recurse_read_control_structure): Ditto.
(process_next_line): Recognize "guile" commands.
* disasm.c (gdb_disassemble_info): Make non-static.
* disasm.h: #include "dis-asm.h".
(struct gdbarch): Add forward decl.
(gdb_disassemble_info): Declare.
* extension.c: #include "guile/guile.h".
(extension_languages): Add guile.
(get_ext_lang_defn): Handle EXT_LANG_GDB.
* extension.h (enum extension_language): New value EXT_LANG_GUILE.
* gdbtypes.c (get_unsigned_type_max): New function.
(get_signed_type_minmax): New function.
* gdbtypes.h (get_unsigned_type_max): Declare.
(get_signed_type_minmax): Declare.
* guile/README: New file.
* guile/guile-internal.h: New file.
* guile/guile.c: New file.
* guile/guile.h: New file.
* guile/scm-arch.c: New file.
* guile/scm-auto-load.c: New file.
* guile/scm-block.c: New file.
* guile/scm-breakpoint.c: New file.
* guile/scm-disasm.c: New file.
* guile/scm-exception.c: New file.
* guile/scm-frame.c: New file.
* guile/scm-gsmob.c: New file.
* guile/scm-iterator.c: New file.
* guile/scm-lazy-string.c: New file.
* guile/scm-math.c: New file.
* guile/scm-objfile.c: New file.
* guile/scm-ports.c: New file.
* guile/scm-pretty-print.c: New file.
* guile/scm-safe-call.c: New file.
* guile/scm-string.c: New file.
* guile/scm-symbol.c: New file.
* guile/scm-symtab.c: New file.
* guile/scm-type.c: New file.
* guile/scm-utils.c: New file.
* guile/scm-value.c: New file.
* guile/lib/gdb.scm: New file.
* guile/lib/gdb/boot.scm: New file.
* guile/lib/gdb/experimental.scm: New file.
* guile/lib/gdb/init.scm: New file.
* guile/lib/gdb/iterator.scm: New file.
* guile/lib/gdb/printing.scm: New file.
* guile/lib/gdb/types.scm: New file.
* data-directory/Makefile.in (GUILE_SRCDIR): New variable.
(VPATH): Add $(GUILE_SRCDIR).
(GUILE_DIR): New variable.
(GUILE_INSTALL_DIR, GUILE_FILES): New variables.
(all): Add stamp-guile dependency.
(stamp-guile): New rule.
(clean-guile, install-guile, uninstall-guile): New rules.
(install-only): Add install-guile dependency.
(uninstall): Add uninstall-guile dependency.
(clean): Add clean-guile dependency.
doc/
* Makefile.in (GDB_DOC_FILES): Add guile.texi.
* gdb.texinfo (Auto-loading): Add set/show auto-load guile-scripts.
(Extending GDB): New menu entries Guile, Multiple Extension Languages.
(Guile docs): Include guile.texi.
(objfile-gdbdotext file): Add objfile-gdb.scm.
(dotdebug_gdb_scripts section): Mention Guile scripts.
(Multiple Extension Languages): New node.
* guile.texi: New file.
testsuite/
* configure.ac (AC_OUTPUT): Add gdb.guile.
* configure: Regenerate.
* lib/gdb-guile.exp: New file.
* lib/gdb.exp (get_target_charset): New function.
* gdb.base/help.exp: Update expected output from "apropos apropos".
* gdb.guile/Makefile.in: New file.
* gdb.guile/guile.exp: New file.
* gdb.guile/scm-arch.c: New file.
* gdb.guile/scm-arch.exp: New file.
* gdb.guile/scm-block.c: New file.
* gdb.guile/scm-block.exp: New file.
* gdb.guile/scm-breakpoint.c: New file.
* gdb.guile/scm-breakpoint.exp: New file.
* gdb.guile/scm-disasm.c: New file.
* gdb.guile/scm-disasm.exp: New file.
* gdb.guile/scm-equal.c: New file.
* gdb.guile/scm-equal.exp: New file.
* gdb.guile/scm-error.exp: New file.
* gdb.guile/scm-error.scm: New file.
* gdb.guile/scm-frame-args.c: New file.
* gdb.guile/scm-frame-args.exp: New file.
* gdb.guile/scm-frame-args.scm: New file.
* gdb.guile/scm-frame-inline.c: New file.
* gdb.guile/scm-frame-inline.exp: New file.
* gdb.guile/scm-frame.c: New file.
* gdb.guile/scm-frame.exp: New file.
* gdb.guile/scm-generics.exp: New file.
* gdb.guile/scm-gsmob.exp: New file.
* gdb.guile/scm-iterator.c: New file.
* gdb.guile/scm-iterator.exp: New file.
* gdb.guile/scm-math.c: New file.
* gdb.guile/scm-math.exp: New file.
* gdb.guile/scm-objfile-script-gdb.in: New file.
* gdb.guile/scm-objfile-script.c: New file.
* gdb.guile/scm-objfile-script.exp: New file.
* gdb.guile/scm-objfile.c: New file.
* gdb.guile/scm-objfile.exp: New file.
* gdb.guile/scm-ports.exp: New file.
* gdb.guile/scm-pretty-print.c: New file.
* gdb.guile/scm-pretty-print.exp: New file.
* gdb.guile/scm-pretty-print.scm: New file.
* gdb.guile/scm-section-script.c: New file.
* gdb.guile/scm-section-script.exp: New file.
* gdb.guile/scm-section-script.scm: New file.
* gdb.guile/scm-symbol.c: New file.
* gdb.guile/scm-symbol.exp: New file.
* gdb.guile/scm-symtab-2.c: New file.
* gdb.guile/scm-symtab.c: New file.
* gdb.guile/scm-symtab.exp: New file.
* gdb.guile/scm-type.c: New file.
* gdb.guile/scm-type.exp: New file.
* gdb.guile/scm-value-cc.cc: New file.
* gdb.guile/scm-value-cc.exp: New file.
* gdb.guile/scm-value.c: New file.
* gdb.guile/scm-value.exp: New file.
* gdb.guile/source2.scm: New file.
* gdb.guile/types-module.cc: New file.
* gdb.guile/types-module.exp: New file.
Diffstat (limited to 'gdb/testsuite')
60 files changed, 5238 insertions, 3 deletions
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 8b9ec44..da1348b 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,64 @@ +2014-02-10 Doug Evans <xdje42@gmail.com> + + * configure.ac (AC_OUTPUT): Add gdb.guile. + * configure: Regenerate. + * lib/gdb-guile.exp: New file. + * lib/gdb.exp (get_target_charset): New function. + * gdb.base/help.exp: Update expected output from "apropos apropos". + * gdb.guile/Makefile.in: New file. + * gdb.guile/guile.exp: New file. + * gdb.guile/scm-arch.c: New file. + * gdb.guile/scm-arch.exp: New file. + * gdb.guile/scm-block.c: New file. + * gdb.guile/scm-block.exp: New file. + * gdb.guile/scm-breakpoint.c: New file. + * gdb.guile/scm-breakpoint.exp: New file. + * gdb.guile/scm-disasm.c: New file. + * gdb.guile/scm-disasm.exp: New file. + * gdb.guile/scm-equal.c: New file. + * gdb.guile/scm-equal.exp: New file. + * gdb.guile/scm-error.exp: New file. + * gdb.guile/scm-error.scm: New file. + * gdb.guile/scm-frame-args.c: New file. + * gdb.guile/scm-frame-args.exp: New file. + * gdb.guile/scm-frame-args.scm: New file. + * gdb.guile/scm-frame-inline.c: New file. + * gdb.guile/scm-frame-inline.exp: New file. + * gdb.guile/scm-frame.c: New file. + * gdb.guile/scm-frame.exp: New file. + * gdb.guile/scm-generics.exp: New file. + * gdb.guile/scm-gsmob.exp: New file. + * gdb.guile/scm-iterator.c: New file. + * gdb.guile/scm-iterator.exp: New file. + * gdb.guile/scm-math.c: New file. + * gdb.guile/scm-math.exp: New file. + * gdb.guile/scm-objfile-script-gdb.in: New file. + * gdb.guile/scm-objfile-script.c: New file. + * gdb.guile/scm-objfile-script.exp: New file. + * gdb.guile/scm-objfile.c: New file. + * gdb.guile/scm-objfile.exp: New file. + * gdb.guile/scm-ports.exp: New file. + * gdb.guile/scm-pretty-print.c: New file. + * gdb.guile/scm-pretty-print.exp: New file. + * gdb.guile/scm-pretty-print.scm: New file. + * gdb.guile/scm-section-script.c: New file. + * gdb.guile/scm-section-script.exp: New file. + * gdb.guile/scm-section-script.scm: New file. + * gdb.guile/scm-symbol.c: New file. + * gdb.guile/scm-symbol.exp: New file. + * gdb.guile/scm-symtab-2.c: New file. + * gdb.guile/scm-symtab.c: New file. + * gdb.guile/scm-symtab.exp: New file. + * gdb.guile/scm-type.c: New file. + * gdb.guile/scm-type.exp: New file. + * gdb.guile/scm-value-cc.cc: New file. + * gdb.guile/scm-value-cc.exp: New file. + * gdb.guile/scm-value.c: New file. + * gdb.guile/scm-value.exp: New file. + * gdb.guile/source2.scm: New file. + * gdb.guile/types-module.cc: New file. + * gdb.guile/types-module.exp: New file. + 2014-02-10 Yao Qi <yao@codesourcery.com> PR testsuite/16543 diff --git a/gdb/testsuite/configure b/gdb/testsuite/configure index aa08add..4bf6121 100755 --- a/gdb/testsuite/configure +++ b/gdb/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.btrace/Makefile gdb.cell/Makefile gdb.cp/Makefile gdb.disasm/Makefile gdb.dwarf2/Makefile gdb.dlang/Makefile gdb.fortran/Makefile gdb.gdb/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.perf/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.btrace/Makefile gdb.cell/Makefile gdb.cp/Makefile gdb.disasm/Makefile gdb.dwarf2/Makefile gdb.dlang/Makefile gdb.fortran/Makefile gdb.gdb/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.guile/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.perf/Makefile gdb.python/Makefile gdb.reverse/Makefile gdb.stabs/Makefile gdb.threads/Makefile gdb.trace/Makefile gdb.xml/Makefile" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure @@ -4170,6 +4170,7 @@ do "gdb.hp/gdb.aCC/Makefile") CONFIG_FILES="$CONFIG_FILES gdb.hp/gdb.aCC/Makefile" ;; "gdb.hp/gdb.compat/Makefile") CONFIG_FILES="$CONFIG_FILES gdb.hp/gdb.compat/Makefile" ;; "gdb.hp/gdb.defects/Makefile") CONFIG_FILES="$CONFIG_FILES gdb.hp/gdb.defects/Makefile" ;; + "gdb.guile/Makefile") CONFIG_FILES="$CONFIG_FILES gdb.guile/Makefile" ;; "gdb.linespec/Makefile") CONFIG_FILES="$CONFIG_FILES gdb.linespec/Makefile" ;; "gdb.mi/Makefile") CONFIG_FILES="$CONFIG_FILES gdb.mi/Makefile" ;; "gdb.modula2/Makefile") CONFIG_FILES="$CONFIG_FILES gdb.modula2/Makefile" ;; diff --git a/gdb/testsuite/configure.ac b/gdb/testsuite/configure.ac index b6640bd..fb084d4 100644 --- a/gdb/testsuite/configure.ac +++ b/gdb/testsuite/configure.ac @@ -95,7 +95,7 @@ AC_OUTPUT([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.hp/gdb.defects/Makefile gdb.guile/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.perf/Makefile gdb.python/Makefile gdb.reverse/Makefile gdb.stabs/Makefile \ diff --git a/gdb/testsuite/gdb.base/help.exp b/gdb/testsuite/gdb.base/help.exp index c55eaf6..c4032a5 100644 --- a/gdb/testsuite/gdb.base/help.exp +++ b/gdb/testsuite/gdb.base/help.exp @@ -124,4 +124,4 @@ gdb_test "apropos \\\(print\[\^ bsiedf\\\".-\]\\\)" "handle -- Specify how to ha # test apropos >1 word string gdb_test "apropos handle signal" "handle -- Specify how to handle signals" # test apropos apropos -gdb_test "apropos apropos" "apropos -- Search for commands matching a REGEXP" +gdb_test "apropos apropos" "apropos -- Search for commands matching a REGEXP.*" diff --git a/gdb/testsuite/gdb.guile/Makefile.in b/gdb/testsuite/gdb.guile/Makefile.in new file mode 100644 index 0000000..37f9cb0 --- /dev/null +++ b/gdb/testsuite/gdb.guile/Makefile.in @@ -0,0 +1,17 @@ +VPATH = @srcdir@ +srcdir = @srcdir@ + +EXECUTABLES = + +MISCELLANEOUS = + +all info install-info dvi install uninstall installcheck check: + @echo "Nothing to be done for $@..." + +clean mostlyclean: + -rm -f *~ *.o *.ci + -rm -f *.dwo *.dwp + -rm -f core $(EXECUTABLES) $(MISCELLANEOUS) + +distclean maintainer-clean realclean: clean + -rm -f Makefile config.status config.log gdb.log gdb.sum diff --git a/gdb/testsuite/gdb.guile/guile.exp b/gdb/testsuite/gdb.guile/guile.exp new file mode 100644 index 0000000..2a171fe --- /dev/null +++ b/gdb/testsuite/gdb.guile/guile.exp @@ -0,0 +1,77 @@ +# Copyright (C) 2008-2014 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/>. + +# This file is part of the GDB testsuite. +# It tests basic Guile features. + +load_lib gdb-guile.exp + +# Start with a fresh gdb. +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir + +# Do this instead of the skip_guile_check. +# We want to do some tests when Guile is not present. +gdb_test_multiple "guile (display 23) (newline)" "verify guile support" { + -re "Undefined command.*$gdb_prompt $" { + unsupported "Guile not supported." + return + } + -re "not supported.*$gdb_prompt $" { + unsupported "guile support is disabled" + + # If Guile is not supported, verify that sourcing a guile script + # causes an error. + gdb_test "source $srcdir/$subdir/source2.scm" \ + "Error in sourced command file:.*" \ + "source source2.scm when guile disabled" + return + } + -re "$gdb_prompt $" {} +} + +gdb_install_guile_utils +gdb_install_guile_module + +gdb_test_multiline "multi-line guile command" \ + "guile" "" \ + "(print 23)" "" \ + "end" "= 23" + +gdb_test_multiline "show guile command" \ + "define zzq" "Type commands for definition of .* just \"end\"\\.*" \ + "guile" "" \ + "(print 23)" "" \ + "end" "" \ + "end" "" \ + "show user zzq" "User command \"zzq\":.* guile.*\\(print 23\\).* end" + +gdb_test "source $srcdir/$subdir/source2.scm" "yes" "source source2.scm" + +gdb_test "source -s source2.scm" "yes" "source -s source2.scm" + +gdb_test "guile (print (current-objfile))" "= #f" +gdb_test "guile (print (objfiles))" "= \\(\\)" + +gdb_test_no_output \ + {guile (define x (execute "printf \"%d\", 23" #:to-string #t))} +gdb_test "guile (print x)" "= 23" + +gdb_test_no_output "guile (define a (execute \"help\" #:to-string #t))" \ + "collect help from uiout" + +gdb_test "guile (print a)" "= .*aliases -- Aliases of other commands.*" \ + "verify help to uiout" diff --git a/gdb/testsuite/gdb.guile/scm-arch.c b/gdb/testsuite/gdb.guile/scm-arch.c new file mode 100644 index 0000000..6c0ef92 --- /dev/null +++ b/gdb/testsuite/gdb.guile/scm-arch.c @@ -0,0 +1,22 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2014 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/>. */ + +int +main (void) +{ + return 0; +} diff --git a/gdb/testsuite/gdb.guile/scm-arch.exp b/gdb/testsuite/gdb.guile/scm-arch.exp new file mode 100644 index 0000000..1fcf615 --- /dev/null +++ b/gdb/testsuite/gdb.guile/scm-arch.exp @@ -0,0 +1,33 @@ +# Copyright 2014 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 gdb-guile.exp + +standard_testfile + +if { [prepare_for_testing ${testfile}.exp ${testfile} ${srcfile}] } { + return +} + +# Skip all tests if Guile scripting is not enabled. +if { [skip_guile_tests] } { continue } + +if ![gdb_guile_runto_main] { + return +} + +gdb_scm_test_silent_cmd "guile (define frame (selected-frame))" "get frame" +gdb_scm_test_silent_cmd "guile (define arch (frame-arch frame))" "get arch" +gdb_scm_test_silent_cmd "guile (define pc (frame-pc frame))" "get pc" diff --git a/gdb/testsuite/gdb.guile/scm-block.c b/gdb/testsuite/gdb.guile/scm-block.c new file mode 100644 index 0000000..69c37d0 --- /dev/null +++ b/gdb/testsuite/gdb.guile/scm-block.c @@ -0,0 +1,38 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2010-2014 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/>. */ + +int block_func (void) +{ + int i = 0; + { + double i = 1.0; + double f = 2.0; + { + const char *i = "stuff"; + const char *f = "foo"; + const char *b = "bar"; + return 0; /* Block break here. */ + } + } +} + + +int main (int argc, char *argv[]) +{ + block_func (); + return 0; /* Break at end. */ +} diff --git a/gdb/testsuite/gdb.guile/scm-block.exp b/gdb/testsuite/gdb.guile/scm-block.exp new file mode 100644 index 0000000..32d109a --- /dev/null +++ b/gdb/testsuite/gdb.guile/scm-block.exp @@ -0,0 +1,107 @@ +# Copyright (C) 2010-2014 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/>. + +# This file is part of the GDB testsuite. +# It tests the mechanism exposing blocks to Guile. + +load_lib gdb-guile.exp + +standard_testfile + +if { [prepare_for_testing ${testfile}.exp ${testfile} ${srcfile}] } { + return -1 +} + +# Skip all tests if Guile scripting is not enabled. +if { [skip_guile_tests] } { continue } + +if ![gdb_guile_runto_main] { + return +} + +gdb_breakpoint [gdb_get_line_number "Block break here."] +gdb_continue_to_breakpoint "Block break here." + +# Test initial innermost block. +gdb_scm_test_silent_cmd "guile (define frame (selected-frame))" \ + "Get frame inner" +gdb_scm_test_silent_cmd "guile (define block (frame-block frame))" \ + "Get block inner" +gdb_test "guile (print block)" "#<gdb:block $hex-$hex>" \ + "Check block not #f" +gdb_test "guile (print (block-function block))" \ + "#f" "First anonymous block" +gdb_test "guile (print (block-start block))" \ + "${decimal}" "Check start not #f" +gdb_test "guile (print (block-end block))" \ + "${decimal}" "Check end not #f" + +# Test eq?. +gdb_test "guile (print (eq? (frame-block frame) (frame-block frame)))" \ + "= #t" "Check eq? on same block" +gdb_test "guile (print (eq? block (block-global-block block)))" \ + "= #f" "Check eq? on different blocks" + +# Test global/static blocks. +gdb_scm_test_silent_cmd "guile (define frame (selected-frame))" \ + "Get frame for global/static" +gdb_scm_test_silent_cmd "guile (define block (frame-block frame))" \ + "Get block for global/static" +gdb_test "guile (print (block-global? block))" \ + "#f" "Not a global block" +gdb_test "guile (print (block-static? block))" \ + "#f" "Not a static block" +gdb_scm_test_silent_cmd "guile (define gblock (block-global-block block))" \ + "Get global block" +gdb_scm_test_silent_cmd "guile (define sblock (block-static-block block))" \ + "Get static block" +gdb_test "guile (print (block-global? gblock))" \ + "#t" "Is the global block" +gdb_test "guile (print (block-static? sblock))" \ + "#t" "Is the static block" + +# Move up superblock(s) until we reach function block_func. +gdb_test_no_output "guile (set! block (block-superblock block))" \ + "Get superblock" +gdb_test "guile (print (block-function block))" \ + "#f" "Second anonymous block" +gdb_test_no_output "guile (set! block (block-superblock block))" \ + "Get superblock 2" +gdb_test "guile (print (block-function block))" \ + "block_func" "Print superblock 2 function" + +# Switch frames, then test for main block. +gdb_test "up" ".*" +gdb_scm_test_silent_cmd "guile (define frame (selected-frame))" \ + "Get frame 2" +gdb_scm_test_silent_cmd "guile (define block (frame-block frame))" \ + "Get frame 2's block" +gdb_test "guile (print block)" "#<gdb:block main $hex-$hex>" \ + "Check Frame 2's block not #f" +gdb_test "guile (print (block-function block))" \ + "main" "main block" + +# Test block-valid?. This must always be the last test in this +# testcase as it unloads the object file. +delete_breakpoints +gdb_scm_test_silent_cmd "guile (define frame (selected-frame))" \ + "Get frame for valid?" +gdb_scm_test_silent_cmd "guile (define block (frame-block frame))" \ + "Get frame block for valid?" +gdb_test "guile (print (block-valid? block))" \ + "#t" "Check block validity" +gdb_unload +gdb_test "guile (print (block-valid? block))" \ + "#f" "Check block validity after unload" diff --git a/gdb/testsuite/gdb.guile/scm-breakpoint.c b/gdb/testsuite/gdb.guile/scm-breakpoint.c new file mode 100644 index 0000000..c8dc7f7 --- /dev/null +++ b/gdb/testsuite/gdb.guile/scm-breakpoint.c @@ -0,0 +1,44 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2010-2014 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/>. */ + +int result = 0; + +int multiply (int i) +{ + return i * i; +} + +int add (int i) +{ + return i + i; +} + + +int main (int argc, char *argv[]) +{ + int foo = 5; + int bar = 42; + int i; + + for (i = 0; i < 10; i++) + { + result += multiply (foo); /* Break at multiply. */ + result += add (bar); /* Break at add. */ + } + + return 0; /* Break at end. */ +} diff --git a/gdb/testsuite/gdb.guile/scm-breakpoint.exp b/gdb/testsuite/gdb.guile/scm-breakpoint.exp new file mode 100644 index 0000000..b25d4e0 --- /dev/null +++ b/gdb/testsuite/gdb.guile/scm-breakpoint.exp @@ -0,0 +1,438 @@ +# Copyright (C) 2010-2014 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/>. + +# This file is part of the GDB testsuite. +# It tests the mechanism exposing breakpoints to Guile. + +load_lib gdb-guile.exp + +standard_testfile + +if { [prepare_for_testing ${testfile}.exp ${testfile} ${srcfile}] } { + return -1 +} + +# Skip all tests if Guile scripting is not enabled. +if { [skip_guile_tests] } { continue } + +proc test_bkpt_basic { } { + global srcfile testfile hex decimal + + with_test_prefix "test_bkpt_basic" { + # Start with a fresh gdb. + clean_restart ${testfile} + + if ![gdb_guile_runto_main] { + return + } + + # Initially there should be one breakpoint: main. + + gdb_scm_test_silent_cmd "guile (define blist (breakpoints))" \ + "get breakpoint list 1" + gdb_test "guile (print (car blist))" \ + "<gdb:breakpoint #1 BP_BREAKPOINT enabled noisy hit:1 ignore:0 @main>" \ + "check main breakpoint" + gdb_test "guile (print (breakpoint-location (car blist)))" \ + "main" "check main breakpoint location" + + set mult_line [gdb_get_line_number "Break at multiply."] + gdb_breakpoint ${mult_line} + gdb_continue_to_breakpoint "Break at multiply." + + # Check that the Guile breakpoint code noted the addition of a + # breakpoint "behind the scenes". + gdb_scm_test_silent_cmd "guile (define blist (breakpoints))" \ + "get breakpoint list 2" + gdb_scm_test_silent_cmd "guile (define mult-bkpt (cadr blist))" \ + "get multiply breakpoint" + gdb_test "guile (print (length blist))" \ + "= 2" "check for two breakpoints" + gdb_test "guile (print mult-bkpt)" \ + "= #<gdb:breakpoint #2 BP_BREAKPOINT enabled noisy hit:1 ignore:0 @.*scm-breakpoint.c:$mult_line>" \ + "check multiply breakpoint" + gdb_test "guile (print (breakpoint-location mult-bkpt))" \ + "scm-breakpoint\.c:${mult_line}*" \ + "check multiply breakpoint location" + + # Check hit and ignore counts. + gdb_test "guile (print (breakpoint-hit-count mult-bkpt))" \ + "= 1" "check multiply breakpoint hit count" + gdb_scm_test_silent_cmd "guile (set-breakpoint-ignore-count! mult-bkpt 4)" \ + "set multiply breakpoint ignore count" + gdb_continue_to_breakpoint "Break at multiply." + gdb_test "guile (print (breakpoint-hit-count mult-bkpt))" \ + "= 6" "check multiply breakpoint hit count 2" + gdb_test "print result" \ + " = 545" "check expected variable result after 6 iterations" + + # Test breakpoint is enabled and disabled correctly. + gdb_breakpoint [gdb_get_line_number "Break at add."] + gdb_continue_to_breakpoint "Break at add." + gdb_test "guile (print (breakpoint-enabled? mult-bkpt))" \ + "= #t" "check multiply breakpoint enabled" + gdb_scm_test_silent_cmd "guile (set-breakpoint-enabled! mult-bkpt #f)" \ + "set multiply breakpoint disabled" + gdb_continue_to_breakpoint "Break at add." + gdb_scm_test_silent_cmd "guile (set-breakpoint-enabled! mult-bkpt #t)" \ + "set multiply breakpoint enabled" + gdb_continue_to_breakpoint "Break at multiply." + + # Test other getters and setters. + gdb_scm_test_silent_cmd "guile (define blist (breakpoints))" \ + "get breakpoint list 3" + gdb_test "guile (print (breakpoint-thread mult-bkpt))" \ + "= #f" "check breakpoint thread" + gdb_test "guile (print (= (breakpoint-type mult-bkpt) BP_BREAKPOINT))" \ + "= #t" "check breakpoint type" + gdb_test "guile (print (map breakpoint-number blist))" \ + "= \\(1 2 3\\)" "check breakpoint numbers" + } +} + +proc test_bkpt_deletion { } { + global srcfile testfile hex decimal + + with_test_prefix test_bkpt_deletion { + # Start with a fresh gdb. + clean_restart ${testfile} + + if ![gdb_guile_runto_main] { + return + } + + # Test breakpoints are deleted correctly. + set deltst_location [gdb_get_line_number "Break at multiply."] + set end_location [gdb_get_line_number "Break at end."] + gdb_scm_test_silent_cmd "guile (define dp1 (create-breakpoint! \"$deltst_location\"))" \ + "create deltst breakpoint" + gdb_breakpoint [gdb_get_line_number "Break at end."] + gdb_scm_test_silent_cmd "guile (define del-list (breakpoints))" \ + "get breakpoint list 4" + gdb_test "guile (print (length del-list))" \ + "= 3" "number of breakpoints before delete" + gdb_continue_to_breakpoint "Break at multiply." \ + ".*/$srcfile:$deltst_location.*" + gdb_scm_test_silent_cmd "guile (breakpoint-delete! dp1)" \ + "delete breakpoint" + gdb_test "guile (print (breakpoint-number dp1))" \ + "ERROR: .*: Invalid object: <gdb:breakpoint> in position 1: #<gdb:breakpoint #2>.*" \ + "check breakpoint invalidated" + gdb_scm_test_silent_cmd "guile (set! del-list (breakpoints))" \ + "get breakpoint list 5" + gdb_test "guile (print (length del-list))" \ + "= 2" "number of breakpoints after delete" + gdb_continue_to_breakpoint "Break at end." ".*/$srcfile:$end_location.*" + } +} + +proc test_bkpt_cond_and_cmds { } { + global srcfile testfile hex decimal + + with_test_prefix test_bkpt_cond_and_cmds { + # Start with a fresh gdb. + clean_restart ${testfile} + + if ![gdb_guile_runto_main] { + return + } + + # Test conditional setting. + set bp_location1 [gdb_get_line_number "Break at multiply."] + gdb_scm_test_silent_cmd "guile (define bp1 (create-breakpoint! \"$bp_location1\"))" \ + "create multiply breakpoint" + gdb_continue_to_breakpoint "Break at multiply." + gdb_scm_test_silent_cmd "guile (set-breakpoint-condition! bp1 \"i == 5\")" \ + "set condition" + gdb_test "guile (print (breakpoint-condition bp1))" \ + "= i == 5" "test condition has been set" + gdb_continue_to_breakpoint "Break at multiply." + gdb_test "print i" \ + "5" "test conditional breakpoint stopped after five iterations" + gdb_scm_test_silent_cmd "guile (set-breakpoint-condition! bp1 #f)" \ + "clear condition" + gdb_test "guile (print (breakpoint-condition bp1))" \ + "= #f" "test condition has been removed" + gdb_continue_to_breakpoint "Break at multiply." + gdb_test "print i" "6" "test breakpoint stopped after six iterations" + + # Test commands. + gdb_breakpoint [gdb_get_line_number "Break at add."] + set test {commands $bpnum} + gdb_test_multiple $test $test { -re "\r\n>$" { pass $test } } + set test {print "Command for breakpoint has been executed."} + gdb_test_multiple $test $test { -re "\r\n>$" { pass $test } } + set test {print result} + gdb_test_multiple $test $test { -re "\r\n>$" { pass $test } } + gdb_test "end" + + gdb_scm_test_silent_cmd "guile (define blist (breakpoints))" \ + "get breakpoint list 6" + gdb_test "guile (print (breakpoint-commands (list-ref blist (- (length blist) 1))))" \ + "print \"Command for breakpoint has been executed.\".*print result" + } +} + +proc test_bkpt_invisible { } { + global srcfile testfile hex decimal + + with_test_prefix test_bkpt_invisible { + # Start with a fresh gdb. + clean_restart ${testfile} + + if ![gdb_guile_runto_main] { + return + } + + # Test invisible breakpoints. + delete_breakpoints + set ibp_location [gdb_get_line_number "Break at multiply."] + gdb_scm_test_silent_cmd "guile (define vbp (create-breakpoint! \"$ibp_location\" #:internal #f))" \ + "create visible breakpoint" + gdb_scm_test_silent_cmd "guile (define vbp (car (breakpoints)))" \ + "get visible breakpoint" + gdb_test "guile (print vbp)" \ + "= #<gdb:breakpoint #2 BP_BREAKPOINT enabled noisy hit:0 ignore:0 @.*scm-breakpoint.c:$ibp_location>" \ + "check visible bp obj exists" + gdb_test "guile (print (breakpoint-location vbp))" \ + "scm-breakpoint\.c:$ibp_location*" "check visible breakpoint location" + gdb_test "guile (print (breakpoint-visible? vbp))" \ + "= #t" "check breakpoint visibility" + gdb_test "info breakpoints" \ + "scm-breakpoint\.c:$ibp_location.*" \ + "check info breakpoints shows visible breakpoints" + delete_breakpoints + gdb_scm_test_silent_cmd "guile (define ibp (create-breakpoint! \"$ibp_location\" #:internal #t))" \ + "create invisible breakpoint" + gdb_test "guile (print ibp)" \ + "= #<gdb:breakpoint #-$decimal BP_BREAKPOINT enabled noisy hit:0 ignore:0 @.*scm-breakpoint.c:$ibp_location>" \ + "check invisible bp obj exists" + gdb_test "guile (print (breakpoint-location ibp))" \ + "scm-breakpoint\.c:$ibp_location*" "check invisible breakpoint location" + gdb_test "guile (print (breakpoint-visible? ibp))" \ + "= #f" "check breakpoint invisibility" + gdb_test "info breakpoints" \ + "No breakpoints or watchpoints.*" \ + "check info breakpoints does not show invisible breakpoints" + gdb_test "maint info breakpoints" \ + "scm-breakpoint\.c:$ibp_location.*" \ + "check maint info breakpoints shows invisible breakpoints" + } +} + +proc test_watchpoints { } { + global srcfile testfile hex decimal + + with_test_prefix test_watchpoints { + # Start with a fresh gdb. + clean_restart ${testfile} + + # Disable hardware watchpoints if necessary. + if [target_info exists gdb,no_hardware_watchpoints] { + gdb_test_no_output "set can-use-hw-watchpoints 0" "" + } + if ![gdb_guile_runto_main] { + return + } + + gdb_scm_test_silent_cmd "guile (define wp1 (create-breakpoint! \"result\" #:type BP_WATCHPOINT #:wp-class WP_WRITE))" \ + "create watchpoint" + gdb_test "continue" \ + ".*\[Ww\]atchpoint.*result.*Old value = 0.*New value = 25.*main.*" \ + "test watchpoint write" + } +} + +proc test_bkpt_internal { } { + global srcfile testfile hex decimal + + with_test_prefix test_bkpt_internal { + # Start with a fresh gdb. + clean_restart ${testfile} + + # Disable hardware watchpoints if necessary. + if [target_info exists gdb,no_hardware_watchpoints] { + gdb_test_no_output "set can-use-hw-watchpoints 0" "" + } + if ![gdb_guile_runto_main] { + return + } + + delete_breakpoints + + gdb_scm_test_silent_cmd "guile (define wp1 (create-breakpoint! \"result\" #:type BP_WATCHPOINT #:wp-class WP_WRITE #:internal #t))" \ + "create invisible watchpoint" + gdb_test "info breakpoints" \ + "No breakpoints or watchpoints.*" \ + "check info breakpoints does not show invisible watchpoint" + gdb_test "maint info breakpoints" \ + ".*watchpoint.*result.*" \ + "check maint info breakpoints shows invisible watchpoint" + gdb_test "continue" \ + ".*\[Ww\]atchpoint.*result.*Old value = 0.*New value = 25.*" \ + "test invisible watchpoint write" + } +} + +proc test_bkpt_eval_funcs { } { + global srcfile testfile hex decimal + + with_test_prefix test_bkpt_eval_funcs { + # Start with a fresh gdb. + clean_restart ${testfile} + + # Disable hardware watchpoints if necessary. + if [target_info exists gdb,no_hardware_watchpoints] { + gdb_test_no_output "set can-use-hw-watchpoints 0" "" + } + if ![gdb_guile_runto_main] { + return + } + + delete_breakpoints + + gdb_test_multiline "data collection breakpoint 1" \ + "guile" "" \ + "(define (make-bp-data) (cons 0 0))" "" \ + "(define bp-data-count car)" "" \ + "(define set-bp-data-count! set-car!)" "" \ + "(define bp-data-inf-i cdr)" "" \ + "(define set-bp-data-inf-i! set-cdr!)" "" \ + "(define (bp-eval-count bkpt) (bp-data-count (gsmob-property bkpt 'bp-data)))" "" \ + "(define (bp-eval-inf-i bkpt) (bp-data-inf-i (gsmob-property bkpt 'bp-data)))" "" \ + "(define (make-bp-eval location)" "" \ + " (let ((bp (create-breakpoint! location)))" "" \ + " (set-gsmob-property! bp 'bp-data (make-bp-data))" "" \ + " (set-breakpoint-stop! bp" "" \ + " (lambda (bkpt)" "" \ + " (let ((data (gsmob-property bkpt 'bp-data))" "" \ + " (inf-i (parse-and-eval \"i\")))" "" \ + " (set-bp-data-count! data (+ (bp-data-count data) 1))" "" \ + " (set-bp-data-inf-i! data inf-i)" "" \ + " (value=? inf-i 3))))" "" \ + " bp))" "" \ + "end" "" + + gdb_test_multiline "data collection breakpoint 2" \ + "guile" "" \ + "(define (make-bp-also-eval location)" "" \ + " (let ((bp (create-breakpoint! location)))" "" \ + " (set-gsmob-property! bp 'bp-data (make-bp-data))" "" \ + " (set-breakpoint-stop! bp" "" \ + " (lambda (bkpt)" "" \ + " (let* ((data (gsmob-property bkpt 'bp-data))" "" \ + " (count (+ (bp-data-count data) 1)))" "" \ + " (set-bp-data-count! data count)" "" \ + " (= count 9))))" "" \ + " bp))" "" \ + "end" "" + + gdb_test_multiline "data collection breakpoint 3" \ + "guile" "" \ + "(define (make-bp-basic location)" "" \ + " (let ((bp (create-breakpoint! location)))" "" \ + " (set-gsmob-property! bp 'bp-data (make-bp-data))" "" \ + " bp))" "" \ + "end" "" + + set bp_location2 [gdb_get_line_number "Break at multiply."] + set end_location [gdb_get_line_number "Break at end."] + gdb_scm_test_silent_cmd "guile (define eval-bp1 (make-bp-eval \"$bp_location2\"))" \ + "create eval-bp1 breakpoint" + gdb_scm_test_silent_cmd "guile (define also-eval-bp1 (make-bp-also-eval \"$bp_location2\"))" \ + "create also-eval-bp1 breakpoint" + gdb_scm_test_silent_cmd "guile (define never-eval-bp1 (make-bp-also-eval \"$end_location\"))" \ + "create never-eval-bp1 breakpoint" + gdb_continue_to_breakpoint "Break at multiply." ".*/$srcfile:$bp_location2.*" + gdb_test "print i" "3" "check inferior value matches guile accounting" + gdb_test "guile (print (bp-eval-inf-i eval-bp1))" \ + "= 3" "check guile accounting matches inferior" + gdb_test "guile (print (bp-eval-count also-eval-bp1))" \ + "= 4" \ + "check non firing same-location breakpoint eval function was also called at each stop 1" + gdb_test "guile (print (bp-eval-count eval-bp1))" \ + "= 4" \ + "check non firing same-location breakpoint eval function was also called at each stop 2" + + # Check we cannot assign a condition to a breakpoint with a stop-func, + # and cannot assign a stop-func to a breakpoint with a condition. + + delete_breakpoints + set cond_bp [gdb_get_line_number "Break at multiply."] + gdb_scm_test_silent_cmd "guile (define eval-bp1 (make-bp-eval \"$cond_bp\"))" \ + "create eval-bp1 breakpoint 2" + set test_cond {cond $bpnum} + gdb_test "$test_cond \"foo==3\"" \ + "Only one stop condition allowed.*" + gdb_scm_test_silent_cmd "guile (define eval-bp2 (make-bp-basic \"$cond_bp\"))" \ + "create basic breakpoint" + gdb_scm_test_silent_cmd "guile (set-breakpoint-condition! eval-bp2 \"1==1\")" \ + "set a condition" + gdb_test_multiline "construct an eval function" \ + "guile" "" \ + "(define (stop-func bkpt)" "" \ + " return #t)" "" \ + "end" "" + gdb_test "guile (set-breakpoint-stop! eval-bp2 stop-func)" \ + "Only one stop condition allowed.*" + + # Check that stop-func is run when location has normal bp. + + delete_breakpoints + gdb_breakpoint [gdb_get_line_number "Break at multiply."] + gdb_scm_test_silent_cmd "guile (define check-eval (make-bp-eval \"$bp_location2\"))" \ + "create check-eval breakpoint" + gdb_test "guile (print (bp-eval-count check-eval))" \ + "= 0" \ + "test that evaluate function has not been yet executed (ie count = 0)" + gdb_continue_to_breakpoint "Break at multiply." ".*/$srcfile:$bp_location2.*" + gdb_test "guile (print (bp-eval-count check-eval))" \ + "= 1" \ + "test that evaluate function is run when location also has normal bp" + + # Test watchpoints with stop-func. + + gdb_test_multiline "watchpoint stop func" \ + "guile" "" \ + "(define (make-wp-eval location)" "" \ + " (let ((wp (create-breakpoint! location #:type BP_WATCHPOINT #:wp-class WP_WRITE)))" "" \ + " (set-breakpoint-stop! wp" "" \ + " (lambda (bkpt)" "" \ + " (let ((result (parse-and-eval \"result\")))" "" \ + " (value=? result 788))))" "" \ + " wp))" "" \ + "end" "" + + delete_breakpoints + gdb_scm_test_silent_cmd "guile (define wp1 (make-wp-eval \"result\"))" \ + "create watchpoint" + gdb_test "continue" ".*\[Ww\]atchpoint.*result.*Old value =.*New value = 788.*" \ + "test watchpoint write" + + # Misc final tests. + + gdb_test "guile (print (bp-eval-count never-eval-bp1))" \ + "= 0" \ + "check that this unrelated breakpoints eval function was never called" + } +} + +test_bkpt_basic +test_bkpt_deletion +test_bkpt_cond_and_cmds +test_bkpt_invisible +test_watchpoints +test_bkpt_internal +test_bkpt_eval_funcs diff --git a/gdb/testsuite/gdb.guile/scm-disasm.c b/gdb/testsuite/gdb.guile/scm-disasm.c new file mode 100644 index 0000000..6c0ef92 --- /dev/null +++ b/gdb/testsuite/gdb.guile/scm-disasm.c @@ -0,0 +1,22 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2014 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/>. */ + +int +main (void) +{ + return 0; +} diff --git a/gdb/testsuite/gdb.guile/scm-disasm.exp b/gdb/testsuite/gdb.guile/scm-disasm.exp new file mode 100644 index 0000000..5a1dae3 --- /dev/null +++ b/gdb/testsuite/gdb.guile/scm-disasm.exp @@ -0,0 +1,133 @@ +# Copyright 2014 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 gdb-guile.exp + +standard_testfile + +if { [prepare_for_testing ${testfile}.exp ${testfile} ${srcfile}] } { + return +} + +# Skip all tests if Guile scripting is not enabled. +if { [skip_guile_tests] } { continue } + +if ![gdb_guile_runto_main] { + return +} + +# Disassemble one instruction at pc and verify the result. + +proc test_disassemble_1 { name address extra_args } { + with_test_prefix $name { + gdb_scm_test_silent_cmd "guile (define insn-list (arch-disassemble arch $address $extra_args #:size 1 #:count 1))" \ + "disassemble" + + gdb_test "guile (print (length insn-list))" \ + "= 1" "test number of instructions" + gdb_scm_test_silent_cmd "guile (define insn (car insn-list))" \ + "get instruction" + + # Verify all the fields are present. + gdb_test "guile (print (->bool (assq-ref insn 'address)))" \ + "= #t" "test key address" + gdb_test "guile (print (->bool (assq-ref insn 'asm)))" \ + "= #t" "test key asm" + gdb_test "guile (print (->bool (assq-ref insn 'length)))" \ + "= #t" "test key length" + + # Verify the correct address is used. + gdb_test "guile (print (= $address (assq-ref insn 'address)))" \ + "= #t" "verify correct address" + } +} + +gdb_scm_test_silent_cmd "guile (define frame (selected-frame))" "get frame" +gdb_scm_test_silent_cmd "guile (define arch (frame-arch frame))" "get arch" +gdb_scm_test_silent_cmd "guile (define pc (frame-pc frame))" "get pc" + +gdb_test "guile (print (arch-disassemble arch pc #:size 0))" \ + "= \\(\\)" "disassemble, zero size" +gdb_test "guile (print (arch-disassemble arch pc #:count 0))" \ + "= \\(\\)" "disassemble, zero count" + +gdb_scm_test_silent_cmd "guile (define insn-list1 (arch-disassemble arch pc #:size 1 #:count 1))" \ + "disassemble" +gdb_scm_test_silent_cmd "guile (define insn-list2 (arch-disassemble arch pc #:size 1))" \ + "disassemble, no count" +gdb_scm_test_silent_cmd "guile (define insn-list3 (arch-disassemble arch pc #:count 1))" \ + "disassemble, no end" +gdb_scm_test_silent_cmd "guile (define insn-list4 (arch-disassemble arch pc))" \ + "disassemble, no end no count" + +gdb_test "guile (print (length insn-list1))" \ + "= 1" "test number of instructions 1" +gdb_test "guile (print (length insn-list2))" \ + "= 1" "test number of instructions 2" +gdb_test "guile (print (length insn-list3))" \ + "= 1" "test number of instructions 3" +gdb_test "guile (print (length insn-list4))" \ + "= 1" "test number of instructions 4" + +test_disassemble_1 "basic" "pc" "" + +# Negative test +gdb_test "guile (arch-disassemble arch 0 #:size 1)" \ + "ERROR: Cannot access memory at address 0x.*" "test bad memory access" + +# Test disassembly through a port. + +gdb_scm_test_silent_cmd "guile (define mem (open-memory))" \ + "open memory port" + +test_disassemble_1 "memory-port" "pc" "#:port mem" + +gdb_scm_test_silent_cmd "guile (define insn-list-mem (arch-disassemble arch pc #:port mem #:size 1 #:count 1))" \ + "disassemble via memory port" + +# Test memory error reading from port. + +gdb_scm_test_silent_cmd "guile (define mem1 (open-memory #:start pc #:size 4))" \ + "open restricted range memory port" + +# The x86 disassembler tries to be clever and will print "byte 0x42" if +# there is insufficient memory for the entire instruction. +# So we pass "#:count 5" to ensure the disassembler tries to read beyond +# the end of the memory range. +gdb_test "guile (arch-disassemble arch pc #:port mem1 #:count 5 #:offset pc)" \ + "ERROR: Cannot access memory at address 0x.*" \ + "test bad memory access from port" + +# Test disassembly of a bytevector. + +gdb_scm_test_silent_cmd "guile (use-modules (rnrs io ports))" \ + "import (rnrs io ports)" + +# First fetch the length of the instruction at $pc. +gdb_scm_test_silent_cmd "guile (define insn-list-for-bv (arch-disassemble arch pc))" \ + "get insn for bytevector" +gdb_test_no_output "guile (define insn-length (assq-ref (car insn-list-for-bv) 'length))" \ + "get insn length for bytevector" + +# Read the insn into a bytevector. +gdb_test_no_output "guile (define insn-bv (get-bytevector-n (open-memory #:start pc #:size insn-length) insn-length))" \ + "read insn into bytevector" + +# Disassemble the bytevector. +gdb_scm_test_silent_cmd "guile (define insn-list-from-bv (arch-disassemble arch pc #:port (open-bytevector-input-port insn-bv) #:offset pc))" \ + "disassemble bytevector" + +gdb_test "guile (print (equal? insn-list-for-bv insn-list-from-bv))" \ + "= #t" "verify bytevector disassembly" diff --git a/gdb/testsuite/gdb.guile/scm-equal.c b/gdb/testsuite/gdb.guile/scm-equal.c new file mode 100644 index 0000000..108c9be --- /dev/null +++ b/gdb/testsuite/gdb.guile/scm-equal.c @@ -0,0 +1,24 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2014 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/>. */ + +int x; + +int +main (void) +{ + return x; +} diff --git a/gdb/testsuite/gdb.guile/scm-equal.exp b/gdb/testsuite/gdb.guile/scm-equal.exp new file mode 100644 index 0000000..ae23aa8 --- /dev/null +++ b/gdb/testsuite/gdb.guile/scm-equal.exp @@ -0,0 +1,55 @@ +# Copyright 2014 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/>. + +# This file is part of the GDB testsuite. +# It tests equal? for the various gsmobs. + +load_lib gdb-guile.exp + +standard_testfile + +if { [prepare_for_testing ${testfile}.exp ${testfile} ${srcfile}] } { + return +} + +# Skip all tests if Guile scripting is not enabled. +if { [skip_guile_tests] } { continue } + +if ![gdb_guile_runto_main] { + return +} + +gdb_scm_test_silent_cmd "guile (define frame (selected-frame))" "get frame" +gdb_scm_test_silent_cmd "guile (define arch (frame-arch frame))" "get arch" + +gdb_test "guile (print (equal? (selected-frame) (newest-frame)))" \ + "= #t" "equal? frame" +gdb_test "guile (print (equal? (selected-frame) (frame-older (newest-frame))))" \ + "= #f" "not equal? frame" + +gdb_test "guile (print (equal? (make-value 1) (make-value 1)))" \ + "= #t" "equal? value" +gdb_test "guile (print (equal? (make-value 1) (make-value 2)))" \ + "= #f" "not equal? value" + +gdb_test "guile (print (equal? (value-type (make-value 1)) (value-type (make-value 2))))" \ + "= #t" "equal? type" +gdb_test "guile (print (equal? (value-type (make-value 1)) (value-type (make-value 2.5))))" \ + "= #f" "not equal? type" + +gdb_test "guile (print (equal? (lookup-global-symbol \"main\") (lookup-global-symbol \"main\")))" \ + "= #t" "equal? symbol" +gdb_test "guile (print (equal? (lookup-global-symbol \"main\") (lookup-global-symbol \"x\")))" \ + "= #f" "not equal? symbol" diff --git a/gdb/testsuite/gdb.guile/scm-error-1.scm b/gdb/testsuite/gdb.guile/scm-error-1.scm new file mode 100644 index 0000000..a68f491 --- /dev/null +++ b/gdb/testsuite/gdb.guile/scm-error-1.scm @@ -0,0 +1,19 @@ +;; Copyright (C) 2014 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/>. + +(use-modules (gdb)) + +;; An intentional error to test error handling when loading a file. +(define foo (+ 42 #f)) diff --git a/gdb/testsuite/gdb.guile/scm-error-2.scm b/gdb/testsuite/gdb.guile/scm-error-2.scm new file mode 100644 index 0000000..87a7ee5 --- /dev/null +++ b/gdb/testsuite/gdb.guile/scm-error-2.scm @@ -0,0 +1,30 @@ +;; Copyright (C) 2014 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/>. + +(use-modules (gdb)) + +;; Create a set of functions to call, with the last one having an error, +;; so we can test backtrace printing. + +(define foo #f) + +(define (top-func x) + (+ (middle-func x) 1)) + +(define (middle-func x) + (+ (bottom-func x) 1)) + +(define (bottom-func x) + (+ x foo)) diff --git a/gdb/testsuite/gdb.guile/scm-error.exp b/gdb/testsuite/gdb.guile/scm-error.exp new file mode 100644 index 0000000..b5a1028 --- /dev/null +++ b/gdb/testsuite/gdb.guile/scm-error.exp @@ -0,0 +1,117 @@ +# Copyright (C) 2010-2014 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/>. + +# Test various error conditions. + +set testfile "scm-error" + +load_lib gdb-guile.exp + +# Start with a fresh gdb. +gdb_exit +gdb_start + +# Skip all tests if Guile scripting is not enabled. +if { [skip_guile_tests] } { continue } + +# Test error while loading .scm. + +# Give the files a new name so we don't clobber the real one if +# objfile == srcdir. +set remote_guile_file_1 [gdb_remote_download host \ + ${srcdir}/${subdir}/${testfile}-1.scm \ + ${subdir}/t-${testfile}-1.scm] +set remote_guile_file_2 [gdb_remote_download host \ + ${srcdir}/${subdir}/${testfile}-2.scm \ + ${subdir}/t-${testfile}-2.scm] + +gdb_test "source $remote_guile_file_1" \ + "(ERROR: )?In procedure \[+\]: Wrong type: #f.*" \ + "error loading scm file caught" + +gdb_test "p 1" " = 1" "no delayed error" + +# Test setting/showing the various states for "guile print-stack". + +gdb_test "show guile print-stack" \ + "The mode of Guile exception printing on error is \"message\".*" \ + "test print-stack show setting of default" +gdb_test_no_output "set guile print-stack full" \ + "test print-stack full setting" +gdb_test "show guile print-stack" \ + "The mode of Guile exception printing on error is \"full\".*" \ + "test print-stack show setting to full" +gdb_test_no_output "set guile print-stack none" \ + "test print-stack none setting" +gdb_test "show guile print-stack" \ + "The mode of Guile exception printing on error is \"none\".*" \ + "test print-stack show setting to none" +# Reset back to default, just in case. +gdb_test_no_output "set guile print-stack message" \ + "reset print-stack to default, post set/show tests" + +# Test "set guile print-stack none". + +gdb_test_no_output "set guile print-stack none" \ + "set print-stack to none, for error test" + +set test_name "no error printed" +set command "guile (define x doesnt-exist)" +gdb_test_multiple $command $test_name { + -re "Backtrace.*$gdb_prompt $" { fail $test_name } + -re "ERROR.*$gdb_prompt $" { fail $test_name } + -re "$gdb_prompt $" { pass $test_name } +} + +# Test "set guile print-stack message". + +gdb_test_no_output "set guile print-stack message" \ + "set print-stack to message, for error test" + +set test_name "error message printed" +set command "guile (define x doesnt-exist)" +gdb_test_multiple $command $test_name { + -re "Backtrace.*$gdb_prompt $" { fail $test_name } + -re "ERROR.*$gdb_prompt $" { pass $test_name } +} + +# Test "set guile print-stack full". + +gdb_scm_test_silent_cmd "source $remote_guile_file_2" "" + +gdb_test_no_output "set guile print-stack full" \ + "set print-stack to full, for backtrace test" + +gdb_test "guile (define x (top-func 42))" \ + "Guile Backtrace:.*top-func 42.*middle-func 42.*bottom-func 42.*" \ + "backtrace printed" + +# Verify gdb-specific errors are printed properly. +# i.e., each gdb error is registered to use init.scm:%error-printer. + +gdb_test_no_output "set guile print-stack message" \ + "set print-stack to message, for error printing tests" + +gdb_test "guile (throw 'gdb:error \"subr\" \"misc error: ~a\" (list 42))" \ + "ERROR: In procedure subr: misc error: 42.*" + +gdb_test "guile (throw 'gdb:invalid-object-error \"subr\" \"invalid object error: ~a\" (list 42))" \ + "ERROR: In procedure subr: invalid object error: 42.*" + +gdb_test "guile (throw 'gdb:memory-error \"subr\" \"memory error: ~a\" (list 42))" \ + "ERROR: In procedure subr: memory error: 42.*" + +gdb_test "guile (throw 'gdb:pp-type-error \"subr\" \"pp-type error: ~a\" (list 42))" \ + "ERROR: In procedure subr: pp-type error: 42.*" diff --git a/gdb/testsuite/gdb.guile/scm-frame-args.c b/gdb/testsuite/gdb.guile/scm-frame-args.c new file mode 100644 index 0000000..c20b1e1 --- /dev/null +++ b/gdb/testsuite/gdb.guile/scm-frame-args.c @@ -0,0 +1,60 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2014 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 <string.h> + +struct s +{ + int m; +}; + +struct ss +{ + struct s a; + struct s b; +}; + +void +init_s (struct s *s, int m) +{ + s->m = m; +} + +void +init_ss (struct ss *s, int a, int b) +{ + init_s (&s->a, a); + init_s (&s->b, b); +} + +void +foo (int x, struct ss ss) +{ + return; /* break-here */ +} + +int +main () +{ + struct ss ss; + + init_ss (&ss, 1, 2); + + foo (42, ss); + + return 0; +} diff --git a/gdb/testsuite/gdb.guile/scm-frame-args.exp b/gdb/testsuite/gdb.guile/scm-frame-args.exp new file mode 100644 index 0000000..22ce6fe --- /dev/null +++ b/gdb/testsuite/gdb.guile/scm-frame-args.exp @@ -0,0 +1,76 @@ +# Copyright (C) 2014 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 gdb-guile.exp + +standard_testfile + +if { [prepare_for_testing ${testfile}.exp ${testfile} ${srcfile}] } { + return +} + +# Skip all tests if Guile scripting is not enabled. +if { [skip_guile_tests] } { continue } + +if ![gdb_guile_runto_main] { + return +} + +# Give the file a new name so we don't clobber the real one if +# objfile == srcdir. +set remote_guile_file [gdb_remote_download host \ + ${srcdir}/${subdir}/${testfile}.scm \ + ${subdir}/t-${testfile}.scm] + +gdb_scm_load_file "$remote_guile_file" "load script" + +gdb_breakpoint [gdb_get_line_number "break-here"] +gdb_continue_to_breakpoint "break-here" ".* break-here .*" + +# Test all combinations with raw off. + +gdb_test_no_output "set print raw frame-arguments off" + +gdb_test_no_output "set print frame-arguments none" +gdb_test "frame" ".*foo \\(x=\[.\]{3}, ss=\[.\]{3}\\).*" \ + "frame pretty,none" + +#gdb_test_no_output "set guile print-stack full" + +gdb_test_no_output "set print frame-arguments scalars" +gdb_test "frame" ".*foo \\(x=42, ss=super struct = {\[.\]{3}}\\).*" \ + "frame pretty,scalars" + +gdb_test_no_output "set print frame-arguments all" +gdb_test "frame" \ + ".*foo \\(x=42, ss=super struct = {a = m=<1>, b = m=<2>}\\).*" \ + "frame pretty,all" + +# Test all combinations with raw on. + +gdb_test_no_output "set print raw frame-arguments on" + +gdb_test_no_output "set print frame-arguments none" +gdb_test "frame" ".*foo \\(x=\[.\]{3}, ss=\[.\]{3}\\).*" \ + "frame raw,none" + +gdb_test_no_output "set print frame-arguments scalars" +gdb_test "frame" ".*foo \\(x=42, ss=\[.\]{3}\\).*" \ + "frame raw,scalars" + +gdb_test_no_output "set print frame-arguments all" +gdb_test "frame" \ + ".*foo \\(x=42, ss={a = {m = 1}, b = {m = 2}}\\).*" \ + "frame raw,all" diff --git a/gdb/testsuite/gdb.guile/scm-frame-args.scm b/gdb/testsuite/gdb.guile/scm-frame-args.scm new file mode 100644 index 0000000..20d42f8 --- /dev/null +++ b/gdb/testsuite/gdb.guile/scm-frame-args.scm @@ -0,0 +1,69 @@ +;; Copyright (C) 2014 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/>. + +(use-modules (gdb) (gdb printing)) + +(define (make-pp_s-printer val) + (make-pretty-printer-worker + #f + (lambda (printer) + (let ((m (value-field val "m"))) + (format #f "m=<~A>" m))) + #f)) + +(define (make-pp_ss-printer val) + (make-pretty-printer-worker + #f + (lambda (printer) "super struct") + (lambda (printer) + (make-iterator val + (make-field-iterator (value-type val)) + (lambda (iter) + (let ((field (iterator-next! + (iterator-progress iter)))) + (if (end-of-iteration? field) + field + (let ((name (field-name field))) + (cons name (value-field val name)))))))))) + +(define (get-type-for-printing val) + "Return type of val, stripping away typedefs, etc." + (let ((type (value-type val))) + (if (= (type-code type) TYPE_CODE_REF) + (set! type (type-target type))) + (type-strip-typedefs (type-unqualified type)))) + +(define (make-pretty-printer-dict) + (let ((dict (make-hash-table))) + (hash-set! dict "struct s" make-pp_s-printer) + (hash-set! dict "s" make-pp_s-printer) + (hash-set! dict "struct ss" make-pp_ss-printer) + (hash-set! dict "ss" make-pp_ss-printer) + dict)) + +(define *pretty-printer* + (make-pretty-printer + "pretty-printer-test" + (let ((pretty-printers-dict (make-pretty-printer-dict))) + (lambda (matcher val) + "Look-up and return a pretty-printer that can print val." + (let ((type (get-type-for-printing val))) + (let ((typename (type-tag type))) + (if typename + (let ((printer-maker (hash-ref pretty-printers-dict typename))) + (and printer-maker (printer-maker val))) + #f))))))) + +(append-pretty-printer! #f *pretty-printer*) diff --git a/gdb/testsuite/gdb.guile/scm-frame-inline.c b/gdb/testsuite/gdb.guile/scm-frame-inline.c new file mode 100644 index 0000000..a3669bc --- /dev/null +++ b/gdb/testsuite/gdb.guile/scm-frame-inline.c @@ -0,0 +1,43 @@ +/* This test is part of GDB, the GNU debugger. + + Copyright 2011-2014 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/>. */ + +volatile int v = 42; + +__attribute__((__always_inline__)) static inline int +f (void) +{ + /* Provide first stub line so that GDB understand the PC is already inside + the inlined function and does not expect a step into it. */ + v++; + v++; /* break-here */ + + return v; +} + +__attribute__((__noinline__)) static int +g (void) +{ + volatile int l = v; + + return f (); +} + +int +main (void) +{ + return g (); +} diff --git a/gdb/testsuite/gdb.guile/scm-frame-inline.exp b/gdb/testsuite/gdb.guile/scm-frame-inline.exp new file mode 100644 index 0000000..ed1c3b8 --- /dev/null +++ b/gdb/testsuite/gdb.guile/scm-frame-inline.exp @@ -0,0 +1,43 @@ +# Copyright (C) 2011-2014 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 gdb-guile.exp + +standard_testfile + +if { [prepare_for_testing ${testfile}.exp ${testfile} ${srcfile}] } { + return +} + +# Skip all tests if Guile scripting is not enabled. +if { [skip_guile_tests] } { continue } + +if ![runto main] { + fail "Can't run to main" + return +} + +gdb_install_guile_utils +gdb_install_guile_module + +gdb_breakpoint [gdb_get_line_number "break-here"] +gdb_continue_to_breakpoint "break-here" + +gdb_test "info frame" "inlined into frame 1\r\n.*" + +gdb_test "up" "#1 g .*" + +gdb_test "guile (print (frame-read-var (selected-frame) \"l\"))" \ + "= 42" diff --git a/gdb/testsuite/gdb.guile/scm-frame.c b/gdb/testsuite/gdb.guile/scm-frame.c new file mode 100644 index 0000000..82db341 --- /dev/null +++ b/gdb/testsuite/gdb.guile/scm-frame.c @@ -0,0 +1,30 @@ +int f2 (int a) +{ + return ++a; +} + +int f1 (int a, int b) +{ + return f2(a) + b; +} + +int block (void) +{ + int i = 99; + { + double i = 1.1; + double f = 2.2; + { + const char *i = "stuff"; + const char *f = "foo"; + const char *b = "bar"; + return 0; /* Block break here. */ + } + } +} + +int main (int argc, char *argv[]) +{ + block (); + return f1 (1, 2); +} diff --git a/gdb/testsuite/gdb.guile/scm-frame.exp b/gdb/testsuite/gdb.guile/scm-frame.exp new file mode 100644 index 0000000..04c8cda --- /dev/null +++ b/gdb/testsuite/gdb.guile/scm-frame.exp @@ -0,0 +1,122 @@ +# Copyright (C) 2009-2014 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/>. + +# This file is part of the GDB testsuite. +# It tests the frame support in Guile. + +load_lib gdb-guile.exp + +standard_testfile + +if { [prepare_for_testing ${testfile}.exp ${testfile} ${srcfile}] } { + return -1 +} + +# Skip all tests if Guile scripting is not enabled. +if { [skip_guile_tests] } { continue } + +# The following tests require execution. + +if ![gdb_guile_runto_main] { + return +} + +gdb_breakpoint [gdb_get_line_number "Block break here."] +gdb_continue_to_breakpoint "Block break here." +gdb_scm_test_silent_cmd "guile (define bf1 (selected-frame))" \ + "get frame" + +# Test frame-architecture method. +gdb_scm_test_silent_cmd "guile (define show-arch-str (execute \"show architecture\" #:to-string #t))" \ + "show arch" +gdb_test "guile (print (->bool (string-contains show-arch-str (arch-name (frame-arch bf1)))))" \ + "#t" "test frame-arch" + +# First test that read-var is unaffected by PR 11036 changes. +gdb_test "guile (print (frame-read-var bf1 \"i\"))" \ + "\"stuff\"" "test i" +gdb_test "guile (print (frame-read-var bf1 \"f\"))" \ + "\"foo\"" "test f" +gdb_test "guile (print (frame-read-var bf1 \"b\"))" \ + "\"bar\"" "test b" + +# Test the read-var function in another block other than the current +# block (in this case, the super block). Test thar read-var is reading +# the correct variables of i and f but they are the correct value and type. +gdb_scm_test_silent_cmd "guile (define sb (block-superblock (frame-block bf1)))" \ + "get superblock" +gdb_test "guile (print (frame-read-var bf1 \"i\" #:block sb))" "1.1.*" \ + "test i = 1.1" +gdb_test "guile (print (value-type (frame-read-var bf1 \"i\" #:block sb)))" \ + "double" "test double i" +gdb_test "guile (print (frame-read-var bf1 \"f\" #:block sb))" \ + "2.2.*" "test f = 2.2" +gdb_test "guile (print (value-type (frame-read-var bf1 \"f\" #:block sb)))" \ + "double" "test double f" + +# And again test another outerblock, this time testing "i" is the +# correct value and type. +gdb_scm_test_silent_cmd "guile (set! sb (block-superblock sb))" \ + "get superblock #2" +gdb_test "guile (print (frame-read-var bf1 \"i\" #:block sb))" \ + "99" "test i = 99" +gdb_test "guile (print (value-type (frame-read-var bf1 \"i\" #:block sb)))" \ + "int" "test int i" + +gdb_breakpoint "f2" +gdb_continue_to_breakpoint "breakpoint at f2" +gdb_scm_test_silent_cmd "guile (define bframe (selected-frame))" \ + "get bottom-most frame" +gdb_test "up" ".*" "" + +gdb_scm_test_silent_cmd "guile (define f1 (selected-frame))" \ +"get second frame" +gdb_scm_test_silent_cmd "guile (define f0 (frame-newer f1))" \ + "get first frame" + +gdb_test "guile (print (eq? f1 (newest-frame)))" \ + #f "selected frame -vs- newest frame" +gdb_test "guile (print (eq? bframe (newest-frame)))" \ + #t "newest frame -vs- newest frame" + +gdb_test "guile (print (eq? f0 f1))" \ + "#f" "test equality comparison (false)" +gdb_test "guile (print (eq? f0 f0))" \ + "#t" "test equality comparison (true)" +gdb_test "guile (print (frame-valid? f0))" \ + "#t" "test frame-valid?" +gdb_test "guile (print (frame-name f0))" \ + "f2" "test frame-name" +gdb_test "guile (print (= (frame-type f0) NORMAL_FRAME))" \ + "#t" "test frame-type" +gdb_test "guile (print (= (frame-unwind-stop-reason f0) FRAME_UNWIND_NO_REASON))" \ + "#t" "test frame-unwind-stop-reason" +gdb_test "guile (print (unwind-stop-reason-string FRAME_UNWIND_INNER_ID))" \ + "previous frame inner to this frame \\(corrupt stack\\?\\)" \ + "test unwind-stop-reason-string" +gdb_test "guile (print (format #f \"= ~A\" (frame-pc f0)))" \ + "= \[0-9\]+" "test frame-pc" +gdb_test "guile (print (format #f \"= ~A\" (eq? (frame-older f0) f1)))" \ + "= #t" "test frame-older" +gdb_test "guile (print (format #f \"= ~A\" (eq? (frame-newer f1) f0)))" \ + "= #t" "test frame-newer" +gdb_test "guile (print (frame-read-var f0 \"variable_which_surely_doesnt_exist\"))" \ + "ERROR: .*: Out of range: variable not found: \"variable_which_surely_doesnt_exist\".*" \ + "test frame-read-var - error" +gdb_test "guile (print (format #f \"= ~A\" (frame-read-var f0 \"a\")))" \ + "= 1" "test frame-read-var - success" + +gdb_test "guile (print (format #f \"= ~A\" (eq? (selected-frame) f1)))" \ + "= #t" "test selected-frame" diff --git a/gdb/testsuite/gdb.guile/scm-generics.exp b/gdb/testsuite/gdb.guile/scm-generics.exp new file mode 100644 index 0000000..664affc --- /dev/null +++ b/gdb/testsuite/gdb.guile/scm-generics.exp @@ -0,0 +1,42 @@ +# Copyright (C) 2010-2014 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/>. + +# This file is part of the GDB testsuite. +# It tests using GDB smobs with generics. + +load_lib gdb-guile.exp + +# Start with a fresh gdb. +gdb_exit +gdb_start + +# Skip all tests if Guile scripting is not enabled. +if { [skip_guile_tests] } { continue } + +gdb_reinitialize_dir $srcdir/$subdir + +gdb_install_guile_utils +gdb_install_guile_module + +gdb_test_no_output "guile (use-modules ((oop goops)))" + +gdb_test_no_output "guile (define-generic +)" +gdb_test_no_output "guile (define-method (+ (x <gdb:value>) (y <gdb:value>)) (value-add x y))" + +gdb_test_no_output "guile (define x (make-value 42))" + +gdb_test_no_output "guile (define y (+ x x))" + +gdb_test "guile y" "#<gdb:value 84>" diff --git a/gdb/testsuite/gdb.guile/scm-gsmob.exp b/gdb/testsuite/gdb.guile/scm-gsmob.exp new file mode 100644 index 0000000..470afc4 --- /dev/null +++ b/gdb/testsuite/gdb.guile/scm-gsmob.exp @@ -0,0 +1,70 @@ +# Copyright (C) 2014 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/>. + +# This file is part of the GDB testsuite. +# It tests basic gsmob features. + +load_lib gdb-guile.exp + +# Start with a fresh gdb. +gdb_exit +gdb_start + +# Skip all tests if Guile scripting is not enabled. +if { [skip_guile_tests] } { continue } + +gdb_reinitialize_dir $srcdir/$subdir + +gdb_install_guile_utils +gdb_install_guile_module + +# Test the transition from alist to htab in the property list. +# N.B. This has the same value as gdb/guile/scm-gsmob.c. +set SMOB_PROP_HTAB_THRESHOLD 7 + +gdb_test_no_output "gu (define arch (current-arch))" + +# Return a property name for integer I suitable for sorting. + +proc prop_name { i } { + return [format "prop%02d" $i] +} + +# Set and ref the properties in separate loops to verify previously set +# properties are not lost when we set a new property or switch to htabs. +for {set i 0} {$i <= $SMOB_PROP_HTAB_THRESHOLD} {incr i} { + gdb_test "gu (print (gsmob-has-property? arch '[prop_name $i]))" \ + "= #f" "property prop$i not present before set" + gdb_test_no_output "gu (set-gsmob-property! arch '[prop_name $i] $i)" \ + "set prop $i" + gdb_test "gu (print (gsmob-has-property? arch '[prop_name $i]))" \ + "= #t" "property prop$i present after set" +} +for {set i 0} {$i <= $SMOB_PROP_HTAB_THRESHOLD} {incr i} { + gdb_test "gu (print (gsmob-has-property? arch '[prop_name $i]))" \ + "= #t" "property prop$i present after all set" + gdb_test "gu (print (gsmob-property arch '[prop_name $i]))" \ + "= $i" "ref prop $i" +} + +# Verify gsmob-properties. +set prop_list "" +for {set i 0} {$i <= $SMOB_PROP_HTAB_THRESHOLD} {incr i} { + set prop_list "$prop_list [prop_name $i]" +} +set prop_list [lsort $prop_list] +verbose -log "prop_list: $prop_list" +gdb_test "gu (print (sort (gsmob-properties arch) (lambda (a b) (string<? (symbol->string a) (symbol->string b)))))" \ + "= \\($prop_list\\)" "gsmob-properties" diff --git a/gdb/testsuite/gdb.guile/scm-iterator.c b/gdb/testsuite/gdb.guile/scm-iterator.c new file mode 100644 index 0000000..80e9178 --- /dev/null +++ b/gdb/testsuite/gdb.guile/scm-iterator.c @@ -0,0 +1,28 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2014 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/>. */ + +void +foo (void) +{ +} + +int +main (void) +{ + foo (); + return 0; /* Break at end. */ +} diff --git a/gdb/testsuite/gdb.guile/scm-iterator.exp b/gdb/testsuite/gdb.guile/scm-iterator.exp new file mode 100644 index 0000000..8ee67ed --- /dev/null +++ b/gdb/testsuite/gdb.guile/scm-iterator.exp @@ -0,0 +1,62 @@ +# Copyright (C) 2014 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/>. + +# This file is part of the GDB testsuite. +# It tests the iterator facility. + +load_lib gdb-guile.exp + +standard_testfile + +if { [prepare_for_testing ${testfile}.exp ${testfile} ${srcfile}] } { + return -1 +} + +# Skip all tests if Guile scripting is not enabled. +if { [skip_guile_tests] } { continue } + +if ![gdb_guile_runto_main] { + return +} + +gdb_breakpoint [gdb_get_line_number "Break at end."] +gdb_continue_to_breakpoint "Break at end." + +gdb_scm_test_silent_cmd "guile (use-modules (gdb iterator))" \ + "import (gdb iterator)" + +gdb_scm_test_silent_cmd "guile (define this-sal (find-pc-line (frame-pc (selected-frame))))" \ + "get frame sal" + +gdb_scm_test_silent_cmd "guile (define this-symtab (sal-symtab this-sal))" \ + "get frame symtab" + +gdb_scm_test_silent_cmd "guile (define this-global-block (symtab-global-block this-symtab))" \ + "get frame global block" + +gdb_scm_test_silent_cmd "guile (define syms-iter (make-block-symbols-iterator this-global-block))" \ + "get global block iterator" + +gdb_scm_test_silent_cmd "guile (define functions (iterator-filter symbol-function? syms-iter))" \ + "get global functions" + +gdb_test "guile (print (sort (map symbol-name functions) string<?))" \ + "= \\(foo main\\)" "test function list" + +gdb_scm_test_silent_cmd "guile (define syms-iter (make-block-symbols-iterator this-global-block))" \ + "get global block iterator 2" + +gdb_test "guile (print (sort (map symbol-name (iterator->list syms-iter)) string<?))" \ + "= \\(foo main\\)" "iterator->list" diff --git a/gdb/testsuite/gdb.guile/scm-math.c b/gdb/testsuite/gdb.guile/scm-math.c new file mode 100644 index 0000000..347fc22 --- /dev/null +++ b/gdb/testsuite/gdb.guile/scm-math.c @@ -0,0 +1,30 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2014 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/>. */ + +enum e + { + ONE = 1, + TWO = 2 + }; + +enum e evalue = TWO; + +int +main (int argc, char *argv[]) +{ + return 0; +} diff --git a/gdb/testsuite/gdb.guile/scm-math.exp b/gdb/testsuite/gdb.guile/scm-math.exp new file mode 100644 index 0000000..12caa71 --- /dev/null +++ b/gdb/testsuite/gdb.guile/scm-math.exp @@ -0,0 +1,309 @@ +# Copyright (C) 2008-2014 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/>. + +# This file is part of the GDB testsuite. +# It tests <gdb:value> math operations. + +load_lib gdb-guile.exp + +standard_testfile + +proc test_value_numeric_ops {} { + global gdb_prompt + + gdb_scm_test_silent_cmd "gu (define i (make-value 5))" \ + "create first integer value" + gdb_scm_test_silent_cmd "gu (define j (make-value 2))" \ + "create second integer value" + gdb_test "gu (print (value-add i j))" \ + "= 7" "add two integer values" + gdb_test "gu (raw-print (value-add i j))" \ + "= #<gdb:value 7>" "verify type of integer add result" + + gdb_scm_test_silent_cmd "gu (define f (make-value 1.25))" \ + "create first double value" + gdb_scm_test_silent_cmd "gu (define g (make-value 2.5))" \ + "create second double value" + gdb_test "gu (print (value-add f g))" \ + "= 3.75" "add two double values" + gdb_test "gu (raw-print (value-add f g))" \ + "= #<gdb:value 3.75>" "verify type of double add result" + + gdb_test "gu (print (value-sub i j))" \ + "= 3" "subtract two integer values" + gdb_test "gu (print (value-sub f g))" \ + "= -1.25" "subtract two double values" + + gdb_test "gu (print (value-mul i j))" \ + "= 10" "multiply two integer values" + gdb_test "gu (print (value-mul f g))" \ + "= 3.125" "multiply two double values" + + gdb_test "gu (print (value-div i j))" \ + "= 2" "divide two integer values" + gdb_test "gu (print (value-div f g))" \ + "= 0.5" "divide two double values" + gdb_test "gu (print (value-rem i j))" \ + "= 1" "take remainder of two integer values" + gdb_test "gu (print (value-mod i j))" \ + "= 1" "take modulus of two integer values" + + gdb_test "gu (print (value-pow i j))" \ + "= 25" "integer value raised to the power of another integer value" + gdb_test "gu (print (value-pow g j))" \ + "= 6.25" "double value raised to the power of integer value" + + gdb_test "gu (print (value-neg i))" \ + "= -5" "negated integer value" + gdb_test "gu (print (value-pos i))" \ + "= 5" "positive integer value" + gdb_test "gu (print (value-neg f))" \ + "= -1.25" "negated double value" + gdb_test "gu (print (value-pos f))" \ + "= 1.25" "positive double value" + gdb_test "gu (print (value-abs (value-sub j i)))" \ + "= 3" "absolute of integer value" + gdb_test "gu (print (value-abs (value-sub f g)))" \ + "= 1.25" "absolute of double value" + + gdb_test "gu (print (value-lsh i j))" \ + "= 20" "left shift" + gdb_test "gu (print (value-rsh i j))" \ + "= 1" "right shift" + + gdb_test "gu (print (value-min i j))" \ + "= 2" "min" + gdb_test "gu (print (value-max i j))" \ + "= 5" "max" + + gdb_test "gu (print (value-lognot i))" \ + "= -6" "lognot" + gdb_test "gu (print (value-logand i j))" \ + "= 0" "logand i j" + gdb_test "gu (print (value-logand 5 1))" \ + "= 1" "logand 5 1" + gdb_test "gu (print (value-logior i j))" \ + "= 7" "logior i j" + gdb_test "gu (print (value-logior 5 1))" \ + "= 5" "logior 5 1" + gdb_test "gu (print (value-logxor i j))" \ + "= 7" "logxor i j" + gdb_test "gu (print (value-logxor 5 1))" \ + "= 4" "logxor 5 1" + + # Test <gdb:value> mixed with Guile types. + + gdb_test "gu (print (value-sub i 1))" \ + "= 4" "subtract integer value from guile integer" + gdb_test "gu (raw-print (value-sub i 1))" \ + "#<gdb:value 4>" \ + "verify type of mixed integer subtraction result" + gdb_test "gu (print (value-add f 1.5))" \ + "= 2.75" "add double value with guile float" + + gdb_test "gu (print (value-sub 1 i))" \ + "= -4" "subtract guile integer from integer value" + gdb_test "gu (print (value-add 1.5 f))" \ + "= 2.75" "add guile float with double value" + + # Enum conversion test. + gdb_test "print evalue" "= TWO" + gdb_test "gu (print (value->integer (history-ref 0)))" "= 2" + + # Test pointer arithmetic. + + # First, obtain the pointers. + gdb_test "print (void *) 2" ".*" "" + gdb_test_no_output "gu (define a (history-ref 0))" + gdb_test "print (void *) 5" ".*" "" + gdb_test_no_output "gu (define b (history-ref 0))" + + gdb_test "gu (print (value-add a 5))" \ + "= 0x7( <.*>)?" "add pointer value with guile integer" + gdb_test "gu (print (value-sub b 2))" \ + "= 0x3( <.*>)?" "subtract guile integer from pointer value" + gdb_test "gu (print (value-sub b a))" \ + "= 3" "subtract two pointer values" + + # Test some invalid operations. + + gdb_test_multiple "gu (print (value-add i '()))" "catch error in guile type conversion" { + -re "Wrong type argument in position 2.*$gdb_prompt $" {pass "catch error in guile type conversion"} + -re "= .*$gdb_prompt $" {fail "catch error in guile type conversion"} + -re "$gdb_prompt $" {fail "catch error in guile type conversion"} + } + + gdb_test_multiple "gu (print (value-add i \"foo\"))" "catch throw of GDB error" { + -re "Argument to arithmetic operation not a number or boolean.*$gdb_prompt $" {pass "catch throw of GDB error"} + -re "= .*$gdb_prompt $" {fail "catch throw of GDB error"} + -re "$gdb_prompt $" {fail "catch throw of GDB error"} + } +} + +# Return the max signed int of size SIZE. +# TCL 8.5 required here. Use lookup table instead? + +proc get_max_int { size } { + return [expr "(1 << ($size - 1)) - 1"] +} + +# Return the min signed int of size SIZE. +# TCL 8.5 required here. Use lookup table instead? + +proc get_min_int { size } { + return [expr "-(1 << ($size - 1))"] +} + +# Return the max unsigned int of size SIZE. +# TCL 8.5 required here. Use lookup table instead? + +proc get_max_uint { size } { + return [expr "(1 << $size) - 1"] +} + +# Helper routine for test_value_numeric_ranges. + +proc test_make_int_value { name size } { + set max [get_max_int $size] + set min [get_min_int $size] + set umax [get_max_uint $size] + gdb_test "gu (print (value-type (make-value $max)))" \ + "= $name" "test make-value $name $size max" + gdb_test "gu (print (value-type (make-value $min)))" \ + "= $name" "test make-value $name $size min" + gdb_test "gu (print (value-type (make-value $umax)))" \ + "= unsigned $name" "test make-value unsigned $name $size umax" +} + +# Helper routine for test_value_numeric_ranges. + +proc test_make_typed_int_value { size } { + set name "int$size" + set uname "uint$size" + set max [get_max_int $size] + set min [get_min_int $size] + set umax [get_max_uint $size] + + gdb_test "gu (print (make-value $max #:type (arch-${name}-type arch)))" \ + "= $max" "test make-value $name $size max" + gdb_test "gu (print (make-value $min #:type (arch-${name}-type arch)))" \ + "= $min" "test make-value $name $size min" + gdb_test "gu (print (make-value $umax #:type (arch-${uname}-type arch)))" \ + "= $umax" "test make-value $uname $size umax" + + gdb_test "gu (print (make-value (+ $max 1) #:type (arch-${name}-type arch)))" \ + "ERROR.*Out of range.*" "test make-value $name $size max+1" + gdb_test "gu (print (make-value (- $min 1) #:type (arch-${name}-type arch)))" \ + "ERROR.*Out of range.*" "test make-value $name $size min-1" + gdb_test "gu (print (make-value (+ $umax 1) #:type (arch-${uname}-type arch)))" \ + "ERROR.*Out of range.*" "test make-value $uname $size umax+1" +} + +proc test_value_numeric_ranges {} { + # We can't assume anything about sizeof (int), etc. on the target. + # Keep it simple for now, this will cover everything important for + # the major targets. + set int_size [get_sizeof "int" 0] + set long_size [get_sizeof "long" 0] + gdb_test_no_output "gu (define arch (current-arch))" + + if { $int_size == 4 } { + test_make_int_value int 32 + } + if { $long_size == 8} { + test_make_int_value long 64 + } + gdb_test "gu (print (value-type (make-value (ash 1 64))))" \ + "ERROR:.*value not a number representable.*" \ + "test make-value, number too large" + + foreach size { 8 16 32 } { + test_make_typed_int_value $size + } + if { $long_size == 8 } { + test_make_typed_int_value 64 + } +} + +proc test_value_boolean {} { + # Note: Boolean values print as 0,1 because they are printed in the + # current language (in this case C). + + gdb_test "gu (print (make-value #t))" "= 1" "create boolean true" + gdb_test "gu (print (make-value #f))" "= 0" "create boolean false" + + gdb_test "gu (print (value-not (make-value #t)))" \ + "= 0" "not true" + gdb_test "gu (print (value-not (make-value #f)))" \ + "= 1" "not false" + + gdb_test "gu (raw-print (make-value #t))" \ + "#<gdb:value 1>" "verify type of boolean" +} + +proc test_value_compare {} { + gdb_test "gu (print (value<? 1 1))" \ + "#f" "less than, equal" + gdb_test "gu (print (value<? 1 2))" \ + "#t" "less than, less" + gdb_test "gu (print (value<? 2 1))" \ + "#f" "less than, greater" + + gdb_test "gu (print (value<=? 1 1))" \ + "#t" "less or equal, equal" + gdb_test "gu (print (value<=? 1 2))" \ + "#t" "less or equal, less" + gdb_test "gu (print (value<=? 2 1))" \ + "#f" "less or equal, greater" + + gdb_test "gu (print (value=? 1 1))" \ + "#t" "equality" + gdb_test "gu (print (value=? 1 2))" \ + "#f" "inequality" + gdb_test "gu (print (value=? (make-value 1) 1.0))" \ + "#t" "equality of gdb:value with Guile value" + gdb_test "gu (print (value=? (make-value 1) 2))" \ + "#f" "inequality of gdb:value with Guile value" + + gdb_test "gu (print (value>? 1 1))" \ + "#f" "greater than, equal" + gdb_test "gu (print (value>? 1 2))" \ + "#f" "greater than, less" + gdb_test "gu (print (value>? 2 1))" \ + "#t" "greater than, greater" + + gdb_test "gu (print (value>=? 1 1))" \ + "#t" "greater or equal, equal" + gdb_test "gu (print (value>=? 1 2))" \ + "#f" "greater or equal, less" + gdb_test "gu (print (value>=? 2 1))" \ + "#t" "greater or equal, greater" +} + +if {[prepare_for_testing $testfile.exp $testfile $srcfile {debug c}]} { + return +} + +# Skip all tests if Guile scripting is not enabled. +if { [skip_guile_tests] } { continue } + +if ![gdb_guile_runto_main] { + return +} + +test_value_numeric_ops +test_value_numeric_ranges +test_value_boolean +test_value_compare diff --git a/gdb/testsuite/gdb.guile/scm-objfile-script-gdb.in b/gdb/testsuite/gdb.guile/scm-objfile-script-gdb.in new file mode 100644 index 0000000..e576721 --- /dev/null +++ b/gdb/testsuite/gdb.guile/scm-objfile-script-gdb.in @@ -0,0 +1,55 @@ +;; Copyright (C) 2011-2014 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/>. + +;; This file is part of the GDB testsuite. + +(use-modules (gdb) (gdb printing)) + +(define (make-pp_ss-printer val) + (make-pretty-printer-worker + #f + (lambda (printer) + (let ((a (value-field val "a")) + (b (value-field val "b"))) + (format #f "a=<~A> b=<~A>" a b))) + #f)) + +(define (get-type-for-printing val) + "Return type of val, stripping away typedefs, etc." + (let ((type (value-type val))) + (if (= (type-code type) TYPE_CODE_REF) + (set! type (type-target type))) + (type-strip-typedefs (type-unqualified type)))) + +(define (make-pretty-printer-dict) + (let ((dict (make-hash-table))) + (hash-set! dict "struct ss" make-pp_ss-printer) + (hash-set! dict "ss" make-pp_ss-printer) + dict)) + +(define *pretty-printer* + (make-pretty-printer + "pretty-printer-test" + (let ((pretty-printers-dict (make-pretty-printer-dict))) + (lambda (matcher val) + "Look-up and return a pretty-printer that can print val." + (let ((type (get-type-for-printing val))) + (let ((typename (type-tag type))) + (if typename + (let ((printer-maker (hash-ref pretty-printers-dict typename))) + (and printer-maker (printer-maker val))) + #f))))))) + +(append-pretty-printer! #f *pretty-printer*) diff --git a/gdb/testsuite/gdb.guile/scm-objfile-script.c b/gdb/testsuite/gdb.guile/scm-objfile-script.c new file mode 100644 index 0000000..10f4776 --- /dev/null +++ b/gdb/testsuite/gdb.guile/scm-objfile-script.c @@ -0,0 +1,39 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2011-2014 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/>. */ + +struct ss +{ + int a; + int b; +}; + +void +init_ss (struct ss *s, int a, int b) +{ + s->a = a; + s->b = b; +} + +int +main () +{ + struct ss ss; + + init_ss (&ss, 1, 2); + + return 0; /* break to inspect struct and union */ +} diff --git a/gdb/testsuite/gdb.guile/scm-objfile-script.exp b/gdb/testsuite/gdb.guile/scm-objfile-script.exp new file mode 100644 index 0000000..65d0c44 --- /dev/null +++ b/gdb/testsuite/gdb.guile/scm-objfile-script.exp @@ -0,0 +1,57 @@ +# Copyright (C) 2011-2014 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/>. + +# This file is part of the GDB testsuite. +# It tests automagic loading of -gdb.scm scripts. + +load_lib gdb-guile.exp + +standard_testfile + +if {[build_executable $testfile.exp $testfile $srcfile debug] == -1} { + return +} + +# Start with a fresh gdb. +gdb_exit +gdb_start + +# Skip all tests if Guile scripting is not enabled. +if { [skip_guile_tests] } { continue } + +# Make the -gdb.scm script available to gdb, it is automagically loaded by gdb. +# Care is taken to put it in the same directory as the binary so that +# gdb will find it. +set remote_guile_file [remote_download host \ + ${srcdir}/${subdir}/${testfile}-gdb.in \ + [standard_output_file ${testfile}-gdb.scm]] + +gdb_reinitialize_dir $srcdir/$subdir +gdb_test_no_output "set auto-load safe-path ${remote_guile_file}" \ + "set auto-load safe-path" +gdb_load ${binfile} + +# Verify gdb loaded the script. +gdb_test "info auto-load guile-scripts" "Yes.*/${testfile}-gdb.scm.*" + +if ![gdb_guile_runto_main] { + return +} + +gdb_test "b [gdb_get_line_number {break to inspect} ${testfile}.c ]" \ + ".*Breakpoint.*" +gdb_test "continue" ".*Breakpoint.*" + +gdb_test "print ss" " = a=<1> b=<2>" diff --git a/gdb/testsuite/gdb.guile/scm-objfile.c b/gdb/testsuite/gdb.guile/scm-objfile.c new file mode 100644 index 0000000..dbdc9b3 --- /dev/null +++ b/gdb/testsuite/gdb.guile/scm-objfile.c @@ -0,0 +1,23 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2011-2014 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/>. */ + +int +main () +{ + int some_var = 0; + return 0; +} diff --git a/gdb/testsuite/gdb.guile/scm-objfile.exp b/gdb/testsuite/gdb.guile/scm-objfile.exp new file mode 100644 index 0000000..70da488 --- /dev/null +++ b/gdb/testsuite/gdb.guile/scm-objfile.exp @@ -0,0 +1,57 @@ +# Copyright (C) 2011-2014 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/>. + +# This file is part of the GDB testsuite. +# It tests the objfile support in Guile. + +load_lib gdb-guile.exp + +standard_testfile + +if { [prepare_for_testing ${testfile}.exp ${testfile} ${srcfile}] } { + return +} + +# Skip all tests if Guile scripting is not enabled. +if { [skip_guile_tests] } { continue } + +if ![gdb_guile_runto_main] { + fail "Can't run to main" + return +} + +gdb_scm_test_silent_cmd "gu (define sym (lookup-symbol \"some_var\"))" \ + "Find a symbol in objfile" +gdb_scm_test_silent_cmd "gu (define objfile (symtab-objfile (symbol-symtab (car sym))))" \ + "Get backing object file" + +gdb_test "gu (print (objfile-filename objfile))" \ + ".*scm-objfile.*" "Get objfile filename" +gdb_test "gu (print (objfile-valid? objfile))" \ + "#t" "Get objfile validity" + +gdb_test "gu (print (->bool (or-map (lambda (o) (string-contains (objfile-filename o) \"scm-objfile\")) (objfiles))))" \ + "= #t" "scm-objfile in objfile list" + +gdb_test "gu (print (objfile-pretty-printers objfile))" \ + "= \\(\\)" + +gdb_test "guile (set-objfile-pretty-printers! objfile 0)" \ + "ERROR: .*: Wrong type argument in position 2 \\(expecting list\\): 0.*" + +# Do this last. +gdb_unload +gdb_test "gu (print (objfile-valid? objfile))" \ + "#f" "Get objfile validity after unload" diff --git a/gdb/testsuite/gdb.guile/scm-ports.exp b/gdb/testsuite/gdb.guile/scm-ports.exp new file mode 100644 index 0000000..ceb9a5f --- /dev/null +++ b/gdb/testsuite/gdb.guile/scm-ports.exp @@ -0,0 +1,37 @@ +# Copyright (C) 2014 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/>. + +# This file is part of the GDB testsuite. +# It tests GDB provided ports. + +load_lib gdb-guile.exp + +# Start with a fresh gdb. +gdb_exit +gdb_start + +# Skip all tests if Guile scripting is not enabled. +if { [skip_guile_tests] } { continue } + +gdb_reinitialize_dir $srcdir/$subdir + +gdb_install_guile_utils +gdb_install_guile_module + +gdb_test "guile (print (stdio-port? 42))" "= #f" +gdb_test "guile (print (stdio-port? (%make-void-port \"r\")))" "= #f" +gdb_test "guile (print (stdio-port? (input-port)))" "= #t" +gdb_test "guile (print (stdio-port? (output-port)))" "= #t" +gdb_test "guile (print (stdio-port? (error-port)))" "= #t" diff --git a/gdb/testsuite/gdb.guile/scm-pretty-print.c b/gdb/testsuite/gdb.guile/scm-pretty-print.c new file mode 100644 index 0000000..0fd05f5 --- /dev/null +++ b/gdb/testsuite/gdb.guile/scm-pretty-print.c @@ -0,0 +1,353 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2008-2014 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 <string.h> + +struct s +{ + int a; + int *b; +}; + +struct ss +{ + struct s a; + struct s b; +}; + +struct arraystruct +{ + int y; + struct s x[2]; +}; + +struct ns { + const char *null_str; + int length; +}; + +struct lazystring { + const char *lazy_str; +}; + +struct hint_error { + int x; +}; + +struct children_as_list { + int x; +}; + +#ifdef __cplusplus +struct S : public s { + int zs; +}; + +struct SS { + int zss; + S s; +}; + +struct SSS +{ + SSS (int x, const S& r); + int a; + const S &b; +}; +SSS::SSS (int x, const S& r) : a(x), b(r) { } + +class VirtualTest +{ + private: + int value; + + public: + VirtualTest () + { + value = 1; + } +}; + +class Vbase1 : public virtual VirtualTest { }; +class Vbase2 : public virtual VirtualTest { }; +class Vbase3 : public virtual VirtualTest { }; + +class Derived : public Vbase1, public Vbase2, public Vbase3 +{ + private: + int value; + + public: + Derived () + { + value = 2; + } +}; + +class Fake +{ + int sname; + + public: + Fake (const int name = 0): + sname (name) + { + } +}; +#endif + +struct substruct { + int a; + int b; +}; + +struct outerstruct { + struct substruct s; + int x; +}; + +struct outerstruct +substruct_test (void) +{ + struct outerstruct outer; + outer.s.a = 0; + outer.s.b = 0; + outer.x = 0; + + outer.s.a = 3; /* MI outer breakpoint here */ + + return outer; +} + +typedef struct string_repr +{ + struct whybother + { + const char *contents; + } whybother; +} string; + +/* This lets us avoid malloc. */ +int array[100]; +int narray[10]; + +struct justchildren +{ + int len; + int *elements; +}; + +typedef struct justchildren nostring_type; + +struct memory_error +{ + const char *s; +}; + +struct container +{ + string name; + int len; + int *elements; +}; + +typedef struct container zzz_type; + +string +make_string (const char *s) +{ + string result; + result.whybother.contents = s; + return result; +} + +zzz_type +make_container (const char *s) +{ + zzz_type result; + + result.name = make_string (s); + result.len = 0; + result.elements = 0; + + return result; +} + +void +add_item (zzz_type *c, int val) +{ + if (c->len == 0) + c->elements = array; + c->elements[c->len] = val; + ++c->len; +} + +void +set_item(zzz_type *c, int i, int val) +{ + if (i < c->len) + c->elements[i] = val; +} + +void init_s(struct s *s, int a) +{ + s->a = a; + s->b = &s->a; +} + +void init_ss(struct ss *s, int a, int b) +{ + init_s(&s->a, a); + init_s(&s->b, b); +} + +void do_nothing(void) +{ + int c; + + c = 23; /* Another MI breakpoint */ +} + +struct nullstr +{ + char *s; +}; + +struct string_repr string_1 = { { "one" } }; +struct string_repr string_2 = { { "two" } }; + +static int +eval_func (int p1, int p2, int p3, int p4, int p5, int p6, int p7, int p8) +{ + return p1; +} + +static void +eval_sub (void) +{ + struct eval_type_s { int x; } eval1 = { 1 }, eval2 = { 2 }, eval3 = { 3 }, + eval4 = { 4 }, eval5 = { 5 }, eval6 = { 6 }, + eval7 = { 7 }, eval8 = { 8 }, eval9 = { 9 }; + + eval1.x++; /* eval-break */ +} + +static void +bug_14741() +{ + zzz_type c = make_container ("bug_14741"); + add_item (&c, 71); + set_item(&c, 0, 42); /* breakpoint bug 14741 */ + set_item(&c, 0, 5); +} + +int +main () +{ + struct ss ss; + struct ss ssa[2]; + struct arraystruct arraystruct; + string x = make_string ("this is x"); + zzz_type c = make_container ("container"); + zzz_type c2 = make_container ("container2"); + const struct string_repr cstring = { { "const string" } }; + /* Clearing by being `static' could invoke an other GDB C++ bug. */ + struct nullstr nullstr; + nostring_type nstype, nstype2; + struct memory_error me; + struct ns ns, ns2; + struct lazystring estring, estring2; + struct hint_error hint_error; + struct children_as_list children_as_list; + + nstype.elements = narray; + nstype.len = 0; + + me.s = "blah"; + + init_ss(&ss, 1, 2); + init_ss(ssa+0, 3, 4); + init_ss(ssa+1, 5, 6); + memset (&nullstr, 0, sizeof nullstr); + + arraystruct.y = 7; + init_s (&arraystruct.x[0], 23); + init_s (&arraystruct.x[1], 24); + + ns.null_str = "embedded\0null\0string"; + ns.length = 20; + + /* Make a "corrupted" string. */ + ns2.null_str = NULL; + ns2.length = 20; + + estring.lazy_str = "embedded x\201\202\203\204" ; + + /* Incomplete UTF-8, but ok Latin-1. */ + estring2.lazy_str = "embedded x\302"; + +#ifdef __cplusplus + S cps; + + cps.zs = 7; + init_s(&cps, 8); + + SS cpss; + cpss.zss = 9; + init_s(&cpss.s, 10); + + SS cpssa[2]; + cpssa[0].zss = 11; + init_s(&cpssa[0].s, 12); + cpssa[1].zss = 13; + init_s(&cpssa[1].s, 14); + + SSS sss(15, cps); + + SSS& ref (sss); + + Derived derived; + + Fake fake (42); +#endif + + add_item (&c, 23); /* MI breakpoint here */ + add_item (&c, 72); + +#ifdef MI + add_item (&c, 1011); + c.elements[0] = 1023; + c.elements[0] = 2323; + + add_item (&c2, 2222); + add_item (&c2, 3333); + + substruct_test (); + do_nothing (); +#endif + + nstype.elements[0] = 7; + nstype.elements[1] = 42; + nstype.len = 2; + + nstype2 = nstype; + + eval_sub (); + + bug_14741(); /* break to inspect struct and union */ + return 0; +} diff --git a/gdb/testsuite/gdb.guile/scm-pretty-print.exp b/gdb/testsuite/gdb.guile/scm-pretty-print.exp new file mode 100644 index 0000000..cd3ae95 --- /dev/null +++ b/gdb/testsuite/gdb.guile/scm-pretty-print.exp @@ -0,0 +1,148 @@ +# Copyright (C) 2008-2014 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/>. + +# This file is part of the GDB testsuite. +# It tests Guile-based pretty-printing for the CLI. + +load_lib gdb-guile.exp + +standard_testfile + +# Start with a fresh gdb. +gdb_exit +gdb_start + +# Skip all tests if Guile scripting is not enabled. +if { [skip_guile_tests] } { continue } + +proc run_lang_tests {exefile lang} { + global srcdir subdir srcfile testfile hex + if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${exefile}" executable "debug $lang"] != "" } { + untested "Couldn't compile ${srcfile} in $lang mode" + return + } + + set nl "\[\r\n\]+" + + # Start with a fresh gdb. + gdb_exit + gdb_start + gdb_reinitialize_dir $srcdir/$subdir + gdb_load ${exefile} + + if ![gdb_guile_runto_main] { + return + } + + gdb_test_no_output "set print pretty on" + + gdb_test "b [gdb_get_line_number {break to inspect} ${testfile}.c ]" \ + ".*Breakpoint.*" + gdb_test "continue" ".*Breakpoint.*" + + set remote_scheme_file [gdb_remote_download host \ + ${srcdir}/${subdir}/${testfile}.scm] + + gdb_scm_load_file ${remote_scheme_file} + + gdb_test "print ss" " = a=<a=<1> b=<$hex>> b=<a=<2> b=<$hex>>" + gdb_test "print ssa\[1\]" " = a=<a=<5> b=<$hex>> b=<a=<6> b=<$hex>>" + gdb_test "print ssa" " = {a=<a=<3> b=<$hex>> b=<a=<4> b=<$hex>>, a=<a=<5> b=<$hex>> b=<a=<6> b=<$hex>>}" + + gdb_test "print arraystruct" " = {$nl *y = 7, *$nl *x = {a=<23> b=<$hex>, a=<24> b=<$hex>} *$nl *}" + + if {$lang == "c++"} { + gdb_test "print cps" "= a=<8> b=<$hex>" + gdb_test "print cpss" " = {$nl *zss = 9, *$nl *s = a=<10> b=<$hex>$nl}" + gdb_test "print cpssa\[0\]" " = {$nl *zss = 11, *$nl *s = a=<12> b=<$hex>$nl}" + gdb_test "print cpssa\[1\]" " = {$nl *zss = 13, *$nl *s = a=<14> b=<$hex>$nl}" + gdb_test "print cpssa" " = {{$nl *zss = 11, *$nl *s = a=<12> b=<$hex>$nl *}, {$nl *zss = 13, *$nl *s = a=<14> b=<$hex>$nl *}}" + gdb_test "print sss" "= a=<15> b=<a=<8> b=<$hex>>" + gdb_test "print ref" "= a=<15> b=<a=<8> b=<$hex>>" + gdb_test "print derived" \ + " = \{.*<Vbase1> = pp class name: Vbase1.*<Vbase2> = \{.*<VirtualTest> = pp value variable is: 1,.*members of Vbase2:.*_vptr.Vbase2 = $hex.*<Vbase3> = \{.*members of Vbase3.*members of Derived:.*value = 2.*" + gdb_test "print ns " "\"embedded\\\\000null\\\\000string\"" + gdb_scm_test_silent_cmd "set print elements 3" "" 1 + gdb_test "print ns" "emb\.\.\.." + gdb_scm_test_silent_cmd "set print elements 10" "" 1 + gdb_test "print ns" "embedded\\\\000n\.\.\.." + gdb_scm_test_silent_cmd "set print elements 200" "" 1 + } + + gdb_test "print ns2" "<error reading variable: ERROR: Cannot access memory at address 0x0>" + + gdb_test "print x" " = \"this is x\"" + gdb_test "print cstring" " = \"const string\"" + + gdb_test "print estring" " = \"embedded x\\\\201\\\\202\\\\203\\\\204\"" + + gdb_test_no_output "guile (set! *pp-ls-encoding* \"UTF-8\")" + gdb_test "print estring2" "\"embedded \", <incomplete sequence \\\\302>" + + gdb_test_no_output "set guile print-stack full" + gdb_test "print hint_error" "ERROR: Invalid display hint: 42\r\nhint_error_val" + + gdb_test "print c" " = container \"container\" with 2 elements = {$nl *.0. = 23,$nl *.1. = 72$nl}" + + gdb_test "print nstype" " = {$nl *.0. = 7,$nl *.1. = 42$nl}" + + gdb_test_no_output "set print pretty off" + gdb_test "print nstype" " = {.0. = 7, .1. = 42}" \ + "print nstype on one line" + + gdb_continue_to_end +} + +run_lang_tests "${binfile}" "c" +run_lang_tests "${binfile}-cxx" "c++" + +# Run various other tests. + +# Start with a fresh gdb. +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +if ![gdb_guile_runto_main] { + return +} + +set remote_scheme_file [gdb_remote_download host \ + ${srcdir}/${subdir}/${testfile}.scm] + +gdb_scm_load_file ${remote_scheme_file} + +gdb_breakpoint [gdb_get_line_number "eval-break"] +gdb_continue_to_breakpoint "eval-break" ".* eval-break .*" + +gdb_test "info locals" "eval9 = eval=<123456789>" + +gdb_test "b [gdb_get_line_number {break to inspect} ${testfile}.c ]" \ + ".*Breakpoint.*" +gdb_test "continue" ".*Breakpoint.*" + +gdb_test "print ss" " = a=<a=<1> b=<$hex>> b=<a=<2> b=<$hex>>" \ + "print ss enabled #1" + +gdb_test_no_output "guile (disable-matcher!)" + +gdb_test "print ss" " = {a = {a = 1, b = $hex}, b = {a = 2, b = $hex}}" \ + "print ss disabled" + +gdb_test_no_output "guile (enable-matcher!)" + +gdb_test "print ss" " = a=<a=<1> b=<$hex>> b=<a=<2> b=<$hex>>" \ + "print ss enabled #2" diff --git a/gdb/testsuite/gdb.guile/scm-pretty-print.scm b/gdb/testsuite/gdb.guile/scm-pretty-print.scm new file mode 100644 index 0000000..a42527c --- /dev/null +++ b/gdb/testsuite/gdb.guile/scm-pretty-print.scm @@ -0,0 +1,301 @@ +;; Copyright (C) 2008-2014 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/>. + +;; This file is part of the GDB testsuite. +;; It tests Scheme pretty printers. + +(use-modules (gdb) (gdb printing)) + +(define (make-pointer-iterator pointer len) + (let ((next! (lambda (iter) + (let* ((start (iterator-object iter)) + (progress (iterator-progress iter)) + (current (car progress)) + (len (cdr progress))) + (if (= current len) + (end-of-iteration) + (let ((pointer (value-add start current))) + (set-car! progress (+ current 1)) + (cons (format #f "[~A]" current) + (value-dereference pointer)))))))) + (make-iterator pointer (cons 0 len) next!))) + +(define (make-pointer-iterator-except pointer len) + (let ((next! (lambda (iter) + (if *exception-flag* + (throw 'gdb:memory-error "hi bob")) + (let* ((start (iterator-object iter)) + (progress (iterator-progress iter)) + (current (car progress)) + (len (cdr progress))) + (if (= current len) + (end-of-iteration) + (let ((pointer (value-add start current))) + (set-car! progress (+ current 1)) + (cons (format #f "[~A]" current) + (value-dereference pointer)))))))) + (make-iterator pointer (cons 0 len) next!))) + +;; Test returning a <gdb:value> from a printer. + +(define (make-string-printer val) + (make-pretty-printer-worker + #f + (lambda (printer) + (value-field (value-field val "whybother") + "contents")) + #f)) + +;; Test a printer with children. + +(define (make-container-printer val) + ;; This is a little different than the Python version in that if there's + ;; an error accessing these fields we'll throw it at matcher time instead + ;; of at printer time. Done this way to explore the possibilities. + (let ((name (value-field val "name")) + (len (value-field val "len")) + (elements (value-field val "elements"))) + (make-pretty-printer-worker + #f + (lambda (printer) + (format #f "container ~A with ~A elements" + name len)) + (lambda (printer) + (make-pointer-iterator elements (value->integer len)))))) + +;; Test "array" display hint. + +(define (make-array-printer val) + (let ((name (value-field val "name")) + (len (value-field val "len")) + (elements (value-field val "elements"))) + (make-pretty-printer-worker + "array" + (lambda (printer) + (format #f "array ~A with ~A elements" + name len)) + (lambda (printer) + (make-pointer-iterator elements (value->integer len)))))) + +;; Flag to make no-string-container printer throw an exception. + +(define *exception-flag* #f) + +;; Test a printer where to_string returns #f. + +(define (make-no-string-container-printer val) + (let ((len (value-field val "len")) + (elements (value-field val "elements"))) + (make-pretty-printer-worker + #f + (lambda (printer) #f) + (lambda (printer) + (make-pointer-iterator-except elements (value->integer len)))))) + +(define (make-pp_s-printer val) + (make-pretty-printer-worker + #f + (lambda (printer) + (let ((a (value-field val "a")) + (b (value-field val "b"))) + (if (not (value=? (value-address a) b)) + (error (format #f "&a(~A) != b(~A)" + (value-address a) b))) + (format #f "a=<~A> b=<~A>" a b))) + #f)) + +(define (make-pp_ss-printer val) + (make-pretty-printer-worker + #f + (lambda (printer) + (let ((a (value-field val "a")) + (b (value-field val "b"))) + (format #f "a=<~A> b=<~A>" a b))) + #f)) + +(define (make-pp_sss-printer val) + (make-pretty-printer-worker + #f + (lambda (printer) + (let ((a (value-field val "a")) + (b (value-field val "b"))) + (format #f "a=<~A> b=<~A>" a b))) + #f)) + +(define (make-pp_multiple_virtual-printer val) + (make-pretty-printer-worker + #f + (lambda (printer) + (format #f "pp value variable is: ~A" (value-field val "value"))) + #f)) + +(define (make-pp_vbase1-printer val) + (make-pretty-printer-worker + #f + (lambda (printer) + (format #f "pp class name: ~A" (type-tag (value-type val)))) + #f)) + +(define (make-pp_nullstr-printer val) + (make-pretty-printer-worker + #f + (lambda (printer) + (value->string (value-field val "s") + #:encoding (arch-charset (current-arch)))) + #f)) + +(define (make-pp_ns-printer val) + (make-pretty-printer-worker + "string" + (lambda (printer) + (let ((len (value-field val "length"))) + (value->string (value-field val "null_str") + #:encoding (arch-charset (current-arch)) + #:length (value->integer len)))) + #f)) + +(define *pp-ls-encoding* #f) + +(define (make-pp_ls-printer val) + (make-pretty-printer-worker + "string" + (lambda (printer) + (if *pp-ls-encoding* + (value->lazy-string (value-field val "lazy_str") + #:encoding *pp-ls-encoding*) + (value->lazy-string (value-field val "lazy_str")))) + #f)) + +(define (make-pp_hint_error-printer val) + "Use an invalid value for the display hint." + (make-pretty-printer-worker + 42 + (lambda (printer) "hint_error_val") + #f)) + +(define (make-pp_children_as_list-printer val) + (make-pretty-printer-worker + #f + (lambda (printer) "children_as_list_val") + (lambda (printer) (make-list-iterator (list (cons "one" 1)))))) + +(define (make-pp_outer-printer val) + (make-pretty-printer-worker + #f + (lambda (printer) + (format #f "x = ~A" (value-field val "x"))) + (lambda (printer) + (make-list-iterator (list (cons "s" (value-field val "s")) + (cons "x" (value-field val "x"))))))) + +(define (make-memory-error-string-printer val) + (make-pretty-printer-worker + "string" + (lambda (printer) + (scm-error 'gdb:memory-error "memory-error-printer" + "Cannot access memory." '() '())) + #f)) + +(define (make-pp_eval_type-printer val) + (make-pretty-printer-worker + #f + (lambda (printer) + (execute "bt" #:to-string #t) + (format #f "eval=<~A>" + (value-print + (parse-and-eval + "eval_func (123456789, 2, 3, 4, 5, 6, 7, 8)")))) + #f)) + +(define (get-type-for-printing val) + "Return type of val, stripping away typedefs, etc." + (let ((type (value-type val))) + (if (= (type-code type) TYPE_CODE_REF) + (set! type (type-target type))) + (type-strip-typedefs (type-unqualified type)))) + +(define (disable-matcher!) + (set-pretty-printer-enabled! *pretty-printer* #f)) + +(define (enable-matcher!) + (set-pretty-printer-enabled! *pretty-printer* #t)) + +(define (make-pretty-printer-dict) + (let ((dict (make-hash-table))) + (hash-set! dict "struct s" make-pp_s-printer) + (hash-set! dict "s" make-pp_s-printer) + (hash-set! dict "S" make-pp_s-printer) + + (hash-set! dict "struct ss" make-pp_ss-printer) + (hash-set! dict "ss" make-pp_ss-printer) + (hash-set! dict "const S &" make-pp_s-printer) + (hash-set! dict "SSS" make-pp_sss-printer) + + (hash-set! dict "VirtualTest" make-pp_multiple_virtual-printer) + (hash-set! dict "Vbase1" make-pp_vbase1-printer) + + (hash-set! dict "struct nullstr" make-pp_nullstr-printer) + (hash-set! dict "nullstr" make-pp_nullstr-printer) + + ;; Note that we purposely omit the typedef names here. + ;; Printer lookup is based on canonical name. + ;; However, we do need both tagged and untagged variants, to handle + ;; both the C and C++ cases. + (hash-set! dict "struct string_repr" make-string-printer) + (hash-set! dict "struct container" make-container-printer) + (hash-set! dict "struct justchildren" make-no-string-container-printer) + (hash-set! dict "string_repr" make-string-printer) + (hash-set! dict "container" make-container-printer) + (hash-set! dict "justchildren" make-no-string-container-printer) + + (hash-set! dict "struct ns" make-pp_ns-printer) + (hash-set! dict "ns" make-pp_ns-printer) + + (hash-set! dict "struct lazystring" make-pp_ls-printer) + (hash-set! dict "lazystring" make-pp_ls-printer) + + (hash-set! dict "struct outerstruct" make-pp_outer-printer) + (hash-set! dict "outerstruct" make-pp_outer-printer) + + (hash-set! dict "struct hint_error" make-pp_hint_error-printer) + (hash-set! dict "hint_error" make-pp_hint_error-printer) + + (hash-set! dict "struct children_as_list" + make-pp_children_as_list-printer) + (hash-set! dict "children_as_list" make-pp_children_as_list-printer) + + (hash-set! dict "memory_error" make-memory-error-string-printer) + + (hash-set! dict "eval_type_s" make-pp_eval_type-printer) + + dict)) + +;; This is one way to register a printer that is composed of several +;; subprinters, but there's no way to disable or list individual subprinters. + +(define *pretty-printer* + (make-pretty-printer + "pretty-printer-test" + (let ((pretty-printers-dict (make-pretty-printer-dict))) + (lambda (matcher val) + "Look-up and return a pretty-printer that can print val." + (let ((type (get-type-for-printing val))) + (let ((typename (type-tag type))) + (if typename + (let ((printer-maker (hash-ref pretty-printers-dict typename))) + (and printer-maker (printer-maker val))) + #f))))))) + +(append-pretty-printer! #f *pretty-printer*) diff --git a/gdb/testsuite/gdb.guile/scm-section-script.c b/gdb/testsuite/gdb.guile/scm-section-script.c new file mode 100644 index 0000000..8a1ede9 --- /dev/null +++ b/gdb/testsuite/gdb.guile/scm-section-script.c @@ -0,0 +1,55 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2010-2014 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 "symcat.h" +#include "gdb/section-scripts.h" + +/* Put the path to the pretty-printer script in .debug_gdb_scripts so + gdb will automagically loaded it. */ + +#define DEFINE_GDB_SCRIPT(script_name) \ + asm("\ +.pushsection \".debug_gdb_scripts\", \"MS\",@progbits,1\n\ +.byte " XSTRING (SECTION_SCRIPT_ID_SCHEME_FILE) "\n\ +.asciz \"" script_name "\"\n\ +.popsection \n\ +"); + +DEFINE_GDB_SCRIPT (SCRIPT_FILE) + +struct ss +{ + int a; + int b; +}; + +void +init_ss (struct ss *s, int a, int b) +{ + s->a = a; + s->b = b; +} + +int +main () +{ + struct ss ss; + + init_ss (&ss, 1, 2); + + return 0; /* break to inspect struct and union */ +} diff --git a/gdb/testsuite/gdb.guile/scm-section-script.exp b/gdb/testsuite/gdb.guile/scm-section-script.exp new file mode 100644 index 0000000..0c5e489 --- /dev/null +++ b/gdb/testsuite/gdb.guile/scm-section-script.exp @@ -0,0 +1,80 @@ +# Copyright (C) 2010-2014 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/>. + +# This file is part of the GDB testsuite. It tests automagic loading of +# scripts specified in the .debug_gdb_scripts section. + +# This test can only be run on targets which support ELF and use gas. +# For now pick a sampling of likely targets. +if {![istarget *-*-linux*] + && ![istarget *-*-gnu*] + && ![istarget *-*-elf*] + && ![istarget *-*-openbsd*] + && ![istarget arm*-*-eabi*] + && ![istarget arm*-*-symbianelf*] + && ![istarget powerpc-*-eabi*]} { + verbose "Skipping scm-section-script.exp because of lack of support." + return +} + +load_lib gdb-guile.exp + +standard_testfile + +# Make this available to gdb before the program starts, it is +# automagically loaded by gdb. +# Give the file a new name so we don't clobber the real one if +# objfile == srcdir. +# We also need to do this before compiling the program because the name +# of the script file is encoded in the binary. +# FIXME: Can we get gdb_remote_download to call standard_output_file for us? +set remote_guile_file [gdb_remote_download host \ + ${srcdir}/${subdir}/${testfile}.scm \ + ${subdir}/t-${testfile}.scm] + +if {[build_executable $testfile.exp $testfile $srcfile \ + [list debug "additional_flags=-I${srcdir}/../../include -DSCRIPT_FILE=\"$remote_guile_file\""]] == -1} { + return +} + +# Start with a fresh gdb. +gdb_exit +gdb_start + +# Skip all tests if Guile scripting is not enabled. +if { [skip_guile_tests] } { continue } + +gdb_reinitialize_dir $srcdir/$subdir +gdb_test_no_output "set auto-load safe-path ${remote_guile_file}" \ + "set auto-load safe-path" +gdb_load ${binfile} + +# Verify gdb loaded the script. +gdb_test "info auto-load guile-scripts" "Yes.*${testfile}.scm.*" +# Again, with a regexp this time. +gdb_test "info auto-load guile-scripts ${testfile}" "Yes.*${testfile}.scm.*" +# Again, with a regexp that matches no scripts. +gdb_test "info auto-load guile-scripts no-script-matches-this" \ + "No auto-load scripts matching no-script-matches-this." + +if ![gdb_guile_runto_main] { + return +} + +gdb_test "b [gdb_get_line_number {break to inspect} ${testfile}.c ]" \ + ".*Breakpoint.*" +gdb_test "continue" ".*Breakpoint.*" + +gdb_test "print ss" " = a=<1> b=<2>" diff --git a/gdb/testsuite/gdb.guile/scm-section-script.scm b/gdb/testsuite/gdb.guile/scm-section-script.scm new file mode 100644 index 0000000..cd31db9 --- /dev/null +++ b/gdb/testsuite/gdb.guile/scm-section-script.scm @@ -0,0 +1,55 @@ +;; Copyright (C) 2010-2014 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/>. + +;; This file is part of the GDB testsuite. + +(use-modules (gdb) (gdb printing)) + +(define (make-pp_ss-printer val) + (make-pretty-printer-worker + #f + (lambda (printer) + (let ((a (value-field val "a")) + (b (value-field val "b"))) + (format #f "a=<~A> b=<~A>" a b))) + #f)) + +(define (get-type-for-printing val) + "Return type of val, stripping away typedefs, etc." + (let ((type (value-type val))) + (if (= (type-code type) TYPE_CODE_REF) + (set! type (type-target type))) + (type-strip-typedefs (type-unqualified type)))) + +(define (make-pretty-printer-dict) + (let ((dict (make-hash-table))) + (hash-set! dict "struct ss" make-pp_ss-printer) + (hash-set! dict "ss" make-pp_ss-printer) + dict)) + +(define *pretty-printer* + (make-pretty-printer + "pretty-printer-test" + (let ((pretty-printers-dict (make-pretty-printer-dict))) + (lambda (matcher val) + "Look-up and return a pretty-printer that can print val." + (let ((type (get-type-for-printing val))) + (let ((typename (type-tag type))) + (if typename + (let ((printer-maker (hash-ref pretty-printers-dict typename))) + (and printer-maker (printer-maker val))) + #f))))))) + +(append-pretty-printer! #f *pretty-printer*) diff --git a/gdb/testsuite/gdb.guile/scm-symbol.c b/gdb/testsuite/gdb.guile/scm-symbol.c new file mode 100644 index 0000000..3201365 --- /dev/null +++ b/gdb/testsuite/gdb.guile/scm-symbol.c @@ -0,0 +1,69 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2010-2014 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/>. */ + +#ifdef __cplusplus +class SimpleClass +{ + private: + int i; + + public: + void seti (int arg) + { + i = arg; + } + + int valueofi (void) + { + return i; /* Break in class. */ + } +}; +#endif + +int qq = 72; /* line of qq */ + +int func (int arg) +{ + int i = 2; + i = i * arg; /* Block break here. */ + return arg; +} + +struct simple_struct +{ + int a; +}; + +int main (int argc, char *argv[]) +{ +#ifdef __cplusplus + SimpleClass sclass; +#endif + int a = 0; + int result; + struct simple_struct ss = { 10 }; + enum tag {one, two, three}; + enum tag t = one; + + result = func (42); + +#ifdef __cplusplus + sclass.seti (42); + sclass.valueofi (); +#endif + return 0; /* Break at end. */ +} diff --git a/gdb/testsuite/gdb.guile/scm-symbol.exp b/gdb/testsuite/gdb.guile/scm-symbol.exp new file mode 100644 index 0000000..5d25c53 --- /dev/null +++ b/gdb/testsuite/gdb.guile/scm-symbol.exp @@ -0,0 +1,196 @@ +# Copyright (C) 2010-2014 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/>. + +# This file is part of the GDB testsuite. +# It tests the mechanism exposing symbols to Guile. + +load_lib gdb-guile.exp + +standard_testfile + +if {[prepare_for_testing $testfile.exp $testfile $srcfile debug]} { + return -1 +} + +# Skip all tests if Guile scripting is not enabled. +if { [skip_guile_tests] } { continue } + +# These tests are done before we call gdb_guile_runto_main so we have to +# import the gdb module ourselves. +gdb_install_guile_utils +gdb_install_guile_module + +# Test looking up a global symbol before we runto_main as this is the +# point where we don't have a current frame, and we don't want to +# require one. +gdb_scm_test_silent_cmd "guile (define main-func (lookup-global-symbol \"main\"))" \ + "lookup main" +gdb_test "guile (print (symbol-function? main-func))" \ + "= #t" "test (symbol-function? main)" +gdb_test "guile (print (lookup-global-symbol \"junk\"))" \ + "= #f" "test (lookup-global-symbol junk)" + +gdb_test "guile (print (symbol-value main-func))" \ + "= {int \\(int, char \[*\]\[*\]\\)} $hex \\<main\\>" "print value of main" + +set qq_line [gdb_get_line_number "line of qq"] +gdb_scm_test_silent_cmd "guile (define qq-var (lookup-global-symbol \"qq\"))" \ + "lookup qq" +gdb_test "guile (print (symbol-line qq-var))" \ + "= $qq_line" "print line number of qq" +gdb_test "guile (print (symbol-value qq-var))" \ + "= 72" "print value of qq" +gdb_test "guile (print (symbol-needs-frame? qq-var))" \ + "= #f" "print whether qq needs a frame" + +if ![gdb_guile_runto_main] { + return +} + +# Test symbol eq? and equal?. +gdb_test "guile (print (eq? (lookup-global-symbol \"main\") (lookup-global-symbol \"main\")))" \ + "= #t" +gdb_test "guile (print (equal? (lookup-global-symbol \"main\") (lookup-global-symbol \"main\")))" \ + "= #t" + +gdb_breakpoint [gdb_get_line_number "Block break here."] +gdb_continue_to_breakpoint "Block break here." +gdb_scm_test_silent_cmd "guile (define frame (selected-frame))" \ + "get frame at block break" +gdb_scm_test_silent_cmd "guile (define block (frame-block frame))" \ + "get block at block break" + +# Test symbol-argument?. +gdb_scm_test_silent_cmd "guile (define arg (car (lookup-symbol \"arg\")))" \ + "get variable arg" +gdb_test "guile (print (symbol-variable? arg))" "= #f" +gdb_test "guile (print (symbol-constant? arg))" "= #f" +gdb_test "guile (print (symbol-argument? arg))" "= #t" +gdb_test "guile (print (symbol-function? arg))" "= #f" + +# Test symbol-function?. +gdb_scm_test_silent_cmd "guile (define func (block-function block))" \ + "get block function" +gdb_test "guile (print (symbol-variable? func))" "= #f" +gdb_test "guile (print (symbol-constant? func))" "= #f" +gdb_test "guile (print (symbol-argument? func))" "= #f" +gdb_test "guile (print (symbol-function? func))" "= #t" + +# Test attributes of func. +gdb_test "guile (print (symbol-name func))" "func" +gdb_test "guile (print (symbol-print-name func))" "func" +gdb_test "guile (print (symbol-linkage-name func))" "func" +gdb_test "guile (print (= (symbol-addr-class func) SYMBOL_LOC_BLOCK))" "= #t" + +gdb_breakpoint [gdb_get_line_number "Break at end."] +gdb_continue_to_breakpoint "Break at end." +gdb_scm_test_silent_cmd "guile (define frame (selected-frame))" \ + "get frame at end" + +# Test symbol-variable?. +gdb_scm_test_silent_cmd "guile (define a (car (lookup-symbol \"a\")))" \ + "get variable a" +gdb_test "guile (print (symbol-variable? a))" "= #t" +gdb_test "guile (print (symbol-constant? a))" "= #f" +gdb_test "guile (print (symbol-argument? a))" "= #f" +gdb_test "guile (print (symbol-function? a))" "= #f" + +# Test attributes of a. +gdb_test "guile (print (= (symbol-addr-class a) SYMBOL_LOC_COMPUTED))" "= #t" + +gdb_test "guile (print (symbol-value a))" \ + "ERROR: Symbol requires a frame to compute its value.*"\ + "try to print value of a without a frame" +gdb_test "guile (print (symbol-value a #:frame frame))" \ + "= 0" "print value of a" +gdb_test "guile (print (symbol-needs-frame? a))" \ + "= #t" "print whether a needs a frame" + +# Test symbol-constant?. +gdb_scm_test_silent_cmd "guile (define t (car (lookup-symbol \"one\")))" \ + "get constant t" +gdb_test "guile (print (symbol-variable? t))" "= #f" +gdb_test "guile (print (symbol-constant? t))" "= #t" +gdb_test "guile (print (symbol-argument? t))" "= #f" +gdb_test "guile (print (symbol-function? t))" "= #f" + +# Test attributes of t. +gdb_test "guile (print (= (symbol-addr-class t) SYMBOL_LOC_CONST))" "= #t" + +# Test type attribute. +gdb_test "guile (print (symbol-type t))" "= enum tag" + +# Test symtab attribute. +gdb_test "guile (print (symbol-symtab t))" "= #<gdb:symtab .*gdb.guile/scm-symbol.c>" + +# C++ tests +# Recompile binary. +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}-cxx" executable "debug c++"] != "" } { + untested "Couldn't compile ${srcfile} in c++ mode" + return -1 +} + +# Start with a fresh gdb. +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile}-cxx + +if ![gdb_guile_runto_main] { + return +} + +gdb_breakpoint [gdb_get_line_number "Break in class."] +gdb_continue_to_breakpoint "Break in class." + +gdb_scm_test_silent_cmd "guile (define cplusframe (selected-frame))" \ + "get frame at class" +gdb_scm_test_silent_cmd "guile (define cplusfunc (block-function (frame-block cplusframe)))" \ + "get function at class" + +gdb_test "guile (print (symbol-variable? cplusfunc))" "= #f" +gdb_test "guile (print (symbol-constant? cplusfunc))" "= #f" +gdb_test "guile (print (symbol-argument? cplusfunc))" "= #f" +gdb_test "guile (print (symbol-function? cplusfunc))" "= #t" + +gdb_test "guile (print (symbol-name cplusfunc))" \ + "= SimpleClass::valueofi().*" "test method.name" +gdb_test "guile (print (symbol-print-name cplusfunc))" \ + "= SimpleClass::valueofi().*" "test method.print_name" +# FIXME: GDB is broken here and we're verifying broken behaviour. +# (linkage-name should be the mangled name) +gdb_test "guile (print (symbol-linkage-name cplusfunc))" \ + "SimpleClass::valueofi().*" "test method.linkage_name" +gdb_test "guile (print (= (symbol-addr-class cplusfunc) SYMBOL_LOC_BLOCK))" "= #t" + +# Test is_valid when the objfile is unloaded. This must be the last +# test as it unloads the object file in GDB. +# Start with a fresh gdb. +clean_restart ${testfile} +if ![gdb_guile_runto_main] { + return +} + +gdb_breakpoint [gdb_get_line_number "Break at end."] +gdb_continue_to_breakpoint "Break at end." +gdb_scm_test_silent_cmd "guile (define a (car (lookup-symbol \"a\")))" \ + "get variable a for unload" +gdb_test "guile (print (symbol-valid? a))" \ + "= #t" "test symbol validity pre-unload" +delete_breakpoints +gdb_unload +gdb_test "guile (print (symbol-valid? a))" \ + "= #f" "test symbol validity post-unload" +gdb_test_no_output "guile (set! a #f) (gc)" "test symbol destructor" diff --git a/gdb/testsuite/gdb.guile/scm-symtab-2.c b/gdb/testsuite/gdb.guile/scm-symtab-2.c new file mode 100644 index 0000000..d45aa6c --- /dev/null +++ b/gdb/testsuite/gdb.guile/scm-symtab-2.c @@ -0,0 +1,28 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2010-2014 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/>. */ + +void +func1 () +{ + return; +} + +int +func2 () +{ + return 0; +} diff --git a/gdb/testsuite/gdb.guile/scm-symtab.c b/gdb/testsuite/gdb.guile/scm-symtab.c new file mode 100644 index 0000000..e4662cd --- /dev/null +++ b/gdb/testsuite/gdb.guile/scm-symtab.c @@ -0,0 +1,45 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2010-2014 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/>. */ + +/* In scm-symtab-2.c. */ +extern void func1 (void); +extern int func2 (void); + +struct simple_struct +{ + int a; +}; + +struct simple_struct qq; + +int +func (int arg) +{ + int i = 2; + i = i * arg; /* Block break here. */ + return arg; +} + +int +main (int argc, char *argv[]) +{ + qq.a = func (42); + + func1 (); + func2 (); /* Break at func2 call site. */ + return 0; /* Break to end. */ +} diff --git a/gdb/testsuite/gdb.guile/scm-symtab.exp b/gdb/testsuite/gdb.guile/scm-symtab.exp new file mode 100644 index 0000000..4309ae6 --- /dev/null +++ b/gdb/testsuite/gdb.guile/scm-symtab.exp @@ -0,0 +1,142 @@ +# Copyright (C) 2010-2014 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/>. + +# This file is part of the GDB testsuite. +# It tests the Guile symbol table support. + +load_lib gdb-guile.exp + +standard_testfile scm-symtab.c scm-symtab-2.c + +if {[prepare_for_testing $testfile.exp $testfile \ + [list $srcfile $srcfile2] debug]} { + return +} + +# Skip all tests if Guile scripting is not enabled. +if { [skip_guile_tests] } { continue } + +if ![gdb_guile_runto_main] { + return +} + +# Setup and get the symbol table. +set line_no [gdb_get_line_number "Block break here."] +gdb_breakpoint $line_no +gdb_continue_to_breakpoint "Block break here." +gdb_scm_test_silent_cmd "guile (define frame (selected-frame))" \ + "get frame" +gdb_scm_test_silent_cmd "guile (define sal (frame-sal frame))" \ + "get sal" +gdb_scm_test_silent_cmd "guile (define symtab (sal-symtab sal))" \ + "get symtab" +gdb_scm_test_silent_cmd "guile (define global-block (symtab-global-block symtab))" \ + "get global block" +gdb_scm_test_silent_cmd "guile (define static-block (symtab-static-block symtab))" \ + "get static block" + +gdb_scm_test_silent_cmd "guile (define global-symbols (map symbol-name (block-symbols global-block)))" \ + "get global symbol names" +gdb_scm_test_silent_cmd "guile (define static-symbols (map symbol-name (block-symbols static-block)))" \ + "get static symbol names" +gdb_scm_test_silent_cmd "guile (define global-isymbols '()) (define static-isymbols '())" \ + "set up iterated symbol name lists" +# TODO: iterated symbols +gdb_scm_test_silent_cmd "step" "Step to the next line" +gdb_scm_test_silent_cmd "guile (define new-pc (sal-pc (frame-sal (selected-frame))))" \ + "get new pc" + +# Test sal. +gdb_test "guile (print (sal-symtab sal))" \ + ".*gdb.guile/scm-symtab.c.*" "Test sal-symtab" +gdb_test "guile (print (sal-pc sal))" \ + "${decimal}" "test sal-pc" +gdb_test "guile (print (= (sal-last sal) (- new-pc 1)))" \ + "#t" "test sal-last" +gdb_test "guile (print (sal-line sal))" \ + "$line_no" "test sal-line" +gdb_test "guile (print (sal-valid? sal))" \ + "#t" "test sal-valid?" + +# Test eq? on symtabs. +gdb_scm_test_silent_cmd "guile (define sal1 (frame-sal frame))" \ + "get sal1" +gdb_scm_test_silent_cmd "guile (define sal2 (frame-sal (frame-older frame)))" \ + "get sal2" +gdb_test "guile (print (eq? symtab (sal-symtab sal1)))" \ + "= #t" "test eq? of equal symtabs" +gdb_test "guile (print (eq? symtab (sal-symtab sal2)))" \ + "= #t" "test eq? of equal symtabs from different sals" +gdb_test "guile (print (eq? symtab (symbol-symtab (lookup-global-symbol \"func1\"))))" \ + "= #f" "test eq? of not-equal symtabs" + +# Test symbol table. +gdb_test "guile (print (symtab-filename symtab))" \ + ".*gdb.guile/scm-symtab.c.*" "test symtab-filename" +gdb_test "guile (print (symtab-objfile symtab))" \ + "#<gdb:objfile .*scm-symtab>" "test symtab-objfile" +gdb_test "guile (print (symtab-fullname symtab))" \ + "testsuite/gdb.guile/scm-symtab.c.*" "test symtab-fullname" +gdb_test "guile (print (symtab-valid? symtab))" \ + "#t" "test symtab-valid?" +gdb_test "guile (print (->bool (member \"qq\" global-symbols)))" \ + "#t" "test qq in global symbols" +gdb_test "guile (print (->bool (member \"func\" global-symbols)))" \ + "#t" "test func in global symbols" +gdb_test "guile (print (->bool (member \"main\" global-symbols)))" \ + "#t" "test main in global symbols" +gdb_test "guile (print (->bool (member \"int\" static-symbols)))" \ + "#t" "test int in static symbols" +gdb_test "guile (print (->bool (member \"char\" static-symbols)))" \ + "#t" "test char in static symbols" +gdb_test "guile (print (->bool (member \"simple_struct\" static-symbols)))" \ + "#t" "test simple_struct in static symbols" + +# Test is_valid when the objfile is unloaded. This must be the last +# test as it unloads the object file in GDB. +gdb_unload +gdb_test "guile (print (sal-valid? sal))" \ + "#f" "test sal-valid? after unloading" +gdb_test "guile (print (symtab-valid? symtab))" \ + "#f" "test symtab-valid? after unloading" + +gdb_test_no_output "guile (set! sal #f)" \ + "test sal destructor" +gdb_test_no_output "guile (set! symtab #f)" \ + "test symtab destructor" +gdb_test_no_output "guile (gc)" "GC to trigger destructors" + +# Start with a fresh gdb. +clean_restart ${testfile} + +# Test find-pc-line. +# The following tests require execution. + +if ![gdb_guile_runto_main] { + return +} + +runto [gdb_get_line_number "Break at func2 call site."] + +gdb_scm_test_silent_cmd "guile (define line (sal-line (frame-sal (selected-frame))))" \ + "get line number of func2 call site" +gdb_test "guile (print (= (sal-line (find-pc-line (frame-pc (selected-frame)))) line))" \ + "#t" "test find-pc-line at func2 call site" + +gdb_scm_test_silent_cmd "step" "step into func2" +gdb_scm_test_silent_cmd "up" "step out of func2" + +gdb_test "guile (print (> (sal-line (find-pc-line (frame-pc (selected-frame)))) line))" \ + "#t" "test find-pc-line with resume address" diff --git a/gdb/testsuite/gdb.guile/scm-type.c b/gdb/testsuite/gdb.guile/scm-type.c new file mode 100644 index 0000000..7cee383 --- /dev/null +++ b/gdb/testsuite/gdb.guile/scm-type.c @@ -0,0 +1,77 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2009-2014 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/>. */ + +struct s +{ + int a; + int b; +}; + +typedef struct s TS; +TS ts; + +#ifdef __cplusplus +struct C +{ + int c; + int d; +}; + +struct D : C +{ + int e; + int f; +}; + +template<typename T, int I, int C::*MP> +struct Temargs +{ +}; + +Temargs<D, 23, &C::c> temvar; + +#endif + +enum E +{ v1, v2, v3 +}; + +struct s vec_data_1 = {1, 1}; +struct s vec_data_2 = {1, 2}; + +int +main () +{ + int ar[2] = {1,2}; + struct s st; +#ifdef __cplusplus + C c; + c.c = 1; + c.d = 2; + D d; + d.e = 3; + d.f = 4; +#endif + enum E e; + + st.a = 3; + st.b = 5; + + e = v2; + + return 0; /* break to inspect struct and array. */ +} diff --git a/gdb/testsuite/gdb.guile/scm-type.exp b/gdb/testsuite/gdb.guile/scm-type.exp new file mode 100644 index 0000000..4a3969e --- /dev/null +++ b/gdb/testsuite/gdb.guile/scm-type.exp @@ -0,0 +1,299 @@ +# Copyright (C) 2009-2014 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/>. + +# This file is part of the GDB testsuite. +# It tests the mechanism of exposing types to Guile. + +load_lib gdb-guile.exp + +standard_testfile + +if [get_compiler_info c++] { + return -1 +} + +# Build inferior to language specification. + +proc build_inferior {exefile lang} { + global srcdir subdir srcfile + + if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${exefile}" executable "debug $lang"] != "" } { + untested "Couldn't compile ${srcfile} in $lang mode" + return -1 + } + return 0 +} + +# Restart GDB. +# The result is the same as gdb_guile_runto_main. + +proc restart_gdb {exefile} { + global srcdir subdir + + gdb_exit + gdb_start + gdb_reinitialize_dir $srcdir/$subdir + gdb_load ${exefile} + + if { [skip_guile_tests] } { + return 0 + } + + if ![gdb_guile_runto_main] { + return 0 + } + gdb_scm_test_silent_cmd "guile (use-modules (gdb iterator))" \ + "load iterator module" + + return 1 +} + +# Set breakpoint and run to that breakpoint. + +proc runto_bp {bp} { + gdb_breakpoint [gdb_get_line_number $bp] + gdb_continue_to_breakpoint $bp +} + +proc test_fields {lang} { + with_test_prefix "test_fields" { + global gdb_prompt + + # fields of a typedef should still return the underlying field list + gdb_test "guile (print (length (type-fields (value-type (parse-and-eval \"ts\")))))" \ + "= 2" "$lang typedef field list" + + if {$lang == "c++"} { + # Test usage with a class. + gdb_scm_test_silent_cmd "print c" "print value (c)" + gdb_scm_test_silent_cmd "guile (define c (history-ref 0))" \ + "get value (c) from history" + gdb_scm_test_silent_cmd "guile (define fields (type-fields (value-type c)))" \ + "get fields from c type" + gdb_test "guile (print (length fields))" \ + "= 2" "check number of fields of c" + gdb_test "guile (print (field-name (car fields)))" \ + "= c" "check class field c name" + gdb_test "guile (print (field-name (cadr fields)))" \ + "= d" "check class field d name" + } + + # Test normal fields usage in structs. + gdb_scm_test_silent_cmd "print st" "print value (st)" + gdb_scm_test_silent_cmd "guile (define st (history-ref 0))" \ + "get value (st) from history" + gdb_scm_test_silent_cmd "guile (define st-type (value-type st))" \ + "get st-type" + gdb_scm_test_silent_cmd "guile (define fields (type-fields st-type))" \ + "get fields from st.type" + gdb_test "guile (print (length fields))" \ + "= 2" "check number of fields (st)" + gdb_test "guile (print (field-name (car fields)))" \ + "= a" "check structure field a name" + gdb_test "guile (print (field-name (cadr fields)))" \ + "= b" "check structure field b name" + gdb_test "guile (print (field-name (type-field st-type \"a\")))" \ + "= a" "check fields lookup by name" + + # Test has-field? + gdb_test "guile (print (type-has-field? st-type \"b\"))" \ + "= #t" "check existent field" + gdb_test "guile (print (type-has-field? st-type \"nosuch\"))" \ + "= #f" "check non-existent field" + + # Test Guile mapping behavior of gdb:type for structs/classes. + gdb_test "guile (print (type-num-fields (value-type st)))" \ + "= 2" "check number of fields (st) with type-num-fields" + gdb_scm_test_silent_cmd "guile (define fi (make-field-iterator st-type))" \ + "create field iterator" + gdb_test "guile (print (iterator-map field-bitpos fi))" \ + "= \\(0 32\\)" "check field iterator" + + # Test rejection of mapping operations on scalar types. + gdb_test "guile (print (make-field-iterator (field-type (type-field st-type \"a\"))))" \ + "ERROR: .*: Out of range: type is not a structure, union, or enum type in position 1: .*" \ + "check field iterator on bad type" + + # Test type-array. + gdb_scm_test_silent_cmd "print ar" "print value (ar)" + gdb_scm_test_silent_cmd "guile (define ar (history-ref 0))" \ + "get value (ar) from history" + gdb_scm_test_silent_cmd "guile (define ar0 (value-subscript ar 0))" \ + "define ar0" + gdb_test "guile (print (value-cast ar0 (type-array (value-type ar0) 1)))" \ + "= \\{1, 2\\}" "cast to array with one argument" + gdb_test "guile (print (value-cast ar0 (type-array (value-type ar0) 0 1)))" \ + "= \\{1, 2\\}" "cast to array with two arguments" + + # Test type-vector. + # Note: vectors cast differently than arrays. Here ar[0] is replicated + # for the size of the vector. + gdb_scm_test_silent_cmd "print vec_data_1" "print value (vec_data_1)" + gdb_scm_test_silent_cmd "guile (define vec_data_1 (history-ref 0))" \ + "get value (vec_data_1) from history" + + gdb_scm_test_silent_cmd "print vec_data_2" "print value (vec_data_2)" + gdb_scm_test_silent_cmd "guile (define vec_data_2 (history-ref 0))" \ + "get value (vec_data_2) from history" + + gdb_scm_test_silent_cmd "guile (define vec1 (value-cast vec_data_1 (type-vector (value-type ar0) 1)))" \ + "set vec1" + gdb_test "guile (print vec1)" \ + "= \\{1, 1\\}" "cast to vector with one argument" + gdb_scm_test_silent_cmd "guile (define vec2 (value-cast vec_data_1 (type-vector (value-type ar0) 0 1)))" \ + "set vec2" + gdb_test "guile (print vec2)" \ + "= \\{1, 1\\}" "cast to vector with two arguments" + gdb_test "guile (print (value=? vec1 vec2))" \ + "= #t" + gdb_scm_test_silent_cmd "guile (define vec3 (value-cast vec_data_2 (type-vector (value-type ar0) 1)))" \ + "set vec3" + gdb_test "guile (print (value=? vec1 vec3))" \ + "= #f" + } +} + +proc test_equality {lang} { + with_test_prefix "test_equality" { + gdb_scm_test_silent_cmd "guile (define st (parse-and-eval \"st\"))" \ + "get st" + gdb_scm_test_silent_cmd "guile (define ar (parse-and-eval \"ar\"))" \ + "get ar" + gdb_test "guile (print (eq? (value-type st) (value-type st)))" \ + "= #t" "test type eq? on equal types" + gdb_test "guile (print (eq? (value-type st) (value-type ar)))" \ + "= #f" "test type eq? on not-equal types" + gdb_test "guile (print (equal? (value-type st) (value-type st)))" \ + "= #t" "test type eq? on equal types" + gdb_test "guile (print (equal? (value-type st) (value-type ar)))" \ + "= #f" "test type eq? on not-equal types" + + if {$lang == "c++"} { + gdb_scm_test_silent_cmd "guile (define c (parse-and-eval \"c\"))" \ + "get c" + gdb_scm_test_silent_cmd "guile (define d (parse-and-eval \"d\"))" \ + "get d" + gdb_test "guile (print (eq? (value-type c) (field-type (car (type-fields (value-type d))))))" \ + "= #t" "test c++ type eq? on equal types" + gdb_test "guile (print (eq? (value-type c) (value-type d)))" \ + "= #f" "test c++ type eq? on not-equal types" + gdb_test "guile (print (equal? (value-type c) (field-type (car (type-fields (value-type d))))))" \ + "= #t" "test c++ type equal? on equal types" + gdb_test "guile (print (equal? (value-type c) (value-type d)))" \ + "= #f" "test c++ type equal? on not-equal types" + } + } +} + +proc test_enums {} { + with_test_prefix "test_enum" { + gdb_scm_test_silent_cmd "print e" "print value (e)" + gdb_scm_test_silent_cmd "guile (define e (history-ref 0))" \ + "get value (e) from history" + gdb_scm_test_silent_cmd "guile (define fields (type-fields (value-type e)))" \ + "extract type fields from e" + gdb_test "guile (print (length fields))" \ + "= 3" "check the number of enum fields" + gdb_test "guile (print (field-name (car fields)))" \ + "= v1" "check enum field\[0\] name" + gdb_test "guile (print (field-name (cadr fields)))" \ + "= v2" "check enum field\[1\]name" + + # Ditto but by mapping operations. + gdb_test "guile (print (type-num-fields (value-type e)))" \ + "= 3" "check the number of enum values" + gdb_test "guile (print (field-name (type-field (value-type e) \"v1\")))" \ + "= v1" "check enum field lookup by name (v1)" + gdb_test "guile (print (field-name (type-field (value-type e) \"v3\")))" \ + "= v3" "check enum field lookup by name (v3)" + gdb_test "guile (print (iterator-map field-enumval (make-field-iterator (value-type e))))" \ + "\\(0 1 2\\)" "check enum fields iteration" + } +} + +proc test_base_class {} { + with_test_prefix "test_base_class" { + gdb_scm_test_silent_cmd "print d" "print value (d)" + gdb_scm_test_silent_cmd "guile (define d (history-ref 0))" \ + "get value (d) from history" + gdb_scm_test_silent_cmd "guile (define fields (type-fields (value-type d)))" \ + "extract type fields from d" + gdb_test "guile (print (length fields))" \ + "= 3" "check the number of fields" + gdb_test "guile (print (field-baseclass? (car fields)))" \ + "= #t" "check base class (fields\[0\])" + gdb_test "guile (print (field-baseclass? (cadr fields)))" \ + "= #f" "check base class (fields\[1\])" + } +} + +proc test_range {} { + with_test_prefix "test_range" { + with_test_prefix "on ranged value" { + # Test a valid range request. + gdb_scm_test_silent_cmd "print ar" "print value (ar)" + gdb_scm_test_silent_cmd "guile (define ar (history-ref 0))" \ + "get value (ar) from history" + gdb_test "guile (print (length (type-range (value-type ar))))" \ + "= 2" "check correct tuple length" + gdb_test "guile (print (type-range (value-type ar)))" \ + "= \\(0 1\\)" "check range" + } + + with_test_prefix "on unranged value" { + # Test where a range does not exist. + gdb_scm_test_silent_cmd "print st" "print value (st)" + gdb_scm_test_silent_cmd "guile (define st (history-ref 0))" \ + "get value (st) from history" + gdb_test "guile (print (type-range (value-type st)))" \ + "ERROR: .*: Wrong type argument in position 1 \\(expecting ranged type\\): .*" \ + "check range for non ranged type" + } + } +} + +# Perform C Tests. + +if { [build_inferior "${binfile}" "c"] < 0 } { + return +} +if ![restart_gdb "${binfile}"] { + return +} + +with_test_prefix "lang_c" { + runto_bp "break to inspect struct and array." + test_fields "c" + test_equality "c" + test_enums +} + +# Perform C++ Tests. + +if { [build_inferior "${binfile}-cxx" "c++"] < 0 } { + return +} +if ![restart_gdb "${binfile}-cxx"] { + return +} + +with_test_prefix "lang_cpp" { + runto_bp "break to inspect struct and array." + test_fields "c++" + test_base_class + test_range + test_equality "c++" + test_enums +} diff --git a/gdb/testsuite/gdb.guile/scm-value-cc.cc b/gdb/testsuite/gdb.guile/scm-value-cc.cc new file mode 100644 index 0000000..df19f0b --- /dev/null +++ b/gdb/testsuite/gdb.guile/scm-value-cc.cc @@ -0,0 +1,39 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2012-2014 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/>. */ + +class A { +}; + +typedef int *int_ptr; + +int +func (const A &a) +{ + int val = 10; + int &int_ref = val; + int_ptr ptr = &val; + int_ptr &int_ptr_ref = ptr; + + return 0; /* Break here. */ +} + +int +main () +{ + A obj; + return func (obj); +} diff --git a/gdb/testsuite/gdb.guile/scm-value-cc.exp b/gdb/testsuite/gdb.guile/scm-value-cc.exp new file mode 100644 index 0000000..685deb1 --- /dev/null +++ b/gdb/testsuite/gdb.guile/scm-value-cc.exp @@ -0,0 +1,57 @@ +# Copyright (C) 2012-2014 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/>. + +# This file is part of the GDB testsuite. +# It tests the mechanism exposing c++ values to Guile. + +load_lib gdb-guile.exp + +if { [skip_cplus_tests] } { continue } + +standard_testfile .cc + +if {[prepare_for_testing $testfile.exp $testfile $srcfile {debug c++}]} { + return +} + +# Skip all tests if Guile scripting is not enabled. +if { [skip_guile_tests] } { continue } + +if ![gdb_guile_runto_main] { + return +} + +gdb_breakpoint [gdb_get_line_number "Break here."] +gdb_continue_to_breakpoint "Break here" ".*Break here.*" + +gdb_test "gu (print (value-type (parse-and-eval \"a\")))" \ + "= const A &" +gdb_test "gu (print (value-type (value-referenced-value (parse-and-eval \"a\"))))" \ + "= const A" +gdb_test "gu (print (value-type (parse-and-eval \"int_ref\")))" \ + "= int &" +gdb_test "gu (print (value-type (value-referenced-value (parse-and-eval \"int_ref\"))))" \ + "= int" +gdb_test "gu (print (value-referenced-value (parse-and-eval \"int_ref\")))" \ + "= 10" + +gdb_test "gu (print (value-type (value-dereference (parse-and-eval \"int_ptr_ref\"))))" \ + "= int" +gdb_test "gu (print (value-type (value-referenced-value (parse-and-eval \"int_ptr_ref\"))))" \ + "= int_ptr" +gdb_test "gu (print (value-dereference (value-referenced-value (parse-and-eval \"int_ptr_ref\"))))" \ + "= 10" +gdb_test "gu (print (value-referenced-value (value-referenced-value (parse-and-eval \"int_ptr_ref\"))))" \ + "= 10" diff --git a/gdb/testsuite/gdb.guile/scm-value.c b/gdb/testsuite/gdb.guile/scm-value.c new file mode 100644 index 0000000..3c61911 --- /dev/null +++ b/gdb/testsuite/gdb.guile/scm-value.c @@ -0,0 +1,101 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2008-2014 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 <stdio.h> + +struct s +{ + int a; + int b; +}; + +union u +{ + int a; + float b; +}; + +enum e + { + ONE = 1, + TWO = 2 + }; + +typedef struct s *PTR; + +enum e evalue = TWO; + +#ifdef __cplusplus + +struct Base { + virtual int x() { return 5; } +}; + +struct Derived : public Base { +}; + +Base *base = new Derived (); + +void ptr_ref(int*& rptr_int) +{ + return; /* break to inspect pointer by reference. */ +} +#endif + +void func1 () +{ + printf ("void function called\n"); +} + +int func2 (int arg1, int arg2) +{ + return arg1 + arg2; +} + +char **save_argv; + +int +main (int argc, char *argv[]) +{ + char *cp = argv[0]; /* Prevent gcc from optimizing argv[] out. */ + struct s s; + union u u; + PTR x = &s; + char st[17] = "divide et impera"; + char nullst[17] = "divide\0et\0impera"; + void (*fp1) (void) = &func1; + int (*fp2) (int, int) = &func2; + const char *sptr = "pointer"; + const char *embed = "embedded x\201\202\203\204"; + int a[3] = {1,2,3}; + int *p = a; + int i = 2; + int *ptr_i = &i; + const char *sn = 0; + s.a = 3; + s.b = 5; + u.a = 7; + (*fp1) (); + (*fp2) (10,20); + +#ifdef __cplusplus + ptr_ref(ptr_i); +#endif + + save_argv = argv; /* break to inspect struct and union */ + return 0; +} diff --git a/gdb/testsuite/gdb.guile/scm-value.exp b/gdb/testsuite/gdb.guile/scm-value.exp new file mode 100644 index 0000000..3ebdd58 --- /dev/null +++ b/gdb/testsuite/gdb.guile/scm-value.exp @@ -0,0 +1,449 @@ +# Copyright (C) 2008-2014 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/>. + +# This file is part of the GDB testsuite. +# It tests the mechanism exposing values to Guile. + +load_lib gdb-guile.exp + +standard_testfile + +# Build inferior to language specification. +# LANG is one of "c" or "c++". +proc build_inferior {exefile lang} { + global srcdir subdir srcfile testfile hex + + # Use different names for .o files based on the language. + # For Fission, the debug info goes in foo.dwo and we don't want, + # for example, a C++ compile to clobber the dwo of a C compile. + # ref: http://gcc.gnu.org/wiki/DebugFission + switch ${lang} { + "c" { set filename ${testfile}.o } + "c++" { set filename ${testfile}-cxx.o } + } + set objfile [standard_output_file $filename] + + if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${objfile}" object "debug $lang"] != "" + || [gdb_compile "${objfile}" "${exefile}" executable "debug $lang"] != "" } { + untested "Couldn't compile ${srcfile} in $lang mode" + return -1 + } + return 0 +} + +proc test_value_in_inferior {} { + global gdb_prompt + global testfile + + gdb_breakpoint [gdb_get_line_number "break to inspect struct and union"] + + gdb_continue_to_breakpoint "break to inspect struct and union" + + # Just get inferior variable s in the value history, available to guile. + gdb_test "print s" "= {a = 3, b = 5}" "" + + gdb_scm_test_silent_cmd "gu (define s (history-ref 0))" "set s" + + gdb_test "gu (print (value-field s \"a\"))" \ + "= 3" "access element inside struct using string name" + + # Test dereferencing the argv pointer. + + # Just get inferior variable argv the value history, available to guile. + gdb_test "print argv" "= \\(char \\*\\*\\) 0x.*" "" + + gdb_scm_test_silent_cmd "gu (define argv (history-ref 0))" \ + "set argv" + gdb_scm_test_silent_cmd "gu (define arg0 (value-dereference argv))" \ + "set arg0" + + # Check that the dereferenced value is sane. + if { ! [target_info exists noargs] } { + gdb_test "gu (print arg0)" \ + "0x.*$testfile\"" "verify dereferenced value" + } + + # Smoke-test value-optimized-out?. + gdb_test "gu (print (value-optimized-out? arg0))" \ + "= #f" "Test value-optimized-out?" + + # Test address attribute. + gdb_test "gu (print (value-address arg0))" \ + "= 0x\[\[:xdigit:\]\]+" "Test address attribute" + # Test address attribute is #f in a non-addressable value. + gdb_test "gu (print (value-address (make-value 42)))" \ + "= #f" "Test address attribute in non-addressable value" + + # Test displaying a variable that is temporarily at a bad address. + # But if we can examine what's at memory address 0, then we'll also be + # able to display it without error. Don't run the test in that case. + set can_read_0 0 + gdb_test_multiple "x 0" "memory at address 0" { + -re "0x0:\[ \t\]*Cannot access memory at address 0x0\r\n$gdb_prompt $" { } + -re "0x0:\[ \t\]*Error accessing memory address 0x0\r\n$gdb_prompt $" { } + -re "\r\n$gdb_prompt $" { + set can_read_0 1 + } + } + + # Test memory error. + set test "parse_and_eval with memory error" + if {$can_read_0} { + untested $test + } else { + gdb_test "gu (print (parse-and-eval \"*(int*)0\"))" \ + "ERROR: Cannot access memory at address 0x0.*" $test + } + + # Test Guile lazy value handling + set test "memory error and lazy values" + if {$can_read_0} { + untested $test + } else { + gdb_test_no_output "gu (define inval (parse-and-eval \"*(int*)0\"))" + gdb_test "gu (print (value-lazy? inval))" \ + "#t" + gdb_test "gu (define inval2 (value-add inval 1))" \ + "ERROR: Cannot access memory at address 0x0.*" $test + gdb_test "gu (value-fetch-lazy! inval))" \ + "ERROR: Cannot access memory at address 0x0.*" $test + } + gdb_test_no_output "gu (define argc-lazy (parse-and-eval \"argc\"))" + gdb_test_no_output "gu (define argc-notlazy (parse-and-eval \"argc\"))" + gdb_test_no_output "gu (value-fetch-lazy! argc-notlazy)" + gdb_test "gu (print (value-lazy? argc-lazy))" "= #t" + gdb_test "gu (print (value-lazy? argc-notlazy))" "= #f" + gdb_test "print argc" "= 1" "sanity check argc" + gdb_test "gu (print (value-lazy? argc-lazy))" "= #t" + gdb_test_no_output "set argc=2" + gdb_test "gu (print argc-notlazy)" "= 1" + gdb_test "gu (print argc-lazy)" "= 2" + gdb_test "gu (print (value-lazy? argc-lazy))" "= #f" + + # Test string fetches, both partial and whole. + gdb_test "print st" "\"divide et impera\"" + gdb_scm_test_silent_cmd "gu (define st (history-ref 0))" \ + "inf: get st value from history" + gdb_test "gu (print (value->string st))" \ + "= divide et impera" "Test string with no length" + gdb_test "gu (print (value->string st #:length -1))" \ + "= divide et impera" "Test string (length = -1) is all of the string" + gdb_test "gu (print (value->string st #:length 6))" \ + "= divide" + gdb_test "gu (print (string-append \"---\" (value->string st #:length 0) \"---\"))" \ + "= ------" "Test string (length = 0) is empty" + gdb_test "gu (print (string-length (value->string st #:length 0)))" \ + "= 0" "Test length is 0" + + # Fetch a string that has embedded nulls. + gdb_test "print nullst" "\"divide\\\\000et\\\\000impera\".*" + gdb_scm_test_silent_cmd "gu (define nullst (history-ref 0))" \ + "inf: get nullst value from history" + gdb_test "gu (print (value->string nullst))" \ + "divide" "Test string to first null" + gdb_scm_test_silent_cmd "gu (set! nullst (value->string nullst #:length 9))" \ + "get string beyond null" + gdb_test "gu (print nullst)" \ + "= divide\\\\000et" +} + +proc test_strings {} { + gdb_test "gu (make-value \"test\")" "#<gdb:value \"test\">" "make string" + + # Test string conversion errors. + set save_charset [get_target_charset] + gdb_test_no_output "set target-charset UTF-8" + + gdb_test_no_output "gu (set-port-conversion-strategy! #f 'error)" + gdb_test "gu (print (value->string (make-value (string #\\x1234)) #:encoding \"ASCII\"))" \ + "ERROR.*decoding-error.*" \ + "value->string with default #:errors = 'error" + + # There is no 'escape strategy for C->SCM string conversions, but it's + # still a legitimate value for %default-port-conversion-strategy. + # GDB handles this by, umm, substituting 'substitute. + # Use this case to also handle "#:errors #f" which explicitly says + # "use %default-port-conversion-strategy". + gdb_test_no_output "gu (set-port-conversion-strategy! #f 'escape)" + gdb_test "gu (print (value->string (make-value (string #\\x1234)) #:encoding \"ASCII\" #:errors #f))" \ + "= \[?\]{3}" "value->string with default #:errors = 'escape" + + # This is last in the default conversion tests so that + # %default-port-conversion-strategy ends up with the default value. + gdb_test_no_output "gu (set-port-conversion-strategy! #f 'substitute)" + gdb_test "gu (print (value->string (make-value (string #\\x1234)) #:encoding \"ASCII\"))" \ + "= \[?\]{3}" "value->string with default #:errors = 'substitute" + + gdb_test "gu (print (value->string (make-value (string #\\x1234)) #:encoding \"ASCII\" #:errors 'error))" \ + "ERROR.*decoding-error.*" "value->string #:errors 'error" + gdb_test "gu (print (value->string (make-value (string #\\x1234)) #:encoding \"ASCII\" #:errors 'substitute))" \ + "= \[?\]{3}" "value->string #:errors 'substitute" + gdb_test "gu (print (value->string (make-value \"abc\") #:errors \"foo\"))" \ + "ERROR.*invalid error kind.*" "bad value for #:errors" + + gdb_test_no_output "set target-charset $save_charset" \ + "restore target-charset" +} + +proc test_lazy_strings {} { + global hex + + gdb_test "print sptr" "\"pointer\"" + gdb_scm_test_silent_cmd "gu (define sptr (history-ref 0))" \ + "lazy strings: get sptr value from history" + + gdb_scm_test_silent_cmd "gu (define lstr (value->lazy-string sptr))" \ + "Aquire lazy string" + gdb_test "gu (print (lazy-string-type lstr))" \ + "= const char \*." "Test lazy-string type name equality" + gdb_test "gu (print (value-type sptr))" \ + "= const char \*." "Test string type name equality" + gdb_test "print sn" "0x0" + gdb_scm_test_silent_cmd "gu (define snptr (history-ref 0))" \ + "lazy strings: get snptr value from history" + gdb_test "gu (define snstr (value->lazy-string snptr #:length 5))" \ + ".*cannot create a lazy string with address.*" "Test lazy string" + gdb_scm_test_silent_cmd "gu (define snstr (value->lazy-string snptr #:length 0))" \ + "Successfully create a lazy string" + gdb_test "gu (print (lazy-string-length snstr))" \ + "= 0" "Test lazy string length" + gdb_test "gu (print (lazy-string-address snstr))" \ + "= 0" "Test lazy string address" +} + +proc test_inferior_function_call {} { + global gdb_prompt hex decimal + + # Correct inferior call without arguments. + gdb_test "p/x fp1" "= $hex.*" + gdb_scm_test_silent_cmd "gu (define fp1 (history-ref 0))" \ + "get fp1 value from history" + gdb_scm_test_silent_cmd "gu (set! fp1 (value-dereference fp1))" \ + "dereference fp1" + gdb_test "gu (print (value-call fp1 '()))" \ + "= void" + + # Correct inferior call with arguments. + gdb_test "p/x fp2" "= $hex.*" + gdb_scm_test_silent_cmd "gu (define fp2 (history-ref 0))" \ + "get fp2 value from history" + gdb_scm_test_silent_cmd "gu (set! fp2 (value-dereference fp2))" \ + "dereference fp2" + gdb_test "gu (print (value-call fp2 (list 10 20)))" \ + "= 30" + + # Incorrect to call an int value. + gdb_test "p i" "= $decimal.*" + gdb_scm_test_silent_cmd "gu (define i (history-ref 0))" \ + "inf call: get i value from history" + gdb_test "gu (print (value-call i '()))" \ + "ERROR: .*: Wrong type argument in position 1 \\(expecting function \\(value of TYPE_CODE_FUNC\\)\\): .*" + + # Incorrect number of arguments. + gdb_test "p/x fp2" "= $hex.*" + gdb_scm_test_silent_cmd "gu (define fp3 (history-ref 0))" \ + "get fp3 value from history" + gdb_scm_test_silent_cmd "gu (set! fp3 (value-dereference fp3))" \ + "dereference fp3" + gdb_test "gu (print (value-call fp3 (list 10)))" \ + "ERROR: Too few arguments in function call.*" +} + +proc test_value_after_death {} { + # Construct a type while the inferior is still running. + gdb_scm_test_silent_cmd "gu (define ptrtype (lookup-type \"PTR\"))" \ + "create PTR type" + + # Kill the inferior and remove the symbols. + gdb_test "kill" "" "kill the inferior" \ + "Kill the program being debugged. .y or n. $" \ + "y" + gdb_test "file" "" "Discard the symbols" \ + "Discard symbol table from.*y or n. $" \ + "y" + + # Now create a value using that type. Relies on arg0, created by + # test_value_in_inferior. + gdb_scm_test_silent_cmd "gu (define castval (value-cast arg0 (type-pointer ptrtype)))" \ + "cast arg0 to PTR" + + # Make sure the type is deleted. + gdb_scm_test_silent_cmd "gu (set! ptrtype #f)" \ + "delete PTR type" + + # Now see if the value's type is still valid. + gdb_test "gu (print (value-type castval))" \ + "= PTR ." "print value's type" +} + +# Regression test for invalid subscript operations. The bug was that +# the type of the value was not being checked before allowing a +# subscript operation to proceed. + +proc test_subscript_regression {exefile lang} { + # Start with a fresh gdb. + clean_restart ${exefile} + + if ![gdb_guile_runto_main ] { + fail "Can't run to main" + return + } + + if {$lang == "c++"} { + gdb_breakpoint [gdb_get_line_number "break to inspect pointer by reference"] + gdb_continue_to_breakpoint "break to inspect pointer by reference" + + gdb_scm_test_silent_cmd "print rptr_int" \ + "Obtain address" + gdb_scm_test_silent_cmd "gu (define rptr (history-ref 0))" \ + "set rptr" + gdb_test "gu (print (value-subscript rptr 0))" \ + "= 2" "Check pointer passed as reference" + + # Just the most basic test of dynamic_cast -- it is checked in + # the C++ tests. + gdb_test "gu (print (value->bool (value-dynamic-cast (parse-and-eval \"base\") (type-pointer (lookup-type \"Derived\")))))" \ + "= #t" + + # Likewise. + gdb_test "gu (print (value-dynamic-type (parse-and-eval \"base\")))" \ + "= Derived \[*\]" + # A static type case. + gdb_test "gu (print (value-dynamic-type (parse-and-eval \"5\")))" \ + "= int" + } + + gdb_breakpoint [gdb_get_line_number "break to inspect struct and union"] + gdb_continue_to_breakpoint "break to inspect struct and union" + + gdb_scm_test_silent_cmd "gu (define intv (make-value 1))" \ + "Create int value for subscript test" + gdb_scm_test_silent_cmd "gu (define stringv (make-value \"foo\"))" \ + "Create string value for subscript test" + + # Try to access an int with a subscript. This should fail. + gdb_test "gu (print intv)" \ + "= 1" "Baseline print of an int Guile value" + gdb_test "gu (print (value-subscript intv 0))" \ + "ERROR: Cannot subscript requested type.*" \ + "Attempt to access an integer with a subscript" + + # Try to access a string with a subscript. This should pass. + gdb_test "gu (print stringv)" \ + "= \"foo\"" "Baseline print of a string Guile value" + gdb_test "gu (print (value-subscript stringv 0))" \ + "= 102 'f'" "Attempt to access a string with a subscript" + + # Try to access an int array via a pointer with a subscript. + # This should pass. + gdb_scm_test_silent_cmd "print p" "Build pointer to array" + gdb_scm_test_silent_cmd "gu (define pointer (history-ref 0))" "set pointer" + gdb_test "gu (print (value-subscript pointer 0))" \ + "= 1" "Access array via pointer with int subscript" + gdb_test "gu (print (value-subscript pointer intv))" \ + "= 2" "Access array via pointer with value subscript" + + # Try to access a single dimension array with a subscript to the + # result. This should fail. + gdb_test "gu (print (value-subscript (value-subscript pointer intv) 0))" \ + "ERROR: Cannot subscript requested type.*" \ + "Attempt to access an integer with a subscript 2" + + # Lastly, test subscript access to an array with multiple + # dimensions. This should pass. + gdb_scm_test_silent_cmd "print {\"fu \",\"foo\",\"bar\"}" "Build array" + gdb_scm_test_silent_cmd "gu (define marray (history-ref 0))" "" + gdb_test "gu (print (value-subscript (value-subscript marray 1) 2))" \ + "o." "Test multiple subscript" +} + +# A few tests of gdb:parse-and-eval. + +proc test_parse_and_eval {} { + gdb_test "gu (print (parse-and-eval \"23\"))" \ + "= 23" "parse-and-eval constant test" + gdb_test "gu (print (parse-and-eval \"5 + 7\"))" \ + "= 12" "parse-and-eval simple expression test" + gdb_test "gu (raw-print (parse-and-eval \"5 + 7\"))" \ + "#<gdb:value 12>" "parse-and-eval type test" +} + +# Test that values are hashable. +# N.B.: While smobs are hashable, the hash is really non-existent, +# they all get hashed to the same value. Guile may provide a hash function +# for smobs in a future release. In the meantime one should use a custom +# hash table that uses gdb:hash-gsmob. + +proc test_value_hash {} { + gdb_test_multiline "Simple Guile value dictionary" \ + "guile" "" \ + "(define one (make-value 1))" "" \ + "(define two (make-value 2))" "" \ + "(define three (make-value 3))" "" \ + "(define vdict (make-hash-table 5))" "" \ + "(hash-set! vdict one \"one str\")" "" \ + "(hash-set! vdict two \"two str\")" "" \ + "(hash-set! vdict three \"three str\")" "" \ + "end" + gdb_test "gu (print (hash-ref vdict one))" \ + "one str" "Test dictionary hash 1" + gdb_test "gu (print (hash-ref vdict two))" \ + "two str" "Test dictionary hash 2" + gdb_test "gu (print (hash-ref vdict three))" \ + "three str" "Test dictionary hash 3" +} + +# Build C version of executable. C++ is built later. +if { [build_inferior "${binfile}" "c"] < 0 } { + return +} + +# Start with a fresh gdb. +clean_restart ${binfile} + +# Skip all tests if Guile scripting is not enabled. +if { [skip_guile_tests] } { continue } + +gdb_install_guile_utils +gdb_install_guile_module + +test_parse_and_eval +test_value_hash + +# The following tests require execution. + +if ![gdb_guile_runto_main] { + fail "Can't run to main" + return +} + +test_value_in_inferior +test_inferior_function_call +test_strings +test_lazy_strings +test_value_after_death + +# Test either C or C++ values. + +test_subscript_regression "${binfile}" "c" + +if ![skip_cplus_tests] { + if { [build_inferior "${binfile}-cxx" "c++"] < 0 } { + return + } + with_test_prefix "c++" { + test_subscript_regression "${binfile}-cxx" "c++" + } +} diff --git a/gdb/testsuite/gdb.guile/source2.scm b/gdb/testsuite/gdb.guile/source2.scm new file mode 100644 index 0000000..f00c269 --- /dev/null +++ b/gdb/testsuite/gdb.guile/source2.scm @@ -0,0 +1,19 @@ +;; This testcase is part of GDB, the GNU debugger. +;; +;; Copyright 2008-2014 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/>. + +(display (format "y~As" "e")) +(newline) diff --git a/gdb/testsuite/gdb.guile/types-module.cc b/gdb/testsuite/gdb.guile/types-module.cc new file mode 100644 index 0000000..90c682a --- /dev/null +++ b/gdb/testsuite/gdb.guile/types-module.cc @@ -0,0 +1,38 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2014 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/>. */ + +enum enum_type { A, B, C }; + +class base +{ + public: + int base_member; +}; + +class derived : public base +{ + public: + enum_type derived_member; +}; + +derived d; + +int +main (void) +{ + return 0; +} diff --git a/gdb/testsuite/gdb.guile/types-module.exp b/gdb/testsuite/gdb.guile/types-module.exp new file mode 100644 index 0000000..8562f3c --- /dev/null +++ b/gdb/testsuite/gdb.guile/types-module.exp @@ -0,0 +1,50 @@ +# Copyright (C) 2014 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/>. + +# This file is part of the GDB testsuite. +# It tests the (gdb types) module. + +load_lib gdb-guile.exp + +standard_testfile .cc + +if { [prepare_for_testing ${testfile}.exp ${testfile} ${srcfile}] } { + return -1 +} + +# Skip all tests if Guile scripting is not enabled. +if { [skip_guile_tests] } { continue } + +if ![gdb_guile_runto_main] { + return +} + +gdb_scm_test_silent_cmd "guile (use-modules (gdb types))" \ + "import (gdb types)" + +gdb_scm_test_silent_cmd "guile (define d (lookup-type \"derived\"))" \ + "get derived type" + +gdb_test "guile (print (type-has-field? d \"base_member\"))" \ + "= #f" "type-has-field? member in baseclass" + +gdb_test "guile (print (type-has-field-deep? d \"base_member\"))" \ + "= #t" "type-has-field-deep? member in baseclass" + +gdb_scm_test_silent_cmd "guile (define enum-htab (make-enum-hashtable (lookup-type \"enum_type\")))" \ + "create enum hash table" + +gdb_test "guile (print (hash-ref enum-htab \"B\"))" \ + "= 1" "verify make-enum-hashtable" diff --git a/gdb/testsuite/lib/gdb-guile.exp b/gdb/testsuite/lib/gdb-guile.exp new file mode 100644 index 0000000..d46f200 --- /dev/null +++ b/gdb/testsuite/lib/gdb-guile.exp @@ -0,0 +1,127 @@ +# Copyright 2010-2014 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/>. + +# Utilities for Guile-scripting related tests. + +# Guile doesn't print the 0x prefix on hex numbers. +set ghex {[0-9a-f]+} + +# Return a 1 for configurations that do not support Guile scripting. + +proc skip_guile_tests {} { + global gdb_prompt + + gdb_test_multiple "guile (display \"test\\n\")" "verify guile support" { + -re "Undefined command.*$gdb_prompt $" { + unsupported "Guile not supported." + return 1 + } + -re "not supported.*$gdb_prompt $" { + unsupported "Guile support is disabled." + return 1 + } + -re "$gdb_prompt $" {} + } + + return 0 +} + +# Run a command in GDB, and report a failure if a Scheme exception is thrown. +# If report_pass is true, report a pass if no exception is thrown. +# This also catches the "Undefined command" error that happens if the user +# passes, e.g., "(print foo)" instead of "guile (print foo)". + +proc gdb_scm_test_silent_cmd { cmd name {report_pass 1} } { + global gdb_prompt + + gdb_test_multiple $cmd $name { + -re "Backtrace.*$gdb_prompt $" { fail $name } + -re "ERROR.*$gdb_prompt $" { fail $name } + -re "Undefined command: .*$gdb_prompt $" { fail $name } + -re "$gdb_prompt $" { if $report_pass { pass $name } } + } +} + +# Usage: gdb_test_multiline NAME INPUT RESULT {INPUT RESULT} ... +# Run a test named NAME, consisting of multiple lines of input. +# After each input line INPUT, search for result line RESULT. +# Succeed if all results are seen; fail otherwise. +# FIXME: Move to gdb.exp and remove Python's gdb_py_test_multiple. + +proc gdb_test_multiline { name args } { + global gdb_prompt + foreach {input result} $args { + if {[gdb_test_multiple $input "$name - $input" { + -re "\[\r\n\]*($result)\[\r\n\]+($gdb_prompt | *>)$" { + pass "$name - $input" + } + }]} { + return 1 + } + } + return 0 +} + +# Load Scheme file FILE_NAME. +# TEST_NAME can be used to specify the name of the test, +# otherwise a standard test name is provided. +# +# Note: When Guile loads something and auto-compilation is enabled +# (which is useful and the default), then the first time a file is loaded +# Guile will compile the file and store the result somewhere +# (e.g., $HOME/.cache/guile). Output of the compilation process will +# appear in gdb.log. But since Guile only does this when necessary +# don't be confused if you don't always see it - Guile just skipped it +# because it thought it was unnecessary. + +proc gdb_scm_load_file { file_name {test_name ""} } { + if { $test_name == "" } { + set test_name "guile (load \"[file tail $file_name]\")" + } + # Note: This can produce output if Guile compiles the file. + gdb_scm_test_silent_cmd "guile (load \"$file_name\")" $test_name +} + +# Install various utilities in Guile to simplify tests. +# +# print - combination of display + newline + +proc gdb_install_guile_utils { } { + # Define utilities in Guile to save needing (newline) all the time, + # and in the case of "print" add a prefix to help erroneous passes. + gdb_test_no_output "guile (define (print x) (format #t \"= ~A\" x) (newline))" + gdb_test_no_output "guile (define (raw-print x) (format #t \"= ~S\" x) (newline))" +} + +# Install the gdb module. + +proc gdb_install_guile_module { } { + gdb_test_no_output "guile (use-modules (gdb))" +} + +# Wrapper around runto_main that installs the guile utils and module. +# The result is the same as for runto_main. + +proc gdb_guile_runto_main { } { + if ![runto_main] { + fail "Can't run to main" + return 0 + } + + gdb_install_guile_utils + gdb_install_guile_module + + return 1 +} diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp index 3716472..66dc8f7 100644 --- a/gdb/testsuite/lib/gdb.exp +++ b/gdb/testsuite/lib/gdb.exp @@ -4399,6 +4399,23 @@ proc get_sizeof { type default } { return [get_integer_valueof "sizeof (${type})" $default] } +proc get_target_charset { } { + global gdb_prompt + + gdb_test_multiple "show target-charset" "" { + -re "The target character set is \"auto; currently (\[^\"\]*)\".*$gdb_prompt $" { + return $expect_out(1,string) + } + -re "The target character set is \"(\[^\"\]*)\".*$gdb_prompt $" { + return $expect_out(1,string) + } + } + + # Pick a reasonable default. + warning "Unable to read target-charset." + return "UTF-8" +} + # Get the current value for remotetimeout and return it. proc get_remotetimeout { } { global gdb_prompt |