bccd0dd203
2009-31-10 Sergio Durigan Junior <sergiodj@linux.vnet.ibm.com> * breakpoint.c (catch_syscall_split_args): Remove unecessary warning displayed when the user provided a syscall name and there is no XML support. * xml-syscall.c: Renamed `_sysinfo' to `sysinfo'. (set_xml_syscall_file_name): Remove syscall_warn_user. (xml_init_syscalls_info): Remove warning. (init_sysinfo): Update warnings. gdb/testsuite/ChangeLog: 2009-31-10 Sergio Durigan Junior <sergiodj@linux.vnet.ibm.com> * gdb.base/catch-syscall.exp: Adapt the testcase in order to accept the modified warnings for catch syscall. Verify if GDB was compiled with support for lib expat, and choose which tests to run depending on this.
453 lines
14 KiB
Text
453 lines
14 KiB
Text
# Copyright 1997, 1999, 2007, 2008 Free Software Foundation, Inc.
|
|
|
|
# This program is free software; you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation; either version 3 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
# This program tests the 'catch syscall' functionality.
|
|
#
|
|
# It was written by Sergio Durigan Junior <sergiodj@linux.vnet.ibm.com>
|
|
# on September/2008.
|
|
|
|
if { [is_remote target] || ![isnative] } then {
|
|
continue
|
|
}
|
|
|
|
set prms_id 0
|
|
set bug_id 0
|
|
|
|
global srcfile
|
|
set testfile "catch-syscall"
|
|
set srcfile ${testfile}.c
|
|
set binfile ${objdir}/${subdir}/${testfile}
|
|
|
|
# All (but the last) syscalls from the example code
|
|
# They are ordered according to the file, so do not change this.
|
|
set all_syscalls { "close" "chroot" }
|
|
set all_syscalls_numbers { }
|
|
# The last syscall (exit()) does not return, so
|
|
# we cannot expect the catchpoint to be triggered
|
|
# twice. It is a special case.
|
|
set last_syscall "exit_group"
|
|
|
|
if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
|
|
untested catch-syscall.exp
|
|
return -1
|
|
}
|
|
|
|
# Until "catch syscall" is implemented on other targets...
|
|
if {![istarget "hppa*-hp-hpux*"] && ![istarget "*-linux*"]} then {
|
|
continue
|
|
}
|
|
|
|
# This shall be updated whenever 'catch syscall' is implemented
|
|
# on some architecture.
|
|
#if { ![istarget "i\[34567\]86-*-linux*"]
|
|
if { ![istarget "x86_64-*-linux*"] && ![istarget "i\[34567\]86-*-linux*"]
|
|
&& ![istarget "powerpc-*-linux*"] && ![istarget "powerpc64-*-linux*"] } {
|
|
continue
|
|
}
|
|
|
|
# Internal procedure used to check if, after issuing a 'catch syscall'
|
|
# command (without arguments), the 'info breakpoints' command displays
|
|
# that '"any syscall"' is to be caught.
|
|
proc check_info_bp_any_syscall {} {
|
|
global gdb_prompt
|
|
|
|
# Verifying that the catchpoint appears in the 'info breakpoints'
|
|
# command, but with "<any syscall>".
|
|
set thistest "catch syscall appears in 'info breakpoints'"
|
|
gdb_test "info breakpoints" ".*catchpoint.*keep y.*syscall \"<any syscall>\".*" $thistest
|
|
}
|
|
|
|
# Internal procedure used to check if, after issuing a 'catch syscall X'
|
|
# command (with arguments), the 'info breakpoints' command displays
|
|
# that the syscall 'X' is to be caught.
|
|
proc check_info_bp_specific_syscall { syscall } {
|
|
global gdb_prompt
|
|
|
|
set thistest "syscall(s) $syscall appears in 'info breakpoints'"
|
|
gdb_test "info breakpoints" ".*catchpoint.*keep y.*syscall(\[(\]s\[)\])? (.)?${syscall}(.)?.*" $thistest
|
|
}
|
|
|
|
# Internal procedure used to check if, after issuing a 'catch syscall X'
|
|
# command (with many arguments), the 'info breakpoints' command displays
|
|
# that the syscalls 'X' are to be caught.
|
|
proc check_info_bp_many_syscalls { syscalls } {
|
|
global gdb_prompt
|
|
set filter_str ""
|
|
|
|
foreach name $syscalls {
|
|
set filter_str "${filter_str}${name}, "
|
|
}
|
|
|
|
set filter_str [ string trimright $filter_str ", " ]
|
|
|
|
set thistest "syscalls $filter_str appears in 'info breakpoints'"
|
|
gdb_test "info breakpoints" ".*catchpoint.*keep y.*syscalls (.)?${filter_str}(.)?.*" $thistest
|
|
}
|
|
|
|
# This procedure checks if there was a call to a syscall.
|
|
proc check_call_to_syscall { syscall } {
|
|
global gdb_prompt
|
|
|
|
set thistest "program has called $syscall"
|
|
gdb_test "continue" "Catchpoint .*(call to syscall .?${syscall}.?).*" $thistest
|
|
}
|
|
|
|
# This procedure checks if the syscall returned.
|
|
proc check_return_from_syscall { syscall } {
|
|
global gdb_prompt
|
|
|
|
set thistest "syscall $syscall has returned"
|
|
gdb_test "continue" "Catchpoint .*(returned from syscall (.)?${syscall}(.)?).*" $thistest
|
|
}
|
|
|
|
# Internal procedure that performs two 'continue' commands and checks if
|
|
# a syscall call AND return occur.
|
|
proc check_continue { syscall } {
|
|
global gdb_prompt
|
|
|
|
# Testing if the 'continue' stops at the
|
|
# specified syscall_name. If it does, then it should
|
|
# first print that the infeior has called the syscall,
|
|
# and after print that the syscall has returned.
|
|
|
|
# Testing if the inferiorr has called the syscall.
|
|
check_call_to_syscall $syscall
|
|
# And now, that the syscall has returned.
|
|
check_return_from_syscall $syscall
|
|
}
|
|
|
|
# Inserts a syscall catchpoint with an argument.
|
|
proc insert_catch_syscall_with_arg { syscall } {
|
|
global gdb_prompt
|
|
|
|
# Trying to set the catchpoint
|
|
set thistest "catch syscall with arguments ($syscall)"
|
|
gdb_test "catch syscall $syscall" "Catchpoint .*(syscall (.)?${syscall}(.)?( \[\[0-9\]+\])?).*" $thistest
|
|
|
|
check_info_bp_specific_syscall $syscall
|
|
}
|
|
|
|
# Inserts a syscall catchpoint with many arguments.
|
|
proc insert_catch_syscall_with_many_args { syscalls numbers } {
|
|
global gdb_prompt
|
|
set catch [ join $syscalls " " ]
|
|
set filter_str ""
|
|
|
|
foreach name $syscalls number $numbers {
|
|
set filter_str "${filter_str}'${name}' \[${number}\] "
|
|
}
|
|
|
|
set filter_str [ string trimright $filter_str " " ]
|
|
|
|
# Trying to set the catchpoint
|
|
set thistest "catch syscall with arguments ($filter_str)"
|
|
gdb_test "catch syscall $catch" "Catchpoint .*(syscalls (.)?${filter_str}(.)?).*" $thistest
|
|
|
|
check_info_bp_many_syscalls $syscalls
|
|
}
|
|
|
|
proc check_for_program_end {} {
|
|
global gdb_prompt
|
|
|
|
# Deleting the catchpoints
|
|
delete_breakpoints
|
|
|
|
set thistest "successful program end"
|
|
gdb_test "continue" "Program exited normally.*" $thistest
|
|
|
|
}
|
|
|
|
proc test_catch_syscall_without_args {} {
|
|
global gdb_prompt all_syscalls last_syscall
|
|
|
|
# Trying to set the syscall
|
|
set thistest "setting catch syscall without arguments"
|
|
gdb_test "catch syscall" "Catchpoint .*(syscall).*" $thistest
|
|
|
|
check_info_bp_any_syscall
|
|
|
|
# We have to check every syscall
|
|
foreach name $all_syscalls {
|
|
check_continue $name
|
|
}
|
|
|
|
# At last but not least, we check if the inferior
|
|
# has called the last (exit) syscall.
|
|
check_call_to_syscall $last_syscall
|
|
|
|
# Now let's see if the inferior correctly finishes.
|
|
check_for_program_end
|
|
}
|
|
|
|
proc test_catch_syscall_with_args {} {
|
|
global gdb_prompt
|
|
set syscall_name "close"
|
|
|
|
insert_catch_syscall_with_arg $syscall_name
|
|
|
|
# Can we continue until we catch the syscall?
|
|
check_continue $syscall_name
|
|
|
|
# Now let's see if the inferior correctly finishes.
|
|
check_for_program_end
|
|
}
|
|
|
|
proc test_catch_syscall_with_many_args {} {
|
|
global gdb_prompt all_syscalls all_syscalls_numbers
|
|
|
|
insert_catch_syscall_with_many_args $all_syscalls $all_syscalls_numbers
|
|
|
|
# Can we continue until we catch the syscalls?
|
|
foreach name $all_syscalls {
|
|
check_continue $name
|
|
}
|
|
|
|
# Now let's see if the inferior correctly finishes.
|
|
check_for_program_end
|
|
}
|
|
|
|
proc test_catch_syscall_with_wrong_args {} {
|
|
global gdb_prompt
|
|
# mlock is not called from the source
|
|
set syscall_name "mlock"
|
|
|
|
insert_catch_syscall_with_arg $syscall_name
|
|
|
|
# Now, we must verify if the program stops with a continue.
|
|
# If it doesn't, everything is right (since we don't have
|
|
# a syscall named "mlock" in it). Otherwise, this is a failure.
|
|
set thistest "catch syscall with unused syscall ($syscall_name)"
|
|
gdb_test "continue" "Program exited normally.*" $thistest
|
|
}
|
|
|
|
proc test_catch_syscall_restarting_inferior {} {
|
|
global gdb_prompt
|
|
set syscall_name "chroot"
|
|
|
|
insert_catch_syscall_with_arg $syscall_name
|
|
|
|
# Let's first reach the call of the syscall.
|
|
check_call_to_syscall $syscall_name
|
|
|
|
# Now, restart the program
|
|
rerun_to_main
|
|
|
|
# And check for call/return
|
|
check_continue $syscall_name
|
|
|
|
# Can we finish?
|
|
check_for_program_end
|
|
}
|
|
|
|
proc test_catch_syscall_fail_nodatadir {} {
|
|
global gdb_prompt
|
|
|
|
# Sanitizing.
|
|
delete_breakpoints
|
|
|
|
# Testing to see if we receive a warning when calling "catch syscall"
|
|
# without XML support (without datadir).
|
|
set thistest "Catch syscall displays a warning when there is no XML support (no datadir set)"
|
|
gdb_test "catch syscall" "warning: Could not load the syscall XML file.*warning: GDB will not be able to display syscall names nor to verify if.*any provided syscall numbers are valid.*Catchpoint .*(syscall).*" $thistest
|
|
|
|
# Since the catchpoint was set, we must check if it's present at
|
|
# "info breakpoints"
|
|
check_info_bp_any_syscall
|
|
|
|
# Sanitizing.
|
|
delete_breakpoints
|
|
}
|
|
|
|
proc do_syscall_tests {} {
|
|
global gdb_prompt srcdir
|
|
|
|
# First, we need to set GDB datadir.
|
|
send_gdb "set data-directory $srcdir/..\n"
|
|
gdb_expect 10 {
|
|
-re "$gdb_prompt $" {
|
|
verbose "Setting GDB datadir to $srcdir/..." 2
|
|
}
|
|
timeout {
|
|
error "Couldn't set GDB datadir."
|
|
}
|
|
}
|
|
|
|
# Verify that the 'catch syscall' help is available
|
|
set thistest "help catch syscall"
|
|
gdb_test "help catch syscall" "Catch system calls.*" $thistest
|
|
|
|
# Try to set a catchpoint to a nonsense syscall
|
|
set thistest "catch syscall to a nonsense syscall is prohibited"
|
|
gdb_test "catch syscall nonsense_syscall" "Unknown syscall name .*" $thistest
|
|
|
|
# Testing the 'catch syscall' command without arguments.
|
|
# This test should catch any syscalls.
|
|
if [runto_main] then { test_catch_syscall_without_args }
|
|
|
|
# Testing the 'catch syscall' command with arguments.
|
|
# This test should only catch the specified syscall.
|
|
if [runto_main] then { test_catch_syscall_with_args }
|
|
|
|
# Testing the 'catch syscall' command with many arguments.
|
|
# This test should catch $all_syscalls.
|
|
if [runto_main] then { test_catch_syscall_with_many_args }
|
|
|
|
# Testing the 'catch syscall' command with WRONG arguments.
|
|
# This test should not trigger any catchpoints.
|
|
if [runto_main] then { test_catch_syscall_with_wrong_args }
|
|
|
|
# Testing the 'catch' syscall command during a restart of
|
|
# the inferior.
|
|
if [runto_main] then { test_catch_syscall_restarting_inferior }
|
|
}
|
|
|
|
proc test_catch_syscall_without_args_noxml {} {
|
|
# We will need the syscall names even not using it
|
|
# because we need to know know many syscalls are in
|
|
# the example file.
|
|
global gdb_prompt all_syscalls last_syscall
|
|
|
|
delete_breakpoints
|
|
|
|
set thistest "Catch syscall without arguments and without XML support"
|
|
gdb_test "catch syscall" "Catchpoint .*(syscall).*"
|
|
|
|
# Now, we should be able to set a catchpoint,
|
|
# and GDB shall not display the warning anymore.
|
|
foreach name $all_syscalls {
|
|
# Unfortunately, we don't know the syscall number
|
|
# that will be caught because this information is
|
|
# arch-dependent. Thus, we try to catch anything
|
|
# similar to a number.
|
|
check_continue "\[0-9\]*"
|
|
}
|
|
|
|
# At last but not least, we check if the inferior
|
|
# has called the last (exit) syscall.
|
|
check_call_to_syscall "\[0-9\]*"
|
|
|
|
delete_breakpoints
|
|
}
|
|
|
|
proc test_catch_syscall_with_args_noxml {} {
|
|
global gdb_prompt
|
|
|
|
# The number of the "close" syscall. This is our
|
|
# option for a "long-estabilished" syscall in all
|
|
# Linux architectures, but unfortunately x86_64 and
|
|
# a few other platforms don't "follow the convention".
|
|
# Because of this, we need this ugly check :-(.
|
|
set close_number ""
|
|
if { [istarget "x86_64-*-linux*"] } {
|
|
set close_number "3"
|
|
} else {
|
|
set close_number "6"
|
|
}
|
|
|
|
delete_breakpoints
|
|
|
|
insert_catch_syscall_with_arg $close_number
|
|
|
|
check_continue $close_number
|
|
|
|
delete_breakpoints
|
|
}
|
|
|
|
proc test_catch_syscall_with_wrong_args_noxml {} {
|
|
global gdb_prompt
|
|
|
|
delete_breakpoints
|
|
|
|
# Even without XML support, GDB should not accept unknown
|
|
# syscall names for the catchpoint.
|
|
set thistest "Catch a nonsense syscall without XML support"
|
|
gdb_test "catch syscall nonsense_syscall" "Unknown syscall name .nonsense_syscall.*" $thistest
|
|
|
|
delete_breakpoints
|
|
}
|
|
|
|
proc do_syscall_tests_without_xml {} {
|
|
global gdb_prompt srcdir
|
|
|
|
# In this case, we don't need to set GDB's datadir because
|
|
# we want GDB to display only numbers, not names. So, let's
|
|
# begin with the tests.
|
|
|
|
# Let's test if we can catch syscalls without XML support.
|
|
# We should succeed, but GDB is not supposed to print syscall names.
|
|
if [runto_main] then { test_catch_syscall_without_args_noxml }
|
|
|
|
# The only valid argument "catch syscall" should accept is the
|
|
# syscall number, and not the name (since it can't translate a
|
|
# name to a number).
|
|
#
|
|
# It's worth mentioning that we only try to catch the syscall
|
|
# close(). This is because the syscall number is an arch-dependent
|
|
# information, so we can't assume that we know every syscall number
|
|
# in this system. Therefore, we have decided to use a "long-estabilished"
|
|
# system call, and close() just sounded the right choice :-).
|
|
if [runto_main] then { test_catch_syscall_with_args_noxml }
|
|
|
|
# Now, we'll try to provide a syscall name (valid or not) to the command,
|
|
# and expect it to fail.
|
|
if [runto_main] then { test_catch_syscall_with_wrong_args_noxml }
|
|
}
|
|
|
|
# This procedure fills the vector "all_syscalls_numbers" with the proper
|
|
# numbers for the used syscalls according to the architecture.
|
|
proc fill_all_syscalls_numbers {} {
|
|
global all_syscalls_numbers
|
|
|
|
# For Linux on x86, PPC and PPC64, the numbers for the syscalls "close" and
|
|
# "chroot" are the same.
|
|
if { ![istarget "i\[34567\]86-*-linux*"]
|
|
|| ![istarget "powerpc-*-linux*"] || ![istarget "powerpc64-*-linux*"] } {
|
|
set all_syscalls_numbers { "6" "61" }
|
|
}
|
|
}
|
|
|
|
# Start with a fresh gdb
|
|
|
|
gdb_exit
|
|
set do_xml_test ![gdb_skip_xml_test]
|
|
gdb_start
|
|
gdb_reinitialize_dir $srcdir/$subdir
|
|
gdb_load ${binfile}
|
|
|
|
# Execute the tests, using XML support
|
|
if $do_xml_test {
|
|
do_syscall_tests
|
|
|
|
# Now, we have to see if GDB displays a warning when we
|
|
# don't set the data-directory but try to use catch syscall
|
|
# anyway. For that, we must restart GDB first.
|
|
gdb_exit
|
|
gdb_start
|
|
gdb_reinitialize_dir $srcdir/$subdir
|
|
gdb_load ${binfile}
|
|
test_catch_syscall_fail_nodatadir
|
|
}
|
|
|
|
# Restart gdb
|
|
|
|
gdb_exit
|
|
gdb_start
|
|
gdb_reinitialize_dir $srcdir/$subdir
|
|
gdb_load ${binfile}
|
|
|
|
# Execute the tests, without XML support. In this case, GDB will
|
|
# only display syscall numbers, and not syscall names.
|
|
do_syscall_tests_without_xml
|