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 <ahajkova@redhat.com>
This commit is contained in:
Tom Tromey
2024-08-14 07:45:59 -06:00
parent 6a4eb277b7
commit d2f6771173
5 changed files with 102 additions and 11 deletions

View 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 (),

View 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.

View 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

View File

@@ -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;
}

View File

@@ -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"
}