]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
Don't return DW_AT_name for function name in C++
authorAlan Modra <amodra@gmail.com>
Tue, 9 Dec 2014 23:21:56 +0000 (09:51 +1030)
committerAlan Modra <amodra@gmail.com>
Wed, 11 Feb 2015 12:36:36 +0000 (23:06 +1030)
DW_AT_name for functions typically just contains the base function
name, so lacks namespace, class and parameter information.  It would
be possible to extract all these from the DWARF, but at a considerable
complication of the parser in dwarf2.c, and then you'd need to mangle
it all together.  Much simpler is to look up the actual symbol.  This
patch does that, avoiding the extra symbol lookup when the language
doesn't do name mangling.

PR 17541
* dwarf2.c (struct comp_unit): Add "lang".
(non_mangled): New function.
(struct funcinfo): Add "is_linkage".  Reorder for better packing.
Make "name" a const char*.
(lookup_address_in_function_table): Delete functionname_ptr param.
(find_abstract_instance_name): Add is_linkage param.  Set if we
have DW_AT_linkage_name or non_mangled DW_AT_name.
(scan_unit_for_symbols): Similarly set func->is_linkage.
(parse_comp_unit): Stash DW_AT_language.
(comp_unit_find_nearest_line): Replace functionname_ptr param
with function_ptr param.
(_bfd_dwarf2_find_nearest_line): Adjust above calls.  Set
functionname_ptr from function->name.  Call _bfd_elf_find_function
to retrieve symbol for function if not linkage name.
(_bfd_elf_find_function): Add bfd_target_elf_flavour test, moved from..
* elf.c (elf_find_function): ..here.
(_bfd_elf_find_nearest_line): Adjust calls.
* elf-bfd.h (_bfd_elf_find_function): Declare.

bfd/ChangeLog
bfd/dwarf2.c
bfd/elf-bfd.h
bfd/elf.c

index 8d3d97f337e657687e088c2fdeb4fc3781d887fc..7565286039fa6d6f1dfc8d7e35d5a201186cf7e6 100644 (file)
@@ -1,6 +1,27 @@
 2015-02-11  Alan Modra  <amodra@gmail.com>
 
        Apply from master.
+       2014-12-10  Alan Modra  <amodra@gmail.com>
+       PR 17541
+       * dwarf2.c (struct comp_unit): Add "lang".
+       (non_mangled): New function.
+       (struct funcinfo): Add "is_linkage".  Reorder for better packing.
+       Make "name" a const char*.
+       (lookup_address_in_function_table): Delete functionname_ptr param.
+       (find_abstract_instance_name): Add is_linkage param.  Set if we
+       have DW_AT_linkage_name or non_mangled DW_AT_name.
+       (scan_unit_for_symbols): Similarly set func->is_linkage.
+       (parse_comp_unit): Stash DW_AT_language.
+       (comp_unit_find_nearest_line): Replace functionname_ptr param
+       with function_ptr param.
+       (_bfd_dwarf2_find_nearest_line): Adjust above calls.  Set
+       functionname_ptr from function->name.  Call _bfd_elf_find_function
+       to retrieve symbol for function if not linkage name.
+       (_bfd_elf_find_function): Add bfd_target_elf_flavour test, moved from..
+       * elf.c (elf_find_function): ..here.
+       (_bfd_elf_find_nearest_line): Adjust calls.
+       * elf-bfd.h (_bfd_elf_find_function): Declare.
+
        2014-12-10  Alan Modra  <amodra@gmail.com>
        PR 17666
        * elf-bfd.h (struct elf_backend_data): Add sort_relocs_p.
index 93236a699b8d0a0b6f34e418e0e06554c2b595be..915d3e2f5a24e304327f03d3c7308c9986ffde65 100644 (file)
@@ -222,6 +222,9 @@ struct comp_unit
   /* The abbrev hash table.  */
   struct abbrev_info **abbrevs;
 
+  /* DW_AT_language.  */
+  int lang;
+
   /* Note that an error was found by comp_unit_find_nearest_line.  */
   int error;
 
@@ -1103,6 +1106,33 @@ read_attribute (struct attribute *attr,
   return info_ptr;
 }
 
+/* Return whether DW_AT_name will return the same as DW_AT_linkage_name
+   for a function.  */
+
+static bfd_boolean
+non_mangled (int lang)
+{
+  switch (lang)
+    {
+    default:
+      return FALSE;
+
+    case DW_LANG_C89:
+    case DW_LANG_C:
+    case DW_LANG_Ada83:
+    case DW_LANG_Cobol74:
+    case DW_LANG_Cobol85:
+    case DW_LANG_Fortran77:
+    case DW_LANG_Pascal83:
+    case DW_LANG_C99:
+    case DW_LANG_Ada95:
+    case DW_LANG_PLI:
+    case DW_LANG_UPC:
+    case DW_LANG_C11:
+      return TRUE;
+    }
+}
+
 /* Source line information table routines.  */
 
 #define FILE_ALLOC_CHUNK 5
@@ -1161,14 +1191,15 @@ struct funcinfo
   struct funcinfo *caller_func;
   /* Source location file name where caller_func inlines this func.  */
   char *caller_file;
-  /* Source location line number where caller_func inlines this func.  */
-  int caller_line;
   /* Source location file name.  */
   char *file;
+  /* Source location line number where caller_func inlines this func.  */
+  int caller_line;
   /* Source location line number.  */
   int line;
   int tag;
-  char *name;
+  bfd_boolean is_linkage;
+  const char *name;
   struct arange arange;
   /* Where the symbol is defined.  */
   asection *sec;
@@ -1992,7 +2023,7 @@ read_debug_ranges (struct comp_unit *unit)
 
 /* Function table functions.  */
 
-/* If ADDR is within UNIT's function tables, set FUNCTIONNAME_PTR, and return
+/* If ADDR is within UNIT's function tables, set FUNCTION_PTR, and return
    TRUE.  Note that we need to find the function that has the smallest range
    that contains ADDR, to handle inlined functions without depending upon
    them being ordered in TABLE by increasing range.  */
@@ -2000,8 +2031,7 @@ read_debug_ranges (struct comp_unit *unit)
 static bfd_boolean
 lookup_address_in_function_table (struct comp_unit *unit,
                                  bfd_vma addr,
-                                 struct funcinfo **function_ptr,
-                                 const char **functionname_ptr)
+                                 struct funcinfo **function_ptr)
 {
   struct funcinfo* each_func;
   struct funcinfo* best_fit = NULL;
@@ -2030,14 +2060,10 @@ lookup_address_in_function_table (struct comp_unit *unit,
 
   if (best_fit)
     {
-      *functionname_ptr = best_fit->name;
       *function_ptr = best_fit;
       return TRUE;
     }
-  else
-    {
-      return FALSE;
-    }
+  return FALSE;
 }
 
 /* If SYM at ADDR is within function table of UNIT, set FILENAME_PTR
@@ -2128,7 +2154,8 @@ lookup_symbol_in_variable_table (struct comp_unit *unit,
 
 static char *
 find_abstract_instance_name (struct comp_unit *unit,
-                            struct attribute *attr_ptr)
+                            struct attribute *attr_ptr,
+                            bfd_boolean *is_linkage)
 {
   bfd *abfd = unit->abfd;
   bfd_byte *info_ptr;
@@ -2179,7 +2206,7 @@ find_abstract_instance_name (struct comp_unit *unit,
          (*_bfd_error_handler)
            (_("Dwarf Error: Unable to read alt ref %u."), die_ref);
          bfd_set_error (bfd_error_bad_value);
-         return name;
+         return NULL;
        }
       /* FIXME: Do we need to locate the correct CU, in a similar
         fashion to the code in the DW_FORM_ref_addr case above ?  */
@@ -2213,17 +2240,24 @@ find_abstract_instance_name (struct comp_unit *unit,
                  /* Prefer DW_AT_MIPS_linkage_name or DW_AT_linkage_name
                     over DW_AT_name.  */
                  if (name == NULL && is_str_attr (attr.form))
-                   name = attr.u.str;
+                   {
+                     name = attr.u.str;
+                     if (non_mangled (unit->lang))
+                       *is_linkage = TRUE;
+                   }
                  break;
                case DW_AT_specification:
-                 name = find_abstract_instance_name (unit, &attr);
+                 name = find_abstract_instance_name (unit, &attr, is_linkage);
                  break;
                case DW_AT_linkage_name:
                case DW_AT_MIPS_linkage_name:
                  /* PR 16949:  Corrupt debug info can place
                     non-string forms into these attributes.  */
                  if (is_str_attr (attr.form))
-                   name = attr.u.str;
+                   {
+                     name = attr.u.str;
+                     *is_linkage = TRUE;
+                   }
                  break;
                default:
                  break;
@@ -2389,14 +2423,19 @@ scan_unit_for_symbols (struct comp_unit *unit)
 
                case DW_AT_abstract_origin:
                case DW_AT_specification:
-                 func->name = find_abstract_instance_name (unit, &attr);
+                 func->name = find_abstract_instance_name (unit, &attr,
+                                                           &func->is_linkage);
                  break;
 
                case DW_AT_name:
                  /* Prefer DW_AT_MIPS_linkage_name or DW_AT_linkage_name
                     over DW_AT_name.  */
                  if (func->name == NULL && is_str_attr (attr.form))
-                   func->name = attr.u.str;
+                   {
+                     func->name = attr.u.str;
+                     if (non_mangled (unit->lang))
+                       func->is_linkage = TRUE;
+                   }
                  break;
 
                case DW_AT_linkage_name:
@@ -2404,7 +2443,10 @@ scan_unit_for_symbols (struct comp_unit *unit)
                  /* PR 16949:  Corrupt debug info can place
                     non-string forms into these attributes.  */
                  if (is_str_attr (attr.form))
-                   func->name = attr.u.str;
+                   {
+                     func->name = attr.u.str;
+                     func->is_linkage = TRUE;
+                   }
                  break;
 
                case DW_AT_low_pc:
@@ -2692,6 +2734,10 @@ parse_comp_unit (struct dwarf2_debug *stash,
            break;
          }
 
+       case DW_AT_language:
+         unit->lang = attr.u.val;
+         break;
+
        default:
          break;
        }
@@ -2736,7 +2782,7 @@ comp_unit_contains_address (struct comp_unit *unit, bfd_vma addr)
 
 /* If UNIT contains ADDR, set the output parameters to the values for
    the line containing ADDR.  The output parameters, FILENAME_PTR,
-   FUNCTIONNAME_PTR, and LINENUMBER_PTR, are pointers to the objects
+   FUNCTION_PTR, and LINENUMBER_PTR, are pointers to the objects
    to be filled in.
 
    Returns the range of addresses covered by the entry that was used
@@ -2746,13 +2792,12 @@ static bfd_vma
 comp_unit_find_nearest_line (struct comp_unit *unit,
                             bfd_vma addr,
                             const char **filename_ptr,
-                            const char **functionname_ptr,
+                            struct funcinfo **function_ptr,
                             unsigned int *linenumber_ptr,
                             unsigned int *discriminator_ptr,
                             struct dwarf2_debug *stash)
 {
   bfd_boolean func_p;
-  struct funcinfo *function;
 
   if (unit->error)
     return FALSE;
@@ -2781,11 +2826,10 @@ comp_unit_find_nearest_line (struct comp_unit *unit,
        }
     }
 
-  function = NULL;
-  func_p = lookup_address_in_function_table (unit, addr,
-                                            &function, functionname_ptr);
-  if (func_p && (function->tag == DW_TAG_inlined_subroutine))
-    stash->inliner_chain = function;
+  *function_ptr = NULL;
+  func_p = lookup_address_in_function_table (unit, addr, function_ptr);
+  if (func_p && (*function_ptr)->tag == DW_TAG_inlined_subroutine)
+    stash->inliner_chain = *function_ptr;
 
   return lookup_address_in_line_info_table (unit->line_table, addr,
                                            filename_ptr,
@@ -3631,6 +3675,7 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd,
   /* What address are we looking for?  */
   bfd_vma addr;
   struct comp_unit* each;
+  struct funcinfo *function = NULL;
   bfd_boolean found = FALSE;
   bfd_boolean do_line;
 
@@ -3713,7 +3758,7 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd,
     {
       bfd_vma min_range = (bfd_vma) -1;
       const char * local_filename = NULL;
-      const char * local_functionname = NULL;
+      struct funcinfo *local_function = NULL;
       unsigned int local_linenumber = 0;
       unsigned int local_discriminator = 0;
 
@@ -3725,7 +3770,7 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd,
                    || comp_unit_contains_address (each, addr))
                   && (range = comp_unit_find_nearest_line (each, addr,
                                                            & local_filename,
-                                                           & local_functionname,
+                                                           & local_function,
                                                            & local_linenumber,
                                                            & local_discriminator,
                                                            stash)) != 0);
@@ -3746,8 +3791,8 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd,
                {
                  if (filename_ptr && local_filename)
                    * filename_ptr = local_filename;
-                 if (functionname_ptr && local_functionname)
-                   * functionname_ptr = local_functionname;
+                 if (local_function)
+                   function = local_function;
                  if (discriminator_ptr && local_discriminator)
                    * discriminator_ptr = local_discriminator;
                  if (local_linenumber)
@@ -3849,7 +3894,7 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd,
                      || comp_unit_contains_address (each, addr))
                     && comp_unit_find_nearest_line (each, addr,
                                                     filename_ptr,
-                                                    functionname_ptr,
+                                                    &function,
                                                     linenumber_ptr,
                                                     discriminator_ptr,
                                                     stash) != 0);
@@ -3868,6 +3913,19 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd,
     }
 
  done:
+  if (function)
+    {
+      if (!function->is_linkage
+         && _bfd_elf_find_function (abfd, symbols, section, offset,
+                                    *filename_ptr ? NULL : filename_ptr,
+                                    functionname_ptr))
+       {
+         function->name = *functionname_ptr;
+         function->is_linkage = TRUE;
+       }
+      else
+       *functionname_ptr = function->name;
+    }
   if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0)
     unset_sections (stash);
 
@@ -3985,3 +4043,109 @@ _bfd_dwarf2_cleanup_debug_info (bfd *abfd, void **pinfo)
   if (stash->alt_bfd_ptr)
     bfd_close (stash->alt_bfd_ptr);
 }
+
+/* Find the function to a particular section and offset,
+   for error reporting.  */
+
+bfd_boolean
+_bfd_elf_find_function (bfd *abfd,
+                       asymbol **symbols,
+                       asection *section,
+                       bfd_vma offset,
+                       const char **filename_ptr,
+                       const char **functionname_ptr)
+{
+  struct elf_find_function_cache
+  {
+    asection *last_section;
+    asymbol *func;
+    const char *filename;
+    bfd_size_type func_size;
+  } *cache;
+
+  if (symbols == NULL)
+    return FALSE;
+
+  if (bfd_get_flavour (abfd) != bfd_target_elf_flavour)
+    return FALSE;
+
+  cache = elf_tdata (abfd)->elf_find_function_cache;
+  if (cache == NULL)
+    {
+      cache = bfd_zalloc (abfd, sizeof (*cache));
+      elf_tdata (abfd)->elf_find_function_cache = cache;
+      if (cache == NULL)
+       return FALSE;
+    }
+  if (cache->last_section != section
+      || cache->func == NULL
+      || offset < cache->func->value
+      || offset >= cache->func->value + cache->func_size)
+    {
+      asymbol *file;
+      bfd_vma low_func;
+      asymbol **p;
+      /* ??? Given multiple file symbols, it is impossible to reliably
+        choose the right file name for global symbols.  File symbols are
+        local symbols, and thus all file symbols must sort before any
+        global symbols.  The ELF spec may be interpreted to say that a
+        file symbol must sort before other local symbols, but currently
+        ld -r doesn't do this.  So, for ld -r output, it is possible to
+        make a better choice of file name for local symbols by ignoring
+        file symbols appearing after a given local symbol.  */
+      enum { nothing_seen, symbol_seen, file_after_symbol_seen } state;
+      const struct elf_backend_data *bed = get_elf_backend_data (abfd);
+
+      file = NULL;
+      low_func = 0;
+      state = nothing_seen;
+      cache->filename = NULL;
+      cache->func = NULL;
+      cache->func_size = 0;
+      cache->last_section = section;
+
+      for (p = symbols; *p != NULL; p++)
+       {
+         asymbol *sym = *p;
+         bfd_vma code_off;
+         bfd_size_type size;
+
+         if ((sym->flags & BSF_FILE) != 0)
+           {
+             file = sym;
+             if (state == symbol_seen)
+               state = file_after_symbol_seen;
+             continue;
+           }
+
+         size = bed->maybe_function_sym (sym, section, &code_off);
+         if (size != 0
+             && code_off <= offset
+             && (code_off > low_func
+                 || (code_off == low_func
+                     && size > cache->func_size)))
+           {
+             cache->func = sym;
+             cache->func_size = size;
+             cache->filename = NULL;
+             low_func = code_off;
+             if (file != NULL
+                 && ((sym->flags & BSF_LOCAL) != 0
+                     || state != file_after_symbol_seen))
+               cache->filename = bfd_asymbol_name (file);
+           }
+         if (state == nothing_seen)
+           state = symbol_seen;
+       }
+    }
+
+  if (cache->func == NULL)
+    return FALSE;
+
+  if (filename_ptr)
+    *filename_ptr = cache->filename;
+  if (functionname_ptr)
+    *functionname_ptr = bfd_asymbol_name (cache->func);
+
+  return TRUE;
+}
index c572812e8e2d753ecd8d0f34ed3ed537e501483d..f667239d6e52a796889e622e94c40ef4f1b59d42 100644 (file)
@@ -1909,6 +1909,8 @@ extern bfd_boolean _bfd_elf_find_line
   (bfd *, asymbol **, asymbol *, const char **, unsigned int *);
 extern bfd_boolean _bfd_elf_find_inliner_info
   (bfd *, const char **, const char **, unsigned int *);
+extern bfd_boolean _bfd_elf_find_function
+  (bfd *, asymbol **, asection *, bfd_vma, const char **, const char **);
 #define _bfd_elf_read_minisymbols _bfd_generic_read_minisymbols
 #define _bfd_elf_minisymbol_to_symbol _bfd_generic_minisymbol_to_symbol
 extern int _bfd_elf_sizeof_headers
index 8b207ad872a3992381e93bdfa0a75ef444651613..78da35b83efc7b116b07b4976a73db5abbcedc33 100644 (file)
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -7648,109 +7648,6 @@ _bfd_elf_set_arch_mach (bfd *abfd,
   return bfd_default_set_arch_mach (abfd, arch, machine);
 }
 
-/* Find the function to a particular section and offset,
-   for error reporting.  */
-
-static bfd_boolean
-elf_find_function (bfd *abfd,
-                  asymbol **symbols,
-                  asection *section,
-                  bfd_vma offset,
-                  const char **filename_ptr,
-                  const char **functionname_ptr)
-{
-  struct elf_find_function_cache
-  {
-    asection *last_section;
-    asymbol *func;
-    const char *filename;
-    bfd_size_type func_size;
-  } *cache;
-
-  if (symbols == NULL)
-    return FALSE;
-
-  cache = elf_tdata (abfd)->elf_find_function_cache;
-  if (cache == NULL)
-    {
-      cache = bfd_zalloc (abfd, sizeof (*cache));
-      elf_tdata (abfd)->elf_find_function_cache = cache;
-      if (cache == NULL)
-       return FALSE;
-    }
-  if (cache->last_section != section
-      || cache->func == NULL
-      || offset < cache->func->value
-      || offset >= cache->func->value + cache->func_size)
-    {
-      asymbol *file;
-      bfd_vma low_func;
-      asymbol **p;
-      /* ??? Given multiple file symbols, it is impossible to reliably
-        choose the right file name for global symbols.  File symbols are
-        local symbols, and thus all file symbols must sort before any
-        global symbols.  The ELF spec may be interpreted to say that a
-        file symbol must sort before other local symbols, but currently
-        ld -r doesn't do this.  So, for ld -r output, it is possible to
-        make a better choice of file name for local symbols by ignoring
-        file symbols appearing after a given local symbol.  */
-      enum { nothing_seen, symbol_seen, file_after_symbol_seen } state;
-      const struct elf_backend_data *bed = get_elf_backend_data (abfd);
-
-      file = NULL;
-      low_func = 0;
-      state = nothing_seen;
-      cache->filename = NULL;
-      cache->func = NULL;
-      cache->func_size = 0;
-      cache->last_section = section;
-
-      for (p = symbols; *p != NULL; p++)
-       {
-         asymbol *sym = *p;
-         bfd_vma code_off;
-         bfd_size_type size;
-
-         if ((sym->flags & BSF_FILE) != 0)
-           {
-             file = sym;
-             if (state == symbol_seen)
-               state = file_after_symbol_seen;
-             continue;
-           }
-
-         size = bed->maybe_function_sym (sym, section, &code_off);
-         if (size != 0
-             && code_off <= offset
-             && (code_off > low_func
-                 || (code_off == low_func
-                     && size > cache->func_size)))
-           {
-             cache->func = sym;
-             cache->func_size = size;
-             cache->filename = NULL;
-             low_func = code_off;
-             if (file != NULL
-                 && ((sym->flags & BSF_LOCAL) != 0
-                     || state != file_after_symbol_seen))
-               cache->filename = bfd_asymbol_name (file);
-           }
-         if (state == nothing_seen)
-           state = symbol_seen;
-       }
-    }
-
-  if (cache->func == NULL)
-    return FALSE;
-
-  if (filename_ptr)
-    *filename_ptr = cache->filename;
-  if (functionname_ptr)
-    *functionname_ptr = bfd_asymbol_name (cache->func);
-
-  return TRUE;
-}
-
 /* Find the nearest line to a particular section and offset,
    for error reporting.  */
 
@@ -7770,24 +7667,15 @@ _bfd_elf_find_nearest_line (bfd *abfd,
                                     filename_ptr, functionname_ptr,
                                     line_ptr, discriminator_ptr,
                                     dwarf_debug_sections, 0,
-                                    &elf_tdata (abfd)->dwarf2_find_line_info))
-    {
-      if (!*functionname_ptr)
-       elf_find_function (abfd, symbols, section, offset,
-                          *filename_ptr ? NULL : filename_ptr,
-                          functionname_ptr);
-
-      return TRUE;
-    }
-
-  if (_bfd_dwarf1_find_nearest_line (abfd, symbols, section, offset,
-                                    filename_ptr, functionname_ptr, line_ptr))
+                                    &elf_tdata (abfd)->dwarf2_find_line_info)
+      || _bfd_dwarf1_find_nearest_line (abfd, symbols, section, offset,
+                                       filename_ptr, functionname_ptr,
+                                       line_ptr))
     {
       if (!*functionname_ptr)
-       elf_find_function (abfd, symbols, section, offset,
-                          *filename_ptr ? NULL : filename_ptr,
-                          functionname_ptr);
-
+       _bfd_elf_find_function (abfd, symbols, section, offset,
+                               *filename_ptr ? NULL : filename_ptr,
+                               functionname_ptr);
       return TRUE;
     }
 
@@ -7802,8 +7690,8 @@ _bfd_elf_find_nearest_line (bfd *abfd,
   if (symbols == NULL)
     return FALSE;
 
-  if (! elf_find_function (abfd, symbols, section, offset,
-                          filename_ptr, functionname_ptr))
+  if (! _bfd_elf_find_function (abfd, symbols, section, offset,
+                               filename_ptr, functionname_ptr))
     return FALSE;
 
   *line_ptr = 0;