Merging robustify patches
by Mark Wielaard
Hi,
I rebased, split out and merged some smaller (indentation) changes together
into 6 commits from the robustify branch. Originally there were only 3
patches because the main patch was one big "Robustify patches from Fedora".
Hopefully the split up makes it easier to review them. A diff of master with
these patches applied and the robustify branch only shows some indention
changes (which were wrong on the branch). I kept the original authors,
but added my own Signed-off-by line.
[PATCH 1/6] robustify: Use gelf_fsize instead of relying on shdr->sh_entsize.
[PATCH 2/6] robustify: elflint.
[PATCH 3/6] robustify: readelf.
[PATCH 4/6] robustify: strip.
[PATCH 5/6] robustify: libelf.
[PATCH 6/6] robustify: libelf gelf define INVALID_NDX macro.
Please let me know if any of this looks wrong or not correct to go on master.
Thanks,
Mark
10 years, 3 months
[PATCH] tests: Reduce the total number of self-test files and add ET_REL files.
by Mark Wielaard
Some self tests would run for a really long time (especially under valgrind)
because we included all libebl backends in the list (there are 12 backends).
Now only test two explicitly. Also there were no ET_REL files in the
self test file list. So add two ET_REL files. The total number of self test
files is now 12.
run-nm-self.sh would run 4 * 3 * 3 * 22 = 792 tests (on all self test files).
Reduce the number of different files to test to 3 (one ET_EXEC, one ET_DYN
and one ET_REL file). Reducing the number of test runs to 99.
Signed-off-by: Mark Wielaard <mjw(a)redhat.com>
---
tests/ChangeLog | 7 +++++++
tests/run-nm-self.sh | 14 ++++++++++++--
tests/test-subr.sh | 11 +++++++----
3 files changed, 26 insertions(+), 6 deletions(-)
diff --git a/tests/ChangeLog b/tests/ChangeLog
index 098093a..10d173e 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -1,5 +1,12 @@
2014-01-16 Mark Wielaard <mjw(a)redhat.com>
+ * run-nm-self.sh: Don't use testrun_on_self_quiet but just testrun
+ on one ET_REL, one ET_EXEC and one ET_DYN file.
+ * test-subr.sh (self_test_files): Add two ET_REL files, only add
+ two libebl ET_DYN backend files.
+
+2014-01-16 Mark Wielaard <mjw(a)redhat.com>
+
* run-backtrace-demangle.sh: Check exitcode and max number of frames.
2014-01-15 Jan Kratochvil <jan.kratochvil(a)redhat.com>
diff --git a/tests/run-nm-self.sh b/tests/run-nm-self.sh
index d2c1246..dac8e27 100755
--- a/tests/run-nm-self.sh
+++ b/tests/run-nm-self.sh
@@ -1,5 +1,5 @@
#! /bin/sh
-# Copyright (C) 2012 Red Hat, Inc.
+# Copyright (C) 2012, 2014 Red Hat, Inc.
# This file is part of elfutils.
#
# This file is free software; you can redistribute it and/or modify
@@ -17,10 +17,20 @@
. $srcdir/test-subr.sh
+# Test different command line combinations on the nm binary itself.
+# Test on nm ET_REL, ET_EXEC and ET_DYN files.
+ET_REL=${abs_top_builddir}/src/nm.o
+ET_EXEC=${abs_top_builddir}/src/nm
+ET_DYN=${abs_top_builddir}/libelf/libelf.so
for what_arg in --debug-syms --defined-only --dynamic --extern-only; do
for format_arg in --format=bsd --format=sysv --format=posix; do
for out_arg in --numeric-sort --no-sort --reverse-sort; do
- testrun_on_self_quiet ${abs_top_builddir}/src/nm $what_arg $format_arg $out_arg
+ for self_file in $ET_REL $ET_EXEC $ET_DYN; do
+ # --dynamic doesn't make sense for ET_REL.
+ if ! test "$what_arg" == "--dynamic" -a "$self_file" == "$ET_REL"; then
+ testrun ${abs_top_builddir}/src/nm $what_arg $format_arg $out_arg $self_file > /dev/null
+ fi
+ done
done
done
done
diff --git a/tests/test-subr.sh b/tests/test-subr.sh
index b5ab105..5e796b4 100644
--- a/tests/test-subr.sh
+++ b/tests/test-subr.sh
@@ -1,5 +1,5 @@
#! /bin/sh
-# Copyright (C) 2005-2013 Red Hat, Inc.
+# Copyright (C) 2005-2014 Red Hat, Inc.
# This file is part of elfutils.
#
# This file is free software; you can redistribute it and/or modify
@@ -118,9 +118,12 @@ program_transform()
self_test_files=`echo ${abs_top_builddir}/src/addr2line \
${abs_top_builddir}/src/elfcmp ${abs_top_builddir}/src/elflint \
${abs_top_builddir}/src/nm ${abs_top_builddir}/src/objdump \
-${abs_top_builddir}/src/readelf ${abs_top_builddir}/src/size \
-${abs_top_builddir}/src/strip ${abs_top_builddir}/libelf/libelf.so \
-${abs_top_builddir}/libdw/libdw.so ${abs_top_builddir}/backends/libebl_*.so`
+${abs_top_builddir}/src/readelf \
+${abs_top_builddir}/src/size.o ${abs_top_builddir}/src/strip.o \
+${abs_top_builddir}/libelf/libelf.so \
+${abs_top_builddir}/libdw/libdw.so \
+${abs_top_builddir}/backends/libebl_i386.so \
+${abs_top_builddir}/backends/libebl_x86_64.so`
# Provide a command to run on all self-test files with testrun.
testrun_on_self()
--
1.7.1
10 years, 3 months
[PATCH] tests: run-backtrace-demangle.sh check exitcode and max number of frames.
by Mark Wielaard
There can be more than 3 frames, but depending on the system/installed
glibc we might not be able to unwind fully till the end.
cxxfunc -> f -> main
Expect to see the top two and a warning that there are more frames
(exit code 1)
Signed-off-by: Mark Wielaard <mjw(a)redhat.com>
---
tests/ChangeLog | 4 ++++
tests/run-backtrace-demangle.sh | 13 +++++++++++--
2 files changed, 15 insertions(+), 2 deletions(-)
diff --git a/tests/ChangeLog b/tests/ChangeLog
index 1b84f3a..098093a 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -1,3 +1,7 @@
+2014-01-16 Mark Wielaard <mjw(a)redhat.com>
+
+ * run-backtrace-demangle.sh: Check exitcode and max number of frames.
+
2014-01-15 Jan Kratochvil <jan.kratochvil(a)redhat.com>
Fix corruption of non-C++ symbols by the demangler.
diff --git a/tests/run-backtrace-demangle.sh b/tests/run-backtrace-demangle.sh
index b5bddeb..6e18e77 100755
--- a/tests/run-backtrace-demangle.sh
+++ b/tests/run-backtrace-demangle.sh
@@ -20,13 +20,22 @@ if test -n "$ELFUTILS_DISABLE_DEMANGLE"; then
fi
. $srcdir/backtrace-subr.sh
-set -x
child=testfile-backtrace-demangle
testfiles $child{,.core}
tempfiles $child.{bt,err}
-testrun ${abs_top_builddir}/src/stack -e $child --core $child.core >$child.bt 2>$child.err
+
+# There can be more than 3 frames, but depending on the system/installed
+# glibc we might not be able to unwind fully till the end.
+# cxxfunc -> f -> main
+# Expect to see the top two and a warning that there are more frames
+# (exit code 1)
+testrun ${abs_top_builddir}/src/stack -n 2 -e $child --core $child.core >$child.bt 2>$child.err || exitcode=$?
cat $child.{bt,err}
+if test $exitcode != 1 || ! grep "shown max number of frames" $child.err; then
+ echo >&2 $2: expected more than 2 frames
+ false
+fi
if ! grep -w f $child.bt; then
echo >&2 $2: no f
false
--
1.7.1
10 years, 3 months
Fix false FAILs on testsuite with ulimit -c unlimited.
by Jan Kratochvil
Hi,
(ulimit -c unlimited;make check)
FAIL: run-backtrace-native.sh
FAIL: run-backtrace-native-biarch.sh
tests/run-backtrace-native.sh.log
rmdir: failed to remove 'test-21522': Directory not empty
tests/test-21522/core.21602
Core was generated by `/home/jkratoch/redhat/elfutils/tests/backtrace-child --ptraceme'.
#2 0x00007f19405fb079 in main (argc=2, argv=0x7fff6d8bf1d8) at backtrace-child.c:222
222 abort ();
(gdb) l
217 if (gencore)
218 pthread_join (thread, NULL);
219 else
220 raise (SIGUSR2);
221 /* Not reached. */
222 abort ();
223 }
Probably obvious.
Thanks,
Jan
>From 9909d959fe48b08682760ba8a615ccc87423f638 Mon Sep 17 00:00:00 2001
From: Jan Kratochvil <jan.kratochvil(a)redhat.com>
Date: Wed, 15 Jan 2014 14:16:13 +0100
Subject: [PATCH] Fix false FAILs on testsuite with ulimit -c unlimited.
tests/
2014-01-15 Jan Kratochvil <jan.kratochvil(a)redhat.com>
Fix false FAILs on testsuite with ulimit -c unlimited.
* backtrace.c (exec_dump): Call kill for PID.
Signed-off-by: Jan Kratochvil <jan.kratochvil(a)redhat.com>
---
tests/backtrace.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/tests/backtrace.c b/tests/backtrace.c
index 758dfed..4ac7910 100644
--- a/tests/backtrace.c
+++ b/tests/backtrace.c
@@ -392,6 +392,7 @@ exec_dump (const char *exec)
dwfl = pid_to_dwfl (pid);
dump (dwfl);
dwfl_end (dwfl);
+ kill (pid, SIGKILL);
}
#define OPT_BACKTRACE_EXEC 0x100
--
1.8.4.2
10 years, 3 months
[PATCH] backends: aarch64_check_special_symbol check shdr is not NULL before usage.
by Mark Wielaard
Signed-off-by: Mark Wielaard <mjw(a)redhat.com>
---
backends/ChangeLog | 5 +++++
backends/aarch64_symbol.c | 9 ++++++---
2 files changed, 11 insertions(+), 3 deletions(-)
diff --git a/backends/ChangeLog b/backends/ChangeLog
index 4ea1acd..a742eb2 100644
--- a/backends/ChangeLog
+++ b/backends/ChangeLog
@@ -1,3 +1,8 @@
+2014-01-14 Mark Wielaard <mjw(a)redhat.com>
+
+ * aarch64_symbol.c (aarch64_check_special_symbol): Check shdr is
+ not NULL before usage.
+
2014-01-04 Mark Wielaard <mjw(a)redhat.com>
* ppc64_symbol.c (ppc64_machine_flag_check): New function.
diff --git a/backends/aarch64_symbol.c b/backends/aarch64_symbol.c
index e41a7a7..3fdc9cf 100644
--- a/backends/aarch64_symbol.c
+++ b/backends/aarch64_symbol.c
@@ -73,9 +73,12 @@ aarch64_check_special_symbol (Elf *elf, GElf_Ehdr *ehdr, const GElf_Sym *sym,
{
GElf_Shdr shdr_mem;
GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
- sname = elf_strptr (elf, ehdr->e_shstrndx, shdr->sh_name);
- if (sname != NULL && strcmp (sname, ".got") == 0)
- return sym->st_value == shdr->sh_addr;
+ if (shdr != NULL)
+ {
+ sname = elf_strptr (elf, ehdr->e_shstrndx, shdr->sh_name);
+ if (sname != NULL && strcmp (sname, ".got") == 0)
+ return sym->st_value == shdr->sh_addr;
+ }
}
}
}
--
1.8.4.2
10 years, 3 months
[PATCH] readelf: print_debug_macro_section clear vendor array before use.
by Mark Wielaard
Not setting a vendor code before use would be invalid which we tried to
catch. But to detect that we do need to initialize the vendor array to
zero first.
Signed-off-by: Mark Wielaard <mjw(a)redhat.com>
---
src/ChangeLog | 5 +++++
src/readelf.c | 1 +
2 files changed, 6 insertions(+)
diff --git a/src/ChangeLog b/src/ChangeLog
index d37cd1b..906f644 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,8 @@
+2014-01-14 Mark Wielaard <mjw(a)redhat.com>
+
+ * readelf.c (print_debug_macro_section): Clear vendor array before
+ use.
+
2014-01-02 Mark Wielaard <mjw(a)redhat.com>
* stack.c (show_raw): Declare unconditionally.
diff --git a/src/readelf.c b/src/readelf.c
index 739156c..3991224 100644
--- a/src/readelf.c
+++ b/src/readelf.c
@@ -6896,6 +6896,7 @@ print_debug_macro_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
}
const unsigned char *vendor[DW_MACRO_GNU_hi_user - DW_MACRO_GNU_lo_user];
+ memset (vendor, 0, sizeof vendor);
if (flag & 0x04)
{
// 1 byte length, for each item, 1 byte opcode, uleb128 number
--
1.8.4.2
10 years, 3 months
[PATCH] lib: Add missing config.h #include to crc32_file.c.
by Lei Zhang
Hi,
We have a large binary on a 32-bit host where the following command failed:
eu-strip -o foo.stripped -f foo.debug foo
eu-strip: while computing checksum for debug information: Invalid argument
Here, foo.debug is over 2 GB. The crc code called pread() with a
negative offset because crc32_file.c does not have LFS, off_t is only
32-bit, and the offset variable overflowed.
10 years, 3 months
[patch] Fix corruption of non-C++ symbols by the demangler
by Jan Kratochvil
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(a)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(a)redhat.com>
* configure.ac: Add AC_PROG_CXX.
src/
2014-01-13 Jan Kratochvil <jan.kratochvil(a)redhat.com>
* stack.c (print_frames) <USE_DEMANGLE>: Check for _Z.
tests/
2014-01-13 Jan Kratochvil <jan.kratochvil(a)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(a)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
10 years, 3 months
[PATCH] stack: Add new '-n MAXFRAMES' option. Resolve addresses after unwind.
by Mark Wielaard
Limit the number of frames printed per thread (defaults to 64) and resolve
addresses to names, modules and source after unwinding so the thread is
only stopped for the minimum time needed to do the actual unwinding. The
thread doesn't need to wait for the lookups and printing of information.
Signed-off-by: Mark Wielaard <mjw(a)redhat.com>
---
src/ChangeLog | 16 +++++
src/stack.c | 174 ++++++++++++++++++++++++++++++++++++---------------------
2 files changed, 127 insertions(+), 63 deletions(-)
diff --git a/src/ChangeLog b/src/ChangeLog
index 0e6d2dc..d3d6807 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,19 @@
+2013-12-22 Mark Wielaard <mjw(a)redhat.com>
+
+ * stack.c (maxframes): New static unsigned. Initialize to 64.
+ (struct frame): New struct.
+ (struct frames): Likewise.
+ (dwfl): New static Dwfl pointer.
+ (frame_callback): Use arg as struct frames and fill it next frame.
+ Return DWARF_CB_ABORT when maxframes has been reached. Move
+ printing of frame to...
+ (print_frames): ...here. New function.
+ (thread_callback): Use arg as struct frames and set frames to zero.
+ Call print_frames.
+ (parse_opt): Handle '-n'.
+ (main): Add -n to options. Allocate frames using maxframes. Pass
+ frames to frame_callback and thread_callback.
+
2013-12-20 Mark Wielaard <mjw(a)redhat.com>
* stack.c (show_one_tid): New static boolean.
diff --git a/src/stack.c b/src/stack.c
index 512c85b..188aa00 100644
--- a/src/stack.c
+++ b/src/stack.c
@@ -41,91 +41,122 @@ static bool show_module = false;
static bool show_source = false;
static bool show_one_tid = false;
-static int
-frame_callback (Dwfl_Frame *state, void *arg)
+static unsigned maxframes = 64;
+
+struct frame
{
- unsigned *framenop = arg;
Dwarf_Addr pc;
bool isactivation;
- if (! dwfl_frame_pc (state, &pc, &isactivation))
+};
+
+struct frames
+{
+ unsigned frames;
+ struct frame frame[];
+};
+
+static Dwfl *dwfl = NULL;
+
+static int
+frame_callback (Dwfl_Frame *state, void *arg)
+{
+ struct frames *frames = (struct frames *) arg;
+ unsigned nr = frames->frames;
+ if (! dwfl_frame_pc (state, &frames->frame[nr].pc,
+ &frames->frame[nr].isactivation))
{
error (0, 0, "%s", dwfl_errmsg (-1));
return DWARF_CB_ABORT;
}
- Dwarf_Addr pc_adjusted = pc - (isactivation ? 0 : 1);
-
- /* Get PC->SYMNAME. */
- Dwfl *dwfl = dwfl_thread_dwfl (dwfl_frame_thread (state));
- Dwfl_Module *mod = dwfl_addrmodule (dwfl, pc_adjusted);
- const char *symname = NULL;
- if (mod)
- symname = dwfl_module_addrname (mod, pc_adjusted);
-
- // Try to find the address wide if possible.
- static int width = 0;
- if (width == 0 && mod)
+
+ frames->frames++;
+ if (frames->frames == maxframes)
+ return DWARF_CB_ABORT;
+
+ return DWARF_CB_OK;
+}
+
+static void
+print_frames (struct frames *frames)
+{
+ for (unsigned nr = 0; nr < frames->frames; nr++)
{
- Dwarf_Addr bias;
- Elf *elf = dwfl_module_getelf (mod, &bias);
- if (elf)
+ Dwarf_Addr pc = frames->frame[nr].pc;
+ bool isactivation = frames->frame[nr].isactivation;
+ Dwarf_Addr pc_adjusted = pc - (isactivation ? 0 : 1);
+
+ /* Get PC->SYMNAME. */
+ Dwfl_Module *mod = dwfl_addrmodule (dwfl, pc_adjusted);
+ const char *symname = NULL;
+ if (mod)
+ symname = dwfl_module_addrname (mod, pc_adjusted);
+
+ // Try to find the address wide if possible.
+ static int width = 0;
+ if (width == 0 && mod)
{
- GElf_Ehdr ehdr_mem;
- GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
- if (ehdr)
- width = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 8 : 16;
+ Dwarf_Addr bias;
+ Elf *elf = dwfl_module_getelf (mod, &bias);
+ if (elf)
+ {
+ GElf_Ehdr ehdr_mem;
+ GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
+ if (ehdr)
+ width = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 8 : 16;
+ }
}
- }
- if (width == 0)
- width = 16;
+ if (width == 0)
+ width = 16;
- printf ("#%-2u 0x%0*" PRIx64, (*framenop)++, width, (uint64_t) pc);
+ printf ("#%-2u 0x%0*" PRIx64, nr, width, (uint64_t) pc);
- if (show_activation)
- printf ("%4s", ! isactivation ? "- 1" : "");
+ if (show_activation)
+ printf ("%4s", ! isactivation ? "- 1" : "");
- if (symname != NULL)
- printf (" %s", symname);
+ if (symname != NULL)
+ printf (" %s", symname);
- if (show_module)
- {
- const char* fname;
-
- fname = dwfl_module_info(mod, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
- if (fname != NULL)
- printf (" - %s", fname);
- }
+ if (show_module)
+ {
+ const char* fname;
+ fname = dwfl_module_info(mod,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL);
+ if (fname != NULL)
+ printf (" - %s", fname);
+ }
- if (show_source)
- {
- Dwfl_Line *lineobj = dwfl_module_getsrc(mod, pc_adjusted);
- if (lineobj)
+ if (show_source)
{
- int line, col;
- const char* sname;
- line = col = -1;
- sname = dwfl_lineinfo (lineobj, NULL, &line, &col, NULL, NULL);
- if (sname != NULL)
+ Dwfl_Line *lineobj = dwfl_module_getsrc(mod, pc_adjusted);
+ if (lineobj)
{
- printf ("\n %s", sname);
- if (line > 0)
+ int line, col;
+ const char* sname;
+ line = col = -1;
+ sname = dwfl_lineinfo (lineobj, NULL, &line, &col, NULL, NULL);
+ if (sname != NULL)
{
- printf (":%d", line);
- if (col > 0)
- printf (":%d", col);
+ printf ("\n %s", sname);
+ if (line > 0)
+ {
+ printf (":%d", line);
+ if (col > 0)
+ printf (":%d", col);
+ }
}
}
}
+ printf ("\n");
}
- printf ("\n");
- return DWARF_CB_OK;
}
static int
-thread_callback (Dwfl_Thread *thread, void *thread_arg __attribute__ ((unused)))
+thread_callback (Dwfl_Thread *thread, void *thread_arg)
{
printf ("TID %ld:\n", (long) dwfl_thread_tid (thread));
- unsigned frameno = 0;
- switch (dwfl_thread_getframes (thread, frame_callback, &frameno))
+ struct frames *frames = (struct frames *) thread_arg;
+ frames->frames = 0;
+ switch (dwfl_thread_getframes (thread, frame_callback, thread_arg))
{
case DWARF_CB_OK:
case DWARF_CB_ABORT:
@@ -136,6 +167,7 @@ thread_callback (Dwfl_Thread *thread, void *thread_arg __attribute__ ((unused)))
default:
abort ();
}
+ print_frames (frames);
return DWARF_CB_OK;
}
@@ -175,6 +207,15 @@ parse_opt (int key, char *arg __attribute__ ((unused)),
show_one_tid = true;
break;
+ case 'n':
+ maxframes = atoi (arg);
+ if (maxframes == 0)
+ {
+ argp_error (state, N_("-n MAXFRAMES should be 1 or higher."));
+ return EINVAL;
+ }
+ break;
+
default:
return ARGP_ERR_UNKNOWN;
}
@@ -204,6 +245,8 @@ main (int argc, char **argv)
N_("Show all additional information (activation, module and source)"), 0 },
{ NULL, '1', NULL, 0,
N_("Show the backtrace of only one thread"), 0 },
+ { NULL, 'n', "MAXFRAMES", 0,
+ N_("Show at most MAXFRAMES per thread (defaults to 64)"), 0 },
{ NULL, 0, NULL, 0, NULL, 0 }
};
@@ -224,11 +267,11 @@ Only real user processes are supported, no kernel or process maps."),
};
int remaining;
- Dwfl *dwfl = NULL;
argp_parse (&argp, argc, argv, 0, &remaining, &dwfl);
assert (dwfl != NULL);
if (remaining != argc)
- error (2, 0, "eu-stack [-a] [-m] [-s] [-v] [-1] [--debuginfo-path=<path>]"
+ error (2, 0, "eu-stack [-a] [-m] [-s] [-v] [-1] [-n MAXFRAMES]"
+ " [--debuginfo-path=<path>]"
" {-p <process id>|--core=<file> [--executable=<file>]|--help}");
/* dwfl_linux_proc_report has been already called from dwfl_standard_argp's
@@ -236,11 +279,14 @@ Only real user processes are supported, no kernel or process maps."),
if (dwfl_report_end (dwfl, NULL, NULL) != 0)
error (2, 0, "dwfl_report_end: %s", dwfl_errmsg (-1));
+ struct frames *frames = malloc (sizeof (struct frames)
+ + sizeof (struct frame) * maxframes);
+ frames->frames = 0;
+
if (show_one_tid)
{
pid_t tid = dwfl_pid (dwfl);
- unsigned frameno = 0;
- switch (dwfl_getthread_frames (dwfl, tid, frame_callback, &frameno))
+ switch (dwfl_getthread_frames (dwfl, tid, frame_callback, frames))
{
case DWARF_CB_OK:
break;
@@ -251,10 +297,11 @@ Only real user processes are supported, no kernel or process maps."),
default:
abort ();
}
+ print_frames (frames);
}
else
{
- switch (dwfl_getthreads (dwfl, thread_callback, NULL))
+ switch (dwfl_getthreads (dwfl, thread_callback, frames))
{
case DWARF_CB_OK:
break;
@@ -265,6 +312,7 @@ Only real user processes are supported, no kernel or process maps."),
abort ();
}
}
+ free (frames);
dwfl_end (dwfl);
return 0;
--
1.7.1
10 years, 3 months
[patch] handle core file names without a pid suffix
by Matthias Klose
The following fix is needed when /proc/sys/kernel/core_uses_pid is set to 0. try
to rename the core file, and if it does still fail, skip the test.
Matthias
--- elfutils-0.158.orig/tests/backtrace-subr.sh
+++ elfutils-0.158/tests/backtrace-subr.sh
@@ -111,6 +111,11 @@ check_native_core()
# Skip the test if we cannot adjust core ulimit.
core="core.`ulimit -c unlimited || exit 77; set +ex; testrun
${abs_builddir}/$child --gencore; true`"
+ # see if /proc/sys/kernel/core_uses_pid is set to 0
+ if [ -f core ]; then
+ mv core "$core"
+ fi
+ if [ ! -f "$core" ]; then exit 77; fi
if [ "x$SAVED_VALGRIND_CMD" != "x" ]; then
VALGRIND_CMD="$SAVED_VALGRIND_CMD"
10 years, 4 months