This is the mail archive of the elfutils-devel@sourceware.org mailing list for the elfutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[patch] Fix corruption of non-C++ symbols by the demangler


Hi,

jankratochvil/demangle

for example currently plain symbol "f" (for function f()) gets printed in the
backtrace as "float" (as for a function float()).

libiberty/cp-demangle.c contains:

d_demangle_callback()
  if (mangled[0] == '_' && mangled[1] == 'Z')
    type = DCT_MANGLED;
  else if (strncmp (mangled, "_GLOBAL_", 8) == 0
           && (mangled[8] == '.' || mangled[8] == '_' || mangled[8] == '$')
           && (mangled[9] == 'D' || mangled[9] == 'I')
           && mangled[10] == '_')
    type = mangled[9] == 'I' ? DCT_GLOBAL_CTORS : DCT_GLOBAL_DTORS;
  else
    {
      if ((options & DMGL_TYPES) == 0)
        return 0;
      type = DCT_TYPE;
    }

I am not completely sure about DCT_GLOBAL_CTORS and DCT_GLOBAL_DTORS but I
could not find a compliant symbol without leading _Z for it.

DCT_TYPE is apparently inappropriate for the unwinder.


Thanks,
Jan

commit e1b6b9d3131f32ef54932388c814adc02ca6a329
Author: Jan Kratochvil <jan.kratochvil@redhat.com>
Date:   Mon Jan 13 23:04:03 2014 +0100

    Fix corruption of non-C++ symbols by the demangler.
    
    ./
    2014-01-13  Jan Kratochvil  <jan.kratochvil@redhat.com>
    
    	* configure.ac: Add AC_PROG_CXX.
    
    src/
    2014-01-13  Jan Kratochvil  <jan.kratochvil@redhat.com>
    
    	* stack.c (print_frames) <USE_DEMANGLE>: Check for _Z.
    
    tests/
    2014-01-13  Jan Kratochvil  <jan.kratochvil@redhat.com>
    
    	* Makefile.am (check_PROGRAMS): Add backtrace-demangle.
    	(TESTS): Add run-backtrace-demangle.sh.
    	<!DEMANGLE>: Add ELFUTILS_DISABLE_DEMANGLE export.
    	(EXTRA_DIST): Add run-backtrace-demangle.sh
    	(backtrace_demangle_SOURCES): New.
    	* backtrace-demangle.cc: New file.
    	* run-backtrace-demangle.sh: New file.
    
    Signed-off-by: Jan Kratochvil <jan.kratochvil@redhat.com>

diff --git a/configure.ac b/configure.ac
index 7bfa1da..0e4e0ba 100644
--- a/configure.ac
+++ b/configure.ac
@@ -81,6 +81,7 @@ AS_IF([test "$enable_dwz" = no -a -d /usr/lib/debug/.dwz],
 AH_TEMPLATE([ENABLE_DWZ], [Defined if libdw should support GNU ref_alt FORM, dwz multi files.])
 
 AC_PROG_CC
+AC_PROG_CXX
 AC_PROG_RANLIB
 AC_PROG_YACC
 AM_PROG_LEX
diff --git a/src/stack.c b/src/stack.c
index fdf4b07..275be08 100644
--- a/src/stack.c
+++ b/src/stack.c
@@ -1,5 +1,5 @@
 /* Unwinding of frames like gstack/pstack.
-   Copyright (C) 2013 Red Hat, Inc.
+   Copyright (C) 2013-2014 Red Hat, Inc.
    This file is part of elfutils.
 
    This file is free software; you can redistribute it and/or modify
@@ -220,7 +220,8 @@ print_frames (struct frames *frames, pid_t tid, int dwflerr, const char *what)
       if (symname != NULL)
 	{
 #ifdef USE_DEMANGLE
-	  if (! show_raw)
+	  // Require GNU v3 ABI by the "_Z" prefix.
+	  if (! show_raw && symname[0] == '_' && symname[1] == 'Z')
 	    {
 	      int status = -1;
 	      char *dsymname = __cxa_demangle (symname, demangle_buffer,
diff --git a/tests/Makefile.am b/tests/Makefile.am
index eae64a8..f9fd18a 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -1,6 +1,6 @@
 ## Process this file with automake to create Makefile.in
 ##
-## Copyright (C) 1996-2013 Red Hat, Inc.
+## Copyright (C) 1996-2014 Red Hat, Inc.
 ## This file is part of elfutils.
 ##
 ## This file is free software; you can redistribute it and/or modify
@@ -53,7 +53,7 @@ check_PROGRAMS = arextract arsymtest newfile saridx scnnames sectiondump \
 		  alldts md5-sha1-test typeiter typeiter2 low_high_pc \
 		  test-elf_cntl_gelf_getshdr dwflsyms dwfllines \
 		  dwfl-report-elf-align varlocs backtrace backtrace-child \
-		  backtrace-data backtrace-dwarf
+		  backtrace-data backtrace-dwarf backtrace-demangle
 asm_TESTS = asm-tst1 asm-tst2 asm-tst3 asm-tst4 asm-tst5 \
 	    asm-tst6 asm-tst7 asm-tst8 asm-tst9
 
@@ -107,12 +107,17 @@ TESTS = run-arextract.sh run-arsymtest.sh newfile test-nlist \
 	run-backtrace-native-biarch.sh run-backtrace-native-core.sh \
 	run-backtrace-native-core-biarch.sh run-backtrace-core-x86_64.sh \
 	run-backtrace-core-i386.sh run-backtrace-core-ppc.sh \
-	run-backtrace-core-s390x.sh run-backtrace-core-s390.sh
+	run-backtrace-core-s390x.sh run-backtrace-core-s390.sh \
+	run-backtrace-demangle.sh
 
 if !BIARCH
 export ELFUTILS_DISABLE_BIARCH = 1
 endif
 
+if !DEMANGLE
+export ELFUTILS_DISABLE_DEMANGLE = 1
+endif
+
 if !STANDALONE
 check_PROGRAMS += msg_tst md5-sha1-test
 TESTS += msg_tst md5-sha1-test
@@ -256,7 +261,8 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh \
 	     run-backtrace-core-ppc.sh testfile66.bz2 testfile66.core.bz2 \
 	     backtrace.s390x.core.bz2 backtrace.s390x.exec.bz2 \
 	     backtrace.s390.core.bz2 backtrace.s390.exec.bz2 \
-	     run-backtrace-core-s390x.sh run-backtrace-core-s390.sh
+	     run-backtrace-core-s390x.sh run-backtrace-core-s390.sh \
+	     run-backtrace-demangle.sh
 
 if USE_VALGRIND
 valgrind_cmd='valgrind -q --error-exitcode=1 --run-libc-freeres=no'
@@ -393,6 +399,7 @@ backtrace_child_biarch_SOURCES = backtrace-child.c
 backtrace_data_LDADD = $(libdw) $(libelf) $(libmudflap)
 backtrace_dwarf_CFLAGS = -Wno-unused-parameter
 backtrace_dwarf_LDADD = $(libdw) $(libelf) $(libmudflap)
+backtrace_demangle_SOURCES = backtrace-demangle.cc
 
 if GCOV
 check: check-am coverage
diff --git a/tests/backtrace-demangle.cc b/tests/backtrace-demangle.cc
new file mode 100644
index 0000000..5f9c075
--- /dev/null
+++ b/tests/backtrace-demangle.cc
@@ -0,0 +1,49 @@
+/* Test program for C++ demangled unwinding.
+   Copyright (C) 2014 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file 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.
+
+   elfutils 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/>.  */
+
+#include <unistd.h>
+
+#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)
+#define NOINLINE_NOCLONE __attribute__ ((noinline, noclone))
+#else
+#define NOINLINE_NOCLONE __attribute__ ((noinline))
+#endif
+
+static void NOINLINE_NOCLONE
+cxxfunc (int i)
+{
+  sleep (60);
+  // Avoid tail call optimization.
+  asm volatile ("");
+}
+
+extern "C"
+{
+  static void NOINLINE_NOCLONE
+  f (void)
+  {
+    cxxfunc(1);
+    // Avoid tail call optimization.
+    asm volatile ("");
+  }
+}
+
+int
+main()
+{
+  f();
+}
diff --git a/tests/run-backtrace-demangle.sh b/tests/run-backtrace-demangle.sh
new file mode 100755
index 0000000..aeb4eeb
--- /dev/null
+++ b/tests/run-backtrace-demangle.sh
@@ -0,0 +1,39 @@
+#! /bin/bash
+# Copyright (C) 2014 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file 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.
+#
+# elfutils 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/>.
+
+if test -n "$ELFUTILS_DISABLE_DEMANGLE"; then
+  exit 77
+fi
+
+. $srcdir/backtrace-subr.sh
+
+child=backtrace-demangle
+tempfiles $child.{bt,err}
+${abs_builddir}/$child & pid=$!
+sleep 1
+testrun ${abs_top_builddir}/src/stack -p $pid >$child.bt 2>$child.err
+kill -9 $pid
+cat $child.{bt,err}
+check_unsupported $child.err $child
+if ! grep -w f $child.bt; then
+  echo >&2 $2: no f
+  false
+fi
+if ! grep ' cxxfunc(int)' $child.bt; then
+  echo >&2 $2: no cxxfunc
+  false
+fi

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]