]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
Fix 'catch exception' with -flto
authorTom Tromey <tromey@adacore.com>
Wed, 14 Aug 2024 13:45:59 +0000 (07:45 -0600)
committerTom Tromey <tromey@adacore.com>
Fri, 6 Sep 2024 18:31:50 +0000 (12:31 -0600)
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 <ahajkova@redhat.com>
gdb/ada-lang.c
gdb/symtab.c
gdb/symtab.h
gdb/testsuite/gdb.ada/exception-lto.c [new file with mode: 0644]
gdb/testsuite/gdb.ada/exception-lto.exp [new file with mode: 0644]

index 51112a1ab021b6087410cd83d5d657d4ff79a93b..1e2ee45164426f2e7ee2103c69c943e2ac09baf3 100644 (file)
@@ -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<ada_catchpoint> c
     (new ada_catchpoint (gdbarch, ex_kind,
                         cond_string.empty () ? nullptr : cond_string.c_str (),
index b955cc873e26faafe4935924a89222f56625e989..3d8dcac63bb0ee891d12a20227031bf756d3be4b 100644 (file)
@@ -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.
index 4197a3a164c5292adc426e0596c7f0ff852b99a6..d615fdf1e52ba6126f2682e2fe572adccd271731 100644 (file)
@@ -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 (file)
index 0000000..c5ee69d
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.  */
+
+/* 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 (file)
index 0000000..21059a3
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+
+# 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"
+}