diff --git a/gdb/NEWS b/gdb/NEWS index 5d9e9ee9d12e..2d57f527b2e5 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -303,6 +303,13 @@ show tui mouse-events Progspace.filename is not None), otherwise, this attribute is itself None. + ** New attribute Progspace.executable_filename. This attribute + holds a string containing a file name set by the "exec-file" or + "file" commands, or None if no executable file is set. This + isn't the exact string passed by the user to these commands; the + file name will have been partially resolved to an absolute file + name. + *** Changes in GDB 13 * MI version 1 is deprecated, and will be removed in GDB 14. diff --git a/gdb/doc/python.texi b/gdb/doc/python.texi index 6510a8364073..4c8bb1222dc1 100644 --- a/gdb/doc/python.texi +++ b/gdb/doc/python.texi @@ -5095,6 +5095,21 @@ If the @code{Progspace} is invalid, i.e.@:, when access this attribute will raise a @code{RuntimeError} exception. @end defvar +@defvar Progspace.executable_filename +The file name, as a string, of the executable file in use by this +program space. The executable file is the file that @value{GDBN} will +invoke in order to start an inferior when using a native target. The +file name within this attribute is updated by the @kbd{exec-file} and +@kbd{file} commands. + +If no executable is currently set within this @code{Progspace} then +this attribute contains @code{None}. + +If the @code{Progspace} is invalid, i.e.@:, when +@code{Progspace.is_valid()} returns @code{False}, then attempting to +access this attribute will raise a @code{RuntimeError} exception. +@end defvar + @defvar Progspace.pretty_printers The @code{pretty_printers} attribute is a list of functions. It is used to look up pretty-printers. A @code{Value} is passed to each diff --git a/gdb/python/py-progspace.c b/gdb/python/py-progspace.c index 929c5f4fa70d..1319978d34a2 100644 --- a/gdb/python/py-progspace.c +++ b/gdb/python/py-progspace.c @@ -131,6 +131,25 @@ pspy_get_symbol_file (PyObject *self, void *closure) Py_RETURN_NONE; } +/* Implement the gdb.Progspace.executable_filename attribute. Retun a + string containing the name of the current executable, or None if no + executable is currently set. If the Progspace is invalid then raise an + exception. */ + +static PyObject * +pspy_get_exec_file (PyObject *self, void *closure) +{ + pspace_object *obj = (pspace_object *) self; + + PSPY_REQUIRE_VALID (obj); + + const char *filename = obj->pspace->exec_filename.get (); + if (filename != nullptr) + return host_string_to_python_string (filename).release (); + + Py_RETURN_NONE; +} + static void pspy_dealloc (PyObject *self) { @@ -596,6 +615,8 @@ static gdb_PyGetSetDef pspace_getset[] = { "symbol_file", pspy_get_symbol_file, nullptr, "The gdb.Objfile for the progspace's main symbol file, or None.", nullptr}, + { "executable_filename", pspy_get_exec_file, nullptr, + "The filename for the progspace's executable, or None.", nullptr}, { "pretty_printers", pspy_get_printers, pspy_set_printers, "Pretty printers.", NULL }, { "frame_filters", pspy_get_frame_filters, pspy_set_frame_filters, diff --git a/gdb/testsuite/gdb.python/py-exec-file.c b/gdb/testsuite/gdb.python/py-exec-file.c new file mode 100644 index 000000000000..8cbea3b68923 --- /dev/null +++ b/gdb/testsuite/gdb.python/py-exec-file.c @@ -0,0 +1,22 @@ +/* This test program is part of GDB, the GNU debugger. + + Copyright 2023 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 . */ + +int +main () +{ + return 0; +} diff --git a/gdb/testsuite/gdb.python/py-exec-file.exp b/gdb/testsuite/gdb.python/py-exec-file.exp new file mode 100644 index 000000000000..14e5088af1cb --- /dev/null +++ b/gdb/testsuite/gdb.python/py-exec-file.exp @@ -0,0 +1,100 @@ +# Copyright (C) 2023 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 . + +require allow_python_tests + +load_lib gdb-python.exp + +standard_testfile + +set binfile1 ${binfile}-a +set binfile2 ${binfile}-b + +if {[build_executable "failed to prepare first executable" \ + $binfile1 $srcfile]} { + return -1 +} + +if {[build_executable "failed to prepare second executable" \ + $binfile2 $srcfile]} { + return -1 +} + +set binfile1 [gdb_remote_download host $binfile1] +set binfile2 [gdb_remote_download host $binfile2] + +# Check that the executable_filename is set correctly after using the +# 'file' command. +with_test_prefix "using 'file' command" { + clean_restart + + gdb_test "python print(gdb.current_progspace().executable_filename)" \ + "None" \ + "check executable_filename when no file is loaded" + + gdb_test "file $binfile1" \ + "Reading symbols from [string_to_regexp $binfile1]\\.\\.\\..*" \ + "load first executable" + gdb_test "python print(gdb.current_progspace().executable_filename)" \ + "[string_to_regexp $binfile1]" \ + "check executable_filename when first executable is loaded" + + gdb_test "file $binfile2" \ + "Reading symbols from [string_to_regexp $binfile2]\\.\\.\\..*" \ + "load second executable" \ + "Load new symbol table from .*\? .y or n. " "y" + gdb_test "python print(gdb.current_progspace().executable_filename)" \ + "[string_to_regexp $binfile2]" \ + "check executable_filename when second executable is loaded" + + gdb_unload + gdb_test "python print(gdb.current_progspace().executable_filename)" \ + "None" \ + "check executable_filename after unloading file" +} + +# Check that the executable_filename is correctly set when we only set +# the exec-file. +with_test_prefix "using 'exec-file' command" { + clean_restart + gdb_test_no_output "exec-file $binfile1" \ + "load first executable" + gdb_test "python print(gdb.current_progspace().executable_filename)" \ + "[string_to_regexp $binfile1]" \ + "check executable_filename when first executable is loaded" + + gdb_test_no_output "exec-file $binfile2" \ + "load second executable" + gdb_test "python print(gdb.current_progspace().executable_filename)" \ + "[string_to_regexp $binfile2]" \ + "check executable_filename when second executable is loaded" + + gdb_test "exec-file" "No executable file now\\." + gdb_test "python print(gdb.current_progspace().executable_filename)" \ + "None" \ + "check executable_filename after unloading file" +} + +# Check that setting the symbol-file doesn't cause the +# executable_filename to be set. +with_test_prefix "using 'symbol-file' command" { + clean_restart + gdb_test "symbol-file $binfile1" \ + "Reading symbols from [string_to_regexp $binfile1]\\.\\.\\..*" \ + "load first executable" + gdb_test "python print(gdb.current_progspace().executable_filename)" \ + "None" \ + "check executable_filename after setting symbol-file" +}