Bug 17541 - addr2line: function names in anonymous namespaces are incorrectly reported.
Summary: addr2line: function names in anonymous namespaces are incorrectly reported.
Status: RESOLVED FIXED
Alias: None
Product: binutils
Classification: Unclassified
Component: binutils (show other bugs)
Version: 2.25
: P2 normal
Target Milestone: 2.26
Assignee: Alan Modra
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2014-11-04 05:28 UTC by John Steele Scott
Modified: 2015-02-11 12:48 UTC (History)
0 users

See Also:
Host:
Target:
Build:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description John Steele Scott 2014-11-04 05:28:53 UTC
When addr2line is asked to print a function name for a C++ method in an anonymous namespace, it prints only the method name. It does not include the namespace, class, or method argument list. This occurs regardless of whether the --demangle argument is given on the command line. This means there is no way to get the correct mangled name from addr2line.

Testcase:

jscott@citra:/tmp$ cat foo.cpp 
#include <stdio.h>
#include <execinfo.h>

namespace ns {
namespace {

class A
{
public:
  A (int x);

private:
  int m_x;
};

A::A (int x) : m_x(x)
{
  void *bt_buffer[10];
  int depth = ::backtrace(bt_buffer, sizeof(bt_buffer)/sizeof(bt_buffer[0]));
  char **bt = ::backtrace_symbols(bt_buffer, depth);
  ::printf("%s\n", *bt);
}

} /* unnamed namespace */
} /* namespace ns */

int main (void)
{
  ns::A a(1);
  return 0;
}
jscott@citra:/tmp$ g++ -o foo -g foo.cpp -O0 -Wall -Wextra
jscott@citra:/tmp$ ./foo | sed -ne 's/.*\[\(.*\)\].*/\1/p' | addr2line -f --exe ./foo -C
A
/tmp/foo.cpp:19



This issue occurs with at least the following versions:
2.25.51.20141103 (git)
GNU addr2line (GNU Binutils for Ubuntu) 2.24
GNU addr2line version 2.23.52.0.1-8.el6 20130226

It does not occur with:
GNU addr2line version 2.20.51.0.2-5.36.el6 20100205

With this version, the above testcase (using the same binary as before, built with GCC 4.9.1) looks like:

(centos-6)jscott@citra:/tmp$ ./foo | sed -ne 's/.*\[\(.*\)\].*/\1/p' | addr2line -f --exe ./foo -C
ns::(anonymous namespace)::A::A(int)
foo.cpp:0


So it seems that with old binutils, I can get the correct function name, but the wrong line number. With the new binutils, I can get the correct line number, but the wrong function name. Any way we can fix it so I can have both? :)


[If I run my "old" addr2line against a binary built with the corresponding "old" GCC (4.4.7 on Centos 6), it shows the same wrong behaviour as the "new" addr2line: correct line number, incorrect function name. Likewise if I build with GCC 4.9.1, but with -gdwarf-2.]
Comment 1 Alan Modra 2014-12-09 10:17:59 UTC
This is because bfd/dwarf2.c doesn't decode the pertinent C++ DWARF information.

The reason the old binutils "works" when given an object compiled by a new gcc is (at a guess) due to not decoding the DWARF, and thus falling back to looking at the symbol table.
Comment 2 Sourceware Commits 2014-12-10 12:32:55 UTC
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "gdb and binutils".

The branch, master has been updated
       via  e00e81980c70659d0efe686b31a55db5faaa91f9 (commit)
      from  fa15f18deaf6f48e0b415ad3e8864de0b1cf6a39 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=e00e81980c70659d0efe686b31a55db5faaa91f9

commit e00e81980c70659d0efe686b31a55db5faaa91f9
Author: Alan Modra <amodra@gmail.com>
Date:   Wed Dec 10 09:51:56 2014 +1030

    Don't return DW_AT_name for function name in C++
    
    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.

-----------------------------------------------------------------------

Summary of changes:
 bfd/ChangeLog |   22 ++++++
 bfd/dwarf2.c  |  228 +++++++++++++++++++++++++++++++++++++++++++++++++--------
 bfd/elf-bfd.h |    2 +
 bfd/elf.c     |  130 ++------------------------------
 4 files changed, 229 insertions(+), 153 deletions(-)
Comment 3 Alan Modra 2014-12-10 12:50:00 UTC
Fixed
Comment 4 Sourceware Commits 2015-02-11 12:48:43 UTC
The binutils-2_25-branch branch has been updated by Alan Modra <amodra@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=607833ff41ae588251ee45c0653d8d31ede45970

commit 607833ff41ae588251ee45c0653d8d31ede45970
Author: Alan Modra <amodra@gmail.com>
Date:   Wed Dec 10 09:51:56 2014 +1030

    Don't return DW_AT_name for function name in C++
    
    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.