Change how versioned symbols are recorded
authorTom Tromey <tromey@adacore.com>
Tue, 3 Aug 2021 18:42:43 +0000 (12:42 -0600)
committerTom Tromey <tromey@adacore.com>
Wed, 5 Jan 2022 17:44:53 +0000 (10:44 -0700)
A change to BFD caused a gdb regression when using the Ada "catch
exception" feature.  The bug is visible when a shared library throws
an exception that is caught in the main executable.

This was discussed here:

https://sourceware.org/pipermail/binutils/2021-July/117538.html

This patch implements Alan's proposed fix, namely to use VERSYM_HIDDEN
rather than the name when deciding to install a version-less symbol.

The internal test case is identical to the catch_ex_std.exp that is
in-tree, so I haven't added a new test.  I could not make that one
fail on x86-64 Linux, though.  It's possible that maybe I'd have to
update the system linker first, but I didn't want to try that.

Regression tested on x86-64 Fedora 32.

gdb/elfread.c

index 9f87c9f25fb330d15f6bf387ae9b0da7ff49b3f5..3f2d8b4e2337c0f948d75b411e130c671b1a2e4a 100644 (file)
@@ -266,6 +266,8 @@ elf_symtab_read (minimal_symbol_reader &reader,
          continue;
        }
 
+      elf_symbol_type *elf_sym = (elf_symbol_type *) sym;
+
       /* Skip "special" symbols, e.g. ARM mapping symbols.  These are
         symbols which do not correspond to objects in the symbol table,
         but have some other target-specific meaning.  */
@@ -373,7 +375,7 @@ elf_symtab_read (minimal_symbol_reader &reader,
                 NOTE: uweigand-20071112: Synthetic symbols do not
                 have an ELF-private part, so do not touch those.  */
              unsigned int shndx = type == ST_SYNTHETIC ? 0 :
-               ((elf_symbol_type *) sym)->internal_elf_sym.st_shndx;
+               elf_sym->internal_elf_sym.st_shndx;
 
              switch (shndx)
                {
@@ -481,7 +483,6 @@ elf_symtab_read (minimal_symbol_reader &reader,
              if (type != ST_SYNTHETIC)
                {
                  /* Pass symbol size field in via BFD.  FIXME!!!  */
-                 elf_symbol_type *elf_sym = (elf_symbol_type *) sym;
                  SET_MSYMBOL_SIZE (msym, elf_sym->internal_elf_sym.st_size);
                }
 
@@ -495,41 +496,39 @@ elf_symtab_read (minimal_symbol_reader &reader,
          if (msym != NULL)
            {
              const char *atsign = strchr (sym->name, '@');
-
-             if (atsign != NULL && atsign[1] == '@' && atsign > sym->name)
-               {
-                 int len = atsign - sym->name;
-
-                 record_minimal_symbol (reader,
-                                        gdb::string_view (sym->name, len),
-                                        true, symaddr, ms_type, sym->section,
-                                        objfile);
-               }
-           }
-
-         /* For @plt symbols, also record a trampoline to the
-            destination symbol.  The @plt symbol will be used in
-            disassembly, and the trampoline will be used when we are
-            trying to find the target.  */
-         if (msym && ms_type == mst_text && type == ST_SYNTHETIC)
-           {
-             int len = strlen (sym->name);
-
-             if (len > 4 && strcmp (sym->name + len - 4, "@plt") == 0)
+             bool is_at_symbol = atsign != nullptr && atsign > sym->name;
+             bool is_plt = is_at_symbol && strcmp (atsign, "@plt") == 0;
+             int len = is_at_symbol ? atsign - sym->name : 0;
+
+             if (is_at_symbol
+                 && !is_plt
+                 && (elf_sym->version & VERSYM_HIDDEN) == 0)
+               record_minimal_symbol (reader,
+                                      gdb::string_view (sym->name, len),
+                                      true, symaddr, ms_type, sym->section,
+                                      objfile);
+             else if (is_plt)
                {
-                 struct minimal_symbol *mtramp;
-
-                 mtramp = record_minimal_symbol
-                   (reader, gdb::string_view (sym->name, len - 4), true,
-                    symaddr, mst_solib_trampoline, sym->section, objfile);
-                 if (mtramp)
+                 /* For @plt symbols, also record a trampoline to the
+                    destination symbol.  The @plt symbol will be used
+                    in disassembly, and the trampoline will be used
+                    when we are trying to find the target.  */
+                 if (ms_type == mst_text && type == ST_SYNTHETIC)
                    {
-                     SET_MSYMBOL_SIZE (mtramp, MSYMBOL_SIZE (msym));
-                     mtramp->created_by_gdb = 1;
-                     mtramp->filename = filesymname;
-                     if (elf_make_msymbol_special_p)
-                       gdbarch_elf_make_msymbol_special (gdbarch,
-                                                         sym, mtramp);
+                     struct minimal_symbol *mtramp;
+
+                     mtramp = record_minimal_symbol
+                       (reader, gdb::string_view (sym->name, len), true,
+                        symaddr, mst_solib_trampoline, sym->section, objfile);
+                     if (mtramp)
+                       {
+                         SET_MSYMBOL_SIZE (mtramp, MSYMBOL_SIZE (msym));
+                         mtramp->created_by_gdb = 1;
+                         mtramp->filename = filesymname;
+                         if (elf_make_msymbol_special_p)
+                           gdbarch_elf_make_msymbol_special (gdbarch,
+                                                             sym, mtramp);
+                       }
                    }
                }
            }