diff options
author | Stan Shebs <shebs@apple.com> | 1999-04-16 01:35:26 +0000 |
---|---|---|
committer | Stan Shebs <shebs@apple.com> | 1999-04-16 01:35:26 +0000 |
commit | 14cd51f7793a9ce07bc435069f57269450141363 (patch) | |
tree | 280a2da48f771d61be5b451ddbacdf9ef8e9ad13 /gdb/testsuite/gdb.hp | |
download | gdb-14cd51f7793a9ce07bc435069f57269450141363.tar.gz |
Initial revision
Diffstat (limited to 'gdb/testsuite/gdb.hp')
73 files changed, 14172 insertions, 0 deletions
diff --git a/gdb/testsuite/gdb.hp/Makefile.in b/gdb/testsuite/gdb.hp/Makefile.in new file mode 100644 index 00000000000..d65fc75e222 --- /dev/null +++ b/gdb/testsuite/gdb.hp/Makefile.in @@ -0,0 +1,25 @@ +VPATH = @srcdir@ +srcdir = @srcdir@ + +PROGS = ambiguous ctti-add exception gen-so-thresh namespace \ + optimize pxdb so-thresh templ-hp watch-hp xdb + +MISCELLANEOUS = \ + lib00-so-thresh.c lib00-so-thresh.sl \ + lib01-so-thresh.c lib01-so-thresh.sl \ + lib02-so-thresh.c lib02-so-thresh.sl \ + so-thresh.c so-thresh.linkopts + +all: + @echo "Nothing to be done for all..." + +#### host, target, and site specific Makefile frags come in here. + +clean mostlyclean: + -rm -f *.ci *.o $(OBJS) $(PROGS) $(MISCELLANEOUS) *~ core + +distclean maintainer-clean realclean: clean + -rm -f Makefile config.status config.log + +Makefile: $(srcdir)/Makefile.in $(srcdir)/configure.in + $(SHELL) ./config.status --recheck diff --git a/gdb/testsuite/gdb.hp/ambiguous.cc b/gdb/testsuite/gdb.hp/ambiguous.cc new file mode 100644 index 00000000000..6ee7bc18ea9 --- /dev/null +++ b/gdb/testsuite/gdb.hp/ambiguous.cc @@ -0,0 +1,110 @@ + +void marker1() +{ + return; +} + +class A1 { +public: + int x; + int y; +}; + +class A2 { +public: + int x; + int y; +}; + +class A3 { +public: + int x; + int y; +}; + +class X : public A1, public A2 { +public: + int z; +}; + +class L : public A1 { +public: + int z; +}; + +class LV : public virtual A1 { +public: + int z; +}; + +class M : public A2 { +public: + int w; +}; + +class N : public L, public M { +public: + int r; +}; + +class K : public A1 { +public: + int i; +}; + +class KV : public virtual A1 { +public: + int i; +}; + +class J : public K, public L { +public: + int j; +}; + +class JV : public KV, public LV { +public: + int jv; +}; + +class JVA1 : public KV, public LV, public A1 { +public: + int jva1; +}; + +class JVA2 : public KV, public LV, public A2 { +public: + int jva2; +}; + +class JVA1V : public KV, public LV, public virtual A1 { +public: + int jva1v; +}; + +int main() +{ + A1 a1; + A2 a2; + A3 a3; + X x; + L l; + M m; + N n; + K k; + J j; + JV jv; + JVA1 jva1; + JVA2 jva2; + JVA1V jva1v; + + int i; + + i += k.i + m.w + a1.x + a2.x + a3.x + x.z + l.z + n.r + j.j; + + marker1(); + +} + + + diff --git a/gdb/testsuite/gdb.hp/ambiguous.exp b/gdb/testsuite/gdb.hp/ambiguous.exp new file mode 100644 index 00000000000..5b87af36d79 --- /dev/null +++ b/gdb/testsuite/gdb.hp/ambiguous.exp @@ -0,0 +1,216 @@ +# Copyright (C) 1998 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 2 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +# Please email any bugs, comments, and/or additions to this file to: +# bug-gdb@prep.ai.mit.edu + +# This file is part of the gdb testsuite + +# tests relating to ambiguous class members +# Written by Satish Pai <pai@apollo.hp.com> 1997-07-28 + +# This file is part of the gdb testsuite + +if $tracelevel then { + strace $tracelevel + } + +# +# test running programs +# + +set prms_id 0 +set bug_id 0 + +set testfile "ambiguous" +set srcfile ${testfile}.cc +set binfile ${objdir}/${subdir}/${testfile} + +if [get_compiler_info ${binfile} "c++"] { + return -1; +} + + +if {[skip_hp_tests $gcc_compiled]} then { continue } + +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } { + gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail." +} + + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + + +# +# set it up at a breakpoint so we can play with the variable values +# +if ![runto_main] then { + perror "couldn't run to breakpoint" + continue +} + +send_gdb "break marker1\n" ; gdb_expect -re ".*$gdb_prompt $" + send_gdb "cont\n" + gdb_expect { + -re "Break.* marker1 \\(\\) at .*:$decimal.*$gdb_prompt $" { + send_gdb "up\n" + gdb_expect { + -re ".*$gdb_prompt $" { pass "up from marker1" } + timeout { fail "up from marker1" } + } + } + -re "$gdb_prompt $" { fail "continue to marker1" } + timeout { fail "(timeout) continue to marker1" } + } + +# print out various class objects' members. The values aren't +# important, just check that the warning is emitted at the +# right times. + +# X is derived from A1 and A2; both A1 and A2 have a member 'x' +send_gdb "print x.x\n" +gdb_expect { + -re "warning: x ambiguous; using X::A1::x. Use a cast to disambiguate.\r\n\\$\[0-9\]* = 0\r\n$gdb_prompt $" { + pass "print x.x" + } + -re ".*$gdb_prompt $" { fail "print x.x" } + timeout { fail "(timeout) print x.x" } +} + + +# N is derived from A1 and A2, but not immediately -- two steps +# up in the hierarchy. Both A1 and A2 have a member 'x'. +send_gdb "print n.x\n" +gdb_expect { + -re "warning: x ambiguous; using N::L::A1::x. Use a cast to disambiguate.\r\n\\$\[0-9\]* = 0\r\n$gdb_prompt $" { + pass "print n.x" + } + -re ".*$gdb_prompt $" { fail "print n.x" } + timeout { fail "(timeout) print n.x" } +} + +# J is derived from A1 twice. A1 has a member x. +send_gdb "print j.x\n" +gdb_expect { + -re "warning: x ambiguous; using J::K::A1::x. Use a cast to disambiguate.\r\n\\$\[0-9\]* = 0\r\n$gdb_prompt $" { + pass "print j.x" + } + -re ".*$gdb_prompt $" { fail "print j.x" } + timeout { fail "(timeout) print j.x" } +} + +# JV is derived from A1 but A1 is a virtual base. Should not +# report an ambiguity in this case. +send_gdb "print jv.x\n" +gdb_expect { + -re "warning: x ambiguous.*Use a cast to disambiguate.\r\n\\$\[0-9\]* = 0\r\n$gdb_prompt $" { + fail "print jv.x (ambiguity reported)" + } + -re "\\$\[0-9\]* = 0\r\n$gdb_prompt $" { pass "print jv.x" } + -re ".*$gdb_prompt $" { fail "print jv.x (??)" } + timeout { fail "(timeout) print jv.x" } +} + +# JVA1 is derived from A1; A1 occurs as a virtual base in two +# ancestors, and as a non-virtual immediate base. Ambiguity must +# be reported. +send_gdb "print jva1.x\n" +gdb_expect { + -re "warning: x ambiguous; using JVA1::KV::A1::x. Use a cast to disambiguate.\r\n\\$\[0-9\]* = 0\r\n$gdb_prompt $" { + pass "print jva1.x" + } + -re ".*$gdb_prompt $" { fail "print jva1.x" } + timeout { fail "(timeout) print jva1.x" } +} + +# JVA2 is derived from A1 & A2; A1 occurs as a virtual base in two +# ancestors, and A2 is a non-virtual immediate base. Ambiguity must +# be reported as A1 and A2 both have a member 'x'. +send_gdb "print jva2.x\n" +gdb_expect { + -re "warning: x ambiguous; using JVA2::KV::A1::x. Use a cast to disambiguate.\r\n\\$\[0-9\]* = 0\r\n$gdb_prompt $" { + pass "print jva2.x" + } + -re ".*$gdb_prompt $" { fail "print jva2.x" } + timeout { fail "(timeout) print jva2.x" } +} + +# JVA1V is derived from A1; A1 occurs as a virtual base in two +# ancestors, and also as a virtual immediate base. Ambiguity must +# not be reported. +send_gdb "print jva1v.x\n" +gdb_expect { + -re "warning: x ambiguous.*Use a cast to disambiguate.\r\n\\$\[0-9\]* = 0\r\n$gdb_prompt $" { + fail "print jva1v.x (ambiguity reported)" + } + -re "\\$\[0-9\]* = 0\r\n$gdb_prompt $" { pass "print jva1v.x" } + -re ".*$gdb_prompt $" { fail "print jva1v.x (??)" } + timeout { fail "(timeout) print jva1v.x" } +} + +# Now check for ambiguous bases. + +# J is derived from A1 twice; report ambiguity if a J is +# cast to an A1. +send_gdb "print (A1)j\n" +gdb_expect { + -re "warning: A1 ambiguous; using J::K::A1. Use a cast to disambiguate.\r\n\\$\[0-9\]* = \{x = 0, y = 0\}\r\n$gdb_prompt $" { + pass "print (A1)j" + } + -re ".*$gdb_prompt $" { fail "print (A1)j" } + timeout { fail "(timeout) print (A1)j" } +} + +# JV is derived from A1 twice, but A1 is a virtual base; should +# not report ambiguity when a JV is cast to an A1. +send_gdb "print (A1)jv\n" +gdb_expect { + -re "warning: A1 ambiguous.*Use a cast to disambiguate.\r\n\\$\[0-9\]* = \{x = 0, y = 0\}\r\n$gdb_prompt $" { + fail "print (A1)jv (ambiguity reported)" + } + -re "\\$\[0-9\]* = \{x = 0, y = 0\}\r\n$gdb_prompt $" { pass "print (A1)jv" } + -re ".*$gdb_prompt $" { fail "print (A1)jv (??)" } + timeout { fail "(timeout) print (A1)jv" } +} + +# JVA1 is derived from A1; A1 is a virtual base and also a +# non-virtual base. Must report ambiguity if a JVA1 is cast to an A1. +send_gdb "print (A1)jva1\n" +gdb_expect { + -re "warning: A1 ambiguous; using JVA1::KV::A1. Use a cast to disambiguate.\r\n\\$\[0-9\]* = \{x = 0, y = 0\}\r\n$gdb_prompt $" { + pass "print (A1)jva1" + } + -re ".*$gdb_prompt $" { fail "print (A1)jva1" } + timeout { fail "(timeout) print (A1)jva1" } +} + +# JVA1V is derived from A1; A1 is a virtual base indirectly +# and also directly; must not report ambiguity when a JVA1V is cast to an A1. +send_gdb "print (A1)jva1v\n" +gdb_expect { + -re "warning: A1 ambiguous.*Use a cast to disambiguate.\r\n\\$\[0-9\]* = \{x = 0, y = 0\}\r\n$gdb_prompt $" { + fail "print (A1)jva1v (ambiguity reported)" + } + -re "\\$\[0-9\]* = \{x = 0, y = 0\}\r\n$gdb_prompt $" { pass "print (A1)jva1v" + } + -re ".*$gdb_prompt $" { fail "print (A1)jva1v (??)" } + timeout { fail "(timeout) print (A1)jva1v" } +} + + diff --git a/gdb/testsuite/gdb.hp/attach.c b/gdb/testsuite/gdb.hp/attach.c new file mode 100644 index 00000000000..1aad3c1cc07 --- /dev/null +++ b/gdb/testsuite/gdb.hp/attach.c @@ -0,0 +1,19 @@ +/* This program is intended to be started outside of gdb, and then + attached to by gdb. Thus, it simply spins in a loop. The loop + is exited when & if the variable 'should_exit' is non-zero. (It + is initialized to zero in this program, so the loop will never + exit unless/until gdb sets the variable to non-zero.) + */ +#include <stdio.h> + +int should_exit = 0; + +main () +{ + int local_i = 0; + + while (! should_exit) + { + local_i++; + } +} diff --git a/gdb/testsuite/gdb.hp/attach.exp b/gdb/testsuite/gdb.hp/attach.exp new file mode 100644 index 00000000000..372acd05d7e --- /dev/null +++ b/gdb/testsuite/gdb.hp/attach.exp @@ -0,0 +1,416 @@ +# Copyright (C) 1997 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 2 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +# Please email any bugs, comments, and/or additions to this file to: +# bug-gdb@prep.ai.mit.edu + +# On HP-UX 11.0, this test is causing a process running +# the program "attach" to be left around spinning. +# Until we figure out why, I am commenting out the test +# to avoid polluting tiamat (our 11.0 nightly test machine) +# with these processes. RT +# +# Setting the magic bit in the target app should work. +# I added a "kill", and also a test for the R3 register +# warning. JB +# +if $tracelevel then { + strace $tracelevel + } + +set prms_id 0 +set bug_id 0 + + +# are we on a target board +if ![isnative] then { + return +} + +if { ![istarget "hppa*-*-hpux10.30"] && ![istarget "hppa*-*-hpux11.*"] } { + #setup_xfail "*-*-*" + return 0 +} + +set testfile "attach" +set srcfile ${testfile}.c +set srcfile2 ${testfile}2.c +set binfile ${objdir}/${subdir}/${testfile} +set binfile2 ${objdir}/${subdir}/${testfile}2 +set cleanupfile ${objdir}/${subdir}/${testfile}.awk + +#execute_anywhere "rm -f ${binfile} ${binfile2}" +remote_exec build "rm -f ${binfile} ${binfile2}" +# For debugging this test +# +#log_user 1 + +# Clean out any old files from past runs. +# +remote_exec build "${cleanupfile}" + +# build the first test case +# +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } { + gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail." +} + +# Build the in-system-call test + +if { [gdb_compile "${srcdir}/${subdir}/${srcfile2}" "${binfile2}" executable {debug}] != "" } { + gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail." +} + +#if { [compile "-E ${srcdir}/${subdir}/compiler.c >> ${objdir}/${subdir}/${testfile}.tmp"] != ""# } { +# perror "Couldn't make ${testfile}.tmp" +# return -1 +#} + +#execute_anywhere "mv ${objdir}/${subdir}/${testfile}.tmp ${binfile}.ci" + +#source ${binfile}.ci + +proc do_attach_tests {} { + global gdb_prompt + global binfile + global srcfile + global testfile + global objdir + global subdir + global timeout + + # Start the program running and then wait for a bit, to be sure + # that it can be attached to. + # + set testpid [eval exec $binfile &] + exec sleep 2 + + # Verify that we cannot attach to nonsense. + # + send_gdb "attach abc\n" + gdb_expect { + -re "Illegal process-id: abc.*$gdb_prompt $"\ + {pass "attach to nonsense is prohibited"} + -re "Attaching to.*$gdb_prompt $"\ + {fail "attach to nonsense is prohibited (bogus pid allowed)"} + -re "$gdb_prompt $" {fail "attach to nonsense is prohibited"} + timeout {fail "(timeout) attach to nonsense is prohibited"} + } + + # Verify that we cannot attach to what appears to be a valid + # process ID, but is a process that doesn't exist. (I don't + # believe any process is ever assigned #0, at least on HPUX.) + # + send_gdb "attach 0\n" + gdb_expect { + # This reponse is expected on HP-UX 10.20 (i.e., ptrace-based). + -re "Attaching to.*, process 0.*No such process.*$gdb_prompt $"\ + {pass "attach to nonexistent process is prohibited"} + # This response is expected on HP-UX 10.30 & 11.0 (i.e., ttrace-based). + -re "Attaching to.*, process 0.*Permission denied.*$gdb_prompt $"\ + {pass "attach to nonexistent process is prohibited"} + -re "$gdb_prompt $" {fail "attach to nonexistent process is prohibited"} + timeout {fail "(timeout) attach to nonexistent process is prohibited"} + } + + # Verify that we can attach to the process by first giving its + # executable name via the file command, and using attach with + # the process ID. + # + # (Actually, the test system appears to do this automatically + # for us. So, we must also be prepared to be asked if we want + # to discard an existing set of symbols.) + # + send_gdb "file $binfile\n" + gdb_expect { + -re "Load new symbol table from.*y or n.*$" { + send_gdb "y\n" + gdb_expect { + -re "Reading symbols from $binfile\.\.\.*done.*$gdb_prompt $"\ + {pass "(re)set file, before attach1"} + -re "$gdb_prompt $" {fail "(re)set file, before attach1"} + timeout {fail "(timeout) (re)set file, before attach1"} + } + } + -re "Reading symbols from $binfile\.\.\.*done.*$gdb_prompt $"\ + {pass "set file, before attach1"} + -re "$gdb_prompt $" {fail "set file, before attach1"} + timeout {fail "(timeout) set file, before attach1"} + } + + send_gdb "attach $testpid\n" + gdb_expect { + -re "Attaching to program.*$binfile, process $testpid.*main.*at .*$srcfile:.*$gdb_prompt $"\ + {pass "attach1, after setting file"} + -re "$gdb_prompt $" {fail "attach1, after setting file"} + timeout {fail "(timeout) attach1, after setting file"} + } + + # Verify that we can "see" the variable "should_exit" in the + # program, and that it is zero. + # + send_gdb "print should_exit\n" + gdb_expect { + -re ".* = 0.*$gdb_prompt $"\ + {pass "after attach1, print should_exit"} + -re "$gdb_prompt $" {fail "after attach1, print should_exit"} + timeout {fail "(timeout) after attach1, print should_exit"} + } + + # Detach the process. + # + send_gdb "detach\n" + gdb_expect { + -re "Detaching from program: .*$binfile.*$gdb_prompt $"\ + {pass "attach1 detach"} + -re "$gdb_prompt $" {fail "attach1 detach"} + timeout {fail "(timeout) attach1 detach"} + } + + # Wait a bit for gdb to finish detaching + # + exec sleep 5 + + # Purge the symbols from gdb's brain. (We want to be certain + # the next attach, which won't be preceded by a "file" command, + # is really getting the executable file without our help.) + # + set old_timeout $timeout + set timeout [expr $timeout + 20] + send_gdb "file\n" + gdb_expect { + -re ".*gdb internal error.*$" { + fail "Internal error, prob. Memory corruption" + } + -re "No exec file now.*Discard symbol table.*y or n.*$" { + send_gdb "y\n" + gdb_expect { + -re "No symbol file now.*$gdb_prompt $"\ + {pass "attach1, purging symbols after detach"} + -re "$gdb_prompt $" {fail "attach1, purging symbols after detach"} + timeout {fail "(timeout) attach1, purging symbols after detach"} + } + } + -re "$gdb_prompt $" {fail "attach1, purging file after detach"} + timeout { + fail "(timeout) attach1, purging file after detach" + } + } + set timeout $old_timeout + + # Verify that we can attach to the process just by giving the + # process ID. + # + send_gdb "attach $testpid\n" + gdb_expect { + -re "Attaching to process $testpid.*Reading symbols from $binfile.*main.*at .*$gdb_prompt $"\ + {pass "attach2"} + -re "$gdb_prompt $" {fail "attach2"} + timeout {fail "(timeout) attach2"} + } + + # Verify that we can modify the variable "should_exit" in the + # program. + # + send_gdb "set should_exit=1\n" + gdb_expect { + -re "$gdb_prompt $" {pass "after attach2, set should_exit"} + timeout {fail "(timeout) after attach2, set should_exit"} + } + + # Verify that the modification really happened. + # + send_gdb "tbreak 19\n" + gdb_expect { + -re "Breakpoint .*at.*$srcfile, line 19.*$gdb_prompt $"\ + {pass "after attach2, set tbreak postloop"} + -re "$gdb_prompt $" {fail "after attach2, set tbreak postloop"} + timeout {fail "(timeout) after attach2, set tbreak postloop"} + } + send_gdb "continue\n" + gdb_expect { + -re "main.*at.*$srcfile:19.*$gdb_prompt $"\ + {pass "after attach2, reach tbreak postloop"} + -re "$gdb_prompt $" {fail "after attach2, reach tbreak postloop"} + timeout {fail "(timeout) after attach2, reach tbreak postloop"} + } + + # Allow the test process to exit, to cleanup after ourselves. + # + send_gdb "continue\n" + gdb_expect { + -re "Program exited normally.*$gdb_prompt $"\ + {pass "after attach2, exit"} + -re "$gdb_prompt $" {fail "after attach2, exit"} + timeout {fail "(timeout) after attach2, exit"} + } + + # Make sure we don't leave a process around to confuse + # the next test run (and prevent the compile by keeping + # the text file busy), in case the "set should_exit" didn't + # work. + # +# execute_anywhere "kill -9 ${testpid}" +remote_exec build "kill -9 ${testpid}" + # Start the program running and then wait for a bit, to be sure + # that it can be attached to. + # + set testpid [eval exec $binfile &] + exec sleep 2 + + # Verify that we can attach to the process, and find its a.out + # when we're cd'd to some directory that doesn't contain the + # a.out. (We use the source path set by the "dir" command.) + # + send_gdb "dir ${objdir}/${subdir}\n" + gdb_expect { + -re ".*Source directories searched: .*$gdb_prompt $"\ + {pass "set source path"} + -re "$gdb_prompt $" {fail "set source path"} + timeout {fail "(timeout) set source path"} + } + + send_gdb "cd /tmp\n" + gdb_expect { + -re ".*Working directory /tmp.*$gdb_prompt $"\ + {pass "cd away from process' a.out"} + -re "$gdb_prompt $" {fail "cd away from process' a.out"} + timeout {fail "(timeout) cd away from process' a.out"} + } + + # Explicitly flush out any knowledge of the previous attachment. + send_gdb "symbol\n" + gdb_expect { + -re ".*Discard symbol table from.*y or n. $"\ + {send_gdb "y\n" + gdb_expect { + -re ".*No symbol file now.*$gdb_prompt $"\ + {pass "before attach3, flush symbols"} + -re "$gdb_prompt $" {fail "before attach3, flush symbols"} + timeout {fail "(timeout) before attach3, flush symbols"} + } + } + -re ".*No symbol file now.*$gdb_prompt $"\ + {pass "before attach3, flush symbols"} + -re "$gdb_prompt $" {fail "before attach3, flush symbols"} + timeout {fail "(timeout) before attach3, flush symbols"} + } + send_gdb "exec\n" + gdb_expect { + -re ".*No exec file now.*$gdb_prompt $"\ + {pass "before attach3, flush exec"} + -re "$gdb_prompt $" {fail "before attach3, flush exec"} + timeout {fail "(timeout) before attach3, flush exec"} + } + + send_gdb "attach $testpid\n" + gdb_expect { + -re "Attaching to process $testpid.*Reading symbols from $binfile.*main.*at .*$gdb_prompt $"\ + {pass "attach when process' a.out not in cwd"} + -re "$gdb_prompt $" {fail "attach when process' a.out not in cwd"} + timeout {fail "(timeout) attach when process' a.out not in cwd"} + } + + send_gdb "kill\n" + gdb_expect { + -re ".*Kill the program being debugged.*y or n. $"\ + {send_gdb "y\n" + gdb_expect { + -re "$gdb_prompt $" {pass "after attach3, exit"} + timeout {fail "(timeout) after attach3, exit"} + } + } + -re "$gdb_prompt $" {fail "after attach3, exit"} + timeout {fail "(timeout) after attach3, exit"} + } +} + +proc do_call_attach_tests {} { + global gdb_prompt + global binfile2 + + # Start the program running and then wait for a bit, to be sure + # that it can be attached to. + # + set testpid [eval exec $binfile2 &] + exec sleep 2 + + # Attach + # + send_gdb "attach $testpid\n" + gdb_expect { + -re ".*warning: reading register.*I.*O error.*$gdb_prompt $" { + fail "attach call, read register 3 error" + } + -re "Attaching to.*process $testpid.*libc.*$gdb_prompt $" { + pass "attach call" + } + -re "$gdb_prompt $" {fail "attach call"} + timeout {fail "(timeout) attach call"} + } + + # See if other registers are problems + # + send_gdb "i r r3\n" + gdb_expect { + -re ".*warning: reading register.*$gdb_prompt $" { + pass "CHFts23490: known bug" + } + -re ".*r3.*$gdb_prompt $" { + pass "Bug fixed, Yayyy!" + } + timeout { fail "timeout on info reg" } + } + + # Get rid of the process + # + gdb_test "p should_exit = 1" ".*" "" + gdb_test "c" ".*Program exited normally.*" "" + + # Be paranoid + # +# execute_anywhere "kill -9 ${testpid}" +remote_exec build "kill -9 ${testpid}" + +} + + +# Start with a fresh gdb +# +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +# This is a test of gdb's ability to attach to a running process. +# +do_attach_tests + +# Test attaching when the target is inside a system call +# +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +do_call_attach_tests + +# Until "set follow-fork-mode" and "catch fork" are implemented on +# other targets... +# +if ![istarget "hppa*-hp-hpux*"] then { + setup_xfail "*-*-*" +} + +return 0 diff --git a/gdb/testsuite/gdb.hp/attach2.c b/gdb/testsuite/gdb.hp/attach2.c new file mode 100644 index 00000000000..8eb7a056746 --- /dev/null +++ b/gdb/testsuite/gdb.hp/attach2.c @@ -0,0 +1,23 @@ +/* This program is intended to be started outside of gdb, and then + attached to by gdb. Thus, it simply spins in a loop. The loop + is exited when & if the variable 'should_exit' is non-zero. (It + is initialized to zero in this program, so the loop will never + exit unless/until gdb sets the variable to non-zero.) + */ +#include <stdio.h> +#include <stdlib.h> + +int should_exit = 0; + +main () +{ + int local_i = 0; + + sleep( 10 ); /* System call causes register fetch to fail */ + /* This is a known HPUX "feature" */ + while (! should_exit) + { + local_i++; + } + return (0); +} diff --git a/gdb/testsuite/gdb.hp/attach2.exp b/gdb/testsuite/gdb.hp/attach2.exp new file mode 100644 index 00000000000..e298ee93f7a --- /dev/null +++ b/gdb/testsuite/gdb.hp/attach2.exp @@ -0,0 +1,263 @@ +# attach.exp -- Expect script to test attaching to a threaded pgm +# Copyright (C) 1992 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 2 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +# Please email any bugs, comments, and/or additions to this file to: +# bug-gdb@prep.ai.mit.edu + +# use this to debug: +# +#log_user 1 + +# Temporarily comment out - hanging +#return 0 + +if $tracelevel then { + strace $tracelevel +} + +# Thread stuff is _slow_; prepare for long waits. +# +# Further, this test has some "null" lines designed +# to consume output from gdb that was too late to be +# matched (sequence is "gdb_test" sends; timeout and +# on to next send; result finally comes in; mismatch). +# +# The null command is 'gdb_test "p \$pc" ".*" ""' +# NOTE: this command undoes any up/down stuff! +# +proc pre_timeout { how_long } { + global timeout + + set timeout [expr "$timeout + $how_long"] +} + +proc post_timeout {} { + global timeout + global oldtimeout + + set timeout $oldtimeout + gdb_test "p \$pc" ".*" "" +} + +if { ![istarget "hppa*-*-hpux10.30"] && ![istarget "hppa*-*-hpux11.*"] } { + verbose "HPUX thread test ignored for non-hppa or pre-HP/UX-10.30 targets." + return 0 +} + +# We used to wait 5 seconds , but tiamat is faster than +# hydra...or is it that the OS allocates time differently(?). +# +set delay 5 +if { ![istarget "hppa*-*-hpux11.*"] } { + set delay 45 +} + +set testfile quicksort +set srcfile ${srcdir}/${subdir}/${testfile}.c +set binfile ${objdir}/${subdir}/${testfile} + +if [get_compiler_info ${binfile}] { + return -1 +} + +set oldtimeout $timeout +#set timeout [expr "$timeout + 100"] +set oldverbose $verbose +#set verbose 40 + +# To build the executable we need to link against the thread library. +# +# cc -Ae -g -o quicksort -lpthread quicksort.c +# +#remote_exec build "${srcfile} -Ae -g -lpthread -o ${binfile}" +#gdb_compile "${srcfile} -Ae -g -lpthread -o ${binfile}" + +if {$gcc_compiled == 0} { + set additional_flags "additional_flags=-Ae" +} else { + set additional_flags "" +} + +if { [gdb_compile "${srcdir}/${subdir}/${testfile}.c" "${binfile}.o" object [list debug $additional_flags]] != "" } { + gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail." +} +remote_exec build "ld /usr/ccs/lib/crt0.o ${binfile}.o -lcl -lpthread -lc /opt/langtools/lib/end.o -o ${binfile}" + + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir + +# Start the application running and get its pid. +# Then we wait for it to get started and attach. +# +set testpid [eval exec $binfile 1 &] +exec sleep $delay + +# Now attach to the file. +# +pre_timeout 100 +gdb_test "attach $testpid" ".*Attaching to process.*Reading symbols from.*done.*" "attach to target" +post_timeout + +# Wait for things to quiesce. +# +exec sleep 0 + +send_gdb "bt\n" + +set do_return 0 +set do_go_to_118 0 +pre_timeout 400 +gdb_expect { + -re ".*sleep.*work_init.*main.*$gdb_prompt $" { + pass "at expected location" + } + -re ".*drand48.*$gdb_prompt $" { + set do_go_to_118 1 + } + -re ".*pthread_mutex_lock.*$gdb_prompt $" { + set do_go_to_118 1 + } + -re ".*pthread_mutex_unlock.*$gdb_prompt $" { + set do_go_to_118 1 + } + -re ".*main.*$gdb_prompt $" { + set do_go_to_118 1 + } + -re ".*No stack.*$gdb_prompt $" { + fail "Failed attach, change wait amount down, rest would fail" + set do_return 1 + } + -re ".*$gdb_prompt $" { + # Who knows? + # + set do_go_to_118 1 + } + timeout { + set do_return 1 + fail "timeout on bt, avoiding rest of test" + } +} +post_timeout + +# Too late; just give up. +# +if { $do_return } { + set timeout $oldtimeout + set verbose $oldverbose + return 0 +} + +# Maybe too early--set a temp break and continue. +# We have to set this on both paths, so that we can +# know what numbers breakpoints will be. +# +gdb_test "tb 118" ".*Breakpoint 1.*118.*" "" +if { $do_go_to_118 } { + pre_timeout 100 + send_gdb "c\n" + gdb_expect { + -re ".*at.*118.*118.*$gdb_prompt $" { + # Ok, just keep going + } + -re ".*Program exited.*$gdb_prompt $" { + fail "Attached too late, set wait amount downwards" + set timeout $oldtimeout + set verbose $oldverbose + return 0 + } + -re ".*$gdb_prompt $" { + fail "Unexpected result on attach" + set timeout $oldtimeout + set verbose $oldverbose + return 0 + } + timeout { + fail "timeout on continue " + } + } + post_timeout +} + +# Look at the threads. +# +pre_timeout 100 +gdb_test "info thread" ".*7.*6.*5.*4.*3.*2.*\\\* 1.*thread.*" "first info thread" +post_timeout + +# We expect to be inside the "sleep" call, so check that. +# +if { [expr "!$do_go_to_118"] } { + gdb_test "up" ".*\#1.*nanosleep.*" "up 1" + gdb_test "up" ".*\#2.*sleep.*" "up 2" + pre_timeout 100 + gdb_test "up" ".*\#3.*work_init.*$testfile.*c:118.*sleep.*" "up 3" + post_timeout +} else { + send_user "Skipped three tests\n" +} + +# Get out of that call. +# +gdb_test "b 120" ".*Breakpoint 2.*120.*" "set bp" +pre_timeout 100 +gdb_test "c" ".*Breakpoint 2.*at.*120.*" "hit bp" +post_timeout + +# Look at the threads. +# +pre_timeout 100 +gdb_test "info thread" ".*7.*6.*5.*4.*3.*2.*1.*thread.*$testfile.*c*120.*" "2nd info thread" +post_timeout + +# Do some more stuff, to make sure we can +# +gdb_test "thread 3" ".*Switching to.*thread.*ksleep.*" "switch thread" + +gdb_test "up" ".*_lwp_cond_timedwait.*" "up 5" +gdb_test "up" ".*pthread_cond_wait.*" "up 6" +gdb_test "up" ".*\#3.*worker.*144.*" "up 7" +gdb_test "up" ".*__pthread_exit.*" "up 8" +gdb_test "up" ".*Initial.*cannot go up.*" "found thread base" + +gdb_test "b 145 thr 3" ".*Breakpoint 3.*145.*" "thread-specific bp" +gdb_test "i b" ".*2.*breakpoint.*at.*120.*3.*breakpoint.*at.*145 thread 3.*" "show thread-specific bp" +gdb_test "del 2" ".*" "" + +gdb_test "c" ".*Breakpoint 3.*145.*" "hit thread-specific bp" +gdb_test "i th" ".*\\\* 3.*145.*" "at correct thread" + +pre_timeout 100 +gdb_test "n" ".*146.*" "next from thread-specific bp" +post_timeout + +gdb_test "d 3" ".*" "" +gdb_test "c" ".*Program exited normally\..*" "run to finish" + +# Done! +# +gdb_exit + +set timeout $oldtimeout +set verbose $oldverbose + +# execute_anywhere "rm -f ${binfile}" +# +return 0 + + diff --git a/gdb/testsuite/gdb.hp/average.c b/gdb/testsuite/gdb.hp/average.c new file mode 100644 index 00000000000..070eaefa27e --- /dev/null +++ b/gdb/testsuite/gdb.hp/average.c @@ -0,0 +1,39 @@ +/* This is a sample program for the HP WDB debugger. */ + +#include <stdio.h> + +#define num 10 + +static int my_list[num] = {3,4,2,0,2,1,8,3,6,7}; + +#ifdef __STDC__ +void print_average(int list[], int low, int high) +#else +void print_average(list, low, high) +int list[], low, high; +#endif + { + int total, num_elements, average; + total = sum(list, low, high); + num_elements = high - low; /* note this is an off-by-one bug */ + + average = total / num_elements; + printf("%10.d\n", average); + } + +#ifdef __STDC__ +int main(void) +#else +main () +#endif +{ + char c; + int first = 0; + int last = num-1; + + /* Try two test cases. */ + print_average (my_list, first, last); + print_average (my_list, first, last - 3); +foo: + exit(0); +} diff --git a/gdb/testsuite/gdb.hp/classes-hp.exp b/gdb/testsuite/gdb.hp/classes-hp.exp new file mode 100644 index 00000000000..cb22c96e8fc --- /dev/null +++ b/gdb/testsuite/gdb.hp/classes-hp.exp @@ -0,0 +1,859 @@ +# Copyright (C) 1992, 1994, 1995, 1997 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 2 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +# Please email any bugs, comments, and/or additions to this file to: +# bug-gdb@prep.ai.mit.edu + +# This file was written by Fred Fish. (fnf@cygnus.com) + +set ws "\[\r\n\t \]+" + +if $tracelevel then { + strace $tracelevel +} + + +# Check to see if we have an executable to test. If not, then either we +# haven't tried to compile one, or the compilation failed for some reason. +# In either case, just notify the user and skip the tests in this file. + +set testfile "misc-hp" +set srcfile ${testfile}.cc +set binfile ${objdir}/${subdir}/${testfile} + +if [get_compiler_info ${binfile} "c++"] { + return -1; +} + + +if {[skip_hp_tests $gcc_compiled]} then { continue } + +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } { + gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail." +} + +# +# Test ptype of class objects. +# + +proc test_ptype_class_objects {} { + global gdb_prompt + global ws + + # Note that struct members are public by default, so we don't print + # "public:" for the public members of structs. + # Accept it as an expected failure if gdb just fails to distinguish between + # class and struct, and everything else is OK. + + send_gdb "ptype struct default_public_struct\n" + gdb_expect { + -re "type = struct default_public_struct \{${ws}int a;${ws}int b;\r\n\}\r\n$gdb_prompt $" { + pass "ptype struct default_public_struct" + } + -re "type = class default_public_struct \{\r\n.*int a;${ws}int b;\r\n.*\}\r\n$gdb_prompt $" { + setup_xfail "*-*-*" + fail "ptype struct default_public_struct" + } + -re ".*$gdb_prompt $" { fail "ptype struct default_public_struct" } + timeout { fail "ptype struct default_public_struct (timeout)" ; return } + } + + # Note that struct members are public by default, so we don't print + # "public:" for the public members of structs. + # Accept it as an expected failure if gdb just fails to distinguish between + # class and struct, and everything else is OK. + + send_gdb "ptype struct explicit_public_struct\n" + gdb_expect { + -re "type = struct explicit_public_struct \{${ws}int a;${ws}int b;\r\n.*\}\r\n$gdb_prompt $" { + pass "ptype struct explicit_public_struct" + } + -re "type = class explicit_public_struct \{\r\n.*int a;${ws}int b;\r\n.*\}\r\n$gdb_prompt $" { + setup_xfail "*-*-*" + fail "ptype struct explicit_public_struct" + } + -re ".*$gdb_prompt $" { fail "ptype struct explicit_public_struct" } + timeout { fail "ptype struct explicit_public_struct (timeout)" ; return } + } + + # Accept it as an expected failure if gdb just fails to distinguish between + # class and struct, and everything else is OK. + + setup_xfail_format "DWARF 1" + send_gdb "ptype struct protected_struct\n" + gdb_expect { + -re "type = struct protected_struct \{${ws}protected:${ws}int a;${ws}int b;\r\n\}\r\n$gdb_prompt $" { + pass "ptype struct protected_struct (FIXME)" + } + -re "type = class protected_struct \{${ws}protected:${ws}int a;${ws}int b;\r\n.*\}\r\n$gdb_prompt $" { + setup_xfail "*-*-*" + fail "ptype struct protected_struct (FIXME)" + } + -re ".*$gdb_prompt $" { fail "ptype struct protected_struct" } + timeout { fail "ptype struct protected_struct (timeout)" ; return } + } + + # Accept it as an expected failure if gdb just fails to distinguish between + # class and struct, and everything else is OK. + + setup_xfail_format "DWARF 1" + send_gdb "ptype struct private_struct\n" + gdb_expect { + -re "type = struct private_struct \{${ws}private:${ws}int a;${ws}int b;\r\n\}\r\n$gdb_prompt $" { + pass "ptype struct private_struct (FIXME)" + } + -re "type = class private_struct \{${ws}private:${ws}int a;${ws}int b;\r\n.*\}\r\n$gdb_prompt $" { + setup_xfail "*-*-*" + fail "ptype struct private_struct (FIXME)" + } + -re ".*$gdb_prompt $" { fail "ptype struct private_struct" } + timeout { fail "ptype struct private_struct (timeout)" ; return } + } + + # Accept it as an expected failure if gdb just fails to distinguish between + # class and struct, and everything else is OK. + + setup_xfail_format "DWARF 1" + send_gdb "ptype struct mixed_protection_struct\n" + gdb_expect { + -re "type = struct mixed_protection_struct \{${ws}int a;${ws}int b;${ws}private:${ws}int c;${ws}int d;${ws}protected:${ws}int e;${ws}int f;${ws}public:${ws}int g;${ws}private:${ws}int h;${ws}protected:${ws}int i;\[\r\n\]+\}\[\r\n\]+$gdb_prompt $" { + pass "ptype struct mixed_protection_struct (FIXME)" + } + -re "type = struct mixed_protection_struct \{\r\n\[ \]*public:\r\n\[ \]*int a;\r\n\[ \]*int b;\r\n\[ \]*private:\r\n\[ \]*int c;\r\n\[ \]*int d;\r\n\[ \]*protected:\r\n\[ \]*int e;\r\n\[ \]*int f;\r\n\[ \]*public:\r\n\[ \]*int g;\r\n\[ \]*private:\r\n\[ \]*int h;\r\n\[ \]*protected:\r\n\[ \]*int i;\r\n.*\}\r\n$gdb_prompt $" { + pass "ptype struct mixed_protection_struct (extra public)" + } + -re "type = class mixed_protection_struct \{${ws}public:${ws}int a;${ws}int b;${ws}private:${ws}int c;${ws}int d;${ws}protected:${ws}int e;${ws}int f;${ws}public:${ws}int g;${ws}private:${ws}int h;${ws}protected:${ws}int i;\r\n.*\}\r\n$gdb_prompt $" { + setup_xfail "*-*-*" + fail "ptype struct mixed_protection_struct (FIXME)" + } + -re ".*$gdb_prompt $" { fail "ptype struct mixed_protection_struct" } + timeout { fail "ptype struct mixed_protection_struct (timeout)" ; return } + } + + # Accept it as an expected failure if gdb just fails to distinguish between + # class and struct, and everything else is OK. + + send_gdb "ptype class public_class\n" + gdb_expect { + -re "type = class public_class \{${ws}public:${ws}int a;${ws}int b;\r\n.*\}\r\n$gdb_prompt $" { + pass "ptype class public_class (FIXME)" + } + -re "type = struct public_class \{${ws}int a;${ws}int b;\r\n\}\r\n$gdb_prompt $" { + setup_xfail "*-*-*" + fail "ptype class public_class (FIXME)" + } + -re ".*$gdb_prompt $" { fail "ptype class public_class" } + timeout { fail "ptype class public_class (timeout)" ; return } + } + + send_gdb "ptype class protected_class\n" + gdb_expect { + -re "type = class protected_class \{${ws}protected:${ws}int a;${ws}int b;\r\n.*\}\r\n$gdb_prompt $" { + pass "ptype class protected_class" + } + -re "type = struct protected_class \{${ws}int a;${ws}int b;\r\n\}\r\n$gdb_prompt $" { + setup_xfail "*-*-*" + fail "ptype class protected_class" + } + -re ".*$gdb_prompt $" { fail "ptype class protected_class" } + timeout { fail "ptype class protected_class (timeout)" ; return } + } + + # Accept it as an expected failure if gdb just emits a superflous "private:" + # attribute, since classes default to private and for consistency with + # structs (where we don't print the "public:" attribute) we don't print + # the "private:" attribute. + + setup_xfail_format "DWARF 1" + send_gdb "ptype class default_private_class\n" + gdb_expect { + -re "type = class default_private_class \{${ws}int a;${ws}int b;\r\n.*\}\r\n$gdb_prompt $" { + pass "ptype class default_private_class (FIXME)" + } + -re "type = class default_private_class \{${ws}private:${ws}int a;${ws}int b;\r\n.*\}\r\n$gdb_prompt $" { + setup_xfail "*-*-*" + fail "ptype class default_private_class (FIXME)" + } + -re ".*$gdb_prompt $" { fail "ptype class default_private_class" } + timeout { fail "ptype class default_private_class (timeout)" ; return } + } + + send_gdb "ptype class explicit_private_class\n" + gdb_expect { + -re "type = class explicit_private_class \{${ws}private:${ws}int a;${ws}int b;\r\n.*\}\r\n$gdb_prompt $" { + pass "ptype class explicit_private_class" + } + -re "type = class explicit_private_class \{\r\n\[ \]*int a;\r\n\[ \]*int b;\r\n.*\}\r\n$gdb_prompt $" { + pass "ptype class explicit_private_class (OK for HP aCC)" + } + -re "type = struct explicit_private_class \{${ws}int a;${ws}int b;\r\n.*\}\r\n$gdb_prompt $" { + setup_xfail "*-*-*" + fail "ptype class explicit_private_class" + } + -re ".*$gdb_prompt $" { fail "ptype class explicit_private_class" } + timeout { fail "ptype class explicit_private_class (timeout)" ; return } + } + + send_gdb "ptype class mixed_protection_class\n" + gdb_expect { + -re "type = class mixed_protection_class \{${ws}public:${ws}int a;${ws}int b;${ws}private:${ws}int c;${ws}int d;${ws}protected:${ws}int e;${ws}int f;${ws}public:${ws}int g;${ws}private:${ws}int h;${ws}protected:${ws}int i;\r\n.*\}\r\n$gdb_prompt $" { + pass "ptype class mixed_protection_class" + } + -re "type = struct mixed_protection_class \{${ws}int a;${ws}int b;${ws}int c;${ws}int d;${ws}int e;${ws}int f;${ws}int g;${ws}int h;${ws}int i;\r\n.*\}\r\n$gdb_prompt $" { + setup_xfail "*-*-*" + fail "ptype class mixed_protection_class" + } + -re ".*$gdb_prompt $" { fail "ptype class mixed_protection_class" } + timeout { fail "ptype class mixed_protection_class (timeout)" ; return } + } + + # This class does not use any C++-specific features, so it's fine for + # it to print as "struct". + send_gdb "ptype class A\n" + gdb_expect { + -re "type = (class|struct) A \{(${ws}public:|)${ws}int a;${ws}int x;((${ws}A & operator=\\(A const &\\);)|(${ws}A\\(A const &\\);)|(${ws}A\\(void\\);))*${ws}\}\r\n$gdb_prompt $" { + pass "ptype class A" + } + -re ".*$gdb_prompt $" { + fail "ptype class A" + } + timeout { + fail "ptype class A (timeout)" + return + } + } + + setup_xfail_format "DWARF 1" + send_gdb "ptype class B\n" + gdb_expect { + -re "type = class B : public A \{${ws}public:${ws}int b;${ws}int x;${ws}B & operator=\\(B const &\\);${ws}B\\(B const &\\);${ws}B\\(void\\);${ws}\}\r\n$gdb_prompt $" { + pass "ptype class B" + } + -re "type = class B : public A \{${ws}public:${ws}int b;${ws}int x;((${ws}B & operator=\\(B const &\\);)|(${ws}B\\(B const &\\);)|(${ws}B\\(void\\);))*${ws}\}\r\n$gdb_prompt $" { + pass "ptype class B (obsolescent gcc or gdb)" + } + -re ".*$gdb_prompt $" { + fail "ptype class B" + } + timeout { + fail "ptype class B (timeout)" + return + } + } + + setup_xfail_format "DWARF 1" + send_gdb "ptype class C\n" + gdb_expect { + -re "type = class C : public A \{${ws}public:${ws}int c;${ws}int x;${ws}C & operator=\\(C const &\\);${ws}C\\(C const &\\);${ws}C\\(void\\);${ws}\}\r\n$gdb_prompt $" { + pass "ptype class C" + } + -re "type = class C : public A \{${ws}public:${ws}int c;${ws}int x;((${ws}C & operator=\\(C const &\\);)|(${ws}C\\(C const &\\);)|(${ws}C\\(void\\);))*${ws}\}\r\n$gdb_prompt $" { + pass "ptype class C (obsolescent gcc or gdb)" + } + -re ".*$gdb_prompt $" { + fail "ptype class C" + } + timeout { + fail "ptype class C (timeout)" + return + } + } + + setup_xfail_format "DWARF 1" + send_gdb "ptype class D\n" + gdb_expect { + -re "type = class D : public B, public C \{${ws}public:${ws}int d;${ws}int x;${ws}D & operator=\\(D const &\\);${ws}D\\(D const &\\);${ws}D\\(void\\);${ws}\}\r\n$gdb_prompt $" { + pass "ptype class D" + } + -re "type = class D : public B, public C \{${ws}public:${ws}int d;${ws}int x;((${ws}D & operator=\\(D const &\\);)|(${ws}D\\(D const &\\);)|(${ws}D\\(void\\);))*${ws}\}\r\n$gdb_prompt $" { + pass "ptype class D (obsolescent gcc or gdb)" + } + -re ".*$gdb_prompt $" { + fail "ptype class D" + } + timeout { + fail "ptype class D (timeout)" + return + } + } + + setup_xfail_format "DWARF 1" + send_gdb "ptype class E\n" + gdb_expect { + -re "type = class E : public D \{${ws}public:${ws}int e;${ws}int x;${ws}E & operator=\\(E const &\\);${ws}E\\(E const &\\);${ws}E\\(void\\);${ws}\}\r\n$gdb_prompt $" { + pass "ptype class E" + } + -re "type = class E : public D \{${ws}public:${ws}int e;${ws}int x;((${ws}E & operator=\\(E const &\\);)|(${ws}E\\(E const &\\);)|(${ws}E\\(void\\);))*${ws}\}\r\n$gdb_prompt $" { + pass "ptype class E" + } + -re ".*$gdb_prompt $" { + fail "ptype class E" + } + timeout { + fail "ptype class E (timeout)" + return + } + } + + send_gdb "ptype class vA\n" + gdb_expect { + -re "type = (class|struct) vA \{(${ws}public:|)${ws}int va;${ws}int vx;${ws}vA & operator=\\(vA const &\\);${ws}vA\\(vA const &\\);${ws}vA\\(void\\);${ws}\}\r\n$gdb_prompt $" { + pass "ptype class vA" + } + -re "type = (class|struct) vA \{(${ws}public:|)${ws}int va;${ws}int vx;((${ws}vA & operator=\\(vA const &\\);)|(${ws}vA\\(vA const &\\);)|(${ws}vA\\(void\\);))*${ws}\}\r\n$gdb_prompt $" { + pass "ptype class vA (obsolescent gcc or gdb)" + } + -re ".*$gdb_prompt $" { + fail "ptype class vA" + } + timeout { + fail "ptype class vA (timeout)" + return + } + } + + # Accept the form with embedded GNU style mangled virtual table constructs + # for now, but with a FIXME. At some future point, gdb should use a + # portable representation for the virtual table constructs. + + setup_xfail_format "DWARF 1" + send_gdb "ptype class vB\n" + gdb_expect { + -re "type = class vB : public virtual vA \{${ws}private:${ws}vA \\*_vb.vA;${ws}public:${ws}int vb;${ws}int vx;${ws}vB & operator=\\(vB const &\\);${ws}vB\\(int, vB const &\\);${ws}vB\\(int\\);${ws}\}\r\n$gdb_prompt $" { + setup_xfail "*-*-*" + fail "ptype class vB (FIXME: non-portable virtual table constructs)" + } + -re "type = class vB : public virtual vA \{\r\n\[ \]*public:\r\n\[ \]*int vb;\r\n\[ \]*int vx;\[\r\n\t \]+\}\r\n$gdb_prompt $" { + pass "ptype class vB (aCC)" + } + -re "type = class vB : public virtual vA \{${ws}private:${ws}vA \\*_vb.vA;${ws}public:${ws}int vb;${ws}int vx;((${ws}vB & operator=\\(vB const &\\);)|(${ws}vB\\(int, vB const &\\);)|(${ws}vB\\(int\\);))*${ws}\}\r\n$gdb_prompt $" { + setup_xfail "*-*-*" + fail "ptype class vB (FIXME) (obsolescent gcc or gdb)" + } + -re ".*$gdb_prompt $" { + fail "ptype class vB" + } + timeout { + fail "ptype class vB (timeout)" + return + } + } + + # Accept the form with embedded GNU style mangled virtual table constructs + # for now, but with a FIXME. At some future point, gdb should use a + # portable representation for the virtual table constructs. + + setup_xfail_format "DWARF 1" + send_gdb "ptype class vC\n" + gdb_expect { + -re "type = class vC : public virtual vA \{${ws}private:${ws}vA \\*_vb.vA;${ws}public:${ws}int vc;${ws}int vx;${ws}vC & operator=\\(vC const &\\);${ws}vC\\(int, vC const &\\);${ws}vC\\(int\\);${ws}\}\r\n$gdb_prompt $" { + setup_xfail "*-*-*" + fail "ptype class vC (FIXME: non-portable virtual table constructs)" + } + -re "type = class vC : public virtual vA \{\r\n\[ \]*public:\r\n\[ \]*int vc;\r\n\[ \]*int vx;\[\r\n\t \]+\}\r\n$gdb_prompt $" { + pass "ptype class vC (aCC)" + } + -re "type = class vC : public virtual vA \{${ws}private:${ws}vA \\*_vb.vA;${ws}public:${ws}int vc;${ws}int vx;((${ws}vC & operator=\\(vC const &\\);)|(${ws}vC\\(int, vC const &\\);)|(${ws}vC\\(int\\);))*${ws}\}\r\n$gdb_prompt $" { + setup_xfail "*-*-*" + fail "ptype class vC (FIXME) (obsolescent gcc or gdb)" + } + -re ".*$gdb_prompt $" { + fail "ptype class vC" + } + timeout { + fail "ptype class vC (timeout)" + return + } + } + + # Accept the form with embedded GNU style mangled virtual table constructs + # for now, but with a FIXME. At some future point, gdb should use a + # portable representation for the virtual table constructs. + + setup_xfail_format "DWARF 1" + send_gdb "ptype class vD\n" + gdb_expect { + -re "type = class vD : public virtual vB, public virtual vC \{${ws}private:${ws}vC \\*_vb.vC;${ws}vB \\*_vb.vB;${ws}public:${ws}int vd;${ws}int vx;${ws}vD & operator=\\(vD const &\\);${ws}vD\\(int, vD const &\\);${ws}vD\\(int\\);${ws}\}\r\n$gdb_prompt $" { + setup_xfail "*-*-*" + fail "ptype class vD (FIXME: non-portable virtual table constructs)" + } + -re "type = class vD : public virtual vB, public virtual vC \{\r\n\[ \]*public:\r\n\[ \]*int vd;\r\n\[ \]*int vx;\[\r\n\t \]+\}\r\n$gdb_prompt $" { + pass "ptype class vD (aCC)" + } + -re "type = class vD : public virtual vB, public virtual vC \{${ws}private:${ws}vC \\*_vb.vC;${ws}vB \\*_vb.vB;${ws}public:${ws}int vd;${ws}int vx;((${ws}vD & operator=\\(vD const &\\);)|(${ws}vD\\(int, vD const &\\);)|(${ws}vD\\(int\\);))*${ws}\}\r\n$gdb_prompt $" { + setup_xfail "*-*-*" + fail "ptype class vD (FIXME) (obsolescent gcc or gdb)" + } + -re ".*$gdb_prompt $" { + fail "ptype class vD" + } + timeout { + fail "ptype class vD (timeout)" + return + } + } + + # Accept the form with embedded GNU style mangled virtual table constructs + # for now, but with a FIXME. At some future point, gdb should use a + # portable representation for the virtual table constructs. + + setup_xfail_format "DWARF 1" + send_gdb "ptype class vE\n" + gdb_expect { + -re "type = class vE : public virtual vD \{${ws}private:${ws}vD \\*_vb.vD;${ws}public:${ws}int ve;${ws}int vx;${ws}vE & operator=\\(vE const &\\);${ws}vE\\(int, vE const &\\);${ws}vE\\(int\\);${ws}\}\r\n$gdb_prompt $" { + setup_xfail "*-*-*" + fail "ptype class vE (FIXME: non-portable virtual table constructs)" + } + -re "type = class vE : public virtual vD \{\r\n\[ \]*public:\r\n\[ \]*int ve;\r\n\[ \]*int vx;\[\r\n\t \]+\}\r\n$gdb_prompt $" { + pass "ptype class vE (aCC)" + } + -re "type = class vE : public virtual vD \{${ws}private:${ws}vD \\*_vb.vD;${ws}public:${ws}int ve;${ws}int vx;((${ws}vE & operator=\\(vE const &\\);)|(${ws}vE\\(int, vE const &\\);)|(${ws}vE\\(int\\);))*${ws}\}\r\n$gdb_prompt $" { + setup_xfail "*-*-*" + fail "ptype class vE (FIXME) (obsolescent gcc or gdb)" + } + -re ".*$gdb_prompt $" { + fail "ptype class vE" + } + timeout { + fail "ptype class vE (timeout)" + return + } + } + + setup_xfail_format "DWARF 1" + send_gdb "ptype class Base1\n" + gdb_expect { + -re "type = class Base1 \{${ws}public:${ws}int x;${ws}Base1 & operator=\\(Base1 const &\\);${ws}Base1\\(Base1 const &\\);${ws}Base1\\(int\\);${ws}\}\r\n$gdb_prompt $" { + pass "ptype class Base1" + } + -re "type = class Base1 \{${ws}public:${ws}int x;((${ws}Base1 & operator=\\(Base1 const &\\);)|(${ws}Base1\\(Base1 const &\\);)|(${ws}Base1\\(int\\);))*${ws}\}\r\n$gdb_prompt $" { + pass "ptype class Base1 (obsolescent gcc or gdb)" + } + -re ".*$gdb_prompt $" { + fail "ptype class Base1" + } + timeout { + fail "ptype class Base1 (timeout)" + return + } + } + + setup_xfail_format "DWARF 1" + send_gdb "ptype class Foo\n" + gdb_expect { + -re "type = class Foo \{\r\n\[ \]*public:\r\n\[ \]*int x;\r\n\[ \]*int y;\r\n\[ \]*static int st;\r\n\r\n\[ \]*Foo\\(int, int\\);\r\n\[ \]*int operator!.void.;\r\n\[ \]*operator int.void.;\r\n\[ \]*int times.int.;\r\n\}\r\n$gdb_prompt $" { + pass "ptype class Foo(aCC)" + } + -re "type = class Foo \{${ws}public:${ws}int x;${ws}int y;${ws}static int st;${ws}Foo & operator=\\(Foo const &\\);${ws}Foo\\(Foo const &\\);${ws}Foo\\(int, int\\);${ws}int operator!\\(void\\);${ws}int operator int\\(void\\);${ws}int times\\(int\\);${ws}\}\r\n$gdb_prompt $" { + pass "ptype class Foo" + } + -re "type = class Foo \{${ws}public:${ws}int x;${ws}int y;${ws}static int st;((${ws}Foo & operator=\\(Foo const &\\);)|(${ws}Foo\\(Foo const &\\);)|(${ws}Foo\\(int, int\\);)|(${ws}int operator!\\(void\\);)|(${ws}int operator int\\(void\\);)|(${ws}int times\\(int\\);))*${ws}\}\r\n$gdb_prompt $" { + pass "ptype class Foo (obsolescent gcc or gdb)" + } + -re ".*$gdb_prompt $" { + fail "ptype class Foo" + } + timeout { + fail "ptype class Foo (timeout)" + return + } + } + + setup_xfail_format "DWARF 1" + send_gdb "ptype class Bar\n" + gdb_expect { + -re "type = class Bar : public Base1, public Foo \{${ws}public:${ws}int z;${ws}Bar & operator=\\(Bar const &\\);${ws}Bar\\(Bar const &\\);${ws}Bar\\(int, int, int\\);${ws}\}\r\n$gdb_prompt $" { + pass "ptype class Bar" + } + -re "type = class Bar : public Base1, public Foo \{${ws}public:${ws}int z;((${ws}Bar & operator=\\(Bar const &\\);)|(${ws}Bar\\(Bar const &\\);)|(${ws}Bar\\(int, int, int\\);))*${ws}\}\r\n$gdb_prompt $" { + pass "ptype class Bar (obsolescent gcc or gdb)" + } + -re ".*$gdb_prompt $" { + fail "ptype class Bar" + } + timeout { + fail "ptype class Bar (timeout)" + return + } + } +} + +# +# Test simple access to class members. +# + +proc test_non_inherited_member_access {} { + global gdb_prompt + + # Print non-inherited members of g_A. + + gdb_test "print g_A.a" ".* = 1" "g_A.a incorrect" + + gdb_test "print g_A.x" ".* = 2" "g_A.x incorrect" + + # Print non-inherited members of g_B. + + gdb_test "print g_B.b" ".* = 5" "g_B.b incorrect" + + gdb_test "print g_B.x" ".* = 6" "g_B.x incorrect" + + # Print non-inherited members of g_C. + + gdb_test "print g_C.c" ".* = 9" "g_C.c incorrect" + + gdb_test "print g_C.x" ".* = 10" "g_C.x incorrect" + + # Print non-inherited members of g_D. + + gdb_test "print g_D.d" ".* = 19" "g_D.d incorrect" + + gdb_test "print g_D.x" ".* = 20" "g_D.x incorrect" + + # Print non-inherited members of g_E. + + gdb_test "print g_E.e" ".* = 31" "g_E.e incorrect" + + gdb_test "print g_E.x" ".* = 32" "g_E.x incorrect" +} + +# +# Try access to non-members that are members of another class. +# Should give errors. +# + +proc test_wrong_class_members {} { + global gdb_prompt + + gdb_test "print g_A.b" "There is no member( or method|) named b." "print g_A.b should be error" + + gdb_test "print g_B.c" "There is no member( or method|) named c." "print g_B.c should be error" + + gdb_test "print g_B.d" "There is no member( or method|) named d." "print g_B.d should be error" + + gdb_test "print g_C.b" "There is no member( or method|) named b." "print g_C.b should be error" + + gdb_test "print g_C.d" "There is no member( or method|) named d." "print g_C.d should be error" + + gdb_test "print g_D.e" "There is no member( or method|) named e." "print g_D.e should be error" +} + +# +# Try access to non-members that are not members of any class. +# Should give errors. +# + +proc test_nonexistant_members {} { + global gdb_prompt + + gdb_test "print g_A.y" "There is no member( or method|) named y." "print g_A.y should be error" + + gdb_test "print g_B.z" "There is no member( or method|) named z." "print g_B.z should be error" + + gdb_test "print g_C.q" "There is no member( or method|) named q." "print g_C.q should be error" + + gdb_test "print g_D.p" "There is no member( or method|) named p." "print g_D.p should be error" +} + +# +# Pointers to class members +# + +proc test_pointers_to_class_members {} { + global gdb_prompt + global decimal + + gdb_test "print Bar::z" ".* = .int\[ \]*\[( \]*Bar::&\[)\]+\[ \]*Bar::z" "print Bar::z" + + gdb_test "print &Foo::x" ".* = .int\[ \]*\[( \]*Foo::\[*)\]+\[ \]*&Foo::x" "print &Foo::x" + + gdb_test "print (int)&Foo::x" ".* = 0" "print (int)&Foo::x" + + send_gdb "print (int)&Bar::y == 2*sizeof(int)\n" + gdb_expect { + -re ".* = true\r\n$gdb_prompt $" { + pass "print (int)&Bar::y == 2*sizeof(int)" + } + -re "There is no field named y.*$gdb_prompt $" { + setup_xfail "*-*-*" + fail "print (int)&Bar::y == 2*sizeof(int)" + } + -re ".*$gdb_prompt $" { fail "print (int)&Bar::y == 2*sizeof(int)" } + timeout { fail "print (int)&Bar::y == 2*sizeof(int) (timeout)" ; return } + } + + send_gdb "next\n" + setup_xfail "*-*-*" + gdb_expect { + -re "$decimal\[ \t\]+inheritance3 \[)(\]+;\r\n$gdb_prompt $" {} + -re ".*$gdb_prompt $" { fail "next to inheritance3" ; return } + } + clear_xfail "*-*-*" + + setup_xfail_format "DWARF 1" + gdb_test "print (int)pmi == sizeof(int)" ".* = false" "print (int)pmi == sizeof(int)" +} + +# +# Test static members. +# + +proc test_static_members {} { + global gdb_prompt + global hex + + send_gdb "print Foo::st\n" + gdb_expect { + -re ".* = 100\r\n$gdb_prompt $" { + pass "print Foo::st" + } + -re "There is no field named st.*$gdb_prompt $" { + setup_xfail "*-*-*" + fail "print Foo::st" + } + -re ".*$gdb_prompt $" { fail "print Foo::st" } + timeout { fail "print Foo::st (timeout)" ; return } + } + + send_gdb "set foo.st = 200\n" + gdb_expect { + -re ".*$gdb_prompt $" {} + } + + send_gdb "print bar.st\n" + gdb_expect { + -re ".* = 200\r\n$gdb_prompt $" { + pass "print bar.st" + } + -re "There is no member( or method|) named st.*$gdb_prompt $" { + setup_xfail "*-*-*" + fail "print bar.st" + } + -re ".*$gdb_prompt $" { fail "print bar.st" } + timeout { fail "print bar.st (timeout)" ; return } + } + + send_gdb "print &foo.st\n" + gdb_expect { + -re ".* = .int \[*)\]+ $hex\r\n$gdb_prompt $" { + pass "print &foo.st" + } + -re "There is no member( or method|) named st.*$gdb_prompt $" { + setup_xfail "*-*-*" + fail "print &foo.st" + } + -re ".*$gdb_prompt $" { fail "print &foo.st" } + timeout { fail "print &foo.st (timeout)" ; return } + } + + set got_bar_st 0 + send_gdb "print &Bar::st\n" + gdb_expect { + -re ".* = .int \[*)\]+ $hex\r\n$gdb_prompt $" { + pass "print &Bar::st" + set got_bar_st 1 + } + -re "There is no field named st.*$gdb_prompt $" { + setup_xfail "*-*-*" + fail "print &Bar::st" + } + -re ".*$gdb_prompt $" { fail "print &Bar::st" } + timeout { fail "print &Bar::st (timeout)" ; return } + } + + if $got_bar_st then { + gdb_test "print *\$" ".* = 200" "print *\$" + } + + gdb_test "set print static-members off" "" + gdb_test "print csi" \ + "{x = 10, y = 20}" \ + "print csi without static members" + gdb_test "print cnsi" \ + "{x = 30, y = 40}" \ + "print cnsi without static members" + + gdb_test "set print static-members on" "" + setup_xfail_format "DWARF 1" + gdb_test "print csi" \ + "{x = 10, y = 20, static null = {x = 0, y = 0, static null = <same as static member of an already seen type>}}" \ + "print csi with static members" + setup_xfail_format "DWARF 1" + gdb_test "print cnsi" \ + "{x = 30, y = 40, static null = {x = 0, y = 0, static null = <same as static member of an already seen type>, static yy = {z = 5, static xx = {x = 1, y = 2, static null = <same as static member of an already seen type>, static yy = <same as static member of an already seen type>}}}, static yy = <same as static member of an already seen type>}" \ + "print cnsi with static members" +} + +proc do_tests {} { + global prms_id + global bug_id + global subdir + global objdir + global srcdir + global binfile + global gdb_prompt + + set prms_id 0 + set bug_id 0 + + # Start with a fresh gdb. + + gdb_exit + gdb_start + gdb_reinitialize_dir $srcdir/$subdir + gdb_load $binfile + + send_gdb "set language c++\n" + gdb_expect -re "$gdb_prompt $" + send_gdb "set width 0\n" + gdb_expect -re "$gdb_prompt $" + + # Get the debug format for the compiled test case. + + if [ runto_main ] then { + get_debug_format + } + + test_ptype_class_objects + + if [ runto 'inheritance2(void)' ] then { + test_non_inherited_member_access + test_wrong_class_members + test_nonexistant_members + } + + if [istarget "mips-idt-*"] then { + # Restart because IDT/SIM runs out of file descriptors. + gdb_exit + gdb_start + gdb_reinitialize_dir $srcdir/$subdir + gdb_load $binfile + } + + if [ runto_main ] then { + test_pointers_to_class_members + test_static_members + } + + if [istarget "mips-idt-*"] then { + # Restart because IDT/SIM runs out of file descriptors. + gdb_exit + gdb_start + gdb_reinitialize_dir $srcdir/$subdir + gdb_load $binfile + } + + if [ runto marker_reg1 ] then { + + gdb_test "finish" "Run till exit from.*" "finish from marker_reg1" + + send_gdb "print v.method ()\n" + gdb_expect { + -re "= 82.*$gdb_prompt $" { + pass "calling method for small class" + } + -re "Address requested for identifier .v. which is in a register.*$gdb_prompt $" { + setup_xfail "*-*-*" 2972 + fail "calling method for small class" + } + -re ".*$gdb_prompt $" { fail "calling method for small class" } + timeout { fail "calling method for small class (timeout)" } + eof { fail "calling method for small class (eof)" } + } + } + +} + +do_tests + + +# Some additional tests for enums inside classes + + +# set a breakpoint and go there +send_gdb "break 498\n" +gdb_expect { + -re "Breakpoint \[0-9\] at.*$gdb_prompt $" { pass "set break 498" } + -re "$gdb_prompt $" { fail "set break 498" } + timeout { fail "(timeout) set break 498" } +} +send_gdb "continue\n" +gdb_expect { + -re "Continuing\\.\r\n\r\nBreakpoint \[0-9\]*, main....at ${srcdir}/${subdir}/${srcfile}:498\r\n498.*\r\n$gdb_prompt $" { pass "continue" } + -re "$gdb_prompt $" { fail "continue" } + timeout { fail "(timeout) continue" } +} + +# print the object +send_gdb "print obj_with_enum\n" +gdb_expect { + -re "\\$\[0-9\]* = \\{priv_enum = red, x = 0\\}.*$gdb_prompt $" { pass "print obj_with_enum (1)" } + -re "$gdb_prompt $" { fail "print obj_with_enum (1)" } + timeout { fail "(timeout) print obj_with_enum (1)" } +} + +send_gdb "next\n" +gdb_expect { + -re "$gdb_prompt $" { pass "next" } + timeout { fail "(timeout) next" } +} + +# print the object again +send_gdb "print obj_with_enum\n" +gdb_expect { + -re "\\$\[0-9\]* = \\{priv_enum = green, x = 0\\}.*$gdb_prompt $" { pass "print obj_with_enum (2)" } + -re "$gdb_prompt $" { fail "print obj_with_enum (2)" } + timeout { fail "(timeout) print obj_with_enum (2)" } +} + +# print out the enum member +send_gdb "print obj_with_enum.priv_enum\n" +gdb_expect { + -re "\\$\[0-9\]* = green.*$gdb_prompt $" { pass "print obj_with_enum.priv_enum" } + -re "$gdb_prompt $" { fail "print obj_with_enum.priv_enum" } + timeout { fail "(timeout) print obj_with_enum.priv_enum" } +} + +# ptype on the enum member +send_gdb "ptype obj_with_enum.priv_enum\n" +gdb_expect { + -re "type = enum ClassWithEnum::PrivEnum \\{red, green, blue, yellow = 42\\}.*$gdb_prompt $" { pass "ptype obj_with_enum.priv_enum" } + -re "$gdb_prompt $" { fail "ptype obj_with_enum.priv_enum" } + timeout { fail "(timeout) ptype obj_with_enum.priv_enum" } +} + +# ptype on the object +send_gdb "ptype obj_with_enum\n" +gdb_expect { + -re "type = class ClassWithEnum \\{\r\n\[ \t\]*public:\r\n\[ \t\]*enum ClassWithEnum::PrivEnum priv_enum;\r\n\[ \t\]*int x;\r\n\\}\r\n$gdb_prompt $" { pass "ptype obj_with_enum" } + -re "$gdb_prompt $" { fail "ptype obj_with_enum" } + timeout { fail "(timeout) ptype obj_with_enum" } +} + +send_gdb "print (ClassWithEnum::PrivEnum) 42\n" +gdb_expect { + -re "\\$\[0-9\]* = yellow.*$gdb_prompt $" { pass "print (ClassWithEnum::PrivEnum) 42" } + -re "$gdb_prompt $" { fail "print (ClassWithEnum::PrivEnum) 42" } + timeout { fail "(timeout) print (ClassWithEnum::PrivEnum) 42" } +} + + +send_gdb "maint demangle inheritance1__Fv\n" +gdb_expect { + -re "inheritance1\\(void\\).*$gdb_prompt $" { pass "demangle" } + -re ".*$gdb_prompt $" { fail "demangle" } + timeout { fail "(timeout) demangle" } +} + diff --git a/gdb/testsuite/gdb.hp/compiler.c b/gdb/testsuite/gdb.hp/compiler.c new file mode 100644 index 00000000000..8eb0d47dd19 --- /dev/null +++ b/gdb/testsuite/gdb.hp/compiler.c @@ -0,0 +1,31 @@ +/* Often the behavior of any particular test depends upon what compiler was + used to compile the test. As each test is compiled, this file is + preprocessed by the same compiler used to compile that specific test + (different tests might be compiled by different compilers, particularly + if compiled at different times), and used to generate a *.ci (compiler + info) file for that test. + + I.E., when callfuncs is compiled, a callfuncs.ci file will be generated, + which can then be sourced by callfuncs.exp to give callfuncs.exp access + to information about the compilation environment. + + TODO: It might be a good idea to add expect code that tests each + definition made with 'set" to see if one already exists, and if so + warn about conflicts if it is being set to something else. */ + +/* This needs to be kept in sync with whatis.c and gdb.exp(get_compiler_info). + If this ends up being hairy, we could use a common header file. */ + +#if defined (__STDC__) || defined (_AIX) +set signed_keyword_not_used 0 +#else +set signed_keyword_not_used 1 +#endif + +#if defined (__GNUC__) +set gcc_compiled __GNUC__ +#else +set gcc_compiled 0 +#endif + +return 0 diff --git a/gdb/testsuite/gdb.hp/compiler.cc b/gdb/testsuite/gdb.hp/compiler.cc new file mode 100644 index 00000000000..aa35c7510ff --- /dev/null +++ b/gdb/testsuite/gdb.hp/compiler.cc @@ -0,0 +1,34 @@ +/* Often the behavior of any particular test depends upon what compiler was + used to compile the test. As each test is compiled, this file is + preprocessed by the same compiler used to compile that specific test + (different tests might be compiled by different compilers, particularly + if compiled at different times), and used to generate a *.ci (compiler + info) file for that test. + + I.E., when callfuncs is compiled, a callfuncs.ci file will be generated, + which can then be sourced by callfuncs.exp to give callfuncs.exp access + to information about the compilation environment. + + TODO: It might be a good idea to add expect code that tests each + definition made with 'set" to see if one already exists, and if so + warn about conflicts if it is being set to something else. */ + +#if defined(__GNUC__) && __GNUC__ >= 2 && __GNUC_MINOR__ >= 6 +set supports_template_debugging 1 +#else +set supports_template_debugging 0 +#endif + +#if defined(__cplusplus) +set supports_template_debugging 1 +#else +set supports_template_debugging 0 +#endif + +#if defined (__GNUC__) +set gcc_compiled __GNUC__ +#else +set gcc_compiled 0 +#endif + +return 0 diff --git a/gdb/testsuite/gdb.hp/ctti-add.cc b/gdb/testsuite/gdb.hp/ctti-add.cc new file mode 100644 index 00000000000..1f50fae24c1 --- /dev/null +++ b/gdb/testsuite/gdb.hp/ctti-add.cc @@ -0,0 +1,29 @@ +template<class T> T add(T v1, T v2) +{ + T v3; + v3 = v1; + v3 += v2; + return v3; + } + +int main() +{ + char c; + int i; + float f; + extern void add1(); + extern void subr2(); + extern void subr3(); + + c = 'a'; + i = 2; + f = 4.5; + + c = add(c, c); + i = add(i, i); + f = add(f, f); + + add1(); + subr2(); + subr3(); +} diff --git a/gdb/testsuite/gdb.hp/ctti-add1.cc b/gdb/testsuite/gdb.hp/ctti-add1.cc new file mode 100644 index 00000000000..7113ecea421 --- /dev/null +++ b/gdb/testsuite/gdb.hp/ctti-add1.cc @@ -0,0 +1,16 @@ +template<class T> T add(T v1, T v2); + +void add1() +{ + char c; + int i; + float f; + + c = 'b'; + i = 3; + f = 6.5; + + c = add(c, c); + i = add(i, i); + f = add(f, f); +} diff --git a/gdb/testsuite/gdb.hp/ctti-add2.cc b/gdb/testsuite/gdb.hp/ctti-add2.cc new file mode 100644 index 00000000000..d0d9891fb2f --- /dev/null +++ b/gdb/testsuite/gdb.hp/ctti-add2.cc @@ -0,0 +1,22 @@ +template<class T> T add2(T v1, T v2) +{ + T v3; + v3 = v1; + v3 += v2; + return v3; +} + +void subr2() +{ + char c; + int i; + float f; + + c = 'b'; + i = 3; + f = 6.5; + + c = add2(c, c); + i = add2(i, i); + f = add2(f, f); +} diff --git a/gdb/testsuite/gdb.hp/ctti-add3.cc b/gdb/testsuite/gdb.hp/ctti-add3.cc new file mode 100644 index 00000000000..7ba1b019f16 --- /dev/null +++ b/gdb/testsuite/gdb.hp/ctti-add3.cc @@ -0,0 +1,33 @@ +template<class T> T add3(T v1, T v2) +{ + T v3; + v3 = v1; + v3 += v2; + return v3; +} + +template<class T> T add4(T v1, T v2) +{ + T v3; + v3 = v1; + v3 += v2; + return v3; +} + +void subr3() +{ + char c; + int i; + float f; + + c = 'b'; + i = 3; + f = 6.5; + + c = add3(c, c); + i = add3(i, i); + f = add3(f, f); + c = add4(c, c); + i = add4(i, i); + f = add4(f, f); +} diff --git a/gdb/testsuite/gdb.hp/ctti.exp b/gdb/testsuite/gdb.hp/ctti.exp new file mode 100644 index 00000000000..e53210dda0b --- /dev/null +++ b/gdb/testsuite/gdb.hp/ctti.exp @@ -0,0 +1,269 @@ +# Copyright (C) 1998 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 2 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +# Please email any bugs, comments, and/or additions to this file to: +# bug-gdb@prep.ai.mit.edu + + +# This file is part of the gdb testsuite +# file written by Elena Zannoni (ezannoni@cygnus.com) +# +# source files ctti-add.cc, ctti-add1.cc, ctti-add2.cc, ctti-add3.cc +# + + +if $tracelevel then { + strace $tracelevel +} + + +# Check to see if we have an executable to test. If not, then either we +# haven't tried to compile one, or the compilation failed for some reason. +# In either case, just notify the user and skip the tests in this file. + +set testfile "ctti-add" +set srcfile ${testfile}.cc +set srcfile1 ${testfile}1.cc +set srcfile2 ${testfile}2.cc +set srcfile3 ${testfile}3.cc +set binfile ${objdir}/${subdir}/${testfile} + +if [get_compiler_info ${binfile} "c++"] { + return -1; +} + + +if {[skip_hp_tests $gcc_compiled]} then { continue } + +#if { [gdb_compile "${srcdir}/${subdir}/${srcfile} ${srcdir}/${subdir}/${srcfile1} ${srcdir}/${subdir}/${srcfile2} ${srcdir}/${subdir}/${srcfile3}" "${binfile}" executable {debug c++}] != "" } { +# gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail." +#} + +set cmdline "$CXX ${srcdir}/${subdir}/${srcfile} ${srcdir}/${subdir}/${srcfile1} ${srcdir}/${subdir}/${srcfile2} ${srcdir}/${subdir}/${srcfile3} -g -o ${binfile}" + +remote_exec build $cmdline + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + + + +if ![runto_main] then { + perror "couldn't run to breakpoint" + continue +} + + +send_gdb "n\n" +gdb_expect { + -re "$decimal.*i = 2;.*$gdb_prompt $" { + pass "next " + } + -re ".*$gdb_prompt $" { fail "next " } + timeout { fail "next " } + } + + +send_gdb "n\n" +gdb_expect { + -re "$decimal.*f = 4.5;.*$gdb_prompt $" { + pass "next " + } + -re ".*$gdb_prompt $" { fail "next " } + timeout { fail "next " } + } + +send_gdb "n\n" +gdb_expect { + -re "$decimal.*c = add\\(c, c\\);.*$gdb_prompt $" { + pass "next " + } + -re ".*$gdb_prompt $" { fail "next " } + timeout { fail "next " } + } + +send_gdb "n\n" +gdb_expect { + -re "$decimal.*i = add\\(i, i\\);.*$gdb_prompt $" { + pass "next " + } + -re ".*$gdb_prompt $" { fail "next " } + timeout { fail "next " } + } + +send_gdb "n\n" +gdb_expect { + -re "$decimal.*f = add\\(f, f\\);.*$gdb_prompt $" { + pass "next " + } + -re ".*$gdb_prompt $" { fail "next " } + timeout { fail "next " } + } + +send_gdb "n\n" +gdb_expect { + -re "$decimal.*add1\\(\\);.*$gdb_prompt $" { + pass "next " + } + -re ".*$gdb_prompt $" { fail "next " } + timeout { fail "next " } + } + +send_gdb "print c\n" +gdb_expect { + -re ".$decimal = -62.*\r\n$gdb_prompt $" { + pass "print value of c" + } + -re ".*$gdb_prompt $" { fail "print value of c" } + timeout { fail "(timeout) print value of c" } + } + + +send_gdb "print f\n" +gdb_expect { + -re ".$decimal = 9\r\n$gdb_prompt $" { + pass "print value of f" + } + -re ".*$gdb_prompt $" { fail "print value of f" } + timeout { fail "(timeout) print value of f" } + } + + +send_gdb "print i\n" +gdb_expect { + -re ".$decimal = 4\r\n$gdb_prompt $" { + pass "print value of i" + } + -re ".*$gdb_prompt $" { fail "print value of i" } + timeout { fail "(timeout) print value of i" } + } + + + +send_gdb "print add<int>(2,2)\n" +gdb_expect { + -re ".$decimal = 4\r\n$gdb_prompt $" { + pass "print value of add<int>(2,2)" + } + -re ".*$gdb_prompt $" { fail "print value of add<int>(2,2)" } + timeout { fail "(timeout) print value of add<int>(2,2)" } + } + +send_gdb "print add<float>(2.3,2.3)\n" +gdb_expect { + -re ".$decimal = 4\\.5\[0-9\]+\r\n$gdb_prompt $" { + pass "print value of add<float>(2.3,2.3)" + } + -re ".*$gdb_prompt $" { fail "print value of add<float>(2.3,2.3)" } + timeout { fail "(timeout) print value of add<float>(2.3,2.3)" } + } + +send_gdb "print add<char>('A','A')\n" +gdb_expect { + -re ".$decimal = -126.*202.\r\n$gdb_prompt $" { + pass "print value of add<char>('A','A')" + } + -re ".*$gdb_prompt $" { fail "print value of add<char>('A','A')" } + timeout { fail "(timeout) print value of add<char>('A','A')" } + } + + +send_gdb "print add2<int>(2,2)\n" +gdb_expect { + -re ".$decimal = 4\r\n$gdb_prompt $" { + pass "print value of add2<int>(2,2)" + } + -re ".*$gdb_prompt $" { fail "print value of add2<int>(2,2)" } + timeout { fail "(timeout) print value of add2<int>(2,2)" } + } + +send_gdb "print add2<float>(2.3,2.3)\n" +gdb_expect { + -re ".$decimal = 4\\.5\[0-9\]+\r\n$gdb_prompt $" { + pass "print value of add2<float>(2.3,2.3)" + } + -re ".*$gdb_prompt $" { fail "print value of add2<float>(2.3,2.3)" } + timeout { fail "(timeout) print value of add2<float>(2.3,2.3)" } + } + +send_gdb "print add2<char>('A','A')\n" +gdb_expect { + -re ".$decimal = -126.*202.\r\n$gdb_prompt $" { + pass "print value of add2<char>('A','A')" + } + -re ".*$gdb_prompt $" { fail "print value of add2<char>('A','A')" } + timeout { fail "(timeout) print value of add2<char>('A','A')" } + } + +send_gdb "print add3<int>(2,2)\n" +gdb_expect { + -re ".$decimal = 4\r\n$gdb_prompt $" { + pass "print value of add3<int>(2,2)" + } + -re ".*$gdb_prompt $" { fail "print value of add3<int>(2,2)" } + timeout { fail "(timeout) print value of add3<int>(2,2)" } + } + +send_gdb "print add3<float>(2.3,2.3)\n" +gdb_expect { + -re ".$decimal = 4\\.5\[0-9\]+\r\n$gdb_prompt $" { + pass "print value of add3<float>(2.3,2.3)" + } + -re ".*$gdb_prompt $" { fail "print value of add3<float>(2.3,2.3)" } + timeout { fail "(timeout) print value of add3<float>(2.3,2.3)" } + } + +send_gdb "print add3<char>('A','A')\n" +gdb_expect { + -re ".$decimal = -126.*202.\r\n$gdb_prompt $" { + pass "print value of add3<char>('A','A')" + } + -re ".*$gdb_prompt $" { fail "print value of add3<char>('A','A')" } + timeout { fail "(timeout) print value of add3<char>('A','A')" } + } + +send_gdb "print add4<int>(2,2)\n" +gdb_expect { + -re ".$decimal = 4\r\n$gdb_prompt $" { + pass "print value of add4<int>(2,2)" + } + -re ".*$gdb_prompt $" { fail "print value of add4<int>(2,2)" } + timeout { fail "(timeout) print value of add4<int>(2,2)" } + } + +send_gdb "print add4<float>(2.3,2.3)\n" +gdb_expect { + -re ".$decimal = 4\\.5\[0-9\]+\r\n$gdb_prompt $" { + pass "print value of add4<float>(2.3,2.3)" + } + -re ".*$gdb_prompt $" { fail "print value of add4<float>(2.3,2.3)" } + timeout { fail "(timeout) print value of add4<float>(2.3,2.3)" } + } + +send_gdb "print add4<char>('A','A')\n" +gdb_expect { + -re ".$decimal = -126.*202.\r\n$gdb_prompt $" { + pass "print value of add4<char>('A','A')" + } + -re ".*$gdb_prompt $" { fail "print value of add4<char>('A','A')" } + timeout { fail "(timeout) print value of add4<char>('A','A')" } + } + + +gdb_exit +return 0 diff --git a/gdb/testsuite/gdb.hp/dbx.exp b/gdb/testsuite/gdb.hp/dbx.exp new file mode 100644 index 00000000000..66f24e90a59 --- /dev/null +++ b/gdb/testsuite/gdb.hp/dbx.exp @@ -0,0 +1,222 @@ +# Copyright (C) 1998 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 2 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +# Please email any bugs, comments, and/or additions to this file to: +# bug-gdb@prep.ai.mit.edu + + +if $tracelevel then { + strace $tracelevel +} + + +set testfile1 "average" +set testfile2 "sum" +set testfile "dbx-test" +set binfile1 ${objdir}/${subdir}/${testfile1} +set binfile2 ${objdir}/${subdir}/${testfile2} +set binfile ${objdir}/${subdir}/${testfile} + + + +if { [gdb_compile "${srcdir}/${subdir}/average.c" "${binfile1}.o" object {debug}] != "" } { + gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail." +} + +if { [gdb_compile "${srcdir}/${subdir}/sum.c" "${binfile2}.o" object {debug}] != "" } { + gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail." +} + +if { [gdb_compile "${binfile1}.o ${binfile2}.o" ${binfile} executable {debug}] != "" } { + gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail." +} + +if [get_compiler_info ${binfile}] { + return -1; +} +if {[skip_hp_tests $gcc_compiled]} then { continue } + +proc dbx_reinitialize_dir { subdir } { + global gdb_prompt + + send_gdb "use\n" + gdb_expect { + -re "Reinitialize source path to empty.*y or n. " { + send_gdb "y\n" + gdb_expect { + -re "Source directories searched.*$gdb_prompt $" { + send_gdb "use $subdir\n" + gdb_expect { + -re "Source directories searched.*$gdb_prompt $" { + verbose "Dir set to $subdir" + } + -re ".*$gdb_prompt $" { + perror "Dir \"$subdir\" failed." + } + } + } + -re ".*$gdb_prompt $" { + perror "Dir \"$subdir\" failed." + } + } + } + -re ".*$gdb_prompt $" { + perror "Dir \"$subdir\" failed." + } + } +} + +# In "testsuite/config/unix-gdb.exp", the routine "gdb_load" +# is defined as "gdb_file_cmd". The binding of "gdb_file_cmd" +# is done at invocation time. Before this file is processed, +# it binds to the definition in "testsuite/lib/gdb.exp"; after +# this file is processed, it binds to this definition. +# TCL lets us overrides a previous routine definition without a +# warning (isn't that special?). +# +# This means that tests before use "file" to load a target, and +# tests afterwards use the pair "symbol-file" "exec-file". +# +# I'm leaving it as it is for now because at the moment it +# is the only test we have of the use of the combination of +# "symbol-file" and "exec-file" to load a debugging target (the +# other definition uses "file". +# +# Symbol-file and exec-file should be tested explicitly, not +# as a side effect of running a particular test (in this case, +# "testsuite/gdb.compat/dbx.exp"). +# +# +proc gdb_file_cmd {arg } { + global verbose + global loadpath + global loadfile + global GDB + global gdb_prompt + global spawn_id + upvar timeout timeout + + send_gdb "symbol-file $arg\n" + gdb_expect { + -re "Reading symbols from.*done.*$gdb_prompt $" { + verbose "\t\tLoaded $arg into the $GDB" + send_gdb "exec-file $arg\n" + return 0 + } + -re "has no symbol-table.*$gdb_prompt $" { + perror "$arg wasn't compiled with \"-g\"" + return -1 + } + -re "A program is being debugged already.*Kill it.*y or n. $" { + send_gdb "y\n" + verbose "\t\tKilling previous program being debugged" + exp_continue + } + -re "Load new symbol table from \".*\".*y or n. $" { + send_gdb "y\n" + gdb_expect { + -re "Reading symbols from.*done.*$gdb_prompt $" { + verbose "\t\tLoaded $arg with new symbol table into $GDB" + return 0 + } + timeout { + perror "(timeout) Couldn't load $arg, other program already loaded." + return -1 + } + } + } + -re ".*No such file or directory.*$gdb_prompt $" { + perror "($arg) No such file or directory\n" + return -1 + } + -re "$gdb_prompt $" { + perror "couldn't load $arg into $GDB." + return -1 + } + timeout { + perror "couldn't load $arg into $GDB (timed out)." + return -1 + } + eof { + # This is an attempt to detect a core dump, but seems not to + # work. Perhaps we need to match .* followed by eof, in which + # expect does not seem to have a way to do that. + perror "couldn't load $arg into $GDB (end of file)." + return -1 + } + } +} + +# +#test_breakpoints +# +proc test_breakpoints { } { + gdb_test "stop in main" "Breakpoint.*at.*: file.*average\.c, line 31\." + gdb_test "status" "Num.*Type.*Disp.*Enb.*Address.*What\r\n1\[ \r\]+breakpoint\[ \r\]+keep y.*in main at.*average\.c:31.*" + gdb_test "stop at 36" "Breakpoint.*at.*: file.*average\.c, line 36.*" + gdb_test "stop in 36" "Usage: stop in <function . address>" + gdb_test "stop at main" "Usage: stop at <line>" +} + +# +#test_assign +# +proc test_assign { } { + gdb_test "run" "" + gdb_test "assign first=1" "" + gdb_test "print first" ".1 = 1" +} + +# +#test_whereis +# +proc test_whereis { } { + gdb_test "whereis my_list" "All variables matching regular expression \"my_list\":\r\n\r\nFile.*average\.c:\r\nstatic int my_list\\\[10\\\];" +} + +# +#test_func +# +proc test_func { } { + gdb_test "cont" "" + gdb_test "step" "" + gdb_test "func sum" "'sum' not within current stack frame\." + gdb_test "stop in sum" "Breakpoint.*at.*: file.*sum\.c, line 11\." + gdb_test "cont" + gdb_test "func print_average" ".*in print_average.*\\(list=.*, low=0, high=6\\).*at.*average\.c:17\r\n17\[ \t\]+total = sum\\(list, low, high\\);" +} + +# Start with a fresh gdb. + +gdb_exit +global GDBFLAGS +set saved_gdbflags $GDBFLAGS + +set GDBFLAGS "$GDBFLAGS --dbx" +gdb_start +dbx_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} +send_gdb "set width 0\n" +gdb_expect -re "$gdb_prompt $" +test_breakpoints +test_assign +test_whereis +gdb_test "file average.c:1" "1\[ \t\]+/. This is a sample program.*" +test_func + +gdb_exit +set GDBFLAGS $saved_gdbflags +return 0 diff --git a/gdb/testsuite/gdb.hp/exception.cc b/gdb/testsuite/gdb.hp/exception.cc new file mode 100644 index 00000000000..27459329a8b --- /dev/null +++ b/gdb/testsuite/gdb.hp/exception.cc @@ -0,0 +1,48 @@ +// Test file for exception handling support. + +#include <iostream.h> + +int foo (int i) +{ + if (i < 32) + throw (int) 13; + else + return i * 2; +} + +extern "C" int bar (int k, unsigned long eharg, int flag); + +int bar (int k, unsigned long eharg, int flag) +{ + cout << "k is " << k << " eharg is " << eharg << " flag is " << flag << endl; + return 1; +} + +int main() +{ + int j; + + try { + j = foo (20); + } + catch (int x) { + cout << "Got an except " << x << endl; + } + + try { + try { + j = foo (20); + } + catch (int x) { + cout << "Got an except " << x << endl; + throw; + } + } + catch (int y) { + cout << "Got an except (rethrown) " << y << endl; + } + + // Not caught + foo (20); + +} diff --git a/gdb/testsuite/gdb.hp/exception.exp b/gdb/testsuite/gdb.hp/exception.exp new file mode 100644 index 00000000000..4cafbdcd001 --- /dev/null +++ b/gdb/testsuite/gdb.hp/exception.exp @@ -0,0 +1,408 @@ +# Copyright (C) 1997, 1998 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 2 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +# Please email any bugs, comments, and/or additions to this file to: +# bug-gdb@prep.ai.mit.edu + +# +# tests for exception-handling support +# Written by Satish Pai <pai@apollo.hp.com> 1997-07-23 + +# This file is part of the gdb testsuite + +# Note: These tests are geared to the HP aCC compiler, +# which has an idiosyncratic way of emitting debug info +# for exceptions -- it uses a callback mechanism, which +# is different from the way g++ records exception info +# for debugging + +# The tests are in two parts; the first part deals with +# statically linked (archive-bound) executables, and the +# second part repeats those tests with dynamically linked +# (shared bound) executables. (In the latter case we use +# a different mechanism to get the address of the notification +# hook in the C++ support library.) The tests themselves are +# the same in both parts. +# +# IMPORTANT: +# --------- +# IF YOU CHANGE A TEST IN ONE PART MAKE SURE YOU CHANGE IT +# -------------------------------------------------------- +# IN THE OTHER PART TOO! +# ---------------------- + + + +if $tracelevel then { + strace $tracelevel + } + + +# +# test running programs +# + +# Part I : Archive-bound executables +# ---------------------------------- + +set testfile "exception" +set srcfile ${testfile}.cc +set binfile ${objdir}/${subdir}/${testfile} + +if [get_compiler_info ${binfile} "c++"] { + return -1; +} + + +if {[skip_hp_tests $gcc_compiled]} then { continue } + +set cmdline "$CXX ${srcdir}/${subdir}/${srcfile} +A -Wl,-a,archive -g -o ${binfile}" + +remote_exec build $cmdline + +# Start with a fresh gdb + +set prms_id 0 +set bug_id 0 + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +if ![runto_main] then { + perror "couldn't run to breakpoint" + continue +} + +# Set a catch catchpoint + +send_gdb "catch catch\n" +gdb_expect { + -re "Catchpoint \[0-9\]* \\(catch\\)\r\n$gdb_prompt $" { + pass "catch catch (static executable)" + } + -re ".*$gdb_prompt $" { fail "catch catch (static executable)" } + timeout { fail "(timeout) catch catch (static executable)" } +} + +# Set a throw catchpoint + +send_gdb "catch throw\n" +gdb_expect { + -re "Catchpoint \[0-9\]* \\(throw\\)\r\n$gdb_prompt $" { + pass "catch throw (static executable)" + } + -re ".*$gdb_prompt $" { fail "catch throw (static executable)" } + timeout { fail "(timeout) catch throw (static executable)" } +} + +# The catchpoints should be listed in the list of breakpoints. + +send_gdb "info break\n" +gdb_expect { + -re ".*\[0-9\]*\[ \]*catch catch\[ \]*keep y\[ \]*exception catch\[ \]*\r\n\[0-9\]*\[ \]*catch throw\[ \]*keep y\[ \]*exception throw\[ \]*\r\n$gdb_prompt $" { + pass "info break with catchpoints (static executable)" + } + -re ".*$gdb_prompt $" { fail "info break (static executable)" } + timeout { fail "(timeout) info break (static executable)" } +} + +# Info catch currently does not work with HP aCC. No easy way to +# list the active handlers on the stack. + +send_gdb "info catch\n" +gdb_expect { + -re "Info catch not supported with this target/compiler combination.\r\n$gdb_prompt $" { + pass "info catch (static executable)" + } + -re ".*$gdb_prompt $" { fail "info catch (static executable)" } + timeout { fail "(timeout) info catch (static executable)" } +} + +# Get the first exception thrown + +send_gdb "continue\n" +gdb_expect { + -re "Continuing.*Catchpoint \[0-9\]* \\(exception thrown\\), throw location.*exception\\.cc:8, catch location .*exception\\.cc:28\r\n.*$gdb_prompt $" { + pass "caught a throw (static executable)" + } + -re ".*$gdb_prompt $" { fail "didn't catch a throw (static executable)" } + timeout { fail "(timeout) after continue -- didn't catch a throw? (static executable)" } +} + +send_gdb "backtrace\n" +gdb_expect { + -re "#0\[ \]*__d_eh_break.*\r\n#1\[ \]*$hex in __d_eh_notify_callback \\(eh_type=__EH_NOTIFY_THROW.*\r\n#2\[ \]*$hex in __eh_notify_throw.*\r\n#3\[ \]*$hex in foo \\(i=20\\) at .*exception\\.cc:8\r\n#4\[ \]*$hex in main.* at .*exception\\.cc:26\r\n$gdb_prompt $" { + pass "backtrace after throw (static executable)" + } + -re ".*$gdb_prompt $" { fail "backtrace after throw (static executable)" } + timeout { fail "(timeout) backtrace after throw (static executable)" } +} + +# Now intercept it when it is caught. + +send_gdb "continue\n" +gdb_expect { + -re "Continuing.*Catchpoint \[0-9\]* \\(exception caught\\), throw location.*exception\\.cc:8, catch location .*exception\\.cc:28\r\n.*$gdb_prompt $" { + pass "caught a catch (static executable)" + } + -re ".*$gdb_prompt $" { fail "didn't catch a catch (static executable)" } + timeout { fail "(timeout) after continue -- didn't catch a catch? (static executable)" } +} + +send_gdb "backtrace\n" +gdb_expect { + -re "#0\[ \]*__d_eh_break.*\r\n#1\[ \]*$hex in __d_eh_notify_callback \\(eh_type=__EH_NOTIFY_CATCH.*\r\n.*\r\n#3\[ \]*$hex in __throw__.*\r\n#4\[ \]*$hex in foo \\(i=20\\) at .*exception.cc:8\r\n#5\[ \]*$hex in main.* at .*exception.cc:26\r\n$gdb_prompt $" { + pass "backtrace after catch (static executable)" + } + -re ".*$gdb_prompt $" { fail "backtrace after catch (static executable)" } + timeout { fail "(timeout) backtrace after catch (static executable)" } +} + +send_gdb "continue\n" +gdb_expect { + -re "Continuing\\.\r\nGot.*\r\nCatchpoint \[0-9\]* \\(exception thrown\\), throw location.*exception\\.cc:8, catch location .*exception\\.cc:36\r\n.*$gdb_prompt $" { + pass "caught a throw (2) (static executable)" + } + -re ".*$gdb_prompt $" { fail "didn't catch a throw (2) (static executable)" } + timeout { fail "(timeout) after continue -- didn't catch a throw (2)? (static executable)" } +} + +send_gdb "continue\n" +gdb_expect { + -re "Continuing.*Catchpoint \[0-9\]* \\(exception caught\\), throw location.*exception\\.cc:8, catch location .*exception\\.cc:36\r\n.*$gdb_prompt $" { + pass "caught a catch (2) (static executable)" + } + -re ".*$gdb_prompt $" { fail "didn't catch a catch (2) (static executable)" } + timeout { fail "(timeout) after continue -- didn't catch a catch (2)? (static executable)" } +} + +# Now the exception will be rethrown. + +send_gdb "continue\n" +gdb_expect { + -re "Continuing\\.\r\nGot.*\r\nCatchpoint \[0-9\]* \\(exception thrown\\), throw location.*exception\\.cc:38, catch location .*exception\\.cc:41\r\n.*$gdb_prompt $" { + pass "caught a rethrow (static executable)" + } + -re ".*$gdb_prompt $" { fail "didn't catch a rethrow (static executable)" } + timeout { fail "(timeout) after continue -- didn't catch a rethrow? (static executable)" } +} + +send_gdb "continue\n" +gdb_expect { + -re "Continuing.*Catchpoint \[0-9\]* \\(exception caught\\), throw location.*exception\\.cc:38, catch location .*exception\\.cc:41\r\n.*$gdb_prompt $" { + pass "caught a catch (3) (static executable)" + } + -re ".*$gdb_prompt $" { fail "didn't catch a catch (3) (static executable)" } + timeout { fail "(timeout) after continue -- didn't catch a catch (3)? (static executable)" } +} + +send_gdb "backtrace\n" +gdb_expect { + -re "#0\[ \]*__d_eh_break.*\r\n#1\[ \]*$hex in __d_eh_notify_callback \\(eh_type=__EH_NOTIFY_CATCH.*\r\n.*\r\n#3\[ \]*$hex in __rethrow.*\r\n#4\[ \]*$hex in main.* at .*exception\\.cc:38\r\n#5\[ \]*$hex in foo \\(i=20\\) at .*exception.cc:8\r\n#6\[ \]*$hex in main.* at .*exception.cc:34\r\n$gdb_prompt $" { + pass "backtrace after catch (3) (static executable)" + } + -re ".*$gdb_prompt $" { fail "backtrace after catch (3) (static executable)" } + timeout { fail "(timeout) backtrace after catch (3) (static executable)" } +} + +# Now the exception will be thrown, but not catch-able anywhere. + +send_gdb "continue\n" +gdb_expect { + -re "Continuing\\.\r\nGot.*\r\nCatchpoint \[0-9\]* \\(exception thrown\\), throw location.*exception\\.cc:8, catch location unknown\r\n.*$gdb_prompt $" { + pass "caught an uncatchable throw (static executable)" + } + -re ".*$gdb_prompt $" { fail "didn't catch an uncatchable throw (static executable)" } + timeout { fail "(timeout) after continue -- didn't catch an uncatchable throw? (static executable)" } +} + +# Part II : Shared-bound executables +# ---------------------------------- + +# Start with a fresh gdb +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir + +set prms_id 0 +set bug_id 0 + +set testfile "exception" +set srcfile ${testfile}.cc +set binfile ${objdir}/${subdir}/${testfile} + +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } { + gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will a +utomatically fail." +} + + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + + +if ![runto_main] then { + perror "couldn't run to breakpoint" + continue +} + +# Set a catch catchpoint + +send_gdb "catch catch\n" +gdb_expect { + -re "Catchpoint \[0-9\]* \\(catch\\)\r\n$gdb_prompt $" { + pass "catch catch (dynamic executable)" + } + -re ".*$gdb_prompt $" { fail "catch catch (dynamic executable)" } + timeout { fail "(timeout) catch catch (dynamic executable)" } +} + +# Set a throw catchpoint + +send_gdb "catch throw\n" +gdb_expect { + -re "Catchpoint \[0-9\]* \\(throw\\)\r\n$gdb_prompt $" { + pass "catch throw (dynamic executable)" + } + -re ".*$gdb_prompt $" { fail "catch throw (dynamic executable)" } + timeout { fail "(timeout) catch throw (dynamic executable)" } +} + +# The catchpoints should be listed in the list of breakpoints. + +send_gdb "info break\n" +gdb_expect { + -re ".*\[0-9\]*\[ \]*catch catch\[ \]*keep y\[ \]*exception catch\[ \]*\r\n\[0-9\]*\[ \]*catch throw\[ \]*keep y\[ \]*exception throw\[ \]*\r\n$gdb_prompt $" { + pass "info break with catchpoints (dynamic executable)" + } + -re ".*$gdb_prompt $" { fail "info break (dynamic executable)" } + timeout { fail "(timeout) info break (dynamic executable)" } +} + +# Info catch currently does not work with HP aCC. No easy way to +# list the active handlers on the stack. + +send_gdb "info catch\n" +gdb_expect { + -re "Info catch not supported with this target/compiler combination.\r\n$gdb_prompt $" { + pass "info catch (dynamic executable)" + } + -re ".*$gdb_prompt $" { fail "info catch (dynamic executable)" } + timeout { fail "(timeout) info catch (dynamic executable)" } +} + +# Get the first exception thrown + +send_gdb "continue\n" +gdb_expect { + -re "Continuing.*Catchpoint \[0-9\]* \\(exception thrown\\), throw location.*exception\\.cc:8, catch location .*exception\\.cc:28\r\n.*$gdb_prompt $" { + pass "caught a throw (dynamic executable)" + } + -re ".*$gdb_prompt $" { fail "didn't catch a throw (dynamic executable)" } + timeout { fail "(timeout) after continue -- didn't catch a throw? (dynamic executable)" } +} + +send_gdb "backtrace\n" +gdb_expect { + -re "#0\[ \]*__d_eh_break.*\r\n#1\[ \]*$hex in __d_eh_notify_callback \\(eh_type=__EH_NOTIFY_THROW.*\r\n#2\[ \]*$hex in __eh_notify_throw.*\r\n#3\[ \]*$hex in foo \\(i=20\\) at .*exception\\.cc:8\r\n#4\[ \]*$hex in main.* at .*exception\\.cc:26\r\n$gdb_prompt $" { + pass "backtrace after throw (dynamic executable)" + } + -re ".*$gdb_prompt $" { fail "backtrace after throw (dynamic executable)" } + timeout { fail "(timeout) backtrace after throw (dynamic executable)" } +} + +# Now intercept it when it is caught. + +send_gdb "continue\n" +gdb_expect { + -re "Continuing.*Catchpoint \[0-9\]* \\(exception caught\\), throw location.*exception\\.cc:8, catch location .*exception\\.cc:28\r\n.*$gdb_prompt $" { + pass "caught a catch (dynamic executable)" + } + -re ".*$gdb_prompt $" { fail "didn't catch a catch (dynamic executable)" } + timeout { fail "(timeout) after continue -- didn't catch a catch? (dynamic executable)" } +} + +send_gdb "backtrace\n" +gdb_expect { + -re "#0\[ \]*__d_eh_break.*\r\n#1\[ \]*$hex in __d_eh_notify_callback \\(eh_type=__EH_NOTIFY_CATCH.*\r\n.*\r\n#3\[ \]*$hex in __throw__.*\r\n#4\[ \]*$hex in foo \\(i=20\\) at .*exception.cc:8\r\n#5\[ \]*$hex in main.* at .*exception.cc:26\r\n$gdb_prompt $" { + pass "backtrace after catch (dynamic executable)" + } + -re ".*$gdb_prompt $" { fail "backtrace after catch (dynamic executable)" } + timeout { fail "(timeout) backtrace after catch (dynamic executable)" } +} + +send_gdb "continue\n" +gdb_expect { + -re "Continuing\\.\r\nGot.*\r\nCatchpoint \[0-9\]* \\(exception thrown\\), throw location.*exception\\.cc:8, catch location .*exception\\.cc:36\r\n.*$gdb_prompt $" { + pass "caught a throw (2) (dynamic executable)" + } + -re ".*$gdb_prompt $" { fail "didn't catch a throw (2) (dynamic executable)" } + timeout { fail "(timeout) after continue -- didn't catch a throw (2)? (dynamic executable)" } +} + +send_gdb "continue\n" +gdb_expect { + -re "Continuing.*Catchpoint \[0-9\]* \\(exception caught\\), throw location.*exception\\.cc:8, catch location .*exception\\.cc:36\r\n.*$gdb_prompt $" { + pass "caught a catch (2) (dynamic executable)" + } + -re ".*$gdb_prompt $" { fail "didn't catch a catch (2) (dynamic executable)" } + timeout { fail "(timeout) after continue -- didn't catch a catch (2)? (dynamic executable)" } +} + +# Now the exception will be rethrown. + +send_gdb "continue\n" +gdb_expect { + -re "Continuing\\.\r\nGot.*\r\nCatchpoint \[0-9\]* \\(exception thrown\\), throw location.*exception\\.cc:38, catch location .*exception\\.cc:41\r\n.*$gdb_prompt $" { + pass "caught a rethrow (dynamic executable)" + } + -re ".*$gdb_prompt $" { fail "didn't catch a rethrow (dynamic executable)" } + timeout { fail "(timeout) after continue -- didn't catch a rethrow? (dynamic executable)" } +} + +send_gdb "continue\n" +gdb_expect { + -re "Continuing.*Catchpoint \[0-9\]* \\(exception caught\\), throw location.*exception\\.cc:38, catch location .*exception\\.cc:41\r\n.*$gdb_prompt $" { + pass "caught a catch (3) (dynamic executable)" + } + -re ".*$gdb_prompt $" { fail "didn't catch a catch (3) (dynamic executable)" } + timeout { fail "(timeout) after continue -- didn't catch a catch (3)? (dynamic executable)" } +} + +send_gdb "backtrace\n" +gdb_expect { + -re "#0\[ \]*__d_eh_break.*\r\n#1\[ \]*$hex in __d_eh_notify_callback \\(eh_type=__EH_NOTIFY_CATCH.*\r\n.*\r\n#3\[ \]*$hex in __rethrow.*\r\n#4\[ \]*$hex in main.* at .*exception\\.cc:38\r\n#5\[ \]*$hex in foo \\(i=20\\) at .*exception.cc:8\r\n#6\[ \]*$hex in main.* at .*exception.cc:34\r\n$gdb_prompt $" { + pass "backtrace after catch (3) (dynamic executable)" + } + -re ".*$gdb_prompt $" { fail "backtrace after catch (3) (dynamic executable)" } + timeout { fail "(timeout) backtrace after catch (3) (dynamic executable)" } +} + +# Now the exception will be thrown, but not catch-able anywhere. + +send_gdb "continue\n" +gdb_expect { + -re "Continuing\\.\r\nGot.*\r\nCatchpoint \[0-9\]* \\(exception thrown\\), throw location.*exception\\.cc:8, catch location unknown\r\n.*$gdb_prompt $" { + pass "caught an uncatchable throw (dynamic executable)" + } + -re ".*$gdb_prompt $" { fail "didn't catch an uncatchable throw (dynamic executable)" } + timeout { fail "(timeout) after continue -- didn't catch an uncatchable throw? (dynamic executable)" } +} + diff --git a/gdb/testsuite/gdb.hp/execd-program.c b/gdb/testsuite/gdb.hp/execd-program.c new file mode 100644 index 00000000000..0320991062d --- /dev/null +++ b/gdb/testsuite/gdb.hp/execd-program.c @@ -0,0 +1,28 @@ +#include <stdio.h> + +/* There is a global_i in follow_exec, which exec's us. We + should not be able to see that other definition of global_i + after we are exec'd. + */ +int global_i = 0; + +main (argc, argv) + int argc; + char * argv[]; +{ + /* There is a local_j in follow_exec, which exec's us. We + should not be able to see that other definition of local_j + after we are exec'd. + */ + int local_j = argc; + char * s; + + printf ("Hello from execd_program...\n"); + if (argc != 2) + { + printf ("expected one string argument\n"); + exit (-1); + } + s = argv[1]; + printf ("argument received: %s\n", s); +} diff --git a/gdb/testsuite/gdb.hp/foll-exec.c b/gdb/testsuite/gdb.hp/foll-exec.c new file mode 100644 index 00000000000..c51fa52dcfd --- /dev/null +++ b/gdb/testsuite/gdb.hp/foll-exec.c @@ -0,0 +1,35 @@ +#include <stdio.h> + +int global_i = 100; + +main () +{ + int local_j = global_i+1; + int local_k = local_j+1; + + printf ("follow-exec is about to execlp(execd-program)...\n"); + + execlp ("gdb.hp/execd-program", + "gdb.hp/execd-program", + "execlp arg1 from follow-exec", + (char *)0); + + printf ("follow-exec is about to execl(execd-program)...\n"); + + execl ("gdb.hp/execd-program", + "gdb.hp/execd-program", + "execl arg1 from follow-exec", + "execl arg2 from follow-exec", + (char *)0); + + { + static char * argv[] = { + "gdb.hp/execd-program", + "execv arg1 from follow-exec", + 0}; + + printf ("follow-exec is about to execv(execd-program)...\n"); + + execv ("gdb.hp/execd-program", argv); + } +} diff --git a/gdb/testsuite/gdb.hp/foll-exec.exp b/gdb/testsuite/gdb.hp/foll-exec.exp new file mode 100644 index 00000000000..f7d6089931c --- /dev/null +++ b/gdb/testsuite/gdb.hp/foll-exec.exp @@ -0,0 +1,412 @@ +# Copyright (C) 1997 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 2 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +# Please email any bugs, comments, and/or additions to this file to: +# bug-gdb@prep.ai.mit.edu + +if $tracelevel then { + strace $tracelevel + } + +set prms_id 0 +set bug_id 0 + +# are we on a target board +if ![isnative] then { + return +} + +if {![istarget "hppa*-*-hpux10.30"] && ![istarget "hppa*-*-hpux11.*"]} { + #setup_xfail "*-*.*" + return 0 +} + +set testfile "foll-exec" +set testfile2 "execd-program" +set srcfile ${testfile}.c +set srcfile2 ${testfile2}.c +set binfile ${objdir}/${subdir}/${testfile} +set binfile2 ${objdir}/${subdir}/${testfile2} + +# build the first test case +#if { [compile "-g -DNO_PROTOTYPES ${srcdir}/${subdir}/${srcfile2} -o ${binfile2} "] != "" } { +# perror "Couldn't compile ${srcfile2}" +# return -1 +#} +if { [gdb_compile "${srcdir}/${subdir}/${srcfile2}" "${binfile2}" executable {debug}] != "" } { + gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail." +} + +#if { [compile "-g ${srcdir}/${subdir}/${srcfile} -o ${binfile} "] != "" } { +# execute_anywhere "rm -f ${objdir}/${subdir}/${testfile}.tmp" + # built the second test case since we can't use prototypes +# warning "Prototypes not supported, rebuilding with -DNO_PROTOTYPES" +# execute_anywhere "echo set prototypes 0 > ${objdir}/${subdir}/${testfile}.tmp" +# if { [compile "-g -DNO_PROTOTYPES ${srcdir}/${subdir}/${srcfile} -o ${binfile} "] != "" } { +# perror "Couldn't compile ${testfile}.c" +# return -1 +# } +#} + +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } { + gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail." +} + + +# Until "catch exec" is implemented on other targets... +# +if ![istarget "hppa*-hp-hpux*"] then { + setup_xfail "*-*-*" +} + +proc zap_session {} { + global gdb_prompt + global binfile + + send_gdb "kill\n" + gdb_expect { + -re ".*Kill the program being debugged.*y or n. $" { + send_gdb "y\n" + send_gdb "file $binfile\n" + gdb_expect { + -re ".*Load new symbol table from.*y or n. $" { + send_gdb "y\n" + gdb_expect { + -re "Reading symbols from.*$gdb_prompt $" {} + timeout { fail "loading symbols (timeout)"; return } + } + } + -re ".*gdb_prompt $" {} + timeout { fail "loading symbols (timeout)"; return } + } + } + -re ".*$gdb_prompt $" {} + timeout { fail "killing inferior (timeout)" ; return } + } +} + +proc do_exec_tests {} { + global gdb_prompt + global binfile + global srcfile + global srcfile2 + global testfile + global testfile2 + + # Start the program running, and stop at main. + # + if ![runto_main] then { + perror "Couldn't run ${testfile}" + return + } + + # Verify that we can see various global and local variables + # in this program, and that they have expected values. Some + # of these variables are also declared in the program we'll + # exec in a moment. + # + send_gdb "next 3\n" + gdb_expect { + -re "12.*execlp.*$gdb_prompt $"\ + {pass "step to exec call"} + -re "$gdb_prompt $" {fail "step to exec call"} + timeout {fail "(timeout) step to exec call"} + } + send_gdb "print global_i\n" + gdb_expect { + -re ".* = 100.*$gdb_prompt $"\ + {pass "print follow-exec/global_i"} + -re "$gdb_prompt $" {fail "print follow-exec/global_i"} + timeout {fail "(timeout) print follow-exec/global_i"} + } + send_gdb "print local_j\n" + gdb_expect { + -re ".* = 101.*$gdb_prompt $"\ + {pass "print follow-exec/local_j"} + -re "$gdb_prompt $" {fail "print follow-exec/local_j"} + timeout {fail "(timeout) print follow-exec/local_j"} + } + send_gdb "print local_k\n" + gdb_expect { + -re ".* = 102.*$gdb_prompt $"\ + {pass "print follow-exec/local_k"} + -re "$gdb_prompt $" {fail "print follow-exec/local_k"} + timeout {fail "(timeout) print follow-exec/local_k"} + } + + # Try stepping through an execlp call, without catching it. + # We should stop in execd-program, at its first statement. + # + send_gdb "next\n" + gdb_expect { + -re "Executing new program: .*${testfile2}.*${srcfile2}:17.*int local_j = argc;.*$gdb_prompt $"\ + {pass "step through execlp call"} + -re "$gdb_prompt $" {fail "step through execlp call"} + timeout {fail "(timeout) step through execlp call"} + } + + # Verify that we can see the variables defined in the newly-exec'd + # program, and CANNOT see those defined in the exec'ing program. + # + send_gdb "next\n" + gdb_expect { + -re "20.*printf.*$gdb_prompt $"\ + {pass "step after execlp call"} + -re "$gdb_prompt $" {fail "step after execlp call"} + timeout {fail "(timeout) step after execlp call"} + } + send_gdb "print global_i\n" + gdb_expect { + -re ".* = 0.*$gdb_prompt $"\ + {pass "print execd-program/global_i (after execlp)"} + -re "$gdb_prompt $" {fail "print execd-program/global_i (after execlp)"} + timeout {fail "(timeout) print execd-program/global_i (after execlp)"} + } + send_gdb "print local_j\n" + gdb_expect { + -re ".* = 2.*$gdb_prompt $"\ + {pass "print execd-program/local_j (after execlp)"} + -re "$gdb_prompt $" {fail "print execd-program/local_j (after execlp)"} + timeout {fail "(timeout) print execd-program/local_j (after execlp)"} + } + send_gdb "print local_k\n" + gdb_expect { + -re "No symbol \"local_k\" in current context.*$gdb_prompt $"\ + {pass "print follow-exec/local_k (after execlp)"} + -re "$gdb_prompt $" {fail "print follow-exec/local_k (after execlp)"} + timeout {fail "(timeout) print follow-exec/local_k (after execlp)"} + } + + # Explicitly kill this program, or a subsequent rerun actually runs + # the exec'd program, not the original program... + zap_session + + # Start the program running, and stop at main. + # + if ![runto_main] then { + perror "Couldn't run ${testfile} (2nd try)" + return + } + + # Verify that we can catch an exec event, and then continue + # to follow through the exec. (Since there's a breakpoint on + # "main", it'll also be transferred to the exec'd program, + # and we expect to stop there.) + # + send_gdb "catch exec\n" + gdb_expect { + -re "Catchpoint .*(exec).*$gdb_prompt $"\ + {pass "set catch exec"} + -re "$gdb_prompt $" {fail "set catch exec"} + timeout {fail "(timeout) set catch exec"} + } + + # Verify that the catchpoint is mentioned in an "info breakpoints", + # and further that the catchpoint mentions no program name. + # + send_gdb "info breakpoints\n" + gdb_expect { + -re ".*catch exec.*keep y.*$gdb_prompt $"\ + {pass "info shows catchpoint without exec pathname"} + -re ".*catch exec.*program \"\".*$gdb_prompt $"\ + {fail "info shows catchpoint without exec pathname"} + -re "$gdb_prompt $" {fail "info shows catchpoint without exec pathname"} + timeout {fail "(timeout) info shows catchpoint without exec pathname"} + } + + send_gdb "continue\n" + gdb_expect { + -re ".*Executing new program:.*${testfile2}.*Catchpoint .*(exec\'d .*${testfile2}).*in .START..*$gdb_prompt $"\ + {pass "hit catch exec"} + -re "$gdb_prompt $" {fail "hit catch exec"} + timeout {fail "(timeout) hit catch exec"} + } + + # Verify that the catchpoint is mentioned in an "info breakpoints", + # and further that the catchpoint managed to capture the exec'd + # program's name. + # + send_gdb "info breakpoints\n" + gdb_expect { + -re ".*catch exec .*program \".*${testfile2}\".*$gdb_prompt $"\ + {pass "info shows catchpoint exec pathname"} + -re "$gdb_prompt $" {fail "info shows catchpoint exec pathname"} + timeout {fail "(timeout) info shows catchpoint exec pathname"} + } + + # Verify that we can continue from the catchpoint, and land in the + # main of the newly-exec'd program. + # + send_gdb "continue\n" + gdb_expect { + -re ".*${srcfile2}:17.*$gdb_prompt $"\ + {pass "continue after hit catch exec"} + -re "$gdb_prompt $" {fail "continue after hit catch exec"} + timeout {fail "(timeout) continue after hit catch exec"} + } + + # Explicitly kill this program, or a subsequent rerun actually runs + # the exec'd program, not the original program... + zap_session + + # Start the program running, and stop at main. + # + if ![runto_main] then { + perror "Couldn't run ${testfile} (3rd try)" + return + } + + # Verify that we can follow through follow an execl() + # call. (We must jump around earlier exec* calls.) + # + send_gdb "tbreak 19\n" + gdb_expect { + -re "Breakpoint .*file .*${srcfile}, line 19.*$gdb_prompt $"\ + {pass "prepare to jump to execl call"} + -re "$gdb_prompt $" {fail "prepare to jump to execl call"} + timeout {fail "(timeout) prepare to jump to execl call"} + } + send_gdb "jump 19\n" + gdb_expect { + -re "main.* at .*${srcfile}:19.*$gdb_prompt $"\ + {pass "jump to execl call"} + -re "$gdb_prompt $" {fail "jump to execl call"} + timeout {fail "(timeout) jump to execl call"} + } + # Note that stepping through an exec call causes the step-count + # to be reset to zero. I.e.: you may specify "next 2" at the + # call, but you'll actually stop at the first breakpoint set in + # the newly-exec'd program, not after the remaining step-count + # reaches zero. + # + send_gdb "next 2\n" + gdb_expect { + -re "Executing new program: .*${testfile2}.*${srcfile2}:17.*int local_j = argc;.*$gdb_prompt $"\ + {pass "step through execl call"} + -re "$gdb_prompt $" {fail "step through execl call"} + timeout {fail "(timeout) step through execl call"} + } + send_gdb "next\n" + gdb_expect { + -re "20.*printf.*$gdb_prompt $"\ + {pass "step after execl call"} + -re "$gdb_prompt $" {fail "step after execl call"} + timeout {fail "(timeout) step after execl call"} + } + + # Verify that we can print a local variable (which happens to be + # assigned the value of main's argc). + # + send_gdb "print local_j\n" + gdb_expect { + -re ".* = 3.*$gdb_prompt $"\ + {pass "print execd-program/local_j (after execl)"} + -re "$gdb_prompt $" {fail "print execd-program/local_j (after execl)"} + timeout {fail "(timeout) print execd-program/local_j (after execl)"} + } + + # Explicitly kill this program, or a subsequent rerun actually runs + # the exec'd program, not the original program... + zap_session + + # Start the program running, and stop at main. + # + if ![runto_main] then { + perror "Couldn't run ${testfile} (4th try)" + return + } + + # Verify that we can follow through follow an execv() + # call. (We must jump around earlier exec* calls.) + # + send_gdb "tbreak 33\n" + gdb_expect { + -re "Breakpoint .*file .*${srcfile}, line 33.*$gdb_prompt $"\ + {pass "prepare to jump to execv call"} + -re "$gdb_prompt $" {fail "prepare to jump to execv call"} + timeout {fail "(timeout) prepare to jump to execv call"} + } + send_gdb "jump 33\n" + gdb_expect { + -re "main.* at .*${srcfile}:33.*$gdb_prompt $"\ + {pass "jump to execv call"} + -re "$gdb_prompt $" {fail "jump to execv call"} + timeout {fail "(timeout) jump to execv call"} + } + send_gdb "next\n" + gdb_expect { + -re "Executing new program: .*${testfile2}.*${srcfile2}:17.*int local_j = argc;.*$gdb_prompt $"\ + {pass "step through execv call"} + -re "$gdb_prompt $" {fail "step through execv call"} + timeout {fail "(timeout) step through execv call"} + } + send_gdb "next\n" + gdb_expect { + -re "20.*printf.*$gdb_prompt $"\ + {pass "step after execv call"} + -re "$gdb_prompt $" {fail "step after execv call"} + timeout {fail "(timeout) step after execv call"} + } + + # Verify that we can print a local variable (which happens to be + # assigned the value of main's argc). + # + send_gdb "print local_j\n" + gdb_expect { + -re ".* = 2.*$gdb_prompt $"\ + {pass "print execd-program/local_j (after execv)"} + -re "$gdb_prompt $" {fail "print execd-program/local_j (after execv)"} + timeout {fail "(timeout) print execd-program/local_j (after execv)"} + } + + # Explicitly kill this program, or a subsequent rerun actually runs + # the exec'd program, not the original program... + zap_session + + # Start the program running, and stop at main. + # + if ![runto_main] then { + perror "Couldn't run ${testfile} (4th try)" + return + } + + # Verify that we can just continue and thereby follow through an + # exec call. (Since the breakpoint on "main" is reset, we should + # just stop in main of the newly-exec'd program.) + # + send_gdb "continue\n" + gdb_expect { + -re "Executing new program: .*${testfile2}.*${srcfile2}:17.*int local_j = argc;.*$gdb_prompt $"\ + {pass "continue through exec"} + -re "$gdb_prompt $" {fail "continue through exec"} + timeout {fail "(timeout) continue through exec"} + } +} + +# Start with a fresh gdb + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + + +# This is a test of gdb's ability to follow a process through a +# Unix exec() system call. +# +do_exec_tests + +return 0 diff --git a/gdb/testsuite/gdb.hp/foll-fork.c b/gdb/testsuite/gdb.hp/foll-fork.c new file mode 100644 index 00000000000..89f92ae22fe --- /dev/null +++ b/gdb/testsuite/gdb.hp/foll-fork.c @@ -0,0 +1,25 @@ +#include <stdio.h> + +void callee (i) + int i; +{ + printf("callee: %d\n", i); +} + +main () +{ + int pid; + int v = 5; + + pid = fork (); + if (pid == 0) + { + v++; + /* printf ("I'm the child!\n"); */ + } + else + { + v--; + /* printf ("I'm the proud parent of child #%d!\n", pid); */ + } +} diff --git a/gdb/testsuite/gdb.hp/foll-fork.exp b/gdb/testsuite/gdb.hp/foll-fork.exp new file mode 100644 index 00000000000..7231764f3b4 --- /dev/null +++ b/gdb/testsuite/gdb.hp/foll-fork.exp @@ -0,0 +1,385 @@ +# Copyright (C) 1997 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 2 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +# Please email any bugs, comments, and/or additions to this file to: +# bug-gdb@prep.ai.mit.edu + +if $tracelevel then { + strace $tracelevel + } + +set prms_id 0 +set bug_id 0 + +# are we on a target board +if ![isnative] then { + return +} + +if {![istarget "hppa*-*-hpux10.30"] && ![istarget "hppa*-*-hpux11.*"]} { + #setup_xfail "*-*.*" + return 0 +} + +set testfile "foll-fork" +set srcfile ${testfile}.c +set binfile ${objdir}/${subdir}/${testfile} + +# build the first test case +#if { [compile "-g ${srcdir}/${subdir}/${srcfile} -o ${binfile} "] != "" } { +# execute_anywhere "rm -f ${objdir}/${subdir}/${testfile}.tmp" + # built the second test case since we can't use prototypes +# warning "Prototypes not supported, rebuilding with -DNO_PROTOTYPES" +# execute_anywhere "echo set prototypes 0 > ${objdir}/${subdir}/${testfile}.tmp" +# if { [compile "-g -DNO_PROTOTYPES ${srcdir}/${subdir}/${srcfile} -o ${binfile} "] != "" } { +# perror "Couldn't compile ${testfile}.c" +# return -1 +# } +#} + +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } { + gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail." +} + + + +# Until "set follow-fork-mode" and "catch fork" are implemented on +# other targets... +# +if ![istarget "hppa*-hp-hpux*"] then { + setup_xfail "*-*-*" +} + +proc default_fork_parent_follow {} { + global gdb_prompt + + send_gdb "show follow\n" + gdb_expect { + -re "Debugger response to a program call of fork or vfork is \"parent\"..*$gdb_prompt $"\ + {pass "default show parent follow, no catchpoints"} + -re "$gdb_prompt $" {fail "default show parent follow, no catchpoints"} + timeout {fail "(timeout) default show parent follow, no catchpoints"} + } + send_gdb "next 2\n" + gdb_expect { + -re "Detaching after fork from.*$gdb_prompt $"\ + {pass "default parent follow, no catchpoints"} + -re "$gdb_prompt $" {fail "default parent follow, no catchpoints"} + timeout {fail "(timeout) default parent follow, no catchpoints" } + } + # The child has been detached; allow time for any output it might + # generate to arrive, so that output doesn't get confused with + # any expected debugger output from a subsequent testpoint. + # + exec sleep 1 +} + +proc explicit_fork_parent_follow {} { + global gdb_prompt + + send_gdb "set follow parent\n" + gdb_expect { + -re "$gdb_prompt $" {pass "set follow parent"} + timeout {fail "(timeout) set follow parent"} + } + send_gdb "show follow\n" + gdb_expect { + -re "Debugger response to a program call of fork or vfork is \"parent\"..*$gdb_prompt $"\ + {pass "explicit show parent follow, no catchpoints"} + -re "$gdb_prompt $" {fail "explicit show parent follow, no catchpoints"} + timeout {fail "(timeout) explicit show parent follow, no catchpoints"} + } + send_gdb "next 2\n" + gdb_expect { + -re "Detaching after fork from.*$gdb_prompt $"\ + {pass "explicit parent follow, no catchpoints"} + -re "$gdb_prompt $" {fail "explicit parent follow, no catchpoints"} + timeout {fail "(timeout) explicit parent follow, no catchpoints"} + } + # The child has been detached; allow time for any output it might + # generate to arrive, so that output doesn't get confused with + # any expected debugger output from a subsequent testpoint. + # + exec sleep 1 +} + +proc explicit_fork_child_follow {} { + global gdb_prompt + + send_gdb "set follow child\n" + gdb_expect { + -re "$gdb_prompt $" {pass "set follow child"} + timeout {fail "(timeout) set follow child"} + } + send_gdb "show follow\n" + gdb_expect { + -re "Debugger response to a program call of fork or vfork is \"child\"..*$gdb_prompt $"\ + {pass "explicit show child follow, no catchpoints"} + -re "$gdb_prompt $" {fail "explicit show child follow, no catchpoints"} + timeout {fail "(timeout) explicit show child follow, no catchpoints"} + } + send_gdb "next 2\n" + gdb_expect { + -re "Detaching from program:.*Attaching after fork to.*$gdb_prompt $"\ + {pass "explicit child follow, no catchpoints"} + -re "$gdb_prompt $" {fail "explicit child follow, no catchpoints"} + timeout {fail "(timeout) explicit child follow, no catchpoints"} + } + # The child has been detached; allow time for any output it might + # generate to arrive, so that output doesn't get confused with + # any gdb_expected debugger output from a subsequent testpoint. + # + exec sleep 1 +} + +proc catch_fork_child_follow {} { + global gdb_prompt + + send_gdb "catch fork\n" + gdb_expect { + -re "Catchpoint .*(fork).*$gdb_prompt $"\ + {pass "explicit child follow, set catch fork"} + -re "$gdb_prompt $" {fail "explicit child follow, set catch fork"} + timeout {fail "(timeout) explicit child follow, set catch fork"} + } + + # Verify that the catchpoint is mentioned in an "info breakpoints", + # and further that the catchpoint mentions no process id. + # + send_gdb "info breakpoints\n" + gdb_expect { + -re ".*catch fork.*keep y.*$gdb_prompt $"\ + {pass "info shows catchpoint without pid"} + -re ".*catch fork.*process .*$gdb_prompt $"\ + {fail "info shows catchpoint without pid"} + -re "$gdb_prompt $" {fail "info shows catchpoint without pid"} + timeout {fail "(timeout) info shows catchpoint without pid"} + } + + send_gdb "continue\n" + gdb_expect { + -re "Catchpoint.*(forked process.*),.*in _fork_sys.*$gdb_prompt $"\ + {pass "explicit child follow, catch fork"} + -re "$gdb_prompt $" {fail "explicit child follow, catch fork"} + timeout {fail "(timeout) explicit child follow, catch fork"} + } + + # Verify that the catchpoint is mentioned in an "info breakpoints", + # and further that the catchpoint managed to capture a process id. + # + send_gdb "info breakpoints\n" + gdb_expect { + -re ".*catch fork .*process \[0-9\]+.*$gdb_prompt $"\ + {pass "info shows catchpoint pid"} + -re "$gdb_prompt $" {fail "info shows catchpoint pid"} + timeout {fail "(timeout) info shows catchpoint pid"} + } + + send_gdb "set follow child\n" + gdb_expect { + -re "$gdb_prompt $" {pass "set follow child"} + timeout {fail "(timeout) set follow child"} + } + send_gdb "tbreak 15\n" + gdb_expect { + -re "Breakpoint.*, line 15.*$gdb_prompt $"\ + {pass "set follow child, tbreak"} + -re "$gdb_prompt $" {fail "set follow child, tbreak"} + timeout {fail "(timeout) set follow child, tbreak"} + } + send_gdb "continue\n" + gdb_expect { + -re ".*Detaching from program:.*Attaching after fork to.* at .*15.*$gdb_prompt $"\ + {pass "set follow child, hit tbreak"} + -re "$gdb_prompt $" {fail "set follow child, hit tbreak"} + timeout {fail "(timeout) set follow child, hit tbreak"} + } + # The child has been detached; allow time for any output it might + # generate to arrive, so that output doesn't get confused with + # any expected debugger output from a subsequent testpoint. + # + exec sleep 1 + send_gdb "delete breakpoints\n" + gdb_expect { + -re "Delete all breakpoints.*$" { + send_gdb "y\n" + gdb_expect { + -re "$gdb_prompt $"\ + {pass "set follow child, cleanup"} + timeout {fail "(timeout) set follow child, cleanup"} + } + } + -re "$gdb_prompt $" {fail "set follow child, cleanup"} + timeout {fail "(timeout) set follow child, cleanup"} + } +} + +proc tcatch_fork_parent_follow {} { + global gdb_prompt + + send_gdb "catch fork\n" + gdb_expect { + -re "Catchpoint .*(fork).*$gdb_prompt $"\ + {pass "explicit parent follow, set tcatch fork"} + -re "$gdb_prompt $" {fail "explicit parent follow, set tcatch fork"} + timeout {fail "(timeout) explicit parent follow, set tcatch fork"} + } +# ??rehrauer: I don't yet know how to get the id of the tcatch +# via this script, so that I can add a -do list to it. For now, +# do the follow stuff after the catch happens. + + send_gdb "continue\n" + gdb_expect { + -re ".*in _fork_sys.*$gdb_prompt $"\ + {pass "explicit parent follow, tcatch fork"} + -re "$gdb_prompt $" {fail "explicit parent follow, tcatch fork"} + timeout {fail "(timeout) explicit parent follow, tcatch fork"} + } + send_gdb "set follow parent\n" + gdb_expect { + -re "$gdb_prompt $" {pass "set follow parent"} + timeout {fail "(timeout) set follow parent"} + } + send_gdb "tbreak 15\n" + gdb_expect { + -re "Breakpoint.*, line 15.*$gdb_prompt $"\ + {pass "set follow parent, tbreak"} + -re "$gdb_prompt $" {fail "set follow parent, tbreak"} + timeout {fail "(timeout) set follow child, tbreak"} + } + send_gdb "continue\n" + gdb_expect { + -re ".*Detaching after fork from.* at .*15.*$gdb_prompt $"\ + {pass "set follow parent, hit tbreak"} + -re "$gdb_prompt $" {fail "set follow parent, hit tbreak"} + timeout {fail "(timeout) set follow parent, hit tbreak"} + } + # The child has been detached; allow time for any output it might + # generate to arrive, so that output doesn't get confused with + # any expected debugger output from a subsequent testpoint. + # + exec sleep 1 + send_gdb "delete breakpoints\n" + gdb_expect { + -re "Delete all breakpoints.*$" { + send_gdb "y\n" + gdb_expect { + -re "$gdb_prompt $"\ + {pass "set follow parent, cleanup"} + timeout {fail "(timeout) set follow parent, cleanup"} + } + } + -re "$gdb_prompt $" {fail "set follow parent, cleanup"} + timeout {fail "(timeout) set follow parent, cleanup"} + } +} + +proc do_fork_tests {} { + global gdb_prompt + + # Verify that help is available for "set follow-fork-mode". + # + send_gdb "help set follow-fork-mode\n" + gdb_expect { + -re "Set debugger response to a program call of fork or vfork..* +A fork or vfork creates a new process. follow-fork-mode can be:.* +.*parent - the original process is debugged after a fork.* +.*child - the new process is debugged after a fork.* +.*ask - the debugger will ask for one of the above choices.* +For \"parent\" or \"child\", the unfollowed process will run free..* +By default, the debugger will follow the parent process..*$gdb_prompt $"\ + { pass "help set follow" } + -re "$gdb_prompt $" { fail "help set follow" } + timeout { fail "(timeout) help set follow" } + } + + # Verify that we can set follow-fork-mode, using an abbreviation + # for both the flag and its value. + # + send_gdb "set follow ch\n" + send_gdb "show fol\n" + gdb_expect { + -re "Debugger response to a program call of fork or vfork is \"child\".*$gdb_prompt $"\ + {pass "set follow, using abbreviations"} + timeout {fail "(timeout) set follow, using abbreviations"} + } + + # Verify that we cannot set follow-fork-mode to nonsense. + # + send_gdb "set follow chork\n" + gdb_expect { + -re "Undefined item: \"chork\".*$gdb_prompt $"\ + {pass "set follow to nonsense is prohibited"} + -re "$gdb_prompt $" {fail "set follow to nonsense is prohibited"} + timeout {fail "(timeout) set follow to nonsense is prohibited"} + } + send_gdb "set follow parent\n" + gdb_expect { + -re "$gdb_prompt $" {pass "set follow to nonsense is prohibited (reset parent)"} + timeout {fail "set follow to nonsense is prohibited (reset parent)"} + } + + # Test the default behaviour, which is to follow the parent of a + # fork, and detach from the child. Do this without catchpoints. + # + if [runto_main] then { default_fork_parent_follow } + + # Test the ability to explicitly follow the parent of a fork, and + # detach from the child. Do this without catchpoints. + # + if [runto_main] then { explicit_fork_parent_follow } + + # Test the ability to follow the child of a fork, and detach from + # the parent. Do this without catchpoints. + # + if [runto_main] then { explicit_fork_child_follow } + + # Test the ability to follow both child and parent of a fork. Do + # this without catchpoints. + # ??rehrauer: NYI. Will add testpoints here when implemented. + # + + # Test the ability to have the debugger ask the user at fork-time + # whether to follow the parent, child or both. Do this without + # catchpoints. + # ??rehrauer: NYI. Will add testpoints here when implemented. + # + + # Test the ability to catch a fork, specify that the child be + # followed, and continue. Make the catchpoint permanent. + # + if [runto_main] then { catch_fork_child_follow } + + # Test the ability to catch a fork, specify via a -do clause that + # the parent be followed, and continue. Make the catchpoint temporary. + # + if [runto_main] then { tcatch_fork_parent_follow } +} + +# Start with a fresh gdb + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + + +# This is a test of gdb's ability to follow the parent, child or both +# parent and child of a Unix fork() system call. +# +do_fork_tests + +return 0 diff --git a/gdb/testsuite/gdb.hp/foll-vfork.c b/gdb/testsuite/gdb.hp/foll-vfork.c new file mode 100644 index 00000000000..c7e6cd32909 --- /dev/null +++ b/gdb/testsuite/gdb.hp/foll-vfork.c @@ -0,0 +1,15 @@ +#include <stdio.h> + +main () +{ + int pid; + + pid = vfork (); + if (pid == 0) { + printf ("I'm the child!\n"); + execlp ("gdb.hp/vforked-program", "gdb.hp/vforked-program", (char *)0); + } + else { + printf ("I'm the proud parent of child #%d!\n", pid); + } +} diff --git a/gdb/testsuite/gdb.hp/foll-vfork.exp b/gdb/testsuite/gdb.hp/foll-vfork.exp new file mode 100644 index 00000000000..26c6981f974 --- /dev/null +++ b/gdb/testsuite/gdb.hp/foll-vfork.exp @@ -0,0 +1,381 @@ +# Copyright (C) 1997 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 2 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +# Please email any bugs, comments, and/or additions to this file to: +# bug-gdb@prep.ai.mit.edu + +if $tracelevel then { + strace $tracelevel + } + +set prms_id 0 +set bug_id 0 + +# are we on a target board +if ![isnative] then { + return +} + +if {![istarget "hppa*-*-hpux10.30"] && ![istarget "hppa*-*-hpux11.*"]} { + #setup_xfail "*-*.*" + return 0 +} + +set testfile "foll-vfork" +set testfile2 "vforked-program" +set srcfile ${testfile}.c +set srcfile2 ${testfile2}.c +set binfile ${objdir}/${subdir}/${testfile} +set binfile2 ${objdir}/${subdir}/${testfile2} + +# build the first test case +#execute_anywhere "echo set prototypes 1 > ${objdir}/${subdir}/${testfile}.tmp" +#if { [compile "-g -DNO_PROTOTYPES ${srcdir}/${subdir}/${srcfile2} -o ${binfile2} "] != "" } { +# perror "Couldn't compile ${srcfile2}" +# return -1 +#} + +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } { + gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail." +} + +#if { [compile "-g ${srcdir}/${subdir}/${srcfile} -o ${binfile} "] != "" } { +# execute_anywhere "rm -f ${objdir}/${subdir}/${testfile}.tmp" + # built the second test case since we can't use prototypes +# warning "Prototypes not supported, rebuilding with -DNO_PROTOTYPES" +# execute_anywhere "echo set prototypes 0 > ${objdir}/${subdir}/${testfile}.tmp" +# if { [compile "-g -DNO_PROTOTYPES ${srcdir}/${subdir}/${srcfile} -o ${binfile} "] != "" } { +# perror "Couldn't compile ${testfile}.c" +# return -1 +# } +#} + +if { [gdb_compile "${srcdir}/${subdir}/${srcfile2}" "${binfile2}" executable {debug}] != "" } { + gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail." +} + + +# Until "set follow-fork-mode" and "catch vfork" are implemented on +# other targets... +# +if ![istarget "hppa*-hp-hpux*"] then { + setup_xfail "*-*-*" +} + + +# A few of these tests require a little more time than the standard +# timeout allows. +set oldtimeout $timeout +set timeout [expr "$timeout + 10"] + +proc vfork_parent_follow_through_step {} { + global gdb_prompt + + send_gdb "set follow parent\n" + gdb_expect { + -re "$gdb_prompt $" {pass "set follow parent, vfork through step"} + timeout {fail "set follow parent, vfork through step"} + } + send_gdb "next\n" + gdb_expect { + -re "Detaching after fork from.*8.*$gdb_prompt $"\ + {pass "vfork parent follow, through step"} + -re "$gdb_prompt $" {fail "vfork parent follow, through step"} + timeout {fail "(timeout) vfork parent follow, through step" } + } + # The child has been detached; allow time for any output it might + # generate to arrive, so that output doesn't get confused with + # any gdb_expected debugger output from a subsequent testpoint. + # + exec sleep 1 +} + +proc vfork_parent_follow_to_bp {} { + global gdb_prompt + + send_gdb "set follow parent\n" + gdb_expect { + -re "$gdb_prompt $" {pass "set follow parent, vfork to bp"} + timeout {fail "set follow parent, vfork to bp"} + } + send_gdb "break 13\n" + gdb_expect { + -re "$gdb_prompt $" {pass "break, vfork to bp"} + timeout {fail "break, vfork to bp"} + } + send_gdb "continue\n" + gdb_expect { + -re ".*Detaching after fork from process.*Breakpoint.*13.*$gdb_prompt $"\ + {pass "vfork parent follow, to bp"} + -re "$gdb_prompt $" {fail "vfork parent follow, to bp"} + timeout {fail "(timeout) vfork parent follow, to bp" } + } + # The child has been detached; allow time for any output it might + # generate to arrive, so that output doesn't get confused with + # any expected debugger output from a subsequent testpoint. + # + exec sleep 1 +} + +proc vfork_and_exec_child_follow_to_main_bp {} { + global gdb_prompt + global binfile + + send_gdb "set follow child\n" + gdb_expect { + -re "$gdb_prompt $" {pass "set follow child, vfork and exec to main bp"} + timeout {fail "set follow child, vfork and exec to main bp"} + } + send_gdb "continue\n" + gdb_expect { + -re "Detaching from program.*Attaching after fork to.*Executing new program.*Breakpoint.*vforked-program.c:5.*$gdb_prompt $"\ + {pass "vfork and exec child follow, to main bp"} + -re "$gdb_prompt $" {fail "vfork and exec child follow, to main bp"} + timeout {fail "(timeout) vfork and exec child follow, to main bp" } + } + # The parent has been detached; allow time for any output it might + # generate to arrive, so that output doesn't get confused with + # any gdb_expected debugger output from a subsequent testpoint. + # + exec sleep 1 + + # Explicitly kill this child, or a subsequent rerun actually runs + # the exec'd child, not the original program... + send_gdb "kill\n" + gdb_expect { + -re ".*Kill the program being debugged.*y or n. $" { + send_gdb "y\n" + send_gdb "file $binfile\n" + gdb_expect { + -re ".*Load new symbol table from.*y or n. $" { + send_gdb "y\n" + gdb_expect { + -re "Reading symbols from.*$gdb_prompt $" {} + timeout { fail "loading symbols (timeout)"; return } + } + } + -re ".*gdb_prompt $" {} + timeout { fail "loading symbols (timeout)"; return } + } + } + -re ".*$gdb_prompt $" {} + timeout { fail "killing inferior (timeout)" ; return } + } +} + +proc vfork_and_exec_child_follow_through_step {} { + global gdb_prompt + global binfile + +# This test cannot be performed prior to HP-UX 10.30, because ptrace-based +# debugging of a vforking program basically doesn't allow the child to do +# things like hit a breakpoint between a vfork and exec. This means that +# saying "set follow child; next" at a vfork() call won't work, because +# the implementation of "next" sets a "step resume" breakpoint at the +# return from the vfork(), which the child will hit on its way to exec'ing. +# + if { ![istarget "hppa*-*-hpux10.30"] && ![istarget "hppa*-*-hpux11.*"] } { + verbose "vfork child-following next test ignored for non-hppa or pre-HP/UX-10.30 targets." + return 0 + } + + send_gdb "set follow child\n" + gdb_expect { + -re "$gdb_prompt $" {pass "set follow child, vfork and exec through step"} + timeout {fail "set follow child, vfork and exec through step"} + } + send_gdb "next\n" + gdb_expect { + -re "Detaching from program.*Attaching after fork to.*Executing new program.*Breakpoint.*vforked_program.c:5.*$gdb_prompt $"\ + {pass "vfork and exec child follow, through step"} + -re "$gdb_prompt $" {fail "vfork and exec child follow, through step"} + timeout {fail "(timeout) vfork and exec child follow, through step" } + } + # The parent has been detached; allow time for any output it might + # generate to arrive, so that output doesn't get confused with + # any expected debugger output from a subsequent testpoint. + # + exec sleep 1 + + # Explicitly kill this child, or a subsequent rerun actually runs + # the exec'd child, not the original program... + send_gdb "kill\n" + gdb_expect { + -re ".*Kill the program being debugged.*y or n. $" { + send_gdb "y\n" + send_gdb "file $binfile\n" + gdb_expect { + -re ".*Load new symbol table from.*y or n. $" { + send_gdb "y\n" + gdb_expect { + -re "Reading symbols from.*$gdb_prompt $" {} + timeout { fail "loading symbols (timeout)"; return } + } + } + -re ".*gdb_prompt $" {} + timeout { fail "loading symbols (timeout)"; return } + } + } + -re ".*$gdb_prompt $" {} + timeout { fail "killing inferior (timeout)" ; return } + } +} + +proc tcatch_vfork_then_parent_follow {} { + global gdb_prompt + global srcfile + + send_gdb "set follow parent\n" + gdb_expect { + -re "$gdb_prompt $" {pass "set follow parent, tcatch vfork"} + timeout {fail "set follow parent, tcatch vfork"} + } + send_gdb "tcatch vfork\n" + gdb_expect { + -re "Catchpoint .*(vfork).*$gdb_prompt $"\ + {pass "vfork parent follow, set tcatch vfork"} + -re "$gdb_prompt $" {fail "vfork parent follow, set tcatch vfork"} + timeout {fail "(timeout) vfork parent follow, set tcatch vfork"} + } + send_gdb "continue\n" +# HP-UX 10.20 seems to stop you in "vfork", while more recent HP-UXs +# stop you in "_vfork". + gdb_expect { + -re "0x\[0-9a-fA-F\]*.*vfork.*$gdb_prompt $"\ + {pass "vfork parent follow, tcatch vfork"} + -re "0x\[0-9a-fA-F\]*.*_vfork.*$gdb_prompt $"\ + {pass "vfork parent follow, tcatch vfork"} + -re "$gdb_prompt $" {fail "vfork parent follow, tcatch vfork"} + timeout {fail "(timeout) vfork parent follow, tcatch vfork"} + } + send_gdb "finish\n" + gdb_expect { + -re "Run till exit from.*vfork.*0x\[0-9a-fA-F\]* in main .* at .*${srcfile}:7.*$gdb_prompt $"\ + {pass "vfork parent follow, finish after tcatch vfork"} + -re "$gdb_prompt $" {fail "vfork parent follow, finish after tcatch vfork"} + timeout {fail "(timeout) vfork parent follow, finish after tcatch vfork" } + } + # The child has been detached; allow time for any output it might + # generate to arrive, so that output doesn't get confused with + # any expected debugger output from a subsequent testpoint. + # + exec sleep 1 +} + +proc tcatch_vfork_then_child_follow {} { + global gdb_prompt + global srcfile2 + + send_gdb "set follow child\n" + gdb_expect { + -re "$gdb_prompt $" {pass "set follow child, tcatch vfork"} + timeout {fail "set follow child, tcatch vfork"} + } + send_gdb "tcatch vfork\n" + gdb_expect { + -re "Catchpoint .*(vfork).*$gdb_prompt $"\ + {pass "vfork child follow, set tcatch vfork"} + -re "$gdb_prompt $" {fail "vfork child follow, set tcatch vfork"} + timeout {fail "(timeout) vfork child follow, set tcatch vfork"} + } + send_gdb "continue\n" +# HP-UX 10.20 seems to stop you in "vfork", while more recent HP-UXs +# stop you in "_vfork". + gdb_expect { + -re "0x\[0-9a-fA-F\]*.*vfork.*$gdb_prompt $"\ + {pass "vfork child follow, tcatch vfork"} + -re "0x\[0-9a-fA-F\]*.*_vfork.*$gdb_prompt $"\ + {pass "vfork child follow, tcatch vfork"} + -re "$gdb_prompt $" {fail "vfork child follow, tcatch vfork"} + timeout {fail "(timeout) vfork child follow, tcatch vfork"} + } + send_gdb "finish\n" + gdb_expect { + -re "Run till exit from.*vfork.*${srcfile2}:5.*$gdb_prompt $"\ + {pass "vfork child follow, finish after tcatch vfork"} + -re "$gdb_prompt $" {fail "vfork child follow, finish after tcatch vfork"} + timeout {fail "(timeout) vfork child follow, finish after tcatch vfork" } + } + # The parent has been detached; allow time for any output it might + # generate to arrive, so that output doesn't get confused with + # any expected debugger output from a subsequent testpoint. + # + exec sleep 1 +} + +proc do_vfork_and_exec_tests {} { + global gdb_prompt + + # Try following the parent process by stepping through a call to + # vfork. Do this without catchpoints. + if [runto_main] then { vfork_parent_follow_through_step } + + # Try following the parent process by setting a breakpoint on the + # other side of a vfork, and running to that point. Do this + # without catchpoints. + if [runto_main] then { vfork_parent_follow_to_bp } + + # Try following the child process by just continuing through the + # vfork, and letting the parent's breakpoint on "main" be auto- + # magically reset in the child. + # + if [runto_main] then { vfork_and_exec_child_follow_to_main_bp } + + # Try following the child process by stepping through a call to + # vfork. The child also executes an exec. Since the child cannot + # be debugged until after it has exec'd, and since there's a bp on + # "main" in the parent, and since the bp's for the parent are + # recomputed in the exec'd child, the step through a vfork should + # land us in the "main" for the exec'd child, too. + # + if [runto_main] then { vfork_and_exec_child_follow_through_step } + + # Try catching a vfork, and stepping out to the parent. + # + if [runto_main] then { tcatch_vfork_then_parent_follow } + + # Try catching a vfork, and stepping out to the child. + # + if [runto_main] then { tcatch_vfork_then_child_follow } + + # Test the ability to follow both child and parent of a vfork. Do + # this without catchpoints. + # ??rehrauer: NYI. Will add testpoints here when implemented. + # + + # Test the ability to have the debugger ask the user at vfork-time + # whether to follow the parent, child or both. Do this without + # catchpoints. + # ??rehrauer: NYI. Will add testpoints here when implemented. + # +} + +# Start with a fresh gdb + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + + +# This is a test of gdb's ability to follow the parent or child +# of a Unix vfork() system call. (The child will subsequently +# call a variant of a Unix exec() system call.) +# +do_vfork_and_exec_tests + +set timeout $oldtimeout +return 0 diff --git a/gdb/testsuite/gdb.hp/gen-so-thresh.c b/gdb/testsuite/gdb.hp/gen-so-thresh.c new file mode 100644 index 00000000000..c1a3eb580c5 --- /dev/null +++ b/gdb/testsuite/gdb.hp/gen-so-thresh.c @@ -0,0 +1,229 @@ +/* + * Program to generate the so-thresh testcase, + * including associated linked-against shared libraries. + * Build as: + * + * cc -g -o gen-so-thresh gen-so-thresh.c + * + * Invoke as: + * + * gen-so-thresh + * + * It will put all the code in the current directory ("."). + * + * A makefile can also be generated if the -makemake option is used. + * To use the makefile: + * + * make -f so-thresh.mk all + * + * The name of the application is + * + * so-thresh + * + * (Revised from a program by John Bishop. --rehrauer) + */ + +#include <stdio.h> +#include <sys/stat.h> +#include <sys/fcntl.h> + +int main (argc, argv) +int argc; +char **argv; +{ +#define NUMBER_OF_INT_VARS 1500 +#define NUMBER_OF_LIBS 3 + int lib_num = NUMBER_OF_LIBS; + int i; + int i2; + FILE *main_file; + FILE *lib_file; + FILE *make_file; + FILE *link_file; + + char testcase_name [1000]; + char linkfile_name [1000]; + char makefile_name [1000]; + char mainfile_name [1000]; + + char file_name[100]; + /* + * 0123456789 <-- length of field + * "./fil0000000002.c"; <-- typical filename + * 12345678901234567890 <-- length of string + * 10 20 + * ^where null goes + */ + char file_name_core[100]; + + /* Verify input. + */ + if ((argc < 1) || (argc > 2) || (argv == NULL) || + ((argc == 2) && (strcmp (argv[1], "-makemake") != 0))) + { + printf ("** Syntax: %s [-makemake]\n", argv[0]); + return; + } + + if (strncmp (argv[0], "gen-", 4) != 0) + { + printf ("** This tool expected to be named \"gen-something\"\n"); + return; + } + strcpy (testcase_name, argv[0]+4); + + strcpy (linkfile_name, testcase_name); + strcat (linkfile_name, ".linkopts"); + link_file = fopen (linkfile_name, "w"); + fprintf (link_file, "# Linker options for %s test\n", testcase_name); + + /* Generate the makefile, if requested. + */ + if (argc == 2) + { + strcpy (makefile_name, testcase_name); + strcat (makefile_name, ".mk.new"); + make_file = fopen (makefile_name, "w"); + printf (" Note: New makefile (%s) generated.\n", makefile_name); + printf (" May want to update existing makefile, if any.\n"); + fprintf (make_file, "# Generated automatically by %s\n", argv[0]); + fprintf (make_file, "# Make file for %s test\n", testcase_name); + fprintf (make_file, "\n"); + fprintf (make_file, "CFLAGS = +DA1.1 -g\n"); + fprintf (make_file, "\n"); + fprintf (make_file, "# This is how to build this generator.\n"); + fprintf (make_file, "%s.o: %s.c\n", argv[0], argv[0]); + fprintf (make_file, "\t$(CC) $(CFLAGS) -o %s.o -c %s.c\n", argv[0], argv[0]); + fprintf (make_file, "%s: %s.o\n", argv[0], argv[0]); + fprintf (make_file, "\t$(CC) $(CFLAGS) -o %s %s.o\n", argv[0], argv[0]); + fprintf (make_file, "\n"); + fprintf (make_file, "# This is how to run this generator.\n"); + fprintf (make_file, "# This target should be made before the 'all' target,\n"); + fprintf (make_file, "# to ensure that the shlib sources are all available.\n"); + fprintf (make_file, "require_shlibs: %s\n", argv[0]); + for (i=0; i < lib_num; i++) + { + fprintf (make_file, "\tif ! [ -a lib%2.2d_%s.c ] ; then \\\n", i, testcase_name); + fprintf (make_file, "\t %s ; \\\n", argv[0]); + fprintf (make_file, "\tfi\n"); + } + fprintf (make_file, "\n"); + fprintf (make_file, "# This is how to build all the shlibs.\n"); + fprintf (make_file, "# Be sure to first make the require_shlibs target!\n"); + for (i=0; i < lib_num; i++) + { + fprintf (make_file, "lib%2.2d_%s.o: lib%2.2d_%s.c\n", i, testcase_name, i, testcase_name); + fprintf (make_file, "\t$(CC) $(CFLAGS) +Z -o lib%2.2d_%s.o -c lib%2.2d_%s.c\n", i, testcase_name, i, testcase_name); + fprintf (make_file, "lib%2.2d-%s.sl: lib%2.2d-%s.o\n", i, testcase_name, i, testcase_name); + fprintf (make_file, "\t$(LD) $(LDFLAGS) -b -o lib%2.2d-%s.sl lib%2.2d-%s.o\n", i, testcase_name, i, testcase_name); + } + fprintf (make_file, "\n"); +fprintf (make_file, "# For convenience, here's names for all pieces of all shlibs.\n"); + fprintf (make_file, "SHLIB_SOURCES = \\\n"); + for (i=0; i < lib_num-1; i++) + fprintf (make_file, "\tlib%2.2d-%s.c \\\n", i, testcase_name); + fprintf (make_file, "\tlib%2.2d-%s.c\n", lib_num-1, testcase_name); + fprintf (make_file, "SHLIB_OBJECTS = $(SHLIB_SOURCES:.c=.o)\n"); + fprintf (make_file, "SHLIBS = $(SHLIB_SOURCES:.c=.sl)\n"); + fprintf (make_file, "SHLIB_NAMES = $(SHLIB_SOURCES:.c=)\n"); + fprintf (make_file, "EXECUTABLES = $(SHLIBS) %s %s\n", argv[0], testcase_name); + fprintf (make_file, "OBJECT_FILES = $(SHLIB_OBJECTS) %s.o %s.o\n", argv[0], testcase_name); + fprintf (make_file, "\n"); + fprintf (make_file, "shlib_objects: $(SHLIB_OBJECTS)\n"); + fprintf (make_file, "shlibs: $(SHLIBS)\n"); + fprintf (make_file, "\n"); + fprintf (make_file, "# This is how to build the debuggable testcase that uses the shlibs.\n"); + fprintf (make_file, "%s.o: %s.c\n", testcase_name, testcase_name); + fprintf (make_file, "\t$(CC) $(CFLAGS) -o %s.o -c %s.c\n", testcase_name, testcase_name); + fprintf (make_file, "%s: shlibs %s.o\n", testcase_name, testcase_name); + fprintf (make_file, "\t$(LD) $(LDFLAGS) -o %s -lc -L. ", testcase_name); + fprintf (make_file, "-c %s /opt/langtools/lib/end.o /lib/crt0.o %s.o\n", linkfile_name, testcase_name); + fprintf (make_file, "\n"); + fprintf (make_file, "# Yeah, but you should first make the require_shlibs target!\n"); + fprintf (make_file, "all: %s %s\n", testcase_name, argv[0]); + fprintf (make_file, "\n"); + fprintf (make_file, "# To remove everything built via this makefile...\n"); + fprintf (make_file, "clean:\n"); + /* Do this carefully, to avoid hitting silly HP-UX ARG_MAX limits... */ + fprintf (make_file, "\trm -f lib0*-%s.*\n", testcase_name); + fprintf (make_file, "\trm -f lib1*-%s.*\n", testcase_name); + fprintf (make_file, "\trm -f lib2*-%s.*\n", testcase_name); + fprintf (make_file, "\trm -f lib3*-%s.*\n", testcase_name); + fprintf (make_file, "\trm -f lib4*-%s.*\n", testcase_name); + fprintf (make_file, "\trm -f lib5*-%s.*\n", testcase_name); + fprintf (make_file, "\trm -f lib6*-%s.*\n", testcase_name); + fprintf (make_file, "\trm -f lib7*-%s.*\n", testcase_name); + fprintf (make_file, "\trm -f lib8*-%s.*\n", testcase_name); + fprintf (make_file, "\trm -f lib9*-%s.*\n", testcase_name); + fprintf (make_file, "\trm -f %s %s %s %s.c\n", argv[0], testcase_name, linkfile_name, testcase_name); + fprintf (make_file, "\n"); + fclose (make_file); + } + + /* Generate the code for the libraries. + */ + for (i=0; i < lib_num; i++) { + + /* Generate the names for the library. + */ + sprintf (file_name, "lib%2.2d-%s.c", i, testcase_name); + sprintf (file_name_core, "lib%2.2d-%s", i, testcase_name); + + /* Generate the source code. + */ + lib_file = fopen (file_name, "w"); + fprintf (lib_file, "/* Shared library file number %d */\n", i); + fprintf (lib_file, "#include <stdio.h>\n\n"); + fprintf (lib_file, "/* The following variables largely exist to bloat this library's debug info. */\n"); + fprintf (lib_file, "static char c_static_buf_%d [100];\n", i); + for (i2=0; i2<NUMBER_OF_INT_VARS; i2++) + fprintf (lib_file, "int i_%d_%d;\n", i, i2); + fprintf (lib_file, "\nint r_%d ()\n", i); + fprintf (lib_file, "{\n"); + for (i2=0; i2<NUMBER_OF_INT_VARS; i2++) + fprintf (lib_file, " i_%d_%d = %d*%d;\n", i, i2, i2, i2); + fprintf (lib_file, " return 1;\n"); + fprintf (lib_file, "}\n\n"); + fprintf (lib_file, "/* end of generated file */\n"); + fclose (lib_file); + + /* Add a linker options line + */ + fprintf (link_file, "-l%2.2d-%s\n", i, testcase_name); + } + + /* Generate the "main" file. + */ + strcpy (mainfile_name, testcase_name); + strcat (mainfile_name, ".c"); + main_file = fopen (mainfile_name, "w"); + fprintf (main_file, "/* Generated test progam with %d shared libraries. */\n\n", + lib_num); + fprintf (main_file, "#include <stdio.h>\n\n"); + + for (i = 0; i < lib_num; i++) { + fprintf (main_file, "extern int r_%d();\n", i); + } + + fprintf (main_file, "\n"); + fprintf (main_file, "int main()\n"); + fprintf (main_file, "{\n"); + fprintf (main_file, " int accum;\n"); + fprintf (main_file, " int lib_num = %d;\n", lib_num); + + for (i = 0; i < lib_num; i++) { + fprintf (main_file, " accum += r_%d();\n", i); + } + + fprintf (main_file, " printf( \"Final value: %%d, should be %%d\\n\", accum, lib_num );\n\n"); + fprintf (main_file, " return 0;\n"); + fprintf (main_file, "}\n\n"); + fprintf (main_file, "/* end of generated file */\n"); + fclose (main_file); + + /* Finish up the link file and the build file + */ + fclose (link_file); +} + +/* End of file */ diff --git a/gdb/testsuite/gdb.hp/hwwatchbus.c b/gdb/testsuite/gdb.hp/hwwatchbus.c new file mode 100644 index 00000000000..7a02c9b4498 --- /dev/null +++ b/gdb/testsuite/gdb.hp/hwwatchbus.c @@ -0,0 +1,9 @@ +/* This program raises a SIGBUS signal on HP-UX when the + pointer "bogus_p" is dereferenced. + */ +int * bogus_p = (int *)3; + +main() +{ + *bogus_p = 0xdeadbeef; +} diff --git a/gdb/testsuite/gdb.hp/hwwatchbus.exp b/gdb/testsuite/gdb.hp/hwwatchbus.exp new file mode 100644 index 00000000000..d4899a997e2 --- /dev/null +++ b/gdb/testsuite/gdb.hp/hwwatchbus.exp @@ -0,0 +1,84 @@ +# Copyright (C) 1997, 1998 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 2 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +# Please email any bugs, comments, and/or additions to this file to: +# bug-gdb@prep.ai.mit.edu + +if $tracelevel then { + strace $tracelevel + } + +set prms_id 0 +set bug_id 0 + +# are we on a target board +if ![isnative] then { + return +} + +if { ![istarget "hppa*-*-hpux10.30"] && ![istarget "hppa*-*-hpux11.*"] } { + verbose "HPUX h/w watch test ignored for non-hppa or pre-HP/UX-10.30 targets." + return 0 +} + +set testfile "hwwatchbus" +set srcfile ${testfile}.c +set binfile ${objdir}/${subdir}/${testfile} + +# build the first test case +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } { + gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail." +} + +if [get_compiler_info ${binfile}] { + return -1 +} + +# Start with a fresh gdb + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + + +# We ought to be able to set a hardware watchpoint, step, and +# get a SIGBUS signal reported. +# +if ![runto_main] then { + fail "can't run to main" + return 0 +} + +send_gdb "watch bogus_p\n" +gdb_expect { + -re "Hardware watchpoint \[0-9\]*: bogus_p.*$gdb_prompt $"\ + {pass "set h/w watchpoint"} + -re "$gdb_prompt $"\ + {fail "set h/w watchpoint"} + timeout {fail "(timeout) set h/w watchpoint"} +} + +send_gdb "step\n" +gdb_expect { + -re "Program received signal SIGBUS, Bus error.* in main .*${srcfile}:8.*$gdb_prompt $"\ + {pass "see real SIGBUS when h/w watchpoint set"} + -re "$gdb_prompt $"\ + {fail "see real SIGBUS when h/w watchpoint set"} + timeout {fail "(timeout) see real SIGBUS when h/w watchpoint set"} +} + +return 0 diff --git a/gdb/testsuite/gdb.hp/inherit-hp.exp b/gdb/testsuite/gdb.hp/inherit-hp.exp new file mode 100644 index 00000000000..645358ec0da --- /dev/null +++ b/gdb/testsuite/gdb.hp/inherit-hp.exp @@ -0,0 +1,849 @@ +# Copyright (C) 1992, 1993, 1994, 1997 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 2 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +# Please email any bugs, comments, and/or additions to this file to: +# bug-gdb@prep.ai.mit.edu + +# This file was written by Fred Fish. (fnf@cygnus.com) + +set ws "\[\r\n\t \]+" + +if $tracelevel then { + strace $tracelevel +} + +# Check to see if we have an executable to test. If not, then either we +# haven't tried to compile one, or the compilation failed for some reason. +# In either case, just notify the user and skip the tests in this file. +# Note - create separate "inherit" executable from misc.cc + +set testfile "inherit-hp" +set srcfile misc-hp.cc +set binfile ${objdir}/${subdir}/${testfile} + +if [get_compiler_info ${binfile} "c++"] { + return -1; +} + + +if {[skip_hp_tests $gcc_compiled]} then { continue } + + +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } { + gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail." +} + +# +# Single inheritance, print individual members. +# + +proc test_print_si_members {} { + # Print all members of g_A using fully qualified form. + + gdb_test "print g_A.A::a" ".* = 1" "print g_A.A::a" + + gdb_test "print g_A.A::x" ".* = 2" "print g_A.A::x" + + # Print members of g_A using nonambiguous compact form. + + gdb_test "print g_A.a" ".* = 1" "print g_A.a" + + gdb_test "print g_A.x" ".* = 2" "print g_A.x" + + # Print all members of g_B using fully qualified form. + + gdb_test "print g_B.A::a" ".* = 3" "print g_B.A::a" + + gdb_test "print g_B.A::x" ".* = 4" "print g_B.A::x" + + gdb_test "print g_B.B::b" ".* = 5" "print g_B.B::b" + + gdb_test "print g_B.B::x" ".* = 6" "print g_B.B::x" + + # Print members of g_B using nonambiguous compact form. + + setup_xfail_format "DWARF 1" + gdb_test "print g_B.a" ".* = 3" "print g_B.a" + + gdb_test "print g_B.b" ".* = 5" "print g_B.b" + + gdb_test "print g_B.x" ".* = 6" "print g_B.x" + + # Print all members of g_C using fully qualified form. + + gdb_test "print g_C.A::a" ".* = 7" "print g_C.A::a" + + gdb_test "print g_C.A::x" ".* = 8" "print g_C.A::x" + + gdb_test "print g_C.C::c" ".* = 9" "print g_C.C::c" + + gdb_test "print g_C.C::x" ".* = 10" "print g_C.C::x" + + # Print members of g_C using nonambiguous compact form. + + setup_xfail_format "DWARF 1" + gdb_test "print g_C.a" ".* = 7" "print g_C.a" + + gdb_test "print g_C.c" ".* = 9" "print g_C.c" + + gdb_test "print g_C.x" ".* = 10" "print g_C.x" +} + +# +# Single inheritance, print type definitions. +# + +proc test_ptype_si {} { + global gdb_prompt + global ws + + # Print class A as a type. + + send_gdb "ptype A\n" + gdb_expect { + -re "type = class A \{\r\n.*\[ \]*int a;\r\n\[ \]*int x;\r\n.*\[ \]*\}\r\n$gdb_prompt $" { + pass "ptype A (FIXME)" + } + -re "type = struct A \{\r\n\[ \]*int a;\r\n\[ \]*int x;\r\n\[ \]*\}\r\n$gdb_prompt $" { + setup_xfail "*-*-*" + fail "ptype A (FIXME)" + } + -re ".*$gdb_prompt $" { fail "ptype A" } + timeout { fail "ptype A (timeout)" ; return } + } + + # Print class A as an explicit class. + + send_gdb "ptype class A\n" + gdb_expect { + -re "type = class A \{\r\n.*\[ \]*int a;\r\n\[ \]*int x;\r\n.*\[ \]*\}\r\n$gdb_prompt $" { + pass "ptype class A (FIXME)" + } + -re "type = struct A \{\r\n\[ \]*int a;\r\n\[ \]*int x;\r\n\[ \]*\}\r\n$gdb_prompt $" { + setup_xfail "*-*-*" + fail "ptype class A (FIXME)" + } + -re ".*$gdb_prompt $" { fail "ptype class A" } + timeout { fail "ptype class A (timeout)" ; return } + } + + # Print type of an object of type A. + + send_gdb "ptype g_A\n" + gdb_expect { + -re "type = class A \{\r\n.*\[ \]*int a;\r\n\[ \]*int x;\r\n.*\[ \]*\}\r\n$gdb_prompt $" { + pass "ptype g_A (FIXME)" + } + -re "type = struct A \{\r\n\[ \]*int a;\r\n\[ \]*int x;\r\n\[ \]*\}\r\n$gdb_prompt $" { + setup_xfail "*-*-*" + fail "ptype g_A (FIXME)" + } + -re ".*$gdb_prompt $" { fail "ptype g_A" } + timeout { fail "ptype g_A (timeout)" ; return } + } + + # Print class B as a type. + + setup_xfail_format "DWARF 1" + gdb_test "ptype B" "type = class B : public A \{\r\n\[ \]*public:\r\n\[ \]*int b;\r\n\[ \]*int x;\r\n.*\}" "ptype B" + + # Print class B as an explicit class. + + setup_xfail_format "DWARF 1" + gdb_test "ptype class B" "type = class B : public A \{\r\n\[ \]*public:\r\n\[ \]*int b;\r\n\[ \]*int x;\r\n.*\}" "ptype class B" + + # Print type of an object of type B. + + setup_xfail_format "DWARF 1" + gdb_test "ptype g_B" "type = class B : public A \{\r\n\[ \]*public:\r\n\[ \]*int b;\r\n\[ \]*int x;\r\n.*\}" "ptype g_B" + + # Print class C as a type. + + setup_xfail_format "DWARF 1" + gdb_test "ptype C" "type = class C : public A \{\r\n\[ \]*public:\r\n\[ \]*int c;\r\n\[ \]*int x;\r\n.*\}" "ptype C" + + # Print class C as an explicit class. + + setup_xfail_format "DWARF 1" + gdb_test "ptype class C" "type = class C : public A \{\r\n\[ \]*public:\r\n\[ \]*int c;\r\n\[ \]*int x;\r\n.*\}" "ptype class C" + + # Print type of an object of type g_C. + + setup_xfail_format "DWARF 1" + gdb_test "ptype g_C" "type = class C : public A \{\r\n\[ \]*public:\r\n\[ \]*int c;\r\n\[ \]*int x;\r\n.*\}" "ptype g_C" + + # gcc cygnus-2.3.3 (Q1) has this bug, but it was fixed as of + # cygnus-2.3.3-930417. PR 2819. + send_gdb "ptype tagless_struct\n" + gdb_expect { + -re "type = class \{${ws}public:${ws}int one;${ws}int two;${ws}tagless_struct & operator=\\(tagless_struct &\\);${ws}\\\$_1 \\(tagless_struct &\\);${ws}\\\$_1 \\(\\);${ws}\}\r\n$gdb_prompt $" { + pass "ptype tagless struct" + } + -re "type = (struct|class).*\{.*int one;.*int two;.*\}\r\n$gdb_prompt $" { + pass "ptype tagless struct (obsolete gcc or gdb)" + } + -re ".*$gdb_prompt $" { + fail "ptype tagless struct" + } + timeout { + fail "ptype tagless struct (timeout)" + } + } + + send_gdb "ptype v_tagless\n" + gdb_expect { + -re "type = class \{${ws}public:${ws}int one;${ws}int two;${ws}tagless_struct & operator=\\(tagless_struct &\\);${ws}\\\$_1 \\(tagless_struct &\\);${ws}\\\$_1 \\(\\);${ws}\}\r\n$gdb_prompt $" { + pass "ptype variable of type tagless struct" + } + -re "type = (struct|class).*\{.*int one;.*int two;.*\}\r\n$gdb_prompt $" { + pass "ptype variable of type tagless struct (obsolete gcc or gdb)" + } + -re ".*$gdb_prompt $" { + fail "ptype variable of type tagless struct" + } + timeout { + fail "ptype variable of type tagless struct (timeout)" + } + } +} + +# +# Single inheritance, print complete classes. +# + +proc test_print_si_classes {} { + # Print all members of g_A. + + gdb_test "print g_A" ".* = \{a = 1, x = 2\}" "print g_A" + + # Print all members of g_B. + + setup_xfail_format "DWARF 1" + gdb_test "print g_B" ".* = \{\<class A\> = \{a = 3, x = 4\}, b = 5, x = 6\}" "print g_B" + + # Print all members of g_C. + + setup_xfail_format "DWARF 1" + gdb_test "print g_C" ".* = \{\<class A\> = \{a = 7, x = 8\}, c = 9, x = 10\}" "print g_C" +} + +# +# Single inheritance, print anonymous unions. +# GDB versions prior to 4.14 entered an infinite loop when printing +# the type of a class containing an anonymous union, and they were also +# incapable of printing the member of an anonymous union. +# We test the printing of the member first, and perform the other tests +# only if the test succeeds, to avoid the infinite loop. +# + +proc test_print_anon_union {} { + global gdb_prompt + global ws + + setup_xfail_format "DWARF 1" + gdb_test "print g_anon_union.a" ".* = 2" "print anonymous union member" + setup_xfail_format "DWARF 1" + send_gdb "print g_anon_union\n" + gdb_expect { + -re ".* = \{one = 1, \{a = 2, b = 2\}\}\r\n$gdb_prompt $" { + pass "print variable of type anonymous union" + } + -re ".* = .*\{one = 1, = \{a = 2, b = .*\}\}\r\n$gdb_prompt $" { + pass "print variable of type anonymous union (obsolete gcc or gdb)" + } + -re ".*\r\n$gdb_prompt $" { + fail "print variable of type anonymous union" + } + timeout { + fail "print variableof type anonymous union (timeout)" + } + } + setup_xfail_format "DWARF 1" + send_gdb "ptype g_anon_union\n" + gdb_expect { + -re "type = class class_with_anon_union \{${ws}public:${ws}int one;${ws}union \{${ws}public:${ws}int a;${ws}long int b;${ws}union \{\.\.\.\} & operator=\\(union \{\.\.\.\} &\\);${ws}\\\$_0 \\(union \{\.\.\.\} &\\);${ws}\\\$_0 \\(\\);${ws}\};${ws}class_with_anon_union & operator=\\(class_with_anon_union const &\\);${ws}class_with_anon_union\\(class_with_anon_union const &\\);${ws}class_with_anon_union\\(void\\);${ws}\}\r\n$gdb_prompt $" { + pass "print type of anonymous union" + } + -re "type = (struct|class).*\{.*int one;.*union \{.*int a;.*(long|long int|int) b;.*\};.*\}\r\n$gdb_prompt $" { + pass "print type of anonymous union (obsolete gcc or gdb)" + } + -re ".*\r\n$gdb_prompt $" { + fail "print type of anonymous union" + } + timeout { + fail "print type of anonymous union (timeout)" + } + } +} + +# +# Multiple inheritance, print individual members. +# + +proc test_print_mi_members {} { + global gdb_prompt + + # Print all members of g_A. + + gdb_test "print g_A.A::a" ".* = 1" "print g_A.A::a" + + gdb_test "print g_A.A::x" ".* = 2" "print g_A.A::x" + + # Print all members of g_B. + + gdb_test "print g_B.A::a" ".* = 3" "print g_B.A::a" + + gdb_test "print g_B.A::x" ".* = 4" "print g_B.A::x" + + gdb_test "print g_B.B::b" ".* = 5" "print g_B.B::b" + + gdb_test "print g_B.B::x" ".* = 6" "print g_B.B::x" + + # Print all members of g_C. + + gdb_test "print g_C.A::a" ".* = 7" "print g_C.A::a" + + gdb_test "print g_C.A::x" ".* = 8" "print g_C.A::x" + + gdb_test "print g_C.C::c" ".* = 9" "print g_C.C::c" + + gdb_test "print g_C.C::x" ".* = 10" "print g_C.C::x" + + # Print all members of g_D. + + # The following is ambiguous, and gdb should detect this. + # For now, accept gdb's behavior as an expected failure if it + # simply prints either member correctly. + + # setup_xfail "*-*-*" + send_gdb "print g_D.A::a\n" + gdb_expect { + -re "warning: A ambiguous; using D::B::A. Use a cast to disambiguate.\r\n\\$\[0-9\]* = 11\r\n$gdb_prompt $" { + pass "print g_D.A::a" + } + -re ".* = 15\r\n$gdb_prompt $" { + fail "print g_D.A::a (did GDB's algorithm change?)" + } + -re ".* = 11\r\n$gdb_prompt $" { + fail "print g_D.A::a (ambiguity not reported)" + } + -re ".*$gdb_prompt $" { fail "print g_D.A::a" } + timeout { fail "print g_D.A::a (timeout)" ; return } + } + + # The following is ambiguous, and gdb should detect this. + # For now, accept gdb's behavior as an expected failure if it + # simply prints either member correctly. + + # setup_xfail "*-*-*" + send_gdb "print g_D.A::x\n" + gdb_expect { + -re "warning: A ambiguous; using D::B::A. Use a cast to disambiguate.\r\n\\$\[0-9\]* = 12\r\n$gdb_prompt $" { + pass "print g_D.A::x" + } + -re ".* = 16\r\n$gdb_prompt $" { + fail "print g_D.A::x (did GDB's algorithm change?)" + } + -re ".* = 12\r\n$gdb_prompt $" { + fail "print g_D.A::x (ambiguity not reported)" + } + -re ".*$gdb_prompt $" { fail "print g_D.A::x" } + timeout { fail "print g_D.A::x (timeout)" ; return } + } + + gdb_test "print g_D.B::b" ".* = 13" "print g_D.B::b" + + gdb_test "print g_D.B::x" ".* = 14" "print g_D.B::x" + + setup_xfail_format "DWARF 1" + gdb_test "print g_D.C::c" ".* = 17" "print g_D.C::c" + + setup_xfail_format "DWARF 1" + gdb_test "print g_D.C::x" ".* = 18" "print g_D.C::x" + + gdb_test "print g_D.D::d" ".* = 19" "print g_D.D::d" + + gdb_test "print g_D.D::x" ".* = 20" "print g_D.D::x" + + # Print all members of g_E. + + # The following is ambiguous, and gdb should detect this. + # For now, accept gdb's behavior as an expected failure if it + # simply prints either member correctly. + + #setup_xfail "*-*-*" + send_gdb "print g_E.A::a\n" + gdb_expect { + -re "warning: A ambiguous; using E::D::B::A. Use a cast to disambiguate.\r\n\\$\[0-9\]* = 21\r\n$gdb_prompt $" { + pass "print g_E.A::a" + } + -re ".* = 25\r\n$gdb_prompt $" { + fail "print g_E.A::a (did GDB's algorithm change?)" + } + -re ".* = 21\r\n$gdb_prompt $" { + fail "print g_E.A::a (ambiguity not reported)" + } + -re ".*$gdb_prompt $" { fail "print g_E.A::a" } + timeout { fail "print g_E.A::a (timeout)" ; return } + } + + # The following is ambiguous, and gdb should detect this. + # For now, accept gdb's behavior as an expected failure if it + # simply prints either member correctly. + + # setup_xfail "*-*-*" + send_gdb "print g_E.A::x\n" + gdb_expect { + -re "warning: A ambiguous; using E::D::B::A. Use a cast to disambiguate.\r\n\\$\[0-9\]* = 22\r\n$gdb_prompt $" { + pass "print g_E.A::x" + } + -re ".* = 26\r\n$gdb_prompt $" { + fail "print g_E.A::x (did GDB's algorithm change?)" + } + -re ".* = 22\r\n$gdb_prompt $" { + fail "print g_E.A::x (ambiguity not reported)" + } + -re ".*$gdb_prompt $" { fail "print g_E.A::x" } + timeout { fail "print g_E.A::x (timeout)" ; return } + } + + gdb_test "print g_E.B::b" ".* = 23" "print g_E.B::b" + + gdb_test "print g_E.B::x" ".* = 24" "print g_E.B::x" + + setup_xfail_format "DWARF 1" + gdb_test "print g_E.C::c" ".* = 27" "print g_E.C::c" + + setup_xfail_format "DWARF 1" + gdb_test "print g_E.C::x" ".* = 28" "print g_E.C::x" + + gdb_test "print g_E.D::d" ".* = 29" "print g_E.D::d" + + gdb_test "print g_E.D::x" ".* = 30" "print g_E.D::x" + + gdb_test "print g_E.E::e" ".* = 31" "print g_E.E::e" + + gdb_test "print g_E.E::x" ".* = 32" "print g_E.E::x" +} + +# +# Multiple inheritance, print type definitions. +# + +proc test_ptype_mi {} { + setup_xfail_format "DWARF 1" + gdb_test "ptype D" "type = class D : public B, public C \{\r\n\[ \]*public:\r\n\[ \]*int d;\r\n\[ \]*int x;\r\n.*\}" "ptype D" + + setup_xfail_format "DWARF 1" + gdb_test "ptype class D" "type = class D : public B, public C \{\r\n\[ \]*public:\r\n\[ \]*int d;\r\n\[ \]*int x;\r\n.*\}" "ptype class D" + + setup_xfail_format "DWARF 1" + gdb_test "ptype g_D" "type = class D : public B, public C \{\r\n\[ \]*public:\r\n\[ \]*int d;\r\n\[ \]*int x;\r\n.*\}" "ptype g_D" + + setup_xfail_format "DWARF 1" + gdb_test "ptype E" "type = class E : public D \{\r\n\[ \]*public:\r\n\[ \]*int e;\r\n\[ \]*int x;\r\n.*\}" "ptype E" + + setup_xfail_format "DWARF 1" + gdb_test "ptype class E" "type = class E : public D \{\r\n\[ \]*public:\r\n\[ \]*int e;\r\n\[ \]*int x;\r\n.*\}" "ptype class E" + + setup_xfail_format "DWARF 1" + gdb_test "ptype g_E" "type = class E : public D \{\r\n\[ \]*public:\r\n\[ \]*int e;\r\n\[ \]*int x;\r\n.*\}" "ptype g_E" +} + +# +# Multiple inheritance, print complete classes. +# + +proc test_print_mi_classes {} { + # Print all members of g_D. + + setup_xfail_format "DWARF 1" + gdb_test "print g_D" ".* = \{\<class B\> = \{\<class A\> = \{a = 11, x = 12\}, b = 13, x = 14\}, \<class C\> = \{\<class A\> = \{a = 15, x = 16\}, c = 17, x = 18\}, d = 19, x = 20\}" "print g_D" + + # Print all members of g_E. + + setup_xfail_format "DWARF 1" + gdb_test "print g_E" ".* = \{\<class D\> = \{\<class B\> = \{\<class A\> = \{a = 21, x = 22\}, b = 23, x = 24\}, \<class C\> = \{\<class A\> = \{a = 25, x = 26\}, c = 27, x = 28\}, d = 29, x = 30\}, e = 31, x = 32\}" "print g_E" +} + +# +# Single virtual inheritance, print individual members. +# + +proc test_print_svi_members {} { + global gdb_prompt + global decimal + + # Print all members of g_vA. + + gdb_test "print g_vA.vA::va" ".* = 1" "print g_vA.vA::va" + + gdb_test "print g_vA.vA::vx" ".* = 2" "print g_vA.vA::vx" + + # Print members of g_vA using compact form. + + gdb_test "print g_vA.va" ".* = 1" "print g_vA.va" + + gdb_test "print g_vA.vx" ".* = 2" "print g_vA.vx" + + # Print all members of g_vB. + + setup_xfail_format "DWARF 1" + send_gdb "print g_vB.vA::va\n" + gdb_expect { + -re ".* = 3\r\n$gdb_prompt $" { pass "print g_vB.vA::va" } + -re ".*virtual baseclass botch.*$gdb_prompt $" { + # Does not happen with gcc cygnus-2.4.5-930828 + fail "print g_vB.vA::va (known bug with gcc cygnus-2.4.5-930417)" + # Many of the rest of these tests have the same problem. + return 0 + } + -re ".*$gdb_prompt $" { fail "print g_vB.vA::va" } + timeout { fail "print g_vB.vA::va (timeout)" ; return } + } + + setup_xfail_format "DWARF 1" + gdb_test "print g_vB.vA::vx" ".* = 4" "print g_vB.vA::vx" + + gdb_test "print g_vB.vB::vb" ".* = 5" "print g_vB.vB::vb" + + gdb_test "print g_vB.vB::vx" ".* = 6" "print g_vB.vB::vx" + + # Print members of g_vB using compact form. + + setup_xfail_format "DWARF 1" + gdb_test "print g_vB.va" ".* = 3" "print g_vB.va" + + gdb_test "print g_vB.vb" ".* = 5" "print g_vB.vb" + + gdb_test "print g_vB.vx" ".* = 6" "print g_vB.vx" + + # Print all members of g_vC. + + setup_xfail_format "DWARF 1" + gdb_test "print g_vC.vA::va" ".* = 7" "print g_vC.vA::va" + + setup_xfail_format "DWARF 1" + gdb_test "print g_vC.vA::vx" ".* = 8" "print g_vC.vA::vx" + + gdb_test "print g_vC.vC::vc" ".* = 9" "print g_vC.vC::vc" + + gdb_test "print g_vC.vC::vx" ".* = 10" "print g_vC.vC::vx" + + # Print members of g_vC using compact form. + + setup_xfail_format "DWARF 1" + gdb_test "print g_vC.va" ".* = 7" "print g_vC.va" + + gdb_test "print g_vC.vc" ".* = 9" "print g_vC.vc" + + gdb_test "print g_vC.vx" ".* = 10" "print g_vC.vx" +} + +# +# Single virtual inheritance, print type definitions. +# + +proc test_ptype_vi {} { + global gdb_prompt + + # This class does not use any C++-specific features, so it's fine for + # it to print as "struct". + send_gdb "ptype vA\n" + gdb_expect { + -re "type = class vA \{\[\r\n\]+\[ \]*public:\[\r\n\]+\[ \]*int va;\[\r\n\]+\[ \]*int vx;\[\r\n\]+.*\}\[\r\n\]+$gdb_prompt $" { + pass "ptype vA" + } + -re "type = struct vA \{\[\r\n\]+\[ \]*int va;\[\r\n\]+\[ \]*int vx;\[\r\n\]+\}\[\r\n\]+$gdb_prompt $" { + pass "ptype vA" + } + -re ".*$gdb_prompt $" { fail "ptype vA" } + timeout { fail "ptype vA (timeout)" ; return } + } + + # This class does not use any C++-specific features, so it's fine for + # it to print as "struct". + send_gdb "ptype class vA\n" + gdb_expect { + -re "type = class vA \{\[\r\n\]+\[ \]*public:\[\r\n\]+\[ \]*int va;\[\r\n\]+\[ \]*int vx;\[\r\n\]+.*\}\[\r\n\]+$gdb_prompt $" { + pass "ptype class vA" + } + -re "type = struct vA \{\[\r\n\]+\[ \]*int va;\[\r\n\]+\[ \]*int vx;\[\r\n\]+\}\[\r\n\]+$gdb_prompt $" { + pass "ptype class vA" + } + -re ".*$gdb_prompt $" { fail "ptype class vA" } + timeout { fail "ptype class vA (timeout)" ; return } + } + + # This class does not use any C++-specific features, so it's fine for + # it to print as "struct". + send_gdb "ptype g_vA\n" + gdb_expect { + -re "type = class vA \{\[\r\n\]+\[ \]*public:\[\r\n\]+\[ \]*int va;\[\r\n\]+\[ \]*int vx;\[\r\n\]+.*\}\[\r\n\]+$gdb_prompt $" { + pass "ptype g_vA" + } + -re "type = struct vA \{\[\r\n\]+\[ \]*int va;\[\r\n\]+\[ \]*int vx;\[\r\n\]+\}\[\r\n\]+$gdb_prompt $" { + pass "ptype g_vA" + } + -re ".*$gdb_prompt $" { fail "ptype g_vA" } + timeout { fail "ptype g_vA (timeout)" ; return } + } + + setup_xfail_format "DWARF 1" + gdb_test "ptype vB" "ptype vB\[\r\n\]+type = class vB : public virtual vA \{\[\r\n\]+ public:\r\n\[ \]+int vb;\r\n\[ \]+int vx;\r\n.*\}" "ptype vB (aCC)" + + setup_xfail_format "DWARF 1" + gdb_test "ptype class vB" "type = class vB : public virtual vA \{\r\n\[ \]*public:\r\n\[ \]*int vb;\r\n\[ \]*int vx;\r\n.*\}" "ptype class vB (aCC)" + + setup_xfail_format "DWARF 1" + gdb_test "ptype g_vB" "type = class vB : public virtual vA \{\r\n\[ \]*public:\r\n\[ \]*int vb;\r\n\[ \]*int vx;\r\n.*\}" "ptype g_vB (aCC)" + + setup_xfail_format "DWARF 1" + gdb_test "ptype vC" "type = class vC : public virtual vA \{\r\n\[ \]*public:\r\n\[ \]*int vc;\r\n\[ \]*int vx;\r\n.*\}" "ptype vC (aCC)" + + setup_xfail_format "DWARF 1" + gdb_test "ptype class vC" "type = class vC : public virtual vA \{\r\n\[ \]*public:\r\n\[ \]*int vc;\r\n\[ \]*int vx;\r\n.*\}" "ptype class vC (aCC)" + + setup_xfail_format "DWARF 1" + gdb_test "ptype g_vC" "type = class vC : public virtual vA \{\r\n\[ \]*public:\r\n\[ \]*int vc;\r\n\[ \]*int vx;\r\n.*\}" "ptype g_vC (aCC)" +} + +# +# Single virtual inheritance, print complete classes. +# + +proc test_print_svi_classes {} { + global gdb_prompt + global hex + global decimal + + # Print all members of g_vA. + + gdb_test "print g_vA" ".* = \{va = 1, vx = 2\}" "print g_vA" + + # Print all members of g_vB. + + setup_xfail_format "DWARF 1" + send_gdb "print g_vB\n" + gdb_expect { + -re ".* = \{\<class vA\> = \{va = 3, vx = 4\}, vb = 5, vx = 6, Virtual table at $hex\}\r\n$gdb_prompt $" { + pass "print g_vB" + } + -re ".*invalid address 0x0.*$gdb_prompt $" { + # Does not happen with gcc cygnus-2.4.5-930828 + fail "print g_vB (known bug with gcc cygnus-2.4.5-930417)" + # Many of the rest of these tests have the same problem. + return 0 + } + -re ".*$gdb_prompt $" { fail "print g_vB" } + timeout { fail "print g_vB (timeout)" ; return } + } + + # Print all members of g_vC. + + setup_xfail_format "DWARF 1" + gdb_test "print g_vC" ".* = \{\<class vA\> = \{va = 7, vx = 8\}, vc = 9, vx = 10, Virtual table at $hex\}" "print g_vC" +} + +# +# Multiple virtual inheritance, print individual members. +# + +proc test_print_mvi_members {} { + global gdb_prompt + global decimal + + # Print all members of g_vD. + + setup_xfail_format "DWARF 1" + send_gdb "print g_vD.vA::va\n" + gdb_expect { + -re ".* = 19\r\n$gdb_prompt $" { pass "print g_vD.vA::va" } + -re ".*virtual baseclass botch.*$gdb_prompt $" { + # Does not happen with gcc cygnus-2.4.5-930828 + fail "print g_vD.vA::va (known bug with gcc cygnus-2.4.5-930417)" + # Many of the rest of these tests have the same problem. + return 0 + } + -re ".*$gdb_prompt $" { fail "print g_vD.vA::va" } + timeout { fail "print g_vD.vA::va (timeout)" ; return } + } + + setup_xfail_format "DWARF 1" + gdb_test "print g_vD.vA::vx" ".* = 20" "print g_vD.vA::vx" + + setup_xfail_format "DWARF 1" + gdb_test "print g_vD.vB::vb" ".* = 21" "print g_vD.vB::vb" + + setup_xfail_format "DWARF 1" + gdb_test "print g_vD.vB::vx" ".* = 22" "print g_vD.vB::vx" + + setup_xfail_format "DWARF 1" + gdb_test "print g_vD.vC::vc" ".* = 23" "print g_vD.vC::vc" + + setup_xfail_format "DWARF 1" + gdb_test "print g_vD.vC::vx" ".* = 24" "print g_vD.vC::vx" + + gdb_test "print g_vD.vD::vd" ".* = 25" "print g_vD.vD::vd" + + gdb_test "print g_vD.vD::vx" ".* = 26" "print g_vD.vD::vx" + + # Print all members of g_vE. + + setup_xfail_format "DWARF 1" + gdb_test "print g_vE.vA::va" ".* = 0" "print g_vE.vA::va" + + setup_xfail_format "DWARF 1" + gdb_test "print g_vE.vA::vx" ".* = 0" "print g_vE.vA::vx" + + setup_xfail_format "DWARF 1" + gdb_test "print g_vE.vB::vb" ".* = 0" "print g_vE.vB::vb" + + setup_xfail_format "DWARF 1" + gdb_test "print g_vE.vB::vx" ".* = 0" "print g_vE.vB::vx" + + setup_xfail_format "DWARF 1" + gdb_test "print g_vE.vC::vc" ".* = 0" "print g_vE.vC::vc" + + setup_xfail_format "DWARF 1" + gdb_test "print g_vE.vC::vx" ".* = 0" "print g_vE.vC::vx" + + setup_xfail_format "DWARF 1" + gdb_test "print g_vE.vD::vd" ".* = 0" "print g_vE.vD::vd" + + gdb_test "print g_vE.vD::vx" ".* = 0" "print g_vE.vD::vx" + + gdb_test "print g_vE.vE::ve" ".* = 27" "print g_vE.vE::ve" + + gdb_test "print g_vE.vE::vx" ".* = 28" "print g_vE.vE::vx" +} + +# +# Multiple virtual inheritance, print type definitions. +# + +proc test_ptype_mvi {} { + setup_xfail_format "DWARF 1" + gdb_test "ptype vD" "type = class vD : public virtual vB, public virtual vC \{\r\n\[ \]*public:\r\n\[ \]*int vd;\r\n\[ \]*int vx;\r\n.*\}" "ptype vD (aCC)" + + setup_xfail_format "DWARF 1" + gdb_test "ptype class vD" "type = class vD : public virtual vB, public virtual vC \{\r\n\[ \]*public:\r\n\[ \]*int vd;\r\n\[ \]*int vx;\r\n.*\}" "ptype class vD (aCC)" + + setup_xfail_format "DWARF 1" + gdb_test "ptype g_vD" "type = class vD : public virtual vB, public virtual vC \{\r\n\[ \]*public:\r\n\[ \]*int vd;\r\n\[ \]*int vx;\r\n.*\}" "ptype g_vD (aCC)" + + setup_xfail_format "DWARF 1" + gdb_test "ptype vE" "type = class vE : public virtual vD \{\r\n\[ \]*public:\r\n\[ \]*int ve;\r\n\[ \]*int vx;\r\n.*\}" "ptype vE (aCC)" + + setup_xfail_format "DWARF 1" + gdb_test "ptype class vE" "type = class vE : public virtual vD \{\r\n\[ \]*public:\r\n\[ \]*int ve;\r\n\[ \]*int vx;\r\n.*\}" "ptype class vE (aCC)" + + setup_xfail_format "DWARF 1" + gdb_test "ptype g_vE" "type = class vE : public virtual vD \{\r\n\[ \]*public:\r\n\[ \]*int ve;\r\n\[ \]*int vx;\r\n.*\}" "ptype g_vE (aCC)" +} + +# +# Multiple virtual inheritance, print complete classes. +# + +proc test_print_mvi_classes {} { + global gdb_prompt + global hex + global decimal + + # Print all members of g_vD. + + setup_xfail_format "DWARF 1" + send_gdb "print g_vD\n" + gdb_expect { + -re ".* = \{\<class vB\> = \{\<class vA\> = \{va = 19, vx = 20\}, vb = 21, vx = 22, Virtual table at $hex\}, \<class vC\> = \{vc = 23, vx = 24, Virtual table at $hex\}, vd = 25, vx = 26, Virtual table at $hex\}\r\n$gdb_prompt $" { + pass "print g_vD" + } + -re ".*invalid address 0x0.*$gdb_prompt $" { + # Does not happen with gcc cygnus-2.4.5-930828 + fail "print g_vD (known bug with gcc cygnus-2.4.5-930417)" + # Many of the rest of these tests have the same problem. + return 0 + } + -re ".*$gdb_prompt $" { fail "print g_vD" } + timeout { fail "print g_vD (timeout)" ; return } + } + + # Print all members of g_vE. + + setup_xfail_format "DWARF 1" + gdb_test "print g_vE" ".* = \{\<class vD\> = \{\<class vB\> = \{\<class vA\> = \{va = 0, vx = 0\}, vb = 0, vx = 0, Virtual table at $hex\}, \<class vC\> = \{vc = 0, vx = 0, Virtual table at $hex\}, vd = 0, vx = 0, Virtual table at $hex\}, ve = 27, vx = 28, Virtual table at $hex\}" "print g_vE" +} + +proc do_tests {} { + global prms_id + global bug_id + global subdir + global objdir + global srcdir + global binfile + + set prms_id 0 + set bug_id 0 + + # Start with a fresh gdb. + + gdb_exit + gdb_start + gdb_reinitialize_dir $srcdir/$subdir + gdb_load $binfile + + gdb_test "set language c++" "" + gdb_test "set width 0" "" + + # Get the debug format for the compiled test case. + + if { ![ runto_main] } { + gdb_suppress_tests; + } else { + get_debug_format + } + + test_ptype_si + test_ptype_mi + test_ptype_vi + test_ptype_mvi + + gdb_stop_suppressing_tests; + + if { ![ runto 'inheritance2(void)' ] } { + gdb_suppress_tests; + } + + test_print_si_members + test_print_si_classes + test_print_mi_members + test_print_mi_classes + test_print_anon_union + + gdb_stop_suppressing_tests; + + if { ![ runto 'inheritance4(void)' ] } { + gdb_suppress_tests; + } + + test_print_svi_members + test_print_svi_classes + test_print_mvi_members + test_print_mvi_classes +} + +do_tests diff --git a/gdb/testsuite/gdb.hp/misc-hp.cc b/gdb/testsuite/gdb.hp/misc-hp.cc new file mode 100644 index 00000000000..af46830601c --- /dev/null +++ b/gdb/testsuite/gdb.hp/misc-hp.cc @@ -0,0 +1,514 @@ +// Test various -*- C++ -*- things. + +typedef struct fleep fleep; +struct fleep { int a; } s; + +// ====================== simple class structures ======================= + +struct default_public_struct { + // defaults to public: + int a; + int b; +}; + +struct explicit_public_struct { + public: + int a; + int b; +}; + +struct protected_struct { + protected: + int a; + int b; +}; + +struct private_struct { + private: + int a; + int b; +}; + +struct mixed_protection_struct { + public: + int a; + int b; + private: + int c; + int d; + protected: + int e; + int f; + public: + int g; + private: + int h; + protected: + int i; +}; + +class public_class { + public: + int a; + int b; +}; + +class protected_class { + protected: + int a; + int b; +}; + +class default_private_class { + // defaults to private: + int a; + int b; +}; + +class explicit_private_class { + private: + int a; + int b; +}; + +class mixed_protection_class { + public: + int a; + int b; + private: + int c; + int d; + protected: + int e; + int f; + public: + int g; + private: + int h; + protected: + int i; +}; + +class const_vol_method_class { +public: + int a; + int b; + int foo (int &) const; + int bar (int &) volatile; + int baz (int &) const volatile; +}; + +int const_vol_method_class::foo (int & ir) const +{ + return ir + 3; +} +int const_vol_method_class::bar (int & ir) volatile +{ + return ir + 4; +} +int const_vol_method_class::baz (int & ir) const volatile +{ + return ir + 5; +} + +// ========================= simple inheritance ========================== + +class A { + public: + int a; + int x; +}; + +A g_A; + +class B : public A { + public: + int b; + int x; +}; + +B g_B; + +class C : public A { + public: + int c; + int x; +}; + +C g_C; + +class D : public B, public C { + public: + int d; + int x; +}; + +D g_D; + +class E : public D { + public: + int e; + int x; +}; + +E g_E; + +class class_with_anon_union +{ + public: + int one; + union + { + int a; + long b; + }; +}; + +class_with_anon_union g_anon_union; + +void inheritance2 (void) +{ +} + +void inheritance1 (void) +{ + int ival; + int *intp; + + // {A::a, A::x} + + g_A.A::a = 1; + g_A.A::x = 2; + + // {{A::a,A::x},B::b,B::x} + + g_B.A::a = 3; + g_B.A::x = 4; + g_B.B::b = 5; + g_B.B::x = 6; + + // {{A::a,A::x},C::c,C::x} + + g_C.A::a = 7; + g_C.A::x = 8; + g_C.C::c = 9; + g_C.C::x = 10; + + // {{{A::a,A::x},B::b,B::x},{{A::a,A::x},C::c,C::x},D::d,D::x} + + // The following initialization code is non-portable, but allows us + // to initialize all members of g_D until we can fill in the missing + // initialization code with legal C++ code. + + for (intp = (int *) &g_D, ival = 11; + intp < ((int *) &g_D + sizeof (g_D) / sizeof (int)); + intp++, ival++) + { + *intp = ival; + } + + // Overlay the nonportable initialization with legal initialization. + + // ????? = 11; (g_D.A::a = 11; is ambiguous) + // ????? = 12; (g_D.A::x = 12; is ambiguous) + g_D.B::b = 13; + g_D.B::x = 14; + // ????? = 15; + // ????? = 16; + g_D.C::c = 17; + g_D.C::x = 18; + g_D.D::d = 19; + g_D.D::x = 20; + + + // {{{{A::a,A::x},B::b,B::x},{{A::a,A::x},C::c,C::x},D::d,D::x}},E::e,E::x} + + // The following initialization code is non-portable, but allows us + // to initialize all members of g_D until we can fill in the missing + // initialization code with legal C++ code. + + for (intp = (int *) &g_E, ival = 21; + intp < ((int *) &g_E + sizeof (g_E) / sizeof (int)); + intp++, ival++) + { + *intp = ival; + } + + // Overlay the nonportable initialization with legal initialization. + + // ????? = 21; (g_E.A::a = 21; is ambiguous) + // ????? = 22; (g_E.A::x = 22; is ambiguous) + g_E.B::b = 23; + g_E.B::x = 24; + // ????? = 25; + // ????? = 26; + g_E.C::c = 27; + g_E.C::x = 28; + g_E.D::d = 29; + g_E.D::x = 30; + g_E.E::e = 31; + g_E.E::x = 32; + + g_anon_union.one = 1; + g_anon_union.a = 2; + + inheritance2 (); +} + +// ======================== virtual base classes========================= + +class vA { + public: + int va; + int vx; +}; + +vA g_vA; + +class vB : public virtual vA { + public: + int vb; + int vx; +}; + +vB g_vB; + +class vC : public virtual vA { + public: + int vc; + int vx; +}; + +vC g_vC; + +class vD : public virtual vB, public virtual vC { + public: + int vd; + int vx; +}; + +vD g_vD; + +class vE : public virtual vD { + public: + int ve; + int vx; +}; + +vE g_vE; + +void inheritance4 (void) +{ +} + +void inheritance3 (void) +{ + int ival; + int *intp; + + // {vA::va, vA::vx} + + g_vA.vA::va = 1; + g_vA.vA::vx = 2; + + // {{vA::va, vA::vx}, vB::vb, vB::vx} + + g_vB.vA::va = 3; + g_vB.vA::vx = 4; + g_vB.vB::vb = 5; + g_vB.vB::vx = 6; + + // {{vA::va, vA::vx}, vC::vc, vC::vx} + + g_vC.vA::va = 7; + g_vC.vA::vx = 8; + g_vC.vC::vc = 9; + g_vC.vC::vx = 10; + + // {{{{vA::va, vA::vx}, vB::vb, vB::vx}, vC::vc, vC::vx}, vD::vd,vD::vx} + + g_vD.vA::va = 11; + g_vD.vA::vx = 12; + g_vD.vB::vb = 13; + g_vD.vB::vx = 14; + g_vD.vC::vc = 15; + g_vD.vC::vx = 16; + g_vD.vD::vd = 17; + g_vD.vD::vx = 18; + + + // {{{{{vA::va,vA::vx},vB::vb,vB::vx},vC::vc,vC::vx},vD::vd,vD::vx},vE::ve,vE::vx} + + g_vD.vA::va = 19; + g_vD.vA::vx = 20; + g_vD.vB::vb = 21; + g_vD.vB::vx = 22; + g_vD.vC::vc = 23; + g_vD.vC::vx = 24; + g_vD.vD::vd = 25; + g_vD.vD::vx = 26; + g_vE.vE::ve = 27; + g_vE.vE::vx = 28; + + inheritance4 (); +} + +// ====================================================================== + +class Base1 { + public: + int x; + Base1(int i) { x = i; } +}; + +class Foo +{ + public: + int x; + int y; + static int st; + Foo (int i, int j) { x = i; y = j; } + int operator! (); + operator int (); + int times (int y); +}; + +class Bar : public Base1, public Foo { + public: + int z; + Bar (int i, int j, int k) : Base1 (10*k), Foo (i, j) { z = k; } +}; + +class ClassWithEnum { +public: + enum PrivEnum { red, green, blue, yellow = 42 }; + PrivEnum priv_enum; + int x; +}; + +int Foo::operator! () { return !x; } + +int Foo::times (int y) { return x * y; } + +int Foo::st = 100; + +Foo::operator int() { return x; } + +Foo foo(10, 11); +Bar bar(20, 21, 22); + +class Contains_static_instance +{ + public: + int x; + int y; + Contains_static_instance (int i, int j) { x = i; y = j; } + static Contains_static_instance null; +}; + +Contains_static_instance Contains_static_instance::null(0,0); +Contains_static_instance csi(10,20); + +class Contains_nested_static_instance +{ + public: + class Nested + { + public: + Nested(int i) : z(i) {} + int z; + static Contains_nested_static_instance xx; + }; + + Contains_nested_static_instance(int i, int j) : x(i), y(j) {} + + int x; + int y; + + static Contains_nested_static_instance null; + static Nested yy; +}; + +Contains_nested_static_instance Contains_nested_static_instance::null(0, 0); +Contains_nested_static_instance::Nested Contains_nested_static_instance::yy(5); +Contains_nested_static_instance + Contains_nested_static_instance::Nested::xx(1,2); +Contains_nested_static_instance cnsi(30,40); + +typedef struct { + int one; + int two; +} tagless_struct; +tagless_struct v_tagless; + +/* Try to get the compiler to allocate a class in a register. */ +class small { + public: + int x; + int method (); +}; +int small::method () +{ + return x + 5; +} +void marker_reg1 () {} + +int +register_class () +{ + /* We don't call any methods for v, so gcc version cygnus-2.3.3-930220 + might put this variable in a register. This is a lose, though, because + it means that GDB can't call any methods for that variable. */ + register small v; + + int i; + + /* Perform a computation sufficiently complicated that optimizing compilers + won't optimized out the variable. If some compiler constant-folds this + whole loop, maybe using a parameter to this function here would help. */ + v.x = 0; + for (i = 0; i < 13; ++i) + v.x += i; + --v.x; /* v.x is now 77 */ + marker_reg1 (); + return v.x + 5; +} + +int +main() +{ +#ifdef usestubs + set_debug_traps(); + breakpoint(); +#endif + inheritance1 (); + inheritance3 (); + register_class (); + + /* FIXME: pmi gets optimized out. Need to do some more computation with + it or something. (No one notices, because the test is xfail'd anyway, + but that probably won't always be true...). */ + int Foo::* pmi = &Foo::y; + + /* Make sure the AIX linker doesn't remove the variable. */ + v_tagless.one = 5; + + /* Class with enumeration inside it */ + ClassWithEnum obj_with_enum; + obj_with_enum.priv_enum = ClassWithEnum::green; + + return foo.*pmi; +} + +/* Create an instance for some classes, otherwise they get optimized away. */ + +default_public_struct default_public_s; +explicit_public_struct explicit_public_s; +protected_struct protected_s; +private_struct private_s; +mixed_protection_struct mixed_protection_s; +public_class public_c; +protected_class protected_c; +default_private_class default_private_c; +explicit_private_class explicit_private_c; +mixed_protection_class mixed_protection_c; diff --git a/gdb/testsuite/gdb.hp/more-steps.c b/gdb/testsuite/gdb.hp/more-steps.c new file mode 100644 index 00000000000..c5ba1e26865 --- /dev/null +++ b/gdb/testsuite/gdb.hp/more-steps.c @@ -0,0 +1,140 @@ +/* BeginSourceFile more_steps.c + + This file creates a lot of threads which then execute + in parallel, so that wdb can be tested on handling + simultaneous thread events. + + To compile: + + cc -Ae +DA1.0 -g -o more_steps -lpthread more_steps.c + + To run: + + more_threads +*/ + +#include <unistd.h> +#include <stdlib.h> +#include <stdio.h> +#include <assert.h> +#include <pthread.h> + +#define TRUE 1 +#define FALSE 0 +#define N_THREADS 3 +#define PHASES 3 + +typedef enum { + ZERO, + ONE, + TWO, + THREE +} phase_t; + +/* Uncomment to turn on debugging output */ +/* #define DEBUG */ + +/* Locks. + */ +int lock_one; /* Main W, others R */ +int lock_two; /* ditto */ +int lock_end[ N_THREADS ]; /* Main R, others R[i] */ +int phase[ N_THREADS ]; + +/* Routine for each thread to run. + */ +void *spin( vp ) + void * vp; +{ + int me = (int) vp; + int i; + + lock_end[ me ] = TRUE; + + phase[ me ] = ONE; + + while( lock_one ); + + phase[ me ] = TWO; + + while( lock_two ); + + phase[ me ] = THREE; + + lock_end[ me ] = FALSE; +} + +void +do_pass() +{ + int i; + pthread_t t[ N_THREADS ]; + int err; + int done; + + /* Start N_THREADS threads, then join them so + * that they are terminated. + */ + for( i = 0; i < N_THREADS; i++ ) { + err = pthread_create( &t[i], NULL, spin, (void *)i ); + if( err != 0 ) { + printf( "== Start/stop, error in thread %d create\n", i ); + } + } + + /* Do phase 1. + */ + lock_one = FALSE; + + /* Do phase 2. + */ + lock_two = FALSE; + + /* Be done. + */ + done = 0; + while( !done ) { + + /* Be optimistic. + */ + done = 1; + for( i = 0; i < N_THREADS; i++ ) { + if( lock_end[i] ) { + /* Thread "i" is not ready yet. + */ + done = 0; + break; + } + } + } + + /* Finish up + */ + for( i = 0; i < N_THREADS; i++ ) { + err = pthread_join(t[i], NULL ); /* Line 105 */ + if( err != 0 ) { /* Line 106 */ + printf( "== Start/stop, error in thread %d join\n", i ); + } + } + + i = 10; /* Line 109. Null line for setting bpts on. */ +} + +main( argc, argv ) +int argc; +char **argv; +{ + int i; + + /* Init + */ + lock_one = TRUE; + lock_two = TRUE; + for( i = 0; i < N_THREADS; i++ ) { + lock_end[i] = TRUE; + phase[i] = ZERO; + } + + do_pass(); + return(0); +} diff --git a/gdb/testsuite/gdb.hp/more-steps.exp b/gdb/testsuite/gdb.hp/more-steps.exp new file mode 100644 index 00000000000..320a0d68872 --- /dev/null +++ b/gdb/testsuite/gdb.hp/more-steps.exp @@ -0,0 +1,152 @@ +# more-steps.exp -- Expect script to test gdb's ability to step threaded pgms +# Copyright (C) 1992 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 2 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +# Please email any bugs, comments, and/or additions to this file to: +# bug-gdb@prep.ai.mit.edu + +# use this to debug: +# +#log_user 1 + +if $tracelevel then { + strace $tracelevel +} + +#if { ![istarget "hppa*-*-hpux10.30"] && ![istarget "hppa*-*-hpux11.*"] } { +# verbose "HPUX thread test ignored for non-hppa or pre-HP/UX-10.30 targets." +# return 0 +#} + +set testfile more-steps +set srcfile ${srcdir}/${subdir}/${testfile}.c +set binfile ${objdir}/${subdir}/${testfile} + +if [get_compiler_info ${binfile}] { + return -1 +} + +# To build the executable we need to link against the thread library. +# +# cc -Ae -g -o more-steps -lpthread more-steps.c +# +#compile "${srcfile} -Ae -g -lpthread -o ${binfile}" + +if {$gcc_compiled == 0} { + set additional_flags "additional_flags=-Ae" +} else { + set additional_flags "" +} + +if { [gdb_compile "${srcdir}/${subdir}/${testfile}.c" "${binfile}.o" object [list debug $additional_flags]] != "" } { + gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail." +} + +if { ![istarget "hppa*-*-hpux10.30"] && ![istarget "hppa*-*-hpux11.*"] } { + if { [gdb_compile "${binfile}.o" "${binfile}" executable {debug "additional_flags=-lpthread"}] != ""} { + gdb_suppress_entire_file "Testcase link failed, so all tests in this file will automatically fail." + } +} else { + remote_exec build "ld /usr/ccs/lib/crt0.o ${binfile}.o -lcl -lpthread -lc /opt/langtools/lib/end.o -o ${binfile}" +} +#remote_exec build "ld /usr/ccs/lib/crt0.o ${binfile}.o -lcl -lpthread -lc /opt/langtools/lib/end.o -o ${binfile}" + + + +# Thread stuff is _slow_; prepare for long waits. +# +set oldtimeout $timeout +set timeout [expr "$timeout + 300"] +set oldverbose $verbose +#set verbose 40 + +# Further, this test has some "null" lines designed +# to consume output from gdb that was too late to be +# matched (sequence is "gdb_test" sends; timeout and +# on to next send; result finally comes in; mismatch). +# +# The null command is 'gdb_test "p \$pc" ".*" ""' +# +# NOTE: to pass a literal "$", "/" or "*" (etc.) to gdb_test, +# remember that the pattern will be escaped once and +# $-evaluated twice: +# +# "\\\*" matches "\*" +# "\$" matches "$" +# +proc fix_timeout {} { + gdb_test "p \$pc" ".*" "" +} + +#========================= +# +# Simple sanity test first. +# +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +# First, step in the main thread. +# +gdb_test "b do_pass" ".*Breakpoint 1.*" "" +gdb_test "r" ".*Breakpoint 1.*do_pass.*" "" + +# Breaks as well as nexts to make +# sure we can handle simultaneous hit +# of bpt and step, as well as stepping +# past bpts. +# +gdb_test "tb 87" ".*Breakpoint 2.*" "" +gdb_test "tb 91" ".*Breakpoint 3.*" "" +gdb_test "tb 96" ".*Breakpoint 4.*" "" +gdb_test "tb 113" ".*Breakpoint 5.*" "" +gdb_test "c" ".*do_pass.*87.*" "87" +gdb_test "n" ".*do_pass.*91.*" "n" + +# This only gets a number, as it doesn't +# hit a bpt. +# +gdb_test "n" ".*95.*" "n" + +gdb_test "n" ".*do_pass.*96.*" "n" +gdb_test "c" ".*do_pass.*113.*" "c" +gdb_test "c" ".*Program exited normally.*" "c" + +# Now step in a thread +# +gdb_test "r" ".*Breakpoint.*do_pass.*" "do_pass" +gdb_test "until 87" ".*do_pass.*87.*" "until" +gdb_test "thr 4" ".*Switching to thread 4.*spin.*56.*" "switch" +gdb_test "tb 60 thr 4" ".*Breakpoint.*" "" + +# If we do "next" now, all the other threads +# can finish! +# +gdb_test "n" ".*spin.*60.*" "" +gdb_test "i th" ".*\\\* 4 sys.*spin.*1 sys.*do_pass.*" "still in 4" + +# Done! +# +gdb_exit + +set timeout $oldtimeout +set verbose $oldverbose + +# execute_anywhere "rm -f ${binfile}" +# +return 0 + diff --git a/gdb/testsuite/gdb.hp/namespace.cc b/gdb/testsuite/gdb.hp/namespace.cc new file mode 100644 index 00000000000..53d5bd6608d --- /dev/null +++ b/gdb/testsuite/gdb.hp/namespace.cc @@ -0,0 +1,103 @@ +namespace AAA { + char c; + int i; + int A_foo (int); + char foo (char); + class inA { + public: + int xx; + int fum (int); + }; +}; + +int AAA::inA::fum (int i) +{ + return 10 + i; +} + +namespace BBB { + char c; + int i; + int B_foo (int); + char foo (char); + + namespace CCC { + char foo (char); + }; + + class Class { + public: + char foo (char); + int dummy; + }; +}; + +int AAA::A_foo (int x) +{ + return 2 * x; +} + +char AAA::foo (char c) +{ + return 'a'; +} + + +int BBB::B_foo (int x) +{ + return 3 * x; +} + +char BBB::foo (char c) +{ + return 'b'; +} + +char BBB::CCC::foo (char c) +{ + return 'z'; +} + +char BBB::Class::foo (char c) +{ + return 'o'; +} + +void marker1(void) +{ + return; +} + + +int main () +{ + using AAA::inA; + char c1; + + using namespace BBB; + + c1 = foo ('x'); + c1 = AAA::foo ('x'); + c1 = BBB::CCC::foo ('m'); + + inA ina; + + ina.xx = 33; + + int y; + + y = AAA::A_foo (33); + y += B_foo (44); + + BBB::Class cl; + + c1 = cl.foo('e'); + + marker1(); + +} + + + + + diff --git a/gdb/testsuite/gdb.hp/namespace.exp b/gdb/testsuite/gdb.hp/namespace.exp new file mode 100644 index 00000000000..1708db8ebb0 --- /dev/null +++ b/gdb/testsuite/gdb.hp/namespace.exp @@ -0,0 +1,195 @@ +# Copyright (C) 1997, 1998 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 2 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +# Please email any bugs, comments, and/or additions to this file to: +# bug-gdb@prep.ai.mit.edu + +# tests for namespaces +# Written by Satish Pai <pai@apollo.hp.com> 1997-07-23 + +# This file is part of the gdb testsuite + +# Note: These tests are geared to the HP aCC compiler, +# which has an idiosyncratic way of emitting debug info +# for namespaces. + + +if $tracelevel then { + strace $tracelevel + } + + +# +# test running programs +# + +set prms_id 0 +set bug_id 0 + +set testfile "namespace" +set srcfile ${testfile}.cc +set binfile ${objdir}/${subdir}/${testfile} + +if [get_compiler_info ${binfile}] { + return -1; +} + + +if {[skip_hp_tests $gcc_compiled]} then { continue } + + +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } { + gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will a +utomatically fail." +} + + + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + + +# +# set it up at a breakpoint so we can play with the variable values +# +if ![runto_main] then { + perror "couldn't run to breakpoint" + continue +} + +send_gdb "break marker1\n" ; gdb_expect -re ".*$gdb_prompt $" + send_gdb "cont\n" + gdb_expect { + -re "Break.* marker1 \\(\\) at .*:$decimal.*$gdb_prompt $" { + send_gdb "up\n" + gdb_expect { + -re ".*$gdb_prompt $" { pass "up from marker1" } + timeout { fail "up from marker1" } + } + } + -re "$gdb_prompt $" { fail "continue to marker1" } + timeout { fail "(timeout) continue to marker1" } + } + +# Access a data item inside a namespace using colons and +# single quotes :-( + +send_gdb "print 'AAA::c'\n" +gdb_expect { + -re "\\$\[0-9\]* = 0 '\\\\000'\r\n$gdb_prompt $" { pass "print 'AAA::c'" } + -re ".*$gdb_prompt $" { fail "print 'AAA::c'" } + timeout { fail "(timeout) print 'AAA::c'" } +} + +# An object declared using "using". + +send_gdb "print ina\n" +gdb_expect { + -re "\\$\[0-9\]+ = {xx = 33}.*$gdb_prompt $" { + pass "print ina" + } + -re ".*$gdb_prompt $" { fail "print ina" } + timeout { fail "(timeout) print ina" } +} + +send_gdb "ptype ina\n" +gdb_expect { + -re "type = class AAA::inA \{\r\n\[ \]*public:\r\n\[ \]*int xx;\r\n\[ \]*\r\n\[ \]*int fum\\(int\\);\r\n\}\r\n$gdb_prompt $" { + pass "ptype ina" + } + -re ".*$gdb_prompt $" { fail "ptype ina" } + timeout { fail "(timeout) ptype ina" } +} + +# Check all functions are known to GDB + +send_gdb "info func foo\n" +gdb_expect { + -re "All functions.*File.*namespace.cc:\r\nint AAA::A_foo\\(int\\);\r\nint BBB::B_foo\\(int\\);\r\nchar AAA::foo\\(char\\);\r\nchar BBB::foo\\(char\\);\r\nchar BBB::CCC::foo\\(char\\);\r\nchar BBB::Class::foo\\(char\\);\r\n$gdb_prompt $" { + pass "info func foo" + } + -re ".*$gdb_prompt $" { fail "info func foo" } + timeout { fail "(timeout) info func foo" } +} + +# Call a function in a namespace + +send_gdb "print 'AAA::foo'('x')\n" +gdb_expect { + -re "\\$\[0-9\]* = 97 'a'\r\n$gdb_prompt $" { + pass "print 'AAA::foo'('x')" + } + -re ".*$gdb_prompt $" { fail "print 'AAA::foo'('x')" } + timeout { fail "(timeout) print 'AAA::foo'('x')" } +} + +# Break on a function in a namespace + +send_gdb "break AAA::foo\n" +gdb_expect { + -re "Breakpoint.*at $hex: file.*namespace.cc, line 42\\.\r\n$gdb_prompt $" { + pass "break AAA::foo" + } + -re ".*$gdb_prompt $" { fail "break AAA::foo" } + timeout { fail "(timeout) break AAA::foo" } +} + +# Call a function in a nested namespace + +send_gdb "print 'BBB::CCC::foo'('x')\n" +gdb_expect { + -re "\\$\[0-9\]* = 122 'z'\r\n$gdb_prompt $" { + pass "print 'BBB::CCC::foo'('x')" + } + -re ".*$gdb_prompt $" { fail "print 'BBB::CCC::foo'('x')" } + timeout { fail "(timeout) print 'BBB::CCC::foo'('x')" } +} + +# Break on a function in a nested namespace + +send_gdb "break BBB::CCC::foo\n" +gdb_expect { + -re "Breakpoint.*at $hex: file.*namespace.cc, line 58\\.\r\n$gdb_prompt $" { + pass "break BBB::CCC::foo" + } + -re ".*$gdb_prompt $" { fail "break BBB::CCC::foo" } + timeout { fail "(timeout) break BBB::CCC::foo" } +} + +# Print address of a function in a class in a namespace + +send_gdb "print 'BBB::Class'::foo\n" +gdb_expect { + -re "\\$\[0-9\]* = \{char \\(BBB::Class \\*, char\\)\} $hex <BBB::Class::foo\\(char\\)>\r\n$gdb_prompt $" { + pass "print 'BBB::Class'::foo" + } + -re ".*$gdb_prompt $" { fail "print 'BBB::Class'::foo" } + timeout { fail "(timeout) print 'BBB::Class'::foo" } +} + +# Break on a function in a class in a namespace + +send_gdb "break BBB::Class::foo\n" +gdb_expect { + -re "Breakpoint.*at $hex: file.*namespace.cc, line 63\\.\r\n$gdb_prompt $" { + pass "break BBB::Class::foo" + } + -re ".*$gdb_prompt $" { fail "break BBB::Class::foo" } + timeout { fail "(timeout) break BBB::Class::foo" } +} + diff --git a/gdb/testsuite/gdb.hp/optimize.c b/gdb/testsuite/gdb.hp/optimize.c new file mode 100644 index 00000000000..2a8daa8c7a0 --- /dev/null +++ b/gdb/testsuite/gdb.hp/optimize.c @@ -0,0 +1,76 @@ +/* Source for debugging optimimzed code test. + + cc -g -O -o optimize optimize.c +*/ +int callee(); +int test_opt; + +int main() +{ + int a,b,c,d,e,f,g,h; + + a = 10;; + + /* Value propagate + */ + b = 2 * a + 1; + c = 3 * b + 2; + + /* Re-use expressions + */ + d = (2 * a + 1) * (3 * b + 2); + e = (2 * a + 1) * (3 * b + 2); + + /* Create dead stores--do lines still exist? + */ + d = (2 * a + 1) * (3 * b + 2); + e = (2 * a + 1) * (3 * b + 2); + d = (2 * a + 1) * (3 * b + 2); + e = (2 * a + 1) * (3 * b + 2); + + /* Alpha and psi motion + */ + if( test_opt ) { + f = e - d; + f = f--; + } + else { + f = e - d; + f = f + d * e; + } + + /* Chi and Rho motion + */ + h = 0; + do { + h++; + a = b * c + d * e; /* Chi */ + f = f + d * e; + g = f + d * e; /* Rho */ + callee( g+1 ); + test_opt = (test_opt != 1); /* Cycles */ + } while( g && h < 10); + + /* Opps for tail recursion, unrolling, + * folding, evaporating + */ + for( a = 0; a < 100; a++ ) { + callee( callee ( callee( a ))); + callee( callee ( callee( a ))); + callee( callee ( callee( a ))); + } + + return callee( test_opt ); +} + +/* defined late to keep line numbers the same +*/ +int callee( x ) + int x; /* not used! */ +{ + test_opt++; /* side effect */ + + return test_opt; +} + +/* end */
\ No newline at end of file diff --git a/gdb/testsuite/gdb.hp/optimize.exp b/gdb/testsuite/gdb.hp/optimize.exp new file mode 100644 index 00000000000..34606eb668f --- /dev/null +++ b/gdb/testsuite/gdb.hp/optimize.exp @@ -0,0 +1,144 @@ +# Copyright (C) 1998 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 2 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +# Please email any bugs, comments, and/or additions to this file to: +# bug-gdb@prep.ai.mit.edu + +# optimize.exp -- Expect script for testing apps compiled with -O + +global timeout + +# use this to debug: +# +#log_user 1 + +if $tracelevel then { + strace $tracelevel +} + +set testfile optimize +set srcfile ${testfile}.c +set binfile ${objdir}/${subdir}/${testfile} + +if [get_compiler_info ${binfile}] { + return -1; +} + + +if {[skip_hp_tests $gcc_compiled]} then { continue } + + +# Vanilla -O, which is the same as +O2 +# +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug optimize=+O2}] != "" } { + gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail." +} + + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir + +send_gdb "file $binfile\n" +gdb_expect { + -re ".*no debugging symbols found.*$gdb_prompt $" { + fail "Didn't find debug symbols; CHFts23488" + } + -re ".*No header section (PXDB data).*$gdb_prompt $" { + fail "pointless warning" + } + -re ".*done.*$gdb_prompt $" { + pass "load debug symbols" + } + timeout { fail "timeout on file" } +} + +# Two lines at the same place after opt. +# +gdb_test "b 28" ".*" "" +gdb_test "b 26" ".*also set at.*" "same line" + +gdb_test "b 47" ".*" "" +gdb_test "b 48" ".*also set at.*" "same line" + +gdb_test "tb main" ".*" "" + +set old_timeout $timeout +set timeout [expr "$timeout + 200"] +send_gdb "r\n" +gdb_expect { + -re ".*No header section (PXDB data).*$gdb_prompt $" { + fail "pointless warning" + } + -re ".*main.*2\[12].*$gdb_prompt $" { + # All the lines before line 21 or 22 are + # evaporated by the compiler. + # + pass "hit main" + } + -re ".*$gdb_prompt $" { + fail "didn't hit main" + } + timeout { fail "timeout on run" } +} +set timeout $old_timeout + +gdb_test "c" ".*Breakpoint 1.*33.*" "" +gdb_test "c" ".*51.*" "" +gdb_test "cle" ".*Deleted breakpoints.*" "set 2, so del 2" + +gdb_test "b callee" ".*" "" +gdb_test "c" ".*callee.*" "hit called rtn" + +gdb_exit + +# +O4, don't use -g +# +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {optimize=+O4}] != "" } { + gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail." +} + +gdb_start +gdb_reinitialize_dir $srcdir/$subdir + +send_gdb "file $binfile\n" +gdb_expect { + -re ".*no debugging symbols found.*$gdb_prompt $" { + pass "Didn't find debug symbols, as expected" + } + -re ".*No header section (PXDB data).*$gdb_prompt $" { + fail "pointless warning" + } + -re ".*done.*$gdb_prompt $" { + fail "Somehow found debug symbols--make this a pass?" + } + timeout { fail "timeout on file" } +} + +gdb_test "b main" ".*" "" +gdb_test "b callee" ".*" "" +gdb_test "r" ".*Breakpoint 1.*main.*" "" +gdb_test "si 3" ".*main.*" "steps" +gdb_test "x/4i \$pc" ".*main.*main+4.*main+8.*" "" +gdb_test "c" ".*callee.*" "hit bp" +gdb_test "disas" ".*callee.*callee+4.*callee+12.*" "" +gdb_test "si" ".*callee.*" "" +gdb_test "fin" ".*Run till exit.*main.*" "finish" +gdb_test "x/i \$pc" ".*main+.*" "back in main" +gdb_exit + +#remote_exec build "rm -f ${binfile}" +return 0 diff --git a/gdb/testsuite/gdb.hp/pxdb.c b/gdb/testsuite/gdb.hp/pxdb.c new file mode 100644 index 00000000000..e3e3fc23e9f --- /dev/null +++ b/gdb/testsuite/gdb.hp/pxdb.c @@ -0,0 +1,20 @@ +#include <stdio.h> + +int callee( x ) +int x; +{ + int y = x * x; + return (y - 2); +} + +main() +{ + int i; + for (i = 1; i < 10; i++) + { + printf( "%d ", callee( i )); + + } + printf( " Goodbye!\n" ); + +} diff --git a/gdb/testsuite/gdb.hp/pxdb.exp b/gdb/testsuite/gdb.hp/pxdb.exp new file mode 100644 index 00000000000..c8b3ace9961 --- /dev/null +++ b/gdb/testsuite/gdb.hp/pxdb.exp @@ -0,0 +1,114 @@ +# Copyright (C) 1998 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 2 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +# Please email any bugs, comments, and/or additions to this file to: +# bug-gdb@prep.ai.mit.edu + + +# This file is part of the gdb testsuite + + +# pxdb.exp Test that gdb calls pxdb on an application +# built without it. +# +if $tracelevel then { + strace $tracelevel +} + +set prms_id 0 +set bug_id 0 + +set testfile pxdb +set srcfile ${testfile}.c +set objfile ${objdir}/${subdir}/${testfile}.o +set binfile ${objdir}/${subdir}/${testfile} + +if [get_compiler_info ${binfile} "c++"] { + return -1; +} + + +if {[skip_hp_tests $gcc_compiled]} then { continue } + +# To build a non-pxdb-ed file, use +# +# <compile to .o file> +# export LD_PXDB /dev/null +# ld -o hello_no_pxdb hello.o /opt/langtools/lib/end.o /usr/ccs/lib/crt0.o -lc +# + +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${objfile}" object {debug}] != "" } { + gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail." +} + +# +# use this to debug: +#log_user 1 + + +# Following should get the error message: +# +# ld: (Warning) Can't exec pxdb using path: /dev/null +# + +set cmdline "ksh -c \"LD_PXDB=/dev/null ld -o ${binfile} ${objfile} /usr/ccs/lib/crt0.o /opt/langtools/lib/end.o -lc\"" + +remote_exec build "rm ${binfile}" +remote_exec build $cmdline + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir + +# We expect to see this: +# +# "warning: File not processed by pxdb--about to process now. +# " +# ". +# "Procedures: 7 +# "Files: 2 +# "Reading symbols from ~/c_code.dir/hello_no_pxdb...done. +# "(gdb) +# +send_gdb "file ${binfile}\n" +gdb_expect { + + -re ".*warning: File not processed by pxdb.*Procedures: \[0-9\]+.*done.*$gdb_prompt $"\ + { pass "PXDB call" } + + -re "$gdb_prompt $" { fail "Didn't call pxdb" } + + timeout { fail "call pxdb (timeout)" } +} + +# Make sure the new data makes sense +# +if { ![runto callee] } then { return } + +send_gdb "print x\n" +gdb_expect { + -re ".*= 1.*$gdb_prompt $" { pass "Good data after pxdb call" } + -re ".*$gdb_prompt $" { fail "No data after pxdb call" } + timeout { fail "(timeout)" } +} + +gdb_exit +return 0 + + + + + diff --git a/gdb/testsuite/gdb.hp/quicksort.c b/gdb/testsuite/gdb.hp/quicksort.c new file mode 100644 index 00000000000..b44b828a8d5 --- /dev/null +++ b/gdb/testsuite/gdb.hp/quicksort.c @@ -0,0 +1,284 @@ +/* BeginSourceFile quicksort.c + + This file is take from the DDE test system. It spawns six + threads to do a sort of an array of random numbers. + + The locations marked "quick N" are used in the test "quicksort.exp". + + The locations marked "att N" are used in the test "attach.exp". + + To compile: + + cc -Ae +DA1.0 -g -o quicksort -lpthread quicksort.c + + To run: + + quicksort --normal run + quicksort 1 --waits before starting to allow attach +*/ + +#include <unistd.h> +#include <stdlib.h> +#include <stdio.h> +#include <assert.h> +#include <pthread.h> + +#define TRUE 1 +#define FALSE 0 +#define SORTSET 100000 + +/* Uncomment to turn on debugging output */ +/* #define QUICK_DEBUG */ + +/* Uncomment to turn on wait on each thread create */ +/* #define THREAD_WAIT */ + +/* Fewer than SORT_DIRECT items are sorted with an insertion sort. */ +#define SORT_DIRECT 20 + +/* Work at this depth or less generates a separate work item. */ +#define DEFER_DEPTH 6 + +/* Workpile controller */ +typedef void (*work_proc_t)(void *); + +typedef struct workpile_struct { + pthread_mutex_t lock; /* mutex for this structure */ + pthread_cond_t work_wait; /* workers waiting for work */ + pthread_cond_t finish_wait; /* to wait for workers to finish */ + int max_pile; /* length of workpile array */ + work_proc_t worker_proc; /* work procedure */ + int n_working; /* number of workers working */ + int n_waiting; /* number of workers waiting for work */ + int n_pile; /* number of pointers in the workpile */ + int inp; /* FIFO input pointer */ + int outp; /* FIFO output pointer */ + void *pile[1]; /* array of pointers - the workpile */ +} *workpile_t; + +typedef struct { + float *data; /* Array to sort */ + int n; /* Number of elements in the array */ + int depth; /* Depth of recursion */ + workpile_t wp; /* Workpile to use */ +} quick_sort_args; + +/* True if waiting for attach. + */ +int wait_here = FALSE; + +static workpile_t quick_sort_workpile = NULL; + +void *worker(void * wptr); + +/* Allocates and initializes a workpile that holds max_pile entries. + * worker_proc is called to process each work item on the queue. + */ +workpile_t +work_init(int max_pile, work_proc_t worker_proc, int n_threads) +{ + int err; + pthread_t t; + workpile_t wp = (workpile_t) + malloc(sizeof (struct workpile_struct) + + (max_pile * sizeof (void *))); + + if (wp != NULL) { + pthread_mutex_init(&wp->lock, NULL); + pthread_cond_init(&wp->work_wait, NULL); + pthread_cond_init(&wp->finish_wait, NULL); + wp->max_pile = max_pile; + wp->worker_proc = worker_proc; + wp->n_working = wp->n_waiting = wp->n_pile = 0; + wp->inp = wp->outp = 0; + while (n_threads--) { + err = pthread_create(&t, NULL, + worker, (void *)&wp); +#ifdef QUICK_DEBUG + printf( "== Quicksort: created new thread\n" ); +#ifdef THREAD_WAIT + if( n_threads > 0 ) { + int i; + printf( "== Quicksort: waiting on user input of an integer\n" ); + scanf( "%d", &i ); + printf( "== Quicksort: continuing with quicksort\n" ); + } +#endif +#endif + + assert(err == 0); /* quick 1 */ + } + /* All the threads have now been created. + */ + assert( n_threads == -1 ); /* att 1 */ + if( wait_here ) { +#ifdef QUICK_DEBUG + printf( "== Quicksort: waiting for attach\n" ); +#endif + sleep( 25 ); + } + wait_here = 99; /* att 2, otherwise useless */ + } + return (wp); /* quick 2 */ +} + +/* + * Worker thread routine. Continuously looks for work, calls the + * worker_proc associated with the workpile to do work. + */ +void * +worker(void * wptr) +{ + workpile_t wp; + void *ptr; + + wp = * (workpile_t *) wptr; + + pthread_mutex_lock(&wp->lock); + wp->n_working++; + for (;;) { + while (wp->n_pile == 0) { /* wait for new work */ + if (--wp->n_working == 0) + pthread_cond_signal(&wp->finish_wait); + wp->n_waiting++; + pthread_cond_wait(&wp->work_wait, &wp->lock); + wp->n_waiting--; /* quick 3 */ + wp->n_working++; + } + wp->n_pile--; + ptr = wp->pile[wp->outp]; + wp->outp = (wp->outp + 1) % wp->max_pile; + pthread_mutex_unlock(&wp->lock); + /* Call application worker routine. */ + (*wp->worker_proc)(ptr); + pthread_mutex_lock(&wp->lock); /* quick 4 */ + } + /* NOTREACHED */ +} + +/* Puts ptr in workpile. Called at the outset, or within a worker. */ +void +work_put(workpile_t wp, void *ptr) +{ + pthread_mutex_lock(&wp->lock); + if (wp->n_waiting) { + /* idle workers to be awakened */ + pthread_cond_signal(&wp->work_wait); + } + assert(wp->n_pile != wp->max_pile); /* check for room */ + wp->n_pile++; + wp->pile[wp->inp] = ptr; + wp->inp = (wp->inp + 1) % wp->max_pile; + pthread_mutex_unlock(&wp->lock); +} + + +/* Wait until all work is done and workers quiesce. */ +void +work_wait(workpile_t wp) +{ + pthread_mutex_lock(&wp->lock); + while(wp->n_pile !=0 || wp->n_working != 0) + pthread_cond_wait(&wp->finish_wait, &wp->lock); + pthread_mutex_unlock(&wp->lock); +} + +void +quick_sort_aux(float *data, int n, int depth, workpile_t wp, int deferrable) +{ + int i,j; + + /* If array small, use insertion sort */ + if (n <= SORT_DIRECT) { + for (j = 1; j < n; j++) { + /* data[0..j-1] in sort; find a spot for data[j] */ + float key = data[j]; + for (i = j - 1; i >= 0 && key < data[i]; i--) + data[i+1] = data[i]; + data[i+1] = key; + } + return; + } + /* Defer this work to work queue if policy says so */ + if (deferrable && depth <= DEFER_DEPTH) { + quick_sort_args *q = (quick_sort_args *) + malloc(sizeof (quick_sort_args)); + assert(q != NULL); + q->data = data; q->n = n; q->depth = depth; q->wp = wp; + work_put(wp, (void *)q); + return; + } + /* Otherwise, partition data based on a median estimate */ +#define swap(i,j) {float t = data[i]; data[i] = data[j]; data[j] = t;} + i = 0; + j = n - 1; + for (;;) { + while (data[i] < data[j]) j--; + if (i >= j) break; + swap(i, j); i++; + while (data[i] < data[j]) i++; + if (i >= j) { i = j; break; } + swap(i, j); j--; + } + /* Median value is now at data[i] */ + /* Partitioned so that data[0..i-1] <= median <= data[i+1..n-1] */ + quick_sort_aux(data, i, depth+1, wp, TRUE); + quick_sort_aux(&data[i+1], n-i-1, depth+1, wp, TRUE); +} +/* Called from workpile controller with argument pointing to work. */ +void +quick_sort_worker(void *a) +{ + quick_sort_args *q = (quick_sort_args *)a; + quick_sort_aux(q->data, q->n, q->depth, q->wp, FALSE); + free(q); +} +/* Main routine, called by client to do a sort. */ +void +quick_sort(float *data, int n) +{ + if (quick_sort_workpile == NULL) { + int n_threads = 6; + quick_sort_workpile = work_init(2 << DEFER_DEPTH, + quick_sort_worker, n_threads); + assert(quick_sort_workpile != NULL); + } + + quick_sort_aux(data, n, 0, quick_sort_workpile, FALSE); + + /* Wait for all work to finish */ + work_wait(quick_sort_workpile); + +#ifdef QUICK_DEBUG + printf( "== Quicksort: done sorting\n" ); +#endif +} + + +main( argc, argv ) +int argc; +char **argv; +{ + float data[SORTSET]; + int i; int debugging = 0; + + if((argc > 1) && (0 != argv )) { + if( 1 == atoi( argv[1] ) ) + wait_here = TRUE; + } + + for(i = 0; i < SORTSET; i++) + data[SORTSET -1 -i] = drand48(); + + for(i = 0; i < SORTSET; i++) + if (debugging) + printf("data[%d] = %f\n", i, data[i]); + + quick_sort(data, SORTSET); + for(i = 0; i < SORTSET; i++) + if (debugging) + printf("data[%d] = %f\n", i, data[i]); + + return(0); +} +/* EndSourceFile */ diff --git a/gdb/testsuite/gdb.hp/quicksort.exp b/gdb/testsuite/gdb.hp/quicksort.exp new file mode 100644 index 00000000000..719bfdfb0a9 --- /dev/null +++ b/gdb/testsuite/gdb.hp/quicksort.exp @@ -0,0 +1,809 @@ +# quicksort.exp -- Expect script to test gdb with quicksort.c +# Copyright (C) 1992 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 2 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +# Please email any bugs, comments, and/or additions to this file to: +# bug-gdb@prep.ai.mit.edu + +# use this to debug: +# +#log_user 1 + +if $tracelevel then { + strace $tracelevel +} + +if { ![istarget "hppa*-*-hpux10.30"] && ![istarget "hppa*-*-hpux11.*"] } { + verbose "HPUX thread test ignored for non-hppa or pre-HP/UX-10.30 targets." + return 0 +} + +set testfile quicksort +set srcfile ${srcdir}/${subdir}/${testfile}.c +set binfile ${objdir}/${subdir}/${testfile} + +if [get_compiler_info ${binfile}] { + return -1 +} + +# To build the executable we need to link against the thread library. +# +# cc -Ae -g -o quicksort -lpthread quicksort.c +# +#compile "${srcfile} -Ae -g -lpthread -o ${binfile}" + +if {$gcc_compiled == 0} { + set additional_flags "additional_flags=-Ae" +} else { + set additional_flags "" +} + +if { [gdb_compile "${srcdir}/${subdir}/${testfile}.c" "${binfile}.o" object [list debug $additional_flags]] != "" } { + gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail." +} +remote_exec build "ld /usr/ccs/lib/crt0.o ${binfile}.o -lcl -lpthread -lc /opt/langtools/lib/end.o -o ${binfile}" + + +# Thread stuff is _slow_; prepare for long waits. +# +set oldtimeout $timeout +set timeout [expr "$timeout + 300"] +set oldverbose $verbose +#set verbose 40 + +# Further, this test has some "null" lines designed +# to consume output from gdb that was too late to be +# matched (sequence is "gdb_test" sends; timeout and +# on to next send; result finally comes in; mismatch). +# +# The null command is 'gdb_test "p \$pc" ".*" ""' +# +# NOTE: to pass a literal "$", "/" or "*" (etc.) to gdb_test, +# remember that the pattern will be escaped once and +# $-evaluated twice: +# +# "\\\*" matches "\*" +# "\$" matches "$" +# +proc fix_timeout {} { + gdb_test "p \$pc" ".*" "" +} + +#========================= +# +# Simple sanity test first. +# +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +gdb_test "tb 122" ".*Breakpoint.*" "" +gdb_test "r" ".*122.*" "" +gdb_test "thr 99" ".*Thread ID 99 not known.*" "Check too-big thread number" +gdb_test "tb 145 thr 3" ".*Breakpoint.*" "set thread-specific bp 145" +gdb_test "tb 146 thr 4" ".*Breakpoint.*" "set thread-specific bp 146" +gdb_test "c" ".*Switched to thread.*145.*" "auto switch" +gdb_test "c" ".*Switched to thread.*146.*" "auto switch 2" +gdb_test "c" ".*Program exited normally.*" "" + +#========================= +# +# Test that you can't do a thread select after a program runs. +# +gdb_test "thread" ".*No stack.*" "No live thread after run" +gdb_test "thr 2" ".*No stack.*" "Can't set thread after run" + +#========================= +# +# Test thread command changes, look for frame level reset bug. +# +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} +gdb_test "b 122" ".*" "" +gdb_test "r" ".*122.*" "" + +# Prep for frame level test--go up/info thread/check frame +# +gdb_test "up" ".*quick_sort.*" "" +gdb_test "up" ".*main.*" "" + +send_gdb "i th\n" +gdb_expect { + -re ".*7 thread.* in .* from .* in .* from .* 6 thread.*$gdb_prompt $" { + fail "old thread command, says things twice" + } + -re ".*7 system thread.*6 system th.*5 sys.*4.*3.*2.*1.*work_init.*$gdb_prompt $" { + pass "info threads" + } + -re ".*$gdb_prompt $" { fail "no info thread command" } + timeout { fail "timeout" } +} + +# We should have been restored two frames up--check. +# +send_gdb "up\n" +gdb_expect { + -re ".*Initial frame selected.*$gdb_prompt $" { + pass "Frame correctly reset after 'info threads'" + } + -re ".*quick_sort.*$gdb_prompt $" { + fail "Old gdb bug; should be fixed someday" + } + -re ".*$gdb_prompt $" { + fail "real bug--FIX!" + } + timeout { fail "timeout" } +} + +# Do it again, only just go to a middle frame, and use another thread. +# +gdb_test "thr 5" ".*" "" +gdb_test "bt" ".* ___ksleep.*_lwp_cond_timedwait.*pthread_cond_wait.*worker.*__pthread_create_system.*" "" +gdb_test "up" ".*1.*_lwp_cond_timedwait.*" "" +gdb_test "up" ".*2.*pthread_cond_wait.*" "" +gdb_test "up" ".*3.*worker.*" "" +gdb_test "i th" ".*7.*6.*work_init.*" "" +gdb_test "f" ".*3.*worker.*" "Frame restored" +gdb_test "p wp->max_pile" ".*= 128.*" "can see vars in frame" + +# Thread command changes +# +gdb_test "thr" ".*Current thread is 5.*" "threads-no-num" +gdb_test "thr 6" ".*Switching to thread 6.*" "new switch" +gdb_test "thr" ".*Current thread is 6.*" "check switch" +#gdb_test "thr 6" ".*Current thread is already 6.*" "dup, no switch" +gdb_test "thr app all p x" ".*No symbol.*" "" +gdb_test "thr" ".*Current thread is 6.*" "restore current thread" + +#========================= +# +# Test new stepping +# + +proc get_hit { } { + global hit2 + global hit3 + global hit4 + global hit5 + global hit6 + global hit7 + global gdb_prompt + + send_gdb "cont\n" + gdb_expect { + -re ".*Breakpoint.*145.*$gdb_prompt $" { + send_gdb "thr\n" + gdb_expect { + -re ".*is 7.*$gdb_prompt $" { + set hit7 [expr "$hit7 + 1"] + } + -re ".*is 6.*$gdb_prompt $" { + set hit6 [expr "$hit6 + 1"] + } + -re ".*is 5.*$gdb_prompt $" { + set hit5 [expr "$hit5 + 1"] + } + -re ".*is 4.*$gdb_prompt $" { + set hit4 [expr "$hit4 + 1"] + } + -re ".*is 3.*$gdb_prompt $" { + set hit3 [expr "$hit3 + 1"] + } + -re ".*is 2.*$gdb_prompt $" { + set hit2 [expr "$hit2 + 1"] + } + -re ".*$gdb_prompt $" { + fail "can't see which thread" + } + timeout { fail "timeout" } + } + } + -re ".*$gdb_prompt $" { + fail "thread command" + } + timeout { fail "timeout" } + } +} + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} +gdb_test "break 122" ".*" "" +gdb_test "run" ".*122.*" "" + +# Make sure we hit a bp on every thread. +# +# Try one, via thread-specific bps +# +gdb_test "break 145 thr 2" ".*" "set thread-specific bp thr 2" +gdb_test "break 145 thr 3" ".*" "set thread-specific bp thr 3" +gdb_test "break 145 thr 4" ".*" "set thread-specific bp thr 4" +gdb_test "break 145 thr 5" ".*" "set thread-specific bp thr 5" +gdb_test "break 145 thr 6" ".*" "set thread-specific bp thr 6" +gdb_test "break 145 thr 7" ".*" "set thread-specific bp thr 7" + +set hit2 0 +set hit3 0 +set hit4 0 +set hit5 0 +set hit6 0 +set hit7 0 + +get_hit +get_hit +get_hit +get_hit +get_hit +get_hit + +if { [expr "$hit2 == 1"] + && [expr "$hit3 == 1"] + && [expr "$hit4 == 1"] + && [expr "$hit5 == 1"] + && [expr "$hit6 == 1"] + && [expr "$hit7 == 1"] } { + pass "thread-specific bps 1" +} else { + fail "thread-specific bps 1" +} + +#==================== +# +# Now use generic bps +# +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} +gdb_test "b 122" ".*" "" +gdb_test "r" ".*122.*" "" + +# Make sure we hit a bp on every thread. +# +# Try two, via non-thread-specific bp +# +gdb_test "b 145" ".*" "b 145" + +set hit2 0 +set hit3 0 +set hit4 0 +set hit5 0 +set hit6 0 +set hit7 0 + +get_hit +get_hit +get_hit +get_hit +get_hit +get_hit + +if { [expr "$hit2 == 1"] + && [expr "$hit3 == 1"] + && [expr "$hit4 == 1"] + && [expr "$hit5 == 1"] + && [expr "$hit6 == 1"] + && [expr "$hit7 == 1"] } { + pass "thread-specific bps 2" +} else { + fail "thread-specific bps 2" +} + +#==================== +# +# Complicated (original) test next. +# +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +if ![runto_main] then { + fail "Can't run to main" + return 0 +} + +# OK, we're at "main", there should be one thread. +# +gdb_test "info thread" ".*\\\* 1 system thread .*main.*" "initial thread" + +# Try to see the threads being created: set a breakpoint +# after the creation and go around the loop a few times. +# +gdb_test "break 109" "Breakpoint.*109.*" "set bpt" + +gdb_test "c" ".*New thread.*Breakpoint.*109.*" "first continue" +fix_timeout + +# Make sure we don't wait (waiting is for attach test) +# +gdb_test "set wait_here = 0" ".*" "" + +send_gdb "info thr\n" +gdb_expect { + -re ".*2 system th.*1 sy.*109.*$gdb_prompt $" { pass "saw thread create" } + -re ".*1 system thread.*87.*$gdb_prompt $" { fail "didn't see thread create" } + -re ".*$gdb_prompt $" { fail "no info thread command" } + timeout { fail "timeout" } +} + +gdb_test "c" ".*New thread.*Breakpoint.*109.*" "continue" +fix_timeout + +send_gdb "info thr\n" +gdb_expect { + -re ".*3 system thread.*2 sys.*\\\* 1 system thread.*109.*$gdb_prompt $" { + pass "saw thread create" } + -re ".*2 system thread.*1 sys.*109.*$gdb_prompt $" { + fail "didn't see thread create" + } + -re ".*1 system thread.*109.*$gdb_prompt $" { + fail "didn't see thread create" + } + -re ".*$gdb_prompt $" { + fail "no info thread command" + } + timeout { fail "timeout" } +} + +fix_timeout +gdb_test "clear" ".*Deleted breakpoint.*" "" + +# Now go on to the end of thread creation. +# +gdb_test "b 122" ".*" "set bpt 122" +gdb_test "c" ".*New thread.*New thread.*New thread.*122.*" "" +gdb_test "p \$pc" ".*" "" +gdb_test "clear" ".*Deleted breakpoint.*" "" + +send_gdb "info thr\n" +gdb_expect { + -re ".*7 system thread.*6 sys.*5.*1 system thread.*122.*$gdb_prompt $" + { pass "saw thread creates" } + -re ".*$gdb_prompt $" + { fail "no info thread command" } + timeout { fail "timeout" } +} + +# Try a thread-specific breakpoint; we expect the other threads to +# be waiting at this point. +# +gdb_test "thr 3" ".*Switching to thread.*ksleep.*" "thread switch" +gdb_test "i th" ".*\\\* 3 system thread.*" "show new current thread" + +gdb_test "up" ".*lwp_cond_timedwait.*" "" +gdb_test "up" ".*pthread_cond_wait.*" "" +gdb_test "up" ".*worker.*144.*" "" + +gdb_test "b 145 th 3" ".*Breakpoint.*145.*" "set thread-specific bp" +gdb_test "i b" ".*breakpoint.*breakpoint.*145 thread 3.*" "show thread-specific bp" + +gdb_test "c" ".*Breakpoint.*145.*145.*" "hit thread-specific bp" +gdb_test "p \$pc" ".*" "" + +# Test thread apply command on thread specific data. +# +gdb_test "thre app all p \$pc" ".*Thread 7.*Thread 6.*Thread 5.*Thread 4.*Thread 3.*Thread 2.*Thread 1.*" "thread apply all" +gdb_test "thr ap 1 3 5 p \$pc" ".*Thread 1.*Thread 3.*Thread 5.*" "thr app 1 3 5" + +# Switch again, and test that others continue on a "next" +# This test _could_ fail due to timing issues, but that's +# unlikely. +# +gdb_test "thr 7" ".*Switching to thread.*" "" + +# Make sure that "up" stops at __pthread_exit, or +# __pthread_create, the pseudo-roots, and that we +# only see that pseudo-root once. +# +send_gdb "bt\n" +gdb_expect { + -re ".*Error accessing memory address.*" { fail "bt" } + -re ".*pthread_create.*pthread_create.*" { fail "bt" } + -re ".*worker.*pthread_create.*" { pass "bt" } + -re ".*pthread_exit.*" { pass "bt" } + timeout { fail "timeout on bt" } +} + +gdb_test "up" ".*" "" +gdb_test "up" ".*" "" +gdb_test "up" ".*144.*" "Up 3" +gdb_test "up" ".*pthread_.*" "Up 4" +gdb_test "up" ".*Initial frame selected; you cannot go up.*" "catch end of thread stack" + +#===================== +# +# Things get iffy here; when we step, sometimes the step +# completes, sometimes it doesn't. When it doesn't, we +# hit a bp somewhere else and the step never completes +# (wait_for_inferior just evaporates it). +# +# I think the right answer is that any failures here +# should stick around to trigger later fixing. +# +# Here's the plan: +# +# Bps at 148 (5) and 154 (6) on thread 7 (two bps so we +# see the difference between going around the loop and +# reporting the same bp hit twice). +# +# Bp at 144 on thread 3. +# +# Step out of a library routine. +# +# Either the step will finish or a bp will hit. Try to +# handle all the cases. +# +gdb_test "b 148 thr 7" ".*Breakpoint.*148.*" "" +gdb_test "b 154 thr 7" ".*Breakpoint.*154.*" "set bpt 2" + +set hit_154_bp 0 +set hit_148_bp 0 +set hit_145_bp 0 +set step_completed 0 + +# Expect zero hits +# +gdb_test "i b" ".*" "" + +send_gdb "n\n" +gdb_expect { + -re ".*Single stepping.*_lwp_cond_timedwait.*$gdb_prompt $" { + send_gdb "thr\n" + gdb_expect { + -re ".*is 7.*$gdb_prompt $" { + set step_completed 1 + pass "completed step in library code" + } + -re ".*$gdb_prompt $" { + fail "completed step in library code, but in wrong thread" + } + timeout { fail "timeout" } + } + } + -re ".*Single stepping.*Switched to thread 3.*Breakpoint.*$gdb_prompt $" { + pass "step cancelled; hit bp due to thread parallelism" + set hit_145_bp 1 + } + -re ".*Single stepping.*Switched to thread 7.*Breakpoint.*148.*$gdb_prompt $" { + pass "step cancelled; hit bp due to thread parallelism" + set hit_148_bp 1 + } + -re ".*Single stepping.*Switched to thread 7.*Breakpoint.*154.*$gdb_prompt $" { + pass "step cancelled; hit bp due to thread parallelism" + set hit_154_bp 1 + } + -re ".*$gdb_prompt $" { + send_gdb "thr\n" + gdb_expect { + -re ".*is 7.*$gdb_prompt $" { + fail "No event?" + } + -re ".*$gdb_prompt $" { + fail "No event" + } + timeout { fail "timeout" } + } + } + timeout { fail "timeout" } +} + +# Sometimes used to get SIGTRAP here; that should be fixed +# + +# Expect appropriate hits of bpt; too much work to parse +# result and check... +# +gdb_test "i b" ".*" "" + +send_gdb "c\n" +gdb_expect { + -re ".*SIGTRAP.*$gdb_prompt $" { + fail "got SIGTRAP" + } + -re ".*Switched to thread 7.*Breakpoint.*154.*$gdb_prompt $" { + if { $hit_154_bp == 1 } { + fail "re-hit old bp" + } else { + pass "continue; hit parallel event after continue" + } + set hit_154_bp 1 + } + -re ".*Switched to thread 7.*Breakpoint.*148.*$gdb_prompt $" { + if { $hit_148_bp == 1 } { + fail "re-hit old bp" + } else { + pass "continue; hit parallel event after continue" + } + set hit_148_bp 1 + } + -re ".*Breakpoint.*154.*$gdb_prompt $" { + if { $hit_154_bp == 1 } { + fail "re-hit old bp" + } else { + send_gdb "thr\n" + gdb_expect { + -re ".*is 7.*$gdb_prompt $" { + pass "continue; hit parallel event after continue" + } + -re ".*$gdb_prompt $" { + fail "hit bp in wrong thread" + } + timeout { fail "timeout" } + } + } + set hit_154_bp 1 + } + -re ".*Breakpoint.*148.*$gdb_prompt $" { + if { $hit_148_bp == 1 } { + fail "re-hit old bp" + } else { + send_gdb "thr\n" + gdb_expect { + -re ".*is 7.*$gdb_prompt $" { + pass "continue; hit parallel event after continue" + } + -re ".*$gdb_prompt $" { + fail "hit bp in wrong thread" + } + timeout { fail "timeout" } + } + } + set hit_148_bp 1 + } + -re ".*Breakpoint.*145.*$gdb_prompt $" { + if { $hit_145_bp == 1 } { + fail "re-hit old bp" + } else { + send_gdb "thr\n" + gdb_expect { + -re ".*is 3.*$gdb_prompt $" { + pass "continue; hit parallel event after continue" + } + -re ".*$gdb_prompt $" { + fail "hit bp in wrong thread" + } + timeout { fail "timeout" } + } + } + set hit_145_bp 1 + } + -re ".*_lwp_cond_timedwait.*$gdb_prompt $" { + pass "continue; hit step completion after continue" + } + -re ".*Program exited normally.*" { + fail "Program ended? HOW?" + } + -re ".*$gdb_prompt $" { + fail "Unexpected event" + } + timeout { fail "timeout" } +} + +# There are a number of places we _could_ be now; +# this is the price of really running in parallel. +# +send_gdb "n\n" +gdb_expect { + -re ".*Switched to thread 7.*pthread_cond_wait.*$gdb_prompt $" { + if { $step_completed } { + fail "step already completed" + } else { + pass "finish step" + } + } + -re ".*pthread_cond_wait.*$gdb_prompt $" { + # + # Unlikely, but we might finish the range step from inside + # ksleep, before anything else. + # + if { $step_completed } { + fail "step already completed" + } else { + send_gdb "thr\n" + gdb_expect { + -re ".*is 7.*$gdb_prompt $" { + pass "finish step" + } + -re ".*$gdb_prompt $" { + fail "step in wrong thread" + } + timeout { fail "timeout" } + } + } + } + -re ".*Switched to thread.*Breakpoint.*145.*$gdb_prompt $" { + pass "auto-switch thread" + } + -re ".*Breakpoint.*145.*$gdb_prompt $" { + pass "auto-switch not needed, ok" + } + -re ".*140.*while.*n_pile.*$gdb_prompt $" { + # + # This is just going around the loop from the 154 bp. + # + send_gdb "thr\n" + gdb_expect { + -re ".*is 7.*$gdb_prompt $" { + pass "finish step" + } + -re ".*$gdb_prompt $" { + fail "step in wrong thread" + } + timeout { fail "timeout" } + } + } + -re ".*149.*ptr = wp.*pile.*$gdb_prompt $" { + # + # This is just going around the loop from the 148 bp. + # + if { $hit_154_bp } { + send_gdb "thr\n" + gdb_expect { + -re ".*is 7.*$gdb_prompt $" { + pass "finish step" + } + -re ".*$gdb_prompt $" { + fail "step in wrong thread" + } + timeout { fail "timeout" } + } + } else { + pass "step from 149 but didn't hit it first" + } + } + -re ".*Breakpoint 5.*154.*$gdb_prompt $" { + gdb_test "i b" ".*" "" + if { $hit_154_bp } { + fail "hit bp again?" + } else { + pass "hit bp" + } + } + -re ".*Breakpoint 5.*148.*$gdb_prompt $" { + gdb_test "i b" ".*" "" + if { $hit_148_bp } { + fail "hit bp again?" + } else { + pass "hit bp" + } + } + -re ".*$gdb_prompt $" { + fail "no step finished" + } + timeout { fail "timeout on 'next'" } +} + +# Let's get into some kind of known state again. +# +gdb_test "thr 7" ".*" "" +gdb_test "info thread" ".*" "" +#gdb_test "i b" ".*" "" + +# Leave breakpoint "154 thr 7" as only live bp. +# +gdb_test "d 1" ".*" "del main bp" +gdb_test "d 4" ".*" "thread-specific bpt delete" +gdb_test "d 5" ".*" "other bp delete" +send_gdb "i b\n" +gdb_expect { + -re ".*breakpoint.*breakpoint.*$gdb_prompt $" { + fail "more than one bp left" + } + -re ".*breakpoint.*154.*thread.*7.*$gdb_prompt $" { + pass "Only one bp left" + } + -re ".*$gdb_prompt $" { + fail "Wrong or no bp left" + } + timeout { fail "timeout on info b" } +} + +send_gdb "c\n" +gdb_expect { + -re ".*SIGTRAP.*Switched to thread.*$gdb_prompt $" { + fail "SIGTRAP error; lost thread-specific bpt" + } + -re ".*SIGTRAP.*Switched to thread.*154.*$gdb_prompt $" { + fail "SIGTRAP, but hit right thread-specific bpt" + } + -re ".*Switched to thread.*Breakpoint.*154.*$gdb_prompt $" { + pass "auto-switch back" + } + -re ".*Breakpoint.*154.*$gdb_prompt $" { + pass "step to bp" + } + -re ".*$gdb_prompt $" { + fail "auto-switch back" + } + -re ".*Program exited normally.*$gdb_prompt $" { + fail "step lost" + } + timeout { + fail "timeout" + } +} +fix_timeout + +gdb_test "cle" ".*Deleted breakpoint.*" "delete last breakpoint" + +# Sometimes get SIGTRAP here. Continue sometimes gets another... +# +send_gdb "c\n" +gdb_expect { + -re ".*SIGTRAP.*154.*154.*$gdb_prompt $" { + fail "SIGTRAP on deleted bp 154 " + send_gdb "c\n" + gdb_expect { + -re ".*$gdb_prompt $" { pass "fixup"} + timeout { fail "fixup" } + } + } + -re ".*SIGTRAP.*144.*145.*$gdb_prompt $" { + fail "SIGTRAP on deleted bp 145 " + send_gdb "c\n" + gdb_expect { + -re ".*$gdb_prompt $" { pass "fixup"} + timeout { fail "fixup" } + } + } + -re ".*SIGTRAP.*148.*148.*$gdb_prompt $" { + fail "SIGTRAP on deleted bp 148 " + send_gdb "c\n" + gdb_expect { + -re ".*$gdb_prompt $" { pass "fixup"} + timeout { fail "fixup" } + } + } + -re ".*SIGTRAP.*$gdb_prompt $" { + fail "unknown SIGTRAP" + send_gdb "c\n" + gdb_expect { + -re ".*$gdb_prompt $" { pass "fixup"} + timeout { fail "fixup" } + } + } + -re ".*Program exited.*$gdb_prompt $" { + pass "run to end" + } + -re ".*$gdb_prompt $" { + fail "run to end" + send_gdb "c\n" + gdb_expect { + -re ".*$gdb_prompt $" { pass "fixup"} + timeout { fail "fixup" } + } + } + timeout { fail "timeout" } +} + +gdb_test "p \$pc" ".*No registers.*" "program done" + +# Done! +# +gdb_exit + +set timeout $oldtimeout +set verbose $oldverbose + +# execute_anywhere "rm -f ${binfile}" +# +return 0 + diff --git a/gdb/testsuite/gdb.hp/reg-test.exp b/gdb/testsuite/gdb.hp/reg-test.exp new file mode 100644 index 00000000000..4bdc3069293 --- /dev/null +++ b/gdb/testsuite/gdb.hp/reg-test.exp @@ -0,0 +1,190 @@ +# Copyright (C) 1998 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 2 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +# Please email any bugs, comments, and/or additions to this file to: +# bug-gdb@prep.ai.mit.edu + +# Tests of wide register displays for GDB on HPPA 2.0 machines + +# use this to debug: +#log_user 1 + +if $tracelevel then { + strace $tracelevel + } + +if ![istarget "hppa*-*-*"] { + verbose "Wide register test ignored for non-hppa targets." + return +} + +set testfile "reg_test" +set srcfile ${testfile}.s +set binfile ${objdir}/${subdir}/${testfile} + +# To build a pa 2.0 executable +# +# as -o reg_test reg_test.s +# or +# cc -g -o reg_test reg_test.s +# +# The +DA2.0N flag doesn't seem to be needed. +# +# Don't reject if there are warnings, as we expect this warning: +# +# (Warning) At least one PA 2.0 object file (pa2.0_test2.o) was detected. +# The linked output may not run on a PA 1.x system. +# + +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } { + gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail." +} + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +# test machine--there's no 2.0n architecture, so we have +# to try to run the app. +# +send_gdb "break main\n" + gdb_expect { + -re "Breakpoint.*$gdb_prompt $" { + pass "initial set-up" + } + -re ".*$gdb_prompt $" { + fail "initial set-up" + } + timeout { + fail "initial set-up (timeout)" + } + } + +send_gdb "run\n" + gdb_expect { + -re ".*Executable file incompatible with hardware.*$gdb_prompt $" { + # Not hppa2.0 machine + # + return 0 + } + -re "Cannot exec.*$gdb_prompt $" { + # Not hppa2.0 machine + # + return 0 + } + -re ".*Starting program:.*$gdb_prompt $" { + pass "Ready to start test" + } + timeout { + fail "initial set-up, part 2 (timeout)" + return 0 + } + } + +# Let the program set known values. This secretly deletes +# the breakpoint at main and re-runs to mainend. +# +runto mainend + +# Look for known values +# +gdb_test "info reg r1" "r1 1" +gdb_test "info reg r4" "r4 2" +gdb_test "info reg r5" "r5 4" +gdb_test "info reg r6" "r6 8" +gdb_test "info reg r7" "r7 10" +gdb_test "info reg r8" "r8 20" +gdb_test "info reg r9" "r9 40" +gdb_test "info reg r10" "r10 80" +gdb_test "info reg r11" "r11 100" +gdb_test "info reg r12" "r12 200" +gdb_test "info reg r13" "r13 400" +gdb_test "info reg r14" "r14 800" +gdb_test "info reg r15" "r15 1000" +gdb_test "info reg r16" "r16 2000" + +# Two odd variants that GDB supports are: +# "1" means "r1", and +# "$1" means "r1" +# +gdb_test "info reg 1 4" "r1 1.*r4 2" +gdb_test "info reg \$1" "r1 1" + +# Verify that GDB responds gracefully to a register ID number that +# is out of range. +# +gdb_test "info reg 999" "999: invalid register" + +# Make sure the floating point status and error registers +# don't show up as floating point numbers! +# +gdb_test "info reg fpsr" ".*fpsr 0.*" "fpsr" +gdb_test "info reg fpe1" ".*fpe1 0.*" "fpe1" +gdb_test "info reg fpe2" ".*fpe2 0.*" "fpe2" +gdb_test "info reg fpe3" ".*fpe3 0.*" "fpe3" +gdb_test "info reg fpe4" ".*fpe4 0.*" "fpe4" +gdb_test "info reg fpe5" ".*fpe5 0.*" "fpe5" +gdb_test "info reg fpe6" ".*fpe6 0.*" "fpe6" +gdb_test "info reg fpe7" ".*fpe7 0.*" "fpe7" + +gdb_test "info reg fr4" ".*fr4.*(double precision).* 1" +gdb_test "info reg fr5" ".*fr5.*(double precision).* 2" +gdb_test "info reg fr6" ".*fr6.*(double precision).* 2" +gdb_test "info reg fr7" ".*fr7.*(double precision).* 4" +gdb_test "info reg fr8" ".*fr8.*(double precision).* 8" +gdb_test "info reg fr9" ".*fr9.*(double precision).* 32" +gdb_test "info reg fr10" ".*fr10.*(double precision).* 256" + +gdb_test "info reg r19" "r19 deadbeefbadcadee" + +# Need to add test of use of $<register-name> +# +# Q: How do you say a literal "$" in expect? +# A: You say "\$". A literal "\" is "\\". +# +# Please note that this test will fail as long as we are running +# in 32-bit mode: it will produce "$1 = 0xbadcadee". To fix it +# would require building a real 64-bit gdb (expression evaluation, +# in particular). +# +send_gdb "p/x \$r19\n" + gdb_expect { + -re ".*= 0xdeadbeefbadcadee.*$gdb_prompt $" { + pass "64-bit works" + } + -re ".*= 0xbadcadee.*$gdb_prompt $" { + pass "32-bit extract when using PRINT; expected but not good" + } + -re ".*$gdb_prompt $" { + fail "didn't print any part of right value" + } + timeout { + fail "timeout on print" + } + } + +# Need to add tests of setting wide regs too. E.g. +# +# set $r4 = 0x1234567890123456 +# p/x $r4 +# + +# done +# +gdb_exit +remote_exec build "rm -f ${binfile}" +return 0 diff --git a/gdb/testsuite/gdb.hp/reg-test.s b/gdb/testsuite/gdb.hp/reg-test.s new file mode 100644 index 00000000000..39bb5d863c1 --- /dev/null +++ b/gdb/testsuite/gdb.hp/reg-test.s @@ -0,0 +1,96 @@ +; assemble as "as -o reg_test.exe reg_test.s" +; or +; cc -g -o +DA2.0N +; +; PA-RISC 2.0 register contents test. +; + .level 2.0 + + .code + .export main,ENTRY + .export mainend,CODE + .export lab1,CODE + .space $TEXT$ + .subspa $CODE$ + +main + .proc + .callinfo NO_CALLS,FRAME=0 + .entry + + ;; Test we have right register numbers + ;; + ADD %r0,%r0,%r1 ; 0 + LDI 1,%r1 ; 1 + ;; + ;; Don't put anything into r2 or r3--they are special registers. + ;; + ADD %r1,%r1,%r4 ; 2 + ADD %r4,%r4,%r5 ; 4 + ADD %r5,%r5,%r6 ; 8 + ADD %r6,%r6,%r7 ; 16 + ADD %r7,%r7,%r8 ; 32 + ADD %r8,%r8,%r9 ; 64 + ADD %r9,%r9,%r10 ; 128 + ADD %r10,%r10,%r11 ; 256 + ADD %r11,%r11,%r12 ; 512 + ADD %r12,%r12,%r13 ; 1024 + ADD %r13,%r13,%r14 ; 2048 + ADD %r14,%r14,%r15 ; 4096 + ADD %r15,%r15,%r16 ; 9192 + + ;; Test high bits, to be sure we show them. + ;; + LDI 0xde,%r19 ; "de" + DEPD,Z %r19,55,56,%r19 ; "de00" + LDI 0xad,%r18 ; "ad" + ADD %r18,%r19,%r19 ; "dead" + DEPD,Z %r19,55,56,%r19 ; "dead00" + LDI 0xbe,%r18 ; "be" + ADD %r18,%r19,%r19 ; "deadbe" + DEPD,Z %r19,55,56,%r19 ; "deadbe00" + LDI 0xef,%r18 ; "ef" + ADD %r18,%r19,%r19 ; "deadbeef" + ; + DEPD,Z %r19,55,56,%r19 ; "deadbeef00" + LDI 0xba,%r18 ; "ba" + ADD %r18,%r19,%r19 ; "deadbeefba" + DEPD,Z %r19,55,56,%r19 ; "deadbeefba00" + LDI 0xdc,%r18 ; "dc" + ADD %r18,%r19,%r19 ; "deadbeefbadc" + DEPD,Z %r19,55,56,%r19 ; "deadbeefbadc00" + LDI 0xad,%r18 ; "ad" + ADD %r18,%r19,%r19 ; "deadbeefbadcad" + DEPD,Z %r19,55,56,%r19 ; "deadbeefbadcad00" + LDI 0xee,%r18 ; "ee" + ADD %r18,%r19,%r19 ; "deadbeefbadcadee" + +lab1 ;; Test floating point registers + ;; + LDIL LR'one,%r22 ; + FLDD RR'one(%r22),%fr4 ; 1.0 + FLDD RR'one+8(%r22),%fr5 ; 2.0 + FLDD RR'one+8(%r22),%fr6 ; 2.0 + FMPY,DBL %fr5,%fr6,%fr7 ; 4.0 + FMPY,DBL %fr6,%fr7,%fr8 ; 8.0 + FMPY,DBL %fr7,%fr8,%fr9 ; 32.0 + FMPY,DBL %fr8,%fr9,%fr10 ; 256.0 + + ;; The NOP prevents anything from end.o or crt0.o from + ;; being appended immediately after "mainend". If that + ;; happens, then we may have other labels that have the + ;; same address as "mainend", and thus the debugger + ;; may symbolize this PC to something other than "mainend". +mainend + NOP + .exit + .procend + + .space $TEXT$ + .subspa $CODE$ + .subspa $LIT$ ;; <don't use> ,QUAD=0,ALIGN=8,ACCESS=0x2c,SORT=16 +one + .align 8 + .stringz "?\xF0\x00\x00\x00\x00\x00\x00@\x00\x00\x00\x00\x00\x00" + .end + diff --git a/gdb/testsuite/gdb.hp/run-hp.c b/gdb/testsuite/gdb.hp/run-hp.c new file mode 100644 index 00000000000..91da1e0fc16 --- /dev/null +++ b/gdb/testsuite/gdb.hp/run-hp.c @@ -0,0 +1,70 @@ +/* + * This simple classical example of recursion is useful for + * testing stack backtraces and such. + */ + +#ifdef vxworks + +# include <stdio.h> + +/* VxWorks does not supply atoi. */ +static int +atoi (z) + char *z; +{ + int i = 0; + + while (*z >= '0' && *z <= '9') + i = i * 10 + (*z++ - '0'); + return i; +} + +/* I don't know of any way to pass an array to VxWorks. This function + can be called directly from gdb. */ + +vxmain (arg) +char *arg; +{ + char *argv[2]; + + argv[0] = ""; + argv[1] = arg; + main (2, argv, (char **) 0); +} + +#else /* ! vxworks */ +# include <stdio.h> +#endif /* ! vxworks */ + +main (argc, argv, envp) +int argc; +char *argv[], **envp; +{ +#ifdef usestubs + set_debug_traps(); + breakpoint(); +#endif +#ifdef FAKEARGV + printf ("%d\n", factorial (1)); +#else + if (argc != 2) { + printf ("usage: factorial <number>\n"); + return 1; + } else { + printf ("%d\n", factorial (atoi (argv[1]))); + } +#endif + return 0; +} + +int factorial (value) +int value; +{ + int local_var; + + if (value > 1) { + value *= factorial (value - 1); + } + local_var = value; + return (value); +} diff --git a/gdb/testsuite/gdb.hp/sized-enum.c b/gdb/testsuite/gdb.hp/sized-enum.c new file mode 100644 index 00000000000..a6d57881f48 --- /dev/null +++ b/gdb/testsuite/gdb.hp/sized-enum.c @@ -0,0 +1,43 @@ + +enum Normal { + red, + blue, + green +}; + +short enum Small { + pink, + cyan, + grey +}; + +char enum Tiny { + orange, + yellow, + brown +}; + + +main() +{ + enum Normal normal[3]; + short enum Small small[3]; + char enum Tiny tiny[3]; + int i; + + for (i=0; i < 3; i++) + { + normal[i] = (enum Normal) i; + small[i] = (short enum Small) i; + tiny[i] = (char enum Tiny) i; + } + normal[0] = 0; /* place to hang a breakpoint */ +} + + + + + + + + diff --git a/gdb/testsuite/gdb.hp/sized-enum.exp b/gdb/testsuite/gdb.hp/sized-enum.exp new file mode 100644 index 00000000000..191050ada4c --- /dev/null +++ b/gdb/testsuite/gdb.hp/sized-enum.exp @@ -0,0 +1,162 @@ +# Copyright (C) 1997, 1998 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 2 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +# Please email any bugs, comments, and/or additions to this file to: +# bug-gdb@prep.ai.mit.edu + +# GDB tests for sized enumerations + +# This is aimed at HP-UX systems. The HP C compiler +# allows specifying "char" or "short" for an enum, to +# indicate that it is 1 or 2 bytes long. + +# This file was written by Satish Pai <pai@apollo.hp.com> +# 1997-09-24 + +if $tracelevel then { + strace $tracelevel + } + +# +# test running programs +# +set prms_id 0 +set bug_id 0 + +set testfile "sized-enum" +set srcfile ${testfile}.c +set binfile ${objdir}/${subdir}/${testfile} + +if [get_compiler_info ${binfile}] { + return -1 +} + +if {[skip_hp_tests $gcc_compiled]} then { continue } + +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } { + gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail." +} + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +# +# set it up at a breakpoint so we can play with the variable values +# + +if ![runto_main] then { + perror "couldn't run to breakpoint" + continue +} + +# set a breakpoint and go there +send_gdb "break 34\n" +gdb_expect { + -re "Breakpoint \[0-9\] at.*$gdb_prompt $" { pass "set break 34" } + -re "$gdb_prompt $" { fail "set break 34" } + timeout { fail "(timeout) set break 34" } +} +send_gdb "continue\n" +gdb_expect { + -re "Continuing\\.\r\n\r\nBreakpoint \[0-9\]*, main....at.*sized-enum\\.c:34\r\n34.*\r\n$gdb_prompt $" { pass "continue" } + -re "$gdb_prompt $" { fail "continue" } + timeout { fail "(timeout) continue" } +} + +# print stuff +send_gdb "print normal\n" +gdb_expect { + -re "\\$\[0-9\]* = \\{red, blue, green\\}.*$gdb_prompt $" { pass "print normal" } + -re "$gdb_prompt $" { fail "print normal" } + timeout { fail "(timeout) print normal" } +} +send_gdb "print small\n" +gdb_expect { + -re "\\$\[0-9\]* = \\{pink, cyan, grey\\}.*$gdb_prompt $" { pass "print small" } + -re "$gdb_prompt $" { fail "print small" } + timeout { fail "(timeout) print small" } +} +send_gdb "print tiny\n" +gdb_expect { + -re "\\$\[0-9\]* = \\{orange, yellow, brown\\}.*$gdb_prompt $" { pass "print tiny" } + -re "$gdb_prompt $" { fail "print tiny" } + timeout { fail "(timeout) print tiny" } +} + +# print type sizes +send_gdb "print sizeof (Normal)\n" +gdb_expect { + -re "\\$\[0-9\]* = 4.*$gdb_prompt $" { pass "print sizeof (Normal)" } + -re "$gdb_prompt $" { fail "print sizeof (Normal)" } + timeout { fail "(timeout) print sizeof (Normal)" } +} +send_gdb "print sizeof (Small)\n" +gdb_expect { + -re "\\$\[0-9\]* = 2.*$gdb_prompt $" { pass "print sizeof (Small)" } + -re "$gdb_prompt $" { fail "print sizeof (Small)" } + timeout { fail "(timeout) print sizeof (Small)" } +} +send_gdb "print sizeof (Tiny)\n" +gdb_expect { + -re "\\$\[0-9\]* = 1.*$gdb_prompt $" { pass "print sizeof (Tiny)" } + -re "$gdb_prompt $" { fail "print sizeof (Tiny)" } + timeout { fail "(timeout) print sizeof (Tiny)" } +} + +# print types +send_gdb "ptype normal\n" +gdb_expect { + -re "type = enum Normal \\{red, blue, green\\} \\\[3\\\].*$gdb_prompt $" { pass "ptype normal" } + -re "$gdb_prompt $" { fail "ptype normal" } + timeout { fail "(timeout) ptype normal" } +} +send_gdb "ptype small\n" +gdb_expect { + -re "type = short enum Small \\{pink, cyan, grey\\} \\\[3\\\].*$gdb_prompt $" { pass "ptype small" } + -re "$gdb_prompt $" { fail "ptype small" } + timeout { fail "(timeout) ptype small" } +} +send_gdb "ptype tiny\n" +gdb_expect { + -re "type = char enum Tiny \\{orange, yellow, brown\\} \\\[3\\\].*$gdb_prompt $" { pass "ptype tiny" } + -re "$gdb_prompt $" { fail "ptype tiny" } + timeout { fail "(timeout) ptype tiny" } +} + +# convert to int +send_gdb "print (int) blue\n" +gdb_expect { + -re "\\$\[0-9\]* = 1.*$gdb_prompt $" { pass "print (int) blue" } + -re "$gdb_prompt $" { fail "print (int) blue" } + timeout { fail "(timeout) print (int) blue" } +} +send_gdb "print (int) cyan\n" +gdb_expect { + -re "\\$\[0-9\]* = 1.*$gdb_prompt $" { pass "print (int) cyan" } + -re "$gdb_prompt $" { fail "print (int) cyan" } + timeout { fail "(timeout) print (int) cyan" } +} +send_gdb "print (int) yellow\n" +gdb_expect { + -re "\\$\[0-9\]* = 1.*$gdb_prompt $" { pass "print (int) yellow" } + -re "$gdb_prompt $" { fail "print (int) yellow" } + timeout { fail "(timeout) print (int) yellow" } +} + + + diff --git a/gdb/testsuite/gdb.hp/so-thresh.exp b/gdb/testsuite/gdb.hp/so-thresh.exp new file mode 100644 index 00000000000..1977e92a7d9 --- /dev/null +++ b/gdb/testsuite/gdb.hp/so-thresh.exp @@ -0,0 +1,362 @@ +# Copyright (C) 1997, 1998 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 2 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +# Please email any bugs, comments, and/or additions to this file to: +# bug-gdb@prep.ai.mit.edu + +if $tracelevel then { + strace $tracelevel + } + +set prms_id 0 +set bug_id 0 + +# are we on a target board +if ![isnative] then { + return +} + +set testfile "so-thresh" +set srcfile ${testfile}.c +set binfile ${objdir}/${subdir}/${testfile} + +if [get_compiler_info ${binfile}] { + return -1 +} + +# This testcase is automatically generated, via the +# gen-so-thresh program, which also should +# live in this same directory. +# +# The generator produces: +# - so-thresh.c +# - 3 .c files named libXX-so-thresh.c +# - a makefile named so-thresh.mk with a +# target named "so-thresh" that will compile +# and link the testcase +# +# Making with so-thresh.mk produces: +# - so-thresh +# - 3 shared libraries that are linked against, named +# libXX-so-thresh.sl +# +# We build gen-so-thresh, run it, and then make with +# the makefile it produces. +# +set genfile gen_${testfile} +set gen_srcfile ${genfile}.c +set gen_binfile ${genfile} +set gen_makefile ${testfile}.mk + +# This testcase is relatively large, and therefore can take awhile to +# load. We'd best set the timeout to something suitable, or we may +# seem to fail... +# +set timeout 60 + +# It's easiest to build and run the testcase in this directory. (Linking +# against shlibs puts relative paths to them in the a.out, so it's best +# if we remain in this directory for the entire test run.) +# +#cd gdb.base + +# Ensure that the testcase is built. This may cause the generator to +# be built & run. +# +# Warning! The final link of this testcase is not for the +# faint-hearted nor under-disked machine! +# +# ??rehrauer: I tried for a very long time to get make invoked +# directly here, rather than invoking a script to do it. I +# finally gave up in frustration; I'm not sure why it wouldn't +# work that way, but this method DOES work, albeit clumsily. +# + +send_user "Making with ${testfile}.mk ...\n" +# remote_exec build "sh -c \\\"cd ${objdir}/${subdir}\\; make -v -f ${srcdir}/${subdir}/${testfile}.mk clean require_shlibs all SRCDIR=${srcdir}/${subdir} OBJDIR=${objdir}/${subdir}\\\"" +remote_exec build "sh -c \\\"cd ${objdir}/${subdir}\\; make -v -f ${srcdir}/${subdir}/${testfile}.mk clean require_shlibs all SRCDIR=${srcdir}/${subdir} OBJDIR=${objdir}/${subdir}\\\"" + +# Only HP-UX (and any other platforms using SOM shared libraries, I +# guess) interprets the auto-solib-add variable as a threshhold, +# rather than a boolean that strictly enables or disables automatic +# loading of shlib symbol tables. +# +# On HP-UX, it is the size threshhold (in megabytes) at which to +# stop auto loading of symbol tables. +# +if ![istarget "hppa*-hp-hpux*"] then { + setup_xfail "*-*-*" +} + +# Start with a fresh gdb +# +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +# This is a test of gdb's ability on HP-UX to stop automatically +# loading symbols of shared libraries, when the total size of the +# debugger's symbol table reaches a specified threshhold. +# + +# On HP-UX, the help text for auto-solib-add mentions that it +# serves as a threshhold. +# +send_gdb "help set auto-solib-add\n" +gdb_expect { + -re "Set autoloading size threshold .in megabytes. of shared library symbols.* +If nonzero, symbols from all shared object libraries will be loaded.* +automatically when the inferior begins execution or when the dynamic linker.* +informs gdb that a new library has been loaded, until the symbol table.* +of the program and libraries exceeds this threshold.* +Otherwise, symbols must be loaded manually, using `sharedlibrary'.*$gdb_prompt $"\ + {pass "help set auto-solib-add"} + -re "$gdb_prompt $"\ + {fail "help set auto-solib-add"} + timeout {fail "(timeout) help set auto-solib-add"} +} + +# On HP-UX, the threshhold is by default set to 50, which means +# 50 megabytes. +# +send_gdb "show auto-solib-add\n" +gdb_expect { + -re "Autoloading size threshold .in megabytes. of shared library symbols is 100.*$gdb_prompt $"\ + {pass "show auto-solib-add (default is 100)"} + -re "$gdb_prompt $"\ + {fail "show auto-solib-add (default is 100)"} + timeout {fail "(timeout) show auto-solib-add (default is 100)"} +} + +send_gdb "set auto-solib-add 1\n" +gdb_expect { + -re ".*$gdb_prompt $" + {pass "set auto-solib-add to 1"} + -re ".*$gdb_prompt $" + {fail "set auto-solib-add to 1"} + timeout {fail "(timeout) set auto-solib-add to 1"} +} + + +# We have manually verified that our testcase exceeds 1 Mbytes +# of heap space in GDB to hold the symbols for the main program +# and all associated linked-against libraries. Thus, when we +# run to the program's main, and therefore notice all the linked- +# against shlibs, we expect to hit the threshhold. +# +# (Note that we're not using the expect [runto main] function here, +# 'cause we want to match on output from the run command. +# +send_gdb "break main\n" +gdb_expect { + -re "Breakpoint \[0-9\]* at.*$gdb_prompt $"\ + {pass "set break at main"} + -re "$gdb_prompt $"\ + {fail "set break at main"} + timeout {fail "(timeout) set break at main"} +} + +send_gdb "run\n" +gdb_expect { + -re ".*warning. Symbols for some libraries have not been loaded, because.* +doing so would exceed the size threshold specified by auto-solib-add.* +To manually load symbols, use the 'sharedlibrary' command.* +To raise the threshold, set auto-solib-add to a larger value and rerun.* +the program.*$gdb_prompt $"\ + {pass "run to main hit auto-solib-add threshold"} + -re "$gdb_prompt $"\ + {fail "run to main hit auto-solib-add threshold"} + timeout {fail "(timeout) run to main hit auto-solib-add threshold"} +} + +# Verify that "info share" mentions something about libraries whose +# symbols weren't loaded. +# +# We'll assume that at least the last two shlib's symbols weren't +# loaded. As a side-effect of matching this pattern, the text start +# address of the last one is captured in expect_out(1,string). +# (we'll need it for the 'add-symbol-file' command in a nonce...) +# +send_gdb "info sharedlibrary\n" +gdb_expect { + -re ".*lib01_$testfile.sl .*symbols not loaded.*0x\[0-9\]* (0x\[0-9a-fA-F\]*).*$gdb_prompt $"\ + { send_gdb "add-symbol-file lib02_$testfile.sl $expect_out(1,string)\n" + gdb_expect { + -re "add symbol table.*y or n.*$"\ + {send_gdb "y\n" + gdb_expect { + -re "$gdb_prompt $" {pass "add-symbol-file and info sharedlib"} + timeout {fail "(timeout) add-symbol-file and info sharedlib"} + }} + -re "$gdb_prompt $"\ + {fail "add-symbol-file and info sharedlib"} + timeout {fail "(timeout) add-symbol-file and info sharedlib"} + } + } + -re "$gdb_prompt $"\ + {fail "info sharedlibrary shows shlibs with unloaded symbols"} + timeout {fail "(timeout) info sharedlibrary shows shlibs with unloaded symbols"} +} + +# Verify that we can manually load the symbol table of a library +# whose symbols weren't loaded. (We'll pick the last one.) +# + +# I moved this test inside the one above, because the expect_out array is not ok if the +# previous test has failed, and expect would error out (elz) +# +#send_gdb "add-symbol-file lib02_$testfile.sl $expect_out(1,string)\n" +#gdb_expect { +# -re "add symbol table.*y or n.*$"\ +# {send_gdb "y\n" +# gdb_expect { +# -re "$gdb_prompt $" {pass "add-symbol-file"} +# timeout {fail "(timeout) add-symbol-file"} +# }} +# -re "$gdb_prompt $"\ +# {fail "add-symbol-file"} +# timeout {fail "(timeout) add-symbol-file"} +#} + +# Verify that we can manually load the symbols for all libraries +# which weren't already loaded. +# +# Warning! On a machine with little free swap space, this may +# fail! +# +send_gdb "sharedlibrary\n" +gdb_expect { + -re "Reading symbols from.*done.*$gdb_prompt $"\ + {pass "sharedlibrary"} + -re "$gdb_prompt $"\ + {fail "sharedlibrary"} + timeout {fail "(timeout) sharedlibrary"} +} + +# Rerun the program, this time verifying that we can set the +# threshhold high enough to avoid hitting it. +# +# It appears that gdb isn't freeing memory when rerunning, as one +# would expect. To avoid potentially hitting a virtual memory +# ceiling, start with a fresh gdb. +# +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +send_gdb "break main\n" +gdb_expect { + -re "Breakpoint \[0-9\]* at.*$gdb_prompt $"\ + {pass "set break at main"} + -re "$gdb_prompt $"\ + {fail "set break at main"} + timeout {fail "(timeout) set break at main"} +} + +send_gdb "set auto-solib-add 9999\n" +gdb_expect { + -re "$gdb_prompt $"\ + {pass "set auto-solib-add threshold to practical infinity"} + timeout {fail "(timeout) set auto-solib-add threshold to practical infinity"} +} +send_gdb "run\n" +gdb_expect { + -re ".*warning. Symbols for some libraries have not been loaded, because.* +doing so would exceed the size threshold specified by auto-solib-add.* +To manually load symbols, use the 'sharedlibrary' command.* +To raise the threshold, set auto-solib-add to a larger value and rerun.* +the program.*$gdb_prompt $"\ + {fail "rerun threshold at practical infinity (still hit threshold)"} + -re "$gdb_prompt $"\ + {pass "rerun with threshold at practical infinity"} + timeout {fail "(timeout) rerun with threshold at practical infinity"} +} + +# Rerun the program, this time altogether disabling the auto loading +# feature. There should be no information at all about shared +# libraries now. +# +# ??rehrauer: Personally, I'd call that a bug, since it doesn't give +# you the ability to manually load single shlibs (you need the text +# start address that 'info share' normall gives you). On the other +# hand, one can easily choose to load them all... +# +# It appears that gdb isn't freeing memory when rerunning, as one +# would expect. To avoid potentially hitting a virtual memory +# ceiling, start with a fresh gdb. +# +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +send_gdb "break main\n" +gdb_expect { + -re "Breakpoint \[0-9\]* at.*$gdb_prompt $"\ + {pass "set break at main"} + -re "$gdb_prompt $"\ + {fail "set break at main"} + timeout {fail "(timeout) set break at main"} +} + +send_gdb "set auto-solib-add 0\n" +gdb_expect { + -re "$gdb_prompt $"\ + {pass "set auto-solib-add threshold to 0"} + timeout {fail "(timeout) set auto-solib-add threshold to 0"} +} +send_gdb "run\n" +gdb_expect { + -re ".*warning. Symbols for some libraries have not been loaded, because.* +doing so would exceed the size threshold specified by auto-solib-add.* +To manually load symbols, use the 'sharedlibrary' command.* +To raise the threshold, set auto-solib-add to a larger value and rerun.* +the program.*$gdb_prompt $"\ + {fail "rerun threshold at 0 (still hit threshold)"} + -re "$gdb_prompt $"\ + {pass "rerun with threshold at 0"} + timeout {fail "(timeout) rerun with threshold at 0"} +} + +# Verify that we can still manually load symbols for all libraries. +# (We'll assume that if the last shlib's symbols are loaded, that +# all of them were.) +# +# Note that we set the GDB "height" variable to prevent GDB from +# prompting +# +# Warning! On a machine with little free swap space, this may +# fail! +# +send_gdb "set height 9999\n" +gdb_expect { + -re "$gdb_prompt $"\ + {pass "set screen page height to practical infinity"} + timeout {fail "(timeout) set screen page height to practical infinity"} +} +send_gdb "sharedlibrary\n" +gdb_expect { + -re ".*Reading symbols from .*/lib02-so-thresh\\.sl\\.\\.\\.done\\..*$gdb_prompt $"\ + {pass "manually load all symbols"} + -re "$gdb_prompt $"\ + {fail "manually load all symbols"} + timeout {fail "(timeout) manually load all symbols"} +} + +#cd .. +return 0 diff --git a/gdb/testsuite/gdb.hp/so-thresh.linkopts b/gdb/testsuite/gdb.hp/so-thresh.linkopts new file mode 100644 index 00000000000..547b4ebb1fe --- /dev/null +++ b/gdb/testsuite/gdb.hp/so-thresh.linkopts @@ -0,0 +1,5 @@ +# Linker options for so-thresh test +-l00-so-thresh +-l01-so-thresh +-l02-so-thresh + diff --git a/gdb/testsuite/gdb.hp/so-thresh.mk b/gdb/testsuite/gdb.hp/so-thresh.mk new file mode 100644 index 00000000000..343185cbe86 --- /dev/null +++ b/gdb/testsuite/gdb.hp/so-thresh.mk @@ -0,0 +1,73 @@ +# Make file for so-thresh test + +OBJDIR=. +SRCDIR=. +CFLAGS = +DA1.1 -g + +# This is how to build this generator. +gen-so-thresh.o: ${SRCDIR}/gen-so-thresh.c + $(CC) $(CFLAGS) -o gen-so-thresh.o -c ${SRCDIR}/gen-so-thresh.c +gen-so-thresh: gen-so-thresh.o + $(CC) $(CFLAGS) -o gen-so-thresh gen-so-thresh.o + +# This is how to run this generator. +# This target should be made before the 'all' target, +# to ensure that the shlib sources are all available. +require_shlibs: gen-so-thresh + if ! [ -a lib00-so-thresh.c ] ; then \ + gen-so-thresh ; \ + fi + if ! [ -a lib01-so-thresh.c ] ; then \ + gen-so-thresh ; \ + fi + if ! [ -a lib02-so-thresh.c ] ; then \ + gen-so-thresh ; \ + fi + +# This is how to build all the shlibs. +# Be sure to first make the require_shlibs target! +lib00-so-thresh.o: lib00-so-thresh.c + $(CC) $(CFLAGS) +Z -o lib00-so-thresh.o -c lib00-so-thresh.c +lib00-so-thresh.sl: lib00-so-thresh.o + $(LD) $(LDFLAGS) -b -o lib00-so-thresh.sl lib00-so-thresh.o +lib01-so-thresh.o: lib01-so-thresh.c + $(CC) $(CFLAGS) +Z -o lib01-so-thresh.o -c lib01-so-thresh.c +lib01-so-thresh.sl: lib01-so-thresh.o + $(LD) $(LDFLAGS) -b -o lib01-so-thresh.sl lib01-so-thresh.o +lib02-so-thresh.o: lib02-so-thresh.c + $(CC) $(CFLAGS) +Z -o lib02-so-thresh.o -c lib02-so-thresh.c +lib02-so-thresh.sl: lib02-so-thresh.o + $(LD) $(LDFLAGS) -b -o lib02-so-thresh.sl lib02-so-thresh.o + + + + +# For convenience, here's names for all pieces of all shlibs. +SHLIB_SOURCES = \ + lib00-so-thresh.c \ + lib01-so-thresh.c \ + lib02-so-thresh.c + +SHLIB_OBJECTS = $(SHLIB_SOURCES:.c=.o) +SHLIBS = $(SHLIB_SOURCES:.c=.sl) +SHLIB_NAMES = $(SHLIB_SOURCES:.c=) +EXECUTABLES = $(SHLIBS) gen-so-thresh so-thresh +OBJECT_FILES = $(SHLIB_OBJECTS) gen-so-thresh.o so-thresh.o + +shlib_objects: $(SHLIB_OBJECTS) +shlibs: $(SHLIBS) + +# This is how to build the debuggable testcase that uses the shlibs. +so-thresh.o: so-thresh.c + $(CC) $(CFLAGS) -o so-thresh.o -c so-thresh.c +so-thresh: shlibs so-thresh.o + $(LD) $(LDFLAGS) -o so-thresh -lc -L${OBJDIR} -c so-thresh.linkopts /opt/langtools/lib/end.o /lib/crt0.o so-thresh.o + +# Yeah, but you should first make the require_shlibs target! +all: so-thresh gen-so-thresh + +# To remove everything built via this makefile... +clean: + rm -f lib0*-so-thresh.* + rm -f *.o gen-so-thresh so-thresh.linkopts so-thresh.c + rm -f so-thresh diff --git a/gdb/testsuite/gdb.hp/so-thresh.sh b/gdb/testsuite/gdb.hp/so-thresh.sh new file mode 100755 index 00000000000..dc90270a1e1 --- /dev/null +++ b/gdb/testsuite/gdb.hp/so-thresh.sh @@ -0,0 +1,12 @@ +#!/bin/ksh +# +# This script is a "wrapper" to use the so-thresh.mk +# Makefile. See the comments in so-thresh.exp +# regarding why this script exists. +# + +#set -o xtrace +#set -o verbose + +MAKEFLAGS= +make -v -f so-thresh.mk require_shlibs all diff --git a/gdb/testsuite/gdb.hp/start-stop.c b/gdb/testsuite/gdb.hp/start-stop.c new file mode 100644 index 00000000000..dcf2c7ebb10 --- /dev/null +++ b/gdb/testsuite/gdb.hp/start-stop.c @@ -0,0 +1,161 @@ +/* BeginSourceFile start_stop.c + + This file creates and deletes threads, so that wdb + can be tested on thread delete. + + To compile: + + cc -Ae +DA1.0 -g -o start_stop -lpthread start_stop.c + + To run: + + start_stop --normal run + start_stop 1 --waits in each thread to keep it alive. +*/ + +#include <unistd.h> +#include <stdlib.h> +#include <stdio.h> +#include <assert.h> +#include <pthread.h> + +#define TRUE 1 +#define FALSE 0 +#define OUTER_LOOP_COUNT 3 +#define N_THREADS 3 +#define MAX_LOCAL_VAL 40 + +/* Uncomment to turn on debugging output */ +/* #define START_DEBUG */ + +/* True if waiting for attach. + */ +int wait_here; + +/* Thing to check for debugging purposes. +*/ +int a_global = 0; + +/* Thread-local storage. + */ +__thread int a_thread_local; + +/* Check the results of thread-local storage. + */ +int thread_local_val[ N_THREADS ]; +int val_debugger_saw[ N_THREADS ]; + +/* Routine for each thread to run, does nothing. + */ +void *spin( vp ) + void * vp; +{ + int me = (int) vp; + int i; + +#ifdef START_DEBUG + printf( "== In thread %d\n", me ); +#endif + + a_global++; + + a_thread_local = 0; + for( i = 0; i < a_global; i++ ) { + a_thread_local += i; + } + + thread_local_val[ me ] = a_thread_local; /* Line 67 */ + + printf( "== Thread %d, a_thread_local is %d\n", + (int) vp, a_thread_local ); + + if( wait_here ) { + /* Extend life of thread to extend life of thread-local var. + * This makes life easier for human debugging (though you'd + * probably want to make the delay longer). + */ + sleep( 5 ); + } +} + +void +do_pass( pass ) + int pass; +{ + int i; + pthread_t t[ N_THREADS ]; + int err; + + for( i = 0; i < N_THREADS; i++) { + thread_local_val[i] = 0; + val_debugger_saw[i] = 0; + } + + /* Start N_THREADS threads, then join them so + * that they are terminated. + */ + for( i = 0; i < N_THREADS; i++ ) { + err = pthread_create( &t[i], NULL, spin, (void *)i ); + if( err != 0 ) { + printf( "== Start/stop, error in thread %d create\n", i ); + } + } + + for( i = 0; i < N_THREADS; i++ ) { + err = pthread_join(t[i], NULL ); /* Line 105 */ + if( err != 0 ) { /* Line 106 */ + printf( "== Start/stop, error in thread %d join\n", i ); + } + } + + i = 10; /* Line 109. Null line for setting bpts on. */ + +/*#ifdef START_DEBUG*/ + for( i = 0; i < N_THREADS; i++) { + printf( " Local in thread %d was %d, debugger saw %d\n", + i, thread_local_val[i], val_debugger_saw[i] ); + } + printf( "== Pass %d done\n", pass ); +/*#endif*/ + +} + +void +do_it() +{ + /* We want to start some threads and then + * end them, and then do it again and again + */ + int i; + int dummy; + + for( i = 0; i < OUTER_LOOP_COUNT; i++ ) { + do_pass( i ); + dummy = i; /* Line 134, null line for setting bps on */ + } +} + +main( argc, argv ) +int argc; +char **argv; +{ + wait_here = FALSE; + if((argc > 1) && (0 != argv )) { + if( 1 == atoi( argv[1] ) ) + wait_here = TRUE; + } + +#ifdef START_DEBUG + printf( "== Test starting\n" ); +#endif + + do_it(); + +#ifdef START_DEBUG + printf( "== Test done\n" ); +#endif + + return(0); +} + +/* EndSourceFile */ diff --git a/gdb/testsuite/gdb.hp/start-stop.exp b/gdb/testsuite/gdb.hp/start-stop.exp new file mode 100644 index 00000000000..4f70f51cede --- /dev/null +++ b/gdb/testsuite/gdb.hp/start-stop.exp @@ -0,0 +1,360 @@ +# start_stop.exp -- Expect script to test a threaded pgm which has terminating threads +# Copyright (C) 1992 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 2 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +# Please email any bugs, comments, and/or additions to this file to: +# bug-gdb@prep.ai.mit.edu + +# Comment out for now, since this test is (sometimes?) hanging on 11.0 +# +# return 0 + +# use this to debug: +# +#log_user 1 + +# Thread stuff is _slow_; prepare for long waits. +# +# Further, this test has some "null" lines designed +# to consume output from gdb that was too late to be +# matched (sequence is "gdb_test" sends; timeout and +# on to next send; result finally comes in; mismatch). +# +# The null command is 'gdb_test "p \$pc" ".*" ""' +# NOTE: this command undoes any up/down stuff! +# +proc pre_timeout {} { + global timeout + + set timeout [expr "$timeout + 100"] +} + +proc post_timeout {} { + global timeout + global oldtimeout + + set timeout $oldtimeout + gdb_test "p \$pc" ".*" "" +} + +if $tracelevel then { + strace $tracelevel +} + +if { ![istarget "hppa*-*-hpux10.30"] && ![istarget "hppa*-*-hpux11.*"] } { + verbose "HPUX thread test ignored for non-hppa or pre-HP/UX-10.30 targets." + return 0 +} + +set testfile start-stop +set srcfile ${srcdir}/${subdir}/${testfile}.c +set binfile ${objdir}/${subdir}/${testfile} + +if [get_compiler_info ${binfile}] { + return -1 +} + +# To build the executable we need to link against the thread library. +# +# cc -Ae -g -o start-stop -lpthread start-stop.c +# +#compile "${srcfile} -Ae -g -lpthread -o ${binfile}" + +if {$gcc_compiled == 0} { + set additional_flags "additional_flags=-Ae" +} else { + set additional_flags "" +} + +if { [gdb_compile "${srcdir}/${subdir}/${testfile}.c" "${binfile}.o" object [list debug $additional_flags]] != "" } { + gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail." +} +remote_exec build "ld /usr/ccs/lib/crt0.o ${binfile}.o -lcl -lpthread -lc /opt/langtools/lib/end.o -o ${binfile}" + + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir + +gdb_load ${binfile} +if ![runto_main] then { + fail "Can't run to main" + return 0 +} + +set oldtimeout $timeout +#set timeout [expr "$timeout + 200"] +set oldverbose $verbose +#set verbose 40 + +gdb_test "b do_pass" ".*" "set do_pass bp" +gdb_test "c" ".*Breakpoint.*do_pass.*" "run to do_pass" + +# Should be only one thread. +# +pre_timeout +send_gdb "info thread\n" +gdb_expect { + -re ".*2 process.*$gdb_prompt $" { fail "Old code for 'thread.c'" } + -re ".*2 system thread.*1 sys.*$gdb_prompt $" { fail "Too many threads" } + -re ".*1 system thread.*$gdb_prompt $" { pass "Just one thread" } + -re ".*$gdb_prompt $" { fail "no thread info" } + timeout { fail "timeout on info thread 1" } +} +post_timeout + +# Run to a point after the thread creates (105 is just +# before the first join). +# +# The "== Thread" stuff is output from the computing threads. +# +gdb_test "b 105" ".*Breakpoint.*" "set 105 bp" + +pre_timeout +send_gdb "c\n" +gdb_expect { + -re ".*== Thread.*== Thread.*== Thread.*105.*$gdb_prompt $" { + pass "new threads created and ended" + set threads_exist 0 + } + -re ".*== Thread.*== Thread.*105.*$gdb_prompt $" { + pass "new threads created and ended" + set threads_exist 1 + } + -re ".*== Thread.*.*105.*$gdb_prompt $" { + pass "new threads created and ended" + set threads_exist 2 + } + -re ".*New thread.*New th.*New th.*105.*$gdb_prompt $" { + pass "new threads created" + set threads_exist 3 + } + -re ".*Breakpoint.*105.*$gdb_prompt $" { + set threads_exist 0 + fail "didn't see any threads" + } + -re ".*$gdb_prompt $" { + set threads_exist 0 + fail "didn't even hit bp" + } + timeout { + set threads_exist -1 + fail "timeout on continue" + } +} + +# Look at the threads again. We expect that some of +# the threads may have already finished execution. +# +send_gdb "info thread\n" +gdb_expect { + -re ".*4.*3.*2.* 1.*thread.*$gdb_prompt $" { set seen_threads 3 } + -re ".*3.*2.* 1.*thread.*$gdb_prompt $" { set seen_threads 2 } + -re ".*2.* 1.*thread.*$gdb_prompt $" { set seen_threads 1 } + -re ".* 1.*thread.*$gdb_prompt $" { set seen_threads 0 } + -re ".*$gdb_prompt $" { set seen_threads 0 } + timeout { + set seen_threads -10 + fail "timeout on second info thread" + } +} +post_timeout + +if { $seen_threads == $threads_exist } { + pass "saw all threads that existed" +} else { + if { $seen_threads > $threads_exist } { + fail "may have seen threads that didn't finish exiting yet" + } else { + fail "didn't see live threads" + } +} + +gdb_test "cle" ".*Deleted.*" "del bp at 105" + +# Check that threads are being consumed at the join call. +# We expect to join three times. If we ever see the bp at +# 111, we've gone too far. +# +gdb_test "b 106" ".*Breakpoint.*106.*" "set bp at 106" +gdb_test "b 111" ".*Breakpoint.*111.*" "set bp at 111" + +# This one is sure: we're already in the loop. +# +gdb_test "c" ".*Breakpoint.*106.*" "hit bp at 106 1st time, 2 left" + +# Did we go around the loop again? +# +send_gdb "c\n" +gdb_expect { + -re ".*Breakpoint.*111.*" { + fail "didn't join right 1" + gdb_test "cle" ".*" "" + } + -re ".*Breakpoint.*106.*" { + pass "hit bp at 106 2nd time, 1 left" + send_gdb "c\n" + gdb_expect { + -re ".*Breakpoint.*111.*" { + fail "didn't join right 2" + gdb_test "cle" ".*" "" + } + -re ".*Breakpoint.*106.*" { + pass "hit bp at 106 3rd time, 0 left" + gdb_test "cle" ".*" "" + gdb_test "c" ".*Breakpoint.*111.*" "" + gdb_test "cle" ".*" "" + } + timeout { fail "timeout going around the loop"} + } + } + timeout { fail "timeout getting to 106"} +} + +# Should only be one thread now. +# +pre_timeout +send_gdb "info thread\n" +gdb_expect { + -re ".*2 system thread.*1 sys.*$gdb_prompt $" { fail "Too many threads" } + -re ".*1 system th.*$gdb_prompt $" { pass "Just one thread" } + -re ".*$gdb_prompt $" { pass "One thread shown as no threads, ok" } + timeout { fail "timeout third info thread" } +} +post_timeout + +#============================= Begin pass 2 =========== +# +# Ok, go around again +# +gdb_test "c" ".*Breakpoint.*do_pass.*" "hit do_pass bp again 2" +gdb_test "b 105" ".*Breakpoint.*" "set 105 bp 2" + +pre_timeout +send_gdb "c\n" +gdb_expect { + -re ".*== Thread.*== Thread.*== Thread.*$gdb_prompt $" { + pass "new threads created and ended 2" + set threads_exist 0 + } + -re ".*== Thread.*== Thread.*$gdb_prompt $" { + pass "new threads created and ended 2" + set threads_exist 1 + } + -re ".*== Thread.*$gdb_prompt $" { + pass "new threads created and ended 2" + set threads_exist 2 + } + -re ".*New system thread.*New sys.*New.*105.*$gdb_prompt $" { + pass "new threads created 2" + set threads_exist 3 + } + timeout { + set threads_exist -1 + fail "timeout on continue 2" + } +} + +# Look at the threads again. We expect that some of +# the threads may have already finished execution. +# +send_gdb "info thread\n" +gdb_expect { + -re ".*4.*3.*2.* 1.*thread.*$gdb_prompt $" { set seen_threads 3 } + -re ".*3.*2.* 1.*thread.*$gdb_prompt $" { set seen_threads 2 } + -re ".*2.* 1.*thread.*$gdb_prompt $" { set seen_threads 1 } + -re ".* 1.*thread.*$gdb_prompt $" { set seen_threads 0 } + -re ".*$gdb_prompt $" { set seen_threads 0 } + timeout { + set seen_threads -10 + fail "timeout on second info thread 2" + } +} +post_timeout + +if { $seen_threads == $threads_exist } { + pass "saw all threads that existed" +} else { + if { $seen_threads > $threads_exist } { + fail "may have seen threads that didn't finish exiting yet 2" + } else { + fail "didn't see live threads 2" + } +} + +gdb_test "cle" ".*Deleted.*" "del bp at 105 2" + +# Check that threads are being consumed at the join call. +# We expect to join three times. If we ever see the bp at +# 111, we've gone too far. +# +gdb_test "b 106" ".*Breakpoint.*106.*" "set bp at 106 2" +gdb_test "b 111" ".*Breakpoint.*111.*" "set bp at 111 2" + +# This one is sure: we're already in the loop. +# +gdb_test "c" ".*Breakpoint.*106.*" "hit bp at 106 1st time, 2 left 2" + +# Did we go around the loop again? +# +send_gdb "c\n" +gdb_expect { + -re ".*Breakpoint.*111.*" { + fail "didn't join right 1, pass 2" + gdb_test "cle" ".*" "" + } + -re ".*Breakpoint.*106.*" { + pass "hit bp at 106 2nd time, 1 left, pass 2" + send_gdb "c\n" + gdb_expect { + -re ".*Breakpoint.*111.*" { + fail "didn't join right 2, pass 2" + gdb_test "cle" ".*" "" + } + -re ".*Breakpoint.*106.*" { + pass "hit bp at 106 3rd time, 0 left, pass 2" + gdb_test "cle" ".*" "" + gdb_test "c" ".*Breakpoint.*111.*" "" + gdb_test "cle" ".*" "" + } + timeout { fail "timeout going around loop, pass 2"} + } + } + timeout { fail "timeout continue to 106, pass 2"} +} + +# Should only be one thread now. +# +pre_timeout +send_gdb "info thread\n" +gdb_expect { + -re ".*2 system thread.*1 sys.*$gdb_prompt $" { fail "Too many threads, pass 2" } + -re ".*1 system thread.*$gdb_prompt $" { pass "Just one thread, pass 2" } + -re ".*$gdb_prompt $" { pass "One thread shown as no threads, ok, pass 2" } + timeout { fail "timeout last info thread, pass 2" } +} +post_timeout + +# Done! +# +gdb_exit + +set timeout $oldtimeout +set verbose $oldverbose + +# execute_anywhere "rm -f ${binfile}" +# +return 0 diff --git a/gdb/testsuite/gdb.hp/sum.c b/gdb/testsuite/gdb.hp/sum.c new file mode 100644 index 00000000000..c28afa53856 --- /dev/null +++ b/gdb/testsuite/gdb.hp/sum.c @@ -0,0 +1,15 @@ +/* This is a sample program for the HP/DDE debugger. */ +#include <stdio.h> + +#ifdef __STDC__ +int sum(int list[], int low, int high) +#else +int sum(list, low, high) +int list[], low, high; +#endif + { + int i, s = 0; + for (i = low; i <= high; i++) + s += list[i]; + return(s); + } diff --git a/gdb/testsuite/gdb.hp/templ-hp.cc b/gdb/testsuite/gdb.hp/templ-hp.cc new file mode 100644 index 00000000000..25241dc6dbf --- /dev/null +++ b/gdb/testsuite/gdb.hp/templ-hp.cc @@ -0,0 +1,785 @@ +/* This test code is from Wendell Baker (wbaker@comet.berkeley.edu) */ + +#include <stddef.h> + +int a_i; +char a_c; +double a_d; + +typedef void *Pix; + +int +f(int i) +{ return 0; } + +int +f(int i, char c) +{ return 0; } + +int +f(int i, char c, double d) +{ return 0; } + +int +f(int i, char c, double d, char *cs) +{ return 0; } + +int +f(int i, char c, double d, char *cs, void (*fig)(int, char)) +{ return 0; } + +int +f(int i, char c, double d, char *cs, void (*fig)(char, int)) +{ return 0; } + +class R { +public: + int i; +}; +class S { +public: + int i; +}; +class T { +public: + int i; +}; + +char g(char, const char, volatile char) +{ return 'c'; } +char g(R, char&, const char&, volatile char&) +{ return 'c'; } +char g(char*, const char*, volatile char*) +{ return 'c'; } +char g(S, char*&, const char*&, volatile char*&) +{ return 'c'; } + +signed char g(T,signed char, const signed char, volatile signed char) +{ return 'c'; } +signed char g(T, R, signed char&, const signed char&, volatile signed char&) +{ return 'c'; } +signed char g(T, signed char*, const signed char*, volatile signed char*) +{ return 'c'; } +signed char g(T, S, signed char*&, const signed char*&, volatile signed char*&) +{ return 'c'; } + +unsigned char g(unsigned char, const unsigned char, volatile unsigned char) +{ return 'c'; } +unsigned char g(R, unsigned char&, const unsigned char&, volatile unsigned char&) +{ return 'c'; } +unsigned char g(unsigned char*, const unsigned char*, volatile unsigned char*) +{ return 'c'; } +unsigned char g(S, unsigned char*&, const unsigned char*&, volatile unsigned char*&) +{ return 'c'; } + +short g(short, const short, volatile short) +{ return 0; } +short g(R, short&, const short&, volatile short&) +{ return 0; } +short g(short*, const short*, volatile short*) +{ return 0; } +short g(S, short*&, const short*&, volatile short*&) +{ return 0; } + +signed short g(T, signed short, const signed short, volatile signed short) +{ return 0; } +signed short g(T, R, signed short&, const signed short&, volatile signed short&) +{ return 0; } +signed short g(T, signed short*, const signed short*, volatile signed short*) +{ return 0; } +signed short g(T, S, double, signed short*&, const signed short*&, volatile signed short*&) +{ return 0; } + +unsigned short g(unsigned short, const unsigned short, volatile unsigned short) +{ return 0; } +unsigned short g(R, unsigned short&, const unsigned short&, volatile unsigned short&) +{ return 0; } +unsigned short g(unsigned short*, const unsigned short*, volatile unsigned short*) +{ return 0; } +unsigned short g(S, unsigned short*&, const unsigned short*&, volatile unsigned short*&) +{ return 0; } + +int g(int, const int, volatile int) +{ return 0; } +int g(R, int&, const int&, volatile int&) +{ return 0; } +int g(int*, const int*, volatile int*) +{ return 0; } +int g(S, int*&, const int*&, volatile int*&) +{ return 0; } + +signed int g(T, signed int, const signed int, volatile signed int) +{ return 0; } +signed int g(T, R, signed int&, const signed int&, volatile signed int&) +{ return 0; } +signed int g(T, signed int*, const signed int*, volatile signed int*) +{ return 0; } +signed int g(T, S, signed int*&, const signed int*&, volatile signed int*&) +{ return 0; } + +unsigned int g(unsigned int, const unsigned int, volatile unsigned int) +{ return 0; } +unsigned int g(R, unsigned int&, const unsigned int&, volatile unsigned int&) +{ return 0; } +unsigned int g(unsigned int*, const unsigned int*, volatile unsigned int*) +{ return 0; } +unsigned int g(S, unsigned int*&, const unsigned int*&, volatile unsigned int*&) +{ return 0; } + +long g(long, const long, volatile long) +{ return 0; } +long g(R, long&, const long&, volatile long&) +{ return 0; } +long g(long*, const long*, volatile long*) +{ return 0; } +long g(S, long*&, const long*&, volatile long*&) +{ return 0; } + +signed long g(T, signed long, const signed long, volatile signed long) +{ return 0; } +signed long g(T, R, signed long&, const signed long&, volatile signed long&) +{ return 0; } +signed long g(T, signed long*, const signed long*, volatile signed long*) +{ return 0; } +signed long g(T, S, signed long*&, const signed long*&, volatile signed long*&) +{ return 0; } + +unsigned long g(unsigned long, const unsigned long, volatile unsigned long) +{ return 0; } +unsigned long g(S, unsigned long&, const unsigned long&, volatile unsigned long&) +{ return 0; } +unsigned long g(unsigned long*, const unsigned long*, volatile unsigned long*) +{ return 0; } +unsigned long g(S, unsigned long*&, const unsigned long*&, volatile unsigned long*&) +{ return 0; } + +#ifdef __GNUC__ +long long g(long long, const long long, volatile long long) +{ return 0; } +long long g(S, long long&, const long long&, volatile long long&) +{ return 0; } +long long g(long long*, const long long*, volatile long long*) +{ return 0; } +long long g(R, long long*&, const long long*&, volatile long long*&) +{ return 0; } + +signed long long g(T, signed long long, const signed long long, volatile signed long long) +{ return 0; } +signed long long g(T, R, signed long long&, const signed long long&, volatile signed long long&) +{ return 0; } +signed long long g(T, signed long long*, const signed long long*, volatile signed long long*) +{ return 0; } +signed long long g(T, S, signed long long*&, const signed long long*&, volatile signed long long*&) +{ return 0; } + +unsigned long long g(unsigned long long, const unsigned long long, volatile unsigned long long) +{ return 0; } +unsigned long long g(R, unsigned long long*, const unsigned long long*, volatile unsigned long long*) +{ return 0; } +unsigned long long g(unsigned long long&, const unsigned long long&, volatile unsigned long long&) +{ return 0; } +unsigned long long g(S, unsigned long long*&, const unsigned long long*&, volatile unsigned long long*&) +{ return 0; } +#endif + +float g(float, const float, volatile float) +{ return 0; } +float g(char, float&, const float&, volatile float&) +{ return 0; } +float g(float*, const float*, volatile float*) +{ return 0; } +float g(char, float*&, const float*&, volatile float*&) +{ return 0; } + +double g(double, const double, volatile double) +{ return 0; } +double g(char, double&, const double&, volatile double&) +{ return 0; } +double g(double*, const double*, volatile double*) +{ return 0; } +double g(char, double*&, const double*&, volatile double*&) +{ return 0; } + +#ifdef __GNUC__ +long double g(long double, const long double, volatile long double) +{ return 0; } +long double g(char, long double&, const long double&, volatile long double&) +{ return 0; } +long double g(long double*, const long double*, volatile long double*) +{ return 0; } +long double g(char, long double*&, const long double*&, volatile long double*&) +{ return 0; } +#endif + +class c { +public: + c(int) {}; + int i; +}; + +class c g(c, const c, volatile c) +{ return 0; } +c g(char, c&, const c&, volatile c&) +{ return 0; } +c g(c*, const c*, volatile c*) +{ return 0; } +c g(char, c*&, const c*&, volatile c*&) +{ return 0; } + +/* +void h(char = 'a') +{ } +void h(char, signed char = 'a') +{ } +void h(unsigned char = 'a') +{ } +*/ +/* +void h(char = (char)'a') +{ } +void h(char, signed char = (signed char)'a') +{ } +void h(unsigned char = (unsigned char)'a') +{ } + + +void h(short = (short)43) +{ } +void h(char, signed short = (signed short)43) +{ } +void h(unsigned short = (unsigned short)43) +{ } + +void h(int = (int)43) +{ } +void h(char, signed int = (signed int)43) +{ } +void h(unsigned int = (unsigned int)43) +{ } + + +void h(long = (long)43) +{ } +void h(char, signed long = (signed long)43) +{ } +void h(unsigned long = (unsigned long)43) +{ } + +#ifdef __GNUC__ +void h(long long = 43) +{ } +void h(char, signed long long = 43) +{ } +void h(unsigned long long = 43) +{ } +#endif + +void h(float = 4.3e-10) +{ } +void h(double = 4.3) +{ } +#ifdef __GNUC__ +void h(long double = 4.33e33) +{ } +#endif +*/ +void printf(const char *format, ... ) +{ + // elipsis +} + +class T1 { +public: + static void* operator new(size_t); + static void operator delete(void *pointer); + + void operator=(const T1&); + T1& operator=(int); + + int operator==(int) const; + int operator==(const T1&) const; + int operator!=(int) const; + int operator!=(const T1&) const; + + int operator<=(int) const; + int operator<=(const T1&) const; + int operator<(int) const; + int operator<(const T1&) const; + int operator>=(int) const; + int operator>=(const T1&) const; + int operator>(int) const; + int operator>(const T1&) const; + + void operator+(int) const; + T1& operator+(const T1&) const; + void operator+=(int) const; + T1& operator+=(const T1&) const; + + T1& operator++() const; + + void operator-(int) const; + T1& operator-(const T1&) const; + void operator-=(int) const; + T1& operator-=(const T1&) const; + + T1& operator--() const; + + void operator*(int) const; + T1& operator*(const T1&) const; + void operator*=(int) const; + T1& operator*=(const T1&) const; + + void operator/(int) const; + T1& operator/(const T1&) const; + void operator/=(int) const; + T1& operator/=(const T1&) const; + + void operator%(int) const; + T1& operator%(const T1&) const; + void operator%=(int) const; + T1& operator%=(const T1&) const; + + void operator&&(int) const; + T1& operator&&(const T1&) const; + + void operator||(int) const; + T1& operator||(const T1&) const; + + void operator&(int) const; + T1& operator&(const T1&) const; + void operator&=(int) const; + T1& operator&=(const T1&) const; + + void operator|(int) const; + T1& operator|(const T1&) const; + void operator|=(int) const; + T1& operator|=(const T1&) const; + + void operator^(int) const; + T1& operator^(const T1&) const; + void operator^=(int) const; + T1& operator^=(const T1&) const; + + T1& operator!() const; + T1& operator~() const; +}; + +void* +T1::operator new(size_t) +{ return 0; } + +void +T1::operator delete(void *pointer) +{ } + +class T2 { +public: + T2(int i): integer(i) + { } + int integer; +}; + +int operator==(const T2&, const T2&) +{ return 0; } +int operator==(const T2&, char) +{ return 0; } +int operator!=(const T2&, const T2&) +{ return 0; } +int operator!=(const T2&, char) +{ return 0; } + +int operator<=(const T2&, const T2&) +{ return 0; } +int operator<=(const T2&, char) +{ return 0; } +int operator<(const T2&, const T2&) +{ return 0; } +int operator<(const T2&, char) +{ return 0; } +int operator>=(const T2&, const T2&) +{ return 0; } +int operator>=(const T2&, char) +{ return 0; } +int operator>(const T2&, const T2&) +{ return 0; } +int operator>(const T2&, char) +{ return 0; } + +T2 operator+(const T2 t, int i) +{ return t.integer + i; } +T2 operator+(const T2 a, const T2& b) +{ return a.integer + b.integer; } +T2& operator+=(T2& t, int i) +{ t.integer += i; return t; } +T2& operator+=(T2& a, const T2& b) +{ a.integer += b.integer; return a; } + +T2 operator-(const T2 t, int i) +{ return t.integer - i; } +T2 operator-(const T2 a, const T2& b) +{ return a.integer - b.integer; } +T2& operator-=(T2& t, int i) +{ t.integer -= i; return t; } +T2& operator-=(T2& a, const T2& b) +{ a.integer -= b.integer; return a; } + +T2 operator*(const T2 t, int i) +{ return t.integer * i; } +T2 operator*(const T2 a, const T2& b) +{ return a.integer * b.integer; } +T2& operator*=(T2& t, int i) +{ t.integer *= i; return t; } +T2& operator*=(T2& a, const T2& b) +{ a.integer *= b.integer; return a; } + +T2 operator/(const T2 t, int i) +{ return t.integer / i; } +T2 operator/(const T2 a, const T2& b) +{ return a.integer / b.integer; } +T2& operator/=(T2& t, int i) +{ t.integer /= i; return t; } +T2& operator/=(T2& a, const T2& b) +{ a.integer /= b.integer; return a; } + +T2 operator%(const T2 t, int i) +{ return t.integer % i; } +T2 operator%(const T2 a, const T2& b) +{ return a.integer % b.integer; } +T2& operator%=(T2& t, int i) +{ t.integer %= i; return t; } +T2& operator%=(T2& a, const T2& b) +{ a.integer %= b.integer; return a; } + +template<class T> +class T5 { +public: + T5(int); + T5(const T5<T>&); + ~T5(); + static void* operator new(size_t); + static void operator delete(void *pointer); + int value(); + + static T X; + T x; + int val; +}; + +template<class T> +T5<T>::T5(int v) +{ val = v; } + +template<class T> +T5<T>::T5(const T5<T>&) +{} + +template<class T> +T5<T>::~T5() +{} + +template<class T> +void* +T5<T>::operator new(size_t) +{ return 0; } + +template<class T> +void +T5<T>::operator delete(void *pointer) +{ } + +template<class T> +int +T5<T>::value() +{ return val; } + + +#if ! defined(__GNUC__) || defined(GCC_BUG) +template<class T> +T T5<T>::X; +#endif + + + + +T5<char> t5c(1); +T5<int> t5i(2); +T5<int (*)(char, void *)> t5fi1(3); +T5<int (*)(int, double **, void *)> t5fi2(4); + + + + + + +class x { +public: + int (*manage[5])(double, + void *(*malloc)(unsigned size), + void (*free)(void *pointer)); + int (*device[5])(int open(const char *, unsigned mode, unsigned perms, int extra = 0), + int *(*read)(int fd, void *place, unsigned size), + int *(*write)(int fd, void *place, unsigned size), + void (*close)(int fd)); +}; +T5<x> t5x(5); + +#if !defined(__GNUC__) || (__GNUC__ >= 2 && __GNUC_MINOR__ >= 6) +template class T5<char>; +template class T5<int>; +template class T5<int (*)(char, void *)>; +template class T5<int (*)(int, double **, void *)>; +template class T5<x>; +#endif + +class T7 { +public: + static int get(); + static void put(int); +}; + +int +T7::get() +{ return 1; } + +void +T7::put(int i) +{ + // nothing +} + +// More template kinds. GDB 4.16 didn't handle these, but +// Wildebeest does. Note: Assuming HP aCC is used to compile +// this file; with g++ or HP cfront or other compilers the +// demangling may not get done correctly. + +// Ordinary template, to be instantiated with different types +template<class T> +class Foo { +public: + int x; + T t; + T foo (int, T); +}; + + +template<class T> T Foo<T>::foo (int i, T tt) +{ + return tt; +} + +// Template with int parameter + +template<class T, int sz> +class Bar { +public: + int x; + T t; + T bar (int, T); +}; + + +template<class T, int sz> T Bar<T, sz>::bar (int i, T tt) +{ + if (i < sz) + return tt; + else + return 0; +} + +// function template with int parameter +template<class T> int dummy (T tt, int i) +{ + return tt; +} + +// Template with partial specializations +template<class T1, class T2> +class Spec { +public: + int x; + T1 spec (T2); +}; + +template<class T1, class T2> +T1 Spec<T1, T2>::spec (T2 t2) +{ + return 0; +} + +template<class T> +class Spec<T, T*> { +public: + int x; + T spec (T*); +}; + +template<class T> +T Spec<T, T*>::spec (T * tp) +{ + return *tp; +} + +// Template with char parameter +template<class T, char sz> +class Baz { +public: + int x; + T t; + T baz (int, T); +}; + +template<class T, char sz> T Baz<T, sz>::baz (int i, T tt) +{ + if (i < sz) + return tt; + else + return 0; +} + +// Template with char * parameter +template<class T, char * sz> +class Qux { +public: + int x; + T t; + T qux (int, T); +}; + +template<class T, char * sz> T Qux<T, sz>::qux (int i, T tt) +{ + if (sz[0] == 'q') + return tt; + else + return 0; +} + +// Template with a function pointer parameter +template<class T, int (*f)(int) > +class Qux1 { +public: + int x; + T t; + T qux (int, T); +}; + +template<class T, int (*f)(int)> T Qux1<T, f>::qux (int i, T tt) +{ + if (f != 0) + return tt; + else + return 0; +} + +// Some functions to provide as arguments to template +int gf1 (int a) { + return a * 2 + 13; +} +int gf2 (int a) { + return a * 2 + 26; +} + +char string[3]; + + +// Template for nested instantiations + +template<class T> +class Garply { +public: + int x; + T t; + T garply (int, T); +}; + +template<class T> T Garply<T>::garply (int i, T tt) +{ + if (i > x) + return tt; + else + { + x += i; + return tt; + } +} + + +int main() +{ + int i; +#ifdef usestubs + set_debug_traps(); + breakpoint(); +#endif + i = i + 1; + + // New tests added here + + Foo<int> fint; + Foo<char> fchar; + Foo<volatile char *> fvpchar; + + Bar<int, 33> bint; + Bar<int, (4 > 3)> bint2; + + Baz<int, 's'> bazint; + Baz<char, 'a'> bazint2; + + Qux<char, string> quxint2; + Qux<int, string> quxint; + + Qux1<int, gf1> qux11; + + int x = fint.foo(33, 47); + char c = fchar.foo(33, 'x'); + volatile char * cp = fvpchar.foo(33, 0); + + int y = dummy<int> (400, 600); + + int z = bint.bar(55, 66); + z += bint2.bar(55, 66); + + c = bazint2.baz(4, 'y'); + c = quxint2.qux(4, 'z'); + + y = bazint.baz(4,3); + y = quxint.qux(4, 22); + y += qux11.qux(4, 22); + + y *= gf1(y) - gf2(y); + + Spec<int, char> sic; + Spec<int, int *> siip; + + sic.spec ('c'); + siip.spec (&x); + + Garply<int> f; + Garply<char> fc; + f.x = 13; + + Garply<Garply<char> > nf; + nf.x = 31; + + x = f.garply (3, 4); + + fc = nf.garply (3, fc); + + y = x + fc.x; + + + return 0; + +} + + + + + + + + + + + + + diff --git a/gdb/testsuite/gdb.hp/templ-hp.exp b/gdb/testsuite/gdb.hp/templ-hp.exp new file mode 100644 index 00000000000..64ca53daf76 --- /dev/null +++ b/gdb/testsuite/gdb.hp/templ-hp.exp @@ -0,0 +1,381 @@ +# Copyright (C) 1992, 1996, 1997 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 2 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +# Please email any bugs, comments, and/or additions to this file to: +# bug-gdb@prep.ai.mit.edu + + + +# More tests for different kinds of template parameters, +# templates with partial specializations, nested templates, etc. +# These have been tested only with HP aCC. They probably won't +# work with other compilers because of differences in mangling +# schemes. +# Added by Satish Pai <pai@apollo.hp.com> 1997-09-25 + + +set ws "\[\r\n\t \]+" + +if $tracelevel then { + strace $tracelevel +} + +set testfile "templ-hp" +set srcfile ${testfile}.cc +set binfile ${objdir}/${subdir}/${testfile} + + + +# Create and source the file that provides information about the compiler +# used to compile the test case. + +if [get_compiler_info ${binfile} "c++"] { + return -1; +} + +if {[skip_hp_tests $gcc_compiled]} then { continue } + + +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } { + gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail." + +} + +# +# Test printing of the types of templates. +# + +proc test_ptype_of_templates {} { + global gdb_prompt + + send_gdb "ptype T5<int>\n" + gdb_expect { + -re "type = class T5<int> \\{\r\n\[ \t\]*public:\r\n\[ \t\]*static int X;\r\n\[ \t\]*int x;\r\n\[ \t\]*int val;\r\n\r\n\[ \t\]*T5\\(int\\);\r\n\[ \t\]*T5\\(class T5<int> const &\\);\r\n\[ \t\]*void ~T5\\(int\\);\r\n\[ \t\]*static void \\* new\\(unsigned int\\);\r\n\[ \t\]*static void delete\\(void \\*\\);\r\n\[ \t\]*int value\\(void\\);\r\n\[ \t\]*\\}\r\n$gdb_prompt $" { pass "ptype T5<int>" } + -re ".*$gdb_prompt $" { fail "ptype T5<int>" } + timeout { fail "ptype T5<int> (timeout)" } + } + + send_gdb "ptype t5i\n" + gdb_expect { + -re "type = class T5<int> \\{\r\n\[ \t\]*public:\r\n\[ \t\]*static int X;\r\n\[ \t\]*int x;\r\n\[ \t\]*int val;\r\n\r\n\[ \t\]*T5\\(int\\);\r\n\[ \t\]*T5\\(class T5<int> const &\\);\r\n\[ \t\]*void ~T5\\(int\\);\r\n\[ \t\]*static void \\* new\\(unsigned int\\);\r\n\[ \t\]*static void delete\\(void \\*\\);\r\n\[ \t\]*int value\\(void\\);\r\n\[ \t\]*\\}\r\n$gdb_prompt $" { pass "ptype t5i<int> 1" } + -re "type = class T5<int> \{.*public:.*static int X;.*int x;.*int val;.*.*T5 \\(int\\);.*.*void ~T5 \\(int\\).*.*.*int value \\(void\\);.*\}.*$gdb_prompt $" { + pass "ptype t5i" + } + -re ".*$gdb_prompt $" { fail "ptype t5i" } + timeout { fail "ptype t5i (timeout)" } + } +} + +# +# Test breakpoint setting on template methods. +# + +proc test_template_breakpoints {} { + global gdb_prompt + global testfile + global srcdir + + send_gdb "break T5<int>::T5\n" + gdb_expect { + -re "0. cancel.*\r\n.1. all.*\r\n.2. *.*\r\n.3. *.*\r\n> $" { + gdb_test "0" \ + "cancelled" \ + "constructor breakpoint" + } + -re ".0. cancel\r\n.1. all\r\n.2. T5<int>::T5\\(T5<int> const &\\) at .*/templates.cc:.*\r\n.3. T5<int>::T5\\(int\\) at .*/templates-hp.cc:.*\r\n> $" { + gdb_test "0" \ + "cancelled" \ + "constructor breakpoint" + } + -re ".*$gdb_prompt $" { fail "constructor breakpoint" } + default { fail "constructor breakpoint (timeout)" } + } + + gdb_test "break T5<int>::~T5" \ + "Breakpoint.*at.* file .*${testfile}.cc, line.*" \ + "destructor breakpoint" + + gdb_test "break T5<int>::value" \ + "Breakpoint.*at.* file .*${testfile}.cc, line.*" \ + "value method breakpoint" + + delete_breakpoints +} + +# +# Test calling of template methods. +# + +proc test_template_calls {} { + global gdb_prompt + + send_gdb "print t5i.value()\n" + gdb_expect { + -re ".* = 2\r\n$gdb_prompt $" { pass "print t5i.value()" } + -re "Cannot invoke functions on this machine.*$gdb_prompt $" { + fail "print t5i.value()" + } + -re ".*$gdb_prompt $" { fail "print t5i.value()" } + timeout { fail "print t5i.value() (timeout)" } + } +} + + +proc do_tests {} { + global prms_id + global bug_id + global subdir + global objdir + global srcdir + global binfile + global prompt + global supports_template_debugging + + set prms_id 0 + set bug_id 0 + + # Start with a fresh gdb. + + gdb_exit + gdb_start + gdb_reinitialize_dir $srcdir/$subdir + gdb_load $binfile + + source ${binfile}.ci + + if { !$supports_template_debugging } { + warning "compiler lacks debugging info for templates; tests suppressed." 0 + return + } + + test_ptype_of_templates + test_template_breakpoints + + if [ runto_main ] { + test_template_calls + } +} + +do_tests + + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load $binfile + +# set it up at a breakpoint so we can play with the variable values +# +if ![runto_main] then { + perror "couldn't run to breakpoint" + continue +} + +send_gdb "print fint\n" +gdb_expect { + -re "\\$\[0-9\]* = \\{x = 0, t = 0\\}\r\n$gdb_prompt $" { pass "print fint" } + -re "$gdb_prompt $" { fail "print fint" } + timeout { fail "(timeout) print fint" } +} + +send_gdb "print fvpchar\n" +gdb_expect { + -re "\\$\[0-9\]* = \\{x = 0, t = 0x0\\}\r\n$gdb_prompt $" { pass "print fvpchar" } + -re "$gdb_prompt $" { fail "print fvpchar" } + timeout { fail "(timeout) print fvpchar" } +} + +# Template Foo<T> + +send_gdb "ptype Foo\n" +gdb_expect { + -re "type = template <(class |)T> (class |)Foo \\{\r\n\[ \t\]*public:\r\n\[ \t\]*int x;\r\n\[ \t\]*T t;\r\n\\}\r\ntemplate instantiations:\r\n\[ \t\]*(class |)Foo<volatile char \\*>\r\n\[ \t\]*(class |)Foo<char>\r\n\[ \t\]*(class |)Foo<int>\r\n$gdb_prompt $" { pass "ptype Foo" } + -re "$gdb_prompt $" { fail "ptype Foo" } + timeout { fail "(timeout) ptype Foo" } +} + +# ptype Foo<int> + +send_gdb "ptype fint\n" +gdb_expect { + -re "type = (class |)Foo<int> \\{\r\n\[ \t\]*public:\r\n\[ \t\]*int x;\r\n\[ \t\]*int t;\r\n\r\n\[ \t\]*int foo\\(int, int\\);\r\n\\}\r\n$gdb_prompt $" { pass "ptype fint" } + -re "$gdb_prompt $" { fail "ptype fint" } + timeout { fail "(timeout) ptype fint" } +} + +# ptype Foo<char> + +send_gdb "ptype fchar\n" +gdb_expect { + -re "type = (class |)Foo<char> \\{\r\n\[ \t\]*public:\r\n\[ \t\]*int x;\r\n\[ \t\]*char t;\r\n\r\n\[ \t\]*char foo\\(int, char\\);\r\n\\}\r\n$gdb_prompt $" { pass "ptype fchar" } + -re "$gdb_prompt $" { fail "ptype fchar" } + timeout { fail "(timeout) ptype fchar" } +} + +# ptype Foo<volatile char *> + +send_gdb "ptype fvpchar\n" +gdb_expect { + -re "type = (class |)Foo<volatile char \\*> \\{\r\n\[ \t\]*public:\r\n\[ \t\]*int x;\r\n\[ \t\]*volatile char \\*t;\r\n\r\n\[ \t\]*volatile char \\* foo\\(int, volatile char \\*\\);\r\n\\}\r\n$gdb_prompt $" { pass "ptype fvpchar" } + -re "$gdb_prompt $" { fail "ptype fvpchar" } + timeout { fail "(timeout) ptype fvpchar" } +} + +# print a function from Foo<volatile char *> + +send_gdb "print Foo<volatile char *>::foo\n" +gdb_expect { + -re "\\$\[0-9\]* = \\{volatile char \\*\\((class |)Foo<volatile char \\*> \\*, int, volatile char \\*\\)\\} $hex <Foo<volatile char \\*>::foo\\(int, volatile char \\*\\)>\r\n$gdb_prompt $" { pass "print Foo<volatile char *>::foo" } + -re "$gdb_prompt $" { fail "print Foo<volatile char *>::foo" } + timeout { fail "(timeout) print Foo<volatile char *>::foo" } +} + +# Template Bar<T, int> + +send_gdb "ptype Bar\n" +gdb_expect { + -re "type = template <(class |)T, (class |)sz> (class |)Bar \\{\r\n\[ \t\]*public:\r\n\[ \t\]*int x;\r\n\[ \t\]*T t;\r\n\\}\r\ntemplate instantiations:\r\n\[ \t\]*(class |)Bar<int,1>\r\n\[ \t\]*(class |)Bar<int,33>\r\n$gdb_prompt $" { pass "ptype Bar" } + -re "$gdb_prompt $" { fail "ptype Bar" } + timeout { fail "(timeout) ptype Bar" } +} + + +# ptype Bar<int,33> + +send_gdb "ptype bint\n" +gdb_expect { + -re "type = (class |)Bar<int,33> \\{\r\n\[ \t\]*public:\r\n\[ \t\]*int x;\r\n\[ \t\]*int t;\r\n\r\n\[ \t\]*int bar\\(int, int\\);\r\n\\}\r\n$gdb_prompt $" { pass "ptype bint" } + -re "$gdb_prompt $" { fail "ptype bint" } + timeout { fail "(timeout) ptype bint" } +} + +# ptype Bar<int, (4>3)> + +send_gdb "ptype bint2\n" +gdb_expect { + -re "type = (class |)Bar<int,1> \\{\r\n\[ \t\]*public:\r\n\[ \t\]*int x;\r\n\[ \t\]*int t;\r\n\r\n\[ \t\]*int bar\\(int, int\\);\r\n\\}\r\n$gdb_prompt $" { pass "ptype bint2" } + -re "$gdb_prompt $" { fail "ptype bint2" } + timeout { fail "(timeout) ptype bint2" } +} + +# Template Baz<T, char> + +send_gdb "ptype Baz\n" +gdb_expect { + -re "type = template <(class |)T, (class |)sz> (class |)Baz \\{\r\n\[ \t\]*public:\r\n\[ \t\]*int x;\r\n\[ \t\]*T t;\r\n\\}\r\ntemplate instantiations:\r\n\[ \t\]*(class |)Baz<char,97>\r\n\[ \t\]*(class |)Baz<int,115>\r\n$gdb_prompt $" { pass "ptype Baz" } + -re "$gdb_prompt $" { fail "ptype Baz" } + timeout { fail "(timeout) ptype Baz" } +} + + +# ptype Baz<int, 's'> + +send_gdb "ptype bazint\n" +gdb_expect { + -re "type = (class |)Baz<int,115> \\{\r\n\[ \t\]*public:\r\n\[ \t\]*int x;\r\n\[ \t\]*int t;\r\n\r\n\[ \t\]*int baz\\(int, int\\);\r\n\\}\r\n$gdb_prompt $" { pass "ptype bazint" } + -re "$gdb_prompt $" { fail "ptype bazint" } + timeout { fail "(timeout) ptype bazint" } +} + +# ptype Baz<char, 'a'> + +send_gdb "ptype bazint2\n" +gdb_expect { + -re "type = (class |)Baz<char,97> \\{\r\n\[ \t\]*public:\r\n\[ \t\]*int x;\r\n\[ \t\]*char t;\r\n\r\n\[ \t\]*char baz\\(int, char\\);\r\n\\}\r\n$gdb_prompt $" { pass "ptype bazint2" } + -re "$gdb_prompt $" { fail "ptype bazint2" } + timeout { fail "(timeout) ptype bazint2" } +} + +# Template Qux<T, int (*f)(int) > + +send_gdb "ptype Qux\n" +gdb_expect { + -re "type = template <(class |)T, (class |)sz> (class |)Qux \\{\r\n\[ \t\]*public:\r\n\[ \t\]*int x;\r\n\[ \t\]*T t;\r\n\\}\r\ntemplate instantiations:\r\n\[ \t\]*(class |)Qux<int,&string>\r\n\[ \t\]*(class |)Qux<char,&string>\r\n$gdb_prompt $" { pass "ptype Qux" } + -re "$gdb_prompt $" { fail "ptype Qux" } + timeout { fail "(timeout) ptype Qux" } +} + +# pt Qux<int,&string> + +send_gdb "ptype quxint\n" +gdb_expect { + -re "type = class Qux<int,&string> \\{\r\n\[ \t\]*public:\r\n\[ \t\]*int x;\r\n\[ \t\]*int t;\r\n\r\n\[ \t\]*int qux\\(int, int\\);\r\n\\}\r\n$gdb_prompt $" { pass "ptype quxint" } + -re "$gdb_prompt $" { fail "ptype quxint" } + timeout { fail "(timeout) ptype quxint" } +} + +# pt Qux<char,0> + +send_gdb "ptype quxint2\n" +gdb_expect { + -re "type = class Qux<char,&string> \\{\r\n\[ \t\]*public:\r\n\[ \t\]*int x;\r\n\[ \t\]*char t;\r\n\r\n\[ \t\]*char qux\\(int, char\\);\r\n\\}\r\n$gdb_prompt $" { pass "ptype quxint2" } + -re "$gdb_prompt $" { fail "ptype quxint2" } + timeout { fail "(timeout) ptype quxint2" } +} + +# Template Spec<T1, T2> + +send_gdb "ptype Spec\n" +gdb_expect { + -re "type = template <(class |)T1, (class |)T2> (class |)Spec \\{\r\n\[ \t\]*public:\r\n\[ \t\]*int x;\r\n\\}\r\ntemplate instantiations:\r\n\[ \t\]*(class |)Spec<int,int \\*>\r\n\[ \t\]*(class |)Spec<int,char>\r\n$gdb_prompt $" { pass "ptype Spec" } + -re "$gdb_prompt $" { fail "ptype Spec" } + timeout { fail "(timeout) ptype Spec" } +} + +# pt Spec<char,0> + +send_gdb "ptype siip\n" +gdb_expect { + -re "type = class Spec<int,int \\*> \\{\r\n\[ \t\]*public:\r\n\[ \t\]*int x;\r\n\r\n\[ \t\]*int spec\\(int \\*\\);\r\n\\}\r\n$gdb_prompt $" { pass "ptype siip" } + -re "$gdb_prompt $" { fail "ptype siip" } + timeout { fail "(timeout) ptype siip" } +} + +# pt Garply<int> + +send_gdb "ptype Garply<int>\n" +gdb_expect { + -re "type = class Garply<int> \\{\r\n\[ \t\]*public:\r\n\[ \t\]*int x;\r\n\[ \t\]*int t;\r\n\r\n\[ \t\]*int garply\\(int, int\\);\r\n\\}\r\n$gdb_prompt $" { pass "ptype Garply<int>" } + -re "$gdb_prompt $" { fail "ptype Garply<int>" } + timeout { fail "(timeout) ptype Garply<int>" } +} + +# ptype of nested template name + +send_gdb "ptype Garply<Garply<char> >\n" +gdb_expect { + -re "type = (class |)Garply<Garply<char> > \\{\r\n\[ \t\]*public:\r\n\[ \t\]*int x;\r\n\[ \t\]*(class |)Garply<char> t;\r\n\r\n\[ \t\]*(class |)Garply<char> garply\\(int, (class |)Garply<char>\\);\r\n\\}\r\n$gdb_prompt $" { pass "ptype Garply<Garply<char> >" } + -re "$gdb_prompt $" { fail "ptype Garply<Garply<char> >" } + timeout { fail "(timeout) ptype Garply<Garply<char> >" } +} + +# print out a function from a nested template name + +send_gdb "print Garply<Garply<char> >::garply\n" +gdb_expect { + -re "\\$\[0-9\]* = \\{(class |)Garply<char> \\((class |)Garply<Garply<char> > \\*, int, (class |)Garply<char>\\)\\} $hex <Garply<Garply<char>>::garply\\(int, (class |)Garply<char>\\)>\r\n$gdb_prompt $" { pass "print Garply<Garply<char> >::garply" } + -re ".*$gdb_prompt $" { fail "print Garply<Garply<char> >::garply" } + timeout { fail "print Garply<Garply<char> >::garply (timeout)" } +} + +# UNFORTUNATELY, "break Garply<Garply<char> >::garply" doesn't yet work. + +#send_gdb "break Garply<Garply<char> >::garply +#gdb_expect { +# -re "Breakpoint \[0-9\]* at $hex: file .*templates.cc, line.*\r\n$gdb_prompt $" { pass "break Garply<Garply<char> >::garply" } +# -re ".*$gdb_prompt $" { fail "break Garply<Garply<char> >::garply" } +# timeout { fail "break Garply<Garply<char> >::garply (timeout)" } +#} diff --git a/gdb/testsuite/gdb.hp/thr-lib.c b/gdb/testsuite/gdb.hp/thr-lib.c new file mode 100644 index 00000000000..15cd16829e1 --- /dev/null +++ b/gdb/testsuite/gdb.hp/thr-lib.c @@ -0,0 +1,79 @@ +/* Thread local in a library. +*/ +#include "thr-lib.h" +/* + * #define NTHREADS 4 + * #define NUM_ELEMS 12 + */ + +extern void* adder( void * ); + +pthread_mutex_t mutex; /* mutex for protecting global data total */ + +int numbers[NUM_ELEMS] = {5, 4, 3, 2, 1, 6, 7, 8, 9, 10, 12, 11}; +int total = 0; + +int debugger_saw[NTHREADS][ELEMS_PER_THREAD]; /* [4][3] */ +int the_code_saw[NTHREADS][ELEMS_PER_THREAD]; + +int get_number(i) +int i; +{ + /* sleep to force context switch to another thread in non-MP system + * so that TLS symbols are used by multiple threads concurrently + * in some way. + */ + sleep(1); + return numbers[i]; +} + +main() +{ + pthread_t thread[NTHREADS]; + void *status; + int i, j, ret; + + printf("== Thread: Test started\n"); + + for( i = 0; i < NTHREADS; i++ ) { + for( j = 0; j < ELEMS_PER_THREAD; j++ ) { + debugger_saw[i][j] = 0; + the_code_saw[i][j] = 0; + } + } + + ret = pthread_mutex_init(&mutex, NULL); + if (ret != 0) { + printf("== Thread: pthread_mutex_init() error: %d\n", ret); + exit(1); + } + + for (i=0; i < NTHREADS; i++) { + ret = pthread_create( &thread[i], + NULL, + adder, + (void *) i); + if (ret != 0) { + printf("== Thread: pthread_create() error: %d\n", ret); + exit(1); + } + printf("== Thread: thread %d created\n", i); + } + + for (i=0; i < NTHREADS; i++) { + pthread_join( thread[i], &status); + } + + printf("== Thread: total = %d\n", total); /* Expect "78" */ + + for( i = 0; i < NTHREADS; i++ ) { + for( j = 0; j < ELEMS_PER_THREAD; j++ ) { + printf( "== Thread: the debugger saw %d, the program saw %d\n", + debugger_saw[i][j], + the_code_saw[i][j] ); + } + } + + printf("== Thread: Test ended\n"); + exit(0); +} diff --git a/gdb/testsuite/gdb.hp/thr-lib.exp b/gdb/testsuite/gdb.hp/thr-lib.exp new file mode 100644 index 00000000000..53bf4668749 --- /dev/null +++ b/gdb/testsuite/gdb.hp/thr-lib.exp @@ -0,0 +1,234 @@ +# thr-lib.exp -- Expect script to test thread-local storage in lib +# Copyright (C) 1992 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 2 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +# Please email any bugs, comments, and/or additions to this file to: +# bug-gdb@prep.ai.mit.edu + +# use this to debug: +# +#log_user 1 + +# Thread stuff is _slow_; prepare for long waits. +# +# Further, this test has some "null" lines designed +# to consume output from gdb that was too late to be +# matched (sequence is "gdb_test" sends; timeout and +# on to next send; result finally comes in; mismatch). +# +# The null command is 'gdb_test "p \$pc" ".*" ""' +# NOTE: this command undoes any up/down stuff! +# +proc pre_timeout {} { + global timeout + + set timeout [expr "$timeout + 100"] +} + +proc post_timeout {} { + global timeout + global oldtimeout + + set timeout $oldtimeout + gdb_test "p \$pc" ".*" "" +} + +if $tracelevel then { + strace $tracelevel +} + +if { ![istarget "hppa*-*-hpux10.30"] && ![istarget "hppa*-*-hpux11.*"] } { + verbose "HPUX thread test ignored for non-hppa or pre-HP/UX-10.30 targets." + return 0 +} + +set testfile thr-lib +set srcfile ${srcdir}/${subdir}/${testfile}.c +set libsrc ${srcdir}/${subdir}/${testfile}lib.c +set mainobj ${objdir}/${testfile}.o +set libobj ${objdir}/${testfile}lib.o +set libsl ${objdir}/${subdir}/${testfile}lib.sl +set binfile ${objdir}/${subdir}/${testfile} + +# To build the executable we need to do this: +# +# cc -c -Aa -g -D_HPUX_SOURCE -D_REENTRANT +DA1.0 ./gdb.hp/thr-lib.c +# cc -c -Aa -g -D_HPUX_SOURCE -D_REENTRANT +DA1.0 +z ./gdb.hp/thr-liblib.c +# ld -o thread_local_in_lib.lib.sl -b ./gdb.hp/thr-liblib.o +# ld -a archive /opt/langtools/lib/crt0.o /opt/langtools/lib/end.o \ +# > thr-lib.o ./gdb.hp/thr-liblib.sl \ +# > -o thr-lib -lpthread -lc +# +remote_exec build "$CC ${srcfile} -c -Aa -g -D_HPUX_SOURCE -D_REENTRANT +DA1.0" +remote_exec build "$CC ${libsrc} -c -Aa -g -D_HPUX_SOURCE -D_REENTRANT +DA1.0 +z" +remote_exec build "ld -o ${libsl} -b ${libobj}" +remote_exec build "ld -a archive /opt/langtools/lib/crt0.o /opt/langtools/lib/end.o ${mainobj} ${libsl} -lpthread -lc -o ${binfile}" + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir + +set oldtimeout $timeout +#set timeout [expr "$timeout + 200"] +set oldverbose $verbose + +gdb_load ${binfile} + +# Here we go: test various things. +# +gdb_test "b adder" ".*Cannot break on adder without a running program.*" "shared loc, needs to run" +gdb_test "b main" ".*" "" +gdb_test "run" ".*Breakpoint 1, main.*" "" + +# Set a bp to inspect the results +# +gdb_test "b 67" ".*Breakpoint 2.*" "" + +# get to a point where we can set the collection breakpoint. +# +gdb_test "tb adder" ".*Breakpoint 3.*line 47.*" "set bp in shared lib" +gdb_test "c" ".*Switched to.*adder.*" "run to shared lib rtn" + +# Check locations of things +# +gdb_test "i ad sum" ".*Symbol \"sum\" is a thread-local variable.*offset.*from the thread base register mpsfu_high.*" "find sum" +gdb_test "i add x" ".*Symbol \"x\" is a thread-local variable.*" "find x" + +# Set a breakpoint later on in "adder" and +# collect the thread local's value. +# +gdb_test "b 61" ".*Breakpoint 4.*61.*" "Set collection bp" + +# extra check for grins, expect to hit "adder" in thread 2 first +# but could be wrong... +# +gdb_test "info thread" ".*\\\* 2.*thread.*thread.*" "two threads" + +# Can't use "gdb_test", as it uses "$gdb_prompt $" in +# testing the result. Our new prompt is ">", with +# no trailing space, so we can't do this just by +# changing "prompt". +# +# Anyway, I couldn't get expect to see the ">" prompt, +# during the command addition, so I just punted. +# _You_ are welcome to try, if you want! +# +send_gdb "commands 4\n" +gdb_expect { + -re "(.*Type commands.*\"end\"\.\r\n\>)" { + pass "start commands" + } + -re ".*$gdb_prompt $" { + fail "start commands" + } +} + +# Assume we're in commands-input mode. (Self-debug stuff turned off) +# +send_gdb "silent\n" +#send_gdb "p id\n" +#send_gdb "p j\n" +#send_gdb "p x\[j\]\n" +send_gdb "set debugger_saw\[id\]\[j\] = x\[j\]\n" +send_gdb "continue\n" +send_gdb "end\n" + +gdb_expect { + -re ".*set.*cont.*$gdb_prompt $" { + pass "add commands" + } + -re ".*$gdb_prompt $" { + fail "add commands" + } +} + +# Check out of paranoia. +# +send_gdb "info break 4\n" +gdb_expect { + -re ".*breakpoint.*set debugger_saw.*continue.*$gdb_prompt $" { + pass "Commands added" + } + -re ".*$gdb_prompt $" { + fail "Commands not added." + } +} + +# We now expect to run through the whole application +# Since this'll run for while, set a generous timeout. +# +set timeout [expr "$timeout + 30"] +send_gdb "c\n" +gdb_expect { + -re ".*Program exited normally.*$gdb_prompt $" { + fail "program runaway" + } + -re ".*Breakpoint 2.*67.*$gdb_prompt $" { + pass "get to end" + } + -re ".*$gdb_prompt $" { + fail "No progress?" + } + timeout { fail "timeout" } +} +set timeout $oldtimeout + +gdb_test "p debugger_saw" ".*5, 1, 9.*4, 6, 10.*3, 7, 12.*2, 8, 11.*" "check results" + +# Often only one misses; let's get detailed! +# +gdb_test "p debugger_saw\[0\]\[0\]" ".*= 5.*" "1" +gdb_test "p debugger_saw\[0\]\[1\]" ".*= 1.*" "2" +gdb_test "p debugger_saw\[0\]\[2\]" ".*= 9.*" "3" +gdb_test "p debugger_saw\[1\]\[0\]" ".*= 4.*" "4" +gdb_test "p debugger_saw\[1\]\[1\]" ".*= 6.*" "5" +gdb_test "p debugger_saw\[1\]\[2\]" ".*= 10.*" "6" +gdb_test "p debugger_saw\[2\]\[0\]" ".*= 3.*" "7" +gdb_test "p debugger_saw\[2\]\[1\]" ".*= 7.*" "8" +gdb_test "p debugger_saw\[2\]\[2\]" ".*= 12.*" "9" +gdb_test "p debugger_saw\[3\]\[0\]" ".*= 2.*" "10" +gdb_test "p debugger_saw\[3\]\[1\]" ".*= 8.*" "11" +gdb_test "p debugger_saw\[3\]\[2\]" ".*= 11.*" "12" + +send_gdb "i th\n" +gdb_expect { + -re ".* 1.*system thread.* 2.*system thread.*$gdb_prompt $" { + fail "Too many threads left" + } + -re ".*\\\* 1.*system thread.*main.*$gdb_prompt $" { + pass "Expect only base thread" + } + -re ".*No stack.*$gdb_prompt $" { + fail "runaway" + } + -re ".*$gdb_prompt $" { + fail "Hunh?" + } + timeout { fail "timeout" } +} + +gdb_test "c" ".*exited normally.*" "run to completion" + +# Done! +# +gdb_exit + +set timeout $oldtimeout +set verbose $oldverbose + +# execute_anywhere "rm -f ${binfile}" +# +return 0 diff --git a/gdb/testsuite/gdb.hp/thr-lib.h b/gdb/testsuite/gdb.hp/thr-lib.h new file mode 100644 index 00000000000..c9395dfd0ca --- /dev/null +++ b/gdb/testsuite/gdb.hp/thr-lib.h @@ -0,0 +1,7 @@ +#include <stdio.h> +#include <pthread.h> + +#define NTHREADS 4 +#define NUM_ELEMS 12 + +#define ELEMS_PER_THREAD (NUM_ELEMS/NTHREADS) diff --git a/gdb/testsuite/gdb.hp/thr-liblib.c b/gdb/testsuite/gdb.hp/thr-liblib.c new file mode 100644 index 00000000000..a3effcc111f --- /dev/null +++ b/gdb/testsuite/gdb.hp/thr-liblib.c @@ -0,0 +1,92 @@ +#include <stdio.h> + +/* Library code for thread local in lib test. +*/ +#include "thr-lib.h" + +extern pthread_mutex_t mutex; +extern int get_number(); +extern int total; +extern int the_code_saw[NTHREADS][ELEMS_PER_THREAD]; + +/* The debugger should see this without a declaration. + * + * extern int debugger_saw[NTHREADS][ELEMS_PER_THREAD]; + */ + +/* The actual thread locals. + */ +__thread int sum; +__thread int x[ ELEMS_PER_THREAD ]; /* [3] */ + +void sumup() +{ + int j; + + sum = 0; + for (j = 0; j < ELEMS_PER_THREAD; j++) { + sum += x[j]; + } + + if( sum == x[0] ) + /* It won't be "==", but this lets us set a breakpoint + * and look at the thread-local storage. + */ + sum++; + + x[0] = x[2]; /* Another no-op for debugger use */ +} + +void *adder( vid ) + void * vid; +{ + int id; + int i, j; + int ret; + + id = (int) vid; + + /* printf( "== Thread: Welcome to adder %d\n", id ); */ + + for (j = 0; j < ELEMS_PER_THREAD; j++) { + x[j] = 0; + } + + for (i = id, j = 0; i < NUM_ELEMS; i += NTHREADS, j++ ) { + + /* printf( "== Thread: id %d, i %d, j %d\n", id, i, j ); + fflush( stdout ); */ + + x[j] = get_number(i); /* {0,1,2,3} +0, +4, +8 */ + + /* Record for posterity; the debugger will gather + * the same data here, using "x[j]". + */ + the_code_saw[ id ][ j ] = x[j]; + + /* printf( "== Thread %d, sample %d, val %d, i %d\n", id, j, x[j],i ); + fflush( stdout ); */ + } + + sumup(); + /* printf("== Thread: adder %d contributes total %d\n", id, sum); */ + + /* protect global data */ + ret = pthread_mutex_lock(&mutex); + if (ret != 0) { + printf("== Thread: pthread_mutex_lock() error: %d\n", ret); + exit(1); + } + + total += sum; + + ret = pthread_mutex_unlock(&mutex); + if (ret != 0) { + printf("== Thread: pthread_mutex_unlock() error: %d\n", ret); + exit(1); + } + + if( NTHREADS != 4 || ELEMS_PER_THREAD != 3 || NUM_ELEMS != 12 ) { + printf( "** ERROR in test code **\n" ); + } +} diff --git a/gdb/testsuite/gdb.hp/thr-stg.exp b/gdb/testsuite/gdb.hp/thr-stg.exp new file mode 100644 index 00000000000..19d69ee9297 --- /dev/null +++ b/gdb/testsuite/gdb.hp/thr-stg.exp @@ -0,0 +1,255 @@ +# thread_local_stg.exp -- Expect script to test thread-local storage +# Copyright (C) 1992 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 2 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +# Please email any bugs, comments, and/or additions to this file to: +# bug-gdb@prep.ai.mit.edu + +# use this to debug: +# +#log_user 1 + +# Thread stuff is _slow_; prepare for long waits. +# +# Further, this test has some "null" lines designed +# to consume output from gdb that was too late to be +# matched (sequence is "gdb_test" sends; timeout and +# on to next send; result finally comes in; mismatch). +# +# The null command is 'gdb_test "p \$pc" ".*" ""' +# NOTE: this command undoes any up/down stuff! +# +proc pre_timeout {} { + global timeout + + set timeout [expr "$timeout + 100"] +} + +proc post_timeout {} { + global timeout + global oldtimeout + + set timeout $oldtimeout + gdb_test "p \$pc" ".*" "" +} + +if $tracelevel then { + strace $tracelevel +} + +if { ![istarget "hppa*-*-hpux10.30"] && ![istarget "hppa*-*-hpux11.*"] } { + verbose "HPUX thread test ignored for non-hppa or pre-HP/UX-10.30 targets." + return 0 +} + +set testfile start-stop +set srcfile ${srcdir}/${subdir}/${testfile}.c +set binfile ${objdir}/${subdir}/${testfile} + +if [get_compiler_info ${binfile}] { + return -1 +} + +# To build the executable we need to link against the thread library. +# +# cc -Ae -g -o start_stop -lpthread start_stop.c +# +#compile "${srcfile} -Ae -g -lpthread -o ${binfile}" + +if {$gcc_compiled == 0} { + set additional_flags "additional_flags=-Ae" +} else { + set additional_flags "" +} + +if { [gdb_compile "${srcdir}/${subdir}/${testfile}.c" "${binfile}.o" object [list debug $additional_flags]] != "" } { + gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail." +} +remote_exec build "ld /usr/ccs/lib/crt0.o ${binfile}.o -lcl -lpthread -lc /opt/langtools/lib/end.o -o ${binfile}" + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir + +gdb_load ${binfile} +if ![runto_main] then { + fail "Can't run to main" + return 0 +} + +set oldtimeout $timeout +#set timeout [expr "$timeout + 200"] +set oldverbose $verbose +#set verbose 40 + +gdb_test "b do_pass" ".*" "set do_pass bp" +gdb_test "c" ".*do_pass.*" "run to do_pass" +gdb_test "cle" ".*" "" + +# Set a breakpoint at the "spin" routine and +# collect the thread local's value. +# +gdb_test "b 67" ".*Breakpoint 3.*67.*" "Set bp" + +# Can't use "gdb_test", as it uses "$gdb_prompt $" in +# testing the result. Our new prompt is ">", with +# no trailing space, so we can't do this just by +# changing "prompt". +# +# Anyway, I couldn't get expect to see the ">" prompt, +# during the command addition, so I just punted. +# _You_ are welcome to try, if you want! +# +send_gdb "commands 3\n" +gdb_expect { + -re "(.*Type commands.*\"end\"\.\r\n\>)" { + pass "start commands" + } + -re ".*$gdb_prompt $" { + fail "start commands" + } +} + +# Assume we're in commands-input mode. +# +send_gdb "silent\n" +send_gdb "set val_debugger_saw\[me\] = a_thread_local\n" +send_gdb "continue\n" +send_gdb "end\n" + +gdb_expect { + -re ".*set.*cont.*$gdb_prompt $" { + pass "add commands" + } + -re ".*$gdb_prompt $" { + fail "add commands" + } +} + +# Check out of paranoia. +# +send_gdb "info break 3\n" +gdb_expect { + -re ".*breakpoint.*set val_debugger.*continue.*$gdb_prompt $" { + pass "Commands added" + } + -re ".*$gdb_prompt $" { + fail "Commands not added." + } +} + +# Set a bp to inspect the results +# +gdb_test "b 134" ".*Breakpoint 4.*" "" + +# We now expect to run through a whole pass, seeing +# specific results as noted below (actual gotten by +# running application with debugging print statements +# turned on. +# +# Since this'll run for while, set a generous timeout. +# +set timeout [expr "$timeout + 30"] +send_gdb "c\n" +gdb_expect { + -re ".*Program exited normally.*$gdb_prompt $" { + fail "program runaway" + } + -re ".*Pass 0 done.*Pass 1 done.*$gdb_prompt $" { + fail "program runaway 2" + } + -re ".*Pass 0 done.*Breakpoint 4.*134.*$gdb_prompt $" { + pass "get to end of first pass" + } + -re ".*$gdb_prompt $" { + fail "No progress?" + } + timeout { fail "timeout" } +} + +gdb_test "p val_debugger_saw" ".*0, 1, 3.*" "first pass" + +send_gdb "i th\n" +gdb_expect { + -re ".* 1.*system thread.* 2.*system thread.*$gdb_prompt $" { + fail "Too many threads left" + } + -re ".*\\\* 1 system thread.*$gdb_prompt $" { + pass "Expect only base thread" + } + -re ".*No stack.*$gdb_prompt $" { + fail "runaway" + } + -re ".*$gdb_prompt $" { + fail "Hunh?" + } + timeout { fail "timeout" } +} + +gdb_test "i b" ".*4.*breakpoint.*134.*hit.*1 time.*" "Expect 134 bp to exist" + +gdb_test "c" ".*Breakpoint 4.*134.*" "get to end of second pass" +gdb_test "p val_debugger_saw" ".*6, 10, 15.*" "second pass" + +gdb_test "c" ".*Breakpoint 4.*134.*" "get to end of third pass" +gdb_test "p val_debugger_saw" ".*21, 28, 36.*" "third pass" + +gdb_test "info bre 3" ".*already hit 9 times.*" "count of silent bp hits" + +# Start over and do some "info address" stuff +# +send_gdb "d\n" +gdb_expect { + -re ".*Delete all breakpoints.*$" { + send_gdb "y\n" + gdb_expect { + -re ".*$gdb_prompt $" { + pass "del bps" + } + } + } + -re ".*$gdb_prompt $" { fail "no question" } +} + +gdb_test "b spin" ".*Breakpoint 5.*" "" + +send_gdb "r\n" +gdb_expect { + -re ".*Start it from the beginning.*$" { + send_gdb "y\n" + gdb_expect { + -re ".*$gdb_prompt $" { pass "restart" } + } + } + -re ".*Starting program.*$gdb_prompt $" { + pass "restart after previous fails" + } + -re ".*$gdb_prompt $" { fail "Can't restart" } +} +gdb_test "i ad a_global" ".*a_global.*static storage at address.*" "i ad a_global" +gdb_test "i add me" ".*me.*local variable at frame offset.*" "i ad me" +gdb_test "i ad a_thread_local" ".*a_thread_local.*a thread-local variable at offset.*" "i ad a_thread_local" + +# Done! +# +gdb_exit + +set timeout $oldtimeout +set verbose $oldverbose + +# execute_anywhere "rm -f ${binfile}" +# +return 0 diff --git a/gdb/testsuite/gdb.hp/vforked-program.c b/gdb/testsuite/gdb.hp/vforked-program.c new file mode 100644 index 00000000000..52c6cd2bbfd --- /dev/null +++ b/gdb/testsuite/gdb.hp/vforked-program.c @@ -0,0 +1,6 @@ +#include <stdio.h> + +main() +{ + printf("Hello from vforked_program...\n"); +} diff --git a/gdb/testsuite/gdb.hp/virtfun-hp.cc b/gdb/testsuite/gdb.hp/virtfun-hp.cc new file mode 100644 index 00000000000..6552a6233fc --- /dev/null +++ b/gdb/testsuite/gdb.hp/virtfun-hp.cc @@ -0,0 +1,192 @@ +// Pls try the following program on virtual functions and try to do print on +// most of the code in main(). Almost none of them works ! + +// +// The inheritance structure is: +// +// V : VA VB +// A : (V) +// B : A +// D : AD (V) +// C : (V) +// E : B (V) D C +// + +class VA +{ +public: + int va; +}; + +class VB +{ +public: + int vb; + int fvb(); + virtual vvb(); +}; + +class V : public VA, public VB +{ +public: + int f(); + virtual vv(); + int w; +}; + +class A : virtual public V +{ +public: + virtual int f(); +private: + int a; +}; + +class B : public A +{ +public: + int f(); +private: + int b; +}; + +class C : public virtual V +{ +public: + int c; +}; + +class AD +{ +public: + virtual int vg() = 0; +}; + +class D : public AD, virtual public V +{ +public: + static void s(); + virtual int vg(); + virtual int vd(); + int fd(); + int d; +}; + +class E : public B, virtual public V, public D, public C +{ +public: + int f(); + int vg(); + int vv(); + int e; +}; + +D dd; +D* ppd = ⅆ +AD* pAd = ⅆ + +A a; +B b; +C c; +D d; +E e; +V v; +VB vb; + + +A* pAa = &a; +A* pAe = &e; + +B* pBe = &e; + +D* pDd = &d; +D* pDe = &e; + +V* pVa = &a; +V* pVv = &v; +V* pVe = &e; +V* pVd = &d; + +AD* pADe = &e; + +E* pEe = &e; + +VB* pVB = &vb; + +void init() +{ + a.vb = 1; + b.vb = 2; + c.vb = 3; + d.vb = 4; + e.vb = 5; + v.vb = 6; + vb.vb = 7; + + d.d = 1; + e.d = 2; +} + +extern "C" printf(const char *, ...); + +int all_count = 0; +int failed_count = 0; + +#define TEST(EXPR, EXPECTED) \ + ret = EXPR; \ + if (ret != EXPECTED) {\ + printf("Failed %s is %d, should be %d!\n", #EXPR, ret, EXPECTED); \ + failed_count++; } \ + all_count++; + +int ret; + +void test_calls() +{ + TEST(pAe->f(), 20); + TEST(pAa->f(), 1); + + TEST(pDe->vg(), 202); + TEST(pADe->vg(), 202); + TEST(pDd->vg(), 101); + + TEST(pEe->vvb(), 411); + + TEST(pVB->vvb(), 407); + + TEST(pBe->vvb(), 411); + TEST(pDe->vvb(), 411); + + TEST(pEe->vd(), 282); + TEST(pEe->fvb(), 311); + + TEST(pEe->D::vg(), 102); + printf("Did %d tests, of which %d failed.\n", all_count, failed_count); +} + +int main() +{ + + init(); + + e.w = 7; + e.vb = 11; + + test_calls(); + return 0; + +} + +int A::f() {return 1;} +int B::f() {return 2;} +void D::s() {} +int E::f() {return 20;} +int D::vg() {return 100+d;} +int E::vg() {return 200+d;} +int V::f() {return 600+w;} +int V::vv() {return 400+w;} +int E::vv() {return 450+w;} +int D::fd() {return 250+d;} +int D::vd() {return 280+d;} +int VB::fvb() {return 300+vb;} +int VB::vvb() {return 400+vb;} diff --git a/gdb/testsuite/gdb.hp/virtfun-hp.exp b/gdb/testsuite/gdb.hp/virtfun-hp.exp new file mode 100644 index 00000000000..f5b36375082 --- /dev/null +++ b/gdb/testsuite/gdb.hp/virtfun-hp.exp @@ -0,0 +1,773 @@ +# Copyright (C) 1992, 1994, 1997 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 2 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +# Please email any bugs, comments, and/or additions to this file to: +# bug-gdb@prep.ai.mit.edu + +# This file was written by Fred Fish. (fnf@cygnus.com) + +set ws "\[\r\n\t \]+" + +if $tracelevel then { + strace $tracelevel +} + +set testfile "virtfun-hp" +set srcfile ${testfile}.cc +set binfile ${objdir}/${subdir}/${testfile} + +if [get_compiler_info ${binfile} "c++"] { + return -1; +} + + +if {[skip_hp_tests $gcc_compiled]} then { continue } + +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } { + gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail." +} + + +proc gdb_virtfunc_init {} { + global srcdir subdir binfile + global gdb_prompt + + gdb_reinitialize_dir $srcdir/$subdir + gdb_load $binfile + + send_gdb "set language c++\n" + gdb_expect -re "$gdb_prompt $" + send_gdb "set width 0\n" + gdb_expect -re "$gdb_prompt $" +} + +proc gdb_virtfunc_restart {} { + gdb_exit; + gdb_start; + gdb_virtfunc_init; + runto 'test_calls(void)'; +} + +# +# Test printing of the types of various classes. +# + +proc test_ptype_of_classes {} { + global gdb_prompt + global ws + + # This used to be a fail if it printed "struct" not "class". But + # since this struct doesn't use any special C++ features, it is + # considered right for GDB to print it as "struct". + send_gdb "ptype VA\n" + gdb_expect { + -re "type = (struct|class) VA \{(${ws}public:|)${ws}int va;${ws}VA & operator=\\(VA const &\\);${ws}VA\\(VA const &\\);${ws}VA\\(void\\);${ws}\}.*$gdb_prompt $" { + pass "ptype VA" + } + -re "type = (struct|class) VA \{(${ws}public:|)${ws}int va;((${ws}VA & operator=\\(VA const &\\);)|(${ws}VA\\(VA const &\\);)|(${ws}VA\\(void\\);))*${ws}\}.*$gdb_prompt $" { + pass "ptype VA (obsolescent gcc or gdb)" + } + -re ".*$gdb_prompt $" { + fail "ptype VA" + } + timeout { + fail "ptype VA (timeout)" + } + } + + send_gdb "ptype VB\n" + gdb_expect { + -re "type = class VB \{${ws}public:${ws}int vb;${ws}VB & operator=\\(VB const &\\);${ws}VB\\(VB const &\\);${ws}VB\\(void\\);${ws}int fvb\\(void\\);${ws}virtual int vvb\\(void\\);${ws}\}.*$gdb_prompt $" { + pass "ptype VB" + } + -re "type = class VB \{${ws}public:${ws}int vb;((${ws}VB & operator=\\(VB const &\\);)|(${ws}VB\\(VB const &\\);)|(${ws}VB\\(void\\);)|(${ws}int fvb\\(void\\);)|(${ws}virtual int vvb\\(void\\);))*${ws}\}.*$gdb_prompt $" { + pass "ptype VB (obsolescent gcc or gdb)" + } + -re ".*$gdb_prompt $" { + fail "ptype VB" + } + timeout { + fail "ptype VB (timeout)" + } + } + + send_gdb "ptype V\n" + gdb_expect { + -re "type = class V : public VA, public VB \{${ws}public:${ws}int w;${ws}V & operator=\\(V const &\\);${ws}V\\(V const &\\);${ws}V\\(void\\);${ws}int f\\(void\\);${ws}virtual int vv\\(void\\);${ws}\}\r\n$gdb_prompt $" { + pass "ptype V" + } + -re "type = class V : public VA, public VB \{${ws}public:${ws}int w;((${ws}V & operator=\\(V const &\\);)|(${ws}V\\(V const &\\);)|(${ws}V\\(void\\);)|(${ws}int f\\(void\\);)|(${ws}virtual int vv\\(void\\);))*${ws}\}\r\n$gdb_prompt $" { + pass "ptype V (obsolescent gcc or gdb)" + } + -re ".*$gdb_prompt $" { + fail "ptype V" + } + timeout { + fail "ptype V (timeout)" + } + } + + send_gdb "ptype A\n" + gdb_expect { + -re "type = class A : public virtual V \{\[\r\n\t \]+private:\[\r\n\t \]+int a;\[\r\n\t \]+public:\[\r\n\t \]+virtual int f\\(void\\);\[\r\n\t \]+\}\r\n$gdb_prompt $" { + pass "ptype A (aCC)" + } + -re "type = class A : public virtual V \{${ws}private:${ws}V \[*\]+_vb\[\\\$\.\]+V;${ws}int a;${ws}public:${ws}A & operator=\\(A const &\\);${ws}A\\(int, A const &\\);${ws}A\\(int\\);${ws}virtual int f\\(void\\);${ws}\}\r\n$gdb_prompt $" { + pass "ptype A" + } + -re "type = class A : public virtual V \{${ws}private:${ws}V \[*\]+_vb\[\\\$\.\]+V;${ws}int a;${ws}public:((${ws}A & operator=\\(A const &\\);)|(${ws}A\\(int, A const &\\);)|(${ws}A\\(int\\);)|(${ws}virtual int f\\(void\\);))*${ws}\}\r\n$gdb_prompt $" { + pass "ptype A (obsolescent gcc or gdb)" + } + -re "type = class A : public virtual V \{${ws}private:${ws}V \[*\]+_vb.FOO;${ws}int a;${ws}public:${ws}virtual int f.void.;${ws}\}\r\n$gdb_prompt $" { + # This happens because the type is defined only after it is + # too late. + fail "ptype A (known failure with gcc cygnus-2.4.5-930417)" + # Many of the rest of these tests have the same problem. + return 0 + } + -re ".*$gdb_prompt $" { + fail "ptype A" + } + timeout { + fail "ptype A (timeout)" + } + } + + send_gdb "ptype B\n" + gdb_expect { + -re "type = class B : public A \{${ws}private:${ws}int b;${ws}public:${ws}B & operator=\\(B const &\\);${ws}B\\(int, B const &\\);${ws}B\\(int\\);${ws}virtual int f\\(void\\);${ws}\}\r\n$gdb_prompt $" { + pass "ptype B" + } + -re "type = class B : public A \{${ws}private:${ws}int b;${ws}public:((${ws}B & operator=\\(B const &\\);)|(${ws}B\\(int, B const &\\);)|(${ws}B\\(int\\);)|(${ws}virtual int f\\(void\\);))*${ws}\}\r\n$gdb_prompt $" { + pass "ptype B (obsolescent gcc or gdb)" + } + -re ".*$gdb_prompt $" { + fail "ptype B" + } + timeout { + fail "ptype B (timeout)" + } + } + + send_gdb "ptype C\n" + gdb_expect { + -re "type = class C : public virtual V \{\[\r\n\t \]+public:\[\r\n\t \]+int c;\[\r\n\t \]+\}\r\n$gdb_prompt $" { + pass "ptype C (aCC)" + } + -re "type = class C : public virtual V \{${ws}private:${ws}V \[*\]+_vb.V;${ws}public:${ws}int c;${ws}C & operator=\\(C const &\\);${ws}C\\(int, C const &\\);${ws}C\\(int\\);${ws}\}\r\n$gdb_prompt $" { + pass "ptype C" + } + -re "type = class C : public virtual V \{${ws}private:${ws}V \[*\]+_vb.V;${ws}public:${ws}int c;((${ws}C & operator=\\(C const &\\);)|(${ws}C\\(int, C const &\\);)|(${ws}C\\(int\\);))*${ws}\}\r\n$gdb_prompt $" { + pass "ptype C (obsolescent gcc or gdb)" + } + -re ".*$gdb_prompt $" { + fail "ptype C" + } + timeout { + fail "ptype C (timeout)" + } + } + + send_gdb "ptype AD\n" + gdb_expect { + -re "type = class AD \{${ws}public:${ws}AD & operator=\\(AD const &\\);${ws}AD\\(AD const &\\);${ws}AD\\(void\\);${ws}virtual int vg\\(void\\);${ws}\}\r\n$gdb_prompt $" { + pass "ptype AD" + } + -re "type = class AD \{${ws}public:((${ws}AD & operator=\\(AD const &\\);)|(${ws}AD\\(AD const &\\);)|(${ws}AD\\(void\\);)|(${ws}virtual int vg\\(void\\);))*${ws}\}\r\n$gdb_prompt $" { + pass "ptype AD (obsolescent gcc or gdb)" + } + -re ".*$gdb_prompt $" { + fail "ptype AD" + } + timeout { + fail "ptype AD (timeout)" + } + } + + send_gdb "ptype D\n" + gdb_expect { + -re "type = class D : public AD, public virtual V \{\[\r\n\t \]+public:\[\r\n\t \]+int d;\[\r\n\t \]+static void s\\(void\\);\[\r\n\t \]+virtual int vg\\(void\\);\[\r\n\t \]+virtual int vd\\(void\\);\[\r\n\t \]+int fd\\(void\\);\[\r\n\t \]+\}\r\n$gdb_prompt $" { + pass "ptype D (aCC)" + } + -re "type = class D : public AD, public virtual V \{${ws}private:${ws}V \[*\]+_vb.V;${ws}public:${ws}int d;${ws}D & operator=\\(D const &\\);${ws}D\\(int, D const &\\);${ws}D\\(int\\);${ws}static void s\\(void\\);${ws}virtual int vg\\(void\\);${ws}virtual int vd\\(void\\);${ws}int fd\\(void\\);${ws}\}\r\n$gdb_prompt $" { + pass "ptype D" + } + -re "type = class D : public AD, public virtual V \{${ws}private:${ws}V \[*\]+_vb.V;${ws}public:${ws}int d;((${ws}D & operator=\\(D const &\\);)|(${ws}D\\(int, D const &\\);)|(${ws}D\\(int\\);)|(${ws}static void s\\(void\\);)|(${ws}virtual int vg\\(void\\);)|(${ws}virtual int vd\\(void\\);)|(${ws}int fd\\(void\\);))*${ws}\}\r\n$gdb_prompt $" { + pass "ptype D (obsolescent gcc or gdb)" + } + -re ".*$gdb_prompt $" { + fail "ptype D" + } + timeout { + fail "ptype D (timeout)" + } + } + + send_gdb "ptype E\n" + gdb_expect { + -re "type = class E : public B, public virtual V, public D, public C \{${ws}public:${ws}int e;${ws}E & operator=\\(E const &\\);${ws}E\\(int, E const &\\);${ws}E\\(int\\);${ws}virtual int f\\(void\\);${ws}virtual int vg\\(void\\);${ws}virtual int vv\\(void\\);${ws}\}\r\n$gdb_prompt $" { + pass "ptype E" + } + -re "type = class E : public B, public virtual V, public D, public C \{${ws}public:${ws}int e;((${ws}E & operator=\\(E const &\\);)|(${ws}E\\(int, E const &\\);)|(${ws}E\\(int\\);)|(${ws}virtual int f\\(void\\);)|(${ws}virtual int vg\\(void\\);)|(${ws}virtual int vv\\(void\\);))*${ws}\}\r\n$gdb_prompt $" { + pass "ptype E (obsolescent gcc or gdb)" + } + -re ".*$gdb_prompt $" { + fail "ptype E" + } + timeout { + fail "ptype E (timeout)" + } + } + + send_gdb "ptype dd\n" + gdb_expect { + -re "type = class D : public AD, public virtual V \{\[\r\n\t \]+public:\[\r\n\t \]+int d;\[\r\n\t \]+static void s\\(void\\);\[\r\n\t \]+virtual int vg\\(void\\);\[\r\n\t \]+virtual int vd\\(void\\);\[\r\n\t \]+int fd\\(void\\);\[\r\n\t \]+\}\r\n$gdb_prompt $" { + pass "ptype dd (aCC)" + } + -re "type = class D : public AD, public virtual V \{${ws}private:${ws}V \[*\]+_vb.V;${ws}public:${ws}int d;${ws}D & operator=\\(D const &\\);${ws}D\\(int, D const &\\);${ws}D\\(int\\);${ws}static void s\\(void\\);${ws}virtual int vg\\(void\\);${ws}virtual int vd\\(void\\);${ws}int fd\\(void\\);${ws}\}\r\n$gdb_prompt $" { + pass "ptype dd" + } + -re "type = class D : public AD, public virtual V \{${ws}private:${ws}V \[*\]+_vb.V;${ws}public:${ws}int d;((${ws}D & operator=\\(D const &\\);)|(${ws}D\\(int, D const &\\);)|(${ws}D\\(int\\);)|(${ws}static void s\\(void\\);)|(${ws}virtual int vg\\(void\\);)|(${ws}virtual int vd\\(void\\);)|(${ws}int fd\\(void\\);))*${ws}\}\r\n$gdb_prompt $" { + pass "ptype dd (obsolescent gcc or gdb)" + } + -re ".*$gdb_prompt $" { + fail "ptype dd" + } + timeout { + fail "ptype dd (timeout)" + } + } + + send_gdb "ptype ppd\n" + gdb_expect { + -re "type = class D : public AD, public virtual V \{\[\r\n\t \]+public:\[\r\n\t \]+int d;\[\r\n\t \]+static void s\\(void\\);\[\r\n\t \]+virtual int vg\\(void\\);\[\r\n\t \]+virtual int vd\\(void\\);\[\r\n\t \]+int fd\\(void\\);\[\r\n\t \]+\} \[*\]+\r\n$gdb_prompt $" { + pass "ptype ppd (aCC)" + } + -re "type = class D : public AD, public virtual V \{${ws}private:${ws}V \[*\]+_vb.V;${ws}public:${ws}int d;${ws}D & operator=\\(D const &\\);${ws}D\\(int, D const &\\);${ws}D\\(int\\);${ws}static void s\\(void\\);${ws}virtual int vg\\(void\\);${ws}virtual int vd\\(void\\);${ws}int fd\\(void\\);${ws}\} \[*\]+\r\n$gdb_prompt $" { + pass "ptype ppd" + } + -re "type = class D : public AD, public virtual V \{${ws}private:${ws}V \[*\]+_vb.V;${ws}public:${ws}int d;((${ws}D & operator=\\(D const &\\);)|(${ws}D\\(int, D const &\\);)|(${ws}D\\(int\\);)|(${ws}static void s\\(void\\);)|(${ws}virtual int vg\\(void\\);)|(${ws}virtual int vd\\(void\\);)|(${ws}int fd\\(void\\);))*${ws}\} \[*\]+\r\n$gdb_prompt $" { + pass "ptype ppd (obsolescent gcc or gdb)" + } + -re ".*$gdb_prompt $" { + fail "ptype ppd" + } + timeout { + fail "ptype ppd (timeout)" + } + } + + send_gdb "ptype pAd\n" + gdb_expect { + -re "type = class AD \{${ws}public:${ws}AD & operator=\\(AD const &\\);${ws}AD\\(AD const &\\);${ws}AD\\(void\\);${ws}virtual int vg\\(void\\);${ws}\} \[*\]+\r\n$gdb_prompt $" { + pass "ptype pAd" + } + -re "type = class AD \{${ws}public:((${ws}AD & operator=\\(AD const &\\);)|(${ws}AD\\(AD const &\\);)|(${ws}AD\\(void\\);)|(${ws}virtual int vg\\(void\\);))*${ws}\} \[*\]+\r\n$gdb_prompt $" { + pass "ptype pAd (obsolescent gcc or gdb)" + } + -re ".*$gdb_prompt $" { + fail "ptype pAd" + } + timeout { + fail "ptype pAd (timeout)" + } + } + + send_gdb "ptype a\n" + gdb_expect { + -re "type = class A : public virtual V \{\[\r\n\t \]+private:\[\r\n\t \]+int a;\[\r\n\t \]+public:\[\r\n\t \]+virtual int f\\(void\\);\[\r\n\t \]+\}\r\n$gdb_prompt $" { + pass "ptype a (aCC)" + } + -re "type = class A : public virtual V \{${ws}private:${ws}V \[*\]+_vb.V;${ws}int a;${ws}public:${ws}A & operator=\\(A const &\\);${ws}A\\(int, A const &\\);${ws}A\\(int\\);${ws}virtual int f\\(void\\);${ws}\}\r\n$gdb_prompt $" { + pass "ptype a" + } + -re "type = class A : public virtual V \{${ws}private:${ws}V \[*\]+_vb.V;${ws}int a;${ws}public:((${ws}A & operator=\\(A const &\\);)|(${ws}A\\(int, A const &\\);)|(${ws}A\\(int\\);)|(${ws}virtual int f\\(void\\);))*${ws}\}\r\n$gdb_prompt $" { + pass "ptype a (obsolescent gcc or gdb)" + } + -re ".*$gdb_prompt $" { + fail "ptype a" + } + timeout { + fail "ptype a (timeout)" + } + } + + send_gdb "ptype b\n" + gdb_expect { + -re "type = class B : public A \{${ws}private:${ws}int b;${ws}public:${ws}B & operator=\\(B const &\\);${ws}B\\(int, B const &\\);${ws}B\\(int\\);${ws}virtual int f\\(void\\);${ws}\}\r\n$gdb_prompt $" { + pass "ptype b" + } + -re "type = class B : public A \{${ws}private:${ws}int b;${ws}public:((${ws}B & operator=\\(B const &\\);)|(${ws}B\\(int, B const &\\);)|(${ws}B\\(int\\);)|(${ws}virtual int f\\(void\\);))*${ws}\}\r\n$gdb_prompt $" { + pass "ptype b (obsolescent gcc or gdb)" + } + -re ".*$gdb_prompt $" { + fail "ptype b" + } + timeout { + fail "ptype b (timeout)" + } + } + + send_gdb "ptype c\n" + gdb_expect { + -re "type = class C : public virtual V \{\[\r\n\t \]+public:\[\r\n\t \]+int c;\[\r\n\t \]+\}\r\n$gdb_prompt $" { + pass "ptype c (aCC)" + } + -re "type = class C : public virtual V \{${ws}private:${ws}V \[*\]+_vb.V;${ws}public:${ws}int c;${ws}C & operator=\\(C const &\\);${ws}C\\(int, C const &\\);${ws}C\\(int\\);${ws}\}\r\n$gdb_prompt $" { + pass "ptype c" + } + -re "type = class C : public virtual V \{${ws}private:${ws}V \[*\]+_vb.V;${ws}public:${ws}int c;((${ws}C & operator=\\(C const &\\);)|(${ws}C\\(int, C const &\\);)|(${ws}C\\(int\\);))*${ws}\}\r\n$gdb_prompt $" { + pass "ptype c (obsolescent gcc or gdb)" + } + -re ".*$gdb_prompt $" { + fail "ptype c" + } + timeout { + fail "ptype c (timeout)" + } + } + + send_gdb "ptype d\n" + gdb_expect { + -re "type = class D : public AD, public virtual V \{\[\r\n\t \]+public:\[\r\n\t \]+int d;\[\r\n\t \]+static void s\\(void\\);\[\r\n\t \]+virtual int vg\\(void\\);\[\r\n\t \]+virtual int vd\\(void\\);\[\r\n\t \]+int fd\\(void\\);\[\r\n\t \]+\}\r\n$gdb_prompt $" { + pass "ptype d (aCC)" + } + -re "type = class D : public AD, public virtual V \{${ws}private:${ws}V \[*\]+_vb.V;${ws}public:${ws}int d;${ws}D & operator=\\(D const &\\);${ws}D\\(int, D const &\\);${ws}D\\(int\\);${ws}static void s\\(void\\);${ws}virtual int vg\\(void\\);${ws}virtual int vd\\(void\\);${ws}int fd\\(void\\);${ws}\}\r\n$gdb_prompt $" { + pass "ptype d" + } + -re "type = class D : public AD, public virtual V \{${ws}private:${ws}V \[*\]+_vb.V;${ws}public:${ws}int d;((${ws}D & operator=\\(D const &\\);)|(${ws}D\\(int, D const &\\);)|(${ws}D\\(int\\);)|(${ws}static void s\\(void\\);)|(${ws}virtual int vg\\(void\\);)|(${ws}virtual int vd\\(void\\);)|(${ws}int fd\\(void\\);))*${ws}\}\r\n$gdb_prompt $" { + pass "ptype d (obsolescent gcc or gdb)" + } + -re ".*$gdb_prompt $" { + fail "ptype d" + } + timeout { + fail "ptype d (timeout)" + } + } + + send_gdb "ptype e\n" + gdb_expect { + -re "type = class E : public B, public virtual V, public D, public C \{${ws}public:${ws}int e;${ws}E & operator=\\(E const &\\);${ws}E\\(int, E const &\\);${ws}E\\(int\\);${ws}virtual int f\\(void\\);${ws}virtual int vg\\(void\\);${ws}virtual int vv\\(void\\);${ws}\}\r\n$gdb_prompt $" { + pass "ptype e" + } + -re "type = class E : public B, public virtual V, public D, public C \{${ws}public:${ws}int e;((${ws}E & operator=\\(E const &\\);)|(${ws}E\\(int, E const &\\);)|(${ws}E\\(int\\);)|(${ws}virtual int f\\(void\\);)|(${ws}virtual int vg\\(void\\);)|(${ws}virtual int vv\\(void\\);))*${ws}\}\r\n$gdb_prompt $" { + pass "ptype e (obsolescent gcc or gdb)" + } + -re ".*$gdb_prompt $" { + fail "ptype e" + } + timeout { + fail "ptype e (timeout)" + } + } + + send_gdb "ptype v\n" + gdb_expect { + -re "type = class V : public VA, public VB \{${ws}public:${ws}int w;${ws}V & operator=\\(V const &\\);${ws}V\\(V const &\\);${ws}V\\(void\\);${ws}int f\\(void\\);${ws}virtual int vv\\(void\\);${ws}\}\r\n$gdb_prompt $" { + pass "ptype v" + } + -re "type = class V : public VA, public VB \{${ws}public:${ws}int w;((${ws}V & operator=\\(V const &\\);)|(${ws}V\\(V const &\\);)|(${ws}V\\(void\\);)|(${ws}int f\\(void\\);)|(${ws}virtual int vv\\(void\\);))*${ws}\}\r\n$gdb_prompt $" { + pass "ptype v (obsolescent gcc or gdb)" + } + -re ".*$gdb_prompt $" { + fail "ptype v" + } + timeout { + fail "ptype v (timeout)" + } + } + + send_gdb "ptype vb\n" + gdb_expect { + -re "type = class VB \{${ws}public:${ws}int vb;${ws}VB & operator=\\(VB const &\\);${ws}VB\\(VB const &\\);${ws}VB\\(void\\);${ws}int fvb\\(void\\);${ws}virtual int vvb\\(void\\);${ws}\}\r\n$gdb_prompt $" { + pass "ptype vb" + } + -re "type = class VB \{${ws}public:${ws}int vb;((${ws}VB & operator=\\(VB const &\\);)|(${ws}VB\\(VB const &\\);)|(${ws}VB\\(void\\);)|(${ws}int fvb\\(void\\);)|(${ws}virtual int vvb\\(void\\);))*${ws}\}\r\n$gdb_prompt $" { + pass "ptype vb (obsolescent gcc or gdb)" + } + -re ".*$gdb_prompt $" { + fail "ptype vb" + } + timeout { + fail "ptype vb (timeout)" + } + } + + send_gdb "ptype pAa\n" + gdb_expect { + -re "type = class A : public virtual V \{\[\r\n\t \]+private:\[\r\n\t \]+int a;\[\r\n\t \]+public:\[\r\n\t \]+virtual int f\\(void\\);\[\r\n\t \]+\} \[*\]+\r\n$gdb_prompt $" { + pass "ptype pAa (aCC)" + } + -re "type = class A : public virtual V \{${ws}private:${ws}V \[*\]+_vb.V;${ws}int a;${ws}public:${ws}A & operator=\\(A const &\\);${ws}A\\(int, A const &\\);${ws}A\\(int\\);${ws}virtual int f\\(void\\);${ws}\} \[*\]+\r\n$gdb_prompt $" { + pass "ptype pAa" + } + -re "type = class A : public virtual V \{${ws}private:${ws}V \[*\]+_vb.V;${ws}int a;${ws}public:((${ws}A & operator=\\(A const &\\);)|(${ws}A\\(int, A const &\\);)|(${ws}A\\(int\\);)|(${ws}virtual int f\\(void\\);))*${ws}\} \[*\]+\r\n$gdb_prompt $" { + pass "ptype pAa (obsolescent gcc or gdb)" + } + -re ".*$gdb_prompt $" { + fail "ptype pAa" + } + timeout { + fail "ptype pAa (timeout)" + } + } + + send_gdb "ptype pAe\n" + gdb_expect { + -re "type = class A : public virtual V \{\[\r\n\t \]+private:\[\r\n\t \]+int a;\[\r\n\t \]+public:\[\r\n\t \]+virtual int f\\(void\\);\[\r\n\t \]+\} \[*\]+\r\n$gdb_prompt $" { + pass "ptype pAe (aCC)" + } + -re "type = class A : public virtual V \{${ws}private:${ws}V \[*\]+_vb.V;${ws}int a;${ws}public:${ws}A & operator=\\(A const &\\);${ws}A\\(int, A const &\\);${ws}A\\(int\\);${ws}virtual int f\\(void\\);${ws}\} \[*\]+\r\n$gdb_prompt $" { + pass "ptype pAe" + } + -re "type = class A : public virtual V \{${ws}private:${ws}V \[*\]+_vb.V;${ws}int a;${ws}public:((${ws}A & operator=\\(A const &\\);)|(${ws}A\\(int, A const &\\);)|(${ws}A\\(int\\);)|(${ws}virtual int f\\(void\\);))*${ws}\} \[*\]+\r\n$gdb_prompt $" { + pass "ptype pAe (obsolescent gcc or gdb)" + } + -re ".*$gdb_prompt $" { + fail "ptype pAe" + } + timeout { + fail "ptype pAe (timeout)" + } + } + + send_gdb "ptype pBe\n" + gdb_expect { + -re "type = class B : public A \{${ws}private:${ws}int b;${ws}public:${ws}B & operator=\\(B const &\\);${ws}B\\(int, B const &\\);${ws}B\\(int\\);${ws}virtual int f\\(void\\);${ws}\} \[*\]+\r\n$gdb_prompt $" { + pass "ptype pBe" + } + -re "type = class B : public A \{${ws}private:${ws}int b;${ws}public:((${ws}B & operator=\\(B const &\\);)|(${ws}B\\(int, B const &\\);)|(${ws}B\\(int\\);)|(${ws}virtual int f\\(void\\);))*${ws}\} \[*\]+\r\n$gdb_prompt $" { + pass "ptype pBe (obsolescent gcc or gdb)" + } + -re ".*$gdb_prompt $" { + fail "ptype pBe" + } + timeout { + fail "ptype pBe (timeout)" + } + } + + send_gdb "ptype pDd\n" + gdb_expect { + -re "type = class D : public AD, public virtual V \{\[\r\n\t \]+public:\[\r\n\t \]+int d;\[\r\n\t \]+static void s\\(void\\);\[\r\n\t \]+virtual int vg\\(void\\);\[\r\n\t \]+virtual int vd\\(void\\);\[\r\n\t \]+int fd\\(void\\);\[\r\n\t \]+\} \[*\]+\r\n$gdb_prompt $" { + pass "ptype pDd (aCC)" + } + -re "type = class D : public AD, public virtual V \{${ws}private:${ws}V \[*\]+_vb.V;${ws}public:${ws}int d;${ws}D & operator=\\(D const &\\);${ws}D\\(int, D const &\\);${ws}D\\(int\\);${ws}static void s\\(void\\);${ws}virtual int vg\\(void\\);${ws}virtual int vd\\(void\\);${ws}int fd\\(void\\);${ws}\} \[*\]+\r\n$gdb_prompt $" { + pass "ptype pDd" + } + -re "type = class D : public AD, public virtual V \{${ws}private:${ws}V \[*\]+_vb.V;${ws}public:${ws}int d;((${ws}D & operator=\\(D const &\\);)|(${ws}D\\(int, D const &\\);)|(${ws}D\\(int\\);)|(${ws}static void s\\(void\\);)|(${ws}virtual int vg\\(void\\);)|(${ws}virtual int vd\\(void\\);)|(${ws}int fd\\(void\\);))*${ws}\} \[*\]+\r\n$gdb_prompt $" { + pass "ptype pDd (obsolescent gcc or gdb)" + } + -re ".*$gdb_prompt $" { + fail "ptype pDd" + } + timeout { + fail "ptype pDd (timeout)" + } + } + + send_gdb "ptype pDe\n" + gdb_expect { + -re "type = class D : public AD, public virtual V \{\[\r\n\t \]+public:\[\r\n\t \]+int d;\[\r\n\t \]+static void s\\(void\\);\[\r\n\t \]+virtual int vg\\(void\\);\[\r\n\t \]+virtual int vd\\(void\\);\[\r\n\t \]+int fd\\(void\\);\[\r\n\t \]+\} \[*\]+\r\n$gdb_prompt $" { + pass "ptype pDe (aCC)" + } + -re "type = class D : public AD, public virtual V \{${ws}private:${ws}V \[*\]+_vb.V;${ws}public:${ws}int d;${ws}D & operator=\\(D const &\\);${ws}D\\(int, D const &\\);${ws}D\\(int\\);${ws}static void s\\(void\\);${ws}virtual int vg\\(void\\);${ws}virtual int vd\\(void\\);${ws}int fd\\(void\\);${ws}\} \[*\]+\r\n$gdb_prompt $" { + pass "ptype pDe" + } + -re "type = class D : public AD, public virtual V \{${ws}private:${ws}V \[*\]+_vb.V;${ws}public:${ws}int d;((${ws}D & operator=\\(D const &\\);)|(${ws}D\\(int, D const &\\);)|(${ws}D\\(int\\);)|(${ws}static void s\\(void\\);)|(${ws}virtual int vg\\(void\\);)|(${ws}virtual int vd\\(void\\);)|(${ws}int fd\\(void\\);))*${ws}\} \[*\]+\r\n$gdb_prompt $" { + pass "ptype pDe (obsolescent gcc or gdb)" + } + -re ".*$gdb_prompt $" { + fail "ptype pDe" + } + timeout { + fail "ptype pDe (timeout)" + } + } + + send_gdb "ptype pVa\n" + gdb_expect { + -re "type = class V : public VA, public VB \{${ws}public:${ws}int w;${ws}V & operator=\\(V const &\\);${ws}V\\(V const &\\);${ws}V\\(void\\);${ws}int f\\(void\\);${ws}virtual int vv\\(void\\);${ws}\} \[*\]+\r\n$gdb_prompt $" { + pass "ptype pVa" + } + -re "type = class V : public VA, public VB \{${ws}public:${ws}int w;((${ws}V & operator=\\(V const &\\);)|(${ws}V\\(V const &\\);)|(${ws}V\\(void\\);)|(${ws}int f\\(void\\);)|(${ws}virtual int vv\\(void\\);))*${ws}\} \[*\]+\r\n$gdb_prompt $" { + pass "ptype pVa (obsolescent gcc or gdb)" + } + -re ".*$gdb_prompt $" { + fail "ptype pVa" + } + timeout { + fail "ptype pVa (timeout)" + } + } + + send_gdb "ptype pVv\n" + gdb_expect { + -re "type = class V : public VA, public VB \{${ws}public:${ws}int w;${ws}V & operator=\\(V const &\\);${ws}V\\(V const &\\);${ws}V\\(void\\);${ws}int f\\(void\\);${ws}virtual int vv\\(void\\);${ws}\} \[*\]+\r\n$gdb_prompt $" { + pass "ptype pVv" + } + -re "type = class V : public VA, public VB \{${ws}public:${ws}int w;((${ws}V & operator=\\(V const &\\);)|(${ws}V\\(V const &\\);)|(${ws}V\\(void\\);)|(${ws}int f\\(void\\);)|(${ws}virtual int vv\\(void\\);))*${ws}\} \[*\]+\r\n$gdb_prompt $" { + pass "ptype pVv (obsolescent gcc or gdb)" + } + -re ".*$gdb_prompt $" { + fail "ptype pVv" + } + timeout { + fail "ptype pVv (timeout)" + } + } + + send_gdb "ptype pVe\n" + gdb_expect { + -re "type = class V : public VA, public VB \{${ws}public:${ws}int w;${ws}V & operator=\\(V const &\\);${ws}V\\(V const &\\);${ws}V\\(void\\);${ws}int f\\(void\\);${ws}virtual int vv\\(void\\);${ws}\} \[*\]+\r\n$gdb_prompt $" { + pass "ptype pVe" + } + -re "type = class V : public VA, public VB \{${ws}public:${ws}int w;((${ws}V & operator=\\(V const &\\);)|(${ws}V\\(V const &\\);)|(${ws}V\\(void\\);)|(${ws}int f\\(void\\);)|(${ws}virtual int vv\\(void\\);))*${ws}\} \[*\]+\r\n$gdb_prompt $" { + pass "ptype pVe (obsolescent gcc or gdb)" + } + -re ".*$gdb_prompt $" { + fail "ptype pVe" + } + timeout { + fail "ptype pVe (timeout)" + } + } + + send_gdb "ptype pVd\n" + gdb_expect { + -re "type = class V : public VA, public VB \{${ws}public:${ws}int w;${ws}V & operator=\\(V const &\\);${ws}V\\(V const &\\);${ws}V\\(void\\);${ws}int f\\(void\\);${ws}virtual int vv\\(void\\);${ws}\} \[*\]+\r\n$gdb_prompt $" { + pass "ptype pVd" + } + -re "type = class V : public VA, public VB \{${ws}public:${ws}int w;((${ws}V & operator=\\(V const &\\);)|(${ws}V\\(V const &\\);)|(${ws}V\\(void\\);)|(${ws}int f\\(void\\);)|(${ws}virtual int vv\\(void\\);))*${ws}\} \[*\]+\r\n$gdb_prompt $" { + pass "ptype pVd (obsolescent gcc or gdb)" + } + -re ".*$gdb_prompt $" { + fail "ptype pVd" + } + timeout { + fail "ptype pVd (timeout)" + } + } + + send_gdb "ptype pADe\n" + gdb_expect { + -re "type = class AD \{${ws}public:${ws}AD & operator=\\(AD const &\\);${ws}AD\\(AD const &\\);${ws}AD\\(void\\);${ws}virtual int vg\\(void\\);${ws}\} \[*\]+\r\n$gdb_prompt $" { + pass "ptype pADe" + } + -re "type = class AD \{${ws}public:((${ws}AD & operator=\\(AD const &\\);)|(${ws}AD\\(AD const &\\);)|(${ws}AD\\(void\\);)|(${ws}virtual int vg\\(void\\);))*${ws}\} \[*\]+\r\n$gdb_prompt $" { + pass "ptype pADe (obsolescent gcc or gdb)" + } + -re ".*$gdb_prompt $" { + fail "ptype pADe" + } + timeout { + fail "ptype pADe (timeout)" + } + } + + send_gdb "ptype pEe\n" + gdb_expect { + -re "type = class E : public B, public virtual V, public D, public C \{${ws}public:${ws}int e;${ws}E & operator=\\(E const &\\);${ws}E\\(int, E const &\\);${ws}E\\(int\\);${ws}virtual int f\\(void\\);${ws}virtual int vg\\(void\\);${ws}virtual int vv\\(void\\);${ws}\} \[*\]+\r\n$gdb_prompt $" { + pass "ptype pEe" + } + -re "type = class E : public B, public virtual V, public D, public C \{${ws}public:${ws}int e;((${ws}E & operator=\\(E const &\\);)|(${ws}E\\(int, E const &\\);)|(${ws}E\\(int\\);)|(${ws}virtual int f\\(void\\);)|(${ws}virtual int vg\\(void\\);)|(${ws}virtual int vv\\(void\\);))*${ws}\} \[*\]+\r\n$gdb_prompt $" { + pass "ptype pEe (obsolescent gcc or gdb)" + } + -re ".*$gdb_prompt $" { + fail "ptype pEe" + } + timeout { + fail "ptype pEe (timeout)" + } + } + + send_gdb "ptype pVB\n" + gdb_expect { + -re "type = class VB \{${ws}public:${ws}int vb;${ws}VB & operator=\\(VB const &\\);${ws}VB\\(VB const &\\);${ws}VB\\(void\\);${ws}int fvb\\(void\\);${ws}virtual int vvb\\(void\\);${ws}\} \[*\]+\r\n$gdb_prompt $" { + pass "ptype pVB" + } + -re "type = class VB \{${ws}public:${ws}int vb;((${ws}VB & operator=\\(VB const &\\);)|(${ws}VB\\(VB const &\\);)|(${ws}VB\\(void\\);)|(${ws}int fvb\\(void\\);)|(${ws}virtual int vvb\\(void\\);))*${ws}\} \[*\]+\r\n$gdb_prompt $" { + pass "ptype pVB (obsolescent gcc or gdb)" + } + -re ".*$gdb_prompt $" { + fail "ptype pVB" + } + timeout { + fail "ptype pVB (timeout)" + } + } +} + +# +# Test calling of virtual functions. +# + +proc test_virtual_calls {} { + global gdb_prompt + global GDB + + if [target_info exists gdb,cannot_call_functions] { + setup_xfail "*-*-*" 2416 + fail "This target can not call functions" + return 0 + } + + send_gdb "print pAe->f()\n" + gdb_expect { + -re ".* = 20\r\n$gdb_prompt $" { pass "print pAe->f()" } + -re "Cannot invoke functions on this machine.*$gdb_prompt $" { + fail "print pAe->f() (cannot invoke functions, skipping virtual calls)" + return 0 + } + -re ".*Cannot access memory at address 0x8.*$gdb_prompt $" { + fail "print pAe->f() \ +(known failure with gcc cygnus-2.4.5-930417, skipping virtual calls)" + return 0 + } + -re ".*$gdb_prompt $" { fail "print pAe->f()" } + timeout { fail "print pAe->f() (timeout)" } + eof { fail "print pAe->f() ($GDB dumped core) (FIXME)" ; gdb_virtfunc_restart; return } + } + + send_gdb "print pAa->f()\n" + gdb_expect { + -re ".* = 1\r\n$gdb_prompt $" { pass "print pAa->f()" } + -re ".*$gdb_prompt $" { fail "print pAa->f()" } + timeout { fail "print pAa->f() (timeout)" } + eof { fail "print pAa->f() ($GDB dumped core) (FIXME)" ; gdb_virtfunc_restart; return } + } + + send_gdb "print pDe->vg()\n" +# setup_xfail "*-*-*" + gdb_expect { + -re ".* = 202\r\n$gdb_prompt $" { pass "print pDe->vg()" } + -re ".*$gdb_prompt $" { fail "print pDe->vg()" } + timeout { fail "print pDe->vg() (timeout)" } + eof { fail "print pDe->vg() ($GDB dumped core) (FIXME)" ; gdb_virtfunc_restart; return } + } + + send_gdb "print pADe->vg()\n" + gdb_expect { + -re ".* = 202\r\n$gdb_prompt $" { pass "print pADe->vg()" } + -re ".*$gdb_prompt $" { fail "print pADe->vg()" } + timeout { fail "print pADe->vg() (timeout)" } + eof { fail "print pADe->vg() ($GDB dumped core) (FIXME)" ; gdb_virtfunc_restart; return } + } + + send_gdb "print pDd->vg()\n" +# setup_xfail "*-*-*" + gdb_expect { + -re ".* = 101\r\n$gdb_prompt $" { pass "print pDd->vg()" } + -re ".*$gdb_prompt $" { fail "print pDd->vg()" } + timeout { fail "print pDd->vg() (timeout)" } + eof { fail "print pDd->vg() ($GDB dumped core) (FIXME)" ; gdb_virtfunc_restart; return } + } + + send_gdb "print pEe->vvb()\n" +# setup_xfail "*-*-*" + gdb_expect { + -re ".* = 411\r\n$gdb_prompt $" { pass "print pEe->vvb()" } + -re ".*$gdb_prompt $" { fail "print pEe->vvb()" } + timeout { fail "print pEe->vvb() (timeout)" } + eof { fail "print pEe->vvb() ($GDB dumped core) (FIXME)" ; gdb_virtfunc_restart; return } + } + + send_gdb "print pVB->vvb()\n" + gdb_expect { + -re ".* = 407\r\n$gdb_prompt $" { pass "print pVB->vvb()" } + -re ".*$gdb_prompt $" { fail "print pVB->vvb()" } + timeout { fail "print pVB->vvb() (timeout)" } + eof { fail "print pVB->vvb() ($GDB dumped core) (FIXME)" ; gdb_virtfunc_restart; return } + } + + send_gdb "print pBe->vvb()\n" +# setup_xfail "*-*-*" + gdb_expect { + -re ".* = 411\r\n$gdb_prompt $" { pass "print pBe->vvb()" } + -re ".*$gdb_prompt $" { fail "print pBe->vvb()" } + timeout { fail "print pBe->vvb() (timeout)" } + eof { fail "print pBe->vvb() ($GDB dumped core) (FIXME)" ; gdb_virtfunc_restart; return } + } + + send_gdb "print pDe->vvb()\n" +# setup_xfail "*-*-*" + gdb_expect { + -re ".* = 411\r\n$gdb_prompt $" { pass "print pDe->vvb()" } + -re ".*$gdb_prompt $" { fail "print pDe->vvb()" } + timeout { fail "print pDe->vvb() (timeout)" } + eof { fail "print pDe->vvb() ($GDB dumped core) (FIXME)" ; gdb_virtfunc_restart; return } + } + + send_gdb "print pEe->vd()\n" +# setup_xfail "*-*-*" + gdb_expect { + -re ".* = 282\r\n$gdb_prompt $" { pass "print pEe->vd()" } + -re ".*$gdb_prompt $" { fail "print pEe->vd()" } + timeout { fail "print pEe->vd() (timeout)" } + eof { fail "print pEe->vd() ($GDB dumped core) (FIXME)" ; gdb_virtfunc_restart; return } + } + + send_gdb "print pEe->fvb()\n" +# setup_xfail "*-*-*" + gdb_expect { + -re ".* = 311\r\n$gdb_prompt $" { pass "print pEe->fvb()" } + -re ".*$gdb_prompt $" { fail "print pEe->fvb()" } + timeout { fail "print pEe->fvb() (timeout)" } + eof { fail "print pEe->fvb() ($GDB dumped core) (FIXME)" ; gdb_virtfunc_restart; return } + } + + send_gdb "print pEe->D::vg()\n" + setup_xfail "*-*-*" + gdb_expect { + -re ".* = 102\r\n$gdb_prompt $" { pass "print pEe->D::vg()" } + -re ".*$gdb_prompt $" { fail "print pEe->D::vg()" } + timeout { fail "print pEe->D::vg() (timeout)" } + eof { fail "print pEe->D::vg() ($GDB dumped core) (FIXME)" ; gdb_virtfunc_restart; return } + } +} + +proc do_tests {} { + global prms_id + global bug_id + + set prms_id 0 + set bug_id 0 + + gdb_start; + gdb_virtfunc_init; + + # Get the debug format for the compiled test case. If that + # format is DWARF 1 then just skip all the tests since none of + # them will pass. + + if [ runto_main ] then { + get_debug_format + if [ setup_xfail_format "DWARF 1" ] then { + fail "C++ tests skipped due to limited C++ support in DWARF 1 debug format" + return + } + clear_xfail "*-*-*" + } + + test_ptype_of_classes + + if [ runto 'test_calls(void)' ] then { + test_virtual_calls + } +} + +do_tests diff --git a/gdb/testsuite/gdb.hp/watch-cmd.exp b/gdb/testsuite/gdb.hp/watch-cmd.exp new file mode 100644 index 00000000000..a7e3b5c5132 --- /dev/null +++ b/gdb/testsuite/gdb.hp/watch-cmd.exp @@ -0,0 +1,165 @@ +# Copyright (C) 1998 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 2 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +# Please email any bugs, comments, and/or additions to this file to: +# bug-gdb@prep.ai.mit.edu + +if $tracelevel then { + strace $tracelevel +} + +# +# test special commands +# +set prms_id 0 +set bug_id 0 + +set testfile "run-hp" +set srcfile ${testfile}.c +set binfile ${objdir}/${subdir}/${testfile} +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug additional_flags=-DFAKEARGV}] != "" } { + gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail." + +} + +# are we on a target board +if ![isnative] then { + return +} + +if {![istarget "hppa*-*-hpux10.30"] && ![istarget "hppa*-*-hpux11.*"]} { + #setup_xfail "*-*.*" + return 0 +} + +if [get_compiler_info ${binfile}] { + return -1; +} +if {[skip_hp_tests $gcc_compiled]} then { continue } + + +gdb_exit +gdb_start +delete_breakpoints +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + + + +proc watchpoint_command_test {} { + global gdb_prompt + + if [target_info exists noargs] { + verbose "Skipping watchpoint_command_test because of noargs." + return + } + + if { ![runto factorial] } then { gdb_suppress_tests } + # Don't depend upon argument passing, since most simulators don't currently + # support it. Bash value variable to be what we want. + gdb_test "p value=6" "" "set value to 6 in watchpoint_command_test" + delete_breakpoints + + # Verify that we can create a watchpoint, and give it a commands + # list that continues the inferior. We set the watchpoint on a + # local variable, too, so that it self-deletes when the watched + # data goes out of scope. + # + # What should happen is: Each time the watchpoint triggers, it + # continues the inferior. Eventually, the watchpoint will self- + # delete, when the watched variable is out of scope. But by that + # time, the inferior should have exited. GDB shouldn't crash or + # anything untoward as a result of this. + # + send_gdb "watch local_var\n" + gdb_expect { + -re ".*\[Ww\]atchpoint (\[0-9\]*): local_var.*$gdb_prompt $"\ + { pass "watch local_var" + set wp_id $expect_out(1,string) + send_gdb "commands $wp_id\n" + gdb_expect { + -re "Type commands for when breakpoint $wp_id is hit, one per line.*>"\ + { pass "begin commands on watch"} + -re "$gdb_prompt $"\ + {fail "begin commands on watch"} + timeout {fail "(timeout) begin commands on watch"} + } + } + -re "$gdb_prompt $"\ + {fail "watch local_var"} + timeout {fail "(timeout) watch local_var"} + } +# set wp_id $expect_out(1,string) +# send_gdb "commands $wp_id\n" +# gdb_expect { +# -re "Type commands for when breakpoint $wp_id is hit, one per line.*>"\ +# {pass "begin commands on watch"} +# -re "$gdb_prompt $"\ +# {fail "begin commands on watch"} +# timeout {fail "(timeout) begin commands on watch"} +# } + send_gdb "print value\n" + gdb_expect { + -re ">"\ + {pass "add print command to watch"} + -re "$gdb_prompt $"\ + {fail "add print command to watch"} + timeout {fail "(timeout) add print command to watch"} + } + send_gdb "continue\n" + gdb_expect { + -re ">"\ + {pass "add continue command to watch"} + -re "$gdb_prompt $"\ + {fail "add continue command to watch"} + timeout {fail "(timeout) add continue command to watch"} + } + send_gdb "end\n" + gdb_expect { + -re "$gdb_prompt $"\ + {pass "begin commands on watch"} + timeout {fail "(timeout) begin commands on watch"} + } + send_gdb "continue\n" + gdb_expect { + -re "Continuing.*\[Ww\]atchpoint $wp_id deleted because the program has left the block in.*which its expression is valid.*in main.*$gdb_prompt $"\ + {pass "continue with watch"} + -re "$gdb_prompt $"\ + {fail "continue with watch"} + timeout {fail "(timeout) continue with watch"} + } + send_gdb "continue\n" + gdb_expect { + -re "Continuing.*$gdb_prompt $"\ + {pass "continue until exit"} + -re "$gdb_prompt $"\ + {fail "continue until exit"} + timeout {fail "(timeout) continue until exit"} + } +} + +watchpoint_command_test + + + + + + + + + + + diff --git a/gdb/testsuite/gdb.hp/watch-hp.c b/gdb/testsuite/gdb.hp/watch-hp.c new file mode 100644 index 00000000000..7336fe2bec8 --- /dev/null +++ b/gdb/testsuite/gdb.hp/watch-hp.c @@ -0,0 +1,166 @@ +#include <stdio.h> +/* + * Since using watchpoints can be very slow, we have to take some pains to + * ensure that we don't run too long with them enabled or we run the risk + * of having the test timeout. To help avoid this, we insert some marker + * functions in the execution stream so we can set breakpoints at known + * locations, without worrying about invalidating line numbers by changing + * this file. We use null bodied functions are markers since gdb does + * not support breakpoints at labeled text points at this time. + * + * One place we need is a marker for when we start executing our tests + * instructions rather than any process startup code, so we insert one + * right after entering main(). Another is right before we finish, before + * we start executing any process termination code. + * + * Another problem we have to guard against, at least for the test + * suite, is that we need to ensure that the line that causes the + * watchpoint to be hit is still the current line when gdb notices + * the hit. Depending upon the specific code generated by the compiler, + * the instruction after the one that triggers the hit may be part of + * the same line or part of the next line. Thus we ensure that there + * are always some instructions to execute on the same line after the + * code that should trigger the hit. + */ + +int count = -1; +int ival1 = -1; +int ival2 = -1; +int ival3 = -1; +int ival4 = -1; +int ival5 = -1; +char buf[10]; +struct foo +{ + int val; +}; +struct foo struct1, struct2, *ptr1, *ptr2; + +int doread = 0; + +void marker1 () +{ +} + +void marker2 () +{ +} + +void marker4 () +{ +} + +void marker5 () +{ +} + +void marker6 () +{ +} + +void recurser (x) + int x; +{ + int local_x; + + if (x > 0) + recurser (x-1); + local_x = x; +} + +void +func2 () +{ + int local_a; + static int static_b; + + ival5++; + local_a = ival5; + static_b = local_a; +} + +int +func1 () +{ + /* The point of this is that we will set a breakpoint at this call. + + Then, if DECR_PC_AFTER_BREAK equals the size of a function call + instruction (true on a sun3 if this is gcc-compiled--FIXME we + should use asm() to make it work for any compiler, present or + future), then we will end up branching to the location just after + the breakpoint. And we better not confuse that with hitting the + breakpoint. */ + func2 (); + return 73; +} + +int main () +{ + struct1.val = 1; + struct2.val = 2; + ptr1 = &struct1; + ptr2 = &struct2; + marker1 (); + func1 (); + for (count = 0; count < 4; count++) { + ival1 = count; + ival3 = count; ival4 = count; + } + ival1 = count; /* Outside loop */ + ival2 = count; + ival3 = count; ival4 = count; + marker2 (); + if (doread) + { + static char msg[] = "type stuff for buf now:"; + write (1, msg, sizeof (msg) - 1); + read (0, &buf[0], 5); + } + marker4 (); + + /* We have a watchpoint on ptr1->val. It should be triggered if + ptr1's value changes. */ + ptr1 = ptr2; + + /* This should not trigger the watchpoint. If it does, then we + used the wrong value chain to re-insert the watchpoints or we + are not evaluating the watchpoint expression correctly. */ + struct1.val = 5; + marker5 (); + + /* We have a watchpoint on ptr1->val. It should be triggered if + ptr1's value changes. */ + ptr1 = ptr2; + + /* This should not trigger the watchpoint. If it does, then we + used the wrong value chain to re-insert the watchpoints or we + are not evaluating the watchpoint expression correctly. */ + struct1.val = 5; + marker5 (); + + /* We're going to watch locals of func2, to see that out-of-scope + watchpoints are detected and properly deleted. + */ + marker6 (); + + /* This invocation is used for watches of a single + local variable. */ + func2 (); + + /* This invocation is used for watches of an expression + involving a local variable. */ + func2 (); + + /* This invocation is used for watches of a static + (non-stack-based) local variable. */ + func2 (); + + /* This invocation is used for watches of a local variable + when recursion happens. + */ + marker6 (); + recurser (2); + + marker6 (); + return 0; +} diff --git a/gdb/testsuite/gdb.hp/watch-hp.exp b/gdb/testsuite/gdb.hp/watch-hp.exp new file mode 100644 index 00000000000..a1c3fc823f7 --- /dev/null +++ b/gdb/testsuite/gdb.hp/watch-hp.exp @@ -0,0 +1,784 @@ +# Copyright (C) 1992, 1994, 1997 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 2 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +# Please email any bugs, comments, and/or additions to this file to: +# bug-gdb@prep.ai.mit.edu + +# This file was written by Fred Fish. (fnf@cygnus.com) + +if $tracelevel then { + strace $tracelevel +} + +set prms_id 0 +set bug_id 0 + +set testfile "watch-hp" +set srcfile ${testfile}.c +set binfile ${objdir}/${subdir}/${testfile} +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } { + gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail." +} + +if [get_compiler_info ${binfile}] { + return -1; +} +if {[skip_hp_tests $gcc_compiled]} then { continue } + +# Prepare for watchpoint tests by setting up two breakpoints and one +# watchpoint. +# +# We use breakpoints at marker functions to get past all the startup code, +# so we can get to the watchpoints in a reasonable amount of time from a +# known starting point. +# +# For simplicity, so we always know how to reference specific breakpoints or +# watchpoints by number, we expect a particular ordering and numbering of +# each in the combined breakpoint/watchpoint table, as follows: +# +# Number What Where +# 1 Breakpoint marker1() +# 2 Breakpoint marker2() +# 3 Watchpoint ival3 + +proc initialize {} { + global gdb_prompt + global hex + global decimal + global srcfile + + if [gdb_test "break marker1" "Breakpoint 1 at $hex: file .*$srcfile, line $decimal.*" "set breakpoint at marker1" ] { + return 0; + } + + + if [gdb_test "break marker2" "Breakpoint 2 at $hex: file .*$srcfile, line $decimal.*" "set breakpoint at marker2" ] { + return 0; + } + + + if [gdb_test "info break" "1\[ \]*breakpoint.*marker1.*\r\n2\[ \]*breakpoint.*marker2.*" "info break in watchpoint.exp" ] { + return 0; + } + +# ??rehrauer: To fix DTS #CHFts23014, in which setting a watchpoint +# before running can cause the inferior to croak on HP-UX 10.30 and +# 11.0 for reasons as yet unknown, we've disabled the ability to set +# watches without a running inferior. Verify the restriction. +# + send_gdb "watch ival3\n" + gdb_expect { + -re ".*can't do that without a running program; try \"break main\", \"run\" first.*$gdb_prompt $" { + pass "set watchpoint on ival3" + } + -re ".*$gdb_prompt $" { fail "set watchpoint on ival3" } + timeout { fail "set watchpoint on ival3 (timeout)" } + } + + +# if [gdb_test "watch ival3" ".*\[Ww\]atchpoint 3: ival3" "set watchpoint on ival3" ] { +# return 0; +# } + + + # "info watch" is the same as "info break" + +# if [gdb_test "info watch" "1\[ \]*breakpoint.*marker1.*\r\n2\[ \]*breakpoint.*marker2.*\r\n3\[ \]*.*watchpoint.*ival3" "watchpoint found in watchpoint/breakpoint table" ] { +# return 0; +# } + + + # After installing the watchpoint, we disable it until we are ready + # to use it. This allows the test program to run at full speed until + # we get to the first marker function. + +# if [gdb_test "disable 3" "disable 3\[\r\n\]+" "disable watchpoint" ] { +# return 0; +# } + + + return 1 +} + +# +# Test simple watchpoint. +# + +proc test_simple_watchpoint {} { + global gdb_prompt + global hex + global decimal + + # Ensure that the watchpoint is disabled when we startup. + +# if [gdb_test "disable 3" "^disable 3\[\r\n\]+" "disable watchpoint in test_simple_watchpoint" ] { +# return 0; +# } + + + # Run until we get to the first marker function. + + gdb_run_cmd + set timeout 600 + gdb_expect { + -re "Breakpoint 1, marker1 .*$gdb_prompt $" { + pass "run to marker1 in test_simple_watchpoint" + } + -re ".*$gdb_prompt $" { + fail "run to marker1 in test_simple_watchpoint" + return + } + timeout { + fail "run to marker1 in test_simple_watchpoint (timeout)" + return + } + } +#************************ + +# ??rehrauer: To fix DTS #CHFts23014, in which setting a watchpoint +# before running can cause the inferior to croak on HP-UX 10.30 and +# 11.0 for reasons as yet unknown, we've disabled the ability to set +# watches without a running inferior. The following testpoints used +# to be in [initialize]. +# + send_gdb "watch ival3\n" + gdb_expect { + -re ".*\[Ww\]atchpoint 3: ival3\r\n$gdb_prompt $" { + pass "set watchpoint on ival3" + } + -re ".*$gdb_prompt $" { fail "set watchpoint on ival3" } + timeout { fail "set watchpoint on ival3 (timeout)" } + } + + # "info watch" is the same as "info break" + + send_gdb "info watch\n" + gdb_expect { + -re "1\[ \]*breakpoint.*marker1.*\r\n2\[ \]*breakpoint.*marker2.*\r\n3\[ \]*.*watchpoint.*ival3\r\n$gdb_prompt $" { + pass "watchpoint found in watchpoint/breakpoint table" + } + -re ".*$gdb_prompt $" { + fail "watchpoint found in watchpoint/breakpoint table" + } + timeout { + fail "watchpoint found in watchpoint/breakpoint table" + } + } + + # After installing the watchpoint, we disable it until we are ready + # to use it. This allows the test program to run at full speed until + # we get to the first marker function. + + send_gdb "disable 3\n" + gdb_expect { + -re "disable 3\[\r\n\]+$gdb_prompt $" { pass "disable watchpoint" } + -re ".*$gdb_prompt $" { fail "disable watchpoint" } + timeout { fail "disable watchpoint (timeout)" } + } +#****** + # After reaching the marker function, enable the watchpoint. + + if [gdb_test "enable 3" "^enable 3\[\r\n\]+" "enable watchpoint" ] { + return ; + } + + + gdb_test "break func1" "Breakpoint.*at.*" + gdb_test "set \$func1_breakpoint_number = \$bpnum" "" + + gdb_test "continue" "Continuing.*Breakpoint \[0-9\]*, func1.*" \ + "continue to breakpoint at func1" + + # Continue until the first change, from -1 to 0 + + send_gdb "cont\n" + gdb_expect { + -re "Continuing.*\[Ww\]atchpoint.*ival3.*Old value = -1.*New value = 0.*ival3 = count; ival4 = count;.*$gdb_prompt $" { + pass "watchpoint hit, first time" + } + -re "Continuing.*Breakpoint.*func1.*$gdb_prompt $" { + setup_xfail "m68*-*-*" 2597 + fail "thought it hit breakpoint at func1 twice" + gdb_test "delete \$func1_breakpoint_number" "" + gdb_test "continue" "\ +Continuing.*\[Ww\]atchpoint.*ival3.*Old value = -1.*New value = 0.*ival3 = count;" \ + "watchpoint hit, first time" + } + -re ".*$gdb_prompt $" { fail "watchpoint hit, first time" ; return } + timeout { fail "watchpoint hit, first time (timeout)" ; return } + eof { fail "watchpoint hit, first time (eof)" ; return } + } + + gdb_test "delete \$func1_breakpoint_number" "" + + # Continue until the next change, from 0 to 1. + gdb_test "cont" "Continuing.*\[Ww\]atchpoint.*ival3.*Old value = 0.*New value = 1.*ival3 = count; ival4 = count;.*" "watchpoint hit, second time" + + # Continue until the next change, from 1 to 2. + gdb_test "cont" "Continuing.*\[Ww\]atchpoint.*ival3.*Old value = 1.*New value = 2.*ival3 = count; ival4 = count;.*" "watchpoint hit, third time" + + # Continue until the next change, from 2 to 3. + gdb_test "cont" "Continuing.*\[Ww\]atchpoint.*ival3.*Old value = 2.*New value = 3.*ival3 = count; ival4 = count;.*" "watchpoint hit, fourth time" + + # Continue until the next change, from 3 to 4. + # Note that this one is outside the loop. + + gdb_test "cont" "Continuing.*\[Ww\]atchpoint.*ival3.*Old value = 3.*New value = 4.*ival3 = count; ival4 = count;.*" "watchpoint hit, fifth time" + + # Continue until we hit the finishing marker function. + # Make sure we hit no more watchpoints. + + gdb_test "cont" "Continuing.*Breakpoint.*marker2 \(\).*" \ + "continue to marker2" + + # Disable the watchpoint so we run at full speed until we exit. + + if [gdb_test "disable 3" "^disable 3\[\r\n\]+" "watchpoint disabled" ] { + return ; + } + + + # Run until process exits. + + if [target_info exists gdb,noresults] { return } + + gdb_test "cont" "Continuing.*Program exited normally.*" \ + "continue to exit in test_simple_watchpoint" +} + +# Test disabling watchpoints. + +proc test_disabling_watchpoints {} { + global gdb_prompt + global binfile + global srcfile + global decimal + global hex + + # Ensure that the watchpoint is disabled when we startup. + + if [gdb_test "disable 3" "^disable 3\[\r\n\]+" "disable watchpoint in test_disabling_watchpoints" ] { + return 0; + } + + + # Run until we get to the first marker function. + + gdb_run_cmd + set timeout 600 + gdb_expect { + -re "Breakpoint 1, marker1 .*$gdb_prompt $" { + pass "run to marker1 in test_disabling_watchpoints" + } + -re ".*$gdb_prompt $" { + fail "run to marker1 in test_disabling_watchpoints" + return + } + timeout { + fail "run to marker1 in test_disabling_watchpoints (timeout)" + return + } + } + + # After reaching the marker function, enable the watchpoint. + + if [gdb_test "enable 3" "^enable 3\[\r\n\]+" "watchpoint enabled" ] { + return ; + } + + + # Continue until the first change, from -1 to 0 + # Don't check the old value, because on VxWorks the variable value + # will not have been reinitialized. + gdb_test "cont" "Continuing.*\[Ww\]atchpoint.*ival3.*Old value = .*New value = 0.*ival3 = count; ival4 = count;.*" "watchpoint hit in test_disabling_watchpoints, first time" + + # Continue until the next change, from 0 to 1. + gdb_test "cont" "Continuing.*\[Ww\]atchpoint.*ival3.*Old value = 0.*New value = 1.*ival3 = count; ival4 = count;.*" "watchpoint hit in test_disabling_watchpoints, second time" + + # Disable the watchpoint but leave breakpoints + + if [gdb_test "disable 3" "^disable 3\[\r\n\]+" "disable watchpoint #2 in test_disabling_watchpoints" ] { + return 0; + } + + + # Check watchpoint list, looking for the entry that confirms the + # watchpoint is disabled. + gdb_test "info watchpoints" "3\[ \]*.*watchpoint\[ \]*keep\[ \]*n\[ \]*ival3\r\n.*" "watchpoint disabled in table" + + # Continue until we hit the finishing marker function. + # Make sure we hit no more watchpoints. + gdb_test "cont" "Continuing.*Breakpoint.*marker2 \\(\\).*" \ + "disabled watchpoint skipped" + + if [target_info exists gdb,noresults] { return } + + gdb_test "cont" "Continuing.*Program exited normally.*" \ + "continue to exit in test_disabling_watchpoints" +} + +# Test stepping and other mundane operations with watchpoints enabled +proc test_stepping {} { + global gdb_prompt + + if [runto marker1] then { + gdb_test "watch ival2" ".*\[Ww\]atchpoint \[0-9\]*: ival2" + + # Well, let's not be too mundane. It should be a *bit* of a challenge + gdb_test "break func2 if 0" "Breakpoint.*at.*" + gdb_test "p \$func2_breakpoint_number = \$bpnum" " = .*" + + # The HPPA has a problem here if it's not using hardware watchpoints + if {[ istarget "hppa*-*-*" ] && ![ istarget "hppa*-*-*bsd*" ]} then { + # Don't actually try doing the call, if we do we can't continue. + setup_xfail "*-*-*" + fail "calling function with watchpoint enabled" + } else { + # The problem is that GDB confuses stepping through the call + # dummy with hitting the breakpoint at the end of the call dummy. + # Will be fixed once all architectures define + # CALL_DUMMY_BREAKPOINT_OFFSET. + setup_xfail "*-*-*" + # This doesn't occur if the call dummy starts with a call, + # because we are out of the dummy by the first time the inferior + # stops. + clear_xfail "d10v*-*-*" + clear_xfail "m68*-*-*" + clear_xfail "i*86*-*-*" + clear_xfail "vax-*-*" + # The following architectures define CALL_DUMMY_BREAKPOINT_OFFSET. + clear_xfail "alpha-*-*" + clear_xfail "mips*-*-*" + clear_xfail "sparc-*-*" + clear_xfail "hppa*-*-*bsd*" + # It works with the generic inferior function calling code too. + clear_xfail "mn10200*-*-*" + clear_xfail "mn10300*-*-*" + gdb_test "p func1 ()" "= 73" \ + "calling function with watchpoint enabled" + } + + # + # "finish" brings us back to main. + # On some targets (e.g. alpha) gdb will stop from the finish in midline + # of the marker1 call. This is due to register restoring code on + # the alpha and might be caused by stack adjustment instructions + # on other targets. In this case we will step once more. + # + + send_gdb "finish\n" + gdb_expect { + -re "Run.*exit from.*marker1.* at" { } + default { fail "finish from marker1" ; return } + } + + gdb_expect { + -re "marker1 \\(\\);.*$gdb_prompt $" { + send_gdb "step\n" + exp_continue + } + -re "func1 \\(\\);.*$gdb_prompt $" { + pass "finish from marker1" + } + -re ".*$gdb_prompt $" { + fail "finish from marker1" + } + default { fail "finish from marker1" ; return } + } + + gdb_test "next" "for \\(count = 0.*" "next to `for' in watchpoint.exp" + + # Now test that "until" works. It's a bit tricky to test + # "until", because compilers don't always arrange the code + # exactly the same way, and we might get slightly different + # sequences of statements. But the following should be true + # (if not it is a compiler or a debugger bug): The user who + # does "until" at every statement of a loop should end up + # stepping through the loop once, and the debugger should not + # stop for any of the remaining iterations. + + gdb_test "until" "ival1 = count.*" "until to ival1 assignment" + gdb_test "until" "ival3 = count.*" "until to ival3 assignment" + send_gdb "until\n" + gdb_expect { + -re "(for \\(count = 0|\}).*$gdb_prompt $" { + gdb_test "until" "ival1 = count; /. Outside loop ./" \ + "until out of loop" + } + -re "ival1 = count; /. Outside loop ./.*$gdb_prompt $" { + pass "until out of loop" + } + -re ".*$gdb_prompt $" { + fail "until out of loop" + } + default { fail "until out of loop" ; return } + } + + gdb_test "step" "ival2 = count.*" "step to ival2 assignment" + } +} + +# Test stepping and other mundane operations with watchpoints enabled +proc test_watchpoint_triggered_in_syscall {} { + global gdb_prompt + + if [target_info exists gdb,noinferiorio] { + verbose "Skipping test_watchpoint_triggered_in_syscall due to noinferiorio" + return + } + # Run until we get to the first marker function. + set x 0 + set y 0 + set testname "Watch buffer passed to read syscall" + if [runto marker2] then { + gdb_test "watch buf\[0\]" ".*\[Ww\]atchpoint \[0-9\]*: buf\\\[0\\\]" + gdb_test "watch buf\[1\]" ".*\[Ww\]atchpoint \[0-9\]*: buf\\\[1\\\]" + gdb_test "watch buf\[2\]" ".*\[Ww\]atchpoint \[0-9\]*: buf\\\[2\\\]" + gdb_test "watch buf\[3\]" ".*\[Ww\]atchpoint \[0-9\]*: buf\\\[3\\\]" + gdb_test "watch buf\[4\]" ".*\[Ww\]atchpoint \[0-9\]*: buf\\\[4\\\]" + gdb_test "break marker4" ".*Breakpoint.*" + + gdb_test "set doread = 1" "" + + # If we send_gdb "123\n" before gdb has switched the tty, then it goes + # to gdb, not the inferior, and we lose. So that is why we have + # watchpoint.c prompt us, so we can wait for that prompt. + send_gdb "continue\n"; + gdb_expect { + -re "Continuing\\.\r\ntype stuff for buf now:" { + pass "continue to read" + } + default { + fail "continue to read"; + return ; + } + } + + send_gdb "123\n" + gdb_expect { + -re ".*\[Ww\]atchpoint.*buf\\\[0\\\].*Old value = 0.*New value = 49\[^\n\]*\n" { set x [expr $x+1] ; exp_continue } + -re ".*\[Ww\]atchpoint.*buf\\\[1\\\].*Old value = 0.*New value = 50\[^\n\]*\n" { set x [expr $x+1] ; exp_continue } + -re ".*\[Ww\]atchpoint.*buf\\\[2\\\].*Old value = 0.*New value = 51\[^\n\]*\n" { set x [expr $x+1] ; exp_continue } + -re ".*\[Ww\]atchpoint.*buf\\\[3\\\].*Old value = 0.*New value = 10\[^\n\]*\n" { set x [expr $x+1] ; exp_continue } + -re ".*$gdb_prompt $" { pass "sent 123" } + timeout { fail "sent 123 (timeout)" } + } + + # Examine the values in buf to see how many watchpoints we + # should have printed. + send_gdb "print buf\[0\]\n" + gdb_expect { + -re ".*= 49.*$gdb_prompt $" { set y [expr $y+1]; pass "print buf\[0\]"} + -re ".*= 0.*$gdb_prompt $" { pass "print buf\[0\]"} + -re ".*$gdb_prompt $" { fail "print buf\[0\]"} + default { fail "print buf\[0\]"} + } + send_gdb "print buf\[1\]\n" + gdb_expect { + -re ".*= 50.*$gdb_prompt $" { set y [expr $y+1]; pass "print buf\[1\]"} + -re ".*= 0.*$gdb_prompt $" { pass "print buf\[1\]"} + -re ".*$gdb_prompt $" { fail "print buf\[1\]"} + default { fail "print buf\[1\]"} + } + send_gdb "print buf\[2\]\n" + gdb_expect { + -re ".*= 51.*$gdb_prompt $" { set y [expr $y+1]; pass "print buf\[2\]"} + -re ".*= 0.*$gdb_prompt $" { pass "print buf\[2\]"} + -re ".*$gdb_prompt $" { fail "print buf\[2\]"} + default { fail "print buf\[2\]"} + } + send_gdb "print buf\[3\]\n" + gdb_expect { + -re ".*= 10.*$gdb_prompt $" { set y [expr $y+1]; pass "print buf\[3\]"} + -re ".*= 0.*$gdb_prompt $" { pass "print buf\[3\]"} + -re ".*$gdb_prompt $" { fail "print buf\[3\]" } + default { fail "print buf\[3\]" } + } + + # Did we find what we were looking for? If not, flunk it. + if [expr $x==$y] then { pass $testname } else { fail "$testname (only triggered $x watchpoints, expected $y)"} + + # Continue until we hit the finishing marker function. + # Make sure we hit no more watchpoints. + gdb_test "cont" "Continuing.*Breakpoint.*marker4 \\(\\).*" \ + "continue to marker4" + + # Disable everything so we can finish the program at full speed + gdb_test "disable" "" "disable in test_watchpoint_triggered_in_syscall" + + if [target_info exists gdb,noresults] { return } + + gdb_test "cont" "Continuing.*Program exited normally.*" \ + "continue to exit in test_watchpoint_triggered_in_syscall" + } +} + +# Do a simple test of of watching through a pointer when the pointer +# itself changes. Should add some more complicated stuff here. + +proc test_complex_watchpoint {} { + global gdb_prompt + + if [runto marker4] then { + gdb_test "watch ptr1->val" ".*\[Ww\]atchpoint \[0-9\]*: ptr1->val" + gdb_test "break marker5" ".*Breakpoint.*" + + gdb_test "cont" "Continuing.*\[Ww\]atchpoint.*ptr1->val.*Old value = 1.*New value = 2.*" "Test complex watchpoint" + + # Continue until we hit the marker5 function. + # Make sure we hit no more watchpoints. + + gdb_test "cont" "Continuing.*Breakpoint.*marker5 \\(\\).*" \ + "did not trigger wrong watchpoint" +#******************** + # Test watches of things declared locally in a function. + # In particular, test that a watch of stack-based things + # is deleted when the stack-based things go out of scope. + # + gdb_test "disable" "" "disable in test_complex_watchpoint" + gdb_test "break marker6" ".*Breakpoint.*" + gdb_test "cont" "Continuing.*Breakpoint.*marker6 \\(\\).*" \ + "continue to marker6" + gdb_test "break func2" ".*Breakpoint.*" + gdb_test "cont" "Continuing.*func2.*" + + # Test a watch of a single stack-based variable, whose scope + # is the function we're now in. This should auto-delete when + # execution exits the scope of the watchpoint. + # + gdb_test "watch local_a" ".*\[Ww\]atchpoint \[0-9\]*: local_a" "set local watch" + gdb_test "cont" "\[Ww\]atchpoint.*local_a.*" "trigger local watch" + gdb_test "cont" "Continuing.*Watchpoint .* deleted because the program has left the block in.*which its expression is valid.*" "self-delete local watch" + + # after func2 returned, gdb stopped and deleted the watchpoint + # we're now in main, let's get to func2 + gdb_test "cont" "Continuing.*func2.*" + + # We should be in "func2" again now. Test a watch of an + # expression which includes both a stack-based local and + # something whose scope is larger than this invocation + # of "func2". This should also auto-delete. + # + gdb_test "watch local_a + ival5" ".*\[Ww\]atchpoint \[0-9\]*: local_a . ival5" \ + "set partially local watch" + gdb_test "cont" "Continuing.*\[Ww\]atchpoint .*: local_a . ival5.*" \ + "trigger1 partially local watch" + gdb_test "cont" "Continuing.*\[Ww\]atchpoint .*: local_a . ival5.*" \ + "trigger2 partially local watch" + gdb_test "cont" "Continuing.*\[Ww\]atchpoint .* deleted because the program has left the block in.*which its expression is valid.*" \ + "self-delete partially local watch" + + # after func2 returned, gdb stopped and deleted the watchpoint + # we're now in main, let's get to func2 + gdb_test "cont" "Continuing.*func2.*" + + # We should be in "func2" again now. Test a watch of a + # static (non-stack-based) local. Since this has scope + # across any invocations of "func2", it should not auto- + # delete. + # + gdb_test "watch static_b" ".*\[Ww\]atchpoint \[0-9\]*: static_b" \ + "set static local watch" + gdb_test "cont" "Continuing.*\[Ww\]atchpoint .*: static_b.*" \ + "trigger static local watch" + gdb_test "cont" "Continuing.*marker6 \\(\\).*" \ + "continue after trigger static local watch" + gdb_test "info break" ".*watchpoint.*static_b.*" \ + "static local watch did not self-delete" + + # We should be in "recurser" now. Test a watch of a stack- + # based local. Symbols mentioned in a watchpoint are bound + # at watchpoint-creation. Thus, a watch of a stack-based + # local to a recursing function should be bound only to that + # one invocation, and should not trigger for other invocations. + # + gdb_test "tbreak recurser" ".*Breakpoint.*" + gdb_test "cont" "Continuing.*recurser.*" + gdb_test "watch local_x" ".*\[Ww\]atchpoint \[0-9\]*: local_x" \ + "set local watch in recursive call" + gdb_test "cont" "Continuing.*\[Ww\]atchpoint .*: local_x.*New value = 2.*" \ + "trigger local watch in recursive call" + gdb_test "cont" "Continuing.*\[Ww\]atchpoint .* deleted because the program has left the block in.*which its expression is valid.*" \ + "self-delete local watch in recursive call" + + + + +#****************** + # Disable everything so we can finish the program at full speed + gdb_test "disable" "" "disable in test_complex_watchpoint" + + if [target_info exists gdb,noresults] { return } + + + gdb_test "cont" "Continuing.*Program exited normally.*" \ + "continue to exit in test_complex_watchpoint" + } +} + +# Start with a fresh gdb. + +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load $binfile +set timeout 600 +verbose "Timeout now 600 sec.\n" + +if [initialize] then { + + test_simple_watchpoint + + # The IDT/sim monitor only has 8 (!) open files, of which it uses + # 4 (!). So we have to make sure one program exits before + # starting another one. + if [istarget "mips-idt-*"] then { + gdb_exit + gdb_start + gdb_reinitialize_dir $srcdir/$subdir + gdb_load $binfile + initialize + } + + test_disabling_watchpoints + + # See above. + if [istarget "mips-idt-*"] then { + gdb_exit + gdb_start + gdb_reinitialize_dir $srcdir/$subdir + gdb_load $binfile + initialize + } + + if ![target_info exists gdb,cannot_call_functions] { + test_stepping + + # See above. + if [istarget "mips-idt-*"] then { + gdb_exit + gdb_start + gdb_reinitialize_dir $srcdir/$subdir + gdb_load $binfile + initialize + } + } + + # Only enabled for some targets merely because it has not been tested + # elsewhere. + # On sparc-sun-sunos4.1.3, GDB was running all the way to the marker4 + # breakpoint before stopping for the watchpoint. I don't know why. + if {[istarget "hppa*-*-*"]} then { + test_watchpoint_triggered_in_syscall + } + + # See above. + if [istarget "mips-idt-*"] then { + gdb_exit + gdb_start + gdb_reinitialize_dir $srcdir/$subdir + gdb_load $binfile + initialize + } + + # Only enabled for some targets merely because it has not been tested + # elsewhere. + if {[istarget "hppa*-*-*"] || \ + [istarget "sparc*-*-sunos*"] || \ + [istarget "m32r-*-*"]} then { + test_complex_watchpoint +#*************** + } + + # Verify that a user can force GDB to use "slow" watchpoints. + # (This proves rather little on kernels that don't support + # fast watchpoints, but still...) + # + if ![runto_main] then { fail "watch tests suppressed" } + + send_gdb "set can-use-hw-watchpoints 0\n" + gdb_expect { + -re "$gdb_prompt $"\ + {pass "disable fast watches"} + timeout {fail "(timeout) disable fast watches"} + } + send_gdb "show can-use-hw-watchpoints\n" + gdb_expect { + -re "Debugger's willingness to use watchpoint hardware is 0.*$gdb_prompt $"\ + {pass "show disable fast watches"} + -re "$gdb_prompt $"\ + {fail "show disable fast watches"} + timeout {fail "(timeout) show disable fast watches"} + } + send_gdb "watch ival3 if count > 1\n" + gdb_expect { + -re "Watchpoint \[0-9\]*: ival3.*$gdb_prompt $"\ + {pass "set slow conditional watch"} + -re "$gdb_prompt $"\ + {fail "set slow conditional watch"} + timeout {fail "(timeout) set slow conditional watch"} + } + send_gdb "continue\n" + gdb_expect { + -re "Watchpoint \[0-9\]*: ival3.*Old value = 1.*New value = 2.*$gdb_prompt $"\ + {pass "trigger slow conditional watch"} + -re "$gdb_prompt $"\ + {fail "trigger slow conditional watch"} + timeout {fail "(timeout) trigger slow conditional watch"} + } + + # We've explicitly disabled hardware watches. Verify that GDB + # + # + send_gdb "rwatch ival3\n" + gdb_expect { + -re "Expression cannot be implemented with read/access watchpoint..*$gdb_prompt $"\ + {pass "rwatch disallowed when can-set-hw-watchpoints cleared"} + -re "$gdb_prompt $"\ + {fail "rwatch disallowed when can-set-hw-watchpoints cleared"} + timeout {fail "(timeout) rwatch disallowed when can-use-hw-watchpoints cleared"} + } + + # Read- and access watchpoints are unsupported on HP-UX. Verify + # that GDB gracefully responds to requests to create them. + # + if [istarget "hppa*-*-hpux*"] then { + send_gdb "set can-use-hw-watchpoints 1\n" + gdb_expect { + -re "$gdb_prompt $"\ + {pass "enable fast watches"} + timeout {fail "(timeout) enable fast watches"} + } + send_gdb "rwatch ival3\n" + gdb_expect { + -re "Target does not have this type of hardware watchpoint support.*$gdb_prompt $"\ + {pass "read watches disallowed"} + -re "$gdb_prompt $"\ + {fail "read watches disallowed"} + timeout {fail "(timeout) read watches disallowed"} + } + + send_gdb "awatch ival3\n" + gdb_expect { + -re "Target does not have this type of hardware watchpoint support.*$gdb_prompt $"\ + {pass "access watches disallowed"} + -re "$gdb_prompt $"\ + {fail "access watches disallowed"} + timeout {fail "(timeout) access watches disallowed"} + } + +#*************** + } +} diff --git a/gdb/testsuite/gdb.hp/xdb.c b/gdb/testsuite/gdb.hp/xdb.c new file mode 100644 index 00000000000..e3e3fc23e9f --- /dev/null +++ b/gdb/testsuite/gdb.hp/xdb.c @@ -0,0 +1,20 @@ +#include <stdio.h> + +int callee( x ) +int x; +{ + int y = x * x; + return (y - 2); +} + +main() +{ + int i; + for (i = 1; i < 10; i++) + { + printf( "%d ", callee( i )); + + } + printf( " Goodbye!\n" ); + +} diff --git a/gdb/testsuite/gdb.hp/xdb0.c b/gdb/testsuite/gdb.hp/xdb0.c new file mode 100644 index 00000000000..fa5c76f7418 --- /dev/null +++ b/gdb/testsuite/gdb.hp/xdb0.c @@ -0,0 +1,42 @@ +#include "xdb0.h" + +main () +{ + int x; +#ifdef usestubs + set_debug_traps(); + breakpoint(); +#endif + x = 0; + foo (x++); + foo (x++); + foo (x++); + foo (x++); + foo (x++); + foo (x++); + foo (x++); + foo (x++); + foo (x++); + foo (x++); + foo (x++); + foo (x++); + foo (x++); + foo (x++); + foo (x++); + foo (x++); + foo (x++); + foo (x++); + foo (x++); + foo (x++); + foo (x++); + foo (x++); + foo (x++); + foo (x++); + foo (x++); +} + +static void +unused () +{ + /* Not used for anything */ +} diff --git a/gdb/testsuite/gdb.hp/xdb0.h b/gdb/testsuite/gdb.hp/xdb0.h new file mode 100644 index 00000000000..c4d337c6770 --- /dev/null +++ b/gdb/testsuite/gdb.hp/xdb0.h @@ -0,0 +1,36 @@ +/* An include file that actually causes code to be generated in the + including file. This is known to cause problems on some systems. */ + +static void +foo (x) +int x; +{ + bar (x++); + bar (x++); + bar (x++); + bar (x++); + bar (x++); + bar (x++); + bar (x++); + bar (x++); + bar (x++); + bar (x++); + bar (x++); + bar (x++); + bar (x++); + bar (x++); + bar (x++); + bar (x++); + bar (x++); + bar (x++); + bar (x++); + bar (x++); + bar (x++); + bar (x++); + bar (x++); + bar (x++); + bar (x++); + bar (x++); + bar (x++); + bar (x++); +} diff --git a/gdb/testsuite/gdb.hp/xdb1.c b/gdb/testsuite/gdb.hp/xdb1.c new file mode 100644 index 00000000000..51632b94d07 --- /dev/null +++ b/gdb/testsuite/gdb.hp/xdb1.c @@ -0,0 +1,33 @@ +void +bar (x) +int x; +{ + printf ("%d\n", x); + + long_line (); +} + +static void +unused () +{ + /* Not used for anything */ +} + + +/* This routine has a very long line that will break searching in older + versions of GDB. */ + +long_line () +{ + oof (67); + + oof (6789); + + oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* 5 */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* 10 */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* 15 */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* 20 */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* 25 */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* 30 */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* 35 */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* 40 */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* 45 */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* 50 */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* 55 */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* 60 */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* 65 */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (12); /* */ oof (12); oof (12); oof (12); oof (12); oof (12); oof (1234); /* 70 */ +} + +oof (n) + int n; +{ + return n + 1; +} diff --git a/gdb/testsuite/gdb.hp/xdb1.exp b/gdb/testsuite/gdb.hp/xdb1.exp new file mode 100644 index 00000000000..88ab2fc5864 --- /dev/null +++ b/gdb/testsuite/gdb.hp/xdb1.exp @@ -0,0 +1,77 @@ +# Copyright (C) 1992, 1994, 1995 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 2 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +# Please email any bugs, comments, and/or additions to this file to: +# bug-gdb@prep.ai.mit.edu + +# This file was written by Fred Fish. (fnf@cygnus.com) + +if $tracelevel then { + strace $tracelevel + } + + +global usestubs + +# +# test running programs +# +set prms_id 0 +set bug_id 0 + +set testfile "xdb" +set srcfile ${testfile}.c +set binfile ${objdir}/${subdir}/${testfile} +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } { + gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail." +} + +if [get_compiler_info ${binfile}] { + return -1; +} +if {[skip_hp_tests $gcc_compiled]} then { continue } + +global GDBFLAGS +set saved_gdbflags $GDBFLAGS + +set GDBFLAGS "$GDBFLAGS --xdb" + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +gdb_test "set pagination off" "" +gdb_test "show pagination" "State of pagination is off." +gdb_test "set pagination on" "" +gdb_test "show pagination" "State of pagination is on." + +gdb_test "txbreak callee" "Breakpoint.*at.*" +gdb_test "info break" "Num.*Type.*Disp.*Enb.*Address.*What\r\n.*breakpoint.*del.*y.*" + +gdb_test "xbreak callee" "Breakpoint.*at.*.*" +gdb_test "info break" "Num.*Type.*Disp.*Enb.*Address.*What\r\n.*breakpoint.*keep.*y.*" + +gdb_exit +set GDBFLAGS $saved_gdbflags +return 0 + + + + + + + diff --git a/gdb/testsuite/gdb.hp/xdb2.exp b/gdb/testsuite/gdb.hp/xdb2.exp new file mode 100644 index 00000000000..4cc7b341e09 --- /dev/null +++ b/gdb/testsuite/gdb.hp/xdb2.exp @@ -0,0 +1,104 @@ +# Copyright (C) 1992, 1994, 1995 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 2 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +# Please email any bugs, comments, and/or additions to this file to: +# bug-gdb@prep.ai.mit.edu + +# This file was written by Fred Fish. (fnf@cygnus.com) + +if $tracelevel then { + strace $tracelevel + } + +global message + +# +# test running programs +# +set prms_id 0 +set bug_id 0 + +set testfile "xdb" +set binfile ${objdir}/${subdir}/${testfile} + +if { [gdb_compile "${srcdir}/${subdir}/xdb0.c" "${binfile}0.o" object {debug}] != "" } { + perror "Couldn't compile ${testfile}0.c to object" + return -1 +} + +if { [gdb_compile "${srcdir}/${subdir}/xdb1.c" "${binfile}1.o" object {debug}] != "" } { + perror "Couldn't compile ${testfile}1.c to object" + return -1 +} + +if { [gdb_compile "${binfile}0.o ${binfile}1.o" ${binfile} executable {debug}] != "" } { + perror "Couldn't link ${testfile}." + return -1 +} + + +if [get_compiler_info ${binfile}] { + return -1; +} +if {[skip_hp_tests $gcc_compiled]} then { continue } + + +global GDBFLAGS +set saved_gdbflags $GDBFLAGS +set GDBFLAGS "$GDBFLAGS --xdb" + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} +gdb_test "break main" "" +gdb_test "run" "" +gdb_test "go +2" "Breakpoint.*at.*file.*xdb0\.c, line 12\.\r\nContinuing at.*\r\nmain \\(\\) at.*xdb0\.c:12\r\n12\[ \t\]+foo \\(x\\+\\+\\);" +gdb_test "go -2" "Note: breakpoint.*also set at pc.*\.\r\nBreakpoint.*at.*file.*xdb0\.c, line 10\.\r\nContinuing at.*\.\r\n\r\nBreakpoint.*, main \\(\\) at.*xdb0\.c:10.*" +gdb_test "go 16" "Breakpoint.*at.*file.*xdb0\.c, line 16\.\r\nContinuing at.*\.\r\nmain \\(\\) at.*xdb0\.c:16\r\n16\[ \t\]+foo \\(x\\+\\+\\);" + +send_gdb "go bar\n" + gdb_expect { + -re ".*Line 5 is not in .main.. Jump anyway.*y or n. $" { + send_gdb "y\n" + gdb_expect { + -re "$gdb_prompt $"\ + {pass "go bar"} + timeout {fail "(timeout) go bar"} + } + } + -re "Continuing at.*\.\r\nbar \\(x=0\\) at.*xdb1\.c:5" {} + timeout { perror "(timeout) go bar" ; return } + } + +# Verify that GDB responds gracefully to a "go" command without +# an argument. +# +gdb_test "go" "Usage: go <location>" + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +gdb_test "break bar" "" +gdb_test "run" "" +gdb_test "backtrace full" ".*bar \\(x=0\\) at.*xdb1\.c:5\r\nNo locals\.\r\n.1.* in foo \\(x=1\\) at.*xdb0\.h:8\r\nNo locals\.\r\n.2.* in main \\(\\) at.*xdb0\.c:11\r\n.*x = 1" +gdb_test "bt 1 full" ".*bar \\(x=0\\) at.*xdb1\.c:5\r\nNo locals\.\r\n\\(More stack frames follow\.\.\.\\)" +gdb_test "bt full 2" ".*bar \\(x=0\\) at.*xdb1\.c:5\r\nNo locals\.\r\n.1.* in foo \\(x=1\\) at.*xdb0\.h:8\r\nNo locals\.\r\n\\(More stack frames follow\.\.\.\\)" + +set GDBFLAGS $saved_gdbflags +return 0 diff --git a/gdb/testsuite/gdb.hp/xdb3.exp b/gdb/testsuite/gdb.hp/xdb3.exp new file mode 100644 index 00000000000..cf569e9511c --- /dev/null +++ b/gdb/testsuite/gdb.hp/xdb3.exp @@ -0,0 +1,307 @@ +# Copyright (C) 1998 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 2 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +# Please email any bugs, comments, and/or additions to this file to: +# bug-gdb@prep.ai.mit.edu + + +if $tracelevel then { + strace $tracelevel +} + + +set testfile1 "average" +set testfile2 "sum" +set testfile "xdb-test" +set binfile1 ${objdir}/${subdir}/${testfile1} +set binfile2 ${objdir}/${subdir}/${testfile2} +set binfile ${objdir}/${subdir}/${testfile} + +if { [gdb_compile "${srcdir}/${subdir}/average.c" "${binfile1}.o" object {debug}] != "" } { + gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail." +} + +if { [gdb_compile "${srcdir}/${subdir}/sum.c" "${binfile2}.o" object {debug}] != "" } { + gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail." +} + +if { [gdb_compile "${binfile1}.o ${binfile2}.o" ${binfile} executable {debug}] != "" } { + gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail." +} + +if [get_compiler_info ${binfile}] { + return -1; +} +if {[skip_hp_tests $gcc_compiled]} then { continue } + + +proc xdb_reinitialize_dir { subdir } { + global gdb_prompt + + send_gdb "D\n" + gdb_expect { + -re "Reinitialize source path to empty.*y or n. " { + send_gdb "y\n" + gdb_expect { + -re "Source directories searched.*$gdb_prompt $" { + send_gdb "D $subdir\n" + gdb_expect { + -re "Source directories searched.*$gdb_prompt $" { + verbose "Dir set to $subdir" + } + -re ".*$gdb_prompt $" { + perror "Dir \"$subdir\" failed." + } + } + } + -re ".*$gdb_prompt $" { + perror "Dir \"$subdir\" failed." + } + } + } + -re ".*$gdb_prompt $" { + perror "Dir \"$subdir\" failed." + } + } +} + +# +#test_search +# +proc test_search { } { + gdb_test "set listsize 4" "" + gdb_test "list average.c:1" "1\[ \t\]+/. This is a sample .*" + gdb_test "/ print_average" "10\[ \t\]+void print_average\\(int list.*" + gdb_test "/ print_average" "12\[ \t\]+void print_average\\(list, low, high\\)" + gdb_test "/ print_average" "35\[ \t\]+print_average \\(my_list, first, last\\);" + gdb_test "? print_average" "12\[ \t\]+void print_average\\(list, low, high\\)" + gdb_test "? sum" "Expression not found" +} + +# +#test_viewing_loc +# +proc test_viewing_loc { } { + gdb_test "L" "No stack." + gdb_test "break main" "" + gdb_test "R" "" + gdb_test "L" "#0\[ \t\]+main \\(\\) at.*average.c:31\r\n31\[ \t\]+int first = 0;" +} + +# +#test_dir_list +# +proc test_dir_list { } { + gdb_test "ld" "Source directories searched: .*" +} + +# +#test_list_sources +# +proc test_list_sources { } { + gdb_test "lf" "Source files for which symbols have been read in:.*average\\.c,.*Source files for which symbols will be read in on demand:.*sum\\.c" +} + +# +#test_vlist +# +proc test_vlist { } { + gdb_test "v main" "27\[ \t\]+main \\(\\)\r\n28\[ \t\]+#endif\r\n29\[ \t\]+.\r\n30\[ \t\]+char c;" +} + +# +#test_va +# +proc test_va { } { + gdb_test "va main" "Dump of assembler code for function main:.*End of assembler dump\." +} + +# +#test_list_globals +# +proc test_list_globals { } { + gdb_test "lg" "All defined variables:\r\n\r\nFile globals:.*" +# gdb_test "lg" "All defined variables:\r\n\r\nFile globals:\r\nchar __buffer.512.;\r\nint __d_eh_catch_catch;\r\nint __d_eh_catch_throw;.*" +} + +# +#test_list_registers +# +proc test_list_registers { } { + gdb_test "lr" "\[ \t\]+flags:.*r18:.*pcsqt:.*ccr:.*\r\n\[ \t\]+r1:.*r19:.*eiem:.*cr12:.*" + gdb_test "lr r1" "r1 .*" +} + +# +#test_backtrace +# +proc test_backtrace { } { + gdb_test "t" "#0 main \\(\\) at.*average.c:31" + gdb_test "T" "#0 main \\(\\) at.*average.c:31\r\n\[ \t\]+c = 0.*\r\n\[ \t\]+first = 0\r\n\[ \t\]+last = 0" + + gdb_test "break sum" "" + gdb_test "cont" "" + + gdb_test "t" "#0 sum \\(list=0x.*, low=0, high=9\\) at.*sum\.c:11\r\n#1 0x.* in print_average \\(list=0x.*, low=0, high=9\\) at.*average\.c:17\r\n#2 0x.* in main \\(\\) at.*average\.c:35" + gdb_test "t 1" "#0 sum \\(list=0x.*, low=0, high=9\\) at.*sum\.c:11\r\n\\(More stack frames follow\.\.\.\\)" + gdb_test "T" "#0 sum \\(list=0x.*, low=0, high=9\\) at.*sum\.c:11\r\n\[ \t\]+i = 0\r\n\[ \t\]+s = 0\r\n#1 0x.* in print_average \\(list=0x.*, low=0, high=9\\) at.*average\.c:17\r\n\[ \t\]+total = 0\r\n\[ \t\]+num_elements = 0\r\n\[ \t\]+average = 0\r\n#2 0x.* in main \\(\\) at.*average\.c:35\r\n\[ \t\]+c = 0 '.000'\r\n\[ \t\]+first = 0\r\n\[ \t\]+last = 9" + gdb_test "T 1" "#0 sum \\(list=0x.*, low=0, high=9\\) at.*sum\.c:11\r\n\[ \t\]+i = 0\r\n\[ \t\]+s = 0\r\n\\(More stack frames follow\.\.\.\\)" + + gdb_test "V" "#0 sum \\(list=0x.*, low=0, high=9\\) at.*sum\.c:11\r\n\\11\[ \t\]+int i, s = 0;" + gdb_test "V 1" "#1 0x.* in print_average \\(list=0x.*, low=0, high=9\\) at.*average\.c:17\r\n17\[ \t\]+total = sum\\(list, low, high\\);" +} + +# +# test_go +# +proc test_go { } { + gdb_test "break main" "" + gdb_test "R" "" + + gdb_test "g +1" "Breakpoint.*at 0x.*: file.*average\.c, line 32\.\r\nContinuing at 0x.*\.\r\nmain \\(\\) at.*average\.c:32\r\n32\[ \t\]+int last = num-1;" + gdb_test "g 35" "Breakpoint.*at 0x.*: file.*average\.c, line 35\.\r\nContinuing at 0x.*\.\r\nmain \\(\\) at.*average\.c:35\r\n35\[ \t\]+print_average \\(my_list, first, last\\);" + +} + +# +#test_breakpoints +# +proc test_breakpoints { } { + global gdb_prompt + + gdb_test "sb" "" + gdb_test "lb" "Num.*Type.*Disp.*Enb.*Address.*What\r\n1\[ \r\]+breakpoint\[ \r\]+keep n.*in main at.*average\.c:31.*" + gdb_test "ab" "" + gdb_test "lb" "Num.*Type.*Disp.*Enb.*Address.*What\r\n1\[ \r\]+breakpoint\[ \r\]+keep y.*in main at.*average\.c:31.*" + gdb_test "ba sum" "Breakpoint.*at.*: file.*sum\.c, line 11\." + gdb_test "cont" "" + gdb_test "bx" "Breakpoint.*at.*: file.*sum.c, line 15\." + gdb_test "bx if (1)" "Breakpoint.*at.*: file.*sum.c, line 15\." + gdb_test "bx 1" "Breakpoint.*at.*: file.*average.c, line 22\." + gdb_test "bx 1 if (1)" "Breakpoint.*at.*: file.*average.c, line 22\." + gdb_test "bc 1 2" "Will ignore next 2 crossings of breakpoint 1\." + gdb_test "lb 1" "Num.*Type.*Disp.*Enb.*Address.*What\r\n1\[ \r\]+breakpoint\[ \r\]+keep y.*in main at.*average\.c:31\r\n.*breakpoint already hit 1 time\r\n.*ignore next 2 hits.*" + + send_gdb "db\n" + gdb_expect { + -re "Delete all breakpoints.*y or n. $" { + send_gdb "y\n" + exp_continue + } + -re "y\r\n$gdb_prompt $" {} + -re ".*$gdb_prompt $" { # This happens if there were no breakpoints + } + timeout { perror "Delete all breakpoints (timeout)" ; return } + } + send_gdb "lb\n" + gdb_expect { + -re "No breakpoints or watchpoints..*$gdb_prompt $" {} + -re ".*$gdb_prompt $" { perror "breakpoints not deleted" ; return } + timeout { perror "info breakpoints (timeout)" ; return } + } +gdb_test "xbreak" "Breakpoint.*at.*file.*sum.c, line 15." +gdb_test "xbreak print_average" "Breakpoint.*at.*file.*average.c, line 22." +gdb_test "xbreak if (1)" "Note: breakpoint.*also set at pc.*Breakpoint.*at.*file.*sum.c, line 15." +gdb_test "xbreak print_average if (1)" "Note: breakpoint.*also set at pc.*Breakpoint.*at.*file.*average.c, line 22." + + send_gdb "lb\n" + gdb_expect { + -re "Num Type Disp Enb Address What.*breakpoint keep y.*in sum at.*sum.c:15.*breakpoint keep y.*in print_average at.*average.c:22.*breakpoint keep y.*in sum at.*sum.c:15.*stop only if 1.*breakpoint keep y.*in print_average at.*average.c:22.*stop only if 1.*$gdb_prompt $" {pass "lb on xbreaks"} + -re ".*$gdb_prompt $" { fail "breakpoints not deleted"} + timeout { fail "info breakpoints (timeout)" } + } + +} + +# +# test_signals +# +proc test_signals { } { + gdb_test "handle SIGTERM nostop noprint" "" + gdb_test "z SIGTERM s" "Signal.*Stop.*Print.*Pass to program.*Description\r\nSIGTERM.*Yes.*Yes.*Yes.*Terminated" + gdb_test "z SIGTERM r" "Signal.*Stop.*Print.*Pass to program.*Description\r\nSIGTERM.*No.*No.*Yes.*Terminated" + gdb_test "z SIGTERM i" "Signal.*Stop.*Print.*Pass to program.*Description\r\nSIGTERM.*No.*No.*No.*Terminated" + gdb_test "z SIGTERM r" "Signal.*Stop.*Print.*Pass to program.*Description\r\nSIGTERM.*No.*Yes.*No.*Terminated" + gdb_test "z SIGTERM Q" "Signal.*Stop.*Print.*Pass to program.*Description\r\nSIGTERM.*No.*No.*No.*Terminated" + gdb_test "lz" "Signal.*Stop.*Print.*Pass to program.*Description\r\n\r\nSIGHUP.*Yes.*" +} + + + +# Start with a fresh gdb. +global GDBFLAGS +set saved_gdbflags $GDBFLAGS + +set GDBFLAGS "$GDBFLAGS --xdb" + +gdb_exit +gdb_start + +xdb_reinitialize_dir $srcdir/$subdir + +gdb_load ${binfile} +send_gdb "set width 0\n" +gdb_expect -re "$gdb_prompt $" +test_search +test_viewing_loc +test_dir_list +test_list_sources +test_vlist +test_va +gdb_test "l" "No arguments.\r\nc = 0.*\r\nfirst = 0\r\nlast = 0" +#test_list_globals +test_list_registers +test_backtrace + +# Start with a fresh gdb. + +gdb_exit +gdb_start +xdb_reinitialize_dir $srcdir/$subdir + +gdb_load ${binfile} +send_gdb "set width 0\n" +gdb_expect -re "$gdb_prompt $" +test_go + + +gdb_exit +gdb_start +xdb_reinitialize_dir $srcdir/$subdir + +gdb_load ${binfile} +send_gdb "set width 0\n" +gdb_expect -re "$gdb_prompt $" +gdb_test "break main" "" +gdb_test "R" "" +gdb_test "S" "32\[ \t\]+int last = num-1;" +test_breakpoints +test_signals +gdb_test "sm" "" +gdb_test "info set" ".*pagination: State of pagination is off.*" +gdb_test "am" "" +gdb_test "info set" ".*pagination: State of pagination is on.*" +gdb_exit + +set GDBFLAGS $saved_gdbflags + +return 0 + + + + + + |