diff options
author | Jason Molenda <jmolenda@apple.com> | 1999-06-28 23:04:32 +0000 |
---|---|---|
committer | Jason Molenda <jmolenda@apple.com> | 1999-06-28 23:04:32 +0000 |
commit | 74cf13956febb1f6c8e0f5d5f48814953d41dd28 (patch) | |
tree | f06240a34afca06791450a91c8aac297abda27df /gdb | |
parent | 9cd2c67bacb9aaa7e82457e68e1a6087c8bde928 (diff) | |
download | gdb-74cf13956febb1f6c8e0f5d5f48814953d41dd28.zip gdb-74cf13956febb1f6c8e0f5d5f48814953d41dd28.tar.gz gdb-74cf13956febb1f6c8e0f5d5f48814953d41dd28.tar.bz2 |
import gdb-1999-06-28 snapshot
Diffstat (limited to 'gdb')
-rw-r--r-- | gdb/testsuite/gdb.base/attach.c | 20 | ||||
-rw-r--r-- | gdb/testsuite/gdb.base/attach.exp | 437 | ||||
-rw-r--r-- | gdb/testsuite/gdb.base/attach2.c | 24 | ||||
-rw-r--r-- | gdb/testsuite/gdb.base/average.c | 46 | ||||
-rw-r--r-- | gdb/testsuite/gdb.base/dbx.exp | 319 | ||||
-rw-r--r-- | gdb/testsuite/gdb.base/execd-prog.c | 34 | ||||
-rw-r--r-- | gdb/testsuite/gdb.base/foll-exec.c | 43 | ||||
-rw-r--r-- | gdb/testsuite/gdb.base/foll-exec.exp | 396 | ||||
-rw-r--r-- | gdb/testsuite/gdb.base/foll-fork.c | 34 | ||||
-rw-r--r-- | gdb/testsuite/gdb.base/foll-fork.exp | 363 | ||||
-rw-r--r-- | gdb/testsuite/gdb.base/foll-vfork.c | 20 | ||||
-rw-r--r-- | gdb/testsuite/gdb.base/foll-vfork.exp | 365 | ||||
-rw-r--r-- | gdb/testsuite/gdb.base/page.exp | 40 | ||||
-rw-r--r-- | gdb/testsuite/gdb.base/structs.c | 211 | ||||
-rw-r--r-- | gdb/testsuite/gdb.base/structs.exp | 148 | ||||
-rw-r--r-- | gdb/testsuite/gdb.base/sum.c | 15 | ||||
-rw-r--r-- | gdb/testsuite/gdb.base/vforked-prog.c | 11 | ||||
-rw-r--r-- | gdb/testsuite/gdb.chill/xstruct-grt.ch | 12 | ||||
-rw-r--r-- | gdb/testsuite/gdb.chill/xstruct.ch | 16 | ||||
-rw-r--r-- | gdb/testsuite/gdb.chill/xstruct.exp | 66 |
20 files changed, 2620 insertions, 0 deletions
diff --git a/gdb/testsuite/gdb.base/attach.c b/gdb/testsuite/gdb.base/attach.c new file mode 100644 index 0000000..0041b47 --- /dev/null +++ b/gdb/testsuite/gdb.base/attach.c @@ -0,0 +1,20 @@ +/* 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; + +int main () +{ + int local_i = 0; + + while (! should_exit) + { + local_i++; + } + return 0; +} diff --git a/gdb/testsuite/gdb.base/attach.exp b/gdb/testsuite/gdb.base/attach.exp new file mode 100644 index 0000000..b86838b --- /dev/null +++ b/gdb/testsuite/gdb.base/attach.exp @@ -0,0 +1,437 @@ +# 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 + + +if { ![istarget "hppa*-*-hpux*"] } { + #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." +} + +# Because we can't attach over nfs, copy binfile to /tmp/${binfile}.${pid} +# and replace binfile with a symbolic link + + set pid [pid] + exec /bin/cp -f ${binfile} /tmp/attach1.${pid} + exec rm -f ${binfile} + set binfile /tmp/attach1.${pid} +# exec ln -s /tmp/attach1.${pid} ${binfile} + +# 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." +} + +# Because we can't attach over nfs, copy binfile2 to /tmp/${binfile2}.${pid} +# and replace binfile2 with a symbolic link + + set pid [pid] + exec cp -f ${binfile2} /tmp/attach2.${pid} + exec rm -f ${binfile2} + set binfile2 /tmp/attach2.${pid} +# exec ln -s /tmp/attach2.${pid} ${binfile2} + + +if [get_compiler_info ${binfile}] { + return -1 +} + +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 failed.*Hint.*$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 15 + send_gdb "file\n" + gdb_expect { + -re ".*gdb internal error.*$" { + fail "Internal error, prob. Memory corruption" + } + -re "No executable 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. + # + 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 executable 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 + # + gdb_test "file $binfile2" ".*" "force switch to gdb64, if necessary" + 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 + # + 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 + +# this seems not necessary. - guo +# +# # Since we have moved the executable to /tmp, it will be hard for gdb +# # to find the object file/executable to read the symbols. This is +# # a known limitation. We try and get the name of the executable the +# # process is running from a variety of methods, but none is foolproof. +# # Using "dir" will get us the symbols. +# +# gdb_test "dir ./gdb.base" ".*" "set up directory before attach" +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 "*-*-*" +} + +# Cleanup the files placed in /tmp and the symlinks + remote_exec build "rm -f ${binfile} ${binfile2} /tmp/attach1.${pid} /tmp/attach2.${pid}" + +return 0 diff --git a/gdb/testsuite/gdb.base/attach2.c b/gdb/testsuite/gdb.base/attach2.c new file mode 100644 index 0000000..a78037e --- /dev/null +++ b/gdb/testsuite/gdb.base/attach2.c @@ -0,0 +1,24 @@ +/* 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> +#include <unistd.h> + +int should_exit = 0; + +int 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.base/average.c b/gdb/testsuite/gdb.base/average.c new file mode 100644 index 0000000..e1695ce --- /dev/null +++ b/gdb/testsuite/gdb.base/average.c @@ -0,0 +1,46 @@ +/* This is a sample program for the HP WDB debugger. */ + +#include <stdio.h> +#include <stdlib.h> + +#ifdef PROTOTYPES +extern int sum(int *, int, int); +#else +extern int sum(); +#endif + +#define num 10 + +static int my_list[num] = {3,4,2,0,2,1,8,3,6,7}; + +#ifdef PROTOTYPES +void print_average(int *list, int low, int high) +#else +void print_average(list, low, high) +int *list, low, high; +#endif + { + int total = 0, num_elements = 0, average = 0; + 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 PROTOTYPES +int main(void) +#else +main () +#endif +{ + char c; + int first = 0, last = 0; + last = num-1; + + /* Try two test cases. */ + print_average (my_list, first, last); + print_average (my_list, first, last - 3); + + exit(0); +} diff --git a/gdb/testsuite/gdb.base/dbx.exp b/gdb/testsuite/gdb.base/dbx.exp new file mode 100644 index 0000000..05f3fe4 --- /dev/null +++ b/gdb/testsuite/gdb.base/dbx.exp @@ -0,0 +1,319 @@ +# 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." +} + +# +# start gdb -- start gdb running, default procedure +# +proc dbx_gdb_start { } { + global verbose + global GDB + global GDBFLAGS + global prompt + global spawn_id + global timeout + verbose "Spawning $GDB -nw $GDBFLAGS" + + if { [which $GDB] == 0 } then { + perror "$GDB does not exist." + exit 1 + } + + set oldtimeout $timeout + set timeout [expr "$timeout + 60"] + eval "spawn $GDB -nw -dbx $GDBFLAGS" + gdb_expect { + -re ".*\r\n$gdb_prompt $" { + verbose "GDB initialized." + } + -re "$prompt $" { + perror "GDB never initialized." + return -1 + } + timeout { + perror "(timeout) GDB never initialized." + return -1 + } + } + set timeout $oldtimeout + # force the height to "unlimited", so no pagers get used + send_gdb "set height 0\n" + gdb_expect { + -re ".*$prompt $" { + verbose "Setting height to 0." 2 + } + timeout { + warning "Couldn't set the height to 0." + } + } + # force the width to "unlimited", so no wraparound occurs + send_gdb "set width 0\n" + gdb_expect { + -re ".*$prompt $" { + verbose "Setting width to 0." 2 + } + timeout { + warning "Couldn't set the width to 0." + } + } +} + + +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"). +# +# CM: Renamed the procedure so it does not override the orginal file name. +# Having the test suite change behavior depending on the tests run makes +# it extremely difficult to reproduce errors. I've also added a +# "dbx_gdb_load" procedure. This and only this test will call these +# procedures now. I also added an "expect" to the "send exec-file" line. +# The "expect" waits for a prompt to appear. Otherwise, if the tests run +# too quickly, the caller could send another command before the prompt +# of this command returns, causing the test to get out of sync and fail +# seemingly randomly or only on a loaded system. +# +proc dbx_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 "Detected 64-bit symbol file.\r\nInvoking.*gdb64.*$gdb_prompt $" { + verbose "\t\tLoaded $arg into the $GDB" + send_gdb "exec-file $arg\n" + gdb_expect { + -re ".*$gdb_prompt $" { + verbose "\t\tLoaded $arg with new symbol table into $GDB" + return 0 + } + timeout { + perror "(timeout) Couldn't load $arg" + return -1 + } + } + return 0 + } + -re "Reading symbols from.*done.*$gdb_prompt $" { + verbose "\t\tLoaded $arg into the $GDB" + send_gdb "exec-file $arg\n" + gdb_expect { + -re ".*$gdb_prompt $" { + verbose "\t\tLoaded $arg with new symbol table into $GDB" + return 0 + } + timeout { + perror "(timeout) Couldn't load $arg" + return -1 + } + } + 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 + } + } +} + +proc dbx_gdb_load { arg } { + global verbose + global loadpath + global loadfile + global GDB + global prompt + upvar timeout timeout + + return [dbx_gdb_file_cmd $arg] +} + +# +#test_breakpoints +# +proc test_breakpoints { } { + gdb_test "stop in main" "Breakpoint.*at.*: file.*average\.c, line 38\." + gdb_test "status" "Num.*Type.*Disp.*Enb.*Address.*What\r\n1\[ \r\]+breakpoint\[ \r\]+keep y.*in main at.*average\.c:38.*" + gdb_test "stop at 43" "Breakpoint.*at.*: file.*average\.c, line 43.*" + gdb_test "stop in 43" "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:24\r\n24\[ \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 +dbx_gdb_load ${binfile} + +test_breakpoints +test_assign +test_whereis +gdb_test "file average.c:1" "1\[ \t\]+/. This is a sample program.*" +test_func + +#exit and cleanup +gdb_exit + +set GDBFLAGS $saved_gdbflags +return 0 diff --git a/gdb/testsuite/gdb.base/execd-prog.c b/gdb/testsuite/gdb.base/execd-prog.c new file mode 100644 index 0000000..5469f65 --- /dev/null +++ b/gdb/testsuite/gdb.base/execd-prog.c @@ -0,0 +1,34 @@ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +/* There is a global_i in foll-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; + +#ifdef PROTOTYPES +int main (int argc, char **argv) +#else +main (argc, argv) + int argc; + char * argv[]; +#endif +{ + /* There is a local_j in foll-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-prog...\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.base/foll-exec.c b/gdb/testsuite/gdb.base/foll-exec.c new file mode 100644 index 0000000..1b76090 --- /dev/null +++ b/gdb/testsuite/gdb.base/foll-exec.c @@ -0,0 +1,43 @@ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> + + +int global_i = 100; + +#ifdef PROTOTYPES +int main (void) +#else +main () +#endif +{ + int local_j = global_i+1; + int local_k = local_j+1; + + printf ("foll-exec is about to execlp(execd-prog)...\n"); + + execlp ("gdb.base/execd-prog", + "gdb.base/execd-prog", + "execlp arg1 from foll-exec", + (char *)0); + + printf ("foll-exec is about to execl(execd-prog)...\n"); + + execl ("gdb.base/execd-prog", + "gdb.base/execd-prog", + "execl arg1 from foll-exec", + "execl arg2 from foll-exec", + (char *)0); + + { + static char * argv[] = { + (char *)"gdb.base/execd-prog", + (char *)"execv arg1 from foll-exec", + (char *)0}; + + printf ("foll-exec is about to execv(execd-prog)...\n"); + + execv ("gdb.base/execd-prog", argv); + } +} diff --git a/gdb/testsuite/gdb.base/foll-exec.exp b/gdb/testsuite/gdb.base/foll-exec.exp new file mode 100644 index 0000000..4342d5f --- /dev/null +++ b/gdb/testsuite/gdb.base/foll-exec.exp @@ -0,0 +1,396 @@ +# 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 + +set testfile "foll-exec" +set testfile2 "execd-prog" +set srcfile ${testfile}.c +set srcfile2 ${testfile2}.c +set binfile ${objdir}/${subdir}/${testfile} +set binfile2 ${objdir}/${subdir}/${testfile2} + +# build the first test case +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 { [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 { + continue +} + +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 "20.*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}:23.*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 "26.*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"} + } + + # DTS CLLbs16760 + # PA64 doesn't know about $START$ in dld.sl at this point. It should. + # - Michael Coulter + setup_xfail hppa2.0w-hp-hpux* + 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"} + } + + # DTS CLLbs16760 + # test gets out of sync if previous test fails. + gdb_test "bt" ".*" "sync up after possible failure 1" + gdb_test "bt" "#0.*" "sync up after possible failure 2" + + # 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}:23.*$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 27\n" + gdb_expect { + -re "Breakpoint .*file .*${srcfile}, line 27.*$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 27\n" + gdb_expect { + -re "main.* at .*${srcfile}:27.*$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}:23.*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 "26.*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 41\n" + gdb_expect { + -re "Breakpoint .*file .*${srcfile}, line 41.*$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 41\n" + gdb_expect { + -re "main.* at .*${srcfile}:41.*$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}:23.*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 "26.*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} (5th 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}:23.*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.base/foll-fork.c b/gdb/testsuite/gdb.base/foll-fork.c new file mode 100644 index 0000000..841258f --- /dev/null +++ b/gdb/testsuite/gdb.base/foll-fork.c @@ -0,0 +1,34 @@ +#include <stdio.h> +#include <unistd.h> + +#ifdef PROTOTYPES +void callee (int i) +#else +void callee (i) + int i; +#endif +{ + printf("callee: %d\n", i); +} + +#ifdef PROTOTYPES +int main (void) +#else +main () +#endif +{ + 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.base/foll-fork.exp b/gdb/testsuite/gdb.base/foll-fork.exp new file mode 100644 index 0000000..23afedd --- /dev/null +++ b/gdb/testsuite/gdb.base/foll-fork.exp @@ -0,0 +1,363 @@ +# 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 + +set testfile "foll-fork" +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." +} + + + +# Until "set follow-fork-mode" and "catch fork" are implemented on +# other targets... +# +if ![istarget "hppa*-hp-hpux*"] then { + continue +} + +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 24\n" + gdb_expect { + -re "Breakpoint.*, line 24.*$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 .*24.*$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 24\n" + gdb_expect { + -re "Breakpoint.*, line 24.*$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 .*24.*$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.base/foll-vfork.c b/gdb/testsuite/gdb.base/foll-vfork.c new file mode 100644 index 0000000..3c7fab5 --- /dev/null +++ b/gdb/testsuite/gdb.base/foll-vfork.c @@ -0,0 +1,20 @@ +#include <stdio.h> +#include <unistd.h> + +#ifdef PROTOTYPES +int main (void) +#else +main () +#endif +{ + int pid; + + pid = vfork (); + if (pid == 0) { + printf ("I'm the child!\n"); + execlp ("gdb.base/vforked-prog", "gdb.base/vforked-prog", (char *)0); + } + else { + printf ("I'm the proud parent of child #%d!\n", pid); + } +} diff --git a/gdb/testsuite/gdb.base/foll-vfork.exp b/gdb/testsuite/gdb.base/foll-vfork.exp new file mode 100644 index 0000000..3a6f99f --- /dev/null +++ b/gdb/testsuite/gdb.base/foll-vfork.exp @@ -0,0 +1,365 @@ +# 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 + } + +if [istarget "hppa2.0w-hp-hpux*"] { + warning "Don't run gdb.base/foll-vfork.exp until JAGaa43495 kernel problem is fixed." + return 0 +} + +set prms_id 0 +set bug_id 0 + +set testfile "foll-vfork" +set testfile2 "vforked-prog" +set srcfile ${testfile}.c +set srcfile2 ${testfile2}.c +set binfile ${objdir}/${subdir}/${testfile} +set binfile2 ${objdir}/${subdir}/${testfile2} + +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 { [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 { + continue +} + +# Test to see if we are on an HP-UX 10.20 and if so, +# do not run these tests as catching vfork is disabled for +# 10.20. + +if [istarget "hppa*-hp-hpux10.20"] then { + return 0 +} + +# 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.*13.*$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 18\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.*18.*$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-prog.c:9.*$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-prog.c:9.*$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}:12.*$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}:9.*$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.base/page.exp b/gdb/testsuite/gdb.base/page.exp new file mode 100644 index 0000000..722840f --- /dev/null +++ b/gdb/testsuite/gdb.base/page.exp @@ -0,0 +1,40 @@ +# 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 { + strace $tracelevel +} + +global message +global timeout + +set timeout 200 + +gdb_exit +gdb_start +gdb_test "set pagination off" "" +gdb_test "info set" ".*pagination: State of pagination is off.*" +gdb_test "set pagination on" "" +gdb_test "info set" ".*pagination: State of pagination is on.*" + +gdb_exit +return 0 + diff --git a/gdb/testsuite/gdb.base/structs.c b/gdb/testsuite/gdb.base/structs.c new file mode 100644 index 0000000..b44d2fe --- /dev/null +++ b/gdb/testsuite/gdb.base/structs.c @@ -0,0 +1,211 @@ +/* Copyright (C) 1996 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 */ + +struct struct1 { char a;}; +struct struct2 { char a, b;}; +struct struct3 { char a, b, c; }; +struct struct4 { char a, b, c, d; }; +struct struct5 { char a, b, c, d, e; }; +struct struct6 { char a, b, c, d, e, f; }; +struct struct7 { char a, b, c, d, e, f, g; }; +struct struct8 { char a, b, c, d, e, f, g, h; }; +struct struct9 { char a, b, c, d, e, f, g, h, i; }; +struct struct10 { char a, b, c, d, e, f, g, h, i, j; }; +struct struct11 { char a, b, c, d, e, f, g, h, i, j, k; }; +struct struct12 { char a, b, c, d, e, f, g, h, i, j, k, l; }; +struct struct16 { char a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p; }; + +struct struct1 foo1 = {'1'}, L1; +struct struct2 foo2 = { 'a', 'b'}, L2; +struct struct3 foo3 = { 'A', 'B', 'C'}, L3; +struct struct4 foo4 = {'1', '2', '3', '4'}, L4; +struct struct5 foo5 = {'a', 'b', 'c', 'd', 'e'}, L5; +struct struct6 foo6 = {'A', 'B', 'C', 'D', 'E', 'F'}, L6; +struct struct7 foo7 = {'1', '2', '3', '4', '5', '6', '7'}, L7; +struct struct8 foo8 = {'1', '2', '3', '4', '5', '6', '7', '8'}, L8; +struct struct9 foo9 = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'}, L9; +struct struct10 foo10 = { + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J'}, L10; +struct struct11 foo11 = { + '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B'}, L11; +struct struct12 foo12 = { + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L'}, L12; +struct struct16 foo16 = { + 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p'}, L16; + +struct struct1 fun1() +{ + return foo1; +} +struct struct2 fun2() +{ + return foo2; +} +struct struct3 fun3() +{ + return foo3; +} +struct struct4 fun4() +{ + return foo4; +} +struct struct5 fun5() +{ + return foo5; +} +struct struct6 fun6() +{ + return foo6; +} +struct struct7 fun7() +{ + return foo7; +} +struct struct8 fun8() +{ + return foo8; +} +struct struct9 fun9() +{ + return foo9; +} +struct struct10 fun10() +{ + return foo10; +} +struct struct11 fun11() +{ + return foo11; +} +struct struct12 fun12() +{ + return foo12; +} +struct struct16 fun16() +{ + return foo16; +} + +void Fun1(foo1) + struct struct1 foo1; +{ + L1 = foo1; +} +void Fun2(foo2) + struct struct2 foo2; +{ + L2 = foo2; +} +void Fun3(foo3) + struct struct3 foo3; +{ + L3 = foo3; +} +void Fun4(foo4) + struct struct4 foo4; +{ + L4 = foo4; +} +void Fun5(foo5) + struct struct5 foo5; +{ + L5 = foo5; +} +void Fun6(foo6) + struct struct6 foo6; +{ + L6 = foo6; +} +void Fun7(foo7) + struct struct7 foo7; +{ + L7 = foo7; +} +void Fun8(foo8) + struct struct8 foo8; +{ + L8 = foo8; +} +void Fun9(foo9) + struct struct9 foo9; +{ + L9 = foo9; +} +void Fun10(foo10) + struct struct10 foo10; +{ + L10 = foo10; +} +void Fun11(foo11) + struct struct11 foo11; +{ + L11 = foo11; +} +void Fun12(foo12) + struct struct12 foo12; +{ + L12 = foo12; +} +void Fun16(foo16) + struct struct16 foo16; +{ + L16 = foo16; +} + +int main() +{ +#ifdef usestubs + set_debug_traps(); + breakpoint(); +#endif + + /* TEST C FUNCTIONS */ + L1 = fun1(); + L2 = fun2(); + L3 = fun3(); + L4 = fun4(); + L5 = fun5(); + L6 = fun6(); + L7 = fun7(); + L8 = fun8(); + L9 = fun9(); + L10 = fun10(); + L11 = fun11(); + L12 = fun12(); + L16 = fun16(); + + foo1.a = foo2.a = foo3.a = foo4.a = foo5.a = foo6.a = foo7.a = foo8.a = + foo9.a = foo10.a = foo11.a = foo12.a = foo16.a = '$'; + + Fun1(foo1); + Fun2(foo2); + Fun3(foo3); + Fun4(foo4); + Fun5(foo5); + Fun6(foo6); + Fun7(foo7); + Fun8(foo8); + Fun9(foo9); + Fun10(foo10); + Fun11(foo11); + Fun12(foo12); + Fun16(foo16); + + return 0; +} diff --git a/gdb/testsuite/gdb.base/structs.exp b/gdb/testsuite/gdb.base/structs.exp new file mode 100644 index 0000000..1c79af5 --- /dev/null +++ b/gdb/testsuite/gdb.base/structs.exp @@ -0,0 +1,148 @@ +# Copyright (C) 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 + +# This file was written by Jeff Law. (law@cygnus.com) + +if $tracelevel then { + strace $tracelevel +} + +set prms_id 0 +set bug_id 0 + +set prototypes 1 +set testfile "structs" +set srcfile ${testfile}.c +set binfile ${objdir}/${subdir}/${testfile} + +# build the first test case +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } { + # built the second test case since we can't use prototypes + warning "Prototypes not supported, rebuilding with -DNO_PROTOTYPES" +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug additional_flags=-DNO_PROTOTYPES}] != "" } { + gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail." + } + set prototypes 0 +} + +# Create and source the file that provides information about the compiler +# used to compile the test case. +if [get_compiler_info ${binfile}] { + return -1; +} + +# The a29k can't call functions, so don't even bother with this test. +if [istarget "a29k-*-udi"] then { + setup_xfail "a29k-*-udi" 2416 + fail "a29k-*-udi can not call functions" + continue +} + +# FIXME: Before calling this proc, we should probably verify that +# we can call inferior functions and get a valid integral value +# returned. +# Note that it is OK to check for 0 or 1 as the returned values, because C +# specifies that the numeric value of a relational or logical expression +# (computed in the inferior) is 1 for true and 0 for false. + +proc do_function_calls {} { + global prototypes + global gcc_compiled + global gdb_prompt + + # First, call the "fun" functions and examine the value they return. + gdb_test "p fun1()" " = {a = 49 '1'}" + gdb_test "p fun2()" " = {a = 97 'a', b = 98 'b'}" + gdb_test "p fun3()" " = {a = 65 'A', b = 66 'B', c = 67 'C'}" + gdb_test "p fun4()" " = {a = 49 '1', b = 50 '2', c = 51 '3', d = 52 '4'}" + gdb_test "p fun5()" " = {a = 97 'a', b = 98 'b', c = 99 'c', d = 100 'd', e = 101 'e'}" + gdb_test "p fun6()" " = {a = 65 'A', b = 66 'B', c = 67 'C', d = 68 'D', e = 69 'E', f = 70 'F'}" + gdb_test "p fun7()" " = {a = 49 '1', b = 50 '2', c = 51 '3', d = 52 '4', e = 53 '5', f = 54 '6', g = 55 '7'}" + gdb_test "p fun8()" " = {a = 49 '1', b = 50 '2', c = 51 '3', d = 52 '4', e = 53 '5', f = 54 '6', g = 55 '7', h = 56 '8'}" + gdb_test "p fun9()" " = {a = 97 'a', b = 98 'b', c = 99 'c', d = 100 'd', e = 101 'e', f = 102 'f', g = 103 'g', h = 104 'h', i = 105 'i'}" + gdb_test "p fun10()" " = {a = 65 'A', b = 66 'B', c = 67 'C', d = 68 'D', e = 69 'E', f = 70 'F', g = 71 'G', h = 72 'H', i = 73 'I', j = 74 'J'}" + gdb_test "p fun11()" " = {a = 49 '1', b = 50 '2', c = 51 '3', d = 52 '4', e = 53 '5', f = 54 '6', g = 55 '7', h = 56 '8', i = 57 '9', j = 65 'A', k = 66 'B'}" + gdb_test "p fun12()" " = {a = 65 'A', b = 66 'B', c = 67 'C', d = 68 'D', e = 69 'E', f = 70 'F', g = 71 'G', h = 72 'H', i = 73 'I', j = 74 'J', k = 75 'K', l = 76 'L'}" + gdb_test "p fun16()" " = {a = 97 'a', b = 98 'b', c = 99 'c', d = 100 'd', e = 101 'e', f = 102 'f', g = 103 'g', h = 104 'h', i = 105 'i', j = 106 'j', k = 107 'k', l = 108 'l', m = 109 'm', n = 110 'n', o = 111 'o', p = 112 'p'}" + + # Now call the Fun functions to set the L* variables. This + # tests that gdb properly passes structures to functions. + gdb_test "p Fun1(foo1)" " = (void|0)" + gdb_test "p Fun2(foo2)" " = (void|0)" + gdb_test "p Fun3(foo3)" " = (void|0)" + gdb_test "p Fun4(foo4)" " = (void|0)" + gdb_test "p Fun5(foo5)" " = (void|0)" + gdb_test "p Fun6(foo6)" " = (void|0)" + gdb_test "p Fun7(foo7)" " = (void|0)" + gdb_test "p Fun8(foo8)" " = (void|0)" + gdb_test "p Fun9(foo9)" " = (void|0)" + gdb_test "p Fun10(foo10)" " = (void|0)" + gdb_test "p Fun11(foo11)" " = (void|0)" + gdb_test "p Fun12(foo12)" " = (void|0)" + gdb_test "p Fun16(foo16)" " = (void|0)" + + # Now print the L* variables and examine their values. + gdb_test "p L1" " = {a = 49 '1'}" + gdb_test "p L2" " = {a = 97 'a', b = 98 'b'}" + gdb_test "p L3" " = {a = 65 'A', b = 66 'B', c = 67 'C'}" + gdb_test "p L4" " = {a = 49 '1', b = 50 '2', c = 51 '3', d = 52 '4'}" + if {$gcc_compiled} then { + setup_xfail "hppa*-*-*" + } + gdb_test "p L5" " = {a = 97 'a', b = 98 'b', c = 99 'c', d = 100 'd', e = 101 'e'}" + if {$gcc_compiled} then { + setup_xfail "hppa*-*-*" + } + gdb_test "p L6" " = {a = 65 'A', b = 66 'B', c = 67 'C', d = 68 'D', e = 69 'E', f = 70 'F'}" + if {$gcc_compiled} then { + setup_xfail "hppa*-*-*" + } + gdb_test "p L7" " = {a = 49 '1', b = 50 '2', c = 51 '3', d = 52 '4', e = 53 '5', f = 54 '6', g = 55 '7'}" + gdb_test "p L8" " = {a = 49 '1', b = 50 '2', c = 51 '3', d = 52 '4', e = 53 '5', f = 54 '6', g = 55 '7', h = 56 '8'}" + gdb_test "p L9" " = {a = 97 'a', b = 98 'b', c = 99 'c', d = 100 'd', e = 101 'e', f = 102 'f', g = 103 'g', h = 104 'h', i = 105 'i'}" + gdb_test "p L10" " = {a = 65 'A', b = 66 'B', c = 67 'C', d = 68 'D', e = 69 'E', f = 70 'F', g = 71 'G', h = 72 'H', i = 73 'I', j = 74 'J'}" + gdb_test "p L11" " = {a = 49 '1', b = 50 '2', c = 51 '3', d = 52 '4', e = 53 '5', f = 54 '6', g = 55 '7', h = 56 '8', i = 57 '9', j = 65 'A', k = 66 'B'}" + gdb_test "p L12" " = {a = 65 'A', b = 66 'B', c = 67 'C', d = 68 'D', e = 69 'E', f = 70 'F', g = 71 'G', h = 72 'H', i = 73 'I', j = 74 'J', k = 75 'K', l = 76 'L'}" + gdb_test "p L16" " = {a = 97 'a', b = 98 'b', c = 99 'c', d = 100 'd', e = 101 'e', f = 102 'f', g = 103 'g', h = 104 'h', i = 105 'i', j = 106 'j', k = 107 'k', l = 108 'l', m = 109 'm', n = 110 'n', o = 111 'o', p = 112 'p'}" +} +# Start with a fresh gdb. + +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +gdb_test "set print sevenbit-strings" "" "" +gdb_test "set print address off" "" "" +gdb_test "set width 0" "" "" + +if [target_info exists gdb,cannot_call_functions] { + setup_xfail "*-*-*" 2416 + fail "This target can not call functions" + return 0 +} + +if { ![runto_main] } then { + gdb_suppress_tests; +} + +do_function_calls; + +gdb_stop_suppressing_tests; + +return 0 diff --git a/gdb/testsuite/gdb.base/sum.c b/gdb/testsuite/gdb.base/sum.c new file mode 100644 index 0000000..f5a5dbf --- /dev/null +++ b/gdb/testsuite/gdb.base/sum.c @@ -0,0 +1,15 @@ +/* This is a sample program for the HP/DDE debugger. */ +#include <stdio.h> + +#ifdef PROTOTYPES +int sum(int *list, int low, int high) +#else +int sum(list, low, high) +int *list, low, high; +#endif + { + int i = 0, s = 0; + for (i = low; i <= high; i++) + s += list[i]; + return(s); + } diff --git a/gdb/testsuite/gdb.base/vforked-prog.c b/gdb/testsuite/gdb.base/vforked-prog.c new file mode 100644 index 0000000..27504db --- /dev/null +++ b/gdb/testsuite/gdb.base/vforked-prog.c @@ -0,0 +1,11 @@ +#include <stdio.h> + +#ifdef PROTOTYPES +int main (void) +#else +main() +#endif +{ + printf("Hello from vforked-prog...\n"); + return 0; +} diff --git a/gdb/testsuite/gdb.chill/xstruct-grt.ch b/gdb/testsuite/gdb.chill/xstruct-grt.ch new file mode 100644 index 0000000..abd0d5e --- /dev/null +++ b/gdb/testsuite/gdb.chill/xstruct-grt.ch @@ -0,0 +1,12 @@ +pot1: MODULE + +SYNMODE m_array1 = ARRAY (2:3) ulong; +SYNMODE m_struct = STRUCT (f1 int, + f2 REF m_array1, + f3 m_array1); +SYNMODE m_array3 = ARRAY (5:6) m_struct; +SYNMODE m_array4 = ARRAY (7:8) ARRAY (9:10) m_struct; + +GRANT all; + +END pot1; diff --git a/gdb/testsuite/gdb.chill/xstruct.ch b/gdb/testsuite/gdb.chill/xstruct.ch new file mode 100644 index 0000000..d8471c8 --- /dev/null +++ b/gdb/testsuite/gdb.chill/xstruct.ch @@ -0,0 +1,16 @@ +pottendo: MODULE + +<> USE_SEIZE_FILE "xstruct-grt.grt" <> +SEIZE m_array3; +SEIZE m_array4; + +SYNMODE m_x = STRUCT (i long, + ar m_array3); +SYNMODE m_y = STRUCT (i long, + ar m_array4); + +DCL x LONG; + +x := 10; + +END pottendo; diff --git a/gdb/testsuite/gdb.chill/xstruct.exp b/gdb/testsuite/gdb.chill/xstruct.exp new file mode 100644 index 0000000..3ac0262 --- /dev/null +++ b/gdb/testsuite/gdb.chill/xstruct.exp @@ -0,0 +1,66 @@ +# 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 Per Bothner. (bothner@cygnus.com) + +if $tracelevel then { + strace $tracelevel +} + +if [skip_chill_tests] then { continue } + +set testfile2 "xstruct-grt" +set srcfile2 ${srcdir}/$subdir/${testfile2}.ch +set objfile2 ${objdir}/$subdir/${testfile2}.o +if { [compile "${srcfile2} -g -c -o ${objfile2}"] != "" } { + perror "Couldn't compile ${srcfile2}" + return -1 +} + +set testfile "xstruct" +set srcfile ${srcdir}/$subdir/${testfile}.ch +set binfile ${objdir}/${subdir}/${testfile}.exe +if { [compile "${srcfile} -g ${objfile2} -o ${binfile} ${CHILL_RT0} ${CHILL_LIB}"] != "" } { + perror "Couldn't compile ${srcfile}" + return -1 +} + +proc do_tests {} { + global prms_id bug_id subdir objdir srcdir binfile 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 + + gdb_test "set language chill" "" + + gdb_test "set var \$i := m_x\[\]" "" + gdb_test "print \$i" { = \[.i: 0, .ar: \[\(5:6\): \[.f1: 0, .f2: NULL, .f3: \[\(2:3\): 0\]\]\]\]} + + gdb_test "set var \$j := m_y\[\]" "" + gdb_test "print \$j" { = \[.i: 0, .ar: \[\(7:8\): \[\(9:10\): \[.f1: 0, .f2: NULL, .f3: \[\(2:3\): 0\]\]\]\]\]} +} + +do_tests |