mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-05-31 01:45:52 +08:00

The documentation for Progspace.block_for_pc says: Return the innermost gdb.Block containing the given pc value. If the block cannot be found for the pc value specified, the function will return None. However, the implementation actually throws an error for invalid addresses, like this: (gdb) python print gdb.current_progspace ().block_for_pc (1) Traceback (most recent call last): File "<string>", line 1, in <module> RuntimeError: Cannot locate object file for block. Error while executing Python code. (gdb) This has been the behaviour since the command was first added (when the documentation was still as above) in this commit: commit f3e9a8177c41893858fce2bdf339dbe90b3a4ef5 Date: Wed Feb 24 21:18:28 2010 +0000 Since that commit the code in question has moved around, but the important parts are largely unchanged. The function in question is now in py-progspace.c:pspy_block_for_pc. Examining the code shows that the real state is more complex than just the function throws an error instead of returning None, instead the real situation is: 1. If we can't find a compilation unit for the $pc value then we throw an error, but 2. If we can find a compilation unit, but can't find a block within the compilation unit for the $pc then return None. I suspect for most users of the Python API this distinction is irrelevant, and I propose that we standardise on one single failure mechanism. Given the function can currently return None in some cases, and is documented to return None on error, I propose we make that the case for all error paths, which is what this patch does. As the Progspace.block_for_pc method is currently untested, I've added some basic tests including for a call with an invalid $pc. This is potentially an API breaking change, though an undocumented part of the API. Also, users should have been checking and handling a None return value anyway, so my hope is that this shouldn't be too disruptive. gdb/ChangeLog: * python/py-progspace.c (pspy_block_for_pc): Return None for all error paths. gdb/testsuite/ChangeLog: * gdb.python/py-progspace.exp: Add tests for the Progspace.block_for_pc method. Change-Id: I9cea8d2132902bcad0013d1fd39080dd5423cc57
99 lines
3.3 KiB
Plaintext
99 lines
3.3 KiB
Plaintext
# Copyright (C) 2010-2019 Free Software Foundation, Inc.
|
|
|
|
# This program is free software; you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation; either version 3 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
# This file is part of the GDB testsuite. It tests the program space
|
|
# support in Python.
|
|
|
|
load_lib gdb-python.exp
|
|
|
|
standard_testfile
|
|
|
|
if {[build_executable $testfile.exp $testfile $srcfile debug] == -1} {
|
|
return -1
|
|
}
|
|
|
|
# Start with a fresh gdb.
|
|
|
|
gdb_exit
|
|
gdb_start
|
|
gdb_reinitialize_dir $srcdir/$subdir
|
|
|
|
# Skip all tests if Python scripting is not enabled.
|
|
if { [skip_python_tests] } { continue }
|
|
|
|
gdb_test "python print (gdb.current_progspace().filename)" "None" \
|
|
"current progspace filename (None)"
|
|
gdb_test "python print (gdb.progspaces())" "\\\[<gdb.Progspace object at $hex>\\\]"
|
|
|
|
gdb_test_no_output "python dir(gdb.current_progspace())"
|
|
|
|
gdb_load ${binfile}
|
|
|
|
gdb_py_test_silent_cmd "python progspace = gdb.current_progspace()" \
|
|
"Get current progspace" 1
|
|
|
|
gdb_test "python print (progspace.filename)" "py-progspace" \
|
|
"current progspace filename (py-progspace)"
|
|
|
|
gdb_py_test_silent_cmd "python progspace.random_attribute = 42" \
|
|
"Set random attribute in progspace" 1
|
|
gdb_test "python print (progspace.random_attribute)" "42" \
|
|
"Verify set of random attribute in progspace"
|
|
|
|
if {![runto_main]} {
|
|
fail "can't run to main"
|
|
return
|
|
}
|
|
|
|
# Check we can get a block for the current $pc.
|
|
set pc_val [get_integer_valueof "\$pc" 0]
|
|
gdb_py_test_silent_cmd "python blk = gdb.current_progspace ().block_for_pc (${pc_val})" \
|
|
"get block for the current \$pc" 1
|
|
gdb_test "python print blk.start <= ${pc_val}" "True" \
|
|
"block start is before \$pc"
|
|
gdb_test "python print blk.end >= ${pc_val}" "True" \
|
|
"block end is after \$pc"
|
|
|
|
# Check what happens when we ask for a block of an invalid address.
|
|
if ![is_address_zero_readable] {
|
|
gdb_test "python print gdb.current_progspace ().block_for_pc (0)" "None"
|
|
}
|
|
|
|
# With a single inferior, progspace.objfiles () and gdb.objfiles () should
|
|
# be identical.
|
|
gdb_test "python print (progspace.objfiles () == gdb.objfiles ())" "True"
|
|
|
|
gdb_test "add-inferior"
|
|
gdb_test "inferior 2"
|
|
|
|
gdb_load ${binfile}
|
|
|
|
# With a second (non-started) inferior, we should have a single objfile - the
|
|
# main one.
|
|
gdb_test "python print (len (gdb.objfiles ())) == 1"
|
|
|
|
# And the gdb.objfiles() list should now be different from the objfiles of the
|
|
# prog space of inferior 1.
|
|
gdb_test "python print (progspace.objfiles () != gdb.objfiles ())" "True"
|
|
|
|
# Delete inferior 2 (and therefore the second progspace), check that the Python
|
|
# object reacts sensibly.
|
|
gdb_py_test_silent_cmd "python progspace2 = gdb.current_progspace()" \
|
|
"save progspace 2" 1
|
|
gdb_test "inferior 1" "Switching to inferior 1.*"
|
|
gdb_test_no_output "remove-inferiors 2"
|
|
gdb_test "python print (progspace2.objfiles ())" \
|
|
"RuntimeError: Program space no longer exists.*"
|