addr2line vs. inlined C functions called from C++
authorAlan Modra <amodra@gmail.com>
Wed, 2 Dec 2015 05:16:48 +0000 (15:46 +1030)
committerAlan Modra <amodra@gmail.com>
Wed, 2 Dec 2015 13:25:51 +0000 (23:55 +1030)
In this case the inlined function doesn't have DW_AT_linkage_name in
.debug_info, but the language is C++ so find_nearest_line goes looking
in the symbol table.  Since the function is inlined the enclosing
non-inline function symbol is returned from _bfd_elf_find_function,
which is wrong.  This patch only uses a symbol if its address matches.

PR binutils/19315
* dwarf2.c (_bfd_elf_find_function): Return symbol matched.
(_bfd_dwarf2_find_nearest_line): Check symbol returned above
against dwarf range.
* elf-bfd.h (_bfd_elf_find_function): Update prototype.

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

index fbbea1d..cc3cc2b 100644 (file)
@@ -1,5 +1,13 @@
 2015-12-02  Alan Modra  <amodra@gmail.com>
 
+       PR binutils/19315
+       * dwarf2.c (_bfd_elf_find_function): Return symbol matched.
+       (_bfd_dwarf2_find_nearest_line): Check symbol returned above
+       against dwarf range.
+       * elf-bfd.h (_bfd_elf_find_function): Update prototype.
+
+2015-12-02  Alan Modra  <amodra@gmail.com>
+
        * elf64-ppc.c (ppc64_elf_tls_optimize): Don't segfault on NULL
        symbol section or output section.
        (ppc64_elf_edit_toc): Similarly for ld -R objects.
index 401ec43..176f018 100644 (file)
@@ -4129,16 +4129,25 @@ _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))
+      if (!function->is_linkage)
        {
-         function->name = *functionname_ptr;
+         asymbol *fun;
+         bfd_vma sec_vma;
+
+         fun = _bfd_elf_find_function (abfd, symbols, section, offset,
+                                       *filename_ptr ? NULL : filename_ptr,
+                                       functionname_ptr);
+         sec_vma = section->vma;
+         if (section->output_section != NULL)
+           sec_vma = section->output_section->vma + section->output_offset;
+         if (fun != NULL
+             && fun->value + sec_vma == function->arange.low)
+           function->name = *functionname_ptr;
+         /* Even if we didn't find a linkage name, say that we have
+            to stop a repeated search of symbols.  */
          function->is_linkage = TRUE;
        }
-      else
-       *functionname_ptr = function->name;
+      *functionname_ptr = function->name;
     }
   if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0)
     unset_sections (stash);
@@ -4261,7 +4270,7 @@ _bfd_dwarf2_cleanup_debug_info (bfd *abfd, void **pinfo)
 /* Find the function to a particular section and offset,
    for error reporting.  */
 
-bfd_boolean
+asymbol *
 _bfd_elf_find_function (bfd *abfd,
                        asymbol **symbols,
                        asection *section,
@@ -4278,10 +4287,10 @@ _bfd_elf_find_function (bfd *abfd,
   } *cache;
 
   if (symbols == NULL)
-    return FALSE;
+    return NULL;
 
   if (bfd_get_flavour (abfd) != bfd_target_elf_flavour)
-    return FALSE;
+    return NULL;
 
   cache = elf_tdata (abfd)->elf_find_function_cache;
   if (cache == NULL)
@@ -4289,7 +4298,7 @@ _bfd_elf_find_function (bfd *abfd,
       cache = bfd_zalloc (abfd, sizeof (*cache));
       elf_tdata (abfd)->elf_find_function_cache = cache;
       if (cache == NULL)
-       return FALSE;
+       return NULL;
     }
   if (cache->last_section != section
       || cache->func == NULL
@@ -4354,12 +4363,12 @@ _bfd_elf_find_function (bfd *abfd,
     }
 
   if (cache->func == NULL)
-    return FALSE;
+    return NULL;
 
   if (filename_ptr)
     *filename_ptr = cache->filename;
   if (functionname_ptr)
     *functionname_ptr = bfd_asymbol_name (cache->func);
 
-  return TRUE;
+  return cache->func;
 }
index 2b05089..70e3327 100644 (file)
@@ -1996,7 +1996,7 @@ 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
+extern asymbol *_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