From: Tom Tromey Date: Wed, 14 Aug 2024 13:45:59 +0000 (-0600) Subject: Fix 'catch exception' with -flto X-Git-Tag: gdb-16-branchpoint~983 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=d2f67711730;p=thirdparty%2Fbinutils-gdb.git Fix 'catch exception' with -flto A user noticed that when an Ada program (including the runtime) is compiled with -flto, then "catch exception" does not work -- even though setting the equivalent breakpoint by hand does work. Looking into this, it turns out that GCC puts the exception functions from the Ada runtime into a CU that uses the C language, not Ada. Then, when trying to look up the relevant symbol, lookup_name_info::search_name_hash uses the "verbatim" form of the symbol name (like "<__gnat_debug_raise_exception>") rather than the "<>"-less form, causing the symbol not to be found. This patch fixes the problem in two steps. First, lookup_name_info::search_name_hash is changed to use the same hack that language_defn::get_symbol_name_matcher uses. That is, when the current language is Ada, verbatim-mode lookups are special-cased. (This is a bit unfortunate; perhaps a better long term approach would be to promote verbatim mode to a fundamental mode of lookup_name_info.) Second, although the above fixes the problem in the Ada language mode, the code still fails in other languages. However, due to the way these lookups are coded in ada-lang.c, I think it makes sense to temporarily set the current language to Ada in create_ada_exception_catchpoint. Tested on x86-64 Fedora 38. A new test case that mimics the -flto scenario is included. Reviewed-By: Alexandra Petlanova Hajkova --- diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c index 51112a1ab02..1e2ee451644 100644 --- a/gdb/ada-lang.c +++ b/gdb/ada-lang.c @@ -12717,6 +12717,10 @@ create_ada_exception_catchpoint (struct gdbarch *gdbarch, int enabled, int from_tty) { + /* This works around an obscure issue when an Ada program is + compiled with LTO. */ + scoped_restore_current_language save_language (language_ada); + std::unique_ptr c (new ada_catchpoint (gdbarch, ex_kind, cond_string.empty () ? nullptr : cond_string.c_str (), diff --git a/gdb/symtab.c b/gdb/symtab.c index b955cc873e2..3d8dcac63bb 100644 --- a/gdb/symtab.c +++ b/gdb/symtab.c @@ -1929,6 +1929,28 @@ lookup_name_info::match_any () return lookup_name; } +/* See symtab.h. */ + +unsigned int +lookup_name_info::search_name_hash (language lang) const +{ + /* This works around an obscure problem. If currently in Ada mode, + and the name is wrapped in '<...>' (indicating verbatim mode), + force the use of the Ada language here so that the '<' and '>' + will be removed. */ + if (current_language->la_language == language_ada && ada ().verbatim_p ()) + lang = language_ada; + + /* Only compute each language's hash once. */ + if (!m_demangled_hashes_p[lang]) + { + m_demangled_hashes[lang] + = ::search_name_hash (lang, language_lookup_name (lang)); + m_demangled_hashes_p[lang] = true; + } + return m_demangled_hashes[lang]; +} + /* Compute the demangled form of NAME as used by the various symbol lookup functions. The result can either be the input NAME directly, or a pointer to a buffer owned by the STORAGE object. diff --git a/gdb/symtab.h b/gdb/symtab.h index 4197a3a164c..d615fdf1e52 100644 --- a/gdb/symtab.h +++ b/gdb/symtab.h @@ -266,17 +266,7 @@ class lookup_name_info final } /* Get the search name hash for searches in language LANG. */ - unsigned int search_name_hash (language lang) const - { - /* Only compute each language's hash once. */ - if (!m_demangled_hashes_p[lang]) - { - m_demangled_hashes[lang] - = ::search_name_hash (lang, language_lookup_name (lang)); - m_demangled_hashes_p[lang] = true; - } - return m_demangled_hashes[lang]; - } + unsigned int search_name_hash (language lang) const; /* Get the search name for searches in language LANG. */ const char *language_lookup_name (language lang) const diff --git a/gdb/testsuite/gdb.ada/exception-lto.c b/gdb/testsuite/gdb.ada/exception-lto.c new file mode 100644 index 00000000000..c5ee69d52f5 --- /dev/null +++ b/gdb/testsuite/gdb.ada/exception-lto.c @@ -0,0 +1,40 @@ +/* This test program is part of GDB, the GNU debugger. + + Copyright 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 . */ + +/* We need a few extra functions here to ensure that the dictionary + for the global block has more than one slot. */ + +void f1 () { } +void f2 () { } +void f3 () { } +void f4 () { } + +void +__gnat_debug_raise_exception () +{ +} + +void +__gnat_begin_handler_v1 () +{ +} + +int +main () +{ + return 0; +} diff --git a/gdb/testsuite/gdb.ada/exception-lto.exp b/gdb/testsuite/gdb.ada/exception-lto.exp new file mode 100644 index 00000000000..21059a3568f --- /dev/null +++ b/gdb/testsuite/gdb.ada/exception-lto.exp @@ -0,0 +1,35 @@ +# Copyright 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 . + +# This test mimics the situation where an Ada program (including the +# runtime) is built with -flto. In this situation, gcc emits the +# exception handling functions in the DWARF -- but in a CU that is +# marked as coming from "C". This then triggered a bug causing the +# Ada catchpoint code not to find the underlying runtime functions. + +require allow_ada_tests + +standard_testfile .c + +if {[build_executable "failed to prepare" $testfile $srcfile] == -1} { + return -1 +} + +# Try this test in both the C and Ada language modes. +foreach_with_prefix lang {c ada} { + clean_restart $testfile + gdb_test_no_output "set lang $lang" + gdb_test "catch exception" "Catchpoint 1: all Ada exceptions" +}