@@ -675,11 +675,9 @@ get_auto_load_pspace_data_for_loading (struct program_space *pspace)
/* Add script file NAME in LANGUAGE to hash table of PSPACE_INFO.
LOADED is true if the script has been (is going to) be loaded, false
otherwise (such as if it has not been found).
- FULL_PATH is NULL if the script wasn't found.
+ FULL_PATH is NULL if the script wasn't found. */
- The result is true if the script was already in the hash table. */
-
-static bool
+static void
maybe_add_script_file (struct auto_load_pspace_info *pspace_info, bool loaded,
const char *name, const char *full_path,
const struct extension_language_defn *language)
@@ -714,20 +712,17 @@ maybe_add_script_file (struct auto_load_pspace_info *pspace_info, bool loaded,
}
else
(*slot)->full_path = NULL;
- (*slot)->loaded = loaded;
(*slot)->language = language;
}
- return in_hash_table;
+ (*slot)->loaded = loaded;
}
/* Add script contents NAME in LANGUAGE to hash table of PSPACE_INFO.
LOADED is true if the script has been (is going to) be loaded, false
- otherwise (such as if it has not been found).
-
- The result is true if the script was already in the hash table. */
+ otherwise (such as if it has not been found). */
-static bool
+static void
maybe_add_script_text (struct auto_load_pspace_info *pspace_info,
bool loaded, const char *name,
const struct extension_language_defn *language)
@@ -753,11 +748,10 @@ maybe_add_script_text (struct auto_load_pspace_info *pspace_info,
strcpy (p, name);
(*slot)->name = p;
(*slot)->full_path = NULL;
- (*slot)->loaded = loaded;
(*slot)->language = language;
}
- return in_hash_table;
+ (*slot)->loaded = loaded;
}
/* Clear the table of loaded section scripts. */
@@ -845,12 +839,7 @@ auto_load_objfile_script_1 (struct objfile *objfile, const char *realname,
= get_auto_load_pspace_data_for_loading (objfile->pspace ());
maybe_add_script_file (pspace_info, is_safe, debugfile, debugfile,
language);
-
- /* To preserve existing behavior we don't check for whether the
- script was already in the table, and always load it.
- It's highly unlikely that we'd ever load it twice,
- and these scripts are required to be idempotent under multiple
- loads anyway. */
+ /* Execute the script if it is on the safe path. */
if (is_safe)
{
objfile_script_sourcer_func *sourcer
@@ -1003,13 +992,12 @@ source_script_file (struct auto_load_pspace_info *pspace_info,
section_name, offset);
}
- bool in_hash_table
- = maybe_add_script_file (pspace_info, bool (opened), file,
- (opened ? opened->full_path.get (): NULL),
- language);
+ maybe_add_script_file (pspace_info, bool (opened), file,
+ (opened ? opened->full_path.get (): NULL),
+ language);
- /* If this file is not currently loaded, load it. */
- if (opened && !in_hash_table)
+ /* Execute the script if it is on the safe path. */
+ if (opened)
sourcer (language, objfile, opened->stream.get (),
opened->full_path.get ());
}
@@ -1087,11 +1075,10 @@ of file %ps."),
bool is_safe = file_is_auto_load_safe (objfile_name (objfile));
- bool in_hash_table
- = maybe_add_script_text (pspace_info, is_safe, name, language);
+ maybe_add_script_text (pspace_info, is_safe, name, language);
- /* If this file is not currently loaded, load it. */
- if (is_safe && !in_hash_table)
+ /* Execute the script if it is on the safe path. */
+ if (is_safe)
executor (language, objfile, name, script_text);
}
similarity index 100%
rename from gdb/testsuite/gdb.python/libpy-autoloaded-pretty-printers-in-newobjfile-event.so-gdb.py
rename to gdb/testsuite/gdb.python/libpy-autoloaded-pretty-printers-in-newobjfile-event-objfile.so-gdb.py
new file mode 100644
@@ -0,0 +1,43 @@
+# Copyright (C) 2026 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 that python pretty
+# printers defined in a python script that is autoloaded have been
+# registered when a custom event handler for the new_objfile event
+# is called.
+
+import gdb.printing
+
+
+class MyClassTestLibPrinter(object):
+ "Print a MyClassTestLib"
+
+ def __init__(self, val):
+ self.val = val
+
+ def to_string(self):
+ return "MyClassTestLib object, id: {}".format(self.val["id"])
+
+ def display_hint(self):
+ return "string"
+
+
+def build_pretty_printer():
+ pp = gdb.printing.RegexpCollectionPrettyPrinter("my_library")
+ pp.add_printer("MyClassTestLib", "^MyClassTestLib$", MyClassTestLibPrinter)
+ return pp
+
+
+gdb.printing.register_pretty_printer(gdb.current_objfile(), build_pretty_printer())
new file mode 100644
@@ -0,0 +1,39 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2026 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/>. */
+
+#include "py-autoloaded-pretty-printers-in-newobjfile-event-lib.h"
+
+#ifndef SCRIPT_FILE
+#error "SCRIPT_FILE not defined"
+#endif
+
+asm(
+".pushsection \".debug_gdb_scripts\",\"MS\",@progbits,1\n"
+".byte 1\n"
+".asciz \"" SCRIPT_FILE "\"\n"
+".popsection\n"
+);
+
+MyClassTestLib::MyClassTestLib (int theId)
+{
+ id = theId;
+}
+
+int MyClassTestLib::getId ()
+{
+ return id;
+}
new file mode 100644
@@ -0,0 +1,49 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2026 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/>. */
+
+#include "py-autoloaded-pretty-printers-in-newobjfile-event-lib.h"
+
+asm(
+".pushsection \".debug_gdb_scripts\",\"MS\",@progbits,1\n"
+".byte 4\n"
+".ascii \"gdb.inlined-script\\n\"\n"
+".ascii \"import gdb.printing\\n\"\n"
+".ascii \"class MyClassTestLibPrinter(object):\\n\"\n"
+".ascii \" def __init__(self, val):\\n\"\n"
+".ascii \" self.val = val\\n\"\n"
+".ascii \" def to_string(self):\\n\"\n"
+".ascii \" return \\\"MyClassTestLib object, id: {}\\\".format(self.val[\\\"id\\\"])\\n\"\n"
+".ascii \" def display_hint(self):\\n\"\n"
+".ascii \" return \\\"string\\\"\\n\"\n"
+".ascii \"def build_pretty_printer():\\n\"\n"
+".ascii \" pp = gdb.printing.RegexpCollectionPrettyPrinter(\\\"my_library\\\")\\n\"\n"
+".ascii \" pp.add_printer(\\\"MyClassTestLib\\\", \\\"^MyClassTestLib$\\\", MyClassTestLibPrinter)\\n\"\n"
+".ascii \" return pp\\n\"\n"
+".ascii \"gdb.printing.register_pretty_printer(gdb.current_objfile(), build_pretty_printer())\\n\"\n"
+".byte 0\n"
+".popsection\n"
+);
+
+MyClassTestLib::MyClassTestLib (int theId)
+{
+ id = theId;
+}
+
+int MyClassTestLib::getId ()
+{
+ return id;
+}
similarity index 100%
rename from gdb/testsuite/gdb.python/py-autoloaded-pretty-printers-in-newobjfile-event-lib.cc
rename to gdb/testsuite/gdb.python/py-autoloaded-pretty-printers-in-newobjfile-event-lib-objfile.cc
@@ -15,7 +15,9 @@
# This file is part of the GDB testsuite. It tests that Python pretty-printers
# defined in a Python script that is autoloaded are registered when an event
-# handler for the new_objfile event is called.
+# handler for the new_objfile event is called. It also tests that scripts
+# which were not loaded because the auto-load safe-path did not cover them are
+# loaded on the next run once the safe-path is widened.
load_lib gdb-python.exp
@@ -23,70 +25,128 @@ require allow_python_tests
standard_testfile -main.cc
-set srcfile_lib "${testfile}-lib.cc"
set python_event_handler_file "${srcdir}/${subdir}/${testfile}.py"
-set libname "lib${testfile}"
-set python_autoload_file "${srcdir}/${subdir}/${libname}.so-gdb.py"
-set binfile_lib [standard_output_file "${libname}.so"]
-
-# Compile library.
-if { [gdb_compile_shlib ${srcdir}/${subdir}/${srcfile_lib} ${binfile_lib} \
- {debug c++}] != "" } {
- return
-}
-
-# Compile main program.
-if { [gdb_compile ${srcdir}/${subdir}/${srcfile} \
- ${binfile} \
- executable \
- [list debug c++ shlib=$binfile_lib]] != "" } {
- return
-}
-
-clean_restart
+set libscript "lib${testfile}-objfile.so-gdb.py"
+set python_autoload_file "${srcdir}/${subdir}/${libscript}"
# Make the -gdb.py script available to gdb, it is automatically loaded by
# gdb if it is put in the same directory as the library.
set remote_python_autoload_file \
[gdb_remote_download host $python_autoload_file]
-gdb_test_no_output \
- "set auto-load safe-path ${remote_python_autoload_file}" \
- "set auto-load safe-path"
-
# Load the Python file that defines a handler for the new_objfile event.
set remote_python_event_handler_file\
[gdb_remote_download host $python_event_handler_file]
-gdb_test_no_output "source ${remote_python_event_handler_file}" "load python file"
-gdb_load ${binfile}
-gdb_load_shlib $binfile_lib
+proc newobjfile_event_test { variant } {
+ global srcdir subdir testfile srcfile
+ global remote_python_autoload_file remote_python_event_handler_file libscript
+ global decimal
-if { ![runto_main] } {
- return
-}
+ with_test_prefix $variant {
+ if { $variant ne "objfile" && [is_remote host] } {
+ unsupported "$variant requires non-remote host"
+ return
+ }
-if { [is_remote target ] } {
- set target_sysroot 0
- gdb_test_multiple "show sysroot" "" {
- -re -wrap "\r\nThe current system root is \"target:.*\"\\." {
- set target_sysroot 1
+ set libname "lib${testfile}-${variant}"
+ set binfile_lib [standard_output_file "${libname}.so"]
+ set binfile [standard_output_file "${testfile}-${variant}"]
+
+ set shlib_flags [list debug c++]
+ if { $variant eq "dotdebug-filename" } {
+ set quoted "\"${srcdir}/${subdir}/${testfile}-${variant}.py\""
+ lappend shlib_flags additional_flags=-DSCRIPT_FILE=$quoted
}
- -re -wrap "" {
+
+ # Compile library.
+ if { [gdb_compile_shlib \
+ "${srcdir}/${subdir}/${testfile}-lib-${variant}.cc" \
+ ${binfile_lib} $shlib_flags] != "" } {
+ return
+ }
+
+ # Compile main program.
+ if { [gdb_compile ${srcdir}/${subdir}/${srcfile} \
+ ${binfile} \
+ executable \
+ [list debug c++ shlib=$binfile_lib]] != "" } {
+ return
+ }
+
+ if { $variant eq "objfile" } {
+ set safe_path_allow $remote_python_autoload_file
+ set script_name $libscript
+ } elseif { $variant eq "dotdebug-filename" } {
+ set safe_path_allow "${srcdir}/${subdir}/${testfile}-${variant}.py"
+ set script_name "${testfile}-${variant}.py"
+ } else {
+ set safe_path_allow $binfile_lib
+ set script_name "gdb.inlined-script"
}
- }
- if { $target_sysroot } {
- unsupported "sysroot start with target: -- auto-load not supported"
- return
+ clean_restart
+ gdb_test_no_output "source $remote_python_event_handler_file" "load python file"
+ gdb_load ${binfile}
+ gdb_load_shlib $binfile_lib
+
+ if { [is_remote target ] } {
+ set target_sysroot 0
+ gdb_test_multiple "show sysroot" "" {
+ -re -wrap "\r\nThe current system root is \"target:.*\"\\." {
+ set target_sysroot 1
+ }
+ -re -wrap "" {
+ }
+ }
+
+ if { $target_sysroot } {
+ unsupported "sysroot start with target: -- auto-load not supported"
+ return
+ }
+ }
+
+ gdb_test_no_output "set auto-load safe-path /restricted" \
+ "set restricted auto-load safe-path"
+
+ if { ![runto_main] } {
+ return
+ }
+
+ gdb_test_multiple "info auto-load python-scripts" "verify script not loaded" {
+ -re -wrap "Yes.*${script_name}.*" {
+ fail $gdb_test_name
+ }
+ -re -wrap "No.*${script_name}.*" {
+ pass $gdb_test_name
+ }
+ }
+
+ gdb_test_no_output \
+ "set auto-load safe-path ${safe_path_allow}" \
+ "set auto-load safe-path"
+
+ if { ![runto_main] } {
+ return
+ }
+
+ gdb_test_multiple "info auto-load python-scripts" "verify script loaded" {
+ -re -wrap "Yes.*${script_name}.*" {
+ pass $gdb_test_name
+ }
+ -re -wrap "No.*${script_name}.*" {
+ fail $gdb_test_name
+ }
+ }
+
+ gdb_test "print all_good" " = true"
+ gdb_test "info pretty-printer" "my_library.*MyClassTestLib.*"
+ gdb_breakpoint [gdb_get_line_number "break to inspect"]
+ gdb_test "continue" "Breakpoint $decimal, main .*"
+ gdb_test "print test" "MyClassTestLib object, id: 1.*"
}
}
-# Check that the new_objfile handler saw the pretty-printer.
-gdb_test "print all_good" " = true"
-
-# Check that the pretty-printer actually works.
-gdb_test "info pretty-printer" "my_library.*MyClassTestLib.*"
-gdb_breakpoint [gdb_get_line_number "break to inspect"]
-gdb_test "continue" "Breakpoint $decimal, main .*"
-gdb_test "print test" "MyClassTestLib object, id: 1.*"
+newobjfile_event_test "objfile"
+newobjfile_event_test "dotdebug-filename"
+newobjfile_event_test "dotdebug-text"