forked from Imagelibrary/binutils-gdb
This reverts commit29c7078711. After the previous commit29c7078711should no longer be needed as the curses dependency has been removed.
476 lines
15 KiB
Plaintext
476 lines
15 KiB
Plaintext
# Copyright (C) 2023-2024 Free Software Foundation, Inc.
|
|
|
|
# This program is free software; you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation; either version 3 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
load_lib gdb-python.exp
|
|
|
|
require allow_python_tests
|
|
|
|
standard_testfile
|
|
|
|
if {[build_executable "failed to prepare" ${testfile} ${srcfile} \
|
|
{debug build-id}]} {
|
|
return -1
|
|
}
|
|
|
|
# Remove debug information from BINFILE and place it into
|
|
# BINFILE.debug.
|
|
if {[gdb_gnu_strip_debug $binfile]} {
|
|
unsupported "cannot produce separate debug info files"
|
|
return -1
|
|
}
|
|
|
|
set remote_python_file \
|
|
[gdb_remote_download host ${srcdir}/${subdir}/${testfile}.py]
|
|
|
|
set debug_filename ${binfile}.debug
|
|
set hidden_filename ${binfile}.hidden
|
|
|
|
# Start GDB.
|
|
clean_restart
|
|
|
|
# Some initial sanity checks; initially, we can find the debug information
|
|
# (this will use the .gnu_debuglink), then after we move the debug
|
|
# information, reload the executable, now the debug can't be found.
|
|
with_test_prefix "initial checks" {
|
|
# Load BINFILE, we should find the separate debug information.
|
|
gdb_file_cmd $binfile
|
|
gdb_assert {$gdb_file_cmd_debug_info == "debug"} \
|
|
"debug info is found"
|
|
|
|
# Rename the debug information file, re-load BINFILE, GDB should fail
|
|
# to find the debug information
|
|
remote_exec build "mv $debug_filename $hidden_filename"
|
|
gdb_file_cmd $binfile
|
|
gdb_assert {$gdb_file_cmd_debug_info == "nodebug"} \
|
|
"debug info no longer found"
|
|
}
|
|
|
|
# Load the Python script into GDB.
|
|
gdb_test "source $remote_python_file" "^Success" \
|
|
"source python script"
|
|
|
|
# Setup the separate debug info directory. This isn't actually needed until
|
|
# some of the later tests, but might as well get this done now.
|
|
set debug_directory [standard_output_file "debug-dir"]
|
|
remote_exec build "mkdir -p $debug_directory"
|
|
gdb_test_no_output "set debug-file-directory $debug_directory" \
|
|
"set debug-file-directory"
|
|
|
|
# Initially the missing debug handler we install is in a mode where it
|
|
# returns None, indicating that it can't help locate the debug information.
|
|
# Check this works as expected.
|
|
with_test_prefix "handler returning None" {
|
|
gdb_test_no_output \
|
|
"python gdb.missing_debug.register_handler(None, handler_obj)" \
|
|
"register the initial handler"
|
|
|
|
gdb_file_cmd $binfile
|
|
gdb_assert {$gdb_file_cmd_debug_info == "nodebug"} \
|
|
"debug info not found"
|
|
|
|
# Check the handler was only called once.
|
|
gdb_test "python print(handler_obj.call_count)" "^1" \
|
|
"check handler was only called once"
|
|
}
|
|
|
|
# Now configure the handler to move the debug file back to the
|
|
# .gnu_debuglink location and then return True, this will cause GDB to
|
|
# recheck, at which point it should find the debug info.
|
|
with_test_prefix "handler in gnu_debuglink mode" {
|
|
gdb_test_no_output "python handler_obj.set_mode(Mode.RETURN_TRUE, \
|
|
\"$hidden_filename\", \
|
|
\"$debug_filename\")" \
|
|
"confirgure handler"
|
|
gdb_file_cmd $binfile
|
|
gdb_assert {$gdb_file_cmd_debug_info == "debug"} "debug info found"
|
|
|
|
# Check the handler was only called once.
|
|
gdb_test "python print(handler_obj.call_count)" "^1" \
|
|
"check handler was only called once"
|
|
}
|
|
|
|
# Setup a directory structure based on the build-id of BINFILE, but don't
|
|
# move the debug information into place just yet.
|
|
#
|
|
# Instead, configure the handler to move the debug info into the build-id
|
|
# directory.
|
|
#
|
|
# Reload BINFILE, at which point the handler will move the debug info into
|
|
# the build-id directory and return True, GDB will then recheck for the
|
|
# debug information, and should find it.
|
|
with_test_prefix "handler in build-id mode" {
|
|
# Move the debug file out of the way once more.
|
|
remote_exec build "mv $debug_filename $hidden_filename"
|
|
|
|
# Create the build-id based directory in which the debug information
|
|
# will be placed.
|
|
set build_id_filename \
|
|
$debug_directory/[build_id_debug_filename_get $binfile]
|
|
remote_exec build "mkdir -p [file dirname $build_id_filename]"
|
|
|
|
# Configure the handler to move the debug info into the build-id dir.
|
|
gdb_test_no_output "python handler_obj.set_mode(Mode.RETURN_TRUE, \
|
|
\"$hidden_filename\", \
|
|
\"$build_id_filename\")" \
|
|
"confirgure handler"
|
|
|
|
# Reload the binary and check the debug information is found.
|
|
gdb_file_cmd $binfile
|
|
gdb_assert {$gdb_file_cmd_debug_info == "debug"} "debug info found"
|
|
|
|
# Check the handler was only called once.
|
|
gdb_test "python print(handler_obj.call_count)" "^1" \
|
|
"check handler was only called once"
|
|
}
|
|
|
|
# Move the debug information back to a hidden location and configure the
|
|
# handler to return the filename of the hidden debug info location. GDB
|
|
# should immediately use this file as the debug information.
|
|
with_test_prefix "handler returning a string" {
|
|
remote_exec build "mv $build_id_filename $hidden_filename"
|
|
|
|
# Configure the handler return a filename string.
|
|
gdb_test_no_output "python handler_obj.set_mode(Mode.RETURN_STRING, \
|
|
\"$hidden_filename\")" \
|
|
"confirgure handler"
|
|
|
|
# Reload the binary and check the debug information is found.
|
|
gdb_file_cmd $binfile
|
|
gdb_assert {$gdb_file_cmd_debug_info == "debug"} "debug info found"
|
|
|
|
# Check the handler was only called once.
|
|
gdb_test "python print(handler_obj.call_count)" "^1" \
|
|
"check handler was only called once"
|
|
}
|
|
|
|
# Register another global handler, this one raises an exception. Reload the
|
|
# debug information, the bad handler should be invoked first, which raises
|
|
# an excetption, at which point GDB should skip further Python handlers.
|
|
with_test_prefix "handler raises an exception" {
|
|
gdb_test_no_output \
|
|
"python gdb.missing_debug.register_handler(None, rhandler)"
|
|
|
|
foreach_with_prefix exception_type {gdb.GdbError TypeError} {
|
|
gdb_test_no_output \
|
|
"python rhandler.exception_type = $exception_type"
|
|
|
|
gdb_file_cmd $binfile
|
|
gdb_assert {$gdb_file_cmd_debug_info == "nodebug"} \
|
|
"debug info not found"
|
|
|
|
set re [string_to_regexp \
|
|
"Python Exception <class '$exception_type'>: message"]
|
|
gdb_assert {[regexp $re $gdb_file_cmd_msg]} \
|
|
"check for exception in file command output"
|
|
|
|
# Our original handler is still registered, but should not have been
|
|
# called again (as the exception occurs first).
|
|
gdb_test "python print(handler_obj.call_count)" "^1" \
|
|
"check good handler hasn't been called again"
|
|
}
|
|
}
|
|
|
|
gdb_test "info missing-debug-handlers" \
|
|
[multi_line \
|
|
"Global:" \
|
|
" exception_handler" \
|
|
" handler"] \
|
|
"check both handlers are visible"
|
|
|
|
# Re-start GDB.
|
|
clean_restart
|
|
|
|
# Load the Python script into GDB.
|
|
gdb_test "source $remote_python_file" "^Success" \
|
|
"source python script for bad handler name checks"
|
|
|
|
# Attempt to register a missing-debug-handler with NAME. The expectation is
|
|
# that this should fail as NAME contains some invalid characters.
|
|
proc check_bad_name {name} {
|
|
set name_re [string_to_regexp $name]
|
|
set re \
|
|
[multi_line \
|
|
"ValueError.*: invalid character '.' in handler name: $name_re" \
|
|
"Error occurred in Python.*"]
|
|
|
|
gdb_test "python register(\"$name\")" $re \
|
|
"check that '$name' is not accepted"
|
|
}
|
|
|
|
# We don't attempt to be exhaustive here, just check a few random examples
|
|
# of invalid names.
|
|
check_bad_name "!! Bad Name"
|
|
check_bad_name "Bad Name"
|
|
check_bad_name "(Bad Name)"
|
|
check_bad_name "Bad \[Name\]"
|
|
check_bad_name "Bad,Name"
|
|
check_bad_name "Bad;Name"
|
|
|
|
# Check that there are no handlers registered.
|
|
gdb_test_no_output "info missing-debug-handlers" \
|
|
"check no handlers are registered"
|
|
|
|
# Check we can use the enable/disable commands where there are no handlers
|
|
# registered.
|
|
gdb_test "enable missing-debug-handler foo" \
|
|
"^0 missing debug handlers enabled"
|
|
gdb_test "disable missing-debug-handler foo" \
|
|
"^0 missing debug handlers disabled"
|
|
|
|
# Grab the current program space object, used for registering handler later.
|
|
gdb_test_no_output "python pspace = gdb.selected_inferior().progspace"
|
|
|
|
# Now register some handlers.
|
|
foreach hspec {{\"Foo\" None}
|
|
{\"-bar\" None}
|
|
{\"baz-\" pspace}
|
|
{\"abc-def\" pspace}} {
|
|
lassign $hspec name locus
|
|
gdb_test "python register($name, $locus)"
|
|
}
|
|
|
|
with_test_prefix "all handlers enabled" {
|
|
gdb_test "info missing-debug-handlers" \
|
|
[multi_line \
|
|
"Current Progspace:" \
|
|
" abc-def" \
|
|
" baz-" \
|
|
"Global:" \
|
|
" -bar" \
|
|
" Foo"]
|
|
|
|
gdb_file_cmd $binfile
|
|
gdb_test "python print(handler_call_log)" \
|
|
[string_to_regexp {['abc-def', 'baz-', '-bar', 'Foo']}]
|
|
gdb_test_no_output "python handler_call_log = \[\]" \
|
|
"reset call log"
|
|
}
|
|
|
|
with_test_prefix "disable 'baz-'" {
|
|
gdb_test "disable missing-debug-handler progspace baz-" \
|
|
"^1 missing debug handler disabled"
|
|
|
|
gdb_test "info missing-debug-handlers" \
|
|
[multi_line \
|
|
"Progspace \[^\r\n\]+:" \
|
|
" abc-def" \
|
|
" baz- \\\[disabled\\\]" \
|
|
"Global:" \
|
|
" -bar" \
|
|
" Foo"]
|
|
|
|
gdb_file_cmd $binfile
|
|
gdb_test "python print(handler_call_log)" \
|
|
[string_to_regexp {['abc-def', '-bar', 'Foo']}]
|
|
gdb_test_no_output "python handler_call_log = \[\]" \
|
|
"reset call log"
|
|
}
|
|
|
|
with_test_prefix "disable 'Foo'" {
|
|
gdb_test "disable missing-debug-handler .* Foo" \
|
|
"^1 missing debug handler disabled"
|
|
|
|
gdb_test "info missing-debug-handlers" \
|
|
[multi_line \
|
|
"Progspace \[^\r\n\]+:" \
|
|
" abc-def" \
|
|
" baz- \\\[disabled\\\]" \
|
|
"Global:" \
|
|
" -bar" \
|
|
" Foo \\\[disabled\\\]"]
|
|
|
|
gdb_file_cmd $binfile
|
|
gdb_test "python print(handler_call_log)" \
|
|
[string_to_regexp {['abc-def', '-bar']}]
|
|
gdb_test_no_output "python handler_call_log = \[\]" \
|
|
"reset call log"
|
|
}
|
|
|
|
with_test_prefix "disable everything" {
|
|
gdb_test "disable missing-debug-handler .* .*" \
|
|
"^2 missing debug handlers disabled"
|
|
|
|
gdb_test "info missing-debug-handlers" \
|
|
[multi_line \
|
|
"Progspace \[^\r\n\]+:" \
|
|
" abc-def \\\[disabled\\\]" \
|
|
" baz- \\\[disabled\\\]" \
|
|
"Global:" \
|
|
" -bar \\\[disabled\\\]" \
|
|
" Foo \\\[disabled\\\]"]
|
|
|
|
gdb_file_cmd $binfile
|
|
gdb_test "python print(handler_call_log)" \
|
|
[string_to_regexp {[]}]
|
|
gdb_test_no_output "python handler_call_log = \[\]" \
|
|
"reset call log"
|
|
}
|
|
|
|
with_test_prefix "enable 'abc-def'" {
|
|
set re [string_to_regexp $binfile]
|
|
|
|
gdb_test "enable missing-debug-handler \"$re\" abc-def" \
|
|
"^1 missing debug handler enabled" \
|
|
"enable missing-debug-handler"
|
|
|
|
gdb_test "info missing-debug-handlers" \
|
|
[multi_line \
|
|
"Progspace \[^\r\n\]+:" \
|
|
" abc-def" \
|
|
" baz- \\\[disabled\\\]" \
|
|
"Global:" \
|
|
" -bar \\\[disabled\\\]" \
|
|
" Foo \\\[disabled\\\]"]
|
|
|
|
gdb_file_cmd $binfile
|
|
gdb_test "python print(handler_call_log)" \
|
|
[string_to_regexp {['abc-def']}]
|
|
gdb_test_no_output "python handler_call_log = \[\]" \
|
|
"reset call log"
|
|
}
|
|
|
|
with_test_prefix "enable global handlers" {
|
|
set re [string_to_regexp $binfile]
|
|
|
|
gdb_test "enable missing-debug-handler global" \
|
|
"^2 missing debug handlers enabled"
|
|
|
|
gdb_test "info missing-debug-handlers" \
|
|
[multi_line \
|
|
"Progspace \[^\r\n\]+:" \
|
|
" abc-def" \
|
|
" baz- \\\[disabled\\\]" \
|
|
"Global:" \
|
|
" -bar" \
|
|
" Foo"]
|
|
|
|
gdb_file_cmd $binfile
|
|
gdb_test "python print(handler_call_log)" \
|
|
[string_to_regexp {['abc-def', '-bar', 'Foo']}]
|
|
gdb_test_no_output "python handler_call_log = \[\]" \
|
|
"reset call log"
|
|
}
|
|
|
|
# Add handler_obj to the global handler list, and configure it to
|
|
# return False. We should call all of the program space specific
|
|
# handlers (which return None), and then call handler_obj from the
|
|
# global list, which returns False, at which point we shouldn't call
|
|
# anyone else.
|
|
with_test_prefix "return False handler in progspace list" {
|
|
gdb_test "enable missing-debug-handler progspace" \
|
|
"^1 missing debug handler enabled"
|
|
|
|
gdb_test_no_output \
|
|
"python gdb.missing_debug.register_handler(None, handler_obj)" \
|
|
"register the initial handler"
|
|
|
|
gdb_test "info missing-debug-handlers" \
|
|
[multi_line \
|
|
"Progspace \[^\r\n\]+:" \
|
|
" abc-def" \
|
|
" baz-" \
|
|
"Global:" \
|
|
" handler" \
|
|
" -bar" \
|
|
" Foo"]
|
|
|
|
gdb_test_no_output "python handler_obj.set_mode(Mode.RETURN_FALSE)" \
|
|
"confirgure handler"
|
|
|
|
gdb_file_cmd $binfile
|
|
gdb_test "python print(handler_call_log)" \
|
|
[string_to_regexp {['abc-def', 'baz-', 'handler']}]
|
|
gdb_test_no_output "python handler_call_log = \[\]" \
|
|
"reset call log"
|
|
}
|
|
|
|
# Now add handler_obj to the current program space's handler list. We
|
|
# use the same handler object here, that's fine. We should only see a
|
|
# call to the first handler object in the call log.
|
|
with_test_prefix "return False handler in global list" {
|
|
gdb_test_no_output \
|
|
"python gdb.missing_debug.register_handler(pspace, handler_obj)" \
|
|
"register the initial handler"
|
|
|
|
gdb_test "info missing-debug-handlers" \
|
|
[multi_line \
|
|
"Progspace \[^\r\n\]+:" \
|
|
" handler" \
|
|
" abc-def" \
|
|
" baz-" \
|
|
"Global:" \
|
|
" handler" \
|
|
" -bar" \
|
|
" Foo"]
|
|
|
|
gdb_file_cmd $binfile
|
|
gdb_test "python print(handler_call_log)" \
|
|
[string_to_regexp {['handler']}]
|
|
gdb_test_no_output "python handler_call_log = \[\]" \
|
|
"reset call log"
|
|
}
|
|
|
|
with_test_prefix "check handler replacement" {
|
|
# First, check we can have the same name appear in both program
|
|
# space and global lists without giving an error.
|
|
gdb_test_no_output "python register(\"Foo\", pspace)"
|
|
|
|
gdb_test "info missing-debug-handlers" \
|
|
[multi_line \
|
|
"Progspace \[^\r\n\]+:" \
|
|
" Foo" \
|
|
" handler" \
|
|
" abc-def" \
|
|
" baz-" \
|
|
"Global:" \
|
|
" handler" \
|
|
" -bar" \
|
|
" Foo"]
|
|
|
|
# Now check that we get an error if we try to add a handler with
|
|
# the same name.
|
|
gdb_test "python gdb.missing_debug.register_handler(pspace, log_handler(\"Foo\"))" \
|
|
[multi_line \
|
|
"RuntimeError.*: Handler Foo already exists\\." \
|
|
"Error occurred in Python.*"]
|
|
|
|
gdb_test "python gdb.missing_debug.register_handler(handler=log_handler(\"Foo\"), locus=pspace)" \
|
|
[multi_line \
|
|
"RuntimeError.*: Handler Foo already exists\\." \
|
|
"Error occurred in Python.*"]
|
|
|
|
# And now try again, but this time with 'replace=True', we
|
|
# shouldn't get an error in this case.
|
|
gdb_test_no_output \
|
|
"python gdb.missing_debug.register_handler(pspace, log_handler(\"Foo\"), replace=True)"
|
|
|
|
gdb_test_no_output \
|
|
"python gdb.missing_debug.register_handler(handler=log_handler(\"Foo\"), locus=None, replace=True)"
|
|
|
|
# Now disable a handler and check we still need to use 'replace=True'.
|
|
gdb_test "disable missing-debug-handler progspace Foo" \
|
|
"^1 missing debug handler disabled"
|
|
|
|
gdb_test "python gdb.missing_debug.register_handler(pspace, log_handler(\"Foo\"))" \
|
|
[multi_line \
|
|
"RuntimeError.*: Handler Foo already exists\\." \
|
|
"Error occurred in Python.*"] \
|
|
"still get an error when handler is disabled"
|
|
|
|
gdb_test_no_output \
|
|
"python gdb.missing_debug.register_handler(pspace, log_handler(\"Foo\"), replace=True)" \
|
|
"can replace a disabled handler"
|
|
}
|