[PATCH] libdw: Try .gnu_debugaltlink paths relative to the debug file
by Josh Stone
The existing code was first trying .gnu_debugaltlink paths directly, so
relative paths would start from the current program's working directory.
That's unlikely to be useful, so it was almost always falling back to a
build-id based path.
In Fedora, these paths are relative to the debug file itself, so that's
a better thing to try first. We don't actually have the debug path in
libdw, but we can usually find it from elf->fildes and /proc/self/fd/.
Signed-off-by: Josh Stone <jistone(a)redhat.com>
---
libdw/ChangeLog | 5 +++++
libdw/dwarf_begin_elf.c | 44 +++++++++++++++++++++++++++++++++++++++++---
tests/ChangeLog | 4 ++++
tests/run-allfcts-multi.sh | 14 ++++++++++----
4 files changed, 60 insertions(+), 7 deletions(-)
diff --git a/libdw/ChangeLog b/libdw/ChangeLog
index aa7b9ca486c2..a540a5219856 100644
--- a/libdw/ChangeLog
+++ b/libdw/ChangeLog
@@ -1,3 +1,8 @@
+2013-12-14 Josh Stone <jistone(a)redhat.com>
+
+ * dwarf_begin_elf.c (build_rel_debugaltlink): New function.
+ (open_debugaltlink): Use it.
+
2013-12-10 Josh Stone <jistone(a)redhat.com>
* memory-access.h (get_uleb128_rest_return): Removed.
diff --git a/libdw/dwarf_begin_elf.c b/libdw/dwarf_begin_elf.c
index 6cf3aa17855d..eeb84c051770 100644
--- a/libdw/dwarf_begin_elf.c
+++ b/libdw/dwarf_begin_elf.c
@@ -42,8 +42,10 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
+#include <libgen.h>
#include "libdwP.h"
+#include "libelfP.h"
#if USE_ZLIB
# include <endian.h>
@@ -136,14 +138,50 @@ try_debugaltlink (Dwarf *result, const char *try_name,
return NULL;
}
+/* Make relative links into an absolute path. */
+static char *
+build_rel_debugaltlink (Dwarf *result, const char *alt_name)
+{
+ if (alt_name[0] == '/' || result->elf->fildes < 0)
+ return NULL;
+
+#define SELFFD_PREFIX "/proc/self/fd/"
+ char fd_name[sizeof SELFFD_PREFIX + 12];
+ sprintf (fd_name, "%s%d", SELFFD_PREFIX, result->elf->fildes);
+
+ /* Note, readlink(2) recommends sizing the buffer based on lstat(2), but
+ procfs always reports st_size=64, even if it's really longer. */
+ char fd_link[PATH_MAX + 1];
+ ssize_t len_link = readlink (fd_name, fd_link, sizeof fd_link);
+ if (len_link == -1 || (size_t) len_link > sizeof fd_link - 1)
+ return NULL;
+ fd_link[len_link] = '\0';
+
+ char *rel_name;
+ if (asprintf (&rel_name, "%s/%s", dirname (fd_link), alt_name) == -1)
+ return NULL;
+
+ return rel_name;
+}
+
/* For dwz multifile support, ignore if it looks wrong. */
static Dwarf *
open_debugaltlink (Dwarf *result, const char *alt_name,
const uint8_t *build_id, const size_t id_len)
{
- /* First try the name itself, it is either an absolute path or
- a relative one. Sadly we don't know relative from where at
- this point. */
+ /* First try it relative to the debug file. */
+ char *rel_name = build_rel_debugaltlink (result, alt_name);
+ if (rel_name != NULL)
+ {
+ Dwarf *alt = try_debugaltlink (result, rel_name, build_id, id_len);
+ free (rel_name);
+ if (alt != NULL)
+ return result;
+ }
+
+ /* Then try the name itself, it is either an absolute path or
+ a relative one. (Using a path relative to the tool's cwd
+ doesn't make much sense in general, but it's also harmless.) */
if (try_debugaltlink (result, alt_name, build_id, id_len) != NULL)
return result;
diff --git a/tests/ChangeLog b/tests/ChangeLog
index 008198166da6..6325a74d5915 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -1,3 +1,7 @@
+2013-12-14 Josh Stone <jistone(a)redhat.com>
+
+ * run-allfcts-multi.sh: Test relative altlinks.
+
2013-12-10 Mark Wielaard <mjw(a)redhat.com>
* Makefile.am (backtrace_child_biarch_SOURCES): New backtrace-child.c.
diff --git a/tests/run-allfcts-multi.sh b/tests/run-allfcts-multi.sh
index 727b76ee5c72..35e3177a57ae 100755
--- a/tests/run-allfcts-multi.sh
+++ b/tests/run-allfcts-multi.sh
@@ -42,15 +42,21 @@ EOF
# dwz test-offset-loop test-offset-loop2 -m test-offset-loop.alt
testfiles test-offset-loop test-offset-loop.alt
-tempfiles allfcts.out
+tempfiles allfcts.in allfcts.out
-# Use head to capture output because the output could be infinite...
-testrun ${abs_builddir}/allfcts test-offset-loop | head -n 20 > allfcts.out
-testrun_compare cat allfcts.out <<\EOF
+cat >allfcts.in <<\EOF
/tmp/test-offset-loop.c:6:get_errno
/tmp/test-offset-loop.c:5:is_error
/tmp/test-offset-loop.c:4:padding
/tmp/test-offset-loop.c:7:main
EOF
+# Use head to capture output because the output could be infinite...
+testrun ${abs_builddir}/allfcts test-offset-loop | head -n 20 > allfcts.out
+testrun_compare cat allfcts.out <allfcts.in
+
+# Repeat from a different directory for relative .gnu_debugaltlink
+(cd / && testrun ${abs_builddir}/allfcts $OLDPWD/test-offset-loop) | head -n 20 > allfcts.out
+testrun_compare cat allfcts.out <allfcts.in
+
exit 0
--
1.8.4.2
10 years, 4 months
elfutils 0.158 released
by Mark Wielaard
A new release of elfutils is available now at:
https://fedorahosted.org/releases/e/l/elfutils/0.158/
* NEWS *
Version 0.158
libdwfl: dwfl_core_file_report has new parameter executable.
New functions dwfl_module_getsymtab_first_global,
dwfl_module_getsym_info and dwfl_module_addrinfo.
Added unwinder with type Dwfl_Thread_Callbacks, opaque types
Dwfl_Thread and Dwfl_Frame and functions dwfl_attach_state,
dwfl_pid, dwfl_thread_dwfl, dwfl_thread_tid, dwfl_frame_thread,
dwfl_thread_state_registers, dwfl_thread_state_register_pc,
dwfl_getthread_frames, dwfl_getthreads, dwfl_thread_getframes
and dwfl_frame_pc.
addr2line: New option -x to show the section an address was found in.
stack: New utility that uses the new unwinder for processes and cores.
backends: Unwinder support for i386, x86_64, s390, s390x, ppc and ppc64.
aarch64 support.
* GIT SHORTLOG *
Jan Kratochvil (24):
Fix executable_for_core for non-dwfl_standard_argp
dwfl_core_file_report: Code cleanup: Reindentation.
dwfl_core_file_report: Fix core files for re-prelink-ed files
dwfl_core_file_report: Fix a regression of dwfl_core_file_report
retval
dwfl_core_file_report: Remove the use of MAX.
Unwinder for x86*.
Fix dwfl_module_addrsym for minidebuginfo
Provide __libdwfl_module_getsym to get dwfl_file *
Fix dwfl_attach_state machine->elf
Code cleanup: Remove const in prototype
Update m4/ChangeLog for m4/biarch.m4 authorship.
Compatibility with older kernels such as RHEL-6.
link_map: Use proper bias, not l_addr
Verify file vs. core build-id, when both available
Fix non-build-id core files on build-id system
Introduce process_attach_error.
Tests for unwinder of x86*.
Fix test FAIL with -O2
unwinder: ppc and ppc64
Fix forgotten call of ebl_dwarf_to_regno.
Remove tests/backtrace-dwarf.c unused code.
unwinder: s390 and s390x
Add NEWS items for the new functions in 0.158.
Use executable_for_core in dwfl_build_id_find_elf.
Josh Stone (6):
libdw: Make sure that every debug_types sig8 is hashed
libdwfl: Fix and test aux_sym address_sync with relocated ELF
Add config/ar-lib to .gitignore
libdw: Add an inlined fast path for __libdw_form_val_len
libdw: Simplify and inline get_uleb128 and get_sleb128
lib: Avoid the hash-lookup division if possible
Mark Wielaard (56):
backends: ppc_abi_cfi reg1 use DW_CFA_val_offset not
DW_CFA_val_expression.
ar: Correct operation check when instance_specifed is set.
libdwfl: Don't report and abort on non-file mappings in maps.
libdw: Handle dwz multi files correctly in dwarf_getfuncs.
README: Document that tools and libraries should be upgraded
together.
README: Fix compatbile -> compatible typo.
tests: allfcts.c (main): Correct dwarf_getfuncs return value check.
readelf: Solve comparison between signed and unsigned compiler
warning.
libelf: Write all section headers if elf flags contains
ELF_F_DIRTY.
configure.ac: Add warning that --enable-thread-safety is
experimental.
configure.ac: Warn when --enable-dwz=no, but /usr/lib/debug/.dwz
exists.
Fix some (harmless) cppcheck warnings.
libelf: Only memcpy ehdr back when not already directly mmapped.
stack: Add basic argp version and bug definitions.
tests: Fix broken dwflsyms tests, extend test and add prelink
tests.
tests: Makefile.am (EXTRA_DIST): Add run-funcretval.sh.
Mark new dwfl functions with version ELFUTILS_0.158.
libdwfl: Add dwfl_module_addrsym_elf and dwfl_module_getsym_elf.
tests: automake 1.13 compatibility fix.
tests: SKIP backtrace-data and backtrace-dwarf on unsupported
arches.
libdw: Handle empty location expression for (indirect) DIE
locations.
tests: Disable valgrind for core dumping and for self-introspecting
tests.
tests: Add backtrace_child_biarch_SOURCES to make distcheck happy.
libdwfl: Fix various frame related memory leaks.
libdwfl: Add dwfl_module_getsymtab_first_global.
libdwfl: linux-pid-attach.c (pid_next_thread): Use rewinddir on
first call.
backends: Avoid type-punning issue in
s390_set_initial_registers_tid.
Fix s390_initreg.c patch copy/paste error.
libdwfl: Introduce dwfl_module_getsym_info and
dwfl_module_addrinfo.
backends: aarch64 always has _GLOBAL_OFFSET_TABLE_ point to
.got[0].
libdwfl: Correct nested asprintf result check in
report_kernel_archive.
tests: backtrace.c only check we caught the last instruction on
x86_64.
libdwfl: Add dwfl_getthread_frames.
libdwfl: Make sure to set the CFI return register only once (for
ppc64).
libdwfl: linux-pid-attach.c: Report actual PID (Tgid) to
dwfl_attach_state.
stack: Add new '-n MAXFRAMES' option. Resolve addresses after
unwind.
stack: -b, --build-id shows module build-id, load address and pc
offset.
stack: Simplify argument parsing. Don't use dwfl_standard_argp.
stack: Add --quiet to not resolve addresses, add --raw to not
demangle.
stack: Improve error checking and exit code handling.
stack: Add -l, --list-modules. Show module memory map, build-id and
files.
libdwfl: Fix build_id memory leak in dwfl_segment_report_module.
libdwfl: Fix memory leak in linux-core-attach. Allow reiterating
threads.
libdwfl: dwfl_linux_proc_find_elf should only return regular files.
libdwfl: Add dwfl_core_file_attach and dwfl_linux_proc_attach.
libdwfl: linux-pid-attach.c (dwfl_linux_proc_attach): Use and check
strtol
stack: Allow -n 0 for unlimited frames. Make default 2048 frames.
stack.c (print_frames): Print 0x before build-id hex-offset.
stack: Show and handle -r,--raw even without USE_DEMANGLE.
backends: Add aarch64 abi_cfi.
Prepare 0.158 release.
tests: Simplify backtrace-dwarf (gcc cleanup-13.c) testcase.
tests: backtrace-subr.sh skip check_native_core test if core ulimit
fails.
backends: Add PPC64 machine_flag_check.
tests: Don't use ptrace detach stopped trick. Raise can return.
libdwfl: Only skip reset of return register for non-CIE-return
regno (ppc64).
Masatake YAMATO (1):
stack: show binary and source file names where a function is
defined
Michael Forney (2):
Check for prefixed ar, readelf, and nm
Fix expansion of libdw_a_LIBADD
Petr Machata (3):
Update elf.h from glibc
Support new 'h' core note item format for hidden fields
Support AArch64 architecture
Yuri Chornoivan (1):
Update Ukrainian translation
10 years, 4 months
Preparing for elfutils 0.158
by Mark Wielaard
Hi,
Lets start the new year with a new release. I still have 4 patches on
mjw/pending that were posted to this list last week. I intent to check
these into master tomorrow unless there are more comments:
libdwfl: Fix build_id memory leak in dwfl_segment_report_module.
libdwfl: Fix memory leak in linux-core-attach. Allow reiterating threads.
libdwfl: dwfl_linux_proc_find_elf should only return regular files.
libdwfl: Add dwfl_core_file_attach and dwfl_linux_proc_attach.
After that I would like to push for a 0.158 release on Monday after
testing it on various setups this weekend. Unless any critical
regressions are found.
Cheers,
Mark
10 years, 4 months
[PATCH] backends: Add aarch64 abi_cfi.
by Mark Wielaard
While testing on aarch64 I noticed that the backend was missing the
abi_cfi hook which is needed by the dwarf_frame functions to setup
the initial register states. And the register_info would leave the
prefix string as NULL instead of the empty string, which is unlike
all other backends. The following fixes those two issues and adds
a testcase for it.
On mjw/aarch64-unwind there is also a first try of adding unwinding
support. It works somewhat, but at least on the setup I had access to
some CFI was missing causing erradic unwinding behavior (or maybe it
is a bug in my patch). Fixing this up is for after 0.158.
<- snip ->
Setup initial CIE values for aarch64 for use with dwarf_frame functions.
Register info prefix should be the empty string (not NULL) when not used.
Add an EM_AARCH64 testcase to tests/run-addrcfi.sh to check both issues.
Signed-off-by: Mark Wielaard <mjw(a)redhat.com>
---
backends/ChangeLog | 7 ++++
backends/Makefile.am | 2 +-
backends/aarch64_cfi.c | 82 +++++++++++++++++++++++++++++++++++++++++++++
backends/aarch64_init.c | 1 +
backends/aarch64_regs.c | 2 +-
tests/ChangeLog | 6 +++
tests/Makefile.am | 2 +-
tests/run-addrcfi.sh | 76 +++++++++++++++++++++++++++++++++++++++++
tests/testfileaarch64.bz2 | Bin 0 -> 3441 bytes
9 files changed, 175 insertions(+), 3 deletions(-)
create mode 100644 backends/aarch64_cfi.c
create mode 100755 tests/testfileaarch64.bz2
diff --git a/backends/ChangeLog b/backends/ChangeLog
index 24cc63d..2074cff 100644
--- a/backends/ChangeLog
+++ b/backends/ChangeLog
@@ -1,3 +1,10 @@
+2014-01-03 Mark Wielaard <mjw(a)redhat.com>
+
+ * Makefile.am (aarch64_SRCS): Add aarch64_cfi.c.
+ * aarch64_cfi.c: New file.
+ * aarch64_init.c (aarch64_init): Hook abi_cfi.
+ * aarch64_regs.c (aarch64_register_info): Set *prefix to "".
+
2013-12-19 Mark Wielaard <mjw(a)redhat.com>
* aarch64_init.c (aarch64_init): Hook check_special_symbol.
diff --git a/backends/Makefile.am b/backends/Makefile.am
index 8deed2f..b8bea36 100644
--- a/backends/Makefile.am
+++ b/backends/Makefile.am
@@ -83,7 +83,7 @@ libebl_arm_pic_a_SOURCES = $(arm_SRCS)
am_libebl_arm_pic_a_OBJECTS = $(arm_SRCS:.c=.os)
aarch64_SRCS = aarch64_init.c aarch64_regs.c aarch64_symbol.c \
- aarch64_corenote.c aarch64_retval.c
+ aarch64_corenote.c aarch64_retval.c aarch64_cfi.c
libebl_aarch64_pic_a_SOURCES = $(aarch64_SRCS)
am_libebl_aarch64_pic_a_OBJECTS = $(aarch64_SRCS:.c=.os)
aarch64_regs_no_Wformat = yes
diff --git a/backends/aarch64_cfi.c b/backends/aarch64_cfi.c
new file mode 100644
index 0000000..acbb9b6
--- /dev/null
+++ b/backends/aarch64_cfi.c
@@ -0,0 +1,82 @@
+/* arm ABI-specified defaults for DWARF CFI.
+ Copyright (C) 2013 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 either
+
+ * the GNU Lesser General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at
+ your option) any later version
+
+ or
+
+ * the GNU General Public License as published by the Free
+ Software Foundation; either version 2 of the License, or (at
+ your option) any later version
+
+ or both in parallel, as here.
+
+ 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 copies of the GNU General Public License and
+ the GNU Lesser General Public License along with this program. If
+ not, see <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+
+#define BACKEND aarch64_
+#include "libebl_CPU.h"
+
+
+/* ABI-specified state of DWARF CFI based on:
+
+ "DWARF for the ARM 64 bit architecture (AArch64) 1.0"
+http://infocenter.arm.com/help/topic/com.arm.doc.ihi0057b/IHI0057B_aadwarf64.pdf
+
+ "Procedure Call Standard for the ARM 64 bit Architecture 1.0"
+http://infocenter.arm.com/help/topic/com.arm.doc.ihi0055b/IHI0055B_aapcs64.pdf
+*/
+
+int
+aarch64_abi_cfi (Ebl *ebl __attribute__ ((unused)), Dwarf_CIE *abi_info)
+{
+ static const uint8_t abi_cfi[] =
+ {
+ /* The initial Canonical Frame Address is the value of the
+ Stack Pointer (r31) as setup in the previous frame. */
+ DW_CFA_def_cfa, ULEB128_7 (30), ULEB128_7 (0),
+
+#define SV(n) DW_CFA_same_value, ULEB128_7 (n)
+ /* Callee-saved regs r19-r28. */
+ SV (19), SV (20), SV (21), SV (22), SV (23),
+ SV (24), SV (25), SV (26), SV (27), SV (28),
+
+ /* The Frame Pointer (FP, r29) and Link Register (LR, r30). */
+ SV (29), SV (30),
+
+ /* Callee-saved fpregs v8-v15. v0 == 64. */
+ SV (72), SV (73), SV (74), SV (75),
+ SV (76), SV (77), SV (78), SV (79),
+#undef SV
+
+ /* XXX Note: registers intentionally unused by the program,
+ for example as a consequence of the procedure call standard
+ should be initialized as if by DW_CFA_same_value. */
+ };
+
+ abi_info->initial_instructions = abi_cfi;
+ abi_info->initial_instructions_end = &abi_cfi[sizeof abi_cfi];
+ abi_info->data_alignment_factor = -4;
+
+ abi_info->return_address_register = 30; /* lr. */
+
+ return 0;
+}
diff --git a/backends/aarch64_init.c b/backends/aarch64_init.c
index d663d40..a1a7060 100644
--- a/backends/aarch64_init.c
+++ b/backends/aarch64_init.c
@@ -57,6 +57,7 @@ aarch64_init (elf, machine, eh, ehlen)
HOOK (eh, reloc_simple_type);
HOOK (eh, return_value_location);
HOOK (eh, check_special_symbol);
+ HOOK (eh, abi_cfi);
return MODVERSION;
}
diff --git a/backends/aarch64_regs.c b/backends/aarch64_regs.c
index 5952b96..aec201f 100644
--- a/backends/aarch64_regs.c
+++ b/backends/aarch64_regs.c
@@ -57,7 +57,7 @@ aarch64_register_info (Ebl *ebl __attribute__ ((unused)),
return s + 1;
}
- *prefix = NULL;
+ *prefix = "";
*bits = 64;
switch (regno)
diff --git a/tests/ChangeLog b/tests/ChangeLog
index 5c80e9b..c68ae26 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -1,3 +1,9 @@
+2014-01-03 Mark Wielaard <mjw(a)redhat.com>
+
+ * run-addrcfi.sh: Add case for EM_AARCH64.
+ * testfileaarch64.bz2: New testfile.
+ * Makefile.am (EXTRA_DIST): Add testfilesaarch64.bz2.
+
2013-12-30 Mark Wielaard <mjw(a)redhat.com>
* backtrace-dwarf.c (report_pid): Explicitly call
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 52eb50a..eae64a8 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -237,7 +237,7 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh \
run-addr2line-i-test.sh testfile-inlines.bz2 \
testfileppc32.bz2 testfileppc64.bz2 \
testfiles390.bz2 testfiles390x.bz2 \
- testfilearm.bz2 \
+ testfilearm.bz2 testfileaarch64.bz2 \
run-varlocs.sh \
testfile_const_type.c testfile_const_type.bz2 \
testfile_implicit_pointer.c testfile_implicit_pointer.bz2 \
diff --git a/tests/run-addrcfi.sh b/tests/run-addrcfi.sh
index c7ab71a..a4225ac 100755
--- a/tests/run-addrcfi.sh
+++ b/tests/run-addrcfi.sh
@@ -2572,3 +2572,79 @@ dwarf_cfi_addrframe (.eh_frame): no matching address range
VFP reg286 (d30): undefined
VFP reg287 (d31): undefined
EOF
+
+# EM_AARCH64 (function bar 0x400550)
+# Same as arm, 390 and ppc above.
+# Note missing coverage in .eh_frame.
+testfiles testfileaarch64
+testrun_compare ${abs_builddir}/addrcfi -e testfileaarch64 0x400550 <<\EOF
+dwarf_cfi_addrframe (.eh_frame): no matching address range
+.debug_frame has 0x400550 => [0x400550, 0x400568):
+ return address in reg30
+ CFA location expression: bregx(31)
+ integer reg0 (x0): undefined
+ integer reg1 (x1): undefined
+ integer reg2 (x2): undefined
+ integer reg3 (x3): undefined
+ integer reg4 (x4): undefined
+ integer reg5 (x5): undefined
+ integer reg6 (x6): undefined
+ integer reg7 (x7): undefined
+ integer reg8 (x8): undefined
+ integer reg9 (x9): undefined
+ integer reg10 (x10): undefined
+ integer reg11 (x11): undefined
+ integer reg12 (x12): undefined
+ integer reg13 (x13): undefined
+ integer reg14 (x14): undefined
+ integer reg15 (x15): undefined
+ integer reg16 (x16): undefined
+ integer reg17 (x17): undefined
+ integer reg18 (x18): undefined
+ integer reg19 (x19): same_value
+ integer reg20 (x20): same_value
+ integer reg21 (x21): same_value
+ integer reg22 (x22): same_value
+ integer reg23 (x23): same_value
+ integer reg24 (x24): same_value
+ integer reg25 (x25): same_value
+ integer reg26 (x26): same_value
+ integer reg27 (x27): same_value
+ integer reg28 (x28): same_value
+ integer reg29 (x29): same_value
+ integer reg30 (x30): same_value
+ integer reg31 (sp): undefined
+ integer reg33 (elr): undefined
+ FP/SIMD reg64 (v0): undefined
+ FP/SIMD reg65 (v1): undefined
+ FP/SIMD reg66 (v2): undefined
+ FP/SIMD reg67 (v3): undefined
+ FP/SIMD reg68 (v4): undefined
+ FP/SIMD reg69 (v5): undefined
+ FP/SIMD reg70 (v6): undefined
+ FP/SIMD reg71 (v7): undefined
+ FP/SIMD reg72 (v8): same_value
+ FP/SIMD reg73 (v9): same_value
+ FP/SIMD reg74 (v10): same_value
+ FP/SIMD reg75 (v11): same_value
+ FP/SIMD reg76 (v12): same_value
+ FP/SIMD reg77 (v13): same_value
+ FP/SIMD reg78 (v14): same_value
+ FP/SIMD reg79 (v15): same_value
+ FP/SIMD reg80 (v16): undefined
+ FP/SIMD reg81 (v17): undefined
+ FP/SIMD reg82 (v18): undefined
+ FP/SIMD reg83 (v19): undefined
+ FP/SIMD reg84 (v20): undefined
+ FP/SIMD reg85 (v21): undefined
+ FP/SIMD reg86 (v22): undefined
+ FP/SIMD reg87 (v23): undefined
+ FP/SIMD reg88 (v24): undefined
+ FP/SIMD reg89 (v25): undefined
+ FP/SIMD reg90 (v26): undefined
+ FP/SIMD reg91 (v27): undefined
+ FP/SIMD reg92 (v28): undefined
+ FP/SIMD reg93 (v29): undefined
+ FP/SIMD reg94 (v30): undefined
+ FP/SIMD reg95 (v31): undefined
+EOF
diff --git a/tests/testfileaarch64.bz2 b/tests/testfileaarch64.bz2
new file mode 100755
index 0000000000000000000000000000000000000000..72e5ef0de7ca8ffaab3e19d0b34ab9acfda34da2
GIT binary patch
literal 3441
zcmV-%4UY0cT4*^jL0KkKSu>catpE*pfB*mg|NsB@|NsC0|9Sua-~Rk*Z{PELNA3J<
zfBW}OfB)bNT>Fh((xXCq&v{Q~dc4|sPV(zpy?NtDpbC4~t$~stAZQcR)f#%9o+R>~
zih6oYO{SyMNX;SW)Y_UJQ$~h{ntGn0;Y?4|Ajktl)NN1I2A-M*nl(0|rhs~b)YEDK
zp`#$s^#q{=G!kryspQ0-LYi!pHccm}^&X+MG->G?9-*N0k5QlpsL=gUqd;l2hEGr$
z21bn<05ky50qOt)L(~DFiK0mIni^=+CX9pB2dK~(KmalT00E!?G|&Jv0002>00000
z000dD5}u@*O-df8gqj&1rhouFKmZ4+>ODXj0i)CdKn#EZpa1}ApaUQP0}ucMKmY^)
z003kF27olsG#VNJ8fXlF00SYBf&gd?fM{qMX`mVbpa2;FWMlvmBt#}nOsA$($sQ6k
zJtNdJNv4}ZJxu@&2AX<?nlUl}446Y88UO&$27ols4FJ#p0iXcqG?rv{R+Z^3mAzo&
z&N(FZvl*)iLaC>>>5k+>bgU?#lLHE=3OA)<M3mUj)R3aEV`FPn;BHI;GqSj{tVp>H
zIdoD}I&Wne22QOUtHFkN<|QdHL|cCLQ*lEUo{4tv*JiH+$UA0exwxK7&~&xmuKfjW
zzg0$uUnX09W$CZJCfcSq((5d7HwCk3F2wrqH1@o5>qEusy+w3znPJkYj!j~XQDmK+
zrGs)6xMIk+M%qlPsNG$nZ#WgB8v?EpObV#5#0rY2s;Y`C5)gUUdHp*XyN#af9b8HH
z+SxSZI-XniUXGCkDN$ZX%fd{piFu`e;4}k`sz4cd3$SjwB+F&yg3DPdKAzgm%|tnY
z=ch=T^FzaJL~pU<Z+{QVFPrMq_BB;jB3to83Cln#hLXy@ji9~q;URJi0M9aQ0x_{~
za9hsg<u+rmZ+XtZ1QCLOmc_*7N=i3Y^rBh7B#l}S34I9!R^fW@%Dchi@1y;Df3!me
z{TZoIQ4A!EMk}80_0)YffXVUT_G!<?m1^OtLL&K~L)XGcB+^)HNH)7@Kv(8%I|-n{
z!-Oz`llCj1oeUAZd4RCSr)eKcc>@MK*e#}e03?MAyyDr4mx)hxFiMh?p(NOvY)uF~
zmLN(^NsO-m2AE<3Y)NNEk_Ei9sTxvhhLmDJ5aTpJr#J<G^KAz@$+00rn?eaNLM~D-
zU_^|_u`wC8DMcqk>Pa3-d5IYe8TUt_^?1!Ln%FC7tOm{{t#OUl)D0~fKL&bXq=Nme
zt09^ph`eE|8sV}~EnvX3*T9t<7!ne+W%~lrfGqULK%~+^nm8p0hLDjakl2RNvSP(#
zoSF>0ph>lxWHTRwq~P&r1eGl#5+MTAEI0rp;tV*bv}K?~G@NOY1D#@02PjDpETqho
zQj}>7sk2~Bvy+K!3ZTX3ZxUcyvUV9o2P!5MognH-e8i*&!CQpJrHLNUkUz=cvyTHr
z5nV|g_xR5T<e@f~9#d~iv}DXXCpSzLNA>(x4BgupB-QC=*?8ntRv7~R4%-y4{HDdC
z4w`5DC%-ie?&W%CGA+B?FA{YV!$tbGdDoWNUS`sBl>z9<15|I=!yP7fMP=l`cUYh<
zq0b8>SRTa=kp-eLqHHTL7NdXGgeqlg+SOg5xxi7JMtp6tN^DlQ%p#MMQXU-17;%em
z3JnG-$Vfh|Es~+~?H|XVluA{&cX$<RwsgAw1+!%W0Ldyq6o5%_L^y<LP)O72=+MKV
zjZcld%FO+^FC0bIUqh^*Ub{-}?1LG=@S1_520+kgnuY;{&_kt(8J4MV7x_X!87xQ^
z0O=T8I|~PRVo{c0{o%#Hl`s%5n31Ew(nx}X7_aI5V)O^YitA@mf&wiH!eJnB4&SV8
zbl%wHV_ok#|9&SX^7|k3fBD>9W&4^3$?Bym-$E2ngPue5Iu&5XjbpU|4Z08}PoF(V
zsuTk(vdc6(H8rho!v|>))Y@L%<O*YZeKt3xhfX5`*{apx)$vs7>w3J3sKktb7+>gm
z3_p5Ae{8w)VFI-ok+*Olq=*2erAncK19pF#jA11!EcpaAVlr5tV+r@sTQVKUiP6nP
z5njBi(@lF;7wlR@4H^cL)3k0Z-jKu`{Z6$2K{Y4}-r(D6A%~tMA{CQX8Utdejb=(7
zgkutG4VbUGVD1#x;Z~QP!mlxTK4IchG?6Ibw>Ap>F>{AEQy6ce))LhjE$4jwLyO^|
zwq>3{1;QwIor57HlVumad)-xvj?I+dkr62oDK}|BUe*z*X{LzD{oT(^D}{nqsZ@h7
z7(s}#>OmA4wFuFurfLA9bPz*{6W-Rta||OR^KNlD6QWbEx}RQWU5+RVcAF5b+CW*q
zktAgpLS^+xp2w@EW6{8jCr+txq<~vsYeFI3s<AmVNqwS{12?0<rDkNt=1)S%jR(^q
zw)Yo*Ws;(*!YZnSM@yXQX@6N8{SjbZ(^;6}uDe>-sYHNdRdnh!5J{v<Q7wV@vZkh@
zp}x0aky0j+uFeDklLimik?dw=oa<qMVSFX2V-1C81qoo)>172T-OTc(O5t`@EpMjQ
zB}N%-24-kZ8+&xY@JqPs?eMu7P}e^|QqAbXxODxODfAUaj;ZD{EJi#fce2jpcU$2$
zZRIu2<(q}NqLYSZV2VpXvN%fE4Sqlz0vM4l*i0ClE)5ccf1ow@rVxlDrFR<PYfsN7
zbmY7Yer+6^>pJIYE^5F_-IaVsLobDFQNVjVUJ|o5Bs6GTrsNH(E7Fv1uJ`w@l<m`x
zrdqr<?EyP*UG}L3(u)<)Y_a|yDM@bNn2#}~OGPYKJ0BwCsX$ZIH>+9=i6y8R5)&lp
zxEGT|$?#@2ml~To(+;y4cvS98=us7X<Q74F4<K=96_%Ymm~HV+P|u#eOGYB1+}lMi
z1D`4j-$wntm|TvHh_iKzsH6}#jX}NdE#%q?p~o-?XQM7!nc!1_?Mh0W$v@-vt`&^1
z%Bh+%B1|45L=LqQky=o;wo<EP!Al9UNs*%rtl?I)ysH<fLY9OEfEZz^phQJdU~nWL
z(9nyEb0`|=!30^S=fs@dhn0xbArcW_Mim%A5J5Azp5|*amj6y19dAI0fe{FK>ha>L
z$54I&iT!J`*|MNAhA4dUx|A8UHW|rNrP|dRNmrSXJ3GU0&E`i+wm6y*7em#W!wfc~
zOfyjP6=w}Xq#_QSDvD>mmek5W!m>>sew2Fe?9PlSM~v-fPR4XDqmg>8{0wn59H6QW
zW?{_BtIzlutK1!|m35u13q6%pGcN#ncE^`Ibo+EI-VKqi`;qZVCM?I~Y!iI46nKmR
zTA`6CS9FhfD6NU5*DJkXnKLsjmq7+_vn3b9E~<Ox;!e)T+-3`N?UxQYZ{_#aa;IIf
zg_Gx=6e<rd9a~urx@EE=>KtkJ2wR;4VCLx0y891%HK{<S5jti}ImyRn41BW<$X%6(
zjG-;yNMR%)3p=!A(1Z#E-%y>Vz;0yn);%@|bq@*PgA089s9b>xwJ;bDXRxbwuje4K
zQCtLAD@NY=M9UvnDXDf=OrpIhxzdxsR&q@jn#zPh*@_Y)hbQ*T2K#9vMabm|3Rd(e
zQYcO@fiRM&eR5{?917_bNwQdu6-?Vx0ZufW!i2#gA^&ev#jUl%f`+34I(kzj%v=ep
zZMOuWEC^J@%*mi=1!k%h0e&4F)vA-+aP{%%wRw?xCs%401vkf1V<<XIWzn^0LmKJG
zR8Hz5Gi1P;v1lT~<Rs^Uu&5>?0}xdt3>;vZB$dgKdOLVK8f)PwH3x)(@sO<6ES72u
z3|A7fQMF!j6)j8%UqTP8MGa(hDO!tSGnh;x3=Fn2Az0*5^(r#^dWVKJnum&NK`BBN
zq8N}|J5$wNl8N{5UOdL(D)z{2^%g}GO%M!{8FzJ$5wvv+XhN-v)Lc2WNQ6al>o^#}
zs(})D()7T-<7aEX*xx$-$138znY;#u-y108C8%Y_bWTSuGZ1j8l|ATtWe~!cd)~%s
zC^BreBFG1btSvNq*B*L#_o2cH7Dcqo8)Chzp@<ZrJwAa*j{Jn$6a$!V)C$uA5h#wK
z8!cnnV9ZvfM5utcJ3VVnvinvWhajzt`65YR%VUAs+!d|IqR;gX{x{=EAoDA`qD>ns
zmtgr&670WNeJ<I$2{!h*b0Bm&_SoW0&(!@=dzzt;W^*{|t$Z-Uda9|auAUA`I^6#{
zFpB(cNw%U=-Pbuo{H~csi71_%kWERf0H)N9NnEKatw=kzgNzRux<~xW{^5ZgE>12I
zlu%DtWL#AKduN*W*^kGAME{$U<-_->p<RgS-=Yek480B0kNEV)Wulb}Hf#z|rso)s
z(_G-uGOlGy<s#QKH9}h9pi>PnLVzKMa-I_|$)#?^Pa+V4<3(*S6pBIFX)Xv}j7+T-
zMl;Zda)p=K>up#I>>vMFtaY8lnA<W0Z7`I84cY((Y$VNF>Dx6eYC&nR<NcYuMu#X?
TNVKM*|BJaIoG3^c%v9EZ(SbFW
literal 0
HcmV?d00001
--
1.7.1
10 years, 4 months
[PATCH] stack: -b, --build-id shows module build-id, load address and pc offset.
by Mark Wielaard
A convenient format for offline processing of the backtrace.
Signed-off-by: Mark Wielaard <mjw(a)redhat.com>
---
src/ChangeLog | 8 ++++++++
src/stack.c | 31 +++++++++++++++++++++++++++----
2 files changed, 35 insertions(+), 4 deletions(-)
diff --git a/src/ChangeLog b/src/ChangeLog
index d3d6807..4737d69 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,11 @@
+2013-12-23 Mark Wielaard <mjw(a)redhat.com>
+
+ * stack.c (show_build_id): New static boolean.
+ (print_frames): Print module build-id, load address and pc offset
+ if show_build_id is true.
+ (parse_opt): Handle '-b'.
+ (main): Add -b to options.
+
2013-12-22 Mark Wielaard <mjw(a)redhat.com>
* stack.c (maxframes): New static unsigned. Initialize to 64.
diff --git a/src/stack.c b/src/stack.c
index 188aa00..362cc06 100644
--- a/src/stack.c
+++ b/src/stack.c
@@ -38,6 +38,7 @@ ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT;
static bool show_activation = false;
static bool show_module = false;
+static bool show_build_id = false;
static bool show_source = false;
static bool show_one_tid = false;
@@ -116,15 +117,31 @@ print_frames (struct frames *frames)
if (symname != NULL)
printf (" %s", symname);
+ const char* fname;
+ Dwarf_Addr start;
+ fname = dwfl_module_info(mod, NULL, &start,
+ NULL, NULL, NULL, NULL, NULL);
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_build_id)
+ {
+ const unsigned char *id;
+ GElf_Addr id_vaddr;
+ int id_len = dwfl_module_build_id (mod, &id, &id_vaddr);
+ if (id_len > 0)
+ {
+ printf ("\n [");
+ do
+ printf ("%02" PRIx8, *id++);
+ while (--id_len > 0);
+ printf ("]@0x%0" PRIx64 "+%" PRIx64, start, pc_adjusted - start);
+ }
+ }
+
if (show_source)
{
Dwfl_Line *lineobj = dwfl_module_getsrc(mod, pc_adjusted);
@@ -203,6 +220,10 @@ parse_opt (int key, char *arg __attribute__ ((unused)),
show_activation = show_source = show_module = true;
break;
+ case 'b':
+ show_build_id = true;
+ break;
+
case '1':
show_one_tid = true;
break;
@@ -243,6 +264,8 @@ main (int argc, char **argv)
N_("Additionally show source file information"), 0 },
{ "verbose", 'v', NULL, 0,
N_("Show all additional information (activation, module and source)"), 0 },
+ { "build-id", 'b', NULL, 0,
+ N_("Show module build-id, load address and pc offset"), 0 },
{ NULL, '1', NULL, 0,
N_("Show the backtrace of only one thread"), 0 },
{ NULL, 'n', "MAXFRAMES", 0,
@@ -270,7 +293,7 @@ Only real user processes are supported, no kernel or process maps."),
argp_parse (&argp, argc, argv, 0, &remaining, &dwfl);
assert (dwfl != NULL);
if (remaining != argc)
- error (2, 0, "eu-stack [-a] [-m] [-s] [-v] [-1] [-n MAXFRAMES]"
+ error (2, 0, "eu-stack [-a] [-m] [-b] [-s] [-v] [-1] [-n MAXFRAMES]"
" [--debuginfo-path=<path>]"
" {-p <process id>|--core=<file> [--executable=<file>]|--help}");
--
1.7.1
10 years, 4 months
[PATCH] stack: Add --quiet to not resolve addresses, add --raw to not demangle.
by Mark Wielaard
Resolving addresses to function symbol names can be expensive. Use -q
to only print addresses (use together with --build-id to process later).
Demangle names by default, but add the -r option to not demangle and
show the raw names.
Signed-off-by: Mark Wielaard <mjw(a)redhat.com>
---
src/ChangeLog | 12 ++++++++++++
src/Makefile.am | 3 ++-
src/stack.c | 45 +++++++++++++++++++++++++++++++++++++++++++--
3 files changed, 57 insertions(+), 3 deletions(-)
diff --git a/src/ChangeLog b/src/ChangeLog
index 0f1b971..28a6f9e 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,5 +1,17 @@
2013-12-23 Mark Wielaard <mjw(a)redhat.com>
+ * Makefile.am (stack_LDADD): Add demanglelib.
+ * stack.c (show_quiet): New static boolean, default false.
+ (show_raw): Likewise.
+ (demangle_buffer_len): New static size_t.
+ (demangle_buffer): New static char *.
+ (print_frames): Don't resolve pc name if show_quiet. Demangle name
+ unless show_raw.
+ (parse_opt): Handle '-q' and '-r'.
+ (main): Add 'q' and 'r' to options. Free demangle_buffer.
+
+2013-12-23 Mark Wielaard <mjw(a)redhat.com>
+
* stack.c (main): Print pid of process or core.
2013-12-23 Mark Wielaard <mjw(a)redhat.com>
diff --git a/src/Makefile.am b/src/Makefile.am
index 954a14b..9a78348 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -115,7 +115,8 @@ ranlib_LDADD = libar.a $(libelf) $(libeu) $(libmudflap)
strings_LDADD = $(libelf) $(libeu) $(libmudflap)
ar_LDADD = libar.a $(libelf) $(libeu) $(libmudflap)
unstrip_LDADD = $(libebl) $(libelf) $(libdw) $(libeu) $(libmudflap) -ldl
-stack_LDADD = $(libebl) $(libelf) $(libdw) $(libeu) $(libmudflap) -ldl
+stack_LDADD = $(libebl) $(libelf) $(libdw) $(libeu) $(libmudflap) -ldl \
+ $(demanglelib)
ldlex.o: ldscript.c
ldlex_no_Werror = yes
diff --git a/src/stack.c b/src/stack.c
index dfb0272..3568298 100644
--- a/src/stack.c
+++ b/src/stack.c
@@ -45,6 +45,10 @@ static bool show_module = false;
static bool show_build_id = false;
static bool show_source = false;
static bool show_one_tid = false;
+static bool show_quiet = false;
+#ifdef USE_DEMANGLE
+static bool show_raw = false;
+#endif
static unsigned maxframes = 64;
@@ -81,6 +85,11 @@ static const Dwfl_Callbacks core_callbacks =
.debuginfo_path = &debuginfo_path,
};
+#ifdef USE_DEMANGLE
+static size_t demangle_buffer_len = 0;
+static char *demangle_buffer = NULL;
+#endif
+
static int
frame_callback (Dwfl_Frame *state, void *arg)
{
@@ -112,7 +121,7 @@ print_frames (struct frames *frames)
/* Get PC->SYMNAME. */
Dwfl_Module *mod = dwfl_addrmodule (dwfl, pc_adjusted);
const char *symname = NULL;
- if (mod)
+ if (mod && ! show_quiet)
symname = dwfl_module_addrname (mod, pc_adjusted);
// Try to find the address wide if possible.
@@ -138,7 +147,19 @@ print_frames (struct frames *frames)
printf ("%4s", ! isactivation ? "- 1" : "");
if (symname != NULL)
- printf (" %s", symname);
+ {
+#ifdef USE_DEMANGLE
+ if (! show_raw)
+ {
+ int status = -1;
+ char *dsymname = __cxa_demangle (symname, demangle_buffer,
+ &demangle_buffer_len, &status);
+ if (status == 0)
+ symname = demangle_buffer = dsymname;
+ }
+#endif
+ printf (" %s", symname);
+ }
const char* fname;
Dwarf_Addr start;
@@ -267,6 +288,16 @@ parse_opt (int key, char *arg __attribute__ ((unused)),
show_build_id = true;
break;
+ case 'q':
+ show_quiet = true;
+ break;
+
+#ifdef USE_DEMANGLE
+ case 'r':
+ show_raw = true;
+ break;
+#endif
+
case '1':
show_one_tid = true;
break;
@@ -352,6 +383,12 @@ main (int argc, char **argv)
N_("Additionally show source file information"), 0 },
{ "verbose", 'v', NULL, 0,
N_("Show all additional information (activation, module and source)"), 0 },
+ { "quiet", 'q', NULL, 0,
+ N_("Do not resolve address to function symbol name"), 0 },
+#ifdef USE_DEMANGLE
+ { "raw", 'r', NULL, 0,
+ N_("Show raw function symbol names, do not try to demangle names"), 0 },
+#endif
{ "build-id", 'b', NULL, 0,
N_("Show module build-id, load address and pc offset"), 0 },
{ NULL, '1', NULL, 0,
@@ -413,5 +450,9 @@ main (int argc, char **argv)
if (core_fd != -1)
close (core_fd);
+#ifdef USE_DEMANGLE
+ free (demangle_buffer);
+#endif
+
return 0;
}
--
1.7.1
10 years, 4 months
[PATCH] libdwfl: Add dwfl_getthread and dwfl_getthread_frames.
by Mark Wielaard
While playing with the new unwinder interfaces I noticed that I was
writing the same extra wrapper callbacks every time. Often one has,
through some other mechanism, a specific thread id that one is interested
in. Then you write a dwfl_getthreads callback just to filter out that one
tid. So this patch adds such convenience wrappers, but also adds a
new callback for a backend to easily get at a specific thread. The
pid backend implements this optimization by directly checking the tid
exists instead of iterating through them all.
This is also useful for eu-stack where it is often convenient to get
the stack of just one thread. That is now implemented through the
new interface when giving "-1" as extra argument.
<- snip ->
dwfl_getthread and dwfl_getthread_frames are convenience functions for
when the user is only interested in one specific thread id of a process.
The can be implemented by just simple wrapper functions that remove and
extra callback layer just to filter on thread id. But they also provide
an optimized path to getting access to just one Dwfl_Thread by providing
and (optional) new callback for provider. The pid_thread_callbacks now
provide pid_getthread that doesn't need to travers all threads anymore.
stack now uses this to implement a new '-1' option that shows just one
specific thread of a process.
Signed-off-by: Mark Wielaard <mjw(a)redhat.com>
---
ChangeLog | 5 ++
NEWS | 5 ++-
libdw/ChangeLog | 5 ++
libdw/libdw.map | 2 +
libdwfl/ChangeLog | 18 +++++++++
libdwfl/dwfl_frame.c | 86 +++++++++++++++++++++++++++++++++++++++++++
libdwfl/libdwfl.h | 31 +++++++++++++++
libdwfl/libdwflP.h | 2 +
libdwfl/linux-core-attach.c | 1 +
libdwfl/linux-pid-attach.c | 12 ++++++
src/ChangeLog | 7 +++
src/stack.c | 46 ++++++++++++++++++-----
tests/backtrace-data.c | 1 +
13 files changed, 210 insertions(+), 11 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index fe109e1..503b95c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,10 @@
2013-12-18 Mark Wielaard <mjw(a)redhat.com>
+ * NEWS (libdwfl): Add dwfl_getthread and dwfl_getthread_frames.
+ (stack): New entry.
+
+2013-12-18 Mark Wielaard <mjw(a)redhat.com>
+
* NEWS (libdwfl): Add dwfl_module_getsym_info and
dwfl_module_addrinfo.
(addr2line): Add -x option.
diff --git a/NEWS b/NEWS
index 49510f7..b22578f 100644
--- a/NEWS
+++ b/NEWS
@@ -7,10 +7,13 @@ libdwfl: dwfl_core_file_report has new parameter executable.
Dwfl_Thread and Dwfl_Frame and functions dwfl_attach_state,
dwfl_pid, dwfl_thread_dwfl, dwfl_thread_tid, dwfl_frame_thread,
dwfl_thread_state_registers, dwfl_thread_state_register_pc,
- dwfl_getthreads, dwfl_thread_getframes and dwfl_frame_pc.
+ dwfl_getthread, dwfl_getthread_frames, dwfl_getthreads,
+ dwfl_thread_getframes and dwfl_frame_pc.
addr2line: New option -x to show the section an address was found in.
+stack: New utility that uses the new unwinder for processes and cores.
+
Version 0.157
libdw: Add new functions dwarf_getlocations, dwarf_getlocation_attr
diff --git a/libdw/ChangeLog b/libdw/ChangeLog
index ef3ed57..2cb8c0c 100644
--- a/libdw/ChangeLog
+++ b/libdw/ChangeLog
@@ -1,3 +1,8 @@
+2013-12-20 Mark Wielaard <mjw(a)redhat.com>
+
+ * libdw.map (ELFUTILS_0.158): Add dwfl_getthread and
+ dwfl_getthread_frames.
+
2013-12-18 Mark Wielaard <mjw(a)redhat.com>
* libdw.map (ELFUTILS_0.158): Remove dwfl_module_addrsym_elf and
diff --git a/libdw/libdw.map b/libdw/libdw.map
index 92392bc..cb8a146 100644
--- a/libdw/libdw.map
+++ b/libdw/libdw.map
@@ -280,6 +280,8 @@ ELFUTILS_0.158 {
dwfl_frame_thread;
dwfl_thread_state_registers;
dwfl_thread_state_register_pc;
+ dwfl_getthread;
+ dwfl_getthread_frames;
dwfl_getthreads;
dwfl_thread_getframes;
dwfl_frame_pc;
diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog
index c3569aa..07667ef 100644
--- a/libdwfl/ChangeLog
+++ b/libdwfl/ChangeLog
@@ -1,3 +1,21 @@
+2013-12-20 Mark Wielaard <mjw(a)redhat.com>
+
+ * dwfl_frame.c (one_arg): New struct.
+ (get_one_thread_cb): New function.
+ (dwfl_getthread): Likewise.
+ (one_thread): New struct.
+ (get_one_thread_frames_cb): New function.
+ (dwfl_getthread_frames): Likewise.
+ * libdwfl.h (Dwfl_Thread_Callbacks): Add get_thread function.
+ (dwfl_getthread): New function definition.
+ (dwfl_getthread_frames): Likewise.
+ * libdwflP.h (dwfl_getthread): New internal function declaration.
+ (dwfl_getthread_frames): Likewise.
+ * linux-core-attach.c (core_thread_callbacks): Initialize get_thread
+ to NULL.
+ * linux-pid-attach.c (pid_getthread): New function.
+ (pid_thread_callbacks): Initialize get_thread to pid_getthread.
+
2013-12-18 Mark Wielaard <mjw(a)redhat.com>
* derelocate.c (__libdwfl_find_section_ndx): New internal function.
diff --git a/libdwfl/dwfl_frame.c b/libdwfl/dwfl_frame.c
index 4a7b3cd..fbc603b 100644
--- a/libdwfl/dwfl_frame.c
+++ b/libdwfl/dwfl_frame.c
@@ -273,6 +273,92 @@ dwfl_getthreads (Dwfl *dwfl, int (*callback) (Dwfl_Thread *thread, void *arg),
}
INTDEF(dwfl_getthreads)
+struct one_arg
+{
+ pid_t tid;
+ bool seen;
+ int (*callback) (Dwfl_Thread *thread, void *arg);
+ void *arg;
+};
+
+static int
+get_one_thread_cb (Dwfl_Thread *thread, void *arg)
+{
+ struct one_arg *oa = (struct one_arg *) arg;
+ if (! oa->seen && INTUSE(dwfl_thread_tid) (thread) == oa->tid)
+ {
+ oa->seen = true;
+ return oa->callback (thread, oa->arg);
+ }
+
+ return DWARF_CB_OK;
+}
+
+int
+dwfl_getthread (Dwfl *dwfl, pid_t tid,
+ int (*callback) (Dwfl_Thread *thread, void *arg),
+ void *arg)
+{
+ Dwfl_Process *process = dwfl->process;
+ if (process == NULL)
+ {
+ __libdwfl_seterrno (dwfl->process_attach_error);
+ return -1;
+ }
+
+ if (process->callbacks->get_thread != NULL)
+ {
+ Dwfl_Thread thread;
+ thread.process = process;
+ thread.unwound = NULL;
+ thread.callbacks_arg = NULL;
+
+ if (process->callbacks->get_thread (dwfl, tid, process->callbacks_arg,
+ &thread.callbacks_arg))
+ {
+ int err;
+ thread.tid = tid;
+ err = callback (&thread, arg);
+ thread_free_all_states (&thread);
+ return err;
+ }
+
+ return -1;
+ }
+
+ struct one_arg oa = { .tid = tid, .callback = callback,
+ .arg = arg, .seen = false };
+ int err = INTUSE(dwfl_getthreads) (dwfl, get_one_thread_cb, &oa);
+ if (err == DWARF_CB_OK && ! oa.seen)
+ return -1;
+
+ return err;
+}
+INTDEF(dwfl_getthread)
+
+struct one_thread
+{
+ int (*callback) (Dwfl_Frame *frame, void *arg);
+ void *arg;
+};
+
+static int
+get_one_thread_frames_cb (Dwfl_Thread *thread, void *arg)
+{
+ struct one_thread *ot = (struct one_thread *) arg;
+ return INTUSE(dwfl_thread_getframes) (thread, ot->callback, ot->arg);
+}
+
+int
+dwfl_getthread_frames (Dwfl *dwfl, pid_t tid,
+ int (*callback) (Dwfl_Frame *frame, void *arg),
+ void *arg)
+{
+ struct one_thread ot = { .callback = callback, .arg = arg };
+ return INTUSE(dwfl_getthread) (dwfl, tid, get_one_thread_frames_cb, &ot);
+}
+INTDEF(dwfl_getthread_frames)
+
int
dwfl_thread_getframes (Dwfl_Thread *thread,
int (*callback) (Dwfl_Frame *state, void *arg),
diff --git a/libdwfl/libdwfl.h b/libdwfl/libdwfl.h
index 007089b..aae2b64 100644
--- a/libdwfl/libdwfl.h
+++ b/libdwfl/libdwfl.h
@@ -662,6 +662,17 @@ typedef struct
pid_t (*next_thread) (Dwfl *dwfl, void *dwfl_arg, void **thread_argp)
__nonnull_attribute__ (1);
+ /* Called to get a specific thread. Returns true if there is a
+ thread with the given thread id number, returns false if no such
+ thread exists and may set dwfl_errno in that case. THREAD_ARGP
+ is never NULL. *THREAD_ARGP will be passed to
+ set_initial_registers or thread_detach callbacks together with
+ Dwfl_Thread *thread. This method may be NULL and will then be
+ emulated using the next_thread callback. */
+ bool (*get_thread) (Dwfl *dwfl, pid_t tid, void *dwfl_arg,
+ void **thread_argp)
+ __nonnull_attribute__ (1);
+
/* Called during unwinding to access memory (stack) state. Returns true for
successfully read *RESULT or false and sets dwfl_errno () on failure.
This method may be NULL - in such case dwfl_thread_getframes will return
@@ -748,6 +759,16 @@ int dwfl_getthreads (Dwfl *dwfl,
void *arg)
__nonnull_attribute__ (1, 2);
+/* Like dwfl_getthreads, but only for one specific thread with the
+ given thead id number if it exists. Returns zero on success,
+ returns -1 on error (and when no thread with the given thread id
+ number exists), or the value of the callback when not DWARF_CB_OK.
+ -1 returned on error will set dwfl_errno (). */
+int dwfl_getthread (Dwfl *dwfl, pid_t tid,
+ int (*callback) (Dwfl_Thread *thread, void *arg),
+ void *arg)
+ __nonnull_attribute__ (1, 3);
+
/* Iterate through the frames for a thread. Returns zero if all frames
have been processed by the callback, returns -1 on error, or the value of
the callback when not DWARF_CB_OK. -1 returned on error will
@@ -762,6 +783,16 @@ int dwfl_thread_getframes (Dwfl_Thread *thread,
void *arg)
__nonnull_attribute__ (1, 2);
+/* Like dwfl_thread_getframes, but specifying the thread by its unique
+ identifier number. Returns zero if all frames have been processed
+ by the callback, returns -1 on error (and when no thread with
+ the given thread id number exists), or the value of the callback
+ when not DWARF_CB_OK. -1 returned on error will set dwfl_errno (). */
+int dwfl_getthread_frames (Dwfl *dwfl, pid_t tid,
+ int (*callback) (Dwfl_Frame *thread, void *arg),
+ void *arg)
+ __nonnull_attribute__ (1, 3);
+
/* Return *PC (program counter) for thread-specific frame STATE.
Set *ISACTIVATION according to DWARF frame "activation" definition.
Typically you need to substract 1 from *PC if *ACTIVATION is false to safely
diff --git a/libdwfl/libdwflP.h b/libdwfl/libdwflP.h
index 267b021..8a53fca 100644
--- a/libdwfl/libdwflP.h
+++ b/libdwfl/libdwflP.h
@@ -702,6 +702,8 @@ INTDECL (dwfl_thread_tid)
INTDECL (dwfl_frame_thread)
INTDECL (dwfl_thread_state_registers)
INTDECL (dwfl_thread_state_register_pc)
+INTDECL (dwfl_getthread)
+INTDECL (dwfl_getthread_frames)
INTDECL (dwfl_getthreads)
INTDECL (dwfl_thread_getframes)
INTDECL (dwfl_frame_pc)
diff --git a/libdwfl/linux-core-attach.c b/libdwfl/linux-core-attach.c
index f55faf7..f259b2c 100644
--- a/libdwfl/linux-core-attach.c
+++ b/libdwfl/linux-core-attach.c
@@ -288,6 +288,7 @@ core_detach (Dwfl *dwfl __attribute__ ((unused)), void *dwfl_arg)
static const Dwfl_Thread_Callbacks core_thread_callbacks =
{
core_next_thread,
+ NULL, /* get_thread */
core_memory_read,
core_set_initial_registers,
core_detach,
diff --git a/libdwfl/linux-pid-attach.c b/libdwfl/linux-pid-attach.c
index 3d0716a..13e60f8 100644
--- a/libdwfl/linux-pid-attach.c
+++ b/libdwfl/linux-pid-attach.c
@@ -201,6 +201,17 @@ pid_next_thread (Dwfl *dwfl __attribute__ ((unused)), void *dwfl_arg,
return tid;
}
+/* Just checks that the thread id status file (currently) exists. */
+static bool
+pid_getthread (Dwfl *dwfl __attribute__ ((unused)), pid_t tid,
+ void *dwfl_arg, void **thread_argp)
+{
+ char fbuf[36];
+ snprintf (fbuf, sizeof (fbuf), "/proc/%ld/status", (long) tid);
+ *thread_argp = dwfl_arg;
+ return access (fbuf, R_OK) == 0;
+}
+
/* Implement the ebl_set_initial_registers_tid setfunc callback. */
static bool
@@ -260,6 +271,7 @@ pid_thread_detach (Dwfl_Thread *thread, void *thread_arg)
static const Dwfl_Thread_Callbacks pid_thread_callbacks =
{
pid_next_thread,
+ pid_getthread,
pid_memory_read,
pid_set_initial_registers,
pid_detach,
diff --git a/src/ChangeLog b/src/ChangeLog
index 5722a50..0e6d2dc 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,10 @@
+2013-12-20 Mark Wielaard <mjw(a)redhat.com>
+
+ * stack.c (show_one_tid): New static boolean.
+ (parse_opt): Handle '-1'.
+ (main): Add -1 to options. Call dwfl_getthread_frames when
+ show_one_tid is true.
+
2013-12-18 Mark Wielaard <mjw(a)redhat.com>
* addr2line.c (options): Add symbol-sections, 'x'.
diff --git a/src/stack.c b/src/stack.c
index 242d393..512c85b 100644
--- a/src/stack.c
+++ b/src/stack.c
@@ -39,6 +39,7 @@ ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT;
static bool show_activation = false;
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)
@@ -170,6 +171,10 @@ parse_opt (int key, char *arg __attribute__ ((unused)),
show_activation = show_source = show_module = true;
break;
+ case '1':
+ show_one_tid = true;
+ break;
+
default:
return ARGP_ERR_UNKNOWN;
}
@@ -197,6 +202,8 @@ main (int argc, char **argv)
N_("Additionally show source file information"), 0 },
{ "verbose", 'v', NULL, 0,
N_("Show all additional information (activation, module and source)"), 0 },
+ { NULL, '1', NULL, 0,
+ N_("Show the backtrace of only one thread"), 0 },
{ NULL, 0, NULL, 0, NULL, 0 }
};
@@ -221,23 +228,42 @@ Only real user processes are supported, no kernel or process maps."),
argp_parse (&argp, argc, argv, 0, &remaining, &dwfl);
assert (dwfl != NULL);
if (remaining != argc)
- error (2, 0, "eu-stack [-a] [-m] [-s] [-v] [--debuginfo-path=<path>] {-p <process id>|"
- "--core=<file> [--executable=<file>]|--help}");
+ error (2, 0, "eu-stack [-a] [-m] [-s] [-v] [-1] [--debuginfo-path=<path>]"
+ " {-p <process id>|--core=<file> [--executable=<file>]|--help}");
/* dwfl_linux_proc_report has been already called from dwfl_standard_argp's
parse_opt function. */
if (dwfl_report_end (dwfl, NULL, NULL) != 0)
error (2, 0, "dwfl_report_end: %s", dwfl_errmsg (-1));
- switch (dwfl_getthreads (dwfl, thread_callback, NULL))
+ if (show_one_tid)
{
- case DWARF_CB_OK:
- break;
- case -1:
- error (0, 0, "dwfl_getthreads: %s", dwfl_errmsg (-1));
- break;
- default:
- abort ();
+ pid_t tid = dwfl_pid (dwfl);
+ unsigned frameno = 0;
+ switch (dwfl_getthread_frames (dwfl, tid, frame_callback, &frameno))
+ {
+ case DWARF_CB_OK:
+ break;
+ case -1:
+ error (0, 0, "dwfl_getthread_frames (%d): %s", tid,
+ dwfl_errmsg (-1));
+ break;
+ default:
+ abort ();
+ }
+ }
+ else
+ {
+ switch (dwfl_getthreads (dwfl, thread_callback, NULL))
+ {
+ case DWARF_CB_OK:
+ break;
+ case -1:
+ error (0, 0, "dwfl_getthreads: %s", dwfl_errmsg (-1));
+ break;
+ default:
+ abort ();
+ }
}
dwfl_end (dwfl);
diff --git a/tests/backtrace-data.c b/tests/backtrace-data.c
index 6d21345..9fa3c4a 100644
--- a/tests/backtrace-data.c
+++ b/tests/backtrace-data.c
@@ -205,6 +205,7 @@ set_initial_registers (Dwfl_Thread *thread,
static const Dwfl_Thread_Callbacks callbacks =
{
next_thread,
+ NULL, /* get_thread */
memory_read,
set_initial_registers,
NULL, /* detach */
--
1.7.1
10 years, 4 months
[patch] Support live PIDs with deleted files
by Jan Kratochvil
Hi Mark,
jankratochvil/deleted
with the new /proc/PID/map_files/ feature it is possible to fully access even
deleted executable + shared_libraries. Current Linux kernels (3.11.10) permit
on root user as the tracer but (1) hopefully it gets fixed in the future and
(2) at least for the use in ABRT it is OK as backtracer is run from core
dumping hook.
Linux kernels have always supported also /proc/PID/exe which works for deleted
main executable. It even works for non-root users. But it works only for the
executable, not for shared libraries. I find more useful to push for Linux
kernel /proc/PID/map_files/ permissions fix than to implement /proc/PID/exe.
If the running binary has been upgraded while it is still running its separate
debug info files in /usr/lib/debug/ will no longer match. But still
.eh_frame-based unwind is possible using /proc/PID/map_files/ that time.
Testcase is skipped when /proc/PID/map_files/ gives permission error.
OK for check-in?
I am not completely sure setting just mod->main.name is right but it looks so.
Thanks,
Jan
10 years, 4 months
[PATCH] libdwfl: Fix build_id memory leak in dwfl_segment_report_module.
by Mark Wielaard
We might already have allocated memory to hold the build_id early in
consider_notes when we called consider_phdr for the program headers
we've read from the image. We would leak that memory when we don't use
it then because we return early/fail. This can be because either we
didn't find the correct bias or we skip the module because it would
conflict in address space with any already existing module of DWFL.
In both cases explicitly free the build_id memory.
Signed-off-by: Mark Wielaard <mjw(a)redhat.com>
---
libdwfl/ChangeLog | 5 +++++
libdwfl/dwfl_segment_report_module.c | 10 ++++++++--
2 files changed, 13 insertions(+), 2 deletions(-)
diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog
index 8a164f0..0e7f80a 100644
--- a/libdwfl/ChangeLog
+++ b/libdwfl/ChangeLog
@@ -1,5 +1,10 @@
2013-12-23 Mark Wielaard <mjw(a)redhat.com>
+ * dwfl_segment_report_module.c (dwfl_segment_report_module): Free
+ build_id before returning early.
+
+2013-12-23 Mark Wielaard <mjw(a)redhat.com>
+
* linux-pid-attach.c (__libdwfl_attach_state_for_pid): Report actual
pid (thread group leader) to dwfl_attach_state.
diff --git a/libdwfl/dwfl_segment_report_module.c b/libdwfl/dwfl_segment_report_module.c
index 55f6d38..fd967e9 100644
--- a/libdwfl/dwfl_segment_report_module.c
+++ b/libdwfl/dwfl_segment_report_module.c
@@ -427,7 +427,10 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
/* We must have seen the segment covering offset 0, or else the ELF
header we read at START was not produced by these program headers. */
if (unlikely (!found_bias))
- return finish ();
+ {
+ free (build_id);
+ return finish ();
+ }
/* Now we know enough to report a module for sure: its bounds. */
module_start += bias;
@@ -519,7 +522,10 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
}
}
if (skip_this_module)
- return finish ();
+ {
+ free (build_id);
+ return finish ();
+ }
}
/* Our return value now says to skip the segments contained
--
1.7.1
10 years, 4 months
[PATCH] stack: Improve error checking and exit code handling.
by Mark Wielaard
Check up front whether we attached correctly, if not error out. Make sure
callbacks report -1 only on real errors and DWARF_CB_ABORT if exiting early
(but not in error). Handle all errors from frame callback in print_frames
after printing of good frames. Print as much information as possible like
tid, address and module name if known with error messages. Only exit with
exit code zero if everything went fine. Exit with error code one if there
were any non-fatal errors. Exit with error code two if no frames could be
printed or a fatal error occurred.
Signed-off-by: Mark Wielaard <mjw(a)redhat.com>
---
src/ChangeLog | 17 ++++++++++
src/stack.c | 102 +++++++++++++++++++++++++++++++++++++++++++++-------------
2 files changed, 97 insertions(+), 22 deletions(-)
diff --git a/src/ChangeLog b/src/ChangeLog
index 142a1c3..7911236 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,20 @@
+2013-12-27 Mark Wielaard <mjw(a)redhat.com>
+
+ * stack.c (frames_shown): New static boolean.
+ (EXIT_OK,EXIT_ERROR,EXIT_BAD,EXIT_USAGES): New defines.
+ (frame_callback): Return -1 on error. Don't print error.
+ (print_frames): Add arguments, tid, dwflerr and what. Print tid.
+ If there was an error report it with address and module if possible.
+ Record whether any frames were actually printed.
+ (thread_callback): Collect tid and err, pass it to print_frames.
+ (parse_opt): Use EXIT_BAD for errors. On ARGP_KEY_END print errno
+ if dwfl_linux_proc_report returned it. Check whether we are properly
+ attached with dwfl_pid.
+ (main): Document exit status. Don't report DWARF_CB_ABORT from
+ callbacks as error. Pass real errors to print_frames. Return
+ EXIT_BAD if no frames could be shown. Return EXIT_ERROR if there
+ were any non-fatal errors.
+
2013-12-23 Mark Wielaard <mjw(a)redhat.com>
* Makefile.am (stack_LDADD): Add demanglelib.
diff --git a/src/stack.c b/src/stack.c
index 3568298..d71d669 100644
--- a/src/stack.c
+++ b/src/stack.c
@@ -90,6 +90,18 @@ static size_t demangle_buffer_len = 0;
static char *demangle_buffer = NULL;
#endif
+/* Whether any frames have been shown at all. Determines exit status. */
+static bool frames_shown = false;
+
+/* Program exit codes. All frames shown without any errors is GOOD.
+ Some frames shown with some non-fatal errors is an ERROR. A fatal
+ error or no frames shown at all is BAD. A command line USAGE exit
+ is generated by argp_error. */
+#define EXIT_OK 0
+#define EXIT_ERROR 1
+#define EXIT_BAD 2
+#define EXIT_USAGE 64
+
static int
frame_callback (Dwfl_Frame *state, void *arg)
{
@@ -97,10 +109,7 @@ frame_callback (Dwfl_Frame *state, void *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;
- }
+ return -1;
frames->frames++;
if (frames->frames == maxframes)
@@ -110,8 +119,12 @@ frame_callback (Dwfl_Frame *state, void *arg)
}
static void
-print_frames (struct frames *frames)
+print_frames (struct frames *frames, pid_t tid, int dwflerr, const char *what)
{
+ if (frames->frames > 0)
+ frames_shown = true;
+
+ printf ("TID %d:\n", tid);
for (unsigned nr = 0; nr < frames->frames; nr++)
{
Dwarf_Addr pc = frames->frame[nr].pc;
@@ -209,13 +222,39 @@ print_frames (struct frames *frames)
}
printf ("\n");
}
+ if (dwflerr != 0)
+ {
+ if (frames->frames > 0)
+ {
+ unsigned nr = frames->frames - 1;
+ Dwarf_Addr pc = frames->frame[nr].pc;
+ bool isactivation = frames->frame[nr].isactivation;
+ Dwarf_Addr pc_adjusted = pc - (isactivation ? 0 : 1);
+ Dwfl_Module *mod = dwfl_addrmodule (dwfl, pc_adjusted);
+ const char *mainfile = NULL;
+ const char *modname = dwfl_module_info (mod, NULL, NULL, NULL, NULL,
+ NULL, &mainfile, NULL);
+ if (modname == NULL || modname[0] == '\0')
+ {
+ if (mainfile != NULL)
+ modname = mainfile;
+ else
+ modname = "<unknown>";
+ }
+ error (0, 0, "%s tid %d at 0x%" PRIx64 " in %s: %s", what, tid,
+ pc_adjusted, modname, dwfl_errmsg (dwflerr));
+ }
+ else
+ error (0, 0, "%s tid %d: %s", what, tid, dwfl_errmsg (dwflerr));
+ }
}
static int
thread_callback (Dwfl_Thread *thread, void *thread_arg)
{
- printf ("TID %ld:\n", (long) dwfl_thread_tid (thread));
struct frames *frames = (struct frames *) thread_arg;
+ pid_t tid = dwfl_thread_tid (thread);
+ int err = 0;
frames->frames = 0;
switch (dwfl_thread_getframes (thread, frame_callback, thread_arg))
{
@@ -223,12 +262,12 @@ thread_callback (Dwfl_Thread *thread, void *thread_arg)
case DWARF_CB_ABORT:
break;
case -1:
- error (0, 0, "dwfl_thread_getframes: %s", dwfl_errmsg (-1));
+ err = dwfl_errno ();
break;
default:
abort ();
}
- print_frames (frames);
+ print_frames (frames, tid, err, "dwfl_thread_getframes");
return DWARF_CB_OK;
}
@@ -253,11 +292,11 @@ parse_opt (int key, char *arg __attribute__ ((unused)),
case OPT_COREFILE:
core_fd = open (arg, O_RDONLY);
if (core_fd < 0)
- error (2, errno, N_("Cannot open core file '%s'."), arg);
+ error (EXIT_BAD, errno, N_("Cannot open core file '%s'"), arg);
elf_version (EV_CURRENT);
core = elf_begin (core_fd, ELF_C_READ_MMAP, NULL);
if (core == NULL)
- error (2, 0, "core '%s' elf_begin: %s", arg, elf_errmsg(-1));
+ error (EXIT_BAD, 0, "core '%s' elf_begin: %s", arg, elf_errmsg(-1));
break;
case 'e':
@@ -328,22 +367,31 @@ parse_opt (int key, char *arg __attribute__ ((unused)),
{
dwfl = dwfl_begin (&proc_callbacks);
if (dwfl == NULL)
- error (2, 0, "dwfl_begin: %s", dwfl_errmsg (-1));
- if (dwfl_linux_proc_report (dwfl, pid) != 0)
- error (2, 0, "dwfl_linux_proc_report: %s", dwfl_errmsg (-1));
+ error (EXIT_BAD, 0, "dwfl_begin: %s", dwfl_errmsg (-1));
+
+ int err = dwfl_linux_proc_report (dwfl, pid);
+ if (err < 0)
+ error (EXIT_BAD, 0, "dwfl_linux_proc_report pid %d: %s", pid,
+ dwfl_errmsg (-1));
+ else if (err > 0)
+ error (EXIT_BAD, err, "dwfl_linux_proc_report pid %d", pid);
}
if (core != NULL)
{
dwfl = dwfl_begin (&core_callbacks);
if (dwfl == NULL)
- error (2, 0, "dwfl_begin: %s", dwfl_errmsg (-1));
+ error (EXIT_BAD, 0, "dwfl_begin: %s", dwfl_errmsg (-1));
if (dwfl_core_file_report (dwfl, core, exec) < 0)
- error (2, 0, "dwfl_core_file_report: %s", dwfl_errmsg (-1));
+ error (EXIT_BAD, 0, "dwfl_core_file_report: %s", dwfl_errmsg (-1));
}
if (dwfl_report_end (dwfl, NULL, NULL) != 0)
- error (2, 0, "dwfl_report_end: %s", dwfl_errmsg (-1));
+ error (EXIT_BAD, 0, "dwfl_report_end: %s", dwfl_errmsg (-1));
+
+ /* Makes sure we are properly attached. */
+ if (dwfl_pid (dwfl) < 0)
+ error (EXIT_BAD, 0, "dwfl_pid: %s\n", dwfl_errmsg (-1));
break;
default:
@@ -402,7 +450,13 @@ main (int argc, char **argv)
{
.options = options,
.parser = parse_opt,
- .doc = N_("Print a stack for each thread in a process or core file."),
+ .doc = N_("Print a stack for each thread in a process or core file.\v\
+Program exits with return code 0 if all frames were shown without \
+any errors. If some frames were shown, but there were some non-fatal \
+errors, possibly causing an incomplete backtrace, the program exits \
+with return code 1. If no frames could be shown, or a fatal error \
+occured the program exits with return code 2. If the program was \
+invoked with bad or missing arguments it will exit with return code 64.")
};
argp_parse (&argp, argc, argv, 0, NULL, NULL);
@@ -413,19 +467,19 @@ main (int argc, char **argv)
if (show_one_tid)
{
- printf ("TID %d:\n", pid);
+ int err = 0;
switch (dwfl_getthread_frames (dwfl, pid, frame_callback, frames))
{
case DWARF_CB_OK:
+ case DWARF_CB_ABORT:
break;
case -1:
- error (0, 0, "dwfl_getthread_frames (%d): %s", pid,
- dwfl_errmsg (-1));
+ err = dwfl_errno ();
break;
default:
abort ();
}
- print_frames (frames);
+ print_frames (frames, pid, err, "dwfl_getthread_frames");
}
else
{
@@ -433,6 +487,7 @@ main (int argc, char **argv)
switch (dwfl_getthreads (dwfl, thread_callback, frames))
{
case DWARF_CB_OK:
+ case DWARF_CB_ABORT:
break;
case -1:
error (0, 0, "dwfl_getthreads: %s", dwfl_errmsg (-1));
@@ -454,5 +509,8 @@ main (int argc, char **argv)
free (demangle_buffer);
#endif
- return 0;
+ if (! frames_shown)
+ error (EXIT_BAD, 0, N_("Couldn't show any frames."));
+
+ return error_message_count != 0 ? EXIT_ERROR : EXIT_OK;
}
--
1.8.4.2
10 years, 4 months