summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Wielaard <[email protected]>2014-01-03 22:49:44 +0100
committerMark Wielaard <[email protected]>2014-01-03 22:49:44 +0100
commit14e5056319def0555bc4183488e7af5c14a3fb28 (patch)
treede729f791c5ec247d90d95f0b97cee91bcbaebbd
parent7cd12085203e55f063f8a9b048d6102bc774d0e5 (diff)
parent70db4cc41d7e0516aecc477fd6aab2ba693029af (diff)
Merge branch 'master' into robustify
-rw-r--r--.gitignore1
-rw-r--r--ChangeLog59
-rw-r--r--NEWS19
-rw-r--r--README7
-rw-r--r--backends/ChangeLog77
-rw-r--r--backends/Makefile.am30
-rw-r--r--backends/aarch64_cfi.c82
-rw-r--r--backends/aarch64_corenote.c162
-rw-r--r--backends/aarch64_init.c63
-rw-r--r--backends/aarch64_regs.c95
-rw-r--r--backends/aarch64_reloc.def157
-rw-r--r--backends/aarch64_retval.c375
-rw-r--r--backends/aarch64_symbol.c84
-rw-r--r--backends/i386_init.c5
-rw-r--r--backends/i386_initreg.c79
-rw-r--r--backends/libebl_CPU.h37
-rw-r--r--backends/ppc64_init.c34
-rw-r--r--backends/ppc64_resolve_sym.c63
-rw-r--r--backends/ppc_cfi.c2
-rw-r--r--backends/ppc_corenote.c2
-rw-r--r--backends/ppc_init.c4
-rw-r--r--backends/ppc_initreg.c114
-rw-r--r--backends/s390_corenote.c10
-rw-r--r--backends/s390_init.c9
-rw-r--r--backends/s390_initreg.c95
-rw-r--r--backends/s390_unwind.c139
-rw-r--r--backends/x86_64_init.c5
-rw-r--r--backends/x86_64_initreg.c73
-rw-r--r--config/ChangeLog8
-rw-r--r--config/elfutils.spec.in15
-rw-r--r--config/eu.am2
-rw-r--r--configure.ac28
-rw-r--r--lib/ChangeLog4
-rw-r--r--lib/dynamicsizehash.c5
-rw-r--r--libasm/Makefile.am2
-rw-r--r--libdw/ChangeLog109
-rw-r--r--libdw/Makefile.am8
-rw-r--r--libdw/cfi.c4
-rw-r--r--libdw/cfi.h6
-rw-r--r--libdw/dwarf_formref_die.c1
-rw-r--r--libdw/dwarf_getaranges.c7
-rw-r--r--libdw/dwarf_getfuncs.c26
-rw-r--r--libdw/dwarf_getlocation.c14
-rw-r--r--libdw/dwarf_getlocation_attr.c8
-rw-r--r--libdw/dwarf_getlocation_implicit_pointer.c16
-rw-r--r--libdw/libdw.map25
-rw-r--r--libdw/libdwP.h40
-rw-r--r--libdw/libdw_findcu.c3
-rw-r--r--libdw/libdw_form.c32
-rw-r--r--libdw/memory-access.h107
-rw-r--r--libdwfl/ChangeLog365
-rw-r--r--libdwfl/Makefile.am6
-rw-r--r--libdwfl/argp-std.c43
-rw-r--r--libdwfl/core-file.c122
-rw-r--r--libdwfl/derelocate.c13
-rw-r--r--libdwfl/dwfl_build_id_find_elf.c17
-rw-r--r--libdwfl/dwfl_end.c5
-rw-r--r--libdwfl/dwfl_frame.c442
-rw-r--r--libdwfl/dwfl_frame_pc.c64
-rw-r--r--libdwfl/dwfl_frame_regs.c57
-rw-r--r--libdwfl/dwfl_module.c6
-rw-r--r--libdwfl/dwfl_module_addrname.c6
-rw-r--r--libdwfl/dwfl_module_addrsym.c247
-rw-r--r--libdwfl/dwfl_module_getdwarf.c68
-rw-r--r--libdwfl/dwfl_module_getsym.c85
-rw-r--r--libdwfl/dwfl_module_info.c2
-rw-r--r--libdwfl/dwfl_segment_report_module.c40
-rw-r--r--libdwfl/frame_unwind.c720
-rw-r--r--libdwfl/libdwfl.h258
-rw-r--r--libdwfl/libdwflP.h166
-rw-r--r--libdwfl/link_map.c21
-rw-r--r--libdwfl/linux-core-attach.c421
-rw-r--r--libdwfl/linux-kernel-modules.c9
-rw-r--r--libdwfl/linux-pid-attach.c349
-rw-r--r--libdwfl/linux-proc-maps.c14
-rw-r--r--libdwfl/relocate.c2
-rw-r--r--libdwfl/segment.c21
-rw-r--r--libebl/ChangeLog55
-rw-r--r--libebl/Makefile.am5
-rw-r--r--libebl/ebl-hooks.h35
-rw-r--r--libebl/ebldwarftoregno.c (renamed from libdw/memory-access.c)25
-rw-r--r--libebl/eblinitreg.c51
-rw-r--r--libebl/eblnormalizepc.c40
-rw-r--r--libebl/eblopenbackend.c3
-rw-r--r--libebl/eblresolvesym.c43
-rw-r--r--libebl/eblunwind.c43
-rw-r--r--libebl/libebl.h68
-rw-r--r--libebl/libeblP.h11
-rw-r--r--libelf/ChangeLog18
-rw-r--r--libelf/Makefile.am2
-rw-r--r--libelf/elf.h152
-rw-r--r--libelf/elf32_updatefile.c8
-rw-r--r--m4/ChangeLog9
-rw-r--r--m4/biarch.m447
-rw-r--r--po/ChangeLog4
-rw-r--r--po/de.po221
-rw-r--r--po/es.po222
-rw-r--r--po/ja.po221
-rw-r--r--po/pl.po222
-rw-r--r--po/uk.po322
-rw-r--r--src/ChangeLog173
-rw-r--r--src/Makefile.am6
-rw-r--r--src/addr2line.c54
-rw-r--r--src/ar.c2
-rw-r--r--src/arlib.c12
-rw-r--r--src/elflint.c4
-rw-r--r--src/nm.c3
-rw-r--r--src/readelf.c23
-rw-r--r--src/stack.c607
-rw-r--r--tests/ChangeLog219
-rw-r--r--tests/Makefile.am79
-rw-r--r--tests/allfcts.c2
-rw-r--r--tests/backtrace-child.c223
-rw-r--r--tests/backtrace-data.c328
-rw-r--r--tests/backtrace-dwarf.c161
-rw-r--r--tests/backtrace-subr.sh126
-rw-r--r--tests/backtrace.c464
-rw-r--r--tests/backtrace.i386.core.bz2bin0 -> 8777 bytes
-rw-r--r--tests/backtrace.i386.exec.bz2bin0 -> 383356 bytes
-rw-r--r--tests/backtrace.ppc.core.bz2bin0 -> 46357 bytes
-rw-r--r--tests/backtrace.ppc.exec.bz2bin0 -> 352898 bytes
-rw-r--r--tests/backtrace.s390.core.bz2bin0 -> 7375 bytes
-rw-r--r--tests/backtrace.s390.exec.bz2bin0 -> 352692 bytes
-rw-r--r--tests/backtrace.s390x.core.bz2bin0 -> 7740 bytes
-rw-r--r--tests/backtrace.s390x.exec.bz2bin0 -> 347228 bytes
-rw-r--r--tests/backtrace.x86_64.core.bz2bin0 -> 11115 bytes
-rw-r--r--tests/backtrace.x86_64.exec.bz2bin0 -> 401581 bytes
-rw-r--r--tests/cleanup-13.c334
-rw-r--r--tests/dwflsyms.c116
-rw-r--r--tests/funcretval_test.c828
-rwxr-xr-xtests/funcretval_test_aarch64.bz2bin0 -> 15644 bytes
-rw-r--r--tests/hello_aarch64.ko.bz2bin0 -> 12768 bytes
-rwxr-xr-xtests/run-addrcfi.sh80
-rwxr-xr-xtests/run-addrname-test.sh35
-rwxr-xr-xtests/run-allfcts-multi.sh56
-rwxr-xr-xtests/run-allregs.sh74
-rwxr-xr-xtests/run-arsymtest.sh2
-rwxr-xr-xtests/run-backtrace-core-i386.sh20
-rwxr-xr-xtests/run-backtrace-core-ppc.sh20
-rwxr-xr-xtests/run-backtrace-core-s390.sh20
-rwxr-xr-xtests/run-backtrace-core-s390x.sh20
-rwxr-xr-xtests/run-backtrace-core-x86_64.sh20
-rwxr-xr-xtests/run-backtrace-data.sh28
-rwxr-xr-xtests/run-backtrace-dwarf.sh30
-rwxr-xr-xtests/run-backtrace-native-biarch.sh24
-rwxr-xr-xtests/run-backtrace-native-core-biarch.sh24
-rwxr-xr-xtests/run-backtrace-native-core.sh20
-rwxr-xr-xtests/run-backtrace-native.sh20
-rwxr-xr-xtests/run-dwflsyms.sh704
-rwxr-xr-xtests/run-funcretval.sh153
-rwxr-xr-xtests/run-readelf-mixed-corenote.sh140
-rwxr-xr-xtests/run-readelf-s.sh77
-rwxr-xr-xtests/run-strip-reloc.sh6
-rwxr-xr-xtests/run-typeiter.sh4
-rwxr-xr-xtests/run-unstrip-M.sh51
-rw-r--r--tests/test-offset-loop.alt.bz2bin0 -> 685 bytes
-rwxr-xr-xtests/test-offset-loop.bz2bin0 -> 3062 bytes
-rwxr-xr-xtests/testfile66.bz2bin0 -> 741 bytes
-rw-r--r--tests/testfile66.core.bz2bin0 -> 56448 bytes
-rw-r--r--tests/testfile_aarch64_core.bz2bin0 -> 61748 bytes
-rwxr-xr-xtests/testfileaarch64.bz2bin0 -> 3441 bytes
-rwxr-xr-xtests/testfilebazdbg_pl.bz2bin0 -> 2589 bytes
-rwxr-xr-xtests/testfilebazdbg_plr.bz2bin0 -> 2241 bytes
-rwxr-xr-xtests/testfilebazdbgppc64.bz2bin0 -> 2366 bytes
-rwxr-xr-xtests/testfilebazdbgppc64.debug.bz2bin0 -> 2295 bytes
-rwxr-xr-xtests/testfilebazdbgppc64_pl.bz2bin0 -> 2775 bytes
-rwxr-xr-xtests/testfilebazdbgppc64_plr.bz2bin0 -> 2399 bytes
-rwxr-xr-xtests/testfilebazdynppc64.bz2bin0 -> 2327 bytes
-rwxr-xr-xtests/testfilebazmdb.bz2bin3259 -> 3313 bytes
-rwxr-xr-xtests/testfilebazmdbppc64.bz2bin0 -> 3528 bytes
-rwxr-xr-xtests/testfilebazmin.bz2bin3194 -> 3323 bytes
-rwxr-xr-xtests/testfilebazmin_pl.bz2bin0 -> 3749 bytes
-rwxr-xr-xtests/testfilebazmin_plr.bz2bin0 -> 3337 bytes
-rwxr-xr-xtests/testfilebazminppc64.bz2bin0 -> 3464 bytes
-rwxr-xr-xtests/testfilebazminppc64_pl.bz2bin0 -> 3900 bytes
-rwxr-xr-xtests/testfilebazminppc64_plr.bz2bin0 -> 3535 bytes
-rwxr-xr-xtests/testfilebaztabppc64.bz2bin0 -> 3697 bytes
-rw-r--r--tests/typeiter2.c89
-rw-r--r--tests/varlocs.c2
179 files changed, 12216 insertions, 1015 deletions
diff --git a/.gitignore b/.gitignore
index d4635563..1eda00b8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -25,6 +25,7 @@ config.h
config.h.in
config.log
config.status
+config/ar-lib
config/config.guess
config/config.sub
config/depcomp
diff --git a/ChangeLog b/ChangeLog
index 0b626eea..c3bea171 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,62 @@
+2014-01-03 Mark Wielaard <[email protected]>
+
+ * configure.ac: Set version to 0.158.
+ * NEWS: Add entries for version 0.158.
+
+2013-12-20 Mark Wielaard <[email protected]>
+
+ * NEWS (libdwfl): Add dwfl_getthread_frames.
+ (stack): New entry.
+
+2013-12-18 Mark Wielaard <[email protected]>
+
+ * NEWS (libdwfl): Add dwfl_module_getsym_info and
+ dwfl_module_addrinfo.
+ (addr2line): Add -x option.
+
+2013-12-17 Jan Kratochvil <[email protected]>
+
+ * NEWS (Version 0.158) (libdwfl): Added Dwfl_Thread_Callbacks,
+ Dwfl_Thread, Dwfl_Frame, 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.
+
+2013-12-16 Mark Wielaard <[email protected]>
+
+ * NEWS (libdwfl): Add dwfl_module_getsymtab_first_global.
+
+2013-12-09 Josh Stone <[email protected]>
+
+ * .gitignore: Add config/ar-lib, installed due to AM_PROG_AR.
+
+2013-12-02 Jan Kratochvil <[email protected]>
+
+ * configure.ac (CC_BIARCH): Remove AS_IF for it.
+
+2013-11-07 Jan Kratochvil <[email protected]>
+
+ * configure.ac: New AC_CHECK_SIZEOF for long. Call utrace_BIARCH, new
+ AC_SUBST for CC_BIARCH.
+
+2013-11-06 Mark Wielaard <[email protected]>
+
+ * configure.ac (--enable-dwz): Add AC_MSG_WARN when disabled but
+ local system does have /usr/lib/debug/.dwz.
+
+2013-11-06 Mark Wielaard <[email protected]>
+
+ * configure.ac (--enable-thread-safety): Add AC_MSG_WARN experimental
+ option.
+
+2013-11-01 Michael Forney <[email protected]>
+
+ * configure.ac: Call AM_PROG_AR and AC_CHECK_TOOL for readelf and nm.
+
+2013-10-30 Jan Kratochvil <[email protected]>
+
+ * NEWS (Version 0.158): New.
+
2013-09-30 Mark Wielaard <[email protected]>
* NEWS: Update for readelf NT_SIGINFO and NT_FILE core notes.
diff --git a/NEWS b/NEWS
index 7236f661..44f1959a 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,22 @@
+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.
+
Version 0.157
libdw: Add new functions dwarf_getlocations, dwarf_getlocation_attr
diff --git a/README b/README
index 33cac74f..f7e4b61e 100644
--- a/README
+++ b/README
@@ -10,3 +10,10 @@ Fundamental design decision:
users must match. No third-party EBL module are supported or allowed.
The only reason there are separate modules is to not have the code for
all architectures in all the binaries.
+
+- although the public libraries (libasm, libdw) have a stable API and are
+ backwards ABI compatible they, and the elfutils tools, do depend on each
+ others internals, and on internals of libelf to provide their interfaces.
+ So they should always be upgraded in lockstep when packaging the tools
+ and libraries separately. For one example of how to do that, see the
+ config/elfutils.spec.
diff --git a/backends/ChangeLog b/backends/ChangeLog
index 3409010d..2074cff3 100644
--- a/backends/ChangeLog
+++ b/backends/ChangeLog
@@ -1,3 +1,80 @@
+2014-01-03 Mark Wielaard <[email protected]>
+
+ * 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 <[email protected]>
+
+ * aarch64_init.c (aarch64_init): Hook check_special_symbol.
+ * aarch64_symbol.c (aarch64_check_special_symbol): New function.
+
+2013-12-18 Mark Wielaard <[email protected]>
+
+ * Makefile.am (ppc64_SRCS): Add ppc64_resolve_sym.c.
+ * ppc64_resolve_sym.c: New file.
+ * ppc64_init.c: Hook resolve_sym_value and find function descriptor
+ table.
+
+2013-12-18 Mark Wielaard <[email protected]>
+
+ * s390_initreg.c (s390_set_initial_registers_tid): Use union
+ to avoid type-punning when assigning a double to a Dwarf_Word.
+
+2013-12-18 Jan Kratochvil <[email protected]>
+
+ unwinder: s390 and s390x
+ * Makefile.am (s390_SRCS): Add s390_initreg.c and s390_unwind.c.
+ * s390_corenote.c (prstatus_regs): Set PC_REGISTER. Reindent all the
+ entries.
+ * s390_init.c (s390_init): Initialize frame_nregs,
+ set_initial_registers_tid, normalize_pc and unwind.
+ * s390_initreg.c: New file.
+ * s390_unwind.c: New file.
+
+2013-12-15 Jan Kratochvil <[email protected]>
+
+ unwinder: ppc and ppc64
+ * Makefile.am (ppc_SRCS, ppc64_SRCS): Add ppc_initreg.c.
+ * ppc64_init.c (ppc64_init): Initialize also frame_nregs,
+ set_initial_registers_tid and dwarf_to_regno.
+ * ppc_corenote.c (PRSTATUS_REGSET_ITEMS) <nip>: Set PC_REGISTER.
+ * ppc_init.c (ppc64_init): Initialize also frame_nregs,
+ set_initial_registers_tid and dwarf_to_regno.
+ * ppc_initreg.c: New file.
+
+2013-11-25 Petr Machata <[email protected]>
+
+ * Makefile.am (modules): Add aarch64.
+ (libebl_pic): Add libebl_aarch64_pic.a.
+ (aarch64_SRCS): New variable.
+ (libebl_aarch64_pic_a_SOURCES): Likewise.
+ (am_libebl_aarch64_pic_a_OBJECTS): Likewise.
+ (aarch64_regs_no_Wformat): Likewise.
+ * aarch64_corenote.c, aarch64_init.c: New files.
+ * aarch64_regs.c, aarch64_reloc.def: Likewise.
+ * aarch64_retval.c, aarch64_symbol.c: Likewise.
+ * libebl_CPU.h (dwarf_peel_type): New function.
+ (dwarf_peeled_die_type): Likewise.
+
+2013-11-07 Jan Kratochvil <[email protected]>
+ Mark Wielaard <[email protected]>
+
+ * Makefile.am (i386_SRCS): Add i386_initreg.c.
+ (x86_64_SRCS): Add x86_64_initreg.c.
+ * i386_initreg.c: New file.
+ * i386_init.c (i386_init): Initialize frame_nregs and
+ set_initial_registers_tid.
+ * x86_64_initreg.c: New file.
+ * x86_64_init.c (x86_64_init): Initialize frame_nregs and
+ set_initial_registers_tid.
+
+2013-10-06 Mark Wielaard <[email protected]>
+
+ * ppc_cfi.c (ppc_abi_cfi): Use DW_CFA_val_offset for reg1, not
+ DW_CFA_val_expression.
+
2013-08-29 Mark Wielaard <[email protected]>
* Makefile.am (arm_SRCS): Add arm_cfi.c.
diff --git a/backends/Makefile.am b/backends/Makefile.am
index 557ed879..b8bea36b 100644
--- a/backends/Makefile.am
+++ b/backends/Makefile.am
@@ -32,11 +32,12 @@ AM_CPPFLAGS += -I$(top_srcdir)/libebl -I$(top_srcdir)/libasm \
-I$(top_srcdir)/libelf -I$(top_srcdir)/libdw
-modules = i386 sh x86_64 ia64 alpha arm sparc ppc ppc64 s390 tilegx
-libebl_pic = libebl_i386_pic.a libebl_sh_pic.a libebl_x86_64_pic.a \
- libebl_ia64_pic.a libebl_alpha_pic.a libebl_arm_pic.a \
- libebl_sparc_pic.a libebl_ppc_pic.a libebl_ppc64_pic.a \
- libebl_s390_pic.a libebl_tilegx_pic.a
+modules = i386 sh x86_64 ia64 alpha arm aarch64 sparc ppc ppc64 s390 \
+ tilegx
+libebl_pic = libebl_i386_pic.a libebl_sh_pic.a libebl_x86_64_pic.a \
+ libebl_ia64_pic.a libebl_alpha_pic.a libebl_arm_pic.a \
+ libebl_aarch64_pic.a libebl_sparc_pic.a libebl_ppc_pic.a \
+ libebl_ppc64_pic.a libebl_s390_pic.a libebl_tilegx_pic.a
noinst_LIBRARIES = $(libebl_pic)
noinst_DATA = $(libebl_pic:_pic.a=.so)
@@ -50,7 +51,8 @@ libdw = ../libdw/libdw.so
endif
i386_SRCS = i386_init.c i386_symbol.c i386_corenote.c i386_cfi.c \
- i386_retval.c i386_regs.c i386_auxv.c i386_syscall.c
+ i386_retval.c i386_regs.c i386_auxv.c i386_syscall.c \
+ i386_initreg.c
cpu_i386 = ../libcpu/libcpu_i386.a
libebl_i386_pic_a_SOURCES = $(i386_SRCS)
am_libebl_i386_pic_a_OBJECTS = $(i386_SRCS:.c=.os)
@@ -60,7 +62,8 @@ libebl_sh_pic_a_SOURCES = $(sh_SRCS)
am_libebl_sh_pic_a_OBJECTS = $(sh_SRCS:.c=.os)
x86_64_SRCS = x86_64_init.c x86_64_symbol.c x86_64_corenote.c x86_64_cfi.c \
- x86_64_retval.c x86_64_regs.c i386_auxv.c x86_64_syscall.c
+ x86_64_retval.c x86_64_regs.c i386_auxv.c x86_64_syscall.c \
+ x86_64_initreg.c
cpu_x86_64 = ../libcpu/libcpu_x86_64.a
libebl_x86_64_pic_a_SOURCES = $(x86_64_SRCS)
am_libebl_x86_64_pic_a_OBJECTS = $(x86_64_SRCS:.c=.os)
@@ -79,6 +82,12 @@ arm_SRCS = arm_init.c arm_symbol.c arm_regs.c arm_corenote.c \
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_cfi.c
+libebl_aarch64_pic_a_SOURCES = $(aarch64_SRCS)
+am_libebl_aarch64_pic_a_OBJECTS = $(aarch64_SRCS:.c=.os)
+aarch64_regs_no_Wformat = yes
+
sparc_SRCS = sparc_init.c sparc_symbol.c sparc_regs.c sparc_retval.c \
sparc_corenote.c sparc64_corenote.c sparc_auxv.c
libebl_sparc_pic_a_SOURCES = $(sparc_SRCS)
@@ -86,18 +95,19 @@ am_libebl_sparc_pic_a_OBJECTS = $(sparc_SRCS:.c=.os)
ppc_SRCS = ppc_init.c ppc_symbol.c ppc_retval.c ppc_regs.c \
ppc_corenote.c ppc_auxv.c ppc_attrs.c ppc_syscall.c \
- ppc_cfi.c
+ ppc_cfi.c ppc_initreg.c
libebl_ppc_pic_a_SOURCES = $(ppc_SRCS)
am_libebl_ppc_pic_a_OBJECTS = $(ppc_SRCS:.c=.os)
ppc64_SRCS = ppc64_init.c ppc64_symbol.c ppc64_retval.c \
ppc64_corenote.c ppc_regs.c ppc_auxv.c ppc_attrs.c ppc_syscall.c \
- ppc_cfi.c
+ ppc_cfi.c ppc_initreg.c ppc64_resolve_sym.c
libebl_ppc64_pic_a_SOURCES = $(ppc64_SRCS)
am_libebl_ppc64_pic_a_OBJECTS = $(ppc64_SRCS:.c=.os)
s390_SRCS = s390_init.c s390_symbol.c s390_regs.c s390_retval.c \
- s390_corenote.c s390x_corenote.c s390_cfi.c
+ s390_corenote.c s390x_corenote.c s390_cfi.c s390_initreg.c \
+ s390_unwind.c
libebl_s390_pic_a_SOURCES = $(s390_SRCS)
am_libebl_s390_pic_a_OBJECTS = $(s390_SRCS:.c=.os)
diff --git a/backends/aarch64_cfi.c b/backends/aarch64_cfi.c
new file mode 100644
index 00000000..acbb9b69
--- /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_corenote.c b/backends/aarch64_corenote.c
new file mode 100644
index 00000000..8f5b9d5d
--- /dev/null
+++ b/backends/aarch64_corenote.c
@@ -0,0 +1,162 @@
+/* AArch64 specific core note handling.
+ 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 <elf.h>
+#include <inttypes.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <sys/time.h>
+
+#define BACKEND aarch64_
+#include "libebl_CPU.h"
+
+#define ULONG uint64_t
+#define PID_T int32_t
+#define UID_T uint32_t
+#define GID_T uint32_t
+#define ALIGN_ULONG 8
+#define ALIGN_PID_T 4
+#define ALIGN_UID_T 4
+#define ALIGN_GID_T 4
+#define TYPE_ULONG ELF_T_XWORD
+#define TYPE_PID_T ELF_T_SWORD
+#define TYPE_UID_T ELF_T_WORD
+#define TYPE_GID_T ELF_T_WORD
+
+#define PRSTATUS_REGS_SIZE (34 * 8)
+
+static const Ebl_Register_Location prstatus_regs[] =
+ {
+ { .offset = 0, .regno = 0, .count = 32, .bits = 64 }, /* x0..x30, sp */
+ };
+
+#define PRSTATUS_REGSET_ITEMS \
+ { \
+ .name = "pc", .type = ELF_T_XWORD, .format = 'x', \
+ .offset = (offsetof (struct EBLHOOK(prstatus), pr_reg) \
+ + PRSTATUS_REGS_SIZE - 16), \
+ .group = "register" \
+ }, \
+ { \
+ .name = "pstate", .type = ELF_T_XWORD, .format = 'x', \
+ .offset = (offsetof (struct EBLHOOK(prstatus), pr_reg) \
+ + PRSTATUS_REGS_SIZE - 8), \
+ .group = "register" \
+ }
+
+static const Ebl_Register_Location aarch64_fpregset_regs[] =
+ {
+ { .offset = 0, .regno = 64, .count = 32, .bits = 128 }, /* v0..v31 */
+ };
+
+static const Ebl_Core_Item aarch64_fpregset_items[] =
+ {
+ {
+ .name = "fpsr", .type = ELF_T_WORD, .format = 'x',
+ .offset = 512, .group = "register"
+ },
+ {
+ .name = "fpcr", .type = ELF_T_WORD, .format = 'x',
+ .offset = 516, .group = "register"
+ }
+ };
+
+static const Ebl_Core_Item aarch64_tls_items[] =
+ {
+ {
+ .name = "tls", .type = ELF_T_XWORD, .format = 'x',
+ .offset = 0, .group = "register"
+ }
+ };
+
+#define AARCH64_HWBP_REG(KIND, N) \
+ { \
+ .name = "DBG" KIND "VR" #N "_EL1", .type = ELF_T_XWORD, .format = 'x', \
+ .offset = 8 + N * 16, .group = "register" \
+ }, \
+ { \
+ .name = "DBG" KIND "CR" #N "_EL1", .type = ELF_T_WORD, .format = 'x', \
+ .offset = 16 + N * 16, .group = "register" \
+ }
+
+#define AARCH64_BP_WP_GROUP(KIND, NAME) \
+ static const Ebl_Core_Item NAME[] = \
+ { \
+ { \
+ .name = "dbg_info", .type = ELF_T_WORD, .format = 'x', \
+ .offset = 0, .group = "control" \
+ }, \
+ /* N.B.: 4 bytes of padding here. */ \
+ \
+ AARCH64_HWBP_REG(KIND, 0), \
+ AARCH64_HWBP_REG(KIND, 1), \
+ AARCH64_HWBP_REG(KIND, 2), \
+ AARCH64_HWBP_REG(KIND, 3), \
+ AARCH64_HWBP_REG(KIND, 4), \
+ AARCH64_HWBP_REG(KIND, 5), \
+ AARCH64_HWBP_REG(KIND, 6), \
+ AARCH64_HWBP_REG(KIND, 7), \
+ AARCH64_HWBP_REG(KIND, 8), \
+ AARCH64_HWBP_REG(KIND, 9), \
+ AARCH64_HWBP_REG(KIND, 10), \
+ AARCH64_HWBP_REG(KIND, 11), \
+ AARCH64_HWBP_REG(KIND, 12), \
+ AARCH64_HWBP_REG(KIND, 13), \
+ AARCH64_HWBP_REG(KIND, 14), \
+ AARCH64_HWBP_REG(KIND, 15), \
+ \
+ /* The DBGBVR+DBGBCR pair only takes 12 bytes. There are 4 bytes \
+ of padding at the end of each pair. The item formatter in \
+ readelf can skip those, but the missing 4 bytes at the end of \
+ the whole block cause it to assume the whole item bunch \
+ repeats, so it loops around to read more. Insert an explicit \
+ (but invisible) padding word. */ \
+ { \
+ .name = "", .type = ELF_T_WORD, .format = 'h', \
+ .offset = 260, .group = "register" \
+ } \
+ }
+
+AARCH64_BP_WP_GROUP ("B", aarch64_hw_bp_items);
+AARCH64_BP_WP_GROUP ("W", aarch64_hw_wp_items);
+
+#undef AARCH64_BP_WP_GROUP
+#undef AARCH64_HWBP_REG
+
+#define EXTRA_NOTES \
+ EXTRA_REGSET_ITEMS (NT_FPREGSET, 528, \
+ aarch64_fpregset_regs, aarch64_fpregset_items) \
+ EXTRA_ITEMS (NT_ARM_TLS, 8, aarch64_tls_items) \
+ EXTRA_ITEMS (NT_ARM_HW_BREAK, 264, aarch64_hw_bp_items) \
+ EXTRA_ITEMS (NT_ARM_HW_WATCH, 264, aarch64_hw_wp_items)
+
+#include "linux-core-note.c"
diff --git a/backends/aarch64_init.c b/backends/aarch64_init.c
new file mode 100644
index 00000000..a1a70606
--- /dev/null
+++ b/backends/aarch64_init.c
@@ -0,0 +1,63 @@
+/* Initialization of AArch64 specific backend library.
+ 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
+
+#define BACKEND aarch64_
+#define RELOC_PREFIX R_AARCH64_
+#include "libebl_CPU.h"
+
+/* This defines the common reloc hooks based on aarch64_reloc.def. */
+#include "common-reloc.c"
+
+
+const char *
+aarch64_init (elf, machine, eh, ehlen)
+ Elf *elf __attribute__ ((unused));
+ GElf_Half machine __attribute__ ((unused));
+ Ebl *eh;
+ size_t ehlen;
+{
+ /* Check whether the Elf_BH object has a sufficent size. */
+ if (ehlen < sizeof (Ebl))
+ return NULL;
+
+ /* We handle it. */
+ eh->name = "AARCH64";
+ aarch64_init_reloc (eh);
+ HOOK (eh, register_info);
+ HOOK (eh, core_note);
+ 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
new file mode 100644
index 00000000..aec201f3
--- /dev/null
+++ b/backends/aarch64_regs.c
@@ -0,0 +1,95 @@
+/* Register names and numbers for AArch64 DWARF.
+ 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 <stdio.h>
+#include <string.h>
+#include <dwarf.h>
+
+#define BACKEND aarch64_
+#include "libebl_CPU.h"
+
+ssize_t
+aarch64_register_info (Ebl *ebl __attribute__ ((unused)),
+ int regno, char *name, size_t namelen,
+ const char **prefix, const char **setnamep,
+ int *bits, int *typep)
+{
+ if (name == NULL)
+ return 128;
+
+ ssize_t
+ regtype (const char *setname, int type, const char *fmt, int arg)
+ {
+ *setnamep = setname;
+ *typep = type;
+ int s = snprintf (name, namelen, fmt, arg);
+ if (s < 0 || (unsigned) s >= namelen)
+ return -1;
+ return s + 1;
+ }
+
+ *prefix = "";
+ *bits = 64;
+
+ switch (regno)
+ {
+ case 0 ... 30:
+ return regtype ("integer", DW_ATE_signed, "x%d", regno);
+
+ case 31:
+ return regtype ("integer", DW_ATE_address, "sp", 0);
+
+ case 32:
+ return 0;
+
+ case 33:
+ return regtype ("integer", DW_ATE_address, "elr", 0);
+
+ case 34 ... 63:
+ return 0;
+
+ case 64 ... 95:
+ /* FP/SIMD register file supports a variety of data types--it
+ can be thought of as a register holding a single integer or
+ floating-point value, or a vector of 8-, 16-, 32- or 64-bit
+ integers. 128-bit quad-word is the only singular value that
+ covers the whole register, so mark the register thus. */
+ *bits = 128;
+ return regtype ("FP/SIMD", DW_ATE_unsigned, "v%d", regno - 64);
+
+ case 96 ... 127:
+ return 0;
+
+ default:
+ return -1;
+ }
+}
diff --git a/backends/aarch64_reloc.def b/backends/aarch64_reloc.def
new file mode 100644
index 00000000..f6331573
--- /dev/null
+++ b/backends/aarch64_reloc.def
@@ -0,0 +1,157 @@
+/* List the relocation types for AArch64. -*- C -*-
+ 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/>. */
+
+/* NAME, REL|EXEC|DYN */
+
+RELOC_TYPE (ABS64, EXEC|DYN)
+RELOC_TYPE (ABS32, EXEC|DYN)
+RELOC_TYPE (COPY, EXEC)
+RELOC_TYPE (GLOB_DAT, EXEC|DYN)
+RELOC_TYPE (JUMP_SLOT, EXEC|DYN)
+RELOC_TYPE (RELATIVE, EXEC|DYN)
+RELOC_TYPE (TLS_DTPMOD64, EXEC|DYN)
+RELOC_TYPE (TLS_DTPREL64, EXEC|DYN)
+RELOC_TYPE (TLS_TPREL64, EXEC|DYN)
+RELOC_TYPE (TLSDESC, EXEC|DYN)
+
+/* R_AARCH64_NONE records that the section containing the place to be
+ relocated depends on the section defining the symbol mentioned in
+ the relocation directive[.] (ARM IHI 0056B). */
+RELOC_TYPE (NONE, REL)
+
+RELOC_TYPE (ABS16, REL)
+RELOC_TYPE (PREL64, REL)
+RELOC_TYPE (PREL32, REL)
+RELOC_TYPE (PREL16, REL)
+RELOC_TYPE (MOVW_UABS_G0, REL)
+RELOC_TYPE (MOVW_UABS_G0_NC, REL)
+RELOC_TYPE (MOVW_UABS_G1, REL)
+RELOC_TYPE (MOVW_UABS_G1_NC, REL)
+RELOC_TYPE (MOVW_UABS_G2, REL)
+RELOC_TYPE (MOVW_UABS_G2_NC, REL)
+RELOC_TYPE (MOVW_UABS_G3, REL)
+RELOC_TYPE (MOVW_SABS_G0, REL)
+RELOC_TYPE (MOVW_SABS_G1, REL)
+RELOC_TYPE (MOVW_SABS_G2, REL)
+RELOC_TYPE (LD_PREL_LO19, REL)
+RELOC_TYPE (ADR_PREL_LO21, REL)
+RELOC_TYPE (ADR_PREL_PG_HI21, REL)
+RELOC_TYPE (ADR_PREL_PG_HI21_NC, REL)
+RELOC_TYPE (ADD_ABS_LO12_NC, REL)
+RELOC_TYPE (LDST8_ABS_LO12_NC, REL)
+RELOC_TYPE (LDST16_ABS_LO12_NC, REL)
+RELOC_TYPE (LDST32_ABS_LO12_NC, REL)
+RELOC_TYPE (LDST64_ABS_LO12_NC, REL)
+RELOC_TYPE (LDST128_ABS_LO12_NC, REL)
+RELOC_TYPE (TSTBR14, REL)
+RELOC_TYPE (CONDBR19, REL)
+RELOC_TYPE (JUMP26, REL)
+RELOC_TYPE (CALL26, REL)
+RELOC_TYPE (MOVW_PREL_G0, REL)
+RELOC_TYPE (MOVW_PREL_G0_NC, REL)
+RELOC_TYPE (MOVW_PREL_G1, REL)
+RELOC_TYPE (MOVW_PREL_G1_NC, REL)
+RELOC_TYPE (MOVW_PREL_G2, REL)
+RELOC_TYPE (MOVW_PREL_G2_NC, REL)
+RELOC_TYPE (MOVW_PREL_G3, REL)
+RELOC_TYPE (MOVW_GOTOFF_G0, REL)
+RELOC_TYPE (MOVW_GOTOFF_G0_NC, REL)
+RELOC_TYPE (MOVW_GOTOFF_G1, REL)
+RELOC_TYPE (MOVW_GOTOFF_G1_NC, REL)
+RELOC_TYPE (MOVW_GOTOFF_G2, REL)
+RELOC_TYPE (MOVW_GOTOFF_G2_NC, REL)
+RELOC_TYPE (MOVW_GOTOFF_G3, REL)
+RELOC_TYPE (GOTREL64, REL)
+RELOC_TYPE (GOTREL32, REL)
+RELOC_TYPE (GOT_LD_PREL19, REL)
+RELOC_TYPE (LD64_GOTOFF_LO15, REL)
+RELOC_TYPE (ADR_GOT_PAGE, REL)
+RELOC_TYPE (LD64_GOT_LO12_NC, REL)
+RELOC_TYPE (LD64_GOTPAGE_LO15, REL)
+RELOC_TYPE (TLSGD_ADR_PREL21, REL)
+RELOC_TYPE (TLSGD_ADR_PAGE21, REL)
+RELOC_TYPE (TLSGD_ADD_LO12_NC, REL)
+RELOC_TYPE (TLSGD_MOVW_G1, REL)
+RELOC_TYPE (TLSGD_MOVW_G0_NC, REL)
+RELOC_TYPE (TLSLD_ADR_PREL21, REL)
+RELOC_TYPE (TLSLD_ADR_PAGE21, REL)
+RELOC_TYPE (TLSLD_ADD_LO12_NC, REL)
+RELOC_TYPE (TLSLD_MOVW_G1, REL)
+RELOC_TYPE (TLSLD_MOVW_G0_NC, REL)
+RELOC_TYPE (TLSLD_LD_PREL19, REL)
+RELOC_TYPE (TLSLD_MOVW_DTPREL_G2, REL)
+RELOC_TYPE (TLSLD_MOVW_DTPREL_G1, REL)
+RELOC_TYPE (TLSLD_MOVW_DTPREL_G1_NC, REL)
+RELOC_TYPE (TLSLD_MOVW_DTPREL_G0, REL)
+RELOC_TYPE (TLSLD_MOVW_DTPREL_G0_NC, REL)
+RELOC_TYPE (TLSLD_ADD_DTPREL_HI12, REL)
+RELOC_TYPE (TLSLD_ADD_DTPREL_LO12, REL)
+RELOC_TYPE (TLSLD_ADD_DTPREL_LO12_NC, REL)
+RELOC_TYPE (TLSLD_LDST8_DTPREL_LO12, REL)
+RELOC_TYPE (TLSLD_LDST8_DTPREL_LO12_NC, REL)
+RELOC_TYPE (TLSLD_LDST16_DTPREL_LO12, REL)
+RELOC_TYPE (TLSLD_LDST16_DTPREL_LO12_NC, REL)
+RELOC_TYPE (TLSLD_LDST32_DTPREL_LO12, REL)
+RELOC_TYPE (TLSLD_LDST32_DTPREL_LO12_NC, REL)
+RELOC_TYPE (TLSLD_LDST64_DTPREL_LO12, REL)
+RELOC_TYPE (TLSLD_LDST64_DTPREL_LO12_NC, REL)
+RELOC_TYPE (TLSLD_LDST128_DTPREL_LO12, REL)
+RELOC_TYPE (TLSLD_LDST128_DTPREL_LO12_NC, REL)
+RELOC_TYPE (TLSIE_MOVW_GOTTPREL_G1, REL)
+RELOC_TYPE (TLSIE_MOVW_GOTTPREL_G0_NC, REL)
+RELOC_TYPE (TLSIE_ADR_GOTTPREL_PAGE21, REL)
+RELOC_TYPE (TLSIE_LD64_GOTTPREL_LO12_NC, REL)
+RELOC_TYPE (TLSIE_LD_GOTTPREL_PREL19, REL)
+RELOC_TYPE (TLSLE_MOVW_TPREL_G2, REL)
+RELOC_TYPE (TLSLE_MOVW_TPREL_G1, REL)
+RELOC_TYPE (TLSLE_MOVW_TPREL_G1_NC, REL)
+RELOC_TYPE (TLSLE_MOVW_TPREL_G0, REL)
+RELOC_TYPE (TLSLE_MOVW_TPREL_G0_NC, REL)
+RELOC_TYPE (TLSLE_ADD_TPREL_HI12, REL)
+RELOC_TYPE (TLSLE_ADD_TPREL_LO12, REL)
+RELOC_TYPE (TLSLE_ADD_TPREL_LO12_NC, REL)
+RELOC_TYPE (TLSLE_LDST8_TPREL_LO12, REL)
+RELOC_TYPE (TLSLE_LDST8_TPREL_LO12_NC, REL)
+RELOC_TYPE (TLSLE_LDST16_TPREL_LO12, REL)
+RELOC_TYPE (TLSLE_LDST16_TPREL_LO12_NC, REL)
+RELOC_TYPE (TLSLE_LDST32_TPREL_LO12, REL)
+RELOC_TYPE (TLSLE_LDST32_TPREL_LO12_NC, REL)
+RELOC_TYPE (TLSLE_LDST64_TPREL_LO12, REL)
+RELOC_TYPE (TLSLE_LDST64_TPREL_LO12_NC, REL)
+RELOC_TYPE (TLSLE_LDST128_TPREL_LO12, REL)
+RELOC_TYPE (TLSLE_LDST128_TPREL_LO12_NC, REL)
+RELOC_TYPE (TLSDESC_LD_PREL19, REL)
+RELOC_TYPE (TLSDESC_ADR_PREL21, REL)
+RELOC_TYPE (TLSDESC_ADR_PAGE21, REL)
+RELOC_TYPE (TLSDESC_LD64_LO12, REL)
+RELOC_TYPE (TLSDESC_ADD_LO12, REL)
+RELOC_TYPE (TLSDESC_OFF_G1, REL)
+RELOC_TYPE (TLSDESC_OFF_G0_NC, REL)
+RELOC_TYPE (TLSDESC_LDR, REL)
+RELOC_TYPE (TLSDESC_ADD, REL)
+RELOC_TYPE (TLSDESC_CALL, REL)
diff --git a/backends/aarch64_retval.c b/backends/aarch64_retval.c
new file mode 100644
index 00000000..0ed7d561
--- /dev/null
+++ b/backends/aarch64_retval.c
@@ -0,0 +1,375 @@
+/* Function return value location for Linux/AArch64 ABI.
+ 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 <stdio.h>
+#include <inttypes.h>
+
+#include <assert.h>
+#include <dwarf.h>
+
+#define BACKEND aarch64_
+#include "libebl_CPU.h"
+
+static int
+skip_until (Dwarf_Die *child, int tag)
+{
+ int i;
+ while (DWARF_TAG_OR_RETURN (child) != tag)
+ if ((i = dwarf_siblingof (child, child)) != 0)
+ /* If there are no members, then this is not a HFA. Errors
+ are propagated. */
+ return i;
+ return 0;
+}
+
+static int
+dwarf_bytesize_aux (Dwarf_Die *die, Dwarf_Word *sizep)
+{
+ int bits;
+ if (((bits = 8 * dwarf_bytesize (die)) < 0
+ && (bits = dwarf_bitsize (die)) < 0)
+ || bits % 8 != 0)
+ return -1;
+
+ *sizep = bits / 8;
+ return 0;
+}
+
+/* HFA (Homogeneous Floating-point Aggregate) is an aggregate type
+ whose members are all of the same floating-point type, which is
+ then base type of this HFA. Instead of being floating-point types
+ directly, members can instead themselves be HFA. Such HFA fields
+ are handled as if their type were HFA base type.
+
+ This function returns 0 if TYPEDIE is HFA, 1 if it is not, or -1 if
+ there were errors. In the former case, *SIZEP contains byte size
+ of the base type (e.g. 8 for IEEE double). *COUNT is set to the
+ number of leaf members of the HFA. */
+static int hfa_type (Dwarf_Die *ftypedie, int tag,
+ Dwarf_Word *sizep, Dwarf_Word *countp);
+
+/* Return 0 if MEMBDIE refers to a member with a floating-point or HFA
+ type, or 1 if it's not. Return -1 for errors. The meaning of the
+ remaining arguments is as documented at hfa_type. */
+static int
+member_is_fp (Dwarf_Die *membdie, Dwarf_Word *sizep, Dwarf_Word *countp)
+{
+ Dwarf_Die typedie;
+ int tag = dwarf_peeled_die_type (membdie, &typedie);
+ switch (tag)
+ {
+ case DW_TAG_base_type:;
+ Dwarf_Word encoding;
+ Dwarf_Attribute attr_mem;
+ if (dwarf_attr_integrate (&typedie, DW_AT_encoding, &attr_mem) == NULL
+ || dwarf_formudata (&attr_mem, &encoding) != 0)
+ return -1;
+
+ switch (encoding)
+ {
+ case DW_ATE_complex_float:
+ *countp = 2;
+ break;
+
+ case DW_ATE_float:
+ *countp = 1;
+ break;
+
+ default:
+ return 1;
+ }
+
+ if (dwarf_bytesize_aux (&typedie, sizep) < 0)
+ return -1;
+
+ *sizep /= *countp;
+ return 0;
+
+ case DW_TAG_structure_type:
+ case DW_TAG_union_type:
+ case DW_TAG_array_type:
+ return hfa_type (&typedie, tag, sizep, countp);
+ }
+
+ return 1;
+}
+
+static int
+hfa_type (Dwarf_Die *ftypedie, int tag, Dwarf_Word *sizep, Dwarf_Word *countp)
+{
+ assert (tag == DW_TAG_structure_type || tag == DW_TAG_class_type
+ || tag == DW_TAG_union_type || tag == DW_TAG_array_type);
+
+ int i;
+ if (tag == DW_TAG_array_type)
+ {
+ Dwarf_Word tot_size;
+ if (dwarf_aggregate_size (ftypedie, &tot_size) < 0)
+ return -1;
+
+ /* For vector types, we don't care about the underlying
+ type, but only about the vector type itself. */
+ bool vec;
+ Dwarf_Attribute attr_mem;
+ if (dwarf_formflag (dwarf_attr_integrate (ftypedie, DW_AT_GNU_vector,
+ &attr_mem), &vec) == 0
+ && vec)
+ {
+ *sizep = tot_size;
+ *countp = 1;
+
+ return 0;
+ }
+
+ if ((i = member_is_fp (ftypedie, sizep, countp)) == 0)
+ {
+ *countp = tot_size / *sizep;
+ return 0;
+ }
+
+ return i;
+ }
+
+ /* Find first DW_TAG_member and determine its type. */
+ Dwarf_Die member;
+ if ((i = dwarf_child (ftypedie, &member) != 0))
+ return i;
+
+ if ((i = skip_until (&member, DW_TAG_member)) != 0)
+ return i;
+
+ *countp = 0;
+ if ((i = member_is_fp (&member, sizep, countp)) != 0)
+ return i;
+
+ while ((i = dwarf_siblingof (&member, &member)) == 0
+ && (i = skip_until (&member, DW_TAG_member)) == 0)
+ {
+ Dwarf_Word size, count;
+ if ((i = member_is_fp (&member, &size, &count)) != 0)
+ return i;
+
+ if (*sizep != size)
+ return 1;
+
+ *countp += count;
+ }
+
+ /* At this point we already have at least one FP member, which means
+ FTYPEDIE is an HFA. So either return 0, or propagate error. */
+ return i < 0 ? i : 0;
+}
+
+static int
+pass_in_gpr (const Dwarf_Op **locp, Dwarf_Word size)
+{
+ static const Dwarf_Op loc[] =
+ {
+ { .atom = DW_OP_reg0 }, { .atom = DW_OP_piece, .number = 8 },
+ { .atom = DW_OP_reg1 }, { .atom = DW_OP_piece, .number = 8 }
+ };
+
+ *locp = loc;
+ return size <= 8 ? 1 : 4;
+}
+
+static int
+pass_by_ref (const Dwarf_Op **locp)
+{
+ static const Dwarf_Op loc[] = { { .atom = DW_OP_breg0 } };
+
+ *locp = loc;
+ return 1;
+}
+
+static int
+pass_hfa (const Dwarf_Op **locp, Dwarf_Word size, Dwarf_Word count)
+{
+ assert (count >= 1 && count <= 4);
+ assert (size == 2 || size == 4 || size == 8 || size == 16);
+
+#define DEFINE_FPREG(NAME, SIZE) \
+ static const Dwarf_Op NAME[] = { \
+ { .atom = DW_OP_regx, .number = 64 }, \
+ { .atom = DW_OP_piece, .number = SIZE }, \
+ { .atom = DW_OP_regx, .number = 65 }, \
+ { .atom = DW_OP_piece, .number = SIZE }, \
+ { .atom = DW_OP_regx, .number = 66 }, \
+ { .atom = DW_OP_piece, .number = SIZE }, \
+ { .atom = DW_OP_regx, .number = 67 }, \
+ { .atom = DW_OP_piece, .number = SIZE } \
+ }
+
+ switch (size)
+ {
+ case 2:;
+ DEFINE_FPREG (loc_hfa_2, 2);
+ *locp = loc_hfa_2;
+ break;
+
+ case 4:;
+ DEFINE_FPREG (loc_hfa_4, 4);
+ *locp = loc_hfa_4;
+ break;
+
+ case 8:;
+ DEFINE_FPREG (loc_hfa_8, 8);
+ *locp = loc_hfa_8;
+ break;
+
+ case 16:;
+ DEFINE_FPREG (loc_hfa_16, 16);
+ *locp = loc_hfa_16;
+ break;
+ }
+#undef DEFINE_FPREG
+
+ return count == 1 ? 1 : 2 * count;
+}
+
+static int
+pass_in_simd (const Dwarf_Op **locp)
+{
+ /* This is like passing single-element HFA. Size doesn't matter, so
+ pretend it's for example double. */
+ return pass_hfa (locp, 8, 1);
+}
+
+int
+aarch64_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
+{
+ /* Start with the function's type, and get the DW_AT_type attribute,
+ which is the type of the return value. */
+ Dwarf_Die typedie;
+ int tag = dwarf_peeled_die_type (functypedie, &typedie);
+ if (tag <= 0)
+ return tag;
+
+ Dwarf_Word size = (Dwarf_Word)-1;
+
+ /* If the argument type is a Composite Type that is larger than 16
+ bytes, then the argument is copied to memory allocated by the
+ caller and the argument is replaced by a pointer to the copy. */
+ if (tag == DW_TAG_structure_type || tag == DW_TAG_union_type
+ || tag == DW_TAG_class_type || tag == DW_TAG_array_type)
+ {
+ Dwarf_Word base_size, count;
+ switch (hfa_type (&typedie, tag, &base_size, &count))
+ {
+ default:
+ return -1;
+
+ case 0:
+ assert (count > 0);
+ if (count <= 4)
+ return pass_hfa (locp, base_size, count);
+ /* Fall through. */
+
+ case 1:
+ /* Not a HFA. */
+ if (dwarf_aggregate_size (&typedie, &size) < 0)
+ return -1;
+ if (size > 16)
+ return pass_by_ref (locp);
+ }
+ }
+
+ if (tag == DW_TAG_base_type
+ || tag == DW_TAG_pointer_type || tag == DW_TAG_ptr_to_member_type)
+ {
+ if (dwarf_bytesize_aux (&typedie, &size) < 0)
+ {
+ if (tag == DW_TAG_pointer_type || tag == DW_TAG_ptr_to_member_type)
+ size = 8;
+ else
+ return -1;
+ }
+
+ Dwarf_Attribute attr_mem;
+ if (tag == DW_TAG_base_type)
+ {
+ Dwarf_Word encoding;
+ if (dwarf_formudata (dwarf_attr_integrate (&typedie, DW_AT_encoding,
+ &attr_mem),
+ &encoding) != 0)
+ return -1;
+
+ switch (encoding)
+ {
+ /* If the argument is a Half-, Single-, Double- or Quad-
+ precision Floating-point [...] the argument is allocated
+ to the least significant bits of register v[NSRN]. */
+ case DW_ATE_float:
+ switch (size)
+ {
+ case 2: /* half */
+ case 4: /* sigle */
+ case 8: /* double */
+ case 16: /* quad */
+ return pass_in_simd (locp);
+
+ default:
+ return -2;
+ }
+
+ case DW_ATE_complex_float:
+ switch (size)
+ {
+ case 8: /* float _Complex */
+ case 16: /* double _Complex */
+ case 32: /* long double _Complex */
+ return pass_hfa (locp, size / 2, 2);
+
+ default:
+ return -2;
+ }
+
+ /* If the argument is an Integral or Pointer Type, the
+ size of the argument is less than or equal to 8 bytes
+ [...] the argument is copied to the least significant
+ bits in x[NGRN]. */
+ case DW_ATE_signed:
+ case DW_ATE_unsigned:
+ case DW_ATE_unsigned_char:
+ case DW_ATE_signed_char:
+ return pass_in_gpr (locp, size);
+ }
+
+ return -2;
+ }
+ else
+ return pass_in_gpr (locp, size);
+ }
+
+ *locp = NULL;
+ return 0;
+}
diff --git a/backends/aarch64_symbol.c b/backends/aarch64_symbol.c
new file mode 100644
index 00000000..e41a7a7d
--- /dev/null
+++ b/backends/aarch64_symbol.c
@@ -0,0 +1,84 @@
+/* AArch64 specific symbolic name handling.
+ 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 <elf.h>
+#include <stddef.h>
+#include <string.h>
+
+#define BACKEND aarch64_
+#include "libebl_CPU.h"
+
+
+/* Check for the simple reloc types. */
+Elf_Type
+aarch64_reloc_simple_type (Ebl *ebl __attribute__ ((unused)), int type)
+{
+ switch (type)
+ {
+ case R_AARCH64_ABS64:
+ return ELF_T_XWORD;
+ case R_AARCH64_ABS32:
+ return ELF_T_WORD;
+ case R_AARCH64_ABS16:
+ return ELF_T_HALF;
+
+ default:
+ return ELF_T_NUM;
+ }
+}
+
+/* If this is the _GLOBAL_OFFSET_TABLE_ symbol, then it should point to
+ .got[0] even if there is a .got.plt section. */
+bool
+aarch64_check_special_symbol (Elf *elf, GElf_Ehdr *ehdr, const GElf_Sym *sym,
+ const char *name, const GElf_Shdr *destshdr)
+{
+ if (name != NULL
+ && strcmp (name, "_GLOBAL_OFFSET_TABLE_") == 0)
+ {
+ const char *sname = elf_strptr (elf, ehdr->e_shstrndx, destshdr->sh_name);
+ if (sname != NULL && strcmp (sname, ".got.plt") == 0)
+ {
+ Elf_Scn *scn = NULL;
+ while ((scn = elf_nextscn (elf, scn)) != NULL)
+ {
+ 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;
+ }
+ }
+ }
+
+ return false;
+}
diff --git a/backends/i386_init.c b/backends/i386_init.c
index cc9b2d7f..1e0b4863 100644
--- a/backends/i386_init.c
+++ b/backends/i386_init.c
@@ -1,5 +1,5 @@
/* Initialization of i386 specific backend library.
- Copyright (C) 2000-2009 Red Hat, Inc.
+ Copyright (C) 2000-2009, 2013 Red Hat, Inc.
This file is part of elfutils.
Written by Ulrich Drepper <[email protected]>, 2000.
@@ -63,6 +63,9 @@ i386_init (elf, machine, eh, ehlen)
HOOK (eh, auxv_info);
HOOK (eh, disasm);
HOOK (eh, abi_cfi);
+ /* gcc/config/ #define DWARF_FRAME_REGISTERS. For i386 it is 17, why? */
+ eh->frame_nregs = 9;
+ HOOK (eh, set_initial_registers_tid);
return MODVERSION;
}
diff --git a/backends/i386_initreg.c b/backends/i386_initreg.c
new file mode 100644
index 00000000..9e819a47
--- /dev/null
+++ b/backends/i386_initreg.c
@@ -0,0 +1,79 @@
+/* Fetch live process registers from TID.
+ 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
+
+#if defined __i386__ || defined __x86_64__
+# include <sys/types.h>
+# include <sys/user.h>
+# include <sys/ptrace.h>
+#endif
+
+#define BACKEND i386_
+#include "libebl_CPU.h"
+
+bool
+i386_set_initial_registers_tid (pid_t tid __attribute__ ((unused)),
+ ebl_tid_registers_t *setfunc __attribute__ ((unused)),
+ void *arg __attribute__ ((unused)))
+{
+#if !defined __i386__ && !defined __x86_64__
+ return false;
+#else /* __i386__ || __x86_64__ */
+ struct user_regs_struct user_regs;
+ if (ptrace (PTRACE_GETREGS, tid, NULL, &user_regs) != 0)
+ return false;
+ Dwarf_Word dwarf_regs[9];
+# if defined __i386__
+ dwarf_regs[0] = user_regs.eax;
+ dwarf_regs[1] = user_regs.ecx;
+ dwarf_regs[2] = user_regs.edx;
+ dwarf_regs[3] = user_regs.ebx;
+ dwarf_regs[4] = user_regs.esp;
+ dwarf_regs[5] = user_regs.ebp;
+ dwarf_regs[6] = user_regs.esi;
+ dwarf_regs[7] = user_regs.edi;
+ dwarf_regs[8] = user_regs.eip;
+# elif defined __x86_64__
+ dwarf_regs[0] = user_regs.rax;
+ dwarf_regs[1] = user_regs.rcx;
+ dwarf_regs[2] = user_regs.rdx;
+ dwarf_regs[3] = user_regs.rbx;
+ dwarf_regs[4] = user_regs.rsp;
+ dwarf_regs[5] = user_regs.rbp;
+ dwarf_regs[6] = user_regs.rsi;
+ dwarf_regs[7] = user_regs.rdi;
+ dwarf_regs[8] = user_regs.rip;
+# else /* (__i386__ || __x86_64__) && (!__i386__ && !__x86_64__) */
+# error "source file error, it cannot happen"
+# endif /* (__i386__ || __x86_64__) && (!__i386__ && !__x86_64__) */
+ return setfunc (0, 9, dwarf_regs, arg);
+#endif /* __i386__ || __x86_64__ */
+}
diff --git a/backends/libebl_CPU.h b/backends/libebl_CPU.h
index 09c8cd10..3ad92588 100644
--- a/backends/libebl_CPU.h
+++ b/backends/libebl_CPU.h
@@ -1,5 +1,5 @@
/* Common interface for libebl modules.
- Copyright (C) 2000, 2001, 2002, 2003, 2005 Red Hat, Inc.
+ Copyright (C) 2000, 2001, 2002, 2003, 2005, 2013 Red Hat, Inc.
This file is part of elfutils.
This file is free software; you can redistribute it and/or modify
@@ -29,6 +29,7 @@
#ifndef _LIBEBL_CPU_H
#define _LIBEBL_CPU_H 1
+#include <dwarf.h>
#include <libeblP.h>
#define EBLHOOK(name) EBLHOOK_1(BACKEND, name)
@@ -52,4 +53,38 @@ extern bool (*generic_debugscn_p) (const char *) attribute_hidden;
if (_die == NULL) return -1; \
dwarf_tag (_die); })
+/* Follow typedefs and qualifiers to get to the actual type. */
+static inline int
+dwarf_peel_type (Dwarf_Die *typediep, Dwarf_Attribute *attrp)
+{
+ int tag = DWARF_TAG_OR_RETURN (typediep);
+ while (tag == DW_TAG_typedef
+ || tag == DW_TAG_const_type || tag == DW_TAG_volatile_type
+ || tag == DW_TAG_restrict_type || tag == DW_TAG_mutable_type)
+ {
+ attrp = dwarf_attr_integrate (typediep, DW_AT_type, attrp);
+ typediep = dwarf_formref_die (attrp, typediep);
+ tag = DWARF_TAG_OR_RETURN (typediep);
+ }
+
+ return tag;
+}
+
+/* Get a type die corresponding to DIE. Peel CV qualifiers off
+ it. */
+static inline int
+dwarf_peeled_die_type (Dwarf_Die *die, Dwarf_Die *result)
+{
+ Dwarf_Attribute attr_mem;
+ Dwarf_Attribute *attr = dwarf_attr_integrate (die, DW_AT_type, &attr_mem);
+ if (attr == NULL)
+ /* The function has no return value, like a `void' function in C. */
+ return 0;
+
+ if (dwarf_formref_die (attr, result) == NULL)
+ return -1;
+
+ return dwarf_peel_type (result, attr);
+}
+
#endif /* libebl_CPU.h */
diff --git a/backends/ppc64_init.c b/backends/ppc64_init.c
index 14358754..d8f1417e 100644
--- a/backends/ppc64_init.c
+++ b/backends/ppc64_init.c
@@ -31,6 +31,8 @@
# include <config.h>
#endif
+#include <string.h>
+
#define BACKEND ppc64_
#define RELOC_PREFIX R_PPC64_
#include "libebl_CPU.h"
@@ -65,6 +67,38 @@ ppc64_init (elf, machine, eh, ehlen)
HOOK (eh, core_note);
HOOK (eh, auxv_info);
HOOK (eh, abi_cfi);
+ /* gcc/config/ #define DWARF_FRAME_REGISTERS. */
+ eh->frame_nregs = (114 - 1) + 32;
+ HOOK (eh, set_initial_registers_tid);
+ HOOK (eh, dwarf_to_regno);
+ HOOK (eh, resolve_sym_value);
+
+ /* Find the function descriptor .opd table for resolve_sym_value. */
+ if (elf != NULL)
+ {
+ GElf_Ehdr ehdr_mem, *ehdr = gelf_getehdr (elf, &ehdr_mem);
+ if (ehdr != NULL && ehdr->e_type != ET_REL)
+ {
+ /* We could also try through DT_PPC64_OPD and DT_PPC64_OPDSZ. */
+ GElf_Shdr opd_shdr_mem, *opd_shdr;
+ Elf_Scn *scn = NULL;
+ while ((scn = elf_nextscn (elf, scn)) != NULL)
+ {
+ opd_shdr = gelf_getshdr (scn, &opd_shdr_mem);
+ if (opd_shdr != NULL
+ && (opd_shdr->sh_flags & SHF_ALLOC) != 0
+ && opd_shdr->sh_type == SHT_PROGBITS
+ && opd_shdr->sh_size > 0
+ && strcmp (elf_strptr (elf, ehdr->e_shstrndx,
+ opd_shdr->sh_name), ".opd") == 0)
+ {
+ eh->fd_addr = opd_shdr->sh_addr;
+ eh->fd_data = elf_getdata (scn, NULL);
+ break;
+ }
+ }
+ }
+ }
return MODVERSION;
}
diff --git a/backends/ppc64_resolve_sym.c b/backends/ppc64_resolve_sym.c
new file mode 100644
index 00000000..03f65584
--- /dev/null
+++ b/backends/ppc64_resolve_sym.c
@@ -0,0 +1,63 @@
+/* Resolve symbol values through .opd function descriptors.
+ 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
+
+#define BACKEND ppc64_
+#include "libebl_CPU.h"
+
+/* Resolve a function descriptor if addr points into the .opd section.
+ The .opd section contains function descriptors consisting of 3 addresses.
+ function, toc and chain. We are just interested in the first.
+ http://refspecs.linuxfoundation.org/ELF/ppc64/PPC-elf64abi-1.9.html#FUNC-DES
+
+ Returns true if the given address could be resolved, false otherwise.
+*/
+bool
+ppc64_resolve_sym_value (Ebl *ebl, GElf_Addr *addr)
+{
+ if (ebl->fd_data != NULL && *addr >= ebl->fd_addr
+ && *addr + sizeof (Elf64_Addr) <= ebl->fd_addr + ebl->fd_data->d_size)
+ {
+ GElf_Ehdr ehdr_mem, *ehdr = gelf_getehdr (ebl->elf, &ehdr_mem);
+ if (ehdr != NULL)
+ {
+ Elf_Data opd_in, opd_out;
+ opd_in.d_buf = ebl->fd_data->d_buf + (*addr - ebl->fd_addr);
+ opd_out.d_buf = addr;
+ opd_out.d_size = opd_in.d_size = sizeof (Elf64_Addr);
+ opd_out.d_type = opd_in.d_type = ELF_T_ADDR;
+ if (elf64_xlatetom (&opd_out, &opd_in,
+ ehdr->e_ident[EI_DATA]) != NULL)
+ return true;
+ }
+ }
+ return false;
+}
diff --git a/backends/ppc_cfi.c b/backends/ppc_cfi.c
index 6a4f4619..55169aef 100644
--- a/backends/ppc_cfi.c
+++ b/backends/ppc_cfi.c
@@ -44,7 +44,7 @@ ppc_abi_cfi (Ebl *ebl __attribute__ ((unused)), Dwarf_CIE *abi_info)
DW_CFA_def_cfa, ULEB128_7 (1), ULEB128_7 (0) */
/* r1 is assumed to be restored from cfa adress,
r1 acts as a stack frame pointer. */
- DW_CFA_val_expression, ULEB128_7 (1), ULEB128_7 (1), DW_OP_nop,
+ DW_CFA_val_offset, ULEB128_7 (1), ULEB128_7 (0),
/* lr is not callee-saved but it needs to be preserved as it is pre-set
by the caller. */
DW_CFA_same_value, ULEB128_7 (65), /* lr */
diff --git a/backends/ppc_corenote.c b/backends/ppc_corenote.c
index 707a3954..9ac88712 100644
--- a/backends/ppc_corenote.c
+++ b/backends/ppc_corenote.c
@@ -123,7 +123,7 @@ static const Ebl_Register_Location spe_regs[] =
{ \
.name = "nip", .type = ELF_T_ADDR, .format = 'x', \
.offset = offsetof (struct EBLHOOK(prstatus), pr_reg[32]), \
- .group = "register" \
+ .group = "register", .pc_register = true \
}, \
{ \
.name = "orig_gpr3", .type = TYPE_LONG, .format = 'd', \
diff --git a/backends/ppc_init.c b/backends/ppc_init.c
index 004c6016..ad92765c 100644
--- a/backends/ppc_init.c
+++ b/backends/ppc_init.c
@@ -65,6 +65,10 @@ ppc_init (elf, machine, eh, ehlen)
HOOK (eh, auxv_info);
HOOK (eh, check_object_attribute);
HOOK (eh, abi_cfi);
+ /* gcc/config/ #define DWARF_FRAME_REGISTERS. */
+ eh->frame_nregs = (114 - 1) + 32;
+ HOOK (eh, set_initial_registers_tid);
+ HOOK (eh, dwarf_to_regno);
return MODVERSION;
}
diff --git a/backends/ppc_initreg.c b/backends/ppc_initreg.c
new file mode 100644
index 00000000..64f53793
--- /dev/null
+++ b/backends/ppc_initreg.c
@@ -0,0 +1,114 @@
+/* Fetch live process registers from TID.
+ 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 "system.h"
+#include <stdlib.h>
+#ifdef __powerpc__
+# include <sys/user.h>
+# include <sys/ptrace.h>
+#endif
+
+#define BACKEND ppc_
+#include "libebl_CPU.h"
+
+bool
+ppc_dwarf_to_regno (Ebl *ebl __attribute__ ((unused)), unsigned *regno)
+{
+ switch (*regno)
+ {
+ case 108:
+ // LR uses both 65 and 108 numbers, there is no consistency for it.
+ *regno = 65;
+ return true;
+ case 0 ... 107:
+ case 109 ... (114 - 1) -1:
+ return true;
+ case 1200 ... 1231:
+ *regno = *regno - 1200 + (114 - 1);
+ return true;
+ default:
+ return false;
+ }
+ abort ();
+}
+
+__typeof (ppc_dwarf_to_regno)
+ ppc64_dwarf_to_regno
+ __attribute__ ((alias ("ppc_dwarf_to_regno")));
+
+bool
+ppc_set_initial_registers_tid (pid_t tid __attribute__ ((unused)),
+ ebl_tid_registers_t *setfunc __attribute__ ((unused)),
+ void *arg __attribute__ ((unused)))
+{
+#ifndef __powerpc__
+ return false;
+#else /* __powerpc__ */
+ union
+ {
+ struct pt_regs r;
+ long l[sizeof (struct pt_regs) / sizeof (long)];
+ }
+ user_regs;
+ eu_static_assert (sizeof (struct pt_regs) % sizeof (long) == 0);
+ /* PTRACE_GETREGS is EIO on kernel-2.6.18-308.el5.ppc64. */
+ errno = 0;
+ for (unsigned regno = 0; regno < sizeof (user_regs) / sizeof (long);
+ regno++)
+ {
+ user_regs.l[regno] = ptrace (PTRACE_PEEKUSER, tid,
+ (void *) (uintptr_t) (regno
+ * sizeof (long)),
+ NULL);
+ if (errno != 0)
+ return false;
+ }
+ const size_t gprs = sizeof (user_regs.r.gpr) / sizeof (*user_regs.r.gpr);
+ Dwarf_Word dwarf_regs[gprs];
+ for (unsigned gpr = 0; gpr < gprs; gpr++)
+ dwarf_regs[gpr] = user_regs.r.gpr[gpr];
+ if (! setfunc (0, gprs, dwarf_regs, arg))
+ return false;
+ dwarf_regs[0] = user_regs.r.link;
+ // LR uses both 65 and 108 numbers, there is no consistency for it.
+ if (! setfunc (65, 1, dwarf_regs, arg))
+ return false;
+ /* Registers like msr, ctr, xer, dar, dsisr etc. are probably irrelevant
+ for CFI. */
+ dwarf_regs[0] = user_regs.r.nip;
+ return setfunc (-1, 1, dwarf_regs, arg);
+#endif /* __powerpc__ */
+}
+
+__typeof (ppc_set_initial_registers_tid)
+ ppc64_set_initial_registers_tid
+ __attribute__ ((alias ("ppc_set_initial_registers_tid")));
diff --git a/backends/s390_corenote.c b/backends/s390_corenote.c
index b88c05cf..7ca35168 100644
--- a/backends/s390_corenote.c
+++ b/backends/s390_corenote.c
@@ -47,13 +47,13 @@
static const Ebl_Register_Location prstatus_regs[] =
{
-#define GR(at, n, dwreg, b) \
+#define GR(at, n, dwreg, b...) \
{ .offset = at * BITS/8, .regno = dwreg, .count = n, .bits = b }
- GR ( 0, 1, 64, BITS), /* pswm */
- GR ( 1, 1, 65, BITS), /* pswa */
- GR ( 2, 16, 0, BITS), /* r0-r15 */
- GR (18, 16, 48, 32), /* ar0-ar15 */
+ GR ( 0, 1, 64, BITS), /* pswm */
+ GR ( 1, 1, 65, BITS, .pc_register = true ), /* pswa */
+ GR ( 2, 16, 0, BITS), /* r0-r15 */
+ GR (18, 16, 48, 32), /* ar0-ar15 */
#undef GR
};
diff --git a/backends/s390_init.c b/backends/s390_init.c
index 630a2ee3..26b20b49 100644
--- a/backends/s390_init.c
+++ b/backends/s390_init.c
@@ -62,6 +62,15 @@ s390_init (elf, machine, eh, ehlen)
else
HOOK (eh, core_note);
HOOK (eh, abi_cfi);
+ /* gcc/config/ #define DWARF_FRAME_REGISTERS 34.
+ But from the gcc/config/s390/s390.h "Register usage." comment it looks as
+ if #32 (Argument pointer) and #33 (Condition code) are not used for
+ unwinding. */
+ eh->frame_nregs = 32;
+ HOOK (eh, set_initial_registers_tid);
+ if (eh->class == ELFCLASS32)
+ HOOK (eh, normalize_pc);
+ HOOK (eh, unwind);
/* Only the 64-bit format uses the incorrect hash table entry size. */
if (eh->class == ELFCLASS64)
diff --git a/backends/s390_initreg.c b/backends/s390_initreg.c
new file mode 100644
index 00000000..b4c4b67c
--- /dev/null
+++ b/backends/s390_initreg.c
@@ -0,0 +1,95 @@
+/* Fetch live process registers from TID.
+ 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 "system.h"
+#include <assert.h>
+#ifdef __s390__
+# include <sys/user.h>
+# include <asm/ptrace.h>
+# include <sys/ptrace.h>
+#endif
+
+#define BACKEND s390_
+#include "libebl_CPU.h"
+
+bool
+s390_set_initial_registers_tid (pid_t tid __attribute__ ((unused)),
+ ebl_tid_registers_t *setfunc __attribute__ ((unused)),
+ void *arg __attribute__ ((unused)))
+{
+#ifndef __s390__
+ return false;
+#else /* __s390__ */
+ struct user user_regs;
+ ptrace_area parea;
+ parea.process_addr = (uintptr_t) &user_regs;
+ parea.kernel_addr = 0;
+ parea.len = sizeof (user_regs);
+ if (ptrace (PTRACE_PEEKUSR_AREA, tid, &parea, NULL) != 0)
+ return false;
+ /* If we run as s390x we get the 64-bit registers of tid.
+ But -m31 executable seems to use only the 32-bit parts of its
+ registers so we ignore the upper half. */
+ Dwarf_Word dwarf_regs[16];
+ for (unsigned u = 0; u < 16; u++)
+ dwarf_regs[u] = user_regs.regs.gprs[u];
+ if (! setfunc (0, 16, dwarf_regs, arg))
+ return false;
+ /* Avoid conversion double -> integer. */
+ eu_static_assert (sizeof user_regs.regs.fp_regs.fprs[0]
+ == sizeof dwarf_regs[0]);
+ for (unsigned u = 0; u < 16; u++)
+ {
+ // Store the double bits as is in the Dwarf_Word without conversion.
+ union
+ {
+ double d;
+ Dwarf_Word w;
+ } fpr = { .d = user_regs.regs.fp_regs.fprs[u] };
+ dwarf_regs[u] = fpr.w;
+ }
+
+ if (! setfunc (16, 16, dwarf_regs, arg))
+ return false;
+ dwarf_regs[0] = user_regs.regs.psw.addr;
+ return setfunc (-1, 1, dwarf_regs, arg);
+#endif /* __s390__ */
+}
+
+void
+s390_normalize_pc (Ebl *ebl __attribute__ ((unused)), Dwarf_Addr *pc)
+{
+ assert (ebl->class == ELFCLASS32);
+
+ /* Clear S390 bit 31. */
+ *pc &= (1U << 31) - 1;
+}
diff --git a/backends/s390_unwind.c b/backends/s390_unwind.c
new file mode 100644
index 00000000..752bc287
--- /dev/null
+++ b/backends/s390_unwind.c
@@ -0,0 +1,139 @@
+/* Get previous frame state for an existing frame state.
+ 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 <stdlib.h>
+#include <assert.h>
+
+#define BACKEND s390_
+#include "libebl_CPU.h"
+
+/* s390/s390x do not annotate signal handler frame by CFI. It would be also
+ difficult as PC points into a stub built on stack. Function below is called
+ only if unwinder could not find CFI. Function then verifies the register
+ state for this frame really belongs to a signal frame. In such case it
+ fetches original registers saved by the signal frame. */
+
+bool
+s390_unwind (Ebl *ebl, Dwarf_Addr pc, ebl_tid_registers_t *setfunc,
+ ebl_tid_registers_get_t *getfunc, ebl_pid_memory_read_t *readfunc,
+ void *arg, bool *signal_framep)
+{
+ /* Caller already assumed caller adjustment but S390 instructions are 4 bytes
+ long. Undo it. */
+ if ((pc & 0x3) != 0x3)
+ return false;
+ pc++;
+ /* We can assume big-endian read here. */
+ Dwarf_Word instr;
+ if (! readfunc (pc, &instr, arg))
+ return false;
+ /* Fetch only the very first two bytes. */
+ instr = (instr >> (ebl->class == ELFCLASS64 ? 48 : 16)) & 0xffff;
+ /* See GDB s390_sigtramp_frame_sniffer. */
+ /* Check for 'svc' as the first instruction. */
+ if (((instr >> 8) & 0xff) != 0x0a)
+ return false;
+ /* Check for 'sigreturn' or 'rt_sigreturn' as the second instruction. */
+ if ((instr & 0xff) != 119 && (instr & 0xff) != 173)
+ return false;
+ /* See GDB s390_sigtramp_frame_unwind_cache. */
+ Dwarf_Word this_sp;
+ if (! getfunc (0 + 15, 1, &this_sp, arg))
+ return false;
+ unsigned word_size = ebl->class == ELFCLASS64 ? 8 : 4;
+ Dwarf_Addr next_cfa = this_sp + 16 * word_size + 32;
+ /* "New-style RT frame" is not supported,
+ assuming "Old-style RT frame and all non-RT frames".
+ Pointer to the array of saved registers is at NEXT_CFA + 8. */
+ Dwarf_Word sigreg_ptr;
+ if (! readfunc (next_cfa + 8, &sigreg_ptr, arg))
+ return false;
+ /* Skip PSW mask. */
+ sigreg_ptr += word_size;
+ /* Read PSW address. */
+ Dwarf_Word val;
+ if (! readfunc (sigreg_ptr, &val, arg))
+ return false;
+ if (! setfunc (-1, 1, &val, arg))
+ return false;
+ sigreg_ptr += word_size;
+ /* Then the GPRs. */
+ Dwarf_Word gprs[16];
+ for (int i = 0; i < 16; i++)
+ {
+ if (! readfunc (sigreg_ptr, &gprs[i], arg))
+ return false;
+ sigreg_ptr += word_size;
+ }
+ /* Then the ACRs. Skip them, they are not used in CFI. */
+ for (int i = 0; i < 16; i++)
+ sigreg_ptr += 4;
+ /* The floating-point control word. */
+ sigreg_ptr += 8;
+ /* And finally the FPRs. */
+ Dwarf_Word fprs[16];
+ for (int i = 0; i < 16; i++)
+ {
+ if (! readfunc (sigreg_ptr, &val, arg))
+ return false;
+ if (ebl->class == ELFCLASS32)
+ {
+ Dwarf_Addr val_low;
+ if (! readfunc (sigreg_ptr + 4, &val_low, arg))
+ return false;
+ val = (val << 32) | val_low;
+ }
+ fprs[i] = val;
+ sigreg_ptr += 8;
+ }
+ /* If we have them, the GPR upper halves are appended at the end. */
+ if (ebl->class == ELFCLASS32)
+ {
+ /* Skip signal number. */
+ sigreg_ptr += 4;
+ for (int i = 0; i < 16; i++)
+ {
+ if (! readfunc (sigreg_ptr, &val, arg))
+ return false;
+ Dwarf_Word val_low = gprs[i];
+ val = (val << 32) | val_low;
+ gprs[i] = val;
+ sigreg_ptr += 4;
+ }
+ }
+ if (! setfunc (0, 16, gprs, arg))
+ return false;
+ if (! setfunc (16, 16, fprs, arg))
+ return false;
+ *signal_framep = true;
+ return true;
+}
diff --git a/backends/x86_64_init.c b/backends/x86_64_init.c
index 67a58804..b885558b 100644
--- a/backends/x86_64_init.c
+++ b/backends/x86_64_init.c
@@ -1,5 +1,5 @@
/* Initialization of x86-64 specific backend library.
- Copyright (C) 2002-2009 Red Hat, Inc.
+ Copyright (C) 2002-2009, 2013 Red Hat, Inc.
This file is part of elfutils.
Written by Ulrich Drepper <[email protected]>, 2002.
@@ -60,6 +60,9 @@ x86_64_init (elf, machine, eh, ehlen)
HOOK (eh, auxv_info);
HOOK (eh, disasm);
HOOK (eh, abi_cfi);
+ /* gcc/config/ #define DWARF_FRAME_REGISTERS. */
+ eh->frame_nregs = 17;
+ HOOK (eh, set_initial_registers_tid);
return MODVERSION;
}
diff --git a/backends/x86_64_initreg.c b/backends/x86_64_initreg.c
new file mode 100644
index 00000000..0c493640
--- /dev/null
+++ b/backends/x86_64_initreg.c
@@ -0,0 +1,73 @@
+/* Fetch live process registers from TID.
+ 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 <stdlib.h>
+#ifdef __x86_64__
+# include <sys/user.h>
+# include <sys/ptrace.h>
+#endif
+
+#define BACKEND x86_64_
+#include "libebl_CPU.h"
+
+bool
+x86_64_set_initial_registers_tid (pid_t tid __attribute__ ((unused)),
+ ebl_tid_registers_t *setfunc __attribute__ ((unused)),
+ void *arg __attribute__ ((unused)))
+{
+#ifndef __x86_64__
+ return false;
+#else /* __x86_64__ */
+ struct user_regs_struct user_regs;
+ if (ptrace (PTRACE_GETREGS, tid, NULL, &user_regs) != 0)
+ return false;
+ Dwarf_Word dwarf_regs[17];
+ dwarf_regs[0] = user_regs.rax;
+ dwarf_regs[1] = user_regs.rdx;
+ dwarf_regs[2] = user_regs.rcx;
+ dwarf_regs[3] = user_regs.rbx;
+ dwarf_regs[4] = user_regs.rsi;
+ dwarf_regs[5] = user_regs.rdi;
+ dwarf_regs[6] = user_regs.rbp;
+ dwarf_regs[7] = user_regs.rsp;
+ dwarf_regs[8] = user_regs.r8;
+ dwarf_regs[9] = user_regs.r9;
+ dwarf_regs[10] = user_regs.r10;
+ dwarf_regs[11] = user_regs.r11;
+ dwarf_regs[12] = user_regs.r12;
+ dwarf_regs[13] = user_regs.r13;
+ dwarf_regs[14] = user_regs.r14;
+ dwarf_regs[15] = user_regs.r15;
+ dwarf_regs[16] = user_regs.rip;
+ return setfunc (0, 17, dwarf_regs, arg);
+#endif /* __x86_64__ */
+}
diff --git a/config/ChangeLog b/config/ChangeLog
index 3b1877d7..53fddec6 100644
--- a/config/ChangeLog
+++ b/config/ChangeLog
@@ -1,3 +1,11 @@
+2014-01-03 Mark Wielaard <[email protected]>
+
+ * elfutils.spec.in: Update for 0.158.
+
+2013-11-01 Michael Forney <[email protected]>
+
+ * eu.am: Use READELF.
+
2013-09-30 Mark Wielaard <[email protected]>
* elfutils.spec.in: Update for readelf NT_SIGINFO and NT_FILE
diff --git a/config/elfutils.spec.in b/config/elfutils.spec.in
index 35b1fa78..bbd2ea43 100644
--- a/config/elfutils.spec.in
+++ b/config/elfutils.spec.in
@@ -195,6 +195,21 @@ rm -rf ${RPM_BUILD_ROOT}
%{_libdir}/libelf.a
%changelog
+* Fri Jan 3 2014 Mark Wielaard <[email protected]> 0.158-1
+- 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.
+
* Mon Sep 30 2013 Mark Wielaard <[email protected]> 0.157-1
- libdw: Add new functions dwarf_getlocations, dwarf_getlocation_attr
and dwarf_getlocation_die.
diff --git a/config/eu.am b/config/eu.am
index 86e5a4e9..38718c7f 100644
--- a/config/eu.am
+++ b/config/eu.am
@@ -61,4 +61,4 @@ endif
CLEANFILES = *.gcno *.gcda
-textrel_check = if readelf -d $@ | fgrep -q TEXTREL; then exit 1; fi
+textrel_check = if $(READELF) -d $@ | fgrep -q TEXTREL; then exit 1; fi
diff --git a/configure.ac b/configure.ac
index b4c249c3..7bfa1da2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,7 +1,7 @@
dnl Process this file with autoconf to produce a configure script.
dnl Configure input file for elfutils. -*-autoconf-*-
dnl
-dnl Copyright (C) 1996-2013 Red Hat, Inc.
+dnl Copyright (C) 1996-2014 Red Hat, Inc.
dnl
dnl This file is part of elfutils.
dnl
@@ -17,12 +17,12 @@ dnl GNU General Public License for more details.
dnl
dnl You should have received a copy of the GNU General Public License
dnl along with this program. If not, see <http://www.gnu.org/licenses/>.
-AC_INIT([elfutils],[0.157],[https://bugzilla.redhat.com/],[elfutils])
+AC_INIT([elfutils],[0.158],[https://bugzilla.redhat.com/],[elfutils])
AC_CONFIG_AUX_DIR([config])
AC_CONFIG_FILES([config/Makefile])
-AC_COPYRIGHT([Copyright (C) 1996-2013 Red Hat, Inc.])
+AC_COPYRIGHT([Copyright (C) 1996-2014 Red Hat, Inc.])
AC_PREREQ(2.63) dnl Minimum Autoconf version required.
dnl We use GNU make extensions; automake 1.10 defaults to -Wportability.
@@ -60,10 +60,13 @@ AC_DEFINE_UNQUOTED(DEFAULT_AR_DETERMINISTIC, $default_ar_deterministic,
[Should ar and ranlib use -D behavior by default?])
AC_ARG_ENABLE([thread-safety],
-AS_HELP_STRING([--enable-thread-safety], [enable thread safety of libraries]),
-use_locks=$enableval, use_locks=no)
+AS_HELP_STRING([--enable-thread-safety],
+ [enable thread safety of libraries EXPERIMENTAL]),
+ use_locks=$enableval, use_locks=no)
AM_CONDITIONAL(USE_LOCKS, test "$use_locks" = yes)
AS_IF([test "$use_locks" = yes], [AC_DEFINE(USE_LOCKS)])
+AS_IF([test "$use_locks" = yes],
+ [AC_MSG_WARN([thread-safety is EXPERIMENTAL tests might fail.])])
AH_TEMPLATE([USE_LOCKS], [Defined if libraries should be thread-safe.])
@@ -72,6 +75,8 @@ AS_HELP_STRING([--enable-dwz], [enable experimental GNU ref_alt FORM, dwz multi
enable_dwz=$enableval, enable_dwz=no)
AM_CONDITIONAL(ENABLE_DWZ, test "$enable_dwz" = yes)
AS_IF([test "$enable_dwz" = yes], [AC_DEFINE(ENABLE_DWZ)])
+AS_IF([test "$enable_dwz" = no -a -d /usr/lib/debug/.dwz],
+ [AC_MSG_WARN([--enable-dwz disabled and /usr/lib/debug/.dwz exists, native tests might fail])])
AH_TEMPLATE([ENABLE_DWZ], [Defined if libdw should support GNU ref_alt FORM, dwz multi files.])
@@ -79,6 +84,10 @@ AC_PROG_CC
AC_PROG_RANLIB
AC_PROG_YACC
AM_PROG_LEX
+# Only available since automake 1.12
+m4_ifdef([AM_PROG_AR], [AM_PROG_AR])
+AC_CHECK_TOOL([READELF], [readelf])
+AC_CHECK_TOOL([NM], [nm])
AC_CACHE_CHECK([for gcc with C99 support], ac_cv_c99, [dnl
old_CFLAGS="$CFLAGS"
@@ -317,4 +326,13 @@ esac
# Round up to the next release API (x.y) version.
eu_version=$(( (eu_version + 999) / 1000 ))
+AC_CHECK_SIZEOF(long)
+
+# On a 64-bit host where can can use $CC -m32, we'll run two sets of tests.
+# Likewise in a 32-bit build on a host where $CC -m64 works.
+utrace_BIARCH
+# `$utrace_biarch' will be `-m64' even on an uniarch i386 machine.
+CC_BIARCH="$CC $utrace_biarch"
+AC_SUBST([CC_BIARCH])
+
AC_OUTPUT
diff --git a/lib/ChangeLog b/lib/ChangeLog
index 6ce3168f..9b8899e2 100644
--- a/lib/ChangeLog
+++ b/lib/ChangeLog
@@ -1,3 +1,7 @@
+2013-12-12 Josh Stone <[email protected]>
+
+ * dynamicsizehash.c (lookup): Add a shortcut around division.
+
2013-04-30 Jan Kratochvil <[email protected]>
* eu-config.h (COMPAT_VERSION_NEWPROTO): New. Twice.
diff --git a/lib/dynamicsizehash.c b/lib/dynamicsizehash.c
index 40f48d5e..1fdff1b0 100644
--- a/lib/dynamicsizehash.c
+++ b/lib/dynamicsizehash.c
@@ -49,8 +49,9 @@ lookup (htab, hval, val)
HASHTYPE hval;
TYPE val __attribute__ ((unused));
{
- /* First hash function: simply take the modul but prevent zero. */
- size_t idx = 1 + hval % htab->size;
+ /* First hash function: simply take the modul but prevent zero. Small values
+ can skip the division, which helps performance when this is common. */
+ size_t idx = 1 + (hval < htab->size ? hval : hval % htab->size);
if (htab->table[idx].hashval != 0)
{
diff --git a/libasm/Makefile.am b/libasm/Makefile.am
index e16d4be0..4d81536b 100644
--- a/libasm/Makefile.am
+++ b/libasm/Makefile.am
@@ -69,7 +69,7 @@ libasm.so: libasm_pic.a libasm.map
-Wl,--version-script,$(srcdir)/libasm.map,--no-undefined \
-Wl,--soname,$@.$(VERSION) \
../libebl/libebl.a ../libelf/libelf.so $(libasm_so_LDLIBS)
- if readelf -d $@ | fgrep -q TEXTREL; then exit 1; fi
+ if $(READELF) -d $@ | fgrep -q TEXTREL; then exit 1; fi
ln -fs $@ $@.$(VERSION)
install: install-am libasm.so
diff --git a/libdw/ChangeLog b/libdw/ChangeLog
index 951f1cba..6e779c8e 100644
--- a/libdw/ChangeLog
+++ b/libdw/ChangeLog
@@ -1,3 +1,112 @@
+2013-12-30 Mark Wielaard <[email protected]>
+
+ * libdw.map (ELFUTILS_0.158): Add dwfl_core_file_attach and
+ dwfl_linux_proc_attach.
+
+2013-12-20 Mark Wielaard <[email protected]>
+
+ * libdw.map (ELFUTILS_0.158): Add dwfl_getthread_frames.
+
+2013-12-18 Mark Wielaard <[email protected]>
+
+ * libdw.map (ELFUTILS_0.158): Remove dwfl_module_addrsym_elf and
+ dwfl_module_getsym_elf. Add dwfl_module_addrinfo and
+ dwfl_module_getsym_info.
+
+2013-12-16 Mark Wielaard <[email protected]>
+
+ * libdw.map (ELFUTILS_0.158): Add dwfl_module_getsymtab_first_global.
+
+2013-12-10 Josh Stone <[email protected]>
+
+ * memory-access.h (get_uleb128_rest_return): Removed.
+ (get_sleb128_rest_return): Removed.
+ (get_uleb128_step): Make this a self-contained block.
+ (get_sleb128_step): Ditto, and use a bitfield to extend signs.
+ (get_uleb128): Make this wholly implemented by __libdw_get_uleb128.
+ (get_sleb128): Make this wholly implemented by __libdw_get_sleb128.
+ (__libdw_get_uleb128): Simplify and inline for all callers.
+ (__libdw_get_sleb128): Ditto.
+ * dwarf_getlocation.c (store_implicit_value): Void the unused uleb128.
+ * memory-access.c: Delete file.
+ * Makefile.am (libdw_a_SOURCES): Remove it.
+ (DEFS): Remove the now unused -DIS_LIBDW.
+
+2013-12-09 Josh Stone <[email protected]>
+
+ * libdw_form.c (__libdw_form_val_compute_len): Renamed function from
+ __libdw_form_val_len, now handling only non-constant form lengths.
+ * libdwP.h (__libdw_form_val_len): New inlined function.
+
+2013-12-09 Mark Wielaard <[email protected]>
+
+ * dwarf_getlocation.c (__libdw_intern_expression): Handle empty
+ location expressions.
+ * dwarf_getlocation_attr.c (dwarf_getlocation_attr): When no
+ location found, return empty location expression.
+ * dwarf_getlocation_implicit_pointer.c
+ (dwarf_getlocation_implicit_pointer): Likewise.
+ (__libdw_empty_loc_attr): New internal function.
+ * libdwP.h (__libdw_empty_loc_attr): Define.
+
+2013-11-27 Mark Wielaard <[email protected]>
+
+ * libdw.map (ELFUTILS_0.158): Add dwfl_module_addrsym_elf and
+ dwfl_module_getsym_elf.
+
+2013-11-26 Mark Wielaard <[email protected]>
+
+ * libdw.map (ELFUTILS_0.156): Move 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 to ...
+ (ELFUTILS_0.158): ... here.
+
+2013-11-09 Mark Wielaard <[email protected]>
+
+ * dwarf_getaranges.c (dwarf_getaranges): Read segment_size and
+ check that it is zero.
+
+2013-11-07 Jan Kratochvil <[email protected]>
+
+ * cfi.h (struct Dwarf_Frame_s): Make the comment more specific.
+ * libdw.map (ELFUTILS_0.156): Add 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.
+
+2013-11-01 Michael Forney <[email protected]>
+
+ * Makefile.am (libdwfl_objects): New definition.
+ (libdw_a_LIBADD): Use libdwfl_objects.
+
+2013-11-01 Michael Forney <[email protected]>
+
+ * Makefile.am: Use READELF.
+
+2013-10-30 Jan Kratochvil <[email protected]>
+
+ * libdw.map (ELFUTILS_0.158): New.
+
+2013-10-10 Mark Wielaard <[email protected]>
+
+ * dwarf_getfuncs.c (struct visitor_info): Rename start_offset to
+ start_addr and rename last_offset to last_addr. Now both void *.
+ (tree_visitor): Use start_add and die_addr instead of start_offset
+ and die_offset.
+ (dwarf_getfuncs): Use last_addr instead of last_offset.
+
+2013-10-06 Mark Wielaard <[email protected]>
+
+ * cfi.c (execute_cfi): Make sure DW_CFA_expression and
+ DW_CFA_val_expression are not used with abi_cfi.
+
+2013-10-03 Josh Stone <[email protected]>
+
+ * dwarf_formref_die.c (dwarf_formref_die): Don't hash the sig8 here.
+ * libdw_findcu.c (__libdw_intern_next_unit): Since this never revisits
+ a unit, make sure to always hash the sig8 here, so none are missed.
+
2013-09-29 Mark Wielaard <[email protected]>
* dwarf_getlocation.c (store_implicit_value): Cast op->number2 to
diff --git a/libdw/Makefile.am b/libdw/Makefile.am
index 5fef2e18..cd9e3143 100644
--- a/libdw/Makefile.am
+++ b/libdw/Makefile.am
@@ -28,7 +28,6 @@
## not, see <http://www.gnu.org/licenses/>.
##
include $(top_srcdir)/config/eu.am
-DEFS += -DIS_LIBDW
if BUILD_STATIC
AM_CFLAGS += -fpic
endif
@@ -79,7 +78,7 @@ libdw_a_SOURCES = dwarf_begin.c dwarf_begin_elf.c dwarf_end.c dwarf_getelf.c \
dwarf_getfuncs.c \
dwarf_decl_file.c dwarf_decl_line.c dwarf_decl_column.c \
dwarf_func_inline.c dwarf_getsrc_file.c \
- libdw_findcu.c libdw_form.c libdw_alloc.c memory-access.c \
+ libdw_findcu.c libdw_form.c libdw_alloc.c \
libdw_visit_scopes.c \
dwarf_entry_breakpoints.c \
dwarf_next_cfi.c \
@@ -113,7 +112,7 @@ libdw.so: $(srcdir)/libdw.map libdw_pic.a \
-Wl,--version-script,$<,--no-undefined \
-Wl,--whole-archive $(filter-out $<,$^) -Wl,--no-whole-archive\
-ldl $(zip_LIBS)
- if readelf -d $@ | fgrep -q TEXTREL; then exit 1; fi
+ if $(READELF) -d $@ | fgrep -q TEXTREL; then exit 1; fi
ln -fs $@ $@.$(VERSION)
install: install-am libdw.so
@@ -129,7 +128,8 @@ uninstall: uninstall-am
rmdir --ignore-fail-on-non-empty $(DESTDIR)$(includedir)/elfutils
endif
-libdw_a_LIBADD = $(addprefix ../libdwfl/,$(shell $(AR) t ../libdwfl/libdwfl.a))
+libdwfl_objects = $(shell $(AR) t ../libdwfl/libdwfl.a)
+libdw_a_LIBADD = $(addprefix ../libdwfl/,$(libdwfl_objects))
noinst_HEADERS = libdwP.h memory-access.h dwarf_abbrev_hash.h \
dwarf_sig8_hash.h cfi.h encoded-value.h
diff --git a/libdw/cfi.c b/libdw/cfi.c
index b1e8d485..a146f129 100644
--- a/libdw/cfi.c
+++ b/libdw/cfi.c
@@ -252,6 +252,8 @@ execute_cfi (Dwarf_CFI *cache,
continue;
case DW_CFA_expression:
+ /* Expression rule relies on section data, abi_cfi cannot use it. */
+ assert (! abi_cfi);
get_uleb128 (regno, program);
offset = program - (const uint8_t *) cache->data->d.d_buf;
/* DW_FORM_block is a ULEB128 length followed by that many bytes. */
@@ -262,6 +264,8 @@ execute_cfi (Dwarf_CFI *cache,
continue;
case DW_CFA_val_expression:
+ /* Expression rule relies on section data, abi_cfi cannot use it. */
+ assert (! abi_cfi);
get_uleb128 (regno, program);
/* DW_FORM_block is a ULEB128 length followed by that many bytes. */
offset = program - (const uint8_t *) cache->data->d.d_buf;
diff --git a/libdw/cfi.h b/libdw/cfi.h
index 89498335..98ac6cfa 100644
--- a/libdw/cfi.h
+++ b/libdw/cfi.h
@@ -1,5 +1,5 @@
/* Internal definitions for libdw CFI interpreter.
- Copyright (C) 2009-2010 Red Hat, Inc.
+ Copyright (C) 2009-2010, 2013 Red Hat, Inc.
This file is part of elfutils.
This file is free software; you can redistribute it and/or modify
@@ -150,8 +150,8 @@ struct dwarf_frame_register
Dwarf_Sword value:(sizeof (Dwarf_Sword) * 8 - 3);
};
-/* This holds everything we know about the state of the frame
- at a particular PC location described by an FDE. */
+/* This holds instructions for unwinding frame at a particular PC location
+ described by an FDE. */
struct Dwarf_Frame_s
{
/* This frame description covers PC values in [start, end). */
diff --git a/libdw/dwarf_formref_die.c b/libdw/dwarf_formref_die.c
index b1af2abf..b54e2166 100644
--- a/libdw/dwarf_formref_die.c
+++ b/libdw/dwarf_formref_die.c
@@ -89,7 +89,6 @@ dwarf_formref_die (attr, result)
?: DWARF_E_INVALID_REFERENCE);
return NULL;
}
- Dwarf_Sig8_Hash_insert (&cu->dbg->sig8_hash, cu->type_sig8, cu);
}
while (cu->type_sig8 != sig);
diff --git a/libdw/dwarf_getaranges.c b/libdw/dwarf_getaranges.c
index cc70cb21..20ac7ec6 100644
--- a/libdw/dwarf_getaranges.c
+++ b/libdw/dwarf_getaranges.c
@@ -144,9 +144,10 @@ dwarf_getaranges (dbg, aranges, naranges)
if (address_size != 4 && address_size != 8)
goto invalid;
- /* Ignore the segment size value. */
- // XXX Really?
- (void) *readp++;
+ /* We don't actually support segment selectors. */
+ unsigned int segment_size = *readp++;
+ if (segment_size != 0)
+ goto invalid;
/* Round the address to the next multiple of 2*address_size. */
readp += ((2 * address_size - ((readp - hdrstart) % (2 * address_size)))
diff --git a/libdw/dwarf_getfuncs.c b/libdw/dwarf_getfuncs.c
index 87e0341a..82894c98 100644
--- a/libdw/dwarf_getfuncs.c
+++ b/libdw/dwarf_getfuncs.c
@@ -43,11 +43,11 @@ struct visitor_info
/* The user arg value to dwarf_getfuncs. */
void *arg;
- /* The DIE offset where to (re)start the search. Zero for all. */
- Dwarf_Off start_offset;
+ /* Addr of the DIE offset where to (re)start the search. Zero for all. */
+ void *start_addr;
- /* Last subprogram DIE offset seen. */
- Dwarf_Off last_offset;
+ /* Last subprogram DIE addr seen. */
+ void *last_addr;
/* The CU only contains C functions. Allows pruning of most subtrees. */
bool c_cu;
@@ -59,8 +59,8 @@ tree_visitor (unsigned int depth __attribute__ ((unused)),
{
struct visitor_info *const v = arg;
Dwarf_Die *die = &chain->die;
- Dwarf_Off start_offset = v->start_offset;
- Dwarf_Off die_offset = INTUSE(dwarf_dieoffset) (die);
+ void *start_addr = v->start_addr;
+ void *die_addr = die->addr;
/* Pure C CUs can only contain defining subprogram DIEs as direct
children of the CU DIE or as nested function inside a normal C
@@ -75,11 +75,11 @@ tree_visitor (unsigned int depth __attribute__ ((unused)),
return DWARF_CB_OK;
}
- /* Skip all DIEs till we found the (re)start offset. */
- if (start_offset != 0)
+ /* Skip all DIEs till we found the (re)start addr. */
+ if (start_addr != NULL)
{
- if (die_offset == start_offset)
- v->start_offset = 0;
+ if (die_addr == start_addr)
+ v->start_addr = NULL;
return DWARF_CB_OK;
}
@@ -88,7 +88,7 @@ tree_visitor (unsigned int depth __attribute__ ((unused)),
|| INTUSE(dwarf_hasattr) (die, DW_AT_declaration))
return DWARF_CB_OK;
- v->last_offset = die_offset;
+ v->last_addr = die_addr;
return (*v->callback) (die, v->arg);
}
@@ -105,13 +105,13 @@ dwarf_getfuncs (Dwarf_Die *cudie, int (*callback) (Dwarf_Die *, void *),
|| lang == DW_LANG_C
|| lang == DW_LANG_C99);
- struct visitor_info v = { callback, arg, offset, 0, c_cu };
+ struct visitor_info v = { callback, arg, (void *) offset, NULL, c_cu };
struct Dwarf_Die_Chain chain = { .die = CUDIE (cudie->cu),
.parent = NULL };
int res = __libdw_visit_scopes (0, &chain, &tree_visitor, NULL, &v);
if (res == DWARF_CB_ABORT)
- return v.last_offset;
+ return (ptrdiff_t) v.last_addr;
else
return res;
}
diff --git a/libdw/dwarf_getlocation.c b/libdw/dwarf_getlocation.c
index ff25fc7c..8dffb83f 100644
--- a/libdw/dwarf_getlocation.c
+++ b/libdw/dwarf_getlocation.c
@@ -100,8 +100,7 @@ store_implicit_value (Dwarf *dbg, void **cache, Dwarf_Op *op)
struct loc_block_s *block = libdw_alloc (dbg, struct loc_block_s,
sizeof (struct loc_block_s), 1);
const unsigned char *data = (const unsigned char *) (uintptr_t) op->number2;
- Dwarf_Word blength; // Ignored, equal to op->number.
- get_uleb128 (blength, data);
+ (void) __libdw_get_uleb128 (&data); // Ignored, equal to op->number.
block->addr = op;
block->data = (unsigned char *) data;
block->length = op->number;
@@ -202,6 +201,13 @@ __libdw_intern_expression (Dwarf *dbg, bool other_byte_order,
bool cfap, bool valuep,
Dwarf_Op **llbuf, size_t *listlen, int sec_index)
{
+ /* Empty location expressions don't have any ops to intern. */
+ if (block->length == 0)
+ {
+ *listlen = 0;
+ return 0;
+ }
+
/* Check whether we already looked at this list. */
struct loc_s fake = { .addr = block->data };
struct loc_s **found = tfind (&fake, cache, loc_compare);
@@ -465,8 +471,8 @@ __libdw_intern_expression (Dwarf *dbg, bool other_byte_order,
if (unlikely (n == 0))
{
/* This is not allowed.
-
- XXX Is it? */
+ It would mean an empty location expression, which we handled
+ already as a special case above. */
goto invalid;
}
diff --git a/libdw/dwarf_getlocation_attr.c b/libdw/dwarf_getlocation_attr.c
index bf155840..cb290456 100644
--- a/libdw/dwarf_getlocation_attr.c
+++ b/libdw/dwarf_getlocation_attr.c
@@ -74,8 +74,8 @@ dwarf_getlocation_attr (attr, op, result)
return -1;
if (INTUSE(dwarf_attr) (&die, DW_AT_location, result) == NULL)
{
- __libdw_seterrno (DWARF_E_INVALID_DWARF);
- return -1;
+ __libdw_empty_loc_attr (result, attr->cu);
+ return 0;
}
}
break;
@@ -88,8 +88,8 @@ dwarf_getlocation_attr (attr, op, result)
if (INTUSE(dwarf_attr) (&die, DW_AT_location, result) == NULL
&& INTUSE(dwarf_attr) (&die, DW_AT_const_value, result) == NULL)
{
- __libdw_seterrno (DWARF_E_INVALID_DWARF);
- return -1;
+ __libdw_empty_loc_attr (result, attr->cu);
+ return 0;
}
}
break;
diff --git a/libdw/dwarf_getlocation_implicit_pointer.c b/libdw/dwarf_getlocation_implicit_pointer.c
index 322fdb8a..f93d17ec 100644
--- a/libdw/dwarf_getlocation_implicit_pointer.c
+++ b/libdw/dwarf_getlocation_implicit_pointer.c
@@ -34,6 +34,18 @@
#include <dwarf.h>
+static unsigned char empty_exprloc = 0;
+
+void
+internal_function
+__libdw_empty_loc_attr (Dwarf_Attribute *attr, struct Dwarf_CU *cu )
+{
+ attr->code = DW_AT_location;
+ attr->form = DW_FORM_exprloc;
+ attr->valp = &empty_exprloc;
+ attr->cu = cu;
+}
+
int
dwarf_getlocation_implicit_pointer (attr, op, result)
Dwarf_Attribute *attr;
@@ -57,8 +69,8 @@ dwarf_getlocation_implicit_pointer (attr, op, result)
if (INTUSE(dwarf_attr) (&die, DW_AT_location, result) == NULL
&& INTUSE(dwarf_attr) (&die, DW_AT_const_value, result) == NULL)
{
- __libdw_seterrno (DWARF_E_INVALID_DWARF);
- return -1;
+ __libdw_empty_loc_attr (result, attr->cu);
+ return 0;
}
return 0;
diff --git a/libdw/libdw.map b/libdw/libdw.map
index 09eae6a7..d0e47317 100644
--- a/libdw/libdw.map
+++ b/libdw/libdw.map
@@ -267,3 +267,28 @@ ELFUTILS_0.157 {
dwarf_getlocation_die;
dwarf_getlocation_attr;
} ELFUTILS_0.156;
+
+ELFUTILS_0.158 {
+ global:
+ # Replaced ELFUTILS_0.146 version, which has a wrapper without executable.
+ dwfl_core_file_report;
+
+ 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;
+ dwfl_frame_pc;
+
+ dwfl_module_getsymtab_first_global;
+ dwfl_module_addrinfo;
+ dwfl_module_getsym_info;
+
+ dwfl_core_file_attach;
+ dwfl_linux_proc_attach;
+} ELFUTILS_0.157;
diff --git a/libdw/libdwP.h b/libdw/libdwP.h
index f02a5bf2..49392005 100644
--- a/libdw/libdwP.h
+++ b/libdw/libdwP.h
@@ -34,6 +34,7 @@
#include <stdbool.h>
#include <libdw.h>
+#include <dwarf.h>
/* gettext helper macros. */
@@ -403,11 +404,40 @@ extern Dwarf_Abbrev *__libdw_getabbrev (Dwarf *dbg, struct Dwarf_CU *cu,
__nonnull_attribute__ (1) internal_function;
/* Helper functions for form handling. */
-extern size_t __libdw_form_val_len (Dwarf *dbg, struct Dwarf_CU *cu,
- unsigned int form,
- const unsigned char *valp)
+extern size_t __libdw_form_val_compute_len (Dwarf *dbg, struct Dwarf_CU *cu,
+ unsigned int form,
+ const unsigned char *valp)
__nonnull_attribute__ (1, 2, 4) internal_function;
+/* Find the length of a form attribute. */
+static inline size_t
+__nonnull_attribute__ (1, 2, 4)
+__libdw_form_val_len (Dwarf *dbg, struct Dwarf_CU *cu,
+ unsigned int form, const unsigned char *valp)
+{
+ /* Small lookup table of forms with fixed lengths. Absent indexes are
+ initialized 0, so any truly desired 0 is set to 0x80 and masked. */
+ static const uint8_t form_lengths[] =
+ {
+ [DW_FORM_flag_present] = 0x80,
+ [DW_FORM_data1] = 1, [DW_FORM_ref1] = 1, [DW_FORM_flag] = 1,
+ [DW_FORM_data2] = 2, [DW_FORM_ref2] = 2,
+ [DW_FORM_data4] = 4, [DW_FORM_ref4] = 4,
+ [DW_FORM_data8] = 8, [DW_FORM_ref8] = 8, [DW_FORM_ref_sig8] = 8,
+ };
+
+ /* Return immediately for forms with fixed lengths. */
+ if (form < sizeof form_lengths / sizeof form_lengths[0])
+ {
+ uint8_t len = form_lengths[form];
+ if (len != 0)
+ return len & 0x7f; /* Mask to allow 0x80 -> 0. */
+ }
+
+ /* Other forms require some computation. */
+ return __libdw_form_val_compute_len (dbg, cu, form, valp);
+}
+
/* Helper function for DW_FORM_ref* handling. */
extern int __libdw_formref (Dwarf_Attribute *attr, Dwarf_Off *return_offset)
__nonnull_attribute__ (1, 2) internal_function;
@@ -632,6 +662,10 @@ int __check_build_id (Dwarf *dw, const uint8_t *build_id, const size_t id_len)
internal_function;
#endif /* ENABLE_DWZ */
+/* Fills in the given attribute to point at an empty location expression. */
+void __libdw_empty_loc_attr (Dwarf_Attribute *attr, struct Dwarf_CU *cu)
+ internal_function;
+
/* Aliases to avoid PLTs. */
INTDECL (dwarf_aggregate_size)
diff --git a/libdw/libdw_findcu.c b/libdw/libdw_findcu.c
index 70e24a03..c0bff2af 100644
--- a/libdw/libdw_findcu.c
+++ b/libdw/libdw_findcu.c
@@ -110,6 +110,9 @@ __libdw_intern_next_unit (dbg, debug_types)
newp->lines = NULL;
newp->locs = NULL;
+ if (debug_types)
+ Dwarf_Sig8_Hash_insert (&dbg->sig8_hash, type_sig8, newp);
+
/* Add the new entry to the search tree. */
if (tsearch (newp, tree, findcu_cb) == NULL)
{
diff --git a/libdw/libdw_form.c b/libdw/libdw_form.c
index c476a6e3..53505564 100644
--- a/libdw/libdw_form.c
+++ b/libdw/libdw_form.c
@@ -39,13 +39,15 @@
size_t
internal_function
-__libdw_form_val_len (Dwarf *dbg, struct Dwarf_CU *cu, unsigned int form,
- const unsigned char *valp)
+__libdw_form_val_compute_len (Dwarf *dbg, struct Dwarf_CU *cu,
+ unsigned int form, const unsigned char *valp)
{
const unsigned char *saved;
Dwarf_Word u128;
size_t result;
+ /* NB: This doesn't cover constant form lengths, which are
+ already handled by the inlined __libdw_form_val_len. */
switch (form)
{
case DW_FORM_addr:
@@ -82,32 +84,6 @@ __libdw_form_val_len (Dwarf *dbg, struct Dwarf_CU *cu, unsigned int form,
result = u128 + (valp - saved);
break;
- case DW_FORM_flag_present:
- result = 0;
- break;
-
- case DW_FORM_ref1:
- case DW_FORM_data1:
- case DW_FORM_flag:
- result = 1;
- break;
-
- case DW_FORM_data2:
- case DW_FORM_ref2:
- result = 2;
- break;
-
- case DW_FORM_data4:
- case DW_FORM_ref4:
- result = 4;
- break;
-
- case DW_FORM_data8:
- case DW_FORM_ref8:
- case DW_FORM_ref_sig8:
- result = 8;
- break;
-
case DW_FORM_string:
result = strlen ((char *) valp) + 1;
break;
diff --git a/libdw/memory-access.h b/libdw/memory-access.h
index 16471990..d0ee63c5 100644
--- a/libdw/memory-access.h
+++ b/libdw/memory-access.h
@@ -37,90 +37,59 @@
/* Number decoding macros. See 7.6 Variable Length Data. */
-#define get_uleb128_step(var, addr, nth, break) \
- __b = *(addr)++; \
- var |= (uintmax_t) (__b & 0x7f) << (nth * 7); \
- if (likely ((__b & 0x80) == 0)) \
- break
-
-#define get_uleb128(var, addr) \
- do { \
- unsigned char __b; \
- var = 0; \
- get_uleb128_step (var, addr, 0, break); \
- var = __libdw_get_uleb128 (var, 1, &(addr)); \
- } while (0)
+#define len_leb128(var) ((8 * sizeof (var) + 6) / 7)
-#define get_uleb128_rest_return(var, i, addrp) \
+#define get_uleb128_step(var, addr, nth) \
do { \
- for (; i < 10; ++i) \
- { \
- get_uleb128_step (var, *addrp, i, return var); \
- } \
- /* Other implementations set VALUE to UINT_MAX in this \
- case. So we better do this as well. */ \
- return UINT64_MAX; \
+ unsigned char __b = *(addr)++; \
+ (var) |= (typeof (var)) (__b & 0x7f) << ((nth) * 7); \
+ if (likely ((__b & 0x80) == 0)) \
+ return (var); \
} while (0)
-/* The signed case is similar, but we sign-extend the result. */
+static inline uint64_t
+__libdw_get_uleb128 (const unsigned char **addrp)
+{
+ uint64_t acc = 0;
+ /* Unroll the first step to help the compiler optimize
+ for the common single-byte case. */
+ get_uleb128_step (acc, *addrp, 0);
+ for (unsigned int i = 1; i < len_leb128 (acc); ++i)
+ get_uleb128_step (acc, *addrp, i);
+ /* Other implementations set VALUE to UINT_MAX in this
+ case. So we better do this as well. */
+ return UINT64_MAX;
+}
-#define get_sleb128_step(var, addr, nth, break) \
- __b = *(addr)++; \
- _v |= (uint64_t) (__b & 0x7f) << (nth * 7); \
- if (likely ((__b & 0x80) == 0)) \
- { \
- var = (_v << (64 - (nth * 7) - 7)) >> (64 - (nth * 7) - 7); \
- break; \
- } \
- else do {} while (0)
+#define get_uleb128(var, addr) ((var) = __libdw_get_uleb128 (&(addr)))
-#define get_sleb128(var, addr) \
- do { \
- unsigned char __b; \
- int64_t _v = 0; \
- get_sleb128_step (var, addr, 0, break); \
- var = __libdw_get_sleb128 (_v, 1, &(addr)); \
- } while (0)
+/* The signed case is similar, but we sign-extend the result. */
-#define get_sleb128_rest_return(var, i, addrp) \
+#define get_sleb128_step(var, addr, nth) \
do { \
- for (; i < 9; ++i) \
+ unsigned char __b = *(addr)++; \
+ if (likely ((__b & 0x80) == 0)) \
{ \
- get_sleb128_step (var, *addrp, i, return var); \
+ struct { signed int i:7; } __s = { .i = __b }; \
+ (var) |= (typeof (var)) __s.i << ((nth) * 7); \
+ return (var); \
} \
- __b = *(*addrp)++; \
- if (likely ((__b & 0x80) == 0)) \
- return var | ((uint64_t) __b << 63); \
- else \
- /* Other implementations set VALUE to INT_MAX in this \
- case. So we better do this as well. */ \
- return INT64_MAX; \
+ (var) |= (typeof (var)) (__b & 0x7f) << ((nth) * 7); \
} while (0)
-#ifdef IS_LIBDW
-extern uint64_t __libdw_get_uleb128 (uint64_t acc, unsigned int i,
- const unsigned char **addrp)
- internal_function attribute_hidden;
-extern int64_t __libdw_get_sleb128 (int64_t acc, unsigned int i,
- const unsigned char **addrp)
- internal_function attribute_hidden;
-#else
-static inline uint64_t
-__attribute__ ((unused))
-__libdw_get_uleb128 (uint64_t acc, unsigned int i, const unsigned char **addrp)
-{
- unsigned char __b;
- get_uleb128_rest_return (acc, i, addrp);
-}
static inline int64_t
-__attribute__ ((unused))
-__libdw_get_sleb128 (int64_t acc, unsigned int i, const unsigned char **addrp)
+__libdw_get_sleb128 (const unsigned char **addrp)
{
- unsigned char __b;
- int64_t _v = acc;
- get_sleb128_rest_return (acc, i, addrp);
+ int64_t acc = 0;
+ /* Unrolling 0 like uleb128 didn't prove to benefit optimization. */
+ for (unsigned int i = 0; i < len_leb128 (acc); ++i)
+ get_sleb128_step (acc, *addrp, i);
+ /* Other implementations set VALUE to INT_MAX in this
+ case. So we better do this as well. */
+ return INT64_MAX;
}
-#endif
+
+#define get_sleb128(var, addr) ((var) = __libdw_get_sleb128 (&(addr)))
/* We use simple memory access functions in case the hardware allows it.
diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog
index af1ec112..572dd1a9 100644
--- a/libdwfl/ChangeLog
+++ b/libdwfl/ChangeLog
@@ -1,3 +1,368 @@
+2014-01-02 Mark Wielaard <[email protected]>
+
+ * linux-pid-attach.c (dwfl_linux_proc_attach): Use strtol, not atoi.
+
+2013-12-30 Mark Wielaard <[email protected]>
+
+ * argp-std.c (parse_opt): Call dwfl_linux_proc_attach and
+ dwfl_core_file_attach explicitly.
+ * core-file.c (dwfl_core_file_report): Don't call
+ __libdwfl_attach_state_for_core implicitly.
+ * dwfl_begin.c (dwfl_begin): Remove setting of process_attach_error.
+ * dwfl_frame.c (dwfl_pid): Set errno to DWFL_E_NO_ATTACH_STATE, not
+ process_attach_error.
+ (dwfl_getthreads): Likewise.
+ (getthread): Likewise.
+ * libdwfl.h (dwfl_core_file_report): Update documentation.
+ (dwfl_linux_proc_report): Likewise.
+ (dwfl_core_file_attach): New function declaration.
+ (dwfl_linux_proc_attach): Likewise.
+ * libdwflP.h (struct Dwfl): Remove process_attach_error.
+ (__libdwfl_attach_state_for_pid): Removed declaration.
+ (__libdwfl_attach_state_for_core): Likewise.
+ (dwfl_core_file_attach): New internal declaration.
+ (dwfl_linux_proc_attach): Likewise.
+ (attach_state_for_core): Renamed to...
+ (dwfl_core_file_attach): ...this. Change return type.
+ (__libdwfl_attach_state_for_core): Removed.
+ * linux-pid-attach.c (struct pid_arg): Add assume_ptrace_stopped.
+ (pid_set_initial_registers): Check assume_ptrace_stopped before
+ calling ptrace.
+ (pid_thread_detach): Likewise.
+ (__libdwfl_attach_state_for_pid): Renamed to...
+ (dwfl_linux_proc_attach): ...this. Adjust return type.
+ * linux-proc-maps.c (dwfl_linux_proc_report): Don't call
+ __libdwfl_attach_state_for_pid implicitly.
+
+2013-12-28 Mark Wielaard <[email protected]>
+
+ * linux-proc-maps.c (dwfl_linux_proc_find_elf): Don't return special
+ character device files, only regular files.
+
+2013-12-24 Mark Wielaard <[email protected]>
+
+ * linux-core-attach.c (core_next_thread): Check whether thread_argp
+ is NULL. Reset core_arg->thread_note_offset and malloc a thread_arg
+ in that case. Free thread_arg if there are no more threads.
+
+2013-12-23 Mark Wielaard <[email protected]>
+
+ * dwfl_segment_report_module.c (dwfl_segment_report_module): Free
+ build_id before returning early.
+
+2013-12-23 Mark Wielaard <[email protected]>
+
+ * linux-pid-attach.c (__libdwfl_attach_state_for_pid): Report actual
+ pid (thread group leader) to dwfl_attach_state.
+
+2013-12-21 Mark Wielaard <[email protected]>
+
+ * frame_unwind.c (handle_cfi): Track whether the return register
+ has been set and only allow it to be set once.
+
+2013-12-20 Mark Wielaard <[email protected]>
+
+ * 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_frames): Likewise.
+ * libdwflP.h (dwfl_getthread_frames): New internal function declaration.
+ * 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-20 Mark Wielaard <[email protected]>
+
+ * linux-kernel-modules.c (report_kernel_archive): Correct nested
+ asprintf result check for debug.a.
+
+2013-12-18 Mark Wielaard <[email protected]>
+
+ * derelocate.c (__libdwfl_find_section_ndx): New internal function.
+ * dwfl_module_addrname.c (dwfl_module_addrname): Use
+ dwfl_module_addrinfo.
+ * dwfl_module_addrsym.c (dwfl_module_addrsym_elf): Replace with...
+ (__libdwfl_addrsym): ...this. Use __libdwfl_getsym, use value
+ for comparisons, not st_value. Fill in off. Search for both value
+ and the (adjusted) sym.st_value when different.
+ (dwfl_module_addrsym): Implement using __libdwfl_addrsym.
+ (dwfl_module_addrinfo): New function.
+ * dwfl_module_getsym.c (dwfl_module_getsym_elf): Replace with...
+ (__libdwfl_getsym): ...this. Use ebl_resolve_sym_value if requested
+ and possible. Adjust sym->st_value only when requested. Fill in addr
+ if available.
+ (dwfl_module_getsym_info): New function.
+ (dwfl_module_getsym): Use __libdwfl_getsym.
+ * libdwfl.h (dwfl_module_getsym_elf): Removed.
+ (dwfl_module_getsym_info): New function declaration.
+ (dwfl_module_addrinfo): Likewise.
+ (dwfl_module_addrsym): Add documentation describing differences
+ with addrinfo variants.
+ (dwfl_module_addrsym_elf): Removed.
+ * libdwflP.h (__libdwfl_getsym): New internal function declaration.
+ (__libdwfl_addrsym): Likewise.
+ (__libdwfl_find_section_ndx): Likewise.
+ (dwfl_module_addrinfo): New internal declaration.
+ (dwfl_module_getsym_info): Likewise.
+ (dwfl_module_addrsym_elf): Removed.
+ (dwfl_module_getsym_elf): Likewise.
+
+2013-12-18 Jan Kratochvil <[email protected]>
+
+ * argp-std.c (offline_find_elf): Remove.
+ (offline_callbacks): Use dwfl_build_id_find_elf instead.
+ * dwfl_build_id_find_elf.c (dwfl_build_id_find_elf): Move here the code
+ removed above.
+
+2013-12-18 Jan Kratochvil <[email protected]>
+
+ unwinder: s390 and s390x
+ * dwfl_frame_pc.c (dwfl_frame_pc): Call ebl_normalize_pc.
+ * frame_unwind.c (new_unwound): New function from ...
+ (handle_cfi): ... here. Call it.
+ (setfunc, getfunc, readfunc): New functions.
+ (__libdwfl_frame_unwind): Call ebl_unwind with those functions.
+ * linux-core-attach.c (core_set_initial_registers): Always iterate
+ through the Ebl_Register_Location loop. Call
+ dwfl_thread_state_register_pc there.
+
+2013-12-17 Jan Kratochvil <[email protected]>
+
+ * frame_unwind.c (handle_cfi): Call ebl_dwarf_to_regno for RA.
+
+2013-12-17 Mark Wielaard <[email protected]>
+
+ * linux-pid-attach.c (pid_next_thread): Call rewinddir on first
+ traversal.
+
+2013-12-16 Mark Wielaard <[email protected]>
+
+ * libdwfl.h (dwfl_module_getsymtab_first_global): New function
+ definition.
+ * dwfl_module_getdwarf.c (dwfl_module_getsymtab_first_global): New
+ function.
+ * libdwflP.h (dwfl_module_getsymtab_first_global): New internal
+ function definition.
+ * dwfl_module_addrsym.c (dwfl_module_addrsym_elf): Use new function.
+
+2013-12-14 Mark Wielaard <[email protected]>
+
+ * dwfl_module.c (__libdwfl_module_free): Free mod->reloc_info if
+ allocated. Call dwarf_cfi_end on mod->eh_cfi if necessary.
+ * frame_unwind.c (handle_cfi): Free frame result from
+ dwarf_cfi_addrframe when done.
+
+2013-12-15 Jan Kratochvil <[email protected]>
+
+ unwinder: ppc and ppc64
+ * frame_unwind.c (__libdwfl_frame_reg_get, __libdwfl_frame_reg_set):
+ Call ebl_dwarf_to_regno.
+ * linux-core-attach.c (core_set_initial_registers): Implement
+ pc_register support.
+ * linux-pid-attach.c (pid_thread_state_registers_cb): Implement
+ FIRSTREG -1.
+
+2013-11-30 Jan Kratochvil <[email protected]>
+
+ Introduce process_attach_error.
+ * dwfl_begin.c (dwfl_begin): Initialize process_attach_error.
+ * dwfl_frame.c (dwfl_pid, dwfl_getthreads): Use PROCESS_ATTACH_ERROR if
+ PROCESS is NULL.
+ * libdwflP.h (struct Dwfl): New field process_attach_error.
+ * linux-core-attach.c (__libdwfl_attach_state_for_core): Rename to ...
+ (attach_state_for_core): ... here, make it static, change return type,
+ no longer use __libdwfl_seterrno.
+ (__libdwfl_attach_state_for_core): New wrapper for it.
+
+2013-11-27 Mark Wielaard <[email protected]>
+
+ * dwfl_module_addrsym.c (dwfl_module_addrsym): Rename to and call...
+ (dwfl_module_addrsym_elf): this. Add elfp and biasp arguments,
+ keep track of symelf, addr_symelf, closest_elf and sizeless_elf
+ instead of tracking dwfl_files.
+ * dwfl_module_getsym.c (__libdwfl_module_getsym): Renamed to...
+ (dwfl_module_getsym_elf): ...this. Remove dwfl_file argument, add
+ new elfp and biasp arguments. Track elf instead of file.
+ (dwfl_module_getsym): Call dwfl_module_getsym_elf.
+ dwfl_module_info.c (dwfl_module_info): Pass elf to
+ dwfl_adjusted_st_value.
+ * libdwfl.h (dwfl_module_getsym): Document limitations of shndx.
+ (dwfl_module_getsym_elf): New function declaration.
+ (dwfl_module_addrsym_elf): Likewise.
+ * libdwflP.h (dwfl_module_addrsym_elf): INTDECL.
+ (dwfl_module_getsym_elf): Likewise.
+ (dwfl_adjusted_st_value): Take and check elf not dwfl_file.
+ (dwfl_deadjust_st_value): Likewise.
+ (__libdwfl_module_getsym): Removed.
+ * relocate.c (resolve_symbol): Pass elf to dwfl_adjusted_st_value.
+
+2013-11-21 Jan Kratochvil <[email protected]>
+
+ Fix non-build-id core files on build-id system.
+ * link_map.c (report_r_debug): Remove valid clearing if build-id cannot
+ be read from memory.
+
+2013-11-21 Jan Kratochvil <[email protected]>
+
+ * dwfl_segment_report_module.c (dwfl_segment_report_module): New
+ variable close_elf. Call __libdwfl_find_elf_build_id and compare the
+ content, if possible.
+
+2013-11-21 Jan Kratochvil <[email protected]>
+
+ link_map: Use proper bias, not l_addr.
+ * core-file.c (dynamic_vaddr_get): Rename to ...
+ (__libdwfl_dynamic_vaddr_get): ... here, make it global,
+ internal_function.
+ (dwfl_core_file_report): Update name in the caller.
+ * libdwflP.h (__libdwfl_dynamic_vaddr_get): New declaration.
+ * link_map.c (report_r_debug): New variable elf_dynamic_vaddr. Call
+ __libdwfl_dynamic_vaddr_get for it. Remove L_ADDR FIXME comment.
+ Use ELF_DYNAMIC_VADDR instead of L_ADDR.
+
+2013-11-19 Jan Kratochvil <[email protected]>
+
+ Compatibility with older kernels such as RHEL-6.
+ * linux-pid-attach.c (struct pid_arg): New field tid_was_stopped.
+ (ptrace_attach): New parameter tid_was_stoppedp. Set it.
+ (pid_set_initial_registers): Pass tid_was_stopped.
+ (pid_thread_detach): Use tid_was_stopped.
+
+2013-11-18 Josh Stone <[email protected]>
+
+ * dwfl_module_getdwarf.c (find_aux_address_sync): New function.
+ (find_aux_sym): Use it.
+
+2013-11-14 Jan Kratochvil <[email protected]>
+
+ Code cleanup: Remove const in prototype
+ * dwfl_frame_regs.c (dwfl_thread_state_registers): Remove const from
+ firstreg.
+ * libdwfl.h (dwfl_thread_state_registers): Likewise.
+ * linux-pid-attach.c (pid_thread_state_registers_cb): Likewise.
+
+2013-11-14 Jan Kratochvil <[email protected]>
+
+ Fix dwfl_attach_state machine->elf.
+ * dwfl_frame.c (dwfl_attach_state): Change parameter machine to elf.
+ Call ebl_openbackend instead of ebl_openbackend_machine.
+ * libdwfl.h (dwfl_attach_state): Change parameter machine to elf.
+ Update the function description.
+ * linux-core-attach.c (__libdwfl_attach_state_for_core): Pass CORE to
+ dwfl_attach_state.
+ * linux-pid-attach.c (__libdwfl_attach_state_for_pid): Pass NULL to
+ dwfl_attach_state.
+
+2013-11-06 Jan Kratochvil <[email protected]>
+
+ Provide __libdwfl_module_getsym to get dwfl_file *.
+ * dwfl_module_addrsym.c (dwfl_module_addrsym) (i_to_symfile): Remove.
+ (dwfl_module_addrsym) (search_table): New variable file. Use
+ __libdwfl_module_getsym. Use file.
+ * dwfl_module_getsym.c (dwfl_module_getsym): Rename to ...
+ (__libdwfl_module_getsym): ... here. Add parameter filep. Set it.
+ (dwfl_module_getsym): New wrapper.
+ * libdwflP.h (__libdwfl_module_getsym): New declaration.
+
+2013-11-13 Jan Kratochvil <[email protected]>
+
+ Fix dwfl_module_addrsym for minidebuginfo.
+ * dwfl_module_addrsym.c (dwfl_module_addrsym): New variable
+ addr_symfile.
+ (dwfl_module_addrsym) (same_section): Use it.
+ (dwfl_module_addrsym) (i_to_symfile): New function.
+ (dwfl_module_addrsym) (search_table): Use it.
+
+2013-11-07 Jan Kratochvil <[email protected]>
+ Mark Wielaard <[email protected]>
+
+ * Makefile.am (libdwfl_a_SOURCES): Add dwfl_frame.c, frame_unwind.c,
+ dwfl_frame_pc.c, linux-pid-attach.c, linux-core-attach.c and
+ dwfl_frame_regs.c.
+ * core-file.c (dwfl_core_file_report): Call
+ __libdwfl_attach_state_for_core.
+ * dwfl_end.c (dwfl_end): Call __libdwfl_process_free.
+ * dwfl_frame.c: New file.
+ * frame_unwind.c: New file.
+ * dwfl_frame_pc.c: New file.
+ * linux-pid-attach.c: New file.
+ * linux-core-attach.c: New file.
+ * dwfl_frame_regs.c: New file.
+ * libdwfl.h (Dwfl_Thread, Dwfl_Frame): New typedefs.
+ (dwfl_core_file_report, dwfl_linux_proc_report): Extend comments.
+ (Dwfl_Thread_Callbacks): New definition.
+ (struct ebl, 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)
+ (dwfl_frame_pc): New declarations.
+ * libdwflP.h (Dwfl_Process): New typedef.
+ (LIBEBL_BAD, CORE_MISSING, INVALID_REGISTER, PROCESS_MEMORY_READ)
+ (PROCESS_NO_ARCH, PARSE_PROC, INVALID_DWARF, UNSUPPORTED_DWARF)
+ (NEXT_THREAD_FAIL, ATTACH_STATE_CONFLICT, NO_ATTACH_STATE, NO_UNWIND)
+ (INVALID_ARGUMENT): New DWFL_ERROR entries.
+ (struct Dwfl): New entry process.
+ (struct Dwfl_Process, struct Dwfl_Thread, struct Dwfl_Frame)
+ (__libdwfl_frame_reg_get, __libdwfl_frame_reg_set)
+ (__libdwfl_process_free, __libdwfl_frame_unwind)
+ (__libdwfl_attach_state_for_pid, __libdwfl_attach_state_for_core)
+ (__libdwfl_segment_start, __libdwfl_segment_end): New declarations.
+ (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)
+ (dwfl_frame_pc): New INTDECL entries.
+ * linux-proc-maps.c (dwfl_linux_proc_report): Call
+ __libdwfl_attach_state_for_pid.
+ * segment.c (segment_start): Rename to ...
+ (__libdwfl_segment_start): ... here and make it internal_function.
+ (segment_end): Rename to ...
+ (__libdwfl_segment_end): ... here and make it internal_function.
+ (reify_segments, dwfl_report_segment): Rename them at the callers.
+
+2013-11-07 Jan Kratochvil <[email protected]>
+
+ * core-file.c (dwfl_core_file_report): Remove the use of MAX.
+
+2013-11-07 Jan Kratochvil <[email protected]>
+
+ * core-file.c (dwfl_core_file_report): Replaced variable sniffed by
+ retval. Fix one forgotten LISTED increase.
+
+2013-11-07 Jan Kratochvil <[email protected]>
+
+ Fix core files for re-prelink-ed files.
+ * core-file.c (dynamic_vaddr_get): New function.
+ (dwfl_core_file_report): New variable file_dynamic_vaddr. Call
+ dynamic_vaddr_get instead of using L_ADDR.
+ * libdwflP.h (struct r_debug_info_module): Remove field l_addr.
+ * link_map.c (report_r_debug): Do not initialize l_addr.
+
+2013-11-07 Jan Kratochvil <[email protected]>
+
+ Code cleanup.
+ * core-file.c (dwfl_core_file_report): Reindent block of code by
+ continue keyword.
+
+2013-10-30 Jan Kratochvil <[email protected]>
+
+ * argp-std.c (parse_opt): Use executable parameter of
+ dwfl_core_file_report.
+ * core-file.c (dwfl_core_file_report): Add parameter executable. Set
+ it to DWFL. Add NEW_VERSION for it.
+ (_compat_without_executable_dwfl_core_file_report): New. Twice.
+ * libdwfl.h (dwfl_core_file_report): Add parameter executable, update
+ the function comment.
+
+2013-10-15 Mark Wielaard <[email protected]>
+
+ * linux-proc-maps.c (proc_maps_report): Ignore non-absolute file
+ mappings.
+ (dwfl_linux_proc_find_elf): Don't abort, just return failure.
+
2013-09-12 Mark Wielaard <[email protected]>
* cu.c (intern_cu): If dwarf_offdie fails free cu.
diff --git a/libdwfl/Makefile.am b/libdwfl/Makefile.am
index 3ef4dd6b..ce590dac 100644
--- a/libdwfl/Makefile.am
+++ b/libdwfl/Makefile.am
@@ -2,7 +2,7 @@
##
## Process this file with automake to create Makefile.in
##
-## Copyright (C) 2005-2010 Red Hat, Inc.
+## Copyright (C) 2005-2010, 2013 Red Hat, Inc.
## This file is part of elfutils.
##
## This file is free software; you can redistribute it and/or modify
@@ -68,7 +68,9 @@ libdwfl_a_SOURCES = dwfl_begin.c dwfl_end.c dwfl_error.c dwfl_version.c \
dwfl_module_return_value_location.c \
dwfl_module_register_names.c \
dwfl_segment_report_module.c \
- link_map.c core-file.c open.c image-header.c
+ link_map.c core-file.c open.c image-header.c \
+ dwfl_frame.c frame_unwind.c dwfl_frame_pc.c \
+ linux-pid-attach.c linux-core-attach.c dwfl_frame_regs.c
if ZLIB
libdwfl_a_SOURCES += gzip.c
diff --git a/libdwfl/argp-std.c b/libdwfl/argp-std.c
index c8843909..3a2d2a59 100644
--- a/libdwfl/argp-std.c
+++ b/libdwfl/argp-std.c
@@ -60,32 +60,6 @@ static const struct argp_option options[] =
{ NULL, 0, NULL, 0, NULL, 0 }
};
-/* Wrapper to provide proper FILE_NAME for -e|--executable. */
-static int
-offline_find_elf (Dwfl_Module *mod, void **userdata, const char *modname,
- Dwarf_Addr base, char **file_name, Elf **elfp)
-{
- if (modname != NULL && (strcmp (modname, "[exe]") == 0
- || strcmp (modname, "[pie]") == 0)
- && mod->dwfl->executable_for_core)
- {
- /* When both --core and --executable are given in whatever order
- dwfl_core_file_report is called first and this callback will replace
- the Dwfl_Module main.name with the recorded --executable file when the
- modname is [exe] or [pie] (which then triggers opening and reporting
- of the executable). */
- char *e_dup = strdup (mod->dwfl->executable_for_core);
- if (e_dup)
- {
- free (*file_name);
- *file_name = e_dup;
- return -1;
- }
- }
- return INTUSE(dwfl_build_id_find_elf) (mod, userdata, modname, base,
- file_name, elfp);
-}
-
static char *debuginfo_path;
static const Dwfl_Callbacks offline_callbacks =
@@ -96,7 +70,7 @@ static const Dwfl_Callbacks offline_callbacks =
.section_address = INTUSE(dwfl_offline_section_address),
/* We use this table for core files too. */
- .find_elf = offline_find_elf,
+ .find_elf = INTUSE(dwfl_build_id_find_elf),
};
static const Dwfl_Callbacks proc_callbacks =
@@ -196,6 +170,11 @@ parse_opt (int key, char *arg, struct argp_state *state)
int result = INTUSE(dwfl_linux_proc_report) (dwfl, atoi (arg));
if (result != 0)
return fail (dwfl, result, arg);
+
+ result = INTUSE(dwfl_linux_proc_attach) (dwfl, atoi (arg), false);
+ if (result != 0)
+ /* Non-fatal to not be able to attach to process. */
+ failure (dwfl, result, _("cannot attach to process"));
opt->dwfl = dwfl;
}
else
@@ -295,9 +274,6 @@ parse_opt (int key, char *arg, struct argp_state *state)
if (opt->core)
{
- if (opt->e)
- dwfl->executable_for_core = strdup (opt->e);
-
int fd = open64 (opt->core, O_RDONLY);
if (fd < 0)
{
@@ -317,7 +293,7 @@ parse_opt (int key, char *arg, struct argp_state *state)
return error == DWFL_E_ERRNO ? errno : EIO;
}
- int result = INTUSE(dwfl_core_file_report) (dwfl, core);
+ int result = INTUSE(dwfl_core_file_report) (dwfl, core, opt->e);
if (result < 0)
{
elf_end (core);
@@ -325,6 +301,11 @@ parse_opt (int key, char *arg, struct argp_state *state)
return fail (dwfl, result, opt->core);
}
+ result = INTUSE(dwfl_core_file_attach) (dwfl, core);
+ if (result < 0)
+ /* Non-fatal to not be able to attach to core. */
+ failure (dwfl, result, _("cannot attach to core"));
+
/* From now we leak FD and CORE. */
if (result == 0)
diff --git a/libdwfl/core-file.c b/libdwfl/core-file.c
index 72075913..4ce63c4e 100644
--- a/libdwfl/core-file.c
+++ b/libdwfl/core-file.c
@@ -1,5 +1,5 @@
/* Core file handling.
- Copyright (C) 2008-2010 Red Hat, Inc.
+ Copyright (C) 2008-2010, 2013 Red Hat, Inc.
This file is part of elfutils.
This file is free software; you can redistribute it and/or modify
@@ -397,8 +397,30 @@ clear_r_debug_info (struct r_debug_info *r_debug_info)
}
}
+bool
+internal_function
+__libdwfl_dynamic_vaddr_get (Elf *elf, GElf_Addr *vaddrp)
+{
+ size_t phnum;
+ if (unlikely (elf_getphdrnum (elf, &phnum) != 0))
+ return false;
+ for (size_t i = 0; i < phnum; ++i)
+ {
+ GElf_Phdr phdr_mem;
+ GElf_Phdr *phdr = gelf_getphdr (elf, i, &phdr_mem);
+ if (unlikely (phdr == NULL))
+ return false;
+ if (phdr->p_type == PT_DYNAMIC)
+ {
+ *vaddrp = phdr->p_vaddr;
+ return true;
+ }
+ }
+ return false;
+}
+
int
-dwfl_core_file_report (Dwfl *dwfl, Elf *elf)
+dwfl_core_file_report (Dwfl *dwfl, Elf *elf, const char *executable)
{
size_t phnum;
if (unlikely (elf_getphdrnum (elf, &phnum) != 0))
@@ -407,6 +429,19 @@ dwfl_core_file_report (Dwfl *dwfl, Elf *elf)
return -1;
}
+ free (dwfl->executable_for_core);
+ if (executable == NULL)
+ dwfl->executable_for_core = NULL;
+ else
+ {
+ dwfl->executable_for_core = strdup (executable);
+ if (dwfl->executable_for_core == NULL)
+ {
+ __libdwfl_seterrno (DWFL_E_NOMEM);
+ return -1;
+ }
+ }
+
/* First report each PT_LOAD segment. */
GElf_Phdr notes_phdr;
int ndx = dwfl_report_core_segments (dwfl, elf, phnum, &notes_phdr);
@@ -449,14 +484,14 @@ dwfl_core_file_report (Dwfl *dwfl, Elf *elf)
struct r_debug_info r_debug_info;
memset (&r_debug_info, 0, sizeof r_debug_info);
- int listed = dwfl_link_map_report (dwfl, auxv, auxv_size,
+ int retval = dwfl_link_map_report (dwfl, auxv, auxv_size,
dwfl_elf_phdr_memory_callback, elf,
&r_debug_info);
+ int listed = retval > 0 ? retval : 0;
/* Now sniff segment contents for modules hinted by information gathered
from DT_DEBUG. */
- int sniffed = 0;
ndx = 0;
do
{
@@ -472,7 +507,7 @@ dwfl_core_file_report (Dwfl *dwfl, Elf *elf)
if (seg > ndx)
{
ndx = seg;
- ++sniffed;
+ ++listed;
}
else
++ndx;
@@ -487,40 +522,59 @@ dwfl_core_file_report (Dwfl *dwfl, Elf *elf)
lastmodp = &(*lastmodp)->next;
for (struct r_debug_info_module *module = r_debug_info.module;
module != NULL; module = module->next)
- if (module->elf != NULL)
- {
- Dwfl_Module *mod;
- mod = __libdwfl_report_elf (dwfl, basename (module->name), module->name,
- module->fd, module->elf, module->l_addr,
- true, true);
- if (mod == NULL)
- continue;
- module->elf = NULL;
- module->fd = -1;
- /* Move this module to the end of the list, so that we end
- up with a list in the same order as the link_map chain. */
- if (mod->next != NULL)
- {
- if (*lastmodp != mod)
- {
- lastmodp = &dwfl->modulelist;
- while (*lastmodp != mod)
- lastmodp = &(*lastmodp)->next;
- }
- *lastmodp = mod->next;
- mod->next = NULL;
- while (*lastmodp != NULL)
- lastmodp = &(*lastmodp)->next;
- *lastmodp = mod;
- }
- lastmodp = &mod->next;
- }
+ {
+ if (module->elf == NULL)
+ continue;
+ GElf_Addr file_dynamic_vaddr;
+ if (! __libdwfl_dynamic_vaddr_get (module->elf, &file_dynamic_vaddr))
+ continue;
+ Dwfl_Module *mod;
+ mod = __libdwfl_report_elf (dwfl, basename (module->name), module->name,
+ module->fd, module->elf,
+ module->l_ld - file_dynamic_vaddr,
+ true, true);
+ if (mod == NULL)
+ continue;
+ ++listed;
+ module->elf = NULL;
+ module->fd = -1;
+ /* Move this module to the end of the list, so that we end
+ up with a list in the same order as the link_map chain. */
+ if (mod->next != NULL)
+ {
+ if (*lastmodp != mod)
+ {
+ lastmodp = &dwfl->modulelist;
+ while (*lastmodp != mod)
+ lastmodp = &(*lastmodp)->next;
+ }
+ *lastmodp = mod->next;
+ mod->next = NULL;
+ while (*lastmodp != NULL)
+ lastmodp = &(*lastmodp)->next;
+ *lastmodp = mod;
+ }
+ lastmodp = &mod->next;
+ }
clear_r_debug_info (&r_debug_info);
/* We return the number of modules we found if we found any.
If we found none, we return -1 instead of 0 if there was an
error rather than just nothing found. */
- return sniffed || listed >= 0 ? listed + sniffed : listed;
+ return listed > 0 ? listed : retval;
}
INTDEF (dwfl_core_file_report)
+NEW_VERSION (dwfl_core_file_report, ELFUTILS_0.158)
+
+#ifdef SHARED
+int _compat_without_executable_dwfl_core_file_report (Dwfl *dwfl, Elf *elf);
+COMPAT_VERSION_NEWPROTO (dwfl_core_file_report, ELFUTILS_0.146,
+ without_executable)
+
+int
+_compat_without_executable_dwfl_core_file_report (Dwfl *dwfl, Elf *elf)
+{
+ return dwfl_core_file_report (dwfl, elf, NULL);
+}
+#endif
diff --git a/libdwfl/derelocate.c b/libdwfl/derelocate.c
index 56f998c3..da679089 100644
--- a/libdwfl/derelocate.c
+++ b/libdwfl/derelocate.c
@@ -1,5 +1,5 @@
/* Recover relocatibility for addresses computed from debug information.
- Copyright (C) 2005-2010 Red Hat, Inc.
+ Copyright (C) 2005-2010, 2013 Red Hat, Inc.
This file is part of elfutils.
This file is free software; you can redistribute it and/or modify
@@ -330,6 +330,17 @@ find_section (Dwfl_Module *mod, Dwarf_Addr *addr)
return -1;
}
+size_t
+internal_function
+__libdwfl_find_section_ndx (Dwfl_Module *mod, Dwarf_Addr *addr)
+{
+ int idx = find_section (mod, addr);
+ if (unlikely (idx == -1))
+ return SHN_UNDEF;
+
+ return elf_ndxscn (mod->reloc_info->refs[idx].scn);
+}
+
int
dwfl_module_relocate_address (Dwfl_Module *mod, Dwarf_Addr *addr)
{
diff --git a/libdwfl/dwfl_build_id_find_elf.c b/libdwfl/dwfl_build_id_find_elf.c
index 9272c1fd..a4f03263 100644
--- a/libdwfl/dwfl_build_id_find_elf.c
+++ b/libdwfl/dwfl_build_id_find_elf.c
@@ -116,6 +116,23 @@ dwfl_build_id_find_elf (Dwfl_Module *mod,
char **file_name, Elf **elfp)
{
*elfp = NULL;
+ if (modname != NULL && mod->dwfl->executable_for_core != NULL
+ && (strcmp (modname, "[exe]") == 0 || strcmp (modname, "[pie]") == 0))
+ {
+ /* When dwfl_core_file_report was called with a non-NULL executable file
+ name this callback will replace the Dwfl_Module main.name with the
+ recorded executable file when the modname is [exe] or [pie] (which
+ then triggers opening and reporting of the executable). */
+ int fd = open64 (mod->dwfl->executable_for_core, O_RDONLY);
+ if (fd >= 0)
+ {
+ *file_name = strdup (mod->dwfl->executable_for_core);
+ if (*file_name != NULL)
+ return fd;
+ else
+ close (fd);
+ }
+ }
int fd = __libdwfl_open_by_build_id (mod, false, file_name);
if (fd >= 0)
{
diff --git a/libdwfl/dwfl_end.c b/libdwfl/dwfl_end.c
index 94fcfc6e..33cae48c 100644
--- a/libdwfl/dwfl_end.c
+++ b/libdwfl/dwfl_end.c
@@ -1,5 +1,5 @@
/* Finish a session using libdwfl.
- Copyright (C) 2005, 2008, 2012 Red Hat, Inc.
+ Copyright (C) 2005, 2008, 2012-2013 Red Hat, Inc.
This file is part of elfutils.
This file is free software; you can redistribute it and/or modify
@@ -34,6 +34,9 @@ dwfl_end (Dwfl *dwfl)
if (dwfl == NULL)
return;
+ if (dwfl->process)
+ __libdwfl_process_free (dwfl->process);
+
free (dwfl->lookup_addr);
free (dwfl->lookup_module);
free (dwfl->lookup_segndx);
diff --git a/libdwfl/dwfl_frame.c b/libdwfl/dwfl_frame.c
new file mode 100644
index 00000000..e45cf14c
--- /dev/null
+++ b/libdwfl/dwfl_frame.c
@@ -0,0 +1,442 @@
+/* Get Dwarf Frame state for target PID or core file.
+ 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/>. */
+
+#include "libdwflP.h"
+#include <sys/ptrace.h>
+#include <unistd.h>
+
+/* Set STATE->pc_set from STATE->regs according to the backend. Return true on
+ success, false on error. */
+static bool
+state_fetch_pc (Dwfl_Frame *state)
+{
+ switch (state->pc_state)
+ {
+ case DWFL_FRAME_STATE_PC_SET:
+ return true;
+ case DWFL_FRAME_STATE_PC_UNDEFINED:
+ abort ();
+ case DWFL_FRAME_STATE_ERROR:
+ {
+ Ebl *ebl = state->thread->process->ebl;
+ Dwarf_CIE abi_info;
+ if (ebl_abi_cfi (ebl, &abi_info) != 0)
+ {
+ __libdwfl_seterrno (DWFL_E_LIBEBL);
+ return false;
+ }
+ unsigned ra = abi_info.return_address_register;
+ /* dwarf_frame_state_reg_is_set is not applied here. */
+ if (ra >= ebl_frame_nregs (ebl))
+ {
+ __libdwfl_seterrno (DWFL_E_LIBEBL_BAD);
+ return false;
+ }
+ state->pc = state->regs[ra];
+ state->pc_state = DWFL_FRAME_STATE_PC_SET;
+ }
+ return true;
+ }
+ abort ();
+}
+
+/* Do not call it on your own, to be used by thread_* functions only. */
+
+static void
+state_free (Dwfl_Frame *state)
+{
+ Dwfl_Thread *thread = state->thread;
+ assert (thread->unwound == state);
+ thread->unwound = state->unwound;
+ free (state);
+}
+
+static void
+thread_free_all_states (Dwfl_Thread *thread)
+{
+ while (thread->unwound)
+ state_free (thread->unwound);
+}
+
+static Dwfl_Frame *
+state_alloc (Dwfl_Thread *thread)
+{
+ assert (thread->unwound == NULL);
+ Ebl *ebl = thread->process->ebl;
+ size_t nregs = ebl_frame_nregs (ebl);
+ if (nregs == 0)
+ return NULL;
+ assert (nregs < sizeof (((Dwfl_Frame *) NULL)->regs_set) * 8);
+ Dwfl_Frame *state = malloc (sizeof (*state) + sizeof (*state->regs) * nregs);
+ if (state == NULL)
+ return NULL;
+ state->thread = thread;
+ state->signal_frame = false;
+ state->initial_frame = true;
+ state->pc_state = DWFL_FRAME_STATE_ERROR;
+ memset (state->regs_set, 0, sizeof (state->regs_set));
+ thread->unwound = state;
+ state->unwound = NULL;
+ return state;
+}
+
+void
+internal_function
+__libdwfl_process_free (Dwfl_Process *process)
+{
+ Dwfl *dwfl = process->dwfl;
+ if (process->callbacks->detach != NULL)
+ process->callbacks->detach (dwfl, process->callbacks_arg);
+ assert (dwfl->process == process);
+ dwfl->process = NULL;
+ if (process->ebl_close)
+ ebl_closebackend (process->ebl);
+ free (process);
+}
+
+/* Allocate new Dwfl_Process for DWFL. */
+static void
+process_alloc (Dwfl *dwfl)
+{
+ Dwfl_Process *process = malloc (sizeof (*process));
+ if (process == NULL)
+ return;
+ process->dwfl = dwfl;
+ dwfl->process = process;
+}
+
+bool
+dwfl_attach_state (Dwfl *dwfl, Elf *elf, pid_t pid,
+ const Dwfl_Thread_Callbacks *thread_callbacks, void *arg)
+{
+ if (thread_callbacks == NULL || thread_callbacks->next_thread == NULL
+ || thread_callbacks->set_initial_registers == NULL)
+ {
+ __libdwfl_seterrno (DWFL_E_INVALID_ARGUMENT);
+ return false;
+ }
+ if (dwfl->process != NULL)
+ {
+ __libdwfl_seterrno (DWFL_E_ATTACH_STATE_CONFLICT);
+ return false;
+ }
+ Ebl *ebl;
+ bool ebl_close;
+ if (elf != NULL)
+ {
+ ebl = ebl_openbackend (elf);
+ ebl_close = true;
+ }
+ else
+ {
+ ebl = NULL;
+ for (Dwfl_Module *mod = dwfl->modulelist; mod != NULL; mod = mod->next)
+ {
+ /* Reading of the vDSO module may fail as /proc/PID/mem is unreadable
+ without PTRACE_ATTACH and we may not be PTRACE_ATTACH-ed now.
+ MOD would not be re-read later to unwind it when we are already
+ PTRACE_ATTACH-ed to PID. */
+ if (strncmp (mod->name, "[vdso: ", 7) == 0)
+ continue;
+ Dwfl_Error error = __libdwfl_module_getebl (mod);
+ if (error != DWFL_E_NOERROR)
+ continue;
+ ebl = mod->ebl;
+ break;
+ }
+ ebl_close = false;
+ }
+ if (ebl == NULL)
+ {
+ /* Not identified EBL from any of the modules. */
+ __libdwfl_seterrno (DWFL_E_PROCESS_NO_ARCH);
+ return false;
+ }
+ process_alloc (dwfl);
+ Dwfl_Process *process = dwfl->process;
+ if (process == NULL)
+ {
+ if (ebl_close)
+ ebl_closebackend (ebl);
+ __libdwfl_seterrno (DWFL_E_NOMEM);
+ return false;
+ }
+ process->ebl = ebl;
+ process->ebl_close = ebl_close;
+ process->pid = pid;
+ process->callbacks = thread_callbacks;
+ process->callbacks_arg = arg;
+ return true;
+}
+INTDEF(dwfl_attach_state)
+
+pid_t
+dwfl_pid (Dwfl *dwfl)
+{
+ if (dwfl->process == NULL)
+ {
+ __libdwfl_seterrno (DWFL_E_NO_ATTACH_STATE);
+ return -1;
+ }
+ return dwfl->process->pid;
+}
+INTDEF(dwfl_pid)
+
+Dwfl *
+dwfl_thread_dwfl (Dwfl_Thread *thread)
+{
+ return thread->process->dwfl;
+}
+INTDEF(dwfl_thread_dwfl)
+
+pid_t
+dwfl_thread_tid (Dwfl_Thread *thread)
+{
+ return thread->tid;
+}
+INTDEF(dwfl_thread_tid)
+
+Dwfl_Thread *
+dwfl_frame_thread (Dwfl_Frame *state)
+{
+ return state->thread;
+}
+INTDEF(dwfl_frame_thread)
+
+int
+dwfl_getthreads (Dwfl *dwfl, int (*callback) (Dwfl_Thread *thread, void *arg),
+ void *arg)
+{
+ Dwfl_Process *process = dwfl->process;
+ if (process == NULL)
+ {
+ __libdwfl_seterrno (DWFL_E_NO_ATTACH_STATE);
+ return -1;
+ }
+
+ Dwfl_Thread thread;
+ thread.process = process;
+ thread.unwound = NULL;
+ thread.callbacks_arg = NULL;
+ for (;;)
+ {
+ thread.tid = process->callbacks->next_thread (dwfl,
+ process->callbacks_arg,
+ &thread.callbacks_arg);
+ if (thread.tid < 0)
+ {
+ Dwfl_Error saved_errno = dwfl_errno ();
+ thread_free_all_states (&thread);
+ __libdwfl_seterrno (saved_errno);
+ return -1;
+ }
+ if (thread.tid == 0)
+ {
+ thread_free_all_states (&thread);
+ __libdwfl_seterrno (DWFL_E_NOERROR);
+ return 0;
+ }
+ int err = callback (&thread, arg);
+ if (err != DWARF_CB_OK)
+ {
+ thread_free_all_states (&thread);
+ return err;
+ }
+ assert (thread.unwound == NULL);
+ }
+ /* NOTREACHED */
+}
+INTDEF(dwfl_getthreads)
+
+struct one_arg
+{
+ pid_t tid;
+ bool seen;
+ int (*callback) (Dwfl_Thread *thread, void *arg);
+ void *arg;
+ int ret;
+};
+
+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;
+ oa->ret = oa->callback (thread, oa->arg);
+ return DWARF_CB_ABORT;
+ }
+
+ return DWARF_CB_OK;
+}
+
+/* Note not currently exported, will be when there are more Dwfl_Thread
+ properties to query. Use dwfl_getthread_frames for now directly. */
+static int
+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_E_NO_ATTACH_STATE);
+ 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_ABORT && oa.seen)
+ return oa.ret;
+
+ if (err == DWARF_CB_OK && ! oa.seen)
+ {
+ errno = ESRCH;
+ __libdwfl_seterrno (DWFL_E_ERRNO);
+ return -1;
+ }
+
+ return err;
+}
+
+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 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),
+ void *arg)
+{
+ if (thread->unwound != NULL)
+ {
+ /* We had to be called from inside CALLBACK. */
+ __libdwfl_seterrno (DWFL_E_ATTACH_STATE_CONFLICT);
+ return -1;
+ }
+ Ebl *ebl = thread->process->ebl;
+ if (ebl_frame_nregs (ebl) == 0)
+ {
+ __libdwfl_seterrno (DWFL_E_NO_UNWIND);
+ return -1;
+ }
+ if (state_alloc (thread) == NULL)
+ {
+ __libdwfl_seterrno (DWFL_E_NOMEM);
+ return -1;
+ }
+ Dwfl_Process *process = thread->process;
+ if (! process->callbacks->set_initial_registers (thread,
+ thread->callbacks_arg))
+ {
+ thread_free_all_states (thread);
+ return -1;
+ }
+ if (! state_fetch_pc (thread->unwound))
+ {
+ if (process->callbacks->thread_detach)
+ process->callbacks->thread_detach (thread, thread->callbacks_arg);
+ thread_free_all_states (thread);
+ return -1;
+ }
+
+ Dwfl_Frame *state;
+ do
+ {
+ state = thread->unwound;
+ int err = callback (state, arg);
+ if (err != DWARF_CB_OK)
+ {
+ if (process->callbacks->thread_detach)
+ process->callbacks->thread_detach (thread, thread->callbacks_arg);
+ thread_free_all_states (thread);
+ return err;
+ }
+ __libdwfl_frame_unwind (state);
+ /* The old frame is no longer needed. */
+ state_free (thread->unwound);
+ state = thread->unwound;
+ }
+ while (state && state->pc_state == DWFL_FRAME_STATE_PC_SET);
+
+ Dwfl_Error err = dwfl_errno ();
+ if (process->callbacks->thread_detach)
+ process->callbacks->thread_detach (thread, thread->callbacks_arg);
+ if (state == NULL || state->pc_state == DWFL_FRAME_STATE_ERROR)
+ {
+ thread_free_all_states (thread);
+ __libdwfl_seterrno (err);
+ return -1;
+ }
+ assert (state->pc_state == DWFL_FRAME_STATE_PC_UNDEFINED);
+ thread_free_all_states (thread);
+ return 0;
+}
+INTDEF(dwfl_thread_getframes)
diff --git a/libdwfl/dwfl_frame_pc.c b/libdwfl/dwfl_frame_pc.c
new file mode 100644
index 00000000..296c815b
--- /dev/null
+++ b/libdwfl/dwfl_frame_pc.c
@@ -0,0 +1,64 @@
+/* Get return address register value for frame.
+ 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 "libdwflP.h"
+
+bool
+dwfl_frame_pc (Dwfl_Frame *state, Dwarf_Addr *pc, bool *isactivation)
+{
+ assert (state->pc_state == DWFL_FRAME_STATE_PC_SET);
+ *pc = state->pc;
+ ebl_normalize_pc (state->thread->process->ebl, pc);
+ if (isactivation)
+ {
+ /* Bottom frame? */
+ if (state->initial_frame)
+ *isactivation = true;
+ /* *ISACTIVATION is logical union of whether current or previous frame
+ state is SIGNAL_FRAME. */
+ else if (state->signal_frame)
+ *isactivation = true;
+ else
+ {
+ /* If the previous frame has unwound unsuccessfully just silently do
+ not consider it could be a SIGNAL_FRAME. */
+ __libdwfl_frame_unwind (state);
+ if (state->unwound == NULL
+ || state->unwound->pc_state != DWFL_FRAME_STATE_PC_SET)
+ *isactivation = false;
+ else
+ *isactivation = state->unwound->signal_frame;
+ }
+ }
+ return true;
+}
+INTDEF (dwfl_frame_pc)
diff --git a/libdwfl/dwfl_frame_regs.c b/libdwfl/dwfl_frame_regs.c
new file mode 100644
index 00000000..10803fe7
--- /dev/null
+++ b/libdwfl/dwfl_frame_regs.c
@@ -0,0 +1,57 @@
+/* Get Dwarf Frame state from modules present in DWFL.
+ 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/>. */
+
+#include "libdwflP.h"
+
+bool
+dwfl_thread_state_registers (Dwfl_Thread *thread, int firstreg,
+ unsigned nregs, const Dwarf_Word *regs)
+{
+ Dwfl_Frame *state = thread->unwound;
+ assert (state && state->unwound == NULL);
+ assert (state->initial_frame);
+ for (unsigned regno = firstreg; regno < firstreg + nregs; regno++)
+ if (! __libdwfl_frame_reg_set (state, regno, regs[regno - firstreg]))
+ {
+ __libdwfl_seterrno (DWFL_E_INVALID_REGISTER);
+ return false;
+ }
+ return true;
+}
+INTDEF(dwfl_thread_state_registers)
+
+void
+dwfl_thread_state_register_pc (Dwfl_Thread *thread, Dwarf_Word pc)
+{
+ Dwfl_Frame *state = thread->unwound;
+ assert (state && state->unwound == NULL);
+ assert (state->initial_frame);
+ state->pc = pc;
+ state->pc_state = DWFL_FRAME_STATE_PC_SET;
+}
+INTDEF(dwfl_thread_state_register_pc)
diff --git a/libdwfl/dwfl_module.c b/libdwfl/dwfl_module.c
index f914b3a3..bb167ab2 100644
--- a/libdwfl/dwfl_module.c
+++ b/libdwfl/dwfl_module.c
@@ -84,6 +84,12 @@ __libdwfl_module_free (Dwfl_Module *mod)
if (mod->build_id_bits != NULL)
free (mod->build_id_bits);
+ if (mod->reloc_info != NULL)
+ free (mod->reloc_info);
+
+ if (mod->eh_cfi != NULL)
+ dwarf_cfi_end (mod->eh_cfi);
+
free (mod->name);
free (mod);
}
diff --git a/libdwfl/dwfl_module_addrname.c b/libdwfl/dwfl_module_addrname.c
index 6ae0123a..88a8139d 100644
--- a/libdwfl/dwfl_module_addrname.c
+++ b/libdwfl/dwfl_module_addrname.c
@@ -1,5 +1,5 @@
/* Find debugging and symbol information for a module in libdwfl.
- Copyright (C) 2005, 2006, 2007 Red Hat, Inc.
+ Copyright (C) 2005, 2006, 2007, 2013 Red Hat, Inc.
This file is part of elfutils.
This file is free software; you can redistribute it and/or modify
@@ -31,6 +31,8 @@
const char *
dwfl_module_addrname (Dwfl_Module *mod, GElf_Addr addr)
{
+ GElf_Off off;
GElf_Sym sym;
- return INTUSE(dwfl_module_addrsym) (mod, addr, &sym, NULL);
+ return INTUSE(dwfl_module_addrinfo) (mod, addr, &off, &sym,
+ NULL, NULL, NULL);
}
diff --git a/libdwfl/dwfl_module_addrsym.c b/libdwfl/dwfl_module_addrsym.c
index 732b6983..d205832c 100644
--- a/libdwfl/dwfl_module_addrsym.c
+++ b/libdwfl/dwfl_module_addrsym.c
@@ -1,5 +1,5 @@
/* Find debugging and symbol information for a module in libdwfl.
- Copyright (C) 2005-2012 Red Hat, Inc.
+ Copyright (C) 2005-2013 Red Hat, Inc.
This file is part of elfutils.
This file is free software; you can redistribute it and/or modify
@@ -32,8 +32,10 @@
Never returns symbols at addresses above ADDR. */
const char *
-dwfl_module_addrsym (Dwfl_Module *mod, GElf_Addr addr,
- GElf_Sym *closest_sym, GElf_Word *shndxp)
+internal_function
+__libdwfl_addrsym (Dwfl_Module *mod, GElf_Addr addr, GElf_Off *off,
+ GElf_Sym *closest_sym, GElf_Word *shndxp,
+ Elf **elfp, Dwarf_Addr *biasp, bool adjust_st_value)
{
int syments = INTUSE(dwfl_module_getsymtab) (mod);
if (syments < 0)
@@ -41,20 +43,36 @@ dwfl_module_addrsym (Dwfl_Module *mod, GElf_Addr addr,
/* Return true iff we consider ADDR to lie in the same section as SYM. */
GElf_Word addr_shndx = SHN_UNDEF;
- inline bool same_section (const GElf_Sym *sym, struct dwfl_file *symfile,
- GElf_Word shndx)
+ Elf *addr_symelf = NULL;
+ inline bool same_section (GElf_Addr value, Elf *symelf, GElf_Word shndx)
{
/* For absolute symbols and the like, only match exactly. */
if (shndx >= SHN_LORESERVE)
- return sym->st_value == addr;
+ return value == addr;
+
+ /* If value might not be st_value, the shndx of the symbol might
+ not match the section of the value. Explicitly look both up. */
+ if (! adjust_st_value)
+ {
+ Dwarf_Addr v;
+ if (addr_shndx == SHN_UNDEF)
+ {
+ v = addr;
+ addr_shndx = __libdwfl_find_section_ndx (mod, &v);
+ }
+
+ v = value;
+ return addr_shndx == __libdwfl_find_section_ndx (mod, &v);
+ }
/* Figure out what section ADDR lies in. */
- if (addr_shndx == SHN_UNDEF)
+ if (addr_shndx == SHN_UNDEF || addr_symelf != symelf)
{
- GElf_Addr mod_addr = dwfl_deadjust_st_value (mod, symfile, addr);
+ GElf_Addr mod_addr = dwfl_deadjust_st_value (mod, symelf, addr);
Elf_Scn *scn = NULL;
addr_shndx = SHN_ABS;
- while ((scn = elf_nextscn (symfile->elf, scn)) != NULL)
+ addr_symelf = symelf;
+ while ((scn = elf_nextscn (symelf, scn)) != NULL)
{
GElf_Shdr shdr_mem;
GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
@@ -68,106 +86,139 @@ dwfl_module_addrsym (Dwfl_Module *mod, GElf_Addr addr,
}
}
- return shndx == addr_shndx;
+ return shndx == addr_shndx && addr_symelf == symelf;
}
/* Keep track of the closest symbol we have seen so far.
Here we store only symbols with nonzero st_size. */
const char *closest_name = NULL;
+ GElf_Addr closest_value = 0;
GElf_Word closest_shndx = SHN_UNDEF;
+ Elf *closest_elf = NULL;
/* Keep track of an eligible symbol with st_size == 0 as a fallback. */
const char *sizeless_name = NULL;
GElf_Sym sizeless_sym = { 0, 0, 0, 0, 0, SHN_UNDEF };
+ GElf_Addr sizeless_value = 0;
GElf_Word sizeless_shndx = SHN_UNDEF;
+ Elf *sizeless_elf = NULL;
/* Keep track of the lowest address a relevant sizeless symbol could have. */
GElf_Addr min_label = 0;
+ /* Try one symbol and associated value from the search table. */
+ inline void try_sym_value (GElf_Addr value, GElf_Sym *sym,
+ const char *name, GElf_Word shndx,
+ Elf *elf, bool resolved)
+ {
+ /* Even if we don't choose this symbol, its existence excludes
+ any sizeless symbol (assembly label) that is below its upper
+ bound. */
+ if (value + sym->st_size > min_label)
+ min_label = value + sym->st_size;
+
+ if (sym->st_size == 0 || addr - value < sym->st_size)
+ {
+ /* Return GELF_ST_BIND as higher-is-better integer. */
+ inline int binding_value (const GElf_Sym *symp)
+ {
+ switch (GELF_ST_BIND (symp->st_info))
+ {
+ case STB_GLOBAL:
+ return 3;
+ case STB_WEAK:
+ return 2;
+ case STB_LOCAL:
+ return 1;
+ default:
+ return 0;
+ }
+ }
+
+ /* This symbol is a better candidate than the current one
+ if it's closer to ADDR or is global when it was local. */
+ if (closest_name == NULL
+ || closest_value < value
+ || binding_value (closest_sym) < binding_value (sym))
+ {
+ if (sym->st_size != 0)
+ {
+ *closest_sym = *sym;
+ closest_value = value;
+ closest_shndx = shndx;
+ closest_elf = elf;
+ closest_name = name;
+ }
+ else if (closest_name == NULL
+ && value >= min_label
+ && same_section (value,
+ resolved ? mod->main.elf : elf, shndx))
+ {
+ /* Handwritten assembly symbols sometimes have no
+ st_size. If no symbol with proper size includes
+ the address, we'll use the closest one that is in
+ the same section as ADDR. */
+ sizeless_sym = *sym;
+ sizeless_value = value;
+ sizeless_shndx = shndx;
+ sizeless_elf = elf;
+ sizeless_name = name;
+ }
+ }
+ /* When the beginning of its range is no closer,
+ the end of its range might be. Otherwise follow
+ GELF_ST_BIND preference. If all are equal prefer
+ the first symbol found. */
+ else if (sym->st_size != 0
+ && closest_value == value
+ && ((closest_sym->st_size > sym->st_size
+ && (binding_value (closest_sym)
+ <= binding_value (sym)))
+ || (closest_sym->st_size >= sym->st_size
+ && (binding_value (closest_sym)
+ < binding_value (sym)))))
+ {
+ *closest_sym = *sym;
+ closest_value = value;
+ closest_shndx = shndx;
+ closest_elf = elf;
+ closest_name = name;
+ }
+ }
+ }
+
/* Look through the symbol table for a matching symbol. */
inline void search_table (int start, int end)
{
for (int i = start; i < end; ++i)
{
GElf_Sym sym;
+ GElf_Addr value;
GElf_Word shndx;
- const char *name = INTUSE(dwfl_module_getsym) (mod, i, &sym, &shndx);
+ Elf *elf;
+ bool resolved;
+ const char *name = __libdwfl_getsym (mod, i, &sym, &value,
+ &shndx, &elf, NULL,
+ &resolved, adjust_st_value);
if (name != NULL && name[0] != '\0'
&& sym.st_shndx != SHN_UNDEF
- && sym.st_value <= addr
+ && value <= addr
&& GELF_ST_TYPE (sym.st_info) != STT_SECTION
&& GELF_ST_TYPE (sym.st_info) != STT_FILE
&& GELF_ST_TYPE (sym.st_info) != STT_TLS)
{
- /* Even if we don't choose this symbol, its existence excludes
- any sizeless symbol (assembly label) that is below its upper
- bound. */
- if (sym.st_value + sym.st_size > min_label)
- min_label = sym.st_value + sym.st_size;
+ try_sym_value (value, &sym, name, shndx, elf, resolved);
- if (sym.st_size == 0 || addr - sym.st_value < sym.st_size)
+ /* If this is an addrinfo variant and the value could be
+ resolved then also try matching the (adjusted) st_value. */
+ if (resolved && mod->e_type != ET_REL)
{
- /* Return GELF_ST_BIND as higher-is-better integer. */
- inline int binding_value (const GElf_Sym *symp)
- {
- switch (GELF_ST_BIND (symp->st_info))
- {
- case STB_GLOBAL:
- return 3;
- case STB_WEAK:
- return 2;
- case STB_LOCAL:
- return 1;
- default:
- return 0;
- }
- }
- /* This symbol is a better candidate than the current one
- if it's closer to ADDR or is global when it was local. */
- if (closest_name == NULL
- || closest_sym->st_value < sym.st_value
- || binding_value (closest_sym) < binding_value (&sym))
- {
- if (sym.st_size != 0)
- {
- *closest_sym = sym;
- closest_shndx = shndx;
- closest_name = name;
- }
- else if (closest_name == NULL
- && sym.st_value >= min_label
- && same_section (&sym,
- ((size_t) i < mod->syments
- ? mod->symfile
- : &mod->aux_sym),
- shndx))
- {
- /* Handwritten assembly symbols sometimes have no
- st_size. If no symbol with proper size includes
- the address, we'll use the closest one that is in
- the same section as ADDR. */
- sizeless_sym = sym;
- sizeless_shndx = shndx;
- sizeless_name = name;
- }
- }
- /* When the beginning of its range is no closer,
- the end of its range might be. Otherwise follow
- GELF_ST_BIND preference. If all are equal prefer
- the first symbol found. */
- else if (sym.st_size != 0
- && closest_sym->st_value == sym.st_value
- && ((closest_sym->st_size > sym.st_size
- && (binding_value (closest_sym)
- <= binding_value (&sym)))
- || (closest_sym->st_size >= sym.st_size
- && (binding_value (closest_sym)
- < binding_value (&sym)))))
- {
- *closest_sym = sym;
- closest_shndx = shndx;
- closest_name = name;
- }
+ GElf_Addr adjusted_st_value;
+ adjusted_st_value = dwfl_adjusted_st_value (mod, elf,
+ sym.st_value);
+ if (value != adjusted_st_value && adjusted_st_value <= addr)
+ try_sym_value (adjusted_st_value, &sym, name, shndx,
+ elf, false);
}
}
}
@@ -182,29 +233,57 @@ dwfl_module_addrsym (Dwfl_Module *mod, GElf_Addr addr,
come first in the symbol table, then all globals. The zeroth,
null entry, in the auxiliary table is skipped if there is a main
table. */
- int first_global = mod->first_global + mod->aux_first_global;
- if (mod->syments > 0 && mod->aux_syments > 0)
- first_global--;
+ int first_global = INTUSE (dwfl_module_getsymtab_first_global) (mod);
+ if (first_global < 0)
+ return NULL;
search_table (first_global == 0 ? 1 : first_global, syments);
/* If we found nothing searching the global symbols, then try the locals.
Unless we have a global sizeless symbol that matches exactly. */
if (closest_name == NULL && first_global > 1
- && (sizeless_name == NULL || sizeless_sym.st_value != addr))
+ && (sizeless_name == NULL || sizeless_value != addr))
search_table (1, first_global);
/* If we found no proper sized symbol to use, fall back to the best
candidate sizeless symbol we found, if any. */
if (closest_name == NULL
- && sizeless_name != NULL && sizeless_sym.st_value >= min_label)
+ && sizeless_name != NULL && sizeless_value >= min_label)
{
*closest_sym = sizeless_sym;
+ closest_value = sizeless_value;
closest_shndx = sizeless_shndx;
+ closest_elf = sizeless_elf;
closest_name = sizeless_name;
}
+ *off = addr - closest_value;
+
if (shndxp != NULL)
*shndxp = closest_shndx;
+ if (elfp != NULL)
+ *elfp = closest_elf;
+ if (biasp != NULL)
+ *biasp = dwfl_adjusted_st_value (mod, closest_elf, 0);
return closest_name;
}
+
+
+const char *
+dwfl_module_addrsym (Dwfl_Module *mod, GElf_Addr addr,
+ GElf_Sym *closest_sym, GElf_Word *shndxp)
+{
+ GElf_Off off;
+ return __libdwfl_addrsym (mod, addr, &off, closest_sym, shndxp,
+ NULL, NULL, true);
+}
INTDEF (dwfl_module_addrsym)
+
+const char
+*dwfl_module_addrinfo (Dwfl_Module *mod, GElf_Addr address,
+ GElf_Off *offset, GElf_Sym *sym,
+ GElf_Word *shndxp, Elf **elfp, Dwarf_Addr *bias)
+{
+ return __libdwfl_addrsym (mod, address, offset, sym, shndxp, elfp, bias,
+ false);
+}
+INTDEF (dwfl_module_addrinfo)
diff --git a/libdwfl/dwfl_module_getdwarf.c b/libdwfl/dwfl_module_getdwarf.c
index 7a65ec3b..c4bd7395 100644
--- a/libdwfl/dwfl_module_getdwarf.c
+++ b/libdwfl/dwfl_module_getdwarf.c
@@ -816,6 +816,33 @@ find_dynsym (Dwfl_Module *mod)
}
}
+
+#if USE_LZMA
+/* Try to find the offset between the main file and .gnu_debugdata. */
+static bool
+find_aux_address_sync (Dwfl_Module *mod)
+{
+ /* Don't trust the phdrs in the minisymtab elf file to be setup correctly.
+ The address_sync is equal to the main file it is embedded in at first. */
+ mod->aux_sym.address_sync = mod->main.address_sync;
+
+ /* Adjust address_sync for the difference in entry addresses, attempting to
+ account for ELF relocation changes after aux was split. */
+ GElf_Ehdr ehdr_main, ehdr_aux;
+ if (unlikely (gelf_getehdr (mod->main.elf, &ehdr_main) == NULL)
+ || unlikely (gelf_getehdr (mod->aux_sym.elf, &ehdr_aux) == NULL))
+ return false;
+ mod->aux_sym.address_sync += ehdr_aux.e_entry - ehdr_main.e_entry;
+
+ /* The shdrs are setup OK to make find_prelink_address_sync () do the right
+ thing, which is possibly more reliable, but it needs .gnu.prelink_undo. */
+ if (mod->aux_sym.address_sync != 0)
+ return find_prelink_address_sync (mod, &mod->aux_sym) == DWFL_E_NOERROR;
+
+ return true;
+}
+#endif
+
/* Try to find the auxiliary symbol table embedded in the main elf file
section .gnu_debugdata. Only matters if the symbol information comes
from the main file dynsym. No harm done if not found. */
@@ -879,21 +906,11 @@ find_aux_sym (Dwfl_Module *mod __attribute__ ((unused)),
mod->aux_sym.elf->flags |= ELF_F_MALLOCED;
if (open_elf (mod, &mod->aux_sym) != DWFL_E_NOERROR)
return;
- /* Don't trust the phdrs in the minisymtab elf file to be
- setup correctly. The address_sync is equal to the main
- file it is embedded in at first. The shdrs are setup
- OK to make find_prelink_address_sync () do the right
- thing if necessary though. */
- mod->aux_sym.address_sync = mod->main.address_sync;
- if (mod->aux_sym.address_sync != 0)
+ if (! find_aux_address_sync (mod))
{
- error = find_prelink_address_sync (mod, &mod->aux_sym);
- if (error != DWFL_E_NOERROR)
- {
- elf_end (mod->aux_sym.elf);
- mod->aux_sym.elf = NULL;
- return;
- }
+ elf_end (mod->aux_sym.elf);
+ mod->aux_sym.elf = NULL;
+ return;
}
/* So far, so good. Get minisymtab table data and cache it. */
@@ -1249,3 +1266,26 @@ dwfl_module_getsymtab (Dwfl_Module *mod)
return -1;
}
INTDEF (dwfl_module_getsymtab)
+
+int
+dwfl_module_getsymtab_first_global (Dwfl_Module *mod)
+{
+ if (mod == NULL)
+ return -1;
+
+ find_symtab (mod);
+ if (mod->symerr == DWFL_E_NOERROR)
+ {
+ /* All local symbols should come before all global symbols. If
+ we have an auxiliary table make sure all the main locals come
+ first, then all aux locals, then all main globals and finally all
+ aux globals. And skip the auxiliary table zero undefined
+ entry. */
+ int skip_aux_zero = (mod->syments > 0 && mod->aux_syments > 0) ? 1 : 0;
+ return mod->first_global + mod->aux_first_global - skip_aux_zero;
+ }
+
+ __libdwfl_seterrno (mod->symerr);
+ return -1;
+}
+INTDEF (dwfl_module_getsymtab_first_global)
diff --git a/libdwfl/dwfl_module_getsym.c b/libdwfl/dwfl_module_getsym.c
index 07127b78..917d0620 100644
--- a/libdwfl/dwfl_module_getsym.c
+++ b/libdwfl/dwfl_module_getsym.c
@@ -29,8 +29,10 @@
#include "libdwflP.h"
const char *
-dwfl_module_getsym (Dwfl_Module *mod, int ndx,
- GElf_Sym *sym, GElf_Word *shndxp)
+internal_function
+__libdwfl_getsym (Dwfl_Module *mod, int ndx, GElf_Sym *sym, GElf_Addr *addr,
+ GElf_Word *shndxp, Elf **elfp, Dwarf_Addr *biasp,
+ bool *resolved, bool adjust_st_value)
{
if (unlikely (mod == NULL))
return NULL;
@@ -49,7 +51,7 @@ dwfl_module_getsym (Dwfl_Module *mod, int ndx,
GElf_Word shndx;
int tndx = ndx;
int skip_aux_zero = (mod->syments > 0 && mod->aux_syments > 0) ? 1 : 0;
- struct dwfl_file *file;
+ Elf *elf;
Elf_Data *symdata;
Elf_Data *symxndxdata;
Elf_Data *symstrdata;
@@ -58,7 +60,7 @@ dwfl_module_getsym (Dwfl_Module *mod, int ndx,
{
/* main symbol table (locals). */
tndx = ndx;
- file = mod->symfile;
+ elf = mod->symfile->elf;
symdata = mod->symdata;
symxndxdata = mod->symxndxdata;
symstrdata = mod->symstrdata;
@@ -67,7 +69,7 @@ dwfl_module_getsym (Dwfl_Module *mod, int ndx,
{
/* aux symbol table (locals). */
tndx = ndx - mod->first_global + skip_aux_zero;
- file = &mod->aux_sym;
+ elf = mod->aux_sym.elf;
symdata = mod->aux_symdata;
symxndxdata = mod->aux_symxndxdata;
symstrdata = mod->aux_symstrdata;
@@ -76,7 +78,7 @@ dwfl_module_getsym (Dwfl_Module *mod, int ndx,
{
/* main symbol table (globals). */
tndx = ndx - mod->aux_first_global + skip_aux_zero;
- file = mod->symfile;
+ elf = mod->symfile->elf;
symdata = mod->symdata;
symxndxdata = mod->symxndxdata;
symstrdata = mod->symstrdata;
@@ -85,7 +87,7 @@ dwfl_module_getsym (Dwfl_Module *mod, int ndx,
{
/* aux symbol table (globals). */
tndx = ndx - mod->syments + skip_aux_zero;
- file = &mod->aux_sym;
+ elf = mod->aux_sym.elf;
symdata = mod->aux_symdata;
symxndxdata = mod->aux_symxndxdata;
symstrdata = mod->aux_symstrdata;
@@ -108,11 +110,37 @@ dwfl_module_getsym (Dwfl_Module *mod, int ndx,
|| (sym->st_shndx < SHN_LORESERVE && sym->st_shndx != SHN_UNDEF)))
{
GElf_Shdr shdr_mem;
- GElf_Shdr *shdr = gelf_getshdr (elf_getscn (file->elf, shndx),
- &shdr_mem);
+ GElf_Shdr *shdr = gelf_getshdr (elf_getscn (elf, shndx), &shdr_mem);
alloc = unlikely (shdr == NULL) || (shdr->sh_flags & SHF_ALLOC);
}
+ /* In case of an value in an allocated section the main Elf Ebl
+ might know where the real value is (e.g. for function
+ descriptors). */
+
+ char *ident;
+ GElf_Addr st_value = sym->st_value;
+ *resolved = false;
+ if (! adjust_st_value && mod->e_type != ET_REL && alloc
+ && (GELF_ST_TYPE (sym->st_info) == STT_FUNC
+ || (GELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC
+ && (ident = elf_getident (elf, NULL)) != NULL
+ && ident[EI_OSABI] == ELFOSABI_LINUX)))
+ {
+ if (likely (__libdwfl_module_getebl (mod) == DWFL_E_NOERROR))
+ {
+ if (elf != mod->main.elf)
+ {
+ st_value = dwfl_adjusted_st_value (mod, elf, st_value);
+ st_value = dwfl_deadjust_st_value (mod, mod->main.elf, st_value);
+ }
+
+ *resolved = ebl_resolve_sym_value (mod->ebl, &st_value);
+ if (! *resolved)
+ st_value = sym->st_value;
+ }
+ }
+
if (shndxp != NULL)
/* Yield -1 in case of a non-SHF_ALLOC section. */
*shndxp = alloc ? shndx : (GElf_Word) -1;
@@ -130,9 +158,9 @@ dwfl_module_getsym (Dwfl_Module *mod, int ndx,
/* In an ET_REL file, the symbol table values are relative
to the section, not to the module's load base. */
size_t symshstrndx = SHN_UNDEF;
- Dwfl_Error result = __libdwfl_relocate_value (mod, file->elf,
+ Dwfl_Error result = __libdwfl_relocate_value (mod, elf,
&symshstrndx,
- shndx, &sym->st_value);
+ shndx, &st_value);
if (unlikely (result != DWFL_E_NOERROR))
{
__libdwfl_seterrno (result);
@@ -141,15 +169,48 @@ dwfl_module_getsym (Dwfl_Module *mod, int ndx,
}
else if (alloc)
/* Apply the bias to the symbol value. */
- sym->st_value = dwfl_adjusted_st_value (mod, file, sym->st_value);
+ st_value = dwfl_adjusted_st_value (mod,
+ *resolved ? mod->main.elf : elf,
+ st_value);
break;
}
+ if (adjust_st_value)
+ sym->st_value = st_value;
+
+ if (addr != NULL)
+ *addr = st_value;
+
if (unlikely (sym->st_name >= symstrdata->d_size))
{
__libdwfl_seterrno (DWFL_E_BADSTROFF);
return NULL;
}
+ if (elfp)
+ *elfp = elf;
+ if (biasp)
+ *biasp = dwfl_adjusted_st_value (mod, elf, 0);
return (const char *) symstrdata->d_buf + sym->st_name;
}
+
+const char *
+dwfl_module_getsym_info (Dwfl_Module *mod, int ndx,
+ GElf_Sym *sym, GElf_Addr *addr,
+ GElf_Word *shndxp,
+ Elf **elfp, Dwarf_Addr *bias)
+{
+ bool resolved;
+ return __libdwfl_getsym (mod, ndx, sym, addr, shndxp, elfp, bias,
+ &resolved, false);
+}
+INTDEF (dwfl_module_getsym_info)
+
+const char *
+dwfl_module_getsym (Dwfl_Module *mod, int ndx,
+ GElf_Sym *sym, GElf_Word *shndxp)
+{
+ bool resolved;
+ return __libdwfl_getsym (mod, ndx, sym, NULL, shndxp, NULL, NULL,
+ &resolved, true);
+}
INTDEF (dwfl_module_getsym)
diff --git a/libdwfl/dwfl_module_info.c b/libdwfl/dwfl_module_info.c
index fdb4202a..df16be41 100644
--- a/libdwfl/dwfl_module_info.c
+++ b/libdwfl/dwfl_module_info.c
@@ -49,7 +49,7 @@ dwfl_module_info (Dwfl_Module *mod, void ***userdata,
: dwfl_adjusted_dwarf_addr (mod, 0));
if (symbias)
*symbias = (mod->symfile == NULL ? (Dwarf_Addr) -1
- : dwfl_adjusted_st_value (mod, mod->symfile, 0));
+ : dwfl_adjusted_st_value (mod, mod->symfile->elf, 0));
if (mainfile)
*mainfile = mod->main.name;
diff --git a/libdwfl/dwfl_segment_report_module.c b/libdwfl/dwfl_segment_report_module.c
index 97f4a1af..fd967e9a 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;
@@ -478,20 +481,40 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
if ((module_end > module->start && module_start < module->end)
|| dyn_vaddr == module->l_ld)
{
+ bool close_elf = false;
if (! module->disk_file_has_build_id && build_id_len > 0)
{
/* Module found in segments with build-id is more reliable
than a module found via DT_DEBUG on disk without any
build-id. */
if (module->elf != NULL)
+ close_elf = true;
+ }
+ if (module->elf != NULL
+ && module->disk_file_has_build_id && build_id_len > 0)
+ {
+ const void *elf_build_id;
+ GElf_Addr elf_build_id_elfaddr;
+ int elf_build_id_len;
+
+ if (__libdwfl_find_elf_build_id (NULL, module->elf,
+ &elf_build_id,
+ &elf_build_id_elfaddr,
+ &elf_build_id_len) > 0)
{
- elf_end (module->elf);
- close (module->fd);
- module->elf = NULL;
- module->fd = -1;
+ if (build_id_len != (size_t) elf_build_id_len
+ || memcmp (build_id, elf_build_id, build_id_len) != 0)
+ close_elf = true;
}
}
- else if (module->elf != NULL)
+ if (close_elf)
+ {
+ elf_end (module->elf);
+ close (module->fd);
+ module->elf = NULL;
+ module->fd = -1;
+ }
+ if (module->elf != NULL)
{
/* Ignore this found module if it would conflict in address
space with any already existing module of DWFL. */
@@ -499,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
diff --git a/libdwfl/frame_unwind.c b/libdwfl/frame_unwind.c
new file mode 100644
index 00000000..3ce45479
--- /dev/null
+++ b/libdwfl/frame_unwind.c
@@ -0,0 +1,720 @@
+/* Get previous frame state for an existing frame state.
+ 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 "cfi.h"
+#include <stdlib.h>
+#include "libdwflP.h"
+#include "../libdw/dwarf.h"
+#include <sys/ptrace.h>
+
+/* Maximum number of DWARF expression stack slots before returning an error. */
+#define DWARF_EXPR_STACK_MAX 0x100
+
+/* Maximum number of DWARF expression executed operations before returning an
+ error. */
+#define DWARF_EXPR_STEPS_MAX 0x1000
+
+#ifndef MAX
+# define MAX(a, b) ((a) > (b) ? (a) : (b))
+#endif
+
+bool
+internal_function
+__libdwfl_frame_reg_get (Dwfl_Frame *state, unsigned regno, Dwarf_Addr *val)
+{
+ Ebl *ebl = state->thread->process->ebl;
+ if (! ebl_dwarf_to_regno (ebl, &regno))
+ return false;
+ if (regno >= ebl_frame_nregs (ebl))
+ return false;
+ if ((state->regs_set[regno / sizeof (*state->regs_set) / 8]
+ & (1U << (regno % (sizeof (*state->regs_set) * 8)))) == 0)
+ return false;
+ if (val)
+ *val = state->regs[regno];
+ return true;
+}
+
+bool
+internal_function
+__libdwfl_frame_reg_set (Dwfl_Frame *state, unsigned regno, Dwarf_Addr val)
+{
+ Ebl *ebl = state->thread->process->ebl;
+ if (! ebl_dwarf_to_regno (ebl, &regno))
+ return false;
+ if (regno >= ebl_frame_nregs (ebl))
+ return false;
+ /* For example i386 user_regs_struct has signed fields. */
+ if (ebl_get_elfclass (ebl) == ELFCLASS32)
+ val &= 0xffffffff;
+ state->regs_set[regno / sizeof (*state->regs_set) / 8] |=
+ (1U << (regno % (sizeof (*state->regs_set) * 8)));
+ state->regs[regno] = val;
+ return true;
+}
+
+static bool
+state_get_reg (Dwfl_Frame *state, unsigned regno, Dwarf_Addr *val)
+{
+ if (! __libdwfl_frame_reg_get (state, regno, val))
+ {
+ __libdwfl_seterrno (DWFL_E_INVALID_REGISTER);
+ return false;
+ }
+ return true;
+}
+
+static int
+bra_compar (const void *key_voidp, const void *elem_voidp)
+{
+ Dwarf_Word offset = (uintptr_t) key_voidp;
+ const Dwarf_Op *op = elem_voidp;
+ return (offset > op->offset) - (offset < op->offset);
+}
+
+/* If FRAME is NULL is are computing CFI frame base. In such case another
+ DW_OP_call_frame_cfa is no longer permitted. */
+
+static bool
+expr_eval (Dwfl_Frame *state, Dwarf_Frame *frame, const Dwarf_Op *ops,
+ size_t nops, Dwarf_Addr *result, Dwarf_Addr bias)
+{
+ Dwfl_Process *process = state->thread->process;
+ if (nops == 0)
+ {
+ __libdwfl_seterrno (DWFL_E_INVALID_DWARF);
+ return false;
+ }
+ Dwarf_Addr *stack = NULL;
+ size_t stack_used = 0, stack_allocated = 0;
+
+ bool
+ push (Dwarf_Addr val)
+ {
+ if (stack_used >= DWARF_EXPR_STACK_MAX)
+ {
+ __libdwfl_seterrno (DWFL_E_INVALID_DWARF);
+ return false;
+ }
+ if (stack_used == stack_allocated)
+ {
+ stack_allocated = MAX (stack_allocated * 2, 32);
+ Dwarf_Addr *stack_new = realloc (stack, stack_allocated * sizeof (*stack));
+ if (stack_new == NULL)
+ {
+ __libdwfl_seterrno (DWFL_E_NOMEM);
+ return false;
+ }
+ stack = stack_new;
+ }
+ stack[stack_used++] = val;
+ return true;
+ }
+
+ bool
+ pop (Dwarf_Addr *val)
+ {
+ if (stack_used == 0)
+ {
+ __libdwfl_seterrno (DWFL_E_INVALID_DWARF);
+ return false;
+ }
+ *val = stack[--stack_used];
+ return true;
+ }
+
+ Dwarf_Addr val1, val2;
+ bool is_location = false;
+ size_t steps_count = 0;
+ for (const Dwarf_Op *op = ops; op < ops + nops; op++)
+ {
+ if (++steps_count > DWARF_EXPR_STEPS_MAX)
+ {
+ __libdwfl_seterrno (DWFL_E_INVALID_DWARF);
+ return false;
+ }
+ switch (op->atom)
+ {
+ /* DW_OP_* order matches libgcc/unwind-dw2.c execute_stack_op: */
+ case DW_OP_lit0 ... DW_OP_lit31:
+ if (! push (op->atom - DW_OP_lit0))
+ {
+ free (stack);
+ return false;
+ }
+ break;
+ case DW_OP_addr:
+ if (! push (op->number + bias))
+ {
+ free (stack);
+ return false;
+ }
+ break;
+ case DW_OP_GNU_encoded_addr:
+ /* Missing support in the rest of elfutils. */
+ __libdwfl_seterrno (DWFL_E_UNSUPPORTED_DWARF);
+ return false;
+ case DW_OP_const1u:
+ case DW_OP_const1s:
+ case DW_OP_const2u:
+ case DW_OP_const2s:
+ case DW_OP_const4u:
+ case DW_OP_const4s:
+ case DW_OP_const8u:
+ case DW_OP_const8s:
+ case DW_OP_constu:
+ case DW_OP_consts:
+ if (! push (op->number))
+ {
+ free (stack);
+ return false;
+ }
+ break;
+ case DW_OP_reg0 ... DW_OP_reg31:
+ if (! state_get_reg (state, op->atom - DW_OP_reg0, &val1)
+ || ! push (val1))
+ {
+ free (stack);
+ return false;
+ }
+ break;
+ case DW_OP_regx:
+ if (! state_get_reg (state, op->number, &val1) || ! push (val1))
+ {
+ free (stack);
+ return false;
+ }
+ break;
+ case DW_OP_breg0 ... DW_OP_breg31:
+ if (! state_get_reg (state, op->atom - DW_OP_breg0, &val1))
+ {
+ free (stack);
+ return false;
+ }
+ val1 += op->number;
+ if (! push (val1))
+ {
+ free (stack);
+ return false;
+ }
+ break;
+ case DW_OP_bregx:
+ if (! state_get_reg (state, op->number, &val1))
+ {
+ free (stack);
+ return false;
+ }
+ val1 += op->number2;
+ if (! push (val1))
+ {
+ free (stack);
+ return false;
+ }
+ break;
+ case DW_OP_dup:
+ if (! pop (&val1) || ! push (val1) || ! push (val1))
+ {
+ free (stack);
+ return false;
+ }
+ break;
+ case DW_OP_drop:
+ if (! pop (&val1))
+ {
+ free (stack);
+ return false;
+ }
+ break;
+ case DW_OP_pick:
+ if (stack_used <= op->number)
+ {
+ free (stack);
+ __libdwfl_seterrno (DWFL_E_INVALID_DWARF);
+ return false;
+ }
+ if (! push (stack[stack_used - 1 - op->number]))
+ {
+ free (stack);
+ return false;
+ }
+ break;
+ case DW_OP_over:
+ if (! pop (&val1) || ! pop (&val2)
+ || ! push (val2) || ! push (val1) || ! push (val2))
+ {
+ free (stack);
+ return false;
+ }
+ break;
+ case DW_OP_swap:
+ if (! pop (&val1) || ! pop (&val2) || ! push (val1) || ! push (val2))
+ {
+ free (stack);
+ return false;
+ }
+ break;
+ case DW_OP_rot:
+ {
+ Dwarf_Addr val3;
+ if (! pop (&val1) || ! pop (&val2) || ! pop (&val3)
+ || ! push (val1) || ! push (val3) || ! push (val2))
+ {
+ free (stack);
+ return false;
+ }
+ }
+ break;
+ case DW_OP_deref:
+ case DW_OP_deref_size:
+ if (process->callbacks->memory_read == NULL)
+ {
+ free (stack);
+ __libdwfl_seterrno (DWFL_E_INVALID_ARGUMENT);
+ return false;
+ }
+ if (! pop (&val1)
+ || ! process->callbacks->memory_read (process->dwfl, val1, &val1,
+ process->callbacks_arg))
+ {
+ free (stack);
+ return false;
+ }
+ if (op->atom == DW_OP_deref_size)
+ {
+ const int elfclass = frame->cache->e_ident[EI_CLASS];
+ const unsigned addr_bytes = elfclass == ELFCLASS32 ? 4 : 8;
+ if (op->number > addr_bytes)
+ {
+ free (stack);
+ __libdwfl_seterrno (DWFL_E_INVALID_DWARF);
+ return false;
+ }
+#if BYTE_ORDER == BIG_ENDIAN
+ if (op->number == 0)
+ val1 = 0;
+ else
+ val1 >>= (addr_bytes - op->number) * 8;
+#else
+ if (op->number < 8)
+ val1 &= (1 << (op->number * 8)) - 1;
+#endif
+ }
+ if (! push (val1))
+ {
+ free (stack);
+ return false;
+ }
+ break;
+#define UNOP(atom, expr) \
+ case atom: \
+ if (! pop (&val1) || ! push (expr)) \
+ { \
+ free (stack); \
+ return false; \
+ } \
+ break;
+ UNOP (DW_OP_abs, abs ((int64_t) val1))
+ UNOP (DW_OP_neg, -(int64_t) val1)
+ UNOP (DW_OP_not, ~val1)
+#undef UNOP
+ case DW_OP_plus_uconst:
+ if (! pop (&val1) || ! push (val1 + op->number))
+ {
+ free (stack);
+ return false;
+ }
+ break;
+#define BINOP(atom, op) \
+ case atom: \
+ if (! pop (&val2) || ! pop (&val1) || ! push (val1 op val2)) \
+ { \
+ free (stack); \
+ return false; \
+ } \
+ break;
+#define BINOP_SIGNED(atom, op) \
+ case atom: \
+ if (! pop (&val2) || ! pop (&val1) \
+ || ! push ((int64_t) val1 op (int64_t) val2)) \
+ { \
+ free (stack); \
+ return false; \
+ } \
+ break;
+ BINOP (DW_OP_and, &)
+ case DW_OP_div:
+ if (! pop (&val2) || ! pop (&val1))
+ {
+ free (stack);
+ return false;
+ }
+ if (val2 == 0)
+ {
+ free (stack);
+ __libdwfl_seterrno (DWFL_E_INVALID_DWARF);
+ return false;
+ }
+ if (! push ((int64_t) val1 / (int64_t) val2))
+ {
+ free (stack);
+ return false;
+ }
+ break;
+ BINOP (DW_OP_minus, -)
+ case DW_OP_mod:
+ if (! pop (&val2) || ! pop (&val1))
+ {
+ free (stack);
+ return false;
+ }
+ if (val2 == 0)
+ {
+ free (stack);
+ __libdwfl_seterrno (DWFL_E_INVALID_DWARF);
+ return false;
+ }
+ if (! push (val1 % val2))
+ {
+ free (stack);
+ return false;
+ }
+ break;
+ BINOP (DW_OP_mul, *)
+ BINOP (DW_OP_or, |)
+ BINOP (DW_OP_plus, +)
+ BINOP (DW_OP_shl, <<)
+ BINOP (DW_OP_shr, >>)
+ BINOP_SIGNED (DW_OP_shra, >>)
+ BINOP (DW_OP_xor, ^)
+ BINOP_SIGNED (DW_OP_le, <=)
+ BINOP_SIGNED (DW_OP_ge, >=)
+ BINOP_SIGNED (DW_OP_eq, ==)
+ BINOP_SIGNED (DW_OP_lt, <)
+ BINOP_SIGNED (DW_OP_gt, >)
+ BINOP_SIGNED (DW_OP_ne, !=)
+#undef BINOP
+#undef BINOP_SIGNED
+ case DW_OP_bra:
+ if (! pop (&val1))
+ {
+ free (stack);
+ return false;
+ }
+ if (val1 == 0)
+ break;
+ /* FALLTHRU */
+ case DW_OP_skip:;
+ Dwarf_Word offset = op->offset + 1 + 2 + (int16_t) op->number;
+ const Dwarf_Op *found = bsearch ((void *) (uintptr_t) offset, ops, nops,
+ sizeof (*ops), bra_compar);
+ if (found == NULL)
+ {
+ free (stack);
+ /* PPC32 vDSO has such invalid operations. */
+ __libdwfl_seterrno (DWFL_E_INVALID_DWARF);
+ return false;
+ }
+ /* Undo the 'for' statement increment. */
+ op = found - 1;
+ break;
+ case DW_OP_nop:
+ break;
+ /* DW_OP_* not listed in libgcc/unwind-dw2.c execute_stack_op: */
+ case DW_OP_call_frame_cfa:;
+ // Not used by CFI itself but it is synthetized by elfutils internation.
+ Dwarf_Op *cfa_ops;
+ size_t cfa_nops;
+ Dwarf_Addr cfa;
+ if (frame == NULL
+ || dwarf_frame_cfa (frame, &cfa_ops, &cfa_nops) != 0
+ || ! expr_eval (state, NULL, cfa_ops, cfa_nops, &cfa, bias)
+ || ! push (cfa))
+ {
+ __libdwfl_seterrno (DWFL_E_LIBDW);
+ free (stack);
+ return false;
+ }
+ is_location = true;
+ break;
+ case DW_OP_stack_value:
+ // Not used by CFI itself but it is synthetized by elfutils internation.
+ is_location = false;
+ break;
+ default:
+ __libdwfl_seterrno (DWFL_E_INVALID_DWARF);
+ return false;
+ }
+ }
+ if (! pop (result))
+ {
+ free (stack);
+ return false;
+ }
+ free (stack);
+ if (is_location)
+ {
+ if (process->callbacks->memory_read == NULL)
+ {
+ __libdwfl_seterrno (DWFL_E_INVALID_ARGUMENT);
+ return false;
+ }
+ if (! process->callbacks->memory_read (process->dwfl, *result, result,
+ process->callbacks_arg))
+ return false;
+ }
+ return true;
+}
+
+static void
+new_unwound (Dwfl_Frame *state)
+{
+ assert (state->unwound == NULL);
+ Dwfl_Thread *thread = state->thread;
+ Dwfl_Process *process = thread->process;
+ Ebl *ebl = process->ebl;
+ size_t nregs = ebl_frame_nregs (ebl);
+ assert (nregs > 0);
+ Dwfl_Frame *unwound;
+ unwound = malloc (sizeof (*unwound) + sizeof (*unwound->regs) * nregs);
+ state->unwound = unwound;
+ unwound->thread = thread;
+ unwound->unwound = NULL;
+ unwound->signal_frame = false;
+ unwound->initial_frame = false;
+ unwound->pc_state = DWFL_FRAME_STATE_ERROR;
+ memset (unwound->regs_set, 0, sizeof (unwound->regs_set));
+}
+
+/* The logic is to call __libdwfl_seterrno for any CFI bytecode interpretation
+ error so one can easily catch the problem with a debugger. Still there are
+ archs with invalid CFI for some registers where the registers are never used
+ later. Therefore we continue unwinding leaving the registers undefined. */
+
+static void
+handle_cfi (Dwfl_Frame *state, Dwarf_Addr pc, Dwarf_CFI *cfi, Dwarf_Addr bias)
+{
+ Dwarf_Frame *frame;
+ if (INTUSE(dwarf_cfi_addrframe) (cfi, pc, &frame) != 0)
+ {
+ __libdwfl_seterrno (DWFL_E_LIBDW);
+ return;
+ }
+ new_unwound (state);
+ Dwfl_Frame *unwound = state->unwound;
+ unwound->signal_frame = frame->fde->cie->signal_frame;
+ Dwfl_Thread *thread = state->thread;
+ Dwfl_Process *process = thread->process;
+ Ebl *ebl = process->ebl;
+ size_t nregs = ebl_frame_nregs (ebl);
+ assert (nregs > 0);
+
+ /* The return register is special for setting the unwound->pc_state. */
+ unsigned ra = frame->fde->cie->return_address_register;
+ bool ra_set = false;
+ ebl_dwarf_to_regno (ebl, &ra);
+
+ for (unsigned regno = 0; regno < nregs; regno++)
+ {
+ Dwarf_Op reg_ops_mem[3], *reg_ops;
+ size_t reg_nops;
+ if (dwarf_frame_register (frame, regno, reg_ops_mem, &reg_ops,
+ &reg_nops) != 0)
+ {
+ __libdwfl_seterrno (DWFL_E_LIBDW);
+ continue;
+ }
+ Dwarf_Addr regval;
+ if (reg_nops == 0)
+ {
+ if (reg_ops == reg_ops_mem)
+ {
+ /* REGNO is undefined. */
+ if (regno == ra)
+ unwound->pc_state = DWFL_FRAME_STATE_PC_UNDEFINED;
+ continue;
+ }
+ else if (reg_ops == NULL)
+ {
+ /* REGNO is same-value. */
+ if (! state_get_reg (state, regno, &regval))
+ continue;
+ }
+ else
+ {
+ __libdwfl_seterrno (DWFL_E_INVALID_DWARF);
+ continue;
+ }
+ }
+ else if (! expr_eval (state, frame, reg_ops, reg_nops, &regval, bias))
+ {
+ /* PPC32 vDSO has various invalid operations, ignore them. The
+ register will look as unset causing an error later, if used.
+ But PPC32 does not use such registers. */
+ continue;
+ }
+
+ /* This is another strange PPC[64] case. There are two
+ registers numbers that can represent the same DWARF return
+ register number. We only want one to actually set the return
+ register value. */
+ if (ra_set)
+ {
+ unsigned r = regno;
+ if (ebl_dwarf_to_regno (ebl, &r) && r == ra)
+ continue;
+ }
+
+ if (! __libdwfl_frame_reg_set (unwound, regno, regval))
+ {
+ __libdwfl_seterrno (DWFL_E_INVALID_REGISTER);
+ continue;
+ }
+ else if (! ra_set)
+ {
+ unsigned r = regno;
+ if (ebl_dwarf_to_regno (ebl, &r) && r == ra)
+ ra_set = true;
+ }
+ }
+ if (unwound->pc_state == DWFL_FRAME_STATE_ERROR
+ && __libdwfl_frame_reg_get (unwound,
+ frame->fde->cie->return_address_register,
+ &unwound->pc))
+ {
+ /* PPC32 __libc_start_main properly CFI-unwinds PC as zero. Currently
+ none of the archs supported for unwinding have zero as a valid PC. */
+ if (unwound->pc == 0)
+ unwound->pc_state = DWFL_FRAME_STATE_PC_UNDEFINED;
+ else
+ unwound->pc_state = DWFL_FRAME_STATE_PC_SET;
+ }
+ free (frame);
+}
+
+static bool
+setfunc (int firstreg, unsigned nregs, const Dwarf_Word *regs, void *arg)
+{
+ Dwfl_Frame *state = arg;
+ Dwfl_Frame *unwound = state->unwound;
+ if (firstreg < 0)
+ {
+ assert (firstreg == -1);
+ assert (nregs == 1);
+ assert (unwound->pc_state == DWFL_FRAME_STATE_PC_UNDEFINED);
+ unwound->pc = *regs;
+ unwound->pc_state = DWFL_FRAME_STATE_PC_SET;
+ return true;
+ }
+ while (nregs--)
+ if (! __libdwfl_frame_reg_set (unwound, firstreg++, *regs++))
+ return false;
+ return true;
+}
+
+static bool
+getfunc (int firstreg, unsigned nregs, Dwarf_Word *regs, void *arg)
+{
+ Dwfl_Frame *state = arg;
+ assert (firstreg >= 0);
+ while (nregs--)
+ if (! __libdwfl_frame_reg_get (state, firstreg++, regs++))
+ return false;
+ return true;
+}
+
+static bool
+readfunc (Dwarf_Addr addr, Dwarf_Word *datap, void *arg)
+{
+ Dwfl_Frame *state = arg;
+ Dwfl_Thread *thread = state->thread;
+ Dwfl_Process *process = thread->process;
+ return process->callbacks->memory_read (process->dwfl, addr, datap,
+ process->callbacks_arg);
+}
+
+void
+internal_function
+__libdwfl_frame_unwind (Dwfl_Frame *state)
+{
+ if (state->unwound)
+ return;
+ /* Do not ask dwfl_frame_pc for ISACTIVATION, it would try to unwind STATE
+ which would deadlock us. */
+ Dwarf_Addr pc;
+ bool ok = INTUSE(dwfl_frame_pc) (state, &pc, NULL);
+ assert (ok);
+ /* Check whether this is the initial frame or a signal frame.
+ Then we need to unwind from the original, unadjusted PC. */
+ if (! state->initial_frame && ! state->signal_frame)
+ pc--;
+ Dwfl_Module *mod = INTUSE(dwfl_addrmodule) (state->thread->process->dwfl, pc);
+ if (mod == NULL)
+ __libdwfl_seterrno (DWFL_E_NO_DWARF);
+ else
+ {
+ Dwarf_Addr bias;
+ Dwarf_CFI *cfi_eh = INTUSE(dwfl_module_eh_cfi) (mod, &bias);
+ if (cfi_eh)
+ {
+ handle_cfi (state, pc - bias, cfi_eh, bias);
+ if (state->unwound)
+ return;
+ }
+ Dwarf_CFI *cfi_dwarf = INTUSE(dwfl_module_dwarf_cfi) (mod, &bias);
+ if (cfi_dwarf)
+ {
+ handle_cfi (state, pc - bias, cfi_dwarf, bias);
+ if (state->unwound)
+ return;
+ }
+ }
+ assert (state->unwound == NULL);
+ Dwfl_Thread *thread = state->thread;
+ Dwfl_Process *process = thread->process;
+ Ebl *ebl = process->ebl;
+ new_unwound (state);
+ state->unwound->pc_state = DWFL_FRAME_STATE_PC_UNDEFINED;
+ // &Dwfl_Frame.signal_frame cannot be passed as it is a bitfield.
+ bool signal_frame = false;
+ if (! ebl_unwind (ebl, pc, setfunc, getfunc, readfunc, state, &signal_frame))
+ {
+ // Discard the unwind attempt. During next __libdwfl_frame_unwind call
+ // we may have for example the appropriate Dwfl_Module already mapped.
+ assert (state->unwound->unwound == NULL);
+ free (state->unwound);
+ state->unwound = NULL;
+ // __libdwfl_seterrno has been called above.
+ return;
+ }
+ assert (state->unwound->pc_state == DWFL_FRAME_STATE_PC_SET);
+ state->unwound->signal_frame = signal_frame;
+}
diff --git a/libdwfl/libdwfl.h b/libdwfl/libdwfl.h
index 2b70e284..2bb4f455 100644
--- a/libdwfl/libdwfl.h
+++ b/libdwfl/libdwfl.h
@@ -1,5 +1,5 @@
/* Interfaces for libdwfl.
- Copyright (C) 2005-2010 Red Hat, Inc.
+ Copyright (C) 2005-2010, 2013 Red Hat, Inc.
This file is part of elfutils.
This file is free software; you can redistribute it and/or modify
@@ -41,6 +41,14 @@ typedef struct Dwfl_Module Dwfl_Module;
/* Handle describing a line record. */
typedef struct Dwfl_Line Dwfl_Line;
+/* This holds information common for all the frames of one backtrace for
+ a partical thread/task/TID. Several threads belong to one Dwfl. */
+typedef struct Dwfl_Thread Dwfl_Thread;
+
+/* This holds everything we know about the state of the frame at a particular
+ PC location described by an FDE belonging to Dwfl_Thread. */
+typedef struct Dwfl_Frame Dwfl_Frame;
+
/* Callbacks. */
typedef struct
{
@@ -349,15 +357,17 @@ extern int dwfl_linux_kernel_report_offline (Dwfl *dwfl, const char *release,
This can follow a dwfl_report_offline call to bootstrap the
DT_DEBUG method of following the dynamic linker link_map chain, in
case the core file does not contain enough of the executable's text
- segment to locate its PT_DYNAMIC in the dump. This might call
- dwfl_report_elf on file names found in the dump if reading some
- link_map files is the only way to ascertain those modules' addresses.
- Returns the number of modules reported, or -1 for errors. */
-extern int dwfl_core_file_report (Dwfl *dwfl, Elf *elf);
+ segment to locate its PT_DYNAMIC in the dump. In such case you need to
+ supply non-NULL EXECUTABLE, otherwise dynamic libraries will not be loaded
+ into the DWFL map. This might call dwfl_report_elf on file names found in
+ the dump if reading some link_map files is the only way to ascertain those
+ modules' addresses. Returns the number of modules reported, or -1 for
+ errors. */
+extern int dwfl_core_file_report (Dwfl *dwfl, Elf *elf, const char *executable);
/* Call dwfl_report_module for each file mapped into the address space of PID.
Returns zero on success, -1 if dwfl_report_module failed,
- or an errno code if opening the kernel binary failed. */
+ or an errno code if opening the proc files failed. */
extern int dwfl_linux_proc_report (Dwfl *dwfl, pid_t pid);
/* Similar, but reads an input stream in the format of Linux /proc/PID/maps
@@ -417,22 +427,92 @@ extern Elf *dwfl_module_getelf (Dwfl_Module *, GElf_Addr *bias)
or -1 for errors. */
extern int dwfl_module_getsymtab (Dwfl_Module *mod);
+/* Return the index of the first global symbol in the module's symbol
+ table, or -1 for errors. In each symbol table, all symbols with
+ STB_LOCAL binding precede the weak and global symbols. This
+ function returns the symbol table index one greater than the last
+ local symbol. */
+extern int dwfl_module_getsymtab_first_global (Dwfl_Module *mod);
+
/* Fetch one entry from the module's symbol table. On errors, returns
NULL. If successful, fills in *SYM and returns the string for st_name.
This works like gelf_getsym except that st_value is always adjusted to
an absolute value based on the module's location, when the symbol is in
an SHF_ALLOC section. If SHNDXP is non-null, it's set with the section
index (whether from st_shndx or extended index table); in case of a
- symbol in a non-allocated section, *SHNDXP is instead set to -1. */
+ symbol in a non-allocated section, *SHNDXP is instead set to -1.
+ Note that since symbols can come from either the main, debug or auxiliary
+ ELF symbol file (either dynsym or symtab) the section index can only
+ be reliably used to compare against special section constants like
+ SHN_UNDEF or SHN_ABS. It is recommended to use dwfl_module_getsym_info
+ which doesn't have these deficiencies. */
extern const char *dwfl_module_getsym (Dwfl_Module *mod, int ndx,
GElf_Sym *sym, GElf_Word *shndxp)
__nonnull_attribute__ (3);
+/* Fetch one entry from the module's symbol table and the associated
+ address value. On errors, returns NULL. If successful, fills in
+ *SYM, *ADDR and returns the string for st_name. This works like
+ gelf_getsym. *ADDR is set to the st_value adjusted to an absolute
+ value based on the module's location, when the symbol is in an
+ SHF_ALLOC section. For non-ET_REL files, if the arch uses function
+ descriptors, and the st_value points to one, *ADDR will be resolved
+ to the actual function entry address. The SYM->ST_VALUE itself
+ isn't adjusted in any way. Fills in ELFP, if not NULL, with the
+ ELF file the symbol originally came from. Note that symbols can
+ come from either the main, debug or auxiliary ELF symbol file
+ (either dynsym or symtab). If SHNDXP is non-null, it's set with
+ the section index (whether from st_shndx or extended index table);
+ in case of a symbol in a non-allocated section, *SHNDXP is instead
+ set to -1. Fills in BIAS, if not NULL, with the difference between
+ addresses within the loaded module and those in symbol table of the
+ ELF file. Note that the address associated with the symbol might
+ be in a different section than the returned symbol. The section in
+ the main elf file in which returned ADDR falls can be found with
+ dwfl_module_address_section. */
+extern const char *dwfl_module_getsym_info (Dwfl_Module *mod, int ndx,
+ GElf_Sym *sym, GElf_Addr *addr,
+ GElf_Word *shndxp,
+ Elf **elfp, Dwarf_Addr *bias)
+ __nonnull_attribute__ (3, 4);
+
/* Find the symbol that ADDRESS lies inside, and return its name. */
extern const char *dwfl_module_addrname (Dwfl_Module *mod, GElf_Addr address);
+/* Find the symbol associated with ADDRESS. Return its name or NULL
+ when nothing was found. If the architecture uses function
+ descriptors, and symbol st_value points to one, ADDRESS wil be
+ matched against either the adjusted st_value or the associated
+ function entry value as described in dwfl_module_getsym_info. If
+ OFFSET is not NULL it will be filled in with the difference from
+ the start of the symbol (or function entry). If SYM is not NULL it
+ is filled in with the symbol associated with the matched ADDRESS.
+ The SYM->ST_VALUE itself isn't adjusted in any way. Fills in ELFP,
+ if not NULL, with the ELF file the symbol originally came from.
+ Note that symbols can come from either the main, debug or auxiliary
+ ELF symbol file (either dynsym or symtab). If SHNDXP is non-null,
+ it's set with the section index (whether from st_shndx or extended
+ index table). Fills in BIAS, if not NULL, with the difference
+ between addresses within the loaded module and those in symbol
+ table of the ELF file. Note that the address matched against the
+ symbol might be in a different section than the returned symbol.
+ The section in the main elf file in ADDRESS falls can be found with
+ dwfl_module_address_section. */
+extern const char *dwfl_module_addrinfo (Dwfl_Module *mod, GElf_Addr address,
+ GElf_Off *offset, GElf_Sym *sym,
+ GElf_Word *shndxp, Elf **elfp,
+ Dwarf_Addr *bias)
+ __nonnull_attribute__ (3);
+
/* Find the symbol that ADDRESS lies inside, and return detailed
- information as for dwfl_module_getsym (above). */
+ information as for dwfl_module_getsym (above). Note that like
+ dwfl_module_getsym this function also adjusts SYM->ST_VALUE to an
+ absolute value based on the module's location. ADDRESS is only
+ matched against this adjusted SYM->ST_VALUE. This means that
+ depending on architecture this might only match symbols that
+ represent function descriptor addresses (and not function entry
+ addresses). For these reasons it is recommended to use
+ dwfl_module_addrinfo instead. */
extern const char *dwfl_module_addrsym (Dwfl_Module *mod, GElf_Addr address,
GElf_Sym *sym, GElf_Word *shndxp)
__nonnull_attribute__ (3);
@@ -565,6 +645,166 @@ extern Dwarf_CFI *dwfl_module_dwarf_cfi (Dwfl_Module *mod, Dwarf_Addr *bias);
extern Dwarf_CFI *dwfl_module_eh_cfi (Dwfl_Module *mod, Dwarf_Addr *bias);
+typedef struct
+{
+ /* Called to iterate through threads. Returns next TID (thread ID) on
+ success, a negative number on failure and zero if there are no more
+ threads. dwfl_errno () should be set if negative number has been
+ returned. *THREAD_ARGP is NULL on first call, and may be optionally
+ set by the implementation. The value set by the implementation will
+ be passed in on the next call to NEXT_THREAD. 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 must not be NULL. */
+ 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 will 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
+ only the initial frame. */
+ bool (*memory_read) (Dwfl *dwfl, Dwarf_Addr addr, Dwarf_Word *result,
+ void *dwfl_arg)
+ __nonnull_attribute__ (1, 3);
+
+ /* Called on initial unwind to get the initial register state of the first
+ frame. Should call dwfl_thread_state_registers, possibly multiple times
+ for different ranges and possibly also dwfl_thread_state_register_pc, to
+ fill in initial (DWARF) register values. After this call, till at least
+ thread_detach is called, the thread is assumed to be frozen, so that it is
+ safe to unwind. Returns true on success or false and sets dwfl_errno ()
+ on failure. In the case of a failure thread_detach will not be called.
+ This method must not be NULL. */
+ bool (*set_initial_registers) (Dwfl_Thread *thread, void *thread_arg)
+ __nonnull_attribute__ (1);
+
+ /* Called by dwfl_end. All thread_detach method calls have been already
+ done. This method may be NULL. */
+ void (*detach) (Dwfl *dwfl, void *dwfl_arg)
+ __nonnull_attribute__ (1);
+
+ /* Called when unwinding is done. No callback will be called after
+ this method has been called. Iff set_initial_registers was called for
+ a TID and it returned success thread_detach will be called before the
+ detach method above. This method may be NULL. */
+ void (*thread_detach) (Dwfl_Thread *thread, void *thread_arg)
+ __nonnull_attribute__ (1);
+} Dwfl_Thread_Callbacks;
+
+/* PID is the process id associated with the DWFL state. Architecture of DWFL
+ modules is specified by ELF, ELF must remain valid during DWFL lifetime.
+ Use NULL ELF to detect architecture from DWFL, the function will then detect
+ it from arbitrary Dwfl_Module of DWFL. DWFL_ARG is the callback backend
+ state. DWFL_ARG will be provided to the callbacks. *THREAD_CALLBACKS
+ function pointers must remain valid during lifetime of DWFL. Function
+ returns true on success, false otherwise. */
+bool dwfl_attach_state (Dwfl *dwfl, Elf *elf, pid_t pid,
+ const Dwfl_Thread_Callbacks *thread_callbacks,
+ void *dwfl_arg)
+ __nonnull_attribute__ (1, 4);
+
+/* Calls dwfl_attach_state with Dwfl_Thread_Callbacks setup for extracting
+ thread state from the ELF core file. Returns the pid number extracted
+ from the core file, or -1 for errors. */
+extern int dwfl_core_file_attach (Dwfl *dwfl, Elf *elf);
+
+/* Calls dwfl_attach_state with Dwfl_Thread_Callbacks setup for extracting
+ thread state from the proc file system. Uses ptrace to attach and stop
+ the thread under inspection and detaches when thread_detach is called
+ and unwinding for the thread is done, unless ASSUME_PTRACE_STOPPED is
+ true. If ASSUME_PTRACE_STOPPED is true the caller should make sure that
+ the thread is ptrace attached and stopped before unwinding by calling
+ either dwfl_thread_getframes or dwfl_getthread_frames. Returns zero on
+ success, -1 if dwfl_attach_state failed, or an errno code if opening the
+ proc files failed. */
+extern int dwfl_linux_proc_attach (Dwfl *dwfl, pid_t pid,
+ bool assume_ptrace_stopped);
+
+/* Return PID for the process associated with DWFL. Function returns -1 if
+ dwfl_attach_state was not called for DWFL. */
+pid_t dwfl_pid (Dwfl *dwfl)
+ __nonnull_attribute__ (1);
+
+/* Return DWFL from which THREAD was created using dwfl_getthreads. */
+Dwfl *dwfl_thread_dwfl (Dwfl_Thread *thread)
+ __nonnull_attribute__ (1);
+
+/* Return positive TID (thread ID) for THREAD. This function never fails. */
+pid_t dwfl_thread_tid (Dwfl_Thread *thread)
+ __nonnull_attribute__ (1);
+
+/* Return thread for frame STATE. This function never fails. */
+Dwfl_Thread *dwfl_frame_thread (Dwfl_Frame *state)
+ __nonnull_attribute__ (1);
+
+/* Called by Dwfl_Thread_Callbacks.set_initial_registers implementation.
+ For every known continuous block of registers <FIRSTREG..FIRSTREG+NREGS)
+ (inclusive..exclusive) set their content to REGS (array of NREGS items).
+ Function returns false if any of the registers has invalid number. */
+bool dwfl_thread_state_registers (Dwfl_Thread *thread, int firstreg,
+ unsigned nregs, const Dwarf_Word *regs)
+ __nonnull_attribute__ (1, 4);
+
+/* Called by Dwfl_Thread_Callbacks.set_initial_registers implementation.
+ If PC is not contained among DWARF registers passed by
+ dwfl_thread_state_registers on the target architecture pass the PC value
+ here. */
+void dwfl_thread_state_register_pc (Dwfl_Thread *thread, Dwarf_Word pc)
+ __nonnull_attribute__ (1);
+
+/* Iterate through the threads for a process. Returns zero if all threads 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 set dwfl_errno ().
+ Keeps calling the callback with the next thread while the callback returns
+ DWARF_CB_OK, till there are no more threads. */
+int dwfl_getthreads (Dwfl *dwfl,
+ int (*callback) (Dwfl_Thread *thread, void *arg),
+ void *arg)
+ __nonnull_attribute__ (1, 2);
+
+/* 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
+ set dwfl_errno (). Some systems return error instead of zero on end of the
+ backtrace, for cross-platform compatibility callers should consider error as
+ a zero. Keeps calling the callback with the next frame while the callback
+ returns DWARF_CB_OK, till there are no more frames. On start will call the
+ set_initial_registers callback and on return will call the detach_thread
+ callback of the Dwfl_Thread. */
+int dwfl_thread_getframes (Dwfl_Thread *thread,
+ int (*callback) (Dwfl_Frame *state, void *arg),
+ 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
+ find function of the caller. ACTIVATION may be NULL. PC must not be NULL.
+ Function returns false if it failed to find *PC. */
+bool dwfl_frame_pc (Dwfl_Frame *state, Dwarf_Addr *pc, bool *isactivation)
+ __nonnull_attribute__ (1, 2);
+
#ifdef __cplusplus
}
#endif
diff --git a/libdwfl/libdwflP.h b/libdwfl/libdwflP.h
index 1d4899b8..710e6992 100644
--- a/libdwfl/libdwflP.h
+++ b/libdwfl/libdwflP.h
@@ -1,5 +1,5 @@
/* Internal definitions for libdwfl.
- Copyright (C) 2005-2012 Red Hat, Inc.
+ Copyright (C) 2005-2013 Red Hat, Inc.
This file is part of elfutils.
This file is free software; you can redistribute it and/or modify
@@ -42,6 +42,8 @@
#include "../libdw/libdwP.h" /* We need its INTDECLs. */
+typedef struct Dwfl_Process Dwfl_Process;
+
/* gettext helper macros. */
#define _(Str) dgettext ("elfutils", Str)
@@ -74,7 +76,20 @@
DWFL_ERROR (BADELF, N_("not a valid ELF file")) \
DWFL_ERROR (WEIRD_TYPE, N_("cannot handle DWARF type description")) \
DWFL_ERROR (WRONG_ID_ELF, N_("ELF file does not match build ID")) \
- DWFL_ERROR (BAD_PRELINK, N_("corrupt .gnu.prelink_undo section data"))
+ DWFL_ERROR (BAD_PRELINK, N_("corrupt .gnu.prelink_undo section data")) \
+ DWFL_ERROR (LIBEBL_BAD, N_("Internal error due to ebl")) \
+ DWFL_ERROR (CORE_MISSING, N_("Missing data in core file")) \
+ DWFL_ERROR (INVALID_REGISTER, N_("Invalid register")) \
+ DWFL_ERROR (PROCESS_MEMORY_READ, N_("Error reading process memory")) \
+ DWFL_ERROR (PROCESS_NO_ARCH, N_("Couldn't find architecture of any ELF")) \
+ DWFL_ERROR (PARSE_PROC, N_("Error parsing /proc filesystem")) \
+ DWFL_ERROR (INVALID_DWARF, N_("Invalid DWARF")) \
+ DWFL_ERROR (UNSUPPORTED_DWARF, N_("Unsupported DWARF")) \
+ DWFL_ERROR (NEXT_THREAD_FAIL, N_("Unable to find more threads")) \
+ DWFL_ERROR (ATTACH_STATE_CONFLICT, N_("Dwfl already has attached state")) \
+ DWFL_ERROR (NO_ATTACH_STATE, N_("Dwfl has no attached state")) \
+ DWFL_ERROR (NO_UNWIND, N_("Unwinding not supported for this architecture")) \
+ DWFL_ERROR (INVALID_ARGUMENT, N_("Invalid argument"))
#define DWFL_ERROR(name, text) DWFL_E_##name,
typedef enum { DWFL_ERRORS DWFL_E_NUM } Dwfl_Error;
@@ -92,6 +107,8 @@ struct Dwfl
Dwfl_Module *modulelist; /* List in order used by full traversals. */
+ Dwfl_Process *process;
+
GElf_Addr offline_next_address;
GElf_Addr segment_align; /* Smallest granularity of segments. */
@@ -189,7 +206,72 @@ struct Dwfl_Module
bool gc; /* Mark/sweep flag. */
};
+/* This holds information common for all the threads/tasks/TIDs of one process
+ for backtraces. */
+
+struct Dwfl_Process
+{
+ struct Dwfl *dwfl;
+ pid_t pid;
+ const Dwfl_Thread_Callbacks *callbacks;
+ void *callbacks_arg;
+ struct ebl *ebl;
+ bool ebl_close:1;
+};
+
+/* See its typedef in libdwfl.h. */
+
+struct Dwfl_Thread
+{
+ Dwfl_Process *process;
+ pid_t tid;
+ /* The current frame being unwound. Initially it is the bottom frame.
+ Later the processed frames get freed and this pointer is updated. */
+ Dwfl_Frame *unwound;
+ void *callbacks_arg;
+};
+
+/* See its typedef in libdwfl.h. */
+
+struct Dwfl_Frame
+{
+ Dwfl_Thread *thread;
+ /* Previous (outer) frame. */
+ Dwfl_Frame *unwound;
+ bool signal_frame : 1;
+ bool initial_frame : 1;
+ enum
+ {
+ /* This structure is still being initialized or there was an error
+ initializing it. */
+ DWFL_FRAME_STATE_ERROR,
+ /* PC field is valid. */
+ DWFL_FRAME_STATE_PC_SET,
+ /* PC field is undefined, this means the next (inner) frame was the
+ outermost frame. */
+ DWFL_FRAME_STATE_PC_UNDEFINED
+ } pc_state;
+ /* Either initialized from appropriate REGS element or on some archs
+ initialized separately as the return address has no DWARF register. */
+ Dwarf_Addr pc;
+ /* (1 << X) bitmask where 0 <= X < ebl_frame_nregs. */
+ uint64_t regs_set[3];
+ /* REGS array size is ebl_frame_nregs.
+ REGS_SET tells which of the REGS are valid. */
+ Dwarf_Addr regs[];
+};
+/* Fetch value from Dwfl_Frame->regs indexed by DWARF REGNO.
+ No error code is set if the function returns FALSE. */
+bool __libdwfl_frame_reg_get (Dwfl_Frame *state, unsigned regno,
+ Dwarf_Addr *val)
+ internal_function;
+
+/* Store value to Dwfl_Frame->regs indexed by DWARF REGNO.
+ No error code is set if the function returns FALSE. */
+bool __libdwfl_frame_reg_set (Dwfl_Frame *state, unsigned regno,
+ Dwarf_Addr val)
+ internal_function;
/* Information cached about each CU in Dwfl_Module.dw. */
struct dwfl_cu
@@ -277,23 +359,21 @@ dwfl_deadjust_aux_sym_addr (Dwfl_Module *mod, Dwarf_Addr addr)
}
static inline GElf_Addr
-dwfl_adjusted_st_value (Dwfl_Module *mod, struct dwfl_file *symfile,
- GElf_Addr addr)
+dwfl_adjusted_st_value (Dwfl_Module *mod, Elf *symelf, GElf_Addr addr)
{
- if (symfile == &mod->main)
+ if (symelf == mod->main.elf)
return dwfl_adjusted_address (mod, addr);
- if (symfile == &mod->debug)
+ if (symelf == mod->debug.elf)
return dwfl_adjusted_dwarf_addr (mod, addr);
return dwfl_adjusted_aux_sym_addr (mod, addr);
}
static inline GElf_Addr
-dwfl_deadjust_st_value (Dwfl_Module *mod, struct dwfl_file *symfile,
- GElf_Addr addr)
+dwfl_deadjust_st_value (Dwfl_Module *mod, Elf *symelf, GElf_Addr addr)
{
- if (symfile == &mod->main)
+ if (symelf == mod->main.elf)
return dwfl_deadjust_address (mod, addr);
- if (symfile == &mod->debug)
+ if (symelf == mod->debug.elf)
return dwfl_deadjust_dwarf_addr (mod, addr);
return dwfl_deadjust_aux_sym_addr (mod, addr);
}
@@ -307,6 +387,23 @@ struct dwfl_arange
};
+/* Internal wrapper for old dwfl_module_getsym and new dwfl_module_getsym_info.
+ adjust_st_value set to true returns adjusted SYM st_value, set to false
+ it will not adjust SYM at all, but does match against resolved *ADDR. */
+extern const char *__libdwfl_getsym (Dwfl_Module *mod, int ndx, GElf_Sym *sym,
+ GElf_Addr *addr, GElf_Word *shndxp,
+ Elf **elfp, Dwarf_Addr *biasp,
+ bool *resolved, bool adjust_st_value)
+ internal_function;
+
+/* Internal wrapper for old dwfl_module_addrsym and new dwfl_module_addrinfo.
+ adjust_st_value set to true returns adjusted SYM st_value, set to false
+ it will not adjust SYM at all, but does match against resolved values. */
+extern const char *__libdwfl_addrsym (Dwfl_Module *mod, GElf_Addr addr,
+ GElf_Off *off, GElf_Sym *sym,
+ GElf_Word *shndxp, Elf **elfp,
+ Dwarf_Addr *bias,
+ bool adjust_st_value) internal_function;
extern void __libdwfl_module_free (Dwfl_Module *mod) internal_function;
@@ -323,6 +420,12 @@ extern void __libdwfl_getelf (Dwfl_Module *mod) internal_function;
extern Dwfl_Error __libdwfl_relocate (Dwfl_Module *mod, Elf *file, bool debug)
internal_function;
+/* Find the section index in mod->main.elf that contains the given
+ *ADDR. Adjusts *ADDR to be section relative on success, returns
+ SHN_UNDEF on failure. */
+extern size_t __libdwfl_find_section_ndx (Dwfl_Module *mod, Dwarf_Addr *addr)
+ internal_function;
+
/* Process (simple) relocations in arbitrary section TSCN of an ET_REL file.
RELOCSCN is SHT_REL or SHT_RELA and TSCN is its sh_info target section. */
extern Dwfl_Error __libdwfl_relocate_section (Dwfl_Module *mod, Elf *relocated,
@@ -339,7 +442,6 @@ extern Dwfl_Error __libdwfl_relocate_value (Dwfl_Module *mod, Elf *elf,
GElf_Addr *value)
internal_function;
-
/* Ensure that MOD->ebl is set up. */
extern Dwfl_Error __libdwfl_module_getebl (Dwfl_Module *mod) internal_function;
@@ -415,6 +517,25 @@ extern Dwfl_Module *__libdwfl_report_offline (Dwfl *dwfl, const char *name,
const char *))
internal_function;
+/* Free PROCESS. Unlink and free also any structures it references. */
+extern void __libdwfl_process_free (Dwfl_Process *process)
+ internal_function;
+
+/* Update STATE->unwound for the unwound frame.
+ On error STATE->unwound == NULL
+ or STATE->unwound->pc_state == DWFL_FRAME_STATE_ERROR;
+ in such case dwfl_errno () is set.
+ If STATE->unwound->pc_state == DWFL_FRAME_STATE_PC_UNDEFINED
+ then STATE was the last valid frame. */
+extern void __libdwfl_frame_unwind (Dwfl_Frame *state)
+ internal_function;
+
+/* Align segment START downwards or END upwards addresses according to DWFL. */
+extern GElf_Addr __libdwfl_segment_start (Dwfl *dwfl, GElf_Addr start)
+ internal_function;
+extern GElf_Addr __libdwfl_segment_end (Dwfl *dwfl, GElf_Addr end)
+ internal_function;
+
/* Decompression wrappers: decompress whole file into memory. */
extern Dwfl_Error __libdw_gunzip (int fd, off64_t start_offset,
void *mapped, size_t mapped_size,
@@ -442,6 +563,11 @@ extern Dwfl_Error __libdw_open_file (int *fdp, Elf **elfp,
bool close_on_fail, bool archive_ok)
internal_function;
+/* Fetch PT_DYNAMIC P_VADDR from ELF and store it to *VADDRP. Return success.
+ *VADDRP is not modified if the function fails. */
+extern bool __libdwfl_dynamic_vaddr_get (Elf *elf, GElf_Addr *vaddrp)
+ internal_function;
+
/* These are working nicely for --core, but are not ready to be
exported interfaces quite yet. */
@@ -467,7 +593,7 @@ struct r_debug_info_module
/* FD is -1 iff ELF is NULL. */
int fd;
Elf *elf;
- GElf_Addr l_addr, l_ld;
+ GElf_Addr l_ld;
/* START and END are both zero if not valid. */
GElf_Addr start, end;
bool disk_file_has_build_id;
@@ -522,16 +648,20 @@ INTDECL (dwfl_addrmodule)
INTDECL (dwfl_addrsegment)
INTDECL (dwfl_addrdwarf)
INTDECL (dwfl_addrdie)
+INTDECL (dwfl_core_file_attach)
INTDECL (dwfl_core_file_report)
INTDECL (dwfl_getmodules)
INTDECL (dwfl_module_addrdie)
INTDECL (dwfl_module_address_section)
+INTDECL (dwfl_module_addrinfo)
INTDECL (dwfl_module_addrsym)
INTDECL (dwfl_module_build_id)
INTDECL (dwfl_module_getdwarf)
INTDECL (dwfl_module_getelf)
INTDECL (dwfl_module_getsym)
+INTDECL (dwfl_module_getsym_info)
INTDECL (dwfl_module_getsymtab)
+INTDECL (dwfl_module_getsymtab_first_global)
INTDECL (dwfl_module_getsrc)
INTDECL (dwfl_module_report_build_id)
INTDECL (dwfl_report_elf)
@@ -547,6 +677,7 @@ INTDECL (dwfl_standard_find_debuginfo)
INTDECL (dwfl_link_map_report)
INTDECL (dwfl_linux_kernel_find_elf)
INTDECL (dwfl_linux_kernel_module_section_address)
+INTDECL (dwfl_linux_proc_attach)
INTDECL (dwfl_linux_proc_report)
INTDECL (dwfl_linux_proc_maps_report)
INTDECL (dwfl_linux_proc_find_elf)
@@ -557,6 +688,17 @@ INTDECL (dwfl_offline_section_address)
INTDECL (dwfl_module_relocate_address)
INTDECL (dwfl_module_dwarf_cfi)
INTDECL (dwfl_module_eh_cfi)
+INTDECL (dwfl_attach_state)
+INTDECL (dwfl_pid)
+INTDECL (dwfl_thread_dwfl)
+INTDECL (dwfl_thread_tid)
+INTDECL (dwfl_frame_thread)
+INTDECL (dwfl_thread_state_registers)
+INTDECL (dwfl_thread_state_register_pc)
+INTDECL (dwfl_getthread_frames)
+INTDECL (dwfl_getthreads)
+INTDECL (dwfl_thread_getframes)
+INTDECL (dwfl_frame_pc)
/* Leading arguments standard to callbacks passed a Dwfl_Module. */
#define MODCB_ARGS(mod) (mod), &(mod)->userdata, (mod)->name, (mod)->low_addr
diff --git a/libdwfl/link_map.c b/libdwfl/link_map.c
index 65e1c3a6..2913d9f7 100644
--- a/libdwfl/link_map.c
+++ b/libdwfl/link_map.c
@@ -369,7 +369,6 @@ report_r_debug (uint_fast8_t elfclass, uint_fast8_t elfdata,
return release_buffer (result);
r_debug_info_module->fd = -1;
r_debug_info_module->elf = NULL;
- r_debug_info_module->l_addr = l_addr;
r_debug_info_module->l_ld = l_ld;
r_debug_info_module->start = 0;
r_debug_info_module->end = 0;
@@ -389,17 +388,15 @@ report_r_debug (uint_fast8_t elfclass, uint_fast8_t elfdata,
{
Elf *elf;
Dwfl_Error error = __libdw_open_file (&fd, &elf, true, false);
- if (error == DWFL_E_NOERROR)
+ GElf_Addr elf_dynamic_vaddr;
+ if (error == DWFL_E_NOERROR
+ && __libdwfl_dynamic_vaddr_get (elf, &elf_dynamic_vaddr))
{
const void *build_id_bits;
GElf_Addr build_id_elfaddr;
int build_id_len;
bool valid = true;
- /* FIXME: Bias L_ADDR should be computed from the prelink
- state in memory (when the file got loaded), not against
- the current on-disk file state as is computed below. */
-
if (__libdwfl_find_elf_build_id (NULL, elf, &build_id_bits,
&build_id_elfaddr,
&build_id_len) > 0
@@ -407,7 +404,9 @@ report_r_debug (uint_fast8_t elfclass, uint_fast8_t elfdata,
{
if (r_debug_info_module != NULL)
r_debug_info_module->disk_file_has_build_id = true;
- GElf_Addr build_id_vaddr = build_id_elfaddr + l_addr;
+ GElf_Addr build_id_vaddr = (build_id_elfaddr
+ - elf_dynamic_vaddr + l_ld);
+
release_buffer (0);
int segndx = INTUSE(dwfl_addrsegment) (dwfl,
build_id_vaddr,
@@ -416,9 +415,11 @@ report_r_debug (uint_fast8_t elfclass, uint_fast8_t elfdata,
&buffer, &buffer_available,
build_id_vaddr, build_id_len,
memory_callback_arg))
- /* File has valid build-id which cannot be verified
- in memory. */
- valid = false;
+ {
+ /* File has valid build-id which cannot be read from
+ memory. This happens for core files without bit 4
+ (0x10) set in Linux /proc/PID/coredump_filter. */
+ }
else
{
if (memcmp (build_id_bits, buffer, build_id_len) != 0)
diff --git a/libdwfl/linux-core-attach.c b/libdwfl/linux-core-attach.c
new file mode 100644
index 00000000..1002788e
--- /dev/null
+++ b/libdwfl/linux-core-attach.c
@@ -0,0 +1,421 @@
+/* Get Dwarf Frame state for target core file.
+ 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/>. */
+
+#include "libdwflP.h"
+#include <fcntl.h>
+#include "system.h"
+
+#ifndef MIN
+# define MIN(a, b) ((a) < (b) ? (a) : (b))
+#endif
+
+struct core_arg
+{
+ Elf *core;
+ Elf_Data *note_data;
+ size_t thread_note_offset;
+ Ebl *ebl;
+};
+
+struct thread_arg
+{
+ struct core_arg *core_arg;
+ size_t note_offset;
+};
+
+static bool
+core_memory_read (Dwfl *dwfl, Dwarf_Addr addr, Dwarf_Word *result,
+ void *dwfl_arg)
+{
+ Dwfl_Process *process = dwfl->process;
+ struct core_arg *core_arg = dwfl_arg;
+ Elf *core = core_arg->core;
+ assert (core != NULL);
+ static size_t phnum;
+ if (elf_getphdrnum (core, &phnum) < 0)
+ {
+ __libdwfl_seterrno (DWFL_E_LIBELF);
+ return false;
+ }
+ for (size_t cnt = 0; cnt < phnum; ++cnt)
+ {
+ GElf_Phdr phdr_mem, *phdr = gelf_getphdr (core, cnt, &phdr_mem);
+ if (phdr == NULL || phdr->p_type != PT_LOAD)
+ continue;
+ /* Bias is zero here, a core file itself has no bias. */
+ GElf_Addr start = __libdwfl_segment_start (dwfl, phdr->p_vaddr);
+ GElf_Addr end = __libdwfl_segment_end (dwfl,
+ phdr->p_vaddr + phdr->p_memsz);
+ unsigned bytes = ebl_get_elfclass (process->ebl) == ELFCLASS64 ? 8 : 4;
+ if (addr < start || addr + bytes > end)
+ continue;
+ Elf_Data *data;
+ data = elf_getdata_rawchunk (core, phdr->p_offset + addr - start,
+ bytes, ELF_T_ADDR);
+ if (data == NULL)
+ {
+ __libdwfl_seterrno (DWFL_E_LIBELF);
+ return false;
+ }
+ assert (data->d_size == bytes);
+ /* FIXME: Currently any arch supported for unwinding supports
+ unaligned access. */
+ if (bytes == 8)
+ *result = *(const uint64_t *) data->d_buf;
+ else
+ *result = *(const uint32_t *) data->d_buf;
+ return true;
+ }
+ __libdwfl_seterrno (DWFL_E_ADDR_OUTOFRANGE);
+ return false;
+}
+
+static pid_t
+core_next_thread (Dwfl *dwfl __attribute__ ((unused)), void *dwfl_arg,
+ void **thread_argp)
+{
+ struct core_arg *core_arg = dwfl_arg;
+ Elf *core = core_arg->core;
+ GElf_Nhdr nhdr;
+ size_t name_offset;
+ size_t desc_offset;
+ Elf_Data *note_data = core_arg->note_data;
+ size_t offset;
+
+ struct thread_arg *thread_arg;
+ if (*thread_argp == NULL)
+ {
+ core_arg->thread_note_offset = 0;
+ thread_arg = malloc (sizeof (*thread_arg));
+ if (thread_arg == NULL)
+ {
+ __libdwfl_seterrno (DWFL_E_NOMEM);
+ return -1;
+ }
+ thread_arg->core_arg = core_arg;
+ *thread_argp = thread_arg;
+ }
+ else
+ thread_arg = (struct thread_arg *) *thread_argp;
+
+ while (offset = core_arg->thread_note_offset, offset < note_data->d_size
+ && (core_arg->thread_note_offset = gelf_getnote (note_data, offset,
+ &nhdr, &name_offset,
+ &desc_offset)) > 0)
+ {
+ /* Do not check NAME for now, help broken Linux kernels. */
+ const char *name = note_data->d_buf + name_offset;
+ const char *desc = note_data->d_buf + desc_offset;
+ GElf_Word regs_offset;
+ size_t nregloc;
+ const Ebl_Register_Location *reglocs;
+ size_t nitems;
+ const Ebl_Core_Item *items;
+ if (! ebl_core_note (core_arg->ebl, &nhdr, name,
+ &regs_offset, &nregloc, &reglocs, &nitems, &items))
+ {
+ /* This note may be just not recognized, skip it. */
+ continue;
+ }
+ if (nhdr.n_type != NT_PRSTATUS)
+ continue;
+ const Ebl_Core_Item *item;
+ for (item = items; item < items + nitems; item++)
+ if (strcmp (item->name, "pid") == 0)
+ break;
+ if (item == items + nitems)
+ continue;
+ uint32_t val32 = *(const uint32_t *) (desc + item->offset);
+ val32 = (elf_getident (core, NULL)[EI_DATA] == ELFDATA2MSB
+ ? be32toh (val32) : le32toh (val32));
+ pid_t tid = (int32_t) val32;
+ eu_static_assert (sizeof val32 <= sizeof tid);
+ thread_arg->note_offset = offset;
+ return tid;
+ }
+
+ free (thread_arg);
+ return 0;
+}
+
+static bool
+core_set_initial_registers (Dwfl_Thread *thread, void *thread_arg_voidp)
+{
+ struct thread_arg *thread_arg = thread_arg_voidp;
+ struct core_arg *core_arg = thread_arg->core_arg;
+ Elf *core = core_arg->core;
+ size_t offset = thread_arg->note_offset;
+ GElf_Nhdr nhdr;
+ size_t name_offset;
+ size_t desc_offset;
+ Elf_Data *note_data = core_arg->note_data;
+ size_t nregs = ebl_frame_nregs (core_arg->ebl);
+ assert (nregs > 0);
+ assert (offset < note_data->d_size);
+ size_t getnote_err = gelf_getnote (note_data, offset, &nhdr, &name_offset,
+ &desc_offset);
+ /* __libdwfl_attach_state_for_core already verified the note is there. */
+ assert (getnote_err != 0);
+ /* Do not check NAME for now, help broken Linux kernels. */
+ const char *name = note_data->d_buf + name_offset;
+ const char *desc = note_data->d_buf + desc_offset;
+ GElf_Word regs_offset;
+ size_t nregloc;
+ const Ebl_Register_Location *reglocs;
+ size_t nitems;
+ const Ebl_Core_Item *items;
+ int core_note_err = ebl_core_note (core_arg->ebl, &nhdr, name, &regs_offset,
+ &nregloc, &reglocs, &nitems, &items);
+ /* __libdwfl_attach_state_for_core already verified the note is there. */
+ assert (core_note_err != 0);
+ assert (nhdr.n_type == NT_PRSTATUS);
+ const Ebl_Core_Item *item;
+ for (item = items; item < items + nitems; item++)
+ if (strcmp (item->name, "pid") == 0)
+ break;
+ assert (item < items + nitems);
+ pid_t tid;
+ {
+ uint32_t val32 = *(const uint32_t *) (desc + item->offset);
+ val32 = (elf_getident (core, NULL)[EI_DATA] == ELFDATA2MSB
+ ? be32toh (val32) : le32toh (val32));
+ tid = (int32_t) val32;
+ eu_static_assert (sizeof val32 <= sizeof tid);
+ }
+ /* core_next_thread already found this TID there. */
+ assert (tid == INTUSE(dwfl_thread_tid) (thread));
+ for (item = items; item < items + nitems; item++)
+ if (item->pc_register)
+ break;
+ if (item < items + nitems)
+ {
+ Dwarf_Word pc;
+ switch (gelf_getclass (core) == ELFCLASS32 ? 32 : 64)
+ {
+ case 32:;
+ uint32_t val32 = *(const uint32_t *) (desc + item->offset);
+ val32 = (elf_getident (core, NULL)[EI_DATA] == ELFDATA2MSB
+ ? be32toh (val32) : le32toh (val32));
+ /* Do a host width conversion. */
+ pc = val32;
+ break;
+ case 64:;
+ uint64_t val64 = *(const uint64_t *) (desc + item->offset);
+ val64 = (elf_getident (core, NULL)[EI_DATA] == ELFDATA2MSB
+ ? be64toh (val64) : le64toh (val64));
+ pc = val64;
+ break;
+ default:
+ abort ();
+ }
+ INTUSE(dwfl_thread_state_register_pc) (thread, pc);
+ }
+ desc += regs_offset;
+ for (size_t regloci = 0; regloci < nregloc; regloci++)
+ {
+ const Ebl_Register_Location *regloc = reglocs + regloci;
+ // Iterate even regs out of NREGS range so that we can find pc_register.
+ if (regloc->bits != 32 && regloc->bits != 64)
+ continue;
+ const char *reg_desc = desc + regloc->offset;
+ for (unsigned regno = regloc->regno;
+ regno < regloc->regno + (regloc->count ?: 1U);
+ regno++)
+ {
+ /* PPC provides DWARF register 65 irrelevant for
+ CFI which clashes with register 108 (LR) we need.
+ LR (108) is provided earlier (in NT_PRSTATUS) than the # 65.
+ FIXME: It depends now on their order in core notes.
+ FIXME: It uses private function. */
+ if (regno < nregs
+ && __libdwfl_frame_reg_get (thread->unwound, regno, NULL))
+ continue;
+ Dwarf_Word val;
+ switch (regloc->bits)
+ {
+ case 32:;
+ uint32_t val32 = *(const uint32_t *) reg_desc;
+ reg_desc += sizeof val32;
+ val32 = (elf_getident (core, NULL)[EI_DATA] == ELFDATA2MSB
+ ? be32toh (val32) : le32toh (val32));
+ /* Do a host width conversion. */
+ val = val32;
+ break;
+ case 64:;
+ uint64_t val64 = *(const uint64_t *) reg_desc;
+ reg_desc += sizeof val64;
+ val64 = (elf_getident (core, NULL)[EI_DATA] == ELFDATA2MSB
+ ? be64toh (val64) : le64toh (val64));
+ assert (sizeof (*thread->unwound->regs) == sizeof val64);
+ val = val64;
+ break;
+ default:
+ abort ();
+ }
+ /* Registers not valid for CFI are just ignored. */
+ if (regno < nregs)
+ INTUSE(dwfl_thread_state_registers) (thread, regno, 1, &val);
+ if (regloc->pc_register)
+ INTUSE(dwfl_thread_state_register_pc) (thread, val);
+ reg_desc += regloc->pad;
+ }
+ }
+ return true;
+}
+
+static void
+core_detach (Dwfl *dwfl __attribute__ ((unused)), void *dwfl_arg)
+{
+ struct core_arg *core_arg = dwfl_arg;
+ ebl_closebackend (core_arg->ebl);
+ free (core_arg);
+}
+
+static const Dwfl_Thread_Callbacks core_thread_callbacks =
+{
+ core_next_thread,
+ NULL, /* get_thread */
+ core_memory_read,
+ core_set_initial_registers,
+ core_detach,
+ NULL, /* core_thread_detach */
+};
+
+int
+dwfl_core_file_attach (Dwfl *dwfl, Elf *core)
+{
+ Ebl *ebl = ebl_openbackend (core);
+ if (ebl == NULL)
+ {
+ __libdwfl_seterrno (DWFL_E_LIBEBL);
+ return -1;
+ }
+ size_t nregs = ebl_frame_nregs (ebl);
+ if (nregs == 0)
+ {
+ __libdwfl_seterrno (DWFL_E_NO_UNWIND);
+ ebl_closebackend (ebl);
+ return -1;
+ }
+ GElf_Ehdr ehdr_mem, *ehdr = gelf_getehdr (core, &ehdr_mem);
+ if (ehdr == NULL)
+ {
+ __libdwfl_seterrno (DWFL_E_LIBELF);
+ ebl_closebackend (ebl);
+ return -1;
+ }
+ assert (ehdr->e_type == ET_CORE);
+ size_t phnum;
+ if (elf_getphdrnum (core, &phnum) < 0)
+ {
+ __libdwfl_seterrno (DWFL_E_LIBELF);
+ ebl_closebackend (ebl);
+ return -1;
+ }
+ pid_t pid = -1;
+ Elf_Data *note_data = NULL;
+ for (size_t cnt = 0; cnt < phnum; ++cnt)
+ {
+ GElf_Phdr phdr_mem, *phdr = gelf_getphdr (core, cnt, &phdr_mem);
+ if (phdr != NULL && phdr->p_type == PT_NOTE)
+ {
+ note_data = elf_getdata_rawchunk (core, phdr->p_offset,
+ phdr->p_filesz, ELF_T_NHDR);
+ break;
+ }
+ }
+ if (note_data == NULL)
+ {
+ ebl_closebackend (ebl);
+ return DWFL_E_LIBELF;
+ }
+ size_t offset = 0;
+ GElf_Nhdr nhdr;
+ size_t name_offset;
+ size_t desc_offset;
+ while (offset < note_data->d_size
+ && (offset = gelf_getnote (note_data, offset,
+ &nhdr, &name_offset, &desc_offset)) > 0)
+ {
+ /* Do not check NAME for now, help broken Linux kernels. */
+ const char *name = note_data->d_buf + name_offset;
+ const char *desc = note_data->d_buf + desc_offset;
+ GElf_Word regs_offset;
+ size_t nregloc;
+ const Ebl_Register_Location *reglocs;
+ size_t nitems;
+ const Ebl_Core_Item *items;
+ if (! ebl_core_note (ebl, &nhdr, name,
+ &regs_offset, &nregloc, &reglocs, &nitems, &items))
+ {
+ /* This note may be just not recognized, skip it. */
+ continue;
+ }
+ if (nhdr.n_type != NT_PRPSINFO)
+ continue;
+ const Ebl_Core_Item *item;
+ for (item = items; item < items + nitems; item++)
+ if (strcmp (item->name, "pid") == 0)
+ break;
+ if (item == items + nitems)
+ continue;
+ uint32_t val32 = *(const uint32_t *) (desc + item->offset);
+ val32 = (elf_getident (core, NULL)[EI_DATA] == ELFDATA2MSB
+ ? be32toh (val32) : le32toh (val32));
+ pid = (int32_t) val32;
+ eu_static_assert (sizeof val32 <= sizeof pid);
+ break;
+ }
+ if (pid == -1)
+ {
+ /* No valid NT_PRPSINFO recognized in this CORE. */
+ __libdwfl_seterrno (DWFL_E_BADELF);
+ ebl_closebackend (ebl);
+ return -1;
+ }
+ struct core_arg *core_arg = malloc (sizeof *core_arg);
+ if (core_arg == NULL)
+ {
+ __libdwfl_seterrno (DWFL_E_NOMEM);
+ ebl_closebackend (ebl);
+ return -1;
+ }
+ core_arg->core = core;
+ core_arg->note_data = note_data;
+ core_arg->thread_note_offset = 0;
+ core_arg->ebl = ebl;
+ if (! INTUSE(dwfl_attach_state) (dwfl, core, pid, &core_thread_callbacks,
+ core_arg))
+ {
+ free (core_arg);
+ ebl_closebackend (ebl);
+ return -1;
+ }
+ return pid;
+}
+INTDEF (dwfl_core_file_attach)
diff --git a/libdwfl/linux-kernel-modules.c b/libdwfl/linux-kernel-modules.c
index fe010282..53075183 100644
--- a/libdwfl/linux-kernel-modules.c
+++ b/libdwfl/linux-kernel-modules.c
@@ -1,5 +1,5 @@
/* Standard libdwfl callbacks for debugging the running Linux kernel.
- Copyright (C) 2005-2011 Red Hat, Inc.
+ Copyright (C) 2005-2011, 2013 Red Hat, Inc.
This file is part of elfutils.
This file is free software; you can redistribute it and/or modify
@@ -251,9 +251,10 @@ report_kernel_archive (Dwfl *dwfl, const char **release,
return result;
char *archive;
- if (unlikely ((*release)[0] == '/'
- ? asprintf (&archive, "%s/debug.a", *release)
- : asprintf (&archive, MODULEDIRFMT "/debug.a", *release) < 0))
+ int res = (((*release)[0] == '/')
+ ? asprintf (&archive, "%s/debug.a", *release)
+ : asprintf (&archive, MODULEDIRFMT "/debug.a", *release));
+ if (unlikely (res < 0))
return ENOMEM;
int fd = try_kernel_name (dwfl, &archive, false);
diff --git a/libdwfl/linux-pid-attach.c b/libdwfl/linux-pid-attach.c
new file mode 100644
index 00000000..58d6942f
--- /dev/null
+++ b/libdwfl/linux-pid-attach.c
@@ -0,0 +1,349 @@
+/* Get Dwarf Frame state for target live PID process.
+ 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/>. */
+
+#include "libdwflP.h"
+#include <sys/ptrace.h>
+#include <sys/wait.h>
+#include <dirent.h>
+#include <sys/syscall.h>
+#include <unistd.h>
+
+#ifndef MAX
+# define MAX(a, b) ((a) > (b) ? (a) : (b))
+#endif
+
+struct pid_arg
+{
+ DIR *dir;
+ /* It is 0 if not used. */
+ pid_t tid_attached;
+ /* Valid only if TID_ATTACHED is not zero. */
+ bool tid_was_stopped;
+ /* True if threads are ptrace stopped by caller. */
+ bool assume_ptrace_stopped;
+};
+
+static bool
+linux_proc_pid_is_stopped (pid_t pid)
+{
+ char buffer[64];
+ FILE *procfile;
+ bool retval, have_state;
+
+ snprintf (buffer, sizeof (buffer), "/proc/%ld/status", (long) pid);
+ procfile = fopen (buffer, "r");
+ if (procfile == NULL)
+ return false;
+
+ have_state = false;
+ while (fgets (buffer, sizeof (buffer), procfile) != NULL)
+ if (strncmp (buffer, "State:", 6) == 0)
+ {
+ have_state = true;
+ break;
+ }
+ retval = (have_state && strstr (buffer, "T (stopped)") != NULL);
+ fclose (procfile);
+ return retval;
+}
+
+static bool
+ptrace_attach (pid_t tid, bool *tid_was_stoppedp)
+{
+ if (ptrace (PTRACE_ATTACH, tid, NULL, NULL) != 0)
+ {
+ __libdwfl_seterrno (DWFL_E_ERRNO);
+ return false;
+ }
+ *tid_was_stoppedp = linux_proc_pid_is_stopped (tid);
+ if (*tid_was_stoppedp)
+ {
+ /* Make sure there is a SIGSTOP signal pending even when the process is
+ already State: T (stopped). Older kernels might fail to generate
+ a SIGSTOP notification in that case in response to our PTRACE_ATTACH
+ above. Which would make the waitpid below wait forever. So emulate
+ it. Since there can only be one SIGSTOP notification pending this is
+ safe. See also gdb/linux-nat.c linux_nat_post_attach_wait. */
+ syscall (__NR_tkill, tid, SIGSTOP);
+ ptrace (PTRACE_CONT, tid, NULL, NULL);
+ }
+ for (;;)
+ {
+ int status;
+ if (waitpid (tid, &status, __WALL) != tid || !WIFSTOPPED (status))
+ {
+ int saved_errno = errno;
+ ptrace (PTRACE_DETACH, tid, NULL, NULL);
+ errno = saved_errno;
+ __libdwfl_seterrno (DWFL_E_ERRNO);
+ return false;
+ }
+ if (WSTOPSIG (status) == SIGSTOP)
+ break;
+ if (ptrace (PTRACE_CONT, tid, NULL,
+ (void *) (uintptr_t) WSTOPSIG (status)) != 0)
+ {
+ int saved_errno = errno;
+ ptrace (PTRACE_DETACH, tid, NULL, NULL);
+ errno = saved_errno;
+ __libdwfl_seterrno (DWFL_E_ERRNO);
+ return false;
+ }
+ }
+ return true;
+}
+
+static bool
+pid_memory_read (Dwfl *dwfl, Dwarf_Addr addr, Dwarf_Word *result, void *arg)
+{
+ struct pid_arg *pid_arg = arg;
+ pid_t tid = pid_arg->tid_attached;
+ assert (tid > 0);
+ Dwfl_Process *process = dwfl->process;
+ if (ebl_get_elfclass (process->ebl) == ELFCLASS64)
+ {
+#if SIZEOF_LONG == 8
+ errno = 0;
+ *result = ptrace (PTRACE_PEEKDATA, tid, (void *) (uintptr_t) addr, NULL);
+ return errno == 0;
+#else /* SIZEOF_LONG != 8 */
+ /* This should not happen. */
+ return false;
+#endif /* SIZEOF_LONG != 8 */
+ }
+#if SIZEOF_LONG == 8
+ /* We do not care about reads unaliged to 4 bytes boundary.
+ But 0x...ffc read of 8 bytes could overrun a page. */
+ bool lowered = (addr & 4) != 0;
+ if (lowered)
+ addr -= 4;
+#endif /* SIZEOF_LONG == 8 */
+ errno = 0;
+ *result = ptrace (PTRACE_PEEKDATA, tid, (void *) (uintptr_t) addr, NULL);
+ if (errno != 0)
+ return false;
+#if SIZEOF_LONG == 8
+# if BYTE_ORDER == BIG_ENDIAN
+ if (! lowered)
+ *result >>= 32;
+# else
+ if (lowered)
+ *result >>= 32;
+# endif
+#endif /* SIZEOF_LONG == 8 */
+ *result &= 0xffffffff;
+ return true;
+}
+
+static pid_t
+pid_next_thread (Dwfl *dwfl __attribute__ ((unused)), void *dwfl_arg,
+ void **thread_argp)
+{
+ struct pid_arg *pid_arg = dwfl_arg;
+ struct dirent *dirent;
+ /* Start fresh on first traversal. */
+ if (*thread_argp == NULL)
+ rewinddir (pid_arg->dir);
+ do
+ {
+ errno = 0;
+ dirent = readdir (pid_arg->dir);
+ if (dirent == NULL)
+ {
+ if (errno != 0)
+ {
+ __libdwfl_seterrno (DWFL_E_ERRNO);
+ return -1;
+ }
+ return 0;
+ }
+ }
+ while (strcmp (dirent->d_name, ".") == 0
+ || strcmp (dirent->d_name, "..") == 0);
+ char *end;
+ errno = 0;
+ long tidl = strtol (dirent->d_name, &end, 10);
+ if (errno != 0)
+ {
+ __libdwfl_seterrno (DWFL_E_ERRNO);
+ return -1;
+ }
+ pid_t tid = tidl;
+ if (tidl <= 0 || (end && *end) || tid != tidl)
+ {
+ __libdwfl_seterrno (DWFL_E_PARSE_PROC);
+ return -1;
+ }
+ *thread_argp = dwfl_arg;
+ return tid;
+}
+
+/* Just checks that the thread id exists. */
+static bool
+pid_getthread (Dwfl *dwfl __attribute__ ((unused)), pid_t tid,
+ void *dwfl_arg, void **thread_argp)
+{
+ *thread_argp = dwfl_arg;
+ if (kill (tid, 0) < 0)
+ {
+ __libdwfl_seterrno (DWFL_E_ERRNO);
+ return false;
+ }
+ return true;
+}
+
+/* Implement the ebl_set_initial_registers_tid setfunc callback. */
+
+static bool
+pid_thread_state_registers_cb (int firstreg, unsigned nregs,
+ const Dwarf_Word *regs, void *arg)
+{
+ Dwfl_Thread *thread = (Dwfl_Thread *) arg;
+ if (firstreg < 0)
+ {
+ assert (firstreg == -1);
+ assert (nregs == 1);
+ INTUSE(dwfl_thread_state_register_pc) (thread, *regs);
+ return true;
+ }
+ assert (nregs > 0);
+ return INTUSE(dwfl_thread_state_registers) (thread, firstreg, nregs, regs);
+}
+
+static bool
+pid_set_initial_registers (Dwfl_Thread *thread, void *thread_arg)
+{
+ struct pid_arg *pid_arg = thread_arg;
+ assert (pid_arg->tid_attached == 0);
+ pid_t tid = INTUSE(dwfl_thread_tid) (thread);
+ if (! pid_arg->assume_ptrace_stopped
+ && ! ptrace_attach (tid, &pid_arg->tid_was_stopped))
+ return false;
+ pid_arg->tid_attached = tid;
+ Dwfl_Process *process = thread->process;
+ Ebl *ebl = process->ebl;
+ return ebl_set_initial_registers_tid (ebl, tid,
+ pid_thread_state_registers_cb, thread);
+}
+
+static void
+pid_detach (Dwfl *dwfl __attribute__ ((unused)), void *dwfl_arg)
+{
+ struct pid_arg *pid_arg = dwfl_arg;
+ closedir (pid_arg->dir);
+ free (pid_arg);
+}
+
+static void
+pid_thread_detach (Dwfl_Thread *thread, void *thread_arg)
+{
+ struct pid_arg *pid_arg = thread_arg;
+ pid_t tid = INTUSE(dwfl_thread_tid) (thread);
+ assert (pid_arg->tid_attached == tid);
+ pid_arg->tid_attached = 0;
+ if (! pid_arg->assume_ptrace_stopped)
+ {
+ /* This handling is needed only on older Linux kernels such as
+ 2.6.32-358.23.2.el6.ppc64. Later kernels such as
+ 3.11.7-200.fc19.x86_64 remember the T (stopped) state
+ themselves and no longer need to pass SIGSTOP during
+ PTRACE_DETACH. */
+ ptrace (PTRACE_DETACH, tid, NULL,
+ (void *) (intptr_t) (pid_arg->tid_was_stopped ? SIGSTOP : 0));
+ }
+}
+
+static const Dwfl_Thread_Callbacks pid_thread_callbacks =
+{
+ pid_next_thread,
+ pid_getthread,
+ pid_memory_read,
+ pid_set_initial_registers,
+ pid_detach,
+ pid_thread_detach,
+};
+
+int
+dwfl_linux_proc_attach (Dwfl *dwfl, pid_t pid, bool assume_ptrace_stopped)
+{
+ char buffer[36];
+ FILE *procfile;
+
+ /* Make sure to report the actual PID (thread group leader) to
+ dwfl_attach_state. */
+ snprintf (buffer, sizeof (buffer), "/proc/%ld/status", (long) pid);
+ procfile = fopen (buffer, "r");
+ if (procfile == NULL)
+ return errno;
+
+ char *line = NULL;
+ size_t linelen = 0;
+ while (getline (&line, &linelen, procfile) >= 0)
+ if (strncmp (line, "Tgid:", 5) == 0)
+ {
+ errno = 0;
+ char *endptr;
+ long val = strtol (&line[5], &endptr, 10);
+ if ((errno == ERANGE && val == LONG_MAX)
+ || *endptr != '\n' || val < 0 || val != (pid_t) val)
+ pid = 0;
+ else
+ pid = (pid_t) val;
+ break;
+ }
+ free (line);
+ fclose (procfile);
+
+ if (pid == 0)
+ return ESRCH;
+
+ char dirname[64];
+ int i = snprintf (dirname, sizeof (dirname), "/proc/%ld/task", (long) pid);
+ assert (i > 0 && i < (ssize_t) sizeof (dirname) - 1);
+ DIR *dir = opendir (dirname);
+ if (dir == NULL)
+ return errno;
+ struct pid_arg *pid_arg = malloc (sizeof *pid_arg);
+ if (pid_arg == NULL)
+ {
+ closedir (dir);
+ return ENOMEM;
+ }
+ pid_arg->dir = dir;
+ pid_arg->tid_attached = 0;
+ pid_arg->assume_ptrace_stopped = assume_ptrace_stopped;
+ if (! INTUSE(dwfl_attach_state) (dwfl, NULL, pid, &pid_thread_callbacks,
+ pid_arg))
+ {
+ closedir (dir);
+ free (pid_arg);
+ return -1;
+ }
+ return 0;
+}
+INTDEF (dwfl_linux_proc_attach)
diff --git a/libdwfl/linux-proc-maps.c b/libdwfl/linux-proc-maps.c
index 10946b9c..cdb6959d 100644
--- a/libdwfl/linux-proc-maps.c
+++ b/libdwfl/linux-proc-maps.c
@@ -1,5 +1,5 @@
/* Standard libdwfl callbacks for debugging a live Linux process.
- Copyright (C) 2005-2010 Red Hat, Inc.
+ Copyright (C) 2005-2010, 2013 Red Hat, Inc.
This file is part of elfutils.
This file is free software; you can redistribute it and/or modify
@@ -29,6 +29,7 @@
#include "libdwflP.h"
#include <inttypes.h>
#include <sys/types.h>
+#include <sys/stat.h>
#include <errno.h>
#include <stdio.h>
#include <stdio_ext.h>
@@ -232,7 +233,7 @@ proc_maps_report (Dwfl *dwfl, FILE *f, GElf_Addr sysinfo_ehdr, pid_t pid)
}
char *file = line + nread + strspn (line + nread, " \t");
- if (file[0] == '\0' || (ino == 0 && dmajor == 0 && dminor == 0))
+ if (file[0] != '/' || (ino == 0 && dmajor == 0 && dminor == 0))
/* This line doesn't indicate a file mapping. */
continue;
@@ -338,6 +339,14 @@ dwfl_linux_proc_find_elf (Dwfl_Module *mod __attribute__ ((unused)),
{
if (module_name[0] == '/')
{
+ /* When this callback is used together with dwfl_linux_proc_report
+ then we might see mappings of special character devices. Make
+ sure we only open and return regular files. Special devices
+ might hang on open or read. */
+ struct stat sb;
+ if (stat (module_name, &sb) == -1 || (sb.st_mode & S_IFMT) != S_IFREG)
+ return -1;
+
int fd = open64 (module_name, O_RDONLY);
if (fd >= 0)
{
@@ -373,7 +382,6 @@ dwfl_linux_proc_find_elf (Dwfl_Module *mod __attribute__ ((unused)),
return -1;
}
- abort ();
return -1;
}
INTDEF (dwfl_linux_proc_find_elf)
diff --git a/libdwfl/relocate.c b/libdwfl/relocate.c
index 90499fc3..7afbea18 100644
--- a/libdwfl/relocate.c
+++ b/libdwfl/relocate.c
@@ -252,7 +252,7 @@ resolve_symbol (Dwfl_Module *referer, struct reloc_symtab_cache *symtab,
if (m->e_type != ET_REL)
{
- sym->st_value = dwfl_adjusted_st_value (m, m->symfile,
+ sym->st_value = dwfl_adjusted_st_value (m, m->symfile->elf,
sym->st_value);
return DWFL_E_NOERROR;
}
diff --git a/libdwfl/segment.c b/libdwfl/segment.c
index 496b4fdc..92769174 100644
--- a/libdwfl/segment.c
+++ b/libdwfl/segment.c
@@ -1,5 +1,5 @@
/* Manage address space lookup table for libdwfl.
- Copyright (C) 2008, 2009, 2010 Red Hat, Inc.
+ Copyright (C) 2008, 2009, 2010, 2013 Red Hat, Inc.
This file is part of elfutils.
This file is free software; you can redistribute it and/or modify
@@ -28,16 +28,18 @@
#include "libdwflP.h"
-static GElf_Addr
-segment_start (Dwfl *dwfl, GElf_Addr start)
+GElf_Addr
+internal_function
+__libdwfl_segment_start (Dwfl *dwfl, GElf_Addr start)
{
if (dwfl->segment_align > 1)
start &= -dwfl->segment_align;
return start;
}
-static GElf_Addr
-segment_end (Dwfl *dwfl, GElf_Addr end)
+GElf_Addr
+internal_function
+__libdwfl_segment_end (Dwfl *dwfl, GElf_Addr end)
{
if (dwfl->segment_align > 1)
end = (end + dwfl->segment_align - 1) & -dwfl->segment_align;
@@ -156,8 +158,8 @@ reify_segments (Dwfl *dwfl)
for (Dwfl_Module *mod = dwfl->modulelist; mod != NULL; mod = mod->next)
if (! mod->gc)
{
- const GElf_Addr start = segment_start (dwfl, mod->low_addr);
- const GElf_Addr end = segment_end (dwfl, mod->high_addr);
+ const GElf_Addr start = __libdwfl_segment_start (dwfl, mod->low_addr);
+ const GElf_Addr end = __libdwfl_segment_end (dwfl, mod->high_addr);
bool resized = false;
int idx = lookup (dwfl, start, hint);
@@ -296,8 +298,9 @@ dwfl_report_segment (Dwfl *dwfl, int ndx, const GElf_Phdr *phdr, GElf_Addr bias,
dwfl->lookup_module = NULL;
}
- GElf_Addr start = segment_start (dwfl, bias + phdr->p_vaddr);
- GElf_Addr end = segment_end (dwfl, bias + phdr->p_vaddr + phdr->p_memsz);
+ GElf_Addr start = __libdwfl_segment_start (dwfl, bias + phdr->p_vaddr);
+ GElf_Addr end = __libdwfl_segment_end (dwfl,
+ bias + phdr->p_vaddr + phdr->p_memsz);
/* Coalesce into the last one if contiguous and matching. */
if (ndx != dwfl->lookup_tail_ndx
diff --git a/libebl/ChangeLog b/libebl/ChangeLog
index e81fae90..fc6bdd56 100644
--- a/libebl/ChangeLog
+++ b/libebl/ChangeLog
@@ -1,3 +1,58 @@
+2013-12-18 Mark Wielaard <[email protected]>
+
+ * Makefile.am (gen_SOURCES): Add eblresolvesym.c.
+ * ebl-hooks.h (resolve_sym_value): New entry.
+ * eblresolvesym.c: New file.
+ * libebl.h (ebl_resolve_sym_value): New definition.
+ * libeblP.h (fd_addr): New field.
+ (fd_data): Likewise.
+
+2013-12-18 Jan Kratochvil <[email protected]>
+
+ unwinder: s390 and s390x
+ * Makefile.am (gen_SOURCES): Add eblnormalizepc.c and eblunwind.c.
+ * ebl-hooks.h (normalize_pc, unwind): New.
+ * eblnormalizepc.c: New file.
+ * eblunwind.c: New file.
+ * libebl.h (Ebl_Register_Location): Add field pc_register.
+ (ebl_normalize_pc): New declaration.
+ (ebl_tid_registers_get_t, ebl_pid_memory_read_t): New definitions.
+ (ebl_unwind): New declaration.
+
+2013-12-15 Jan Kratochvil <[email protected]>
+
+ unwinder: ppc and ppc64
+ * Makefile.am (gen_SOURCES): Add ebldwarftoregno.c.
+ * ebl-hooks.h (dwarf_to_regno): New.
+ * ebldwarftoregno.c: New file.
+ * libebl.h (Ebl_Core_Item): New field pc_register.
+ (ebl_tid_registers_t): Add FIRSTREG -1 to the comment.
+ (ebl_dwarf_to_regno): New.
+
+2013-11-25 Petr Machata <[email protected]>
+
+ * eblopenbackend.c (machines): Add entry for AArch64.
+
+2013-11-14 Jan Kratochvil <[email protected]>
+
+ Code cleanup: Remove const in prototype
+ * libebl.h (ebl_tid_registers_t): Remove const from firstreg.
+
+2013-11-07 Jan Kratochvil <[email protected]>
+ Mark Wielaard <[email protected]>
+
+ * Makefile.am (gen_SOURCES): Add eblinitreg.c.
+ * ebl-hooks.h (set_initial_registers_tid): New entry.
+ * eblinitreg.c: New file.
+ * libebl.h (ebl_tid_registers_t): New definition.
+ (ebl_set_initial_registers_tid, ebl_frame_nregs): New declarations.
+ * libeblP.h (struct ebl): New entry frame_nregs.
+
+2013-10-06 Mark Wielaard <[email protected]>
+
+ * libebl.h (ebl_abi_cfi): Document restrictions using register
+ rules.
+
2013-09-26 Petr Machata <[email protected]>
* eblcorenotetypename.c: Handle NT_ARM_TLS, NT_ARM_HW_BREAK,
diff --git a/libebl/Makefile.am b/libebl/Makefile.am
index 4d62fad1..916af72a 100644
--- a/libebl/Makefile.am
+++ b/libebl/Makefile.am
@@ -1,6 +1,6 @@
## Process this file with automake to create Makefile.in
##
-## Copyright (C) 2000-2010 Red Hat, Inc.
+## Copyright (C) 2000-2010, 2013 Red Hat, Inc.
## This file is part of elfutils.
##
## This file is free software; you can redistribute it and/or modify
@@ -54,7 +54,8 @@ gen_SOURCES = eblopenbackend.c eblclosebackend.c eblstrtab.c \
eblreginfo.c eblnonerelocp.c eblrelativerelocp.c \
eblsysvhashentrysize.c eblauxvinfo.c eblcheckobjattr.c \
ebl_check_special_section.c ebl_syscall_abi.c eblabicfi.c \
- eblstother.c
+ eblstother.c eblinitreg.c ebldwarftoregno.c eblnormalizepc.c \
+ eblunwind.c eblresolvesym.c
libebl_a_SOURCES = $(gen_SOURCES)
diff --git a/libebl/ebl-hooks.h b/libebl/ebl-hooks.h
index d3cf3e62..bfb7f4a9 100644
--- a/libebl/ebl-hooks.h
+++ b/libebl/ebl-hooks.h
@@ -1,5 +1,5 @@
/* Backend hook signatures internal interface for libebl.
- Copyright (C) 2000-2011 Red Hat, Inc.
+ Copyright (C) 2000-2011, 2013 Red Hat, Inc.
This file is part of elfutils.
This file is free software; you can redistribute it and/or modify
@@ -155,5 +155,38 @@ int EBLHOOK(disasm) (const uint8_t **startp, const uint8_t *end,
Function returns 0 on success and -1 on error. */
int EBLHOOK(abi_cfi) (Ebl *ebl, Dwarf_CIE *abi_info);
+/* Fetch process data from live TID and call SETFUNC one or more times.
+ Method should be present only when EBL_FRAME_NREGS > 0, otherwise the
+ backend doesn't support unwinding. */
+bool EBLHOOK(set_initial_registers_tid) (pid_t tid,
+ ebl_tid_registers_t *setfunc,
+ void *arg);
+
+/* Convert *REGNO as is in DWARF to a lower range suitable for
+ Dwarf_Frame->REGS indexing. */
+bool EBLHOOK(dwarf_to_regno) (Ebl *ebl, unsigned *regno);
+
+/* Optionally modify *PC as fetched from inferior data into valid PC
+ instruction pointer. */
+void EBLHOOK(normalize_pc) (Ebl *ebl, Dwarf_Addr *pc);
+
+/* Get previous frame state for an existing frame state. Method is called only
+ if unwinder could not find CFI for current PC. PC is for the
+ existing frame. SETFUNC sets register in the previous frame. GETFUNC gets
+ register from the existing frame. Note that GETFUNC vs. SETFUNC act on
+ a disjunct set of registers. READFUNC reads memory. ARG has to be passed
+ for SETFUNC, GETFUNC and READFUNC. *SIGNAL_FRAMEP is initialized to false,
+ it can be set to true if existing frame is a signal frame. SIGNAL_FRAMEP is
+ never NULL. */
+bool EBLHOOK(unwind) (Ebl *ebl, Dwarf_Addr pc, ebl_tid_registers_t *setfunc,
+ ebl_tid_registers_get_t *getfunc,
+ ebl_pid_memory_read_t *readfunc, void *arg,
+ bool *signal_framep);
+
+/* Returns true if the value can be resolved to an address in an
+ allocated section, which will be returned in *SHNDXP.
+ (e.g. function descriptor resolving) */
+bool EBLHOOK(resolve_sym_value) (Ebl *ebl, GElf_Addr *addr);
+
/* Destructor for ELF backend handle. */
void EBLHOOK(destr) (struct ebl *);
diff --git a/libdw/memory-access.c b/libebl/ebldwarftoregno.c
index 7666fb60..8fb85401 100644
--- a/libdw/memory-access.c
+++ b/libebl/ebldwarftoregno.c
@@ -1,5 +1,5 @@
-/* Out of line functions for memory-access.h macros.
- Copyright (C) 2005, 2006 Red Hat, Inc.
+/* Convert *REGNO as is in DWARF to a lower range.
+ Copyright (C) 2013 Red Hat, Inc.
This file is part of elfutils.
This file is free software; you can redistribute it and/or modify
@@ -29,22 +29,13 @@
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
-#include "libdwP.h"
-#include "memory-access.h"
-uint64_t
-internal_function
-__libdw_get_uleb128 (uint64_t acc, unsigned int i, const unsigned char **addrp)
-{
- unsigned char __b;
- get_uleb128_rest_return (acc, i, addrp);
-}
+#include <libeblP.h>
-int64_t
-internal_function
-__libdw_get_sleb128 (int64_t acc, unsigned int i, const unsigned char **addrp)
+bool
+ebl_dwarf_to_regno (Ebl *ebl, unsigned *regno)
{
- unsigned char __b;
- int64_t _v = acc;
- get_sleb128_rest_return (acc, i, addrp);
+ if (ebl == NULL)
+ return false;
+ return ebl->dwarf_to_regno == NULL ? true : ebl->dwarf_to_regno (ebl, regno);
}
diff --git a/libebl/eblinitreg.c b/libebl/eblinitreg.c
new file mode 100644
index 00000000..8909c500
--- /dev/null
+++ b/libebl/eblinitreg.c
@@ -0,0 +1,51 @@
+/* Fetch live process Dwfl_Frame from PID.
+ 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 <libeblP.h>
+#include <assert.h>
+
+bool
+ebl_set_initial_registers_tid (Ebl *ebl, pid_t tid,
+ ebl_tid_registers_t *setfunc,
+ void *arg)
+{
+ /* Otherwise caller could not allocate THREAD frame of proper size.
+ If set_initial_registers_tid is unsupported then FRAME_NREGS is zero. */
+ assert (ebl->set_initial_registers_tid != NULL);
+ return ebl->set_initial_registers_tid (tid, setfunc, arg);
+}
+
+size_t
+ebl_frame_nregs (Ebl *ebl)
+{
+ return ebl == NULL ? 0 : ebl->frame_nregs;
+}
diff --git a/libebl/eblnormalizepc.c b/libebl/eblnormalizepc.c
new file mode 100644
index 00000000..a5fea77e
--- /dev/null
+++ b/libebl/eblnormalizepc.c
@@ -0,0 +1,40 @@
+/* Modify PC as fetched from inferior data into valid PC.
+ 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 <libeblP.h>
+
+void
+ebl_normalize_pc (Ebl *ebl, Dwarf_Addr *pc)
+{
+ if (ebl != NULL && ebl->normalize_pc != NULL)
+ ebl->normalize_pc (ebl, pc);
+}
diff --git a/libebl/eblopenbackend.c b/libebl/eblopenbackend.c
index ed0c0ffe..c19ae1b2 100644
--- a/libebl/eblopenbackend.c
+++ b/libebl/eblopenbackend.c
@@ -1,5 +1,5 @@
/* Generate ELF backend handle.
- Copyright (C) 2000-2011 Red Hat, Inc.
+ Copyright (C) 2000-2013 Red Hat, Inc.
This file is part of elfutils.
This file is free software; you can redistribute it and/or modify
@@ -131,6 +131,7 @@ static const struct
{ "openrisc", "elf_openrisc", "openrisc", 8, EM_OPENRISC, 0, 0 },
{ "arc", "elf_arc_a5", "arc_a5", 6, EM_ARC_A5, 0, 0 },
{ "xtensa", "elf_xtensa", "xtensa", 6, EM_XTENSA, 0, 0 },
+ { "aarch64", "elf_aarch64", "aarch64", 7, EM_AARCH64, ELFCLASS64, 0 },
};
#define nmachines (sizeof (machines) / sizeof (machines[0]))
diff --git a/libebl/eblresolvesym.c b/libebl/eblresolvesym.c
new file mode 100644
index 00000000..470f6f06
--- /dev/null
+++ b/libebl/eblresolvesym.c
@@ -0,0 +1,43 @@
+/* Resolve a symbol value to an allocated section of the Elf file.
+ 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 <libeblP.h>
+#include <assert.h>
+
+bool
+ebl_resolve_sym_value (Ebl *ebl, GElf_Addr *addr)
+{
+ if (ebl == NULL || ebl->resolve_sym_value == NULL)
+ return false;
+
+ return ebl->resolve_sym_value (ebl, addr);
+}
diff --git a/libebl/eblunwind.c b/libebl/eblunwind.c
new file mode 100644
index 00000000..1251c1b5
--- /dev/null
+++ b/libebl/eblunwind.c
@@ -0,0 +1,43 @@
+/* Get previous frame state for an existing frame state.
+ 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 <libeblP.h>
+
+bool
+ebl_unwind (Ebl *ebl, Dwarf_Addr pc, ebl_tid_registers_t *setfunc,
+ ebl_tid_registers_get_t *getfunc, ebl_pid_memory_read_t *readfunc,
+ void *arg, bool *signal_framep)
+{
+ if (ebl == NULL || ebl->unwind == NULL)
+ return false;
+ return ebl->unwind (ebl, pc, setfunc, getfunc, readfunc, arg, signal_framep);
+}
diff --git a/libebl/libebl.h b/libebl/libebl.h
index cae31c9b..50d6baab 100644
--- a/libebl/libebl.h
+++ b/libebl/libebl.h
@@ -1,5 +1,5 @@
/* Interface for libebl.
- Copyright (C) 2000-2010 Red Hat, Inc.
+ Copyright (C) 2000-2010, 2013 Red Hat, Inc.
This file is part of elfutils.
This file is free software; you can redistribute it and/or modify
@@ -257,6 +257,11 @@ extern int ebl_syscall_abi (Ebl *ebl, int *sp, int *pc,
before each CIE's initial instructions. It should set the
data_alignment_factor member if it affects the initial instructions.
+ The callback should not use the register rules DW_CFA_expression or
+ DW_CFA_val_expression. Defining the CFA using DW_CFA_def_cfa_expression
+ is allowed. This is an implementation detail since register rules
+ store expressions as offsets from the .eh_frame or .debug_frame data.
+
As a shorthand for some common cases, for this instruction stream
we overload some CFI instructions that cannot be used in a CIE:
@@ -351,6 +356,7 @@ typedef struct
uint8_t bits; /* Bits of data for one register. */
uint8_t pad; /* Bytes of padding after register's data. */
Dwarf_Half count; /* Consecutive register numbers here. */
+ bool pc_register;
} Ebl_Register_Location;
/* Non-register data items in core notes. */
@@ -363,6 +369,7 @@ typedef struct
Elf_Type type;
char format;
bool thread_identifier;
+ bool pc_register;
} Ebl_Core_Item;
/* Describe the format of a core file note with the given header and NAME.
@@ -378,6 +385,65 @@ extern int ebl_auxv_info (Ebl *ebl, GElf_Xword a_type,
const char **name, const char **format)
__nonnull_attribute__ (1, 3, 4);
+/* Callback type for ebl_set_initial_registers_tid.
+ Register -1 is mapped to PC (if arch PC has no DWARF number).
+ If FIRSTREG is -1 then NREGS has to be 1. */
+typedef bool (ebl_tid_registers_t) (int firstreg, unsigned nregs,
+ const Dwarf_Word *regs, void *arg)
+ __nonnull_attribute__ (3);
+
+/* Callback to fetch process data from live TID.
+ EBL architecture has to have EBL_FRAME_NREGS > 0, otherwise the
+ backend doesn't support unwinding and this function call may crash. */
+extern bool ebl_set_initial_registers_tid (Ebl *ebl,
+ pid_t tid,
+ ebl_tid_registers_t *setfunc,
+ void *arg)
+ __nonnull_attribute__ (1, 3);
+
+/* Number of registers to allocate for ebl_set_initial_registers_tid.
+ EBL architecture can unwind iff EBL_FRAME_NREGS > 0. */
+extern size_t ebl_frame_nregs (Ebl *ebl)
+ __nonnull_attribute__ (1);
+
+/* Convert *REGNO as is in DWARF to a lower range suitable for
+ Dwarf_Frame->REGS indexing. */
+extern bool ebl_dwarf_to_regno (Ebl *ebl, unsigned *regno)
+ __nonnull_attribute__ (1, 2);
+
+/* Modify PC as fetched from inferior data into valid PC. */
+extern void ebl_normalize_pc (Ebl *ebl, Dwarf_Addr *pc)
+ __nonnull_attribute__ (1, 2);
+
+/* Callback type for ebl_unwind's parameter getfunc. */
+typedef bool (ebl_tid_registers_get_t) (int firstreg, unsigned nregs,
+ Dwarf_Word *regs, void *arg)
+ __nonnull_attribute__ (3);
+
+/* Callback type for ebl_unwind's parameter readfunc. */
+typedef bool (ebl_pid_memory_read_t) (Dwarf_Addr addr, Dwarf_Word *data,
+ void *arg)
+ __nonnull_attribute__ (3);
+
+/* Get previous frame state for an existing frame state. Method is called only
+ if unwinder could not find CFI for current PC. PC is for the
+ existing frame. SETFUNC sets register in the previous frame. GETFUNC gets
+ register from the existing frame. Note that GETFUNC vs. SETFUNC act on
+ a disjunct set of registers. READFUNC reads memory. ARG has to be passed
+ for SETFUNC, GETFUNC and READFUNC. *SIGNAL_FRAMEP is initialized to false,
+ it can be set to true if existing frame is a signal frame. SIGNAL_FRAMEP is
+ never NULL. */
+extern bool ebl_unwind (Ebl *ebl, Dwarf_Addr pc, ebl_tid_registers_t *setfunc,
+ ebl_tid_registers_get_t *getfunc,
+ ebl_pid_memory_read_t *readfunc, void *arg,
+ bool *signal_framep)
+ __nonnull_attribute__ (1, 3, 4, 5, 7);
+
+/* Returns true if the value can be resolved to an address in an
+ allocated section, which will be returned in *ADDR
+ (e.g. function descriptor resolving) */
+extern bool ebl_resolve_sym_value (Ebl *ebl, GElf_Addr *addr)
+ __nonnull_attribute__ (2);
#ifdef __cplusplus
}
diff --git a/libebl/libeblP.h b/libebl/libeblP.h
index 5ec26a4b..f91c2a0d 100644
--- a/libebl/libeblP.h
+++ b/libebl/libeblP.h
@@ -1,5 +1,5 @@
/* Internal definitions for interface for libebl.
- Copyright (C) 2000-2009 Red Hat, Inc.
+ Copyright (C) 2000-2009, 2013 Red Hat, Inc.
This file is part of elfutils.
This file is free software; you can redistribute it and/or modify
@@ -60,6 +60,15 @@ struct ebl
/* Size of entry in Sysv-style hash table. */
int sysvhash_entrysize;
+ /* Number of registers to allocate for ebl_set_initial_registers_tid.
+ Ebl architecture can unwind iff FRAME_NREGS > 0. */
+ size_t frame_nregs;
+
+ /* Function descriptor load address and table as used by
+ ebl_resolve_sym_value if available for this arch. */
+ GElf_Addr fd_addr;
+ Elf_Data *fd_data;
+
/* Internal data. */
void *dlhandle;
};
diff --git a/libelf/ChangeLog b/libelf/ChangeLog
index 7334179c..bf3fa193 100644
--- a/libelf/ChangeLog
+++ b/libelf/ChangeLog
@@ -1,3 +1,21 @@
+2013-11-08 Mark Wielaard <[email protected]>
+
+ * elf32_updatefile.c (elfXX_updatemmap): Only memcpy ehdr when not
+ already directly mmapped.
+
+2013-11-05 Mark Wielaard <[email protected]>
+
+ * elf32_updatefile.c (elfXX_updatefile): Copy all section headers
+ if elf->flags dirty.
+
+2013-11-01 Michael Forney <[email protected]>
+
+ * Makefile.am: Use READELF.
+
+2013-10-01 Petr Machata <[email protected]>
+
+ * elf.h: Update from glibc.
+
2013-06-17 Petr Machata <[email protected]>
* elf.h: Update from glibc.
diff --git a/libelf/Makefile.am b/libelf/Makefile.am
index 5903ea86..4646fbae 100644
--- a/libelf/Makefile.am
+++ b/libelf/Makefile.am
@@ -106,7 +106,7 @@ libelf.so: libelf_pic.a libelf.map
$(LINK) -shared -o $@ -Wl,--whole-archive,$<,--no-whole-archive \
-Wl,--version-script,$(srcdir)/libelf.map,--no-undefined \
-Wl,--soname,$@.$(VERSION),-z,defs,-z,relro $(libelf_so_LDLIBS)
- if readelf -d $@ | fgrep -q TEXTREL; then exit 1; fi
+ if $(READELF) -d $@ | fgrep -q TEXTREL; then exit 1; fi
ln -fs $@ $@.$(VERSION)
install: install-am libelf.so
diff --git a/libelf/elf.h b/libelf/elf.h
index d096a97e..a05ea3b6 100644
--- a/libelf/elf.h
+++ b/libelf/elf.h
@@ -251,6 +251,7 @@ typedef struct
#define EM_XTENSA 94 /* Tensilica Xtensa Architecture */
#define EM_AARCH64 183 /* ARM AARCH64 */
#define EM_TILEPRO 188 /* Tilera TILEPro */
+#define EM_MICROBLAZE 189 /* Xilinx MicroBlaze */
#define EM_TILEGX 191 /* Tilera TILE-Gx */
#define EM_NUM 192
@@ -810,7 +811,7 @@ typedef struct
#define DF_1_EDITED 0x00200000 /* Object is modified after built. */
#define DF_1_NORELOC 0x00400000
#define DF_1_SYMINTPOSE 0x00800000 /* Object has individual interposers. */
-#define DF_1_GLOBAUDIT 0x01000000 /* Global auditin required. */
+#define DF_1_GLOBAUDIT 0x01000000 /* Global auditing required. */
#define DF_1_SINGLETON 0x02000000 /* Singleton symbols are used. */
/* Flags for the feature selection in DT_FEATURE_1. */
@@ -992,7 +993,7 @@ typedef struct
/* Some more special a_type values describing the hardware. */
#define AT_PLATFORM 15 /* String identifying platform. */
-#define AT_HWCAP 16 /* Machine dependent hints about
+#define AT_HWCAP 16 /* Machine-dependent hints about
processor capabilities. */
/* This entry gives some information about the FPU initialization
@@ -1014,6 +1015,9 @@ typedef struct
#define AT_RANDOM 25 /* Address of 16 random bytes. */
+#define AT_HWCAP2 26 /* More machine-dependent hints about
+ processor capabilities. */
+
#define AT_EXECFN 31 /* Filename of executable. */
/* Pointer to the global system page used for system calls and other
@@ -1379,6 +1383,7 @@ typedef struct
#define EF_MIPS_64BIT_WHIRL 16
#define EF_MIPS_ABI2 32
#define EF_MIPS_ABI_ON32 64
+#define EF_MIPS_NAN2008 1024 /* Uses IEEE 754-2008 NaN encoding. */
#define EF_MIPS_ARCH 0xf0000000 /* MIPS architecture level. */
/* Legal values for MIPS architecture level. */
@@ -2331,6 +2336,117 @@ typedef Elf32_Addr Elf32_Conflict;
#define R_AARCH64_NONE 0 /* No relocation. */
#define R_AARCH64_ABS64 257 /* Direct 64 bit. */
#define R_AARCH64_ABS32 258 /* Direct 32 bit. */
+#define R_AARCH64_ABS16 259 /* Direct 16-bit. */
+#define R_AARCH64_PREL64 260 /* PC-relative 64-bit. */
+#define R_AARCH64_PREL32 261 /* PC-relative 32-bit. */
+#define R_AARCH64_PREL16 262 /* PC-relative 16-bit. */
+#define R_AARCH64_MOVW_UABS_G0 263 /* Dir. MOVZ imm. from bits 15:0. */
+#define R_AARCH64_MOVW_UABS_G0_NC 264 /* Likewise for MOVK; no check. */
+#define R_AARCH64_MOVW_UABS_G1 265 /* Dir. MOVZ imm. from bits 31:16. */
+#define R_AARCH64_MOVW_UABS_G1_NC 266 /* Likewise for MOVK; no check. */
+#define R_AARCH64_MOVW_UABS_G2 267 /* Dir. MOVZ imm. from bits 47:32. */
+#define R_AARCH64_MOVW_UABS_G2_NC 268 /* Likewise for MOVK; no check. */
+#define R_AARCH64_MOVW_UABS_G3 269 /* Dir. MOV{K,Z} imm. from 63:48. */
+#define R_AARCH64_MOVW_SABS_G0 270 /* Dir. MOV{N,Z} imm. from 15:0. */
+#define R_AARCH64_MOVW_SABS_G1 271 /* Dir. MOV{N,Z} imm. from 31:16. */
+#define R_AARCH64_MOVW_SABS_G2 272 /* Dir. MOV{N,Z} imm. from 47:32. */
+#define R_AARCH64_LD_PREL_LO19 273 /* PC-rel. LD imm. from bits 20:2. */
+#define R_AARCH64_ADR_PREL_LO21 274 /* PC-rel. ADR imm. from bits 20:0. */
+#define R_AARCH64_ADR_PREL_PG_HI21 275 /* Page-rel. ADRP imm. from 32:12. */
+#define R_AARCH64_ADR_PREL_PG_HI21_NC 276 /* Likewise; no overflow check. */
+#define R_AARCH64_ADD_ABS_LO12_NC 277 /* Dir. ADD imm. from bits 11:0. */
+#define R_AARCH64_LDST8_ABS_LO12_NC 278 /* Likewise for LD/ST; no check. */
+#define R_AARCH64_TSTBR14 279 /* PC-rel. TBZ/TBNZ imm. from 15:2. */
+#define R_AARCH64_CONDBR19 280 /* PC-rel. cond. br. imm. from 20:2. */
+#define R_AARCH64_JUMP26 282 /* PC-rel. B imm. from bits 27:2. */
+#define R_AARCH64_CALL26 283 /* Likewise for CALL. */
+#define R_AARCH64_LDST16_ABS_LO12_NC 284 /* Dir. ADD imm. from bits 11:1. */
+#define R_AARCH64_LDST32_ABS_LO12_NC 285 /* Likewise for bits 11:2. */
+#define R_AARCH64_LDST64_ABS_LO12_NC 286 /* Likewise for bits 11:3. */
+#define R_AARCH64_MOVW_PREL_G0 287 /* PC-rel. MOV{N,Z} imm. from 15:0. */
+#define R_AARCH64_MOVW_PREL_G0_NC 288 /* Likewise for MOVK; no check. */
+#define R_AARCH64_MOVW_PREL_G1 289 /* PC-rel. MOV{N,Z} imm. from 31:16. */
+#define R_AARCH64_MOVW_PREL_G1_NC 290 /* Likewise for MOVK; no check. */
+#define R_AARCH64_MOVW_PREL_G2 291 /* PC-rel. MOV{N,Z} imm. from 47:32. */
+#define R_AARCH64_MOVW_PREL_G2_NC 292 /* Likewise for MOVK; no check. */
+#define R_AARCH64_MOVW_PREL_G3 293 /* PC-rel. MOV{N,Z} imm. from 63:48. */
+#define R_AARCH64_LDST128_ABS_LO12_NC 299 /* Dir. ADD imm. from bits 11:4. */
+#define R_AARCH64_MOVW_GOTOFF_G0 300 /* GOT-rel. off. MOV{N,Z} imm. 15:0. */
+#define R_AARCH64_MOVW_GOTOFF_G0_NC 301 /* Likewise for MOVK; no check. */
+#define R_AARCH64_MOVW_GOTOFF_G1 302 /* GOT-rel. o. MOV{N,Z} imm. 31:16. */
+#define R_AARCH64_MOVW_GOTOFF_G1_NC 303 /* Likewise for MOVK; no check. */
+#define R_AARCH64_MOVW_GOTOFF_G2 304 /* GOT-rel. o. MOV{N,Z} imm. 47:32. */
+#define R_AARCH64_MOVW_GOTOFF_G2_NC 305 /* Likewise for MOVK; no check. */
+#define R_AARCH64_MOVW_GOTOFF_G3 306 /* GOT-rel. o. MOV{N,Z} imm. 63:48. */
+#define R_AARCH64_GOTREL64 307 /* GOT-relative 64-bit. */
+#define R_AARCH64_GOTREL32 308 /* GOT-relative 32-bit. */
+#define R_AARCH64_GOT_LD_PREL19 309 /* PC-rel. GOT off. load imm. 20:2. */
+#define R_AARCH64_LD64_GOTOFF_LO15 310 /* GOT-rel. off. LD/ST imm. 14:3. */
+#define R_AARCH64_ADR_GOT_PAGE 311 /* P-page-rel. GOT off. ADRP 32:12. */
+#define R_AARCH64_LD64_GOT_LO12_NC 312 /* Dir. GOT off. LD/ST imm. 11:3. */
+#define R_AARCH64_LD64_GOTPAGE_LO15 313 /* GOT-page-rel. GOT off. LD/ST 14:3 */
+#define R_AARCH64_TLSGD_ADR_PREL21 512 /* PC-relative ADR imm. 20:0. */
+#define R_AARCH64_TLSGD_ADR_PAGE21 513 /* page-rel. ADRP imm. 32:12. */
+#define R_AARCH64_TLSGD_ADD_LO12_NC 514 /* direct ADD imm. from 11:0. */
+#define R_AARCH64_TLSGD_MOVW_G1 515 /* GOT-rel. MOV{N,Z} 31:16. */
+#define R_AARCH64_TLSGD_MOVW_G0_NC 516 /* GOT-rel. MOVK imm. 15:0. */
+#define R_AARCH64_TLSLD_ADR_PREL21 517 /* Like 512; local dynamic model. */
+#define R_AARCH64_TLSLD_ADR_PAGE21 518 /* Like 513; local dynamic model. */
+#define R_AARCH64_TLSLD_ADD_LO12_NC 519 /* Like 514; local dynamic model. */
+#define R_AARCH64_TLSLD_MOVW_G1 520 /* Like 515; local dynamic model. */
+#define R_AARCH64_TLSLD_MOVW_G0_NC 521 /* Like 516; local dynamic model. */
+#define R_AARCH64_TLSLD_LD_PREL19 522 /* TLS PC-rel. load imm. 20:2. */
+#define R_AARCH64_TLSLD_MOVW_DTPREL_G2 523 /* TLS DTP-rel. MOV{N,Z} 47:32. */
+#define R_AARCH64_TLSLD_MOVW_DTPREL_G1 524 /* TLS DTP-rel. MOV{N,Z} 31:16. */
+#define R_AARCH64_TLSLD_MOVW_DTPREL_G1_NC 525 /* Likewise; MOVK; no check. */
+#define R_AARCH64_TLSLD_MOVW_DTPREL_G0 526 /* TLS DTP-rel. MOV{N,Z} 15:0. */
+#define R_AARCH64_TLSLD_MOVW_DTPREL_G0_NC 527 /* Likewise; MOVK; no check. */
+#define R_AARCH64_TLSLD_ADD_DTPREL_HI12 528 /* DTP-rel. ADD imm. from 23:12. */
+#define R_AARCH64_TLSLD_ADD_DTPREL_LO12 529 /* DTP-rel. ADD imm. from 11:0. */
+#define R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC 530 /* Likewise; no ovfl. check. */
+#define R_AARCH64_TLSLD_LDST8_DTPREL_LO12 531 /* DTP-rel. LD/ST imm. 11:0. */
+#define R_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC 532 /* Likewise; no check. */
+#define R_AARCH64_TLSLD_LDST16_DTPREL_LO12 533 /* DTP-rel. LD/ST imm. 11:1. */
+#define R_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC 534 /* Likewise; no check. */
+#define R_AARCH64_TLSLD_LDST32_DTPREL_LO12 535 /* DTP-rel. LD/ST imm. 11:2. */
+#define R_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC 536 /* Likewise; no check. */
+#define R_AARCH64_TLSLD_LDST64_DTPREL_LO12 537 /* DTP-rel. LD/ST imm. 11:3. */
+#define R_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC 538 /* Likewise; no check. */
+#define R_AARCH64_TLSIE_MOVW_GOTTPREL_G1 539 /* GOT-rel. MOV{N,Z} 31:16. */
+#define R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC 540 /* GOT-rel. MOVK 15:0. */
+#define R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21 541 /* Page-rel. ADRP 32:12. */
+#define R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC 542 /* Direct LD off. 11:3. */
+#define R_AARCH64_TLSIE_LD_GOTTPREL_PREL19 543 /* PC-rel. load imm. 20:2. */
+#define R_AARCH64_TLSLE_MOVW_TPREL_G2 544 /* TLS TP-rel. MOV{N,Z} 47:32. */
+#define R_AARCH64_TLSLE_MOVW_TPREL_G1 545 /* TLS TP-rel. MOV{N,Z} 31:16. */
+#define R_AARCH64_TLSLE_MOVW_TPREL_G1_NC 546 /* Likewise; MOVK; no check. */
+#define R_AARCH64_TLSLE_MOVW_TPREL_G0 547 /* TLS TP-rel. MOV{N,Z} 15:0. */
+#define R_AARCH64_TLSLE_MOVW_TPREL_G0_NC 548 /* Likewise; MOVK; no check. */
+#define R_AARCH64_TLSLE_ADD_TPREL_HI12 549 /* TP-rel. ADD imm. 23:12. */
+#define R_AARCH64_TLSLE_ADD_TPREL_LO12 550 /* TP-rel. ADD imm. 11:0. */
+#define R_AARCH64_TLSLE_ADD_TPREL_LO12_NC 551 /* Likewise; no ovfl. check. */
+#define R_AARCH64_TLSLE_LDST8_TPREL_LO12 552 /* TP-rel. LD/ST off. 11:0. */
+#define R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC 553 /* Likewise; no ovfl. check. */
+#define R_AARCH64_TLSLE_LDST16_TPREL_LO12 554 /* TP-rel. LD/ST off. 11:1. */
+#define R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC 555 /* Likewise; no check. */
+#define R_AARCH64_TLSLE_LDST32_TPREL_LO12 556 /* TP-rel. LD/ST off. 11:2. */
+#define R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC 557 /* Likewise; no check. */
+#define R_AARCH64_TLSLE_LDST64_TPREL_LO12 558 /* TP-rel. LD/ST off. 11:3. */
+#define R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC 559 /* Likewise; no check. */
+#define R_AARCH64_TLSDESC_LD_PREL19 560 /* PC-rel. load immediate 20:2. */
+#define R_AARCH64_TLSDESC_ADR_PREL21 561 /* PC-rel. ADR immediate 20:0. */
+#define R_AARCH64_TLSDESC_ADR_PAGE21 562 /* Page-rel. ADRP imm. 32:12. */
+#define R_AARCH64_TLSDESC_LD64_LO12 563 /* Direct LD off. from 11:3. */
+#define R_AARCH64_TLSDESC_ADD_LO12 564 /* Direct ADD imm. from 11:0. */
+#define R_AARCH64_TLSDESC_OFF_G1 565 /* GOT-rel. MOV{N,Z} imm. 31:16. */
+#define R_AARCH64_TLSDESC_OFF_G0_NC 566 /* GOT-rel. MOVK imm. 15:0; no ck. */
+#define R_AARCH64_TLSDESC_LDR 567 /* Relax LDR. */
+#define R_AARCH64_TLSDESC_ADD 568 /* Relax ADD. */
+#define R_AARCH64_TLSDESC_CALL 569 /* Relax BLR. */
+#define R_AARCH64_TLSLE_LDST128_TPREL_LO12 570 /* TP-rel. LD/ST off. 11:4. */
+#define R_AARCH64_TLSLE_LDST128_TPREL_LO12_NC 571 /* Likewise; no check. */
+#define R_AARCH64_TLSLD_LDST128_DTPREL_LO12 572 /* DTP-rel. LD/ST imm. 11:4. */
+#define R_AARCH64_TLSLD_LDST128_DTPREL_LO12_NC 573 /* Likewise; no check. */
#define R_AARCH64_COPY 1024 /* Copy symbol at runtime. */
#define R_AARCH64_GLOB_DAT 1025 /* Create GOT entry. */
#define R_AARCH64_JUMP_SLOT 1026 /* Create PLT entry. */
@@ -2339,6 +2455,7 @@ typedef Elf32_Addr Elf32_Conflict;
#define R_AARCH64_TLS_DTPREL64 1029 /* Module-relative offset, 64 bit. */
#define R_AARCH64_TLS_TPREL64 1030 /* TP-relative offset, 64 bit. */
#define R_AARCH64_TLSDESC 1031 /* TLS Descriptor. */
+#define R_AARCH64_IRELATIVE 1032 /* STT_GNU_IFUNC relocation. */
/* ARM relocs. */
@@ -2955,6 +3072,37 @@ typedef Elf32_Addr Elf32_Conflict;
#define R_M32R_GOTOFF_LO 64 /* Low 16 bit offset to GOT */
#define R_M32R_NUM 256 /* Keep this the last entry. */
+/* MicroBlaze relocations */
+#define R_MICROBLAZE_NONE 0 /* No reloc. */
+#define R_MICROBLAZE_32 1 /* Direct 32 bit. */
+#define R_MICROBLAZE_32_PCREL 2 /* PC relative 32 bit. */
+#define R_MICROBLAZE_64_PCREL 3 /* PC relative 64 bit. */
+#define R_MICROBLAZE_32_PCREL_LO 4 /* Low 16 bits of PCREL32. */
+#define R_MICROBLAZE_64 5 /* Direct 64 bit. */
+#define R_MICROBLAZE_32_LO 6 /* Low 16 bit. */
+#define R_MICROBLAZE_SRO32 7 /* Read-only small data area. */
+#define R_MICROBLAZE_SRW32 8 /* Read-write small data area. */
+#define R_MICROBLAZE_64_NONE 9 /* No reloc. */
+#define R_MICROBLAZE_32_SYM_OP_SYM 10 /* Symbol Op Symbol relocation. */
+#define R_MICROBLAZE_GNU_VTINHERIT 11 /* GNU C++ vtable hierarchy. */
+#define R_MICROBLAZE_GNU_VTENTRY 12 /* GNU C++ vtable member usage. */
+#define R_MICROBLAZE_GOTPC_64 13 /* PC-relative GOT offset. */
+#define R_MICROBLAZE_GOT_64 14 /* GOT entry offset. */
+#define R_MICROBLAZE_PLT_64 15 /* PLT offset (PC-relative). */
+#define R_MICROBLAZE_REL 16 /* Adjust by program base. */
+#define R_MICROBLAZE_JUMP_SLOT 17 /* Create PLT entry. */
+#define R_MICROBLAZE_GLOB_DAT 18 /* Create GOT entry. */
+#define R_MICROBLAZE_GOTOFF_64 19 /* 64 bit offset to GOT. */
+#define R_MICROBLAZE_GOTOFF_32 20 /* 32 bit offset to GOT. */
+#define R_MICROBLAZE_COPY 21 /* Runtime copy. */
+#define R_MICROBLAZE_TLS 22 /* TLS Reloc. */
+#define R_MICROBLAZE_TLSGD 23 /* TLS General Dynamic. */
+#define R_MICROBLAZE_TLSLD 24 /* TLS Local Dynamic. */
+#define R_MICROBLAZE_TLSDTPMOD32 25 /* TLS Module ID. */
+#define R_MICROBLAZE_TLSDTPREL32 26 /* TLS Offset Within TLS Block. */
+#define R_MICROBLAZE_TLSDTPREL64 27 /* TLS Offset Within TLS Block. */
+#define R_MICROBLAZE_TLSGOTTPREL32 28 /* TLS Offset From Thread Pointer. */
+#define R_MICROBLAZE_TLSTPREL32 29 /* TLS Offset From Thread Pointer. */
/* TILEPro relocations. */
#define R_TILEPRO_NONE 0 /* No reloc */
diff --git a/libelf/elf32_updatefile.c b/libelf/elf32_updatefile.c
index 871de0a0..2e59849d 100644
--- a/libelf/elf32_updatefile.c
+++ b/libelf/elf32_updatefile.c
@@ -133,7 +133,7 @@ __elfw2(LIBELFBITS,updatemmap) (Elf *elf, int change_bo, size_t shnum)
(*fctp) ((char *) elf->map_address + elf->start_offset, ehdr,
sizeof (ElfW2(LIBELFBITS,Ehdr)), 1);
}
- else
+ else if (elf->map_address + elf->start_offset != ehdr)
memcpy (elf->map_address + elf->start_offset, ehdr,
sizeof (ElfW2(LIBELFBITS,Ehdr)));
@@ -640,7 +640,8 @@ __elfw2(LIBELFBITS,updatefile) (Elf *elf, int change_bo, size_t shnum)
#endif
ElfW2(LIBELFBITS,Shdr) *shdr_data;
- if (change_bo || elf->state.ELFW(elf,LIBELFBITS).shdr == NULL)
+ if (change_bo || elf->state.ELFW(elf,LIBELFBITS).shdr == NULL
+ || (elf->flags & ELF_F_DIRTY))
shdr_data = (ElfW2(LIBELFBITS,Shdr) *)
alloca (shnum * sizeof (ElfW2(LIBELFBITS,Shdr)));
else
@@ -771,7 +772,8 @@ __elfw2(LIBELFBITS,updatefile) (Elf *elf, int change_bo, size_t shnum)
(*shdr_fctp) (&shdr_data[scn->index],
scn->shdr.ELFW(e,LIBELFBITS),
sizeof (ElfW2(LIBELFBITS,Shdr)), 1);
- else if (elf->state.ELFW(elf,LIBELFBITS).shdr == NULL)
+ else if (elf->state.ELFW(elf,LIBELFBITS).shdr == NULL
+ || (elf->flags & ELF_F_DIRTY))
memcpy (&shdr_data[scn->index], scn->shdr.ELFW(e,LIBELFBITS),
sizeof (ElfW2(LIBELFBITS,Shdr)));
diff --git a/m4/ChangeLog b/m4/ChangeLog
index f82b0ca7..c950e54b 100644
--- a/m4/ChangeLog
+++ b/m4/ChangeLog
@@ -1,3 +1,12 @@
+2013-12-02 Jan Kratochvil <[email protected]>
+
+ * biarch.m4 (utrace_BIARCH): Call AC_MSG_WARN if !BIARCH.
+
+2013-11-07 Roland McGrath <[email protected]>
+ Jan Kratochvil <[email protected]>
+
+ * biarch.m4: New file.
+
2013-04-24 Mark Wielaard <[email protected]>
* gettext.m4: Upgrade to gettext-0.18.2.
diff --git a/m4/biarch.m4 b/m4/biarch.m4
new file mode 100644
index 00000000..04c8dbab
--- /dev/null
+++ b/m4/biarch.m4
@@ -0,0 +1,47 @@
+AC_DEFUN([utrace_CC_m32], [dnl
+AC_CACHE_CHECK([$CC option for 32-bit word size], utrace_cv_CC_m32, [dnl
+save_CC="$CC"
+utrace_cv_CC_m32=none
+for ut_try in -m32 -m31; do
+ [CC=`echo "$save_CC" | sed 's/ -m[36][241]//'`" $ut_try"]
+ AC_COMPILE_IFELSE([AC_LANG_SOURCE([[int foo (void) { return 1; }]])],
+ [utrace_cv_CC_m32=$ut_try])
+ test x$utrace_cv_CC_m32 = xnone || break
+done
+CC="$save_CC"])])
+
+AC_DEFUN([utrace_HOST64], [AC_REQUIRE([utrace_CC_m32])
+AS_IF([test x$utrace_cv_CC_m32 != xnone], [dnl
+AC_CACHE_CHECK([for 64-bit host], utrace_cv_host64, [dnl
+AC_EGREP_CPP([@utrace_host64@], [#include <stdint.h>
+#if (UINTPTR_MAX > 0xffffffffUL)
+@utrace_host64@
+#endif],
+ utrace_cv_host64=yes, utrace_cv_host64=no)])
+AS_IF([test $utrace_cv_host64 = no],
+ [utrace_biarch=-m64 utrace_thisarch=$utrace_cv_CC_m32],
+ [utrace_biarch=$utrace_cv_CC_m32 utrace_thisarch=-m64])
+
+biarch_CC=`echo "$CC" | sed "s/ *${utrace_thisarch}//"`
+biarch_CC="$biarch_CC $utrace_biarch"])])
+
+AC_DEFUN([utrace_BIARCH], [AC_REQUIRE([utrace_HOST64])
+utrace_biarch_forced=no
+AC_ARG_WITH([biarch],
+ AC_HELP_STRING([--with-biarch],
+ [enable biarch tests despite build problems]),
+ [AS_IF([test "x$with_biarch" != xno], [utrace_biarch_forced=yes])])
+AS_IF([test $utrace_biarch_forced = yes], [dnl
+utrace_cv_cc_biarch=yes
+AC_MSG_NOTICE([enabling biarch tests regardless using $biarch_CC])], [dnl
+AS_IF([test x$utrace_cv_CC_m32 != xnone], [dnl
+AC_CACHE_CHECK([whether $biarch_CC makes executables we can run],
+ utrace_cv_cc_biarch, [dnl
+save_CC="$CC"
+CC="$biarch_CC"
+AC_RUN_IFELSE([AC_LANG_PROGRAM([], [])],
+ utrace_cv_cc_biarch=yes, utrace_cv_cc_biarch=no)
+CC="$save_CC"])], [utrace_cv_cc_biarch=no])
+AS_IF([test $utrace_cv_cc_biarch != yes], [dnl
+AC_MSG_WARN([not running biarch tests, $biarch_CC does not work])])])
+AM_CONDITIONAL(BIARCH, [test $utrace_cv_cc_biarch = yes])])
diff --git a/po/ChangeLog b/po/ChangeLog
index 30183024..120507b0 100644
--- a/po/ChangeLog
+++ b/po/ChangeLog
@@ -1,3 +1,7 @@
+2014-01-03 Mark Wielaard <[email protected]>
+
+ * *.po: Update for 0.158.
+
2013-07-30 Mark Wielaard <[email protected]>
* *.po: Update for 0.157.
diff --git a/po/de.po b/po/de.po
index b04b730d..1149339a 100644
--- a/po/de.po
+++ b/po/de.po
@@ -11,7 +11,7 @@ msgid ""
msgstr ""
"Project-Id-Version: elfutils VERSION\n"
"Report-Msgid-Bugs-To: http://bugzilla.redhat.com/\n"
-"POT-Creation-Date: 2013-09-30 13:52+0200\n"
+"POT-Creation-Date: 2013-12-31 14:01+0100\n"
"PO-Revision-Date: 2009-06-29 15:15+0200\n"
"Last-Translator: Michael Münch <[email protected]>\n"
"Language-Team: German\n"
@@ -28,12 +28,12 @@ msgstr ""
msgid "memory exhausted"
msgstr "Kein Speicher mehr verfügbar"
-#: libasm/asm_error.c:65 libdw/dwarf_error.c:58 libdwfl/libdwflP.h:49
+#: libasm/asm_error.c:65 libdw/dwarf_error.c:58 libdwfl/libdwflP.h:51
#: libelf/elf_error.c:60
msgid "no error"
msgstr "kein Fehler"
-#: libasm/asm_error.c:66 libdw/dwarf_error.c:67 libdwfl/libdwflP.h:51
+#: libasm/asm_error.c:66 libdw/dwarf_error.c:67 libdwfl/libdwflP.h:53
#: libelf/elf_error.c:91
msgid "out of memory"
msgstr "nicht genügend Speicher"
@@ -72,7 +72,7 @@ msgstr "Fehler bei Datenausgabe"
msgid "no backend support available"
msgstr "keine Backend-Unterstützung verfügbar"
-#: libasm/asm_error.c:84 libdw/dwarf_error.c:59 libdwfl/libdwflP.h:50
+#: libasm/asm_error.c:84 libdw/dwarf_error.c:59 libdwfl/libdwflP.h:52
#: libelf/elf_error.c:63
msgid "unknown error"
msgstr "unbekannter Fehler"
@@ -169,7 +169,7 @@ msgstr "Ungültige DWARF Version"
msgid "invalid directory index"
msgstr "ungültiger Verzeichnisindex"
-#: libdw/dwarf_error.c:84 libdwfl/libdwflP.h:70
+#: libdw/dwarf_error.c:84 libdwfl/libdwflP.h:72
msgid "address out of range"
msgstr "Außerhalb des Adressbereiches"
@@ -189,7 +189,7 @@ msgstr "Ungültiger Zeilenindex"
msgid "invalid address range index"
msgstr "Ungültiger Adressbereichs Index"
-#: libdw/dwarf_error.c:89 libdwfl/libdwflP.h:71
+#: libdw/dwarf_error.c:89 libdwfl/libdwflP.h:73
msgid "no matching address range"
msgstr "Kein passender Adressbereich"
@@ -248,134 +248,199 @@ msgstr "Kernel mit allen Modulen"
msgid "Search path for separate debuginfo files"
msgstr "Dateisuchpfad für separate Debug-Informationen"
-#: libdwfl/argp-std.c:183
+#: libdwfl/argp-std.c:157
msgid "only one of -e, -p, -k, -K, or --core allowed"
msgstr "Nur eine Option von -e, -p, -k, -K, oder --core erlaubt"
-#: libdwfl/argp-std.c:252
+#: libdwfl/argp-std.c:177
+#, fuzzy
+msgid "cannot attach to process"
+msgstr "Kann Suchbaum nicht erstellen"
+
+#: libdwfl/argp-std.c:231
msgid "cannot load kernel symbols"
msgstr "Konnte Kernel Symbole nicht laden"
-#: libdwfl/argp-std.c:256
+#: libdwfl/argp-std.c:235
msgid "cannot find kernel modules"
msgstr "Konnte Kernel Module nicht finden"
-#: libdwfl/argp-std.c:273
+#: libdwfl/argp-std.c:252
msgid "cannot find kernel or modules"
msgstr "Konnte Kernel oder Module nicht finden"
-#: libdwfl/argp-std.c:315
+#: libdwfl/argp-std.c:291
#, c-format
msgid "cannot read ELF core file: %s"
msgstr "Konnte ELF Kerndatei %s nicht lesen"
-#: libdwfl/argp-std.c:333
+#: libdwfl/argp-std.c:307
+#, fuzzy
+msgid "cannot attach to core"
+msgstr "Kann Suchbaum nicht erstellen"
+
+#: libdwfl/argp-std.c:314
msgid "No modules recognized in core file"
msgstr "Keine Module in der Kerndatei gefunden"
-#: libdwfl/libdwflP.h:52
+#: libdwfl/libdwflP.h:54
msgid "See errno"
msgstr ""
-#: libdwfl/libdwflP.h:53
+#: libdwfl/libdwflP.h:55
msgid "See elf_errno"
msgstr ""
-#: libdwfl/libdwflP.h:54
+#: libdwfl/libdwflP.h:56
msgid "See dwarf_errno"
msgstr ""
-#: libdwfl/libdwflP.h:55
+#: libdwfl/libdwflP.h:57
msgid "See ebl_errno (XXX missing)"
msgstr ""
-#: libdwfl/libdwflP.h:56
+#: libdwfl/libdwflP.h:58
msgid "gzip decompression failed"
msgstr ""
-#: libdwfl/libdwflP.h:57
+#: libdwfl/libdwflP.h:59
msgid "bzip2 decompression failed"
msgstr ""
-#: libdwfl/libdwflP.h:58
+#: libdwfl/libdwflP.h:60
msgid "LZMA decompression failed"
msgstr ""
-#: libdwfl/libdwflP.h:59
+#: libdwfl/libdwflP.h:61
msgid "no support library found for machine"
msgstr ""
-#: libdwfl/libdwflP.h:60
+#: libdwfl/libdwflP.h:62
msgid "Callbacks missing for ET_REL file"
msgstr ""
-#: libdwfl/libdwflP.h:61
+#: libdwfl/libdwflP.h:63
msgid "Unsupported relocation type"
msgstr ""
-#: libdwfl/libdwflP.h:62
+#: libdwfl/libdwflP.h:64
msgid "r_offset is bogus"
msgstr ""
-#: libdwfl/libdwflP.h:63 libelf/elf_error.c:111 libelf/elf_error.c:171
+#: libdwfl/libdwflP.h:65 libelf/elf_error.c:111 libelf/elf_error.c:171
msgid "offset out of range"
msgstr "Offset ausserhalb des Bereichs"
-#: libdwfl/libdwflP.h:64
+#: libdwfl/libdwflP.h:66
#, fuzzy
msgid "relocation refers to undefined symbol"
msgstr "Zeige Grösse der definierten Symbole"
-#: libdwfl/libdwflP.h:65
+#: libdwfl/libdwflP.h:67
msgid "Callback returned failure"
msgstr ""
-#: libdwfl/libdwflP.h:66
+#: libdwfl/libdwflP.h:68
#, fuzzy
msgid "No DWARF information found"
msgstr "keine DWARF Information"
-#: libdwfl/libdwflP.h:67
+#: libdwfl/libdwflP.h:69
msgid "No symbol table found"
msgstr ""
-#: libdwfl/libdwflP.h:68
+#: libdwfl/libdwflP.h:70
#, fuzzy
msgid "No ELF program headers"
msgstr "Programm-Köpfe anzeigen"
-#: libdwfl/libdwflP.h:69
+#: libdwfl/libdwflP.h:71
msgid "address range overlaps an existing module"
msgstr ""
-#: libdwfl/libdwflP.h:72
+#: libdwfl/libdwflP.h:74
msgid "image truncated"
msgstr ""
-#: libdwfl/libdwflP.h:73
+#: libdwfl/libdwflP.h:75
#, fuzzy
msgid "ELF file opened"
msgstr "keine ELF Datei"
-#: libdwfl/libdwflP.h:74
+#: libdwfl/libdwflP.h:76
#, fuzzy
msgid "not a valid ELF file"
msgstr "Ungültige ELF Datei"
-#: libdwfl/libdwflP.h:75
+#: libdwfl/libdwflP.h:77
#, fuzzy
msgid "cannot handle DWARF type description"
msgstr "konnte Elf-Deskriptor nicht erzeugen: %s"
-#: libdwfl/libdwflP.h:76
+#: libdwfl/libdwflP.h:78
msgid "ELF file does not match build ID"
msgstr ""
-#: libdwfl/libdwflP.h:77
+#: libdwfl/libdwflP.h:79
#, fuzzy
msgid "corrupt .gnu.prelink_undo section data"
msgstr "konnte Abschnittsdaten nicht holen: %s"
+#: libdwfl/libdwflP.h:80
+msgid "Internal error due to ebl"
+msgstr ""
+
+#: libdwfl/libdwflP.h:81
+msgid "Missing data in core file"
+msgstr ""
+
+#: libdwfl/libdwflP.h:82
+#, fuzzy
+msgid "Invalid register"
+msgstr "ungültiger Parameter"
+
+#: libdwfl/libdwflP.h:83
+msgid "Error reading process memory"
+msgstr ""
+
+#: libdwfl/libdwflP.h:84
+msgid "Couldn't find architecture of any ELF"
+msgstr ""
+
+#: libdwfl/libdwflP.h:85
+msgid "Error parsing /proc filesystem"
+msgstr ""
+
+#: libdwfl/libdwflP.h:86
+#, fuzzy
+msgid "Invalid DWARF"
+msgstr "DWARF ungültig"
+
+#: libdwfl/libdwflP.h:87
+msgid "Unsupported DWARF"
+msgstr ""
+
+#: libdwfl/libdwflP.h:88
+msgid "Unable to find more threads"
+msgstr ""
+
+#: libdwfl/libdwflP.h:89
+msgid "Dwfl already has attached state"
+msgstr ""
+
+#: libdwfl/libdwflP.h:90
+msgid "Dwfl has no attached state"
+msgstr ""
+
+#: libdwfl/libdwflP.h:91
+msgid "Unwinding not supported for this architecture"
+msgstr ""
+
+#: libdwfl/libdwflP.h:92
+#, fuzzy
+msgid "Invalid argument"
+msgstr "ungültiger Parameter"
+
#: libebl/eblbackendname.c:42
msgid "No backend"
msgstr "Kein Backend"
@@ -623,34 +688,38 @@ msgid "Also show symbol or section names"
msgstr ""
#: src/addr2line.c:64
+msgid "Also show symbol and the section names"
+msgstr ""
+
+#: src/addr2line.c:65
msgid "Also show line table flags"
msgstr ""
-#: src/addr2line.c:66
+#: src/addr2line.c:67
msgid "Treat addresses as offsets relative to NAME section."
msgstr ""
-#: src/addr2line.c:68
+#: src/addr2line.c:69
msgid ""
"Show all source locations that caused inline expansion of subroutines at the "
"address."
msgstr ""
-#: src/addr2line.c:71 src/elfcmp.c:72 src/findtextrel.c:67 src/nm.c:100
+#: src/addr2line.c:72 src/elfcmp.c:72 src/findtextrel.c:67 src/nm.c:100
#: src/strings.c:75
msgid "Miscellaneous:"
msgstr "Verschiedenes:"
-#: src/addr2line.c:80
+#: src/addr2line.c:81
msgid ""
"Locate source files and line information for ADDRs (in a.out by default)."
msgstr ""
-#: src/addr2line.c:84
+#: src/addr2line.c:85
msgid "[ADDR...]"
msgstr ""
-#: src/addr2line.c:192 src/ar.c:289 src/elfcmp.c:662 src/elflint.c:231
+#: src/addr2line.c:196 src/ar.c:289 src/elfcmp.c:662 src/elflint.c:231
#: src/findtextrel.c:162 src/ld.c:949 src/nm.c:265 src/objdump.c:181
#: src/ranlib.c:128 src/readelf.c:500 src/size.c:211 src/strings.c:219
#: src/strip.c:213 src/unstrip.c:226
@@ -665,7 +734,7 @@ msgstr ""
"GARANTIE,\n"
"auch nicht für Marktgängigkeit oder Eignung für einen Bestimmten Zweck.\n"
-#: src/addr2line.c:197 src/ar.c:294 src/elfcmp.c:667 src/elflint.c:236
+#: src/addr2line.c:201 src/ar.c:294 src/elfcmp.c:667 src/elflint.c:236
#: src/findtextrel.c:167 src/ld.c:954 src/nm.c:270 src/objdump.c:186
#: src/ranlib.c:133 src/readelf.c:505 src/size.c:216 src/strings.c:224
#: src/strip.c:218 src/unstrip.c:231
@@ -673,22 +742,22 @@ msgstr ""
msgid "Written by %s.\n"
msgstr "Geschrieben von %s.\n"
-#: src/addr2line.c:437
+#: src/addr2line.c:474
#, fuzzy, c-format
msgid "Section syntax requires exactly one module"
msgstr "Abschnitt syntax benötigt genau ein Modul"
-#: src/addr2line.c:460
+#: src/addr2line.c:497
#, c-format
msgid "offset %#<PRIxMAX> lies outside section '%s'"
msgstr ""
-#: src/addr2line.c:525
+#: src/addr2line.c:563
#, c-format
msgid "cannot find symbol '%s'"
msgstr "Konnte Symbol '%s' nicht finden"
-#: src/addr2line.c:530
+#: src/addr2line.c:568
#, c-format
msgid "offset %#<PRIxMAX> lies outside contents of '%s'"
msgstr ""
@@ -3721,17 +3790,17 @@ msgstr "%s%s%s: Dateiformat nicht erkannt"
msgid "cannot create search tree"
msgstr "Kann Suchbaum nicht erstellen"
-#: src/nm.c:757 src/nm.c:1157 src/objdump.c:787 src/readelf.c:536
+#: src/nm.c:757 src/nm.c:1158 src/objdump.c:787 src/readelf.c:536
#: src/readelf.c:1071 src/readelf.c:1214 src/readelf.c:1362 src/readelf.c:1544
#: src/readelf.c:1744 src/readelf.c:1930 src/readelf.c:2140 src/readelf.c:2394
#: src/readelf.c:2460 src/readelf.c:2538 src/readelf.c:3036 src/readelf.c:3072
-#: src/readelf.c:3134 src/readelf.c:7805 src/readelf.c:8882 src/readelf.c:9029
-#: src/readelf.c:9097 src/size.c:417 src/size.c:491 src/strip.c:503
+#: src/readelf.c:3134 src/readelf.c:7805 src/readelf.c:8885 src/readelf.c:9032
+#: src/readelf.c:9100 src/size.c:417 src/size.c:491 src/strip.c:503
#, c-format
msgid "cannot get section header string table index"
msgstr ""
-#: src/nm.c:783
+#: src/nm.c:784
#, c-format
msgid ""
"\n"
@@ -3744,29 +3813,29 @@ msgstr ""
"Symbole aus %s:\n"
"\n"
-#: src/nm.c:786
+#: src/nm.c:787
#, c-format
msgid ""
"%*s%-*s %-*s Class Type %-*s %*s Section\n"
"\n"
msgstr ""
-#: src/nm.c:1167
+#: src/nm.c:1168
#, c-format
msgid "%s: entry size in section `%s' is not what we expect"
msgstr "%s: entry size in section `%s' is not what we expect"
-#: src/nm.c:1171
+#: src/nm.c:1172
#, c-format
msgid "%s: size of section `%s' is not multiple of entry size"
msgstr ""
-#: src/nm.c:1429
+#: src/nm.c:1430
#, c-format
msgid "%s%s%s%s: Invalid operation"
msgstr "%s%s%s%s: Ungültige Operation"
-#: src/nm.c:1486
+#: src/nm.c:1487
#, c-format
msgid "%s%s%s: no symbols"
msgstr "%s%s%s: keine Symbole"
@@ -3993,7 +4062,7 @@ msgstr "konnte Elf-Deskriptor nicht erzeugen: %s"
msgid "cannot get section: %s"
msgstr ""
-#: src/readelf.c:554 src/readelf.c:1092 src/readelf.c:1246 src/readelf.c:9049
+#: src/readelf.c:554 src/readelf.c:1092 src/readelf.c:1246 src/readelf.c:9052
#: src/unstrip.c:345 src/unstrip.c:376 src/unstrip.c:425 src/unstrip.c:533
#: src/unstrip.c:550 src/unstrip.c:586 src/unstrip.c:784 src/unstrip.c:1052
#: src/unstrip.c:1242 src/unstrip.c:1302 src/unstrip.c:1423 src/unstrip.c:1476
@@ -5413,118 +5482,118 @@ msgstr ""
msgid "cannot get debug context descriptor: %s"
msgstr ""
-#: src/readelf.c:7952 src/readelf.c:8555 src/readelf.c:8666 src/readelf.c:8724
+#: src/readelf.c:7952 src/readelf.c:8558 src/readelf.c:8669 src/readelf.c:8727
#, c-format
msgid "cannot convert core note data: %s"
msgstr ""
-#: src/readelf.c:8296
+#: src/readelf.c:8299
#, c-format
msgid ""
"\n"
"%*s... <repeats %u more times> ..."
msgstr ""
-#: src/readelf.c:8799
+#: src/readelf.c:8802
msgid " Owner Data size Type\n"
msgstr ""
-#: src/readelf.c:8817
+#: src/readelf.c:8820
#, c-format
msgid " %-13.*s %9<PRId32> %s\n"
msgstr ""
-#: src/readelf.c:8867
+#: src/readelf.c:8870
#, c-format
msgid "cannot get content of note section: %s"
msgstr ""
-#: src/readelf.c:8894
+#: src/readelf.c:8897
#, c-format
msgid ""
"\n"
"Note section [%2zu] '%s' of %<PRIu64> bytes at offset %#0<PRIx64>:\n"
msgstr ""
-#: src/readelf.c:8917
+#: src/readelf.c:8920
#, c-format
msgid ""
"\n"
"Note segment of %<PRIu64> bytes at offset %#0<PRIx64>:\n"
msgstr ""
-#: src/readelf.c:8963
+#: src/readelf.c:8966
#, c-format
msgid ""
"\n"
"Section [%Zu] '%s' has no data to dump.\n"
msgstr ""
-#: src/readelf.c:8969 src/readelf.c:8992
+#: src/readelf.c:8972 src/readelf.c:8995
#, c-format
msgid "cannot get data for section [%Zu] '%s': %s"
msgstr ""
-#: src/readelf.c:8973
+#: src/readelf.c:8976
#, c-format
msgid ""
"\n"
"Hex dump of section [%Zu] '%s', %<PRIu64> bytes at offset %#0<PRIx64>:\n"
msgstr ""
-#: src/readelf.c:8986
+#: src/readelf.c:8989
#, c-format
msgid ""
"\n"
"Section [%Zu] '%s' has no strings to dump.\n"
msgstr ""
-#: src/readelf.c:8996
+#: src/readelf.c:8999
#, c-format
msgid ""
"\n"
"String section [%Zu] '%s' contains %<PRIu64> bytes at offset %#0<PRIx64>:\n"
msgstr ""
-#: src/readelf.c:9044
+#: src/readelf.c:9047
#, c-format
msgid ""
"\n"
"section [%lu] does not exist"
msgstr ""
-#: src/readelf.c:9073
+#: src/readelf.c:9076
#, c-format
msgid ""
"\n"
"section '%s' does not exist"
msgstr ""
-#: src/readelf.c:9130
+#: src/readelf.c:9133
#, c-format
msgid "cannot get symbol index of archive '%s': %s"
msgstr ""
-#: src/readelf.c:9133
+#: src/readelf.c:9136
#, c-format
msgid ""
"\n"
"Archive '%s' has no symbol index\n"
msgstr ""
-#: src/readelf.c:9137
+#: src/readelf.c:9140
#, c-format
msgid ""
"\n"
"Index of archive '%s' has %Zu entries:\n"
msgstr ""
-#: src/readelf.c:9155
+#: src/readelf.c:9158
#, c-format
msgid "cannot extract member at offset %Zu in '%s': %s"
msgstr ""
-#: src/readelf.c:9160
+#: src/readelf.c:9163
#, c-format
msgid "Archive member '%s' contains:\n"
msgstr ""
diff --git a/po/es.po b/po/es.po
index 5b43517b..9773165e 100644
--- a/po/es.po
+++ b/po/es.po
@@ -10,7 +10,7 @@ msgid ""
msgstr ""
"Project-Id-Version: elfutils.master.es\n"
"Report-Msgid-Bugs-To: http://bugzilla.redhat.com/\n"
-"POT-Creation-Date: 2013-09-30 13:52+0200\n"
+"POT-Creation-Date: 2013-12-31 14:01+0100\n"
"PO-Revision-Date: 2011-01-10 15:17-0300\n"
"Last-Translator: Claudio Rodrigo Pereyra Diaz <claudiorodrigo@pereyradiaz."
"com.ar>\n"
@@ -30,12 +30,12 @@ msgstr ""
msgid "memory exhausted"
msgstr "memoria agotada"
-#: libasm/asm_error.c:65 libdw/dwarf_error.c:58 libdwfl/libdwflP.h:49
+#: libasm/asm_error.c:65 libdw/dwarf_error.c:58 libdwfl/libdwflP.h:51
#: libelf/elf_error.c:60
msgid "no error"
msgstr "ningún error"
-#: libasm/asm_error.c:66 libdw/dwarf_error.c:67 libdwfl/libdwflP.h:51
+#: libasm/asm_error.c:66 libdw/dwarf_error.c:67 libdwfl/libdwflP.h:53
#: libelf/elf_error.c:91
msgid "out of memory"
msgstr "memoria agotada"
@@ -74,7 +74,7 @@ msgstr "error durante salida de datos"
msgid "no backend support available"
msgstr "No hay soporte de segundo plano"
-#: libasm/asm_error.c:84 libdw/dwarf_error.c:59 libdwfl/libdwflP.h:50
+#: libasm/asm_error.c:84 libdw/dwarf_error.c:59 libdwfl/libdwflP.h:52
#: libelf/elf_error.c:63
msgid "unknown error"
msgstr "error desconocido"
@@ -171,7 +171,7 @@ msgstr "versión DWARF inválida"
msgid "invalid directory index"
msgstr "Índice de directorio inválido"
-#: libdw/dwarf_error.c:84 libdwfl/libdwflP.h:70
+#: libdw/dwarf_error.c:84 libdwfl/libdwflP.h:72
msgid "address out of range"
msgstr "dirección fuera de rango"
@@ -191,7 +191,7 @@ msgstr "Índice de línea inválido"
msgid "invalid address range index"
msgstr "Índice de dirección de rango inválido"
-#: libdw/dwarf_error.c:89 libdwfl/libdwflP.h:71
+#: libdw/dwarf_error.c:89 libdwfl/libdwflP.h:73
msgid "no matching address range"
msgstr "dirección de rango no coincidente"
@@ -251,128 +251,193 @@ msgstr "Kernel con todos los módulos"
msgid "Search path for separate debuginfo files"
msgstr "Ruta de búsqueda para archivos debugingfo independientes"
-#: libdwfl/argp-std.c:183
+#: libdwfl/argp-std.c:157
msgid "only one of -e, -p, -k, -K, or --core allowed"
msgstr "Sólo uno de -e, -p, -k, -K, ó --core está permitido"
-#: libdwfl/argp-std.c:252
+#: libdwfl/argp-std.c:177
+#, fuzzy
+msgid "cannot attach to process"
+msgstr "No se puede crear el árbol de búsqueda"
+
+#: libdwfl/argp-std.c:231
msgid "cannot load kernel symbols"
msgstr "No se pueden cargar símbolos de kernel"
-#: libdwfl/argp-std.c:256
+#: libdwfl/argp-std.c:235
msgid "cannot find kernel modules"
msgstr "no se pueden hallar módulos de kernel"
-#: libdwfl/argp-std.c:273
+#: libdwfl/argp-std.c:252
msgid "cannot find kernel or modules"
msgstr "imposible encontrar kernel o módulos"
-#: libdwfl/argp-std.c:315
+#: libdwfl/argp-std.c:291
#, c-format
msgid "cannot read ELF core file: %s"
msgstr "No se puede leer archivo core ELF: %s"
-#: libdwfl/argp-std.c:333
+#: libdwfl/argp-std.c:307
+#, fuzzy
+msgid "cannot attach to core"
+msgstr "No se puede crear el árbol de búsqueda"
+
+#: libdwfl/argp-std.c:314
msgid "No modules recognized in core file"
msgstr "No hay módulos reconocidos en el archivo core"
-#: libdwfl/libdwflP.h:52
+#: libdwfl/libdwflP.h:54
msgid "See errno"
msgstr "Ve errno"
-#: libdwfl/libdwflP.h:53
+#: libdwfl/libdwflP.h:55
msgid "See elf_errno"
msgstr "Ver elf_errno"
-#: libdwfl/libdwflP.h:54
+#: libdwfl/libdwflP.h:56
msgid "See dwarf_errno"
msgstr "Ver dwarf_errno"
-#: libdwfl/libdwflP.h:55
+#: libdwfl/libdwflP.h:57
msgid "See ebl_errno (XXX missing)"
msgstr "Ver ebl_errno (no se encuentra XXX)"
-#: libdwfl/libdwflP.h:56
+#: libdwfl/libdwflP.h:58
msgid "gzip decompression failed"
msgstr "falló la descompresión gzip"
-#: libdwfl/libdwflP.h:57
+#: libdwfl/libdwflP.h:59
msgid "bzip2 decompression failed"
msgstr "falló la descompresión bzip2"
-#: libdwfl/libdwflP.h:58
+#: libdwfl/libdwflP.h:60
msgid "LZMA decompression failed"
msgstr "falló la descompresión LZMA"
-#: libdwfl/libdwflP.h:59
+#: libdwfl/libdwflP.h:61
msgid "no support library found for machine"
msgstr "no se ha encontrado una biblioteca de soporte para la máquina"
-#: libdwfl/libdwflP.h:60
+#: libdwfl/libdwflP.h:62
msgid "Callbacks missing for ET_REL file"
msgstr "No se encuentran rellamadas para el archivo ET_REL"
-#: libdwfl/libdwflP.h:61
+#: libdwfl/libdwflP.h:63
msgid "Unsupported relocation type"
msgstr "Tipo de reubicación no soportada"
-#: libdwfl/libdwflP.h:62
+#: libdwfl/libdwflP.h:64
msgid "r_offset is bogus"
msgstr "r_offset se encuentra inutilizable"
-#: libdwfl/libdwflP.h:63 libelf/elf_error.c:111 libelf/elf_error.c:171
+#: libdwfl/libdwflP.h:65 libelf/elf_error.c:111 libelf/elf_error.c:171
msgid "offset out of range"
msgstr "desplazamiento fuera de rango"
-#: libdwfl/libdwflP.h:64
+#: libdwfl/libdwflP.h:66
msgid "relocation refers to undefined symbol"
msgstr "la reubicación hace referencia a un símbolo no definido"
-#: libdwfl/libdwflP.h:65
+#: libdwfl/libdwflP.h:67
msgid "Callback returned failure"
msgstr "La rellamada devolvió un fallo"
-#: libdwfl/libdwflP.h:66
+#: libdwfl/libdwflP.h:68
msgid "No DWARF information found"
msgstr "No se ha encontrado una información DWARF"
-#: libdwfl/libdwflP.h:67
+#: libdwfl/libdwflP.h:69
msgid "No symbol table found"
msgstr "No se ha encontrado una tabla simbólica"
-#: libdwfl/libdwflP.h:68
+#: libdwfl/libdwflP.h:70
msgid "No ELF program headers"
msgstr "No existen encabezados de programa ELF"
-#: libdwfl/libdwflP.h:69
+#: libdwfl/libdwflP.h:71
msgid "address range overlaps an existing module"
msgstr "el rango de dirección se superpone con un módulo existente"
-#: libdwfl/libdwflP.h:72
+#: libdwfl/libdwflP.h:74
msgid "image truncated"
msgstr "imagen truncada"
-#: libdwfl/libdwflP.h:73
+#: libdwfl/libdwflP.h:75
msgid "ELF file opened"
msgstr "Archivo ELF abierto"
-#: libdwfl/libdwflP.h:74
+#: libdwfl/libdwflP.h:76
msgid "not a valid ELF file"
msgstr "no es un archivo ELF válido"
-#: libdwfl/libdwflP.h:75
+#: libdwfl/libdwflP.h:77
msgid "cannot handle DWARF type description"
msgstr "no es posible manipular tipo de descripción DWARF"
-#: libdwfl/libdwflP.h:76
+#: libdwfl/libdwflP.h:78
msgid "ELF file does not match build ID"
msgstr "El archivo ELF no coincide con el ID construido"
-#: libdwfl/libdwflP.h:77
+#: libdwfl/libdwflP.h:79
#, fuzzy
msgid "corrupt .gnu.prelink_undo section data"
msgstr "no se puede leer sección '.gnu.prelink_undo': %s"
+#: libdwfl/libdwflP.h:80
+msgid "Internal error due to ebl"
+msgstr ""
+
+#: libdwfl/libdwflP.h:81
+msgid "Missing data in core file"
+msgstr ""
+
+#: libdwfl/libdwflP.h:82
+#, fuzzy
+msgid "Invalid register"
+msgstr "Parámetro inválido"
+
+#: libdwfl/libdwflP.h:83
+msgid "Error reading process memory"
+msgstr ""
+
+#: libdwfl/libdwflP.h:84
+msgid "Couldn't find architecture of any ELF"
+msgstr ""
+
+#: libdwfl/libdwflP.h:85
+msgid "Error parsing /proc filesystem"
+msgstr ""
+
+#: libdwfl/libdwflP.h:86
+#, fuzzy
+msgid "Invalid DWARF"
+msgstr "DWARF inválido"
+
+#: libdwfl/libdwflP.h:87
+msgid "Unsupported DWARF"
+msgstr ""
+
+#: libdwfl/libdwflP.h:88
+msgid "Unable to find more threads"
+msgstr ""
+
+#: libdwfl/libdwflP.h:89
+msgid "Dwfl already has attached state"
+msgstr ""
+
+#: libdwfl/libdwflP.h:90
+msgid "Dwfl has no attached state"
+msgstr ""
+
+#: libdwfl/libdwflP.h:91
+msgid "Unwinding not supported for this architecture"
+msgstr ""
+
+#: libdwfl/libdwflP.h:92
+#, fuzzy
+msgid "Invalid argument"
+msgstr "Parámetro inválido"
+
#: libebl/eblbackendname.c:42
msgid "No backend"
msgstr "No hay segundo plano (Backend)"
@@ -621,36 +686,41 @@ msgid "Also show symbol or section names"
msgstr "También mostrar símbolo o nombres de sección"
#: src/addr2line.c:64
+#, fuzzy
+msgid "Also show symbol and the section names"
+msgstr "También mostrar símbolo o nombres de sección"
+
+#: src/addr2line.c:65
msgid "Also show line table flags"
msgstr "También mostrar marcas de líneas de tabla"
-#: src/addr2line.c:66
+#: src/addr2line.c:67
msgid "Treat addresses as offsets relative to NAME section."
msgstr "Manejar direcciones como compensaciones relativas a sección de NOMBRE."
-#: src/addr2line.c:68
+#: src/addr2line.c:69
msgid ""
"Show all source locations that caused inline expansion of subroutines at the "
"address."
msgstr ""
-#: src/addr2line.c:71 src/elfcmp.c:72 src/findtextrel.c:67 src/nm.c:100
+#: src/addr2line.c:72 src/elfcmp.c:72 src/findtextrel.c:67 src/nm.c:100
#: src/strings.c:75
msgid "Miscellaneous:"
msgstr "Misceláneos:"
-#: src/addr2line.c:80
+#: src/addr2line.c:81
msgid ""
"Locate source files and line information for ADDRs (in a.out by default)."
msgstr ""
"Localizar archivos fuente e información de línea para DIRECCIONES (en a.out "
"por defecto)."
-#: src/addr2line.c:84
+#: src/addr2line.c:85
msgid "[ADDR...]"
msgstr "[DIREC...]"
-#: src/addr2line.c:192 src/ar.c:289 src/elfcmp.c:662 src/elflint.c:231
+#: src/addr2line.c:196 src/ar.c:289 src/elfcmp.c:662 src/elflint.c:231
#: src/findtextrel.c:162 src/ld.c:949 src/nm.c:265 src/objdump.c:181
#: src/ranlib.c:128 src/readelf.c:500 src/size.c:211 src/strings.c:219
#: src/strip.c:213 src/unstrip.c:226
@@ -666,7 +736,7 @@ msgstr ""
"garantía, ni siquiera para SU COMERCIALIZACIÓN o PARA SER USADO CON UN FIN "
"DETERMINADO.\n"
-#: src/addr2line.c:197 src/ar.c:294 src/elfcmp.c:667 src/elflint.c:236
+#: src/addr2line.c:201 src/ar.c:294 src/elfcmp.c:667 src/elflint.c:236
#: src/findtextrel.c:167 src/ld.c:954 src/nm.c:270 src/objdump.c:186
#: src/ranlib.c:133 src/readelf.c:505 src/size.c:216 src/strings.c:224
#: src/strip.c:218 src/unstrip.c:231
@@ -674,22 +744,22 @@ msgstr ""
msgid "Written by %s.\n"
msgstr "Escrito por %s.\n"
-#: src/addr2line.c:437
+#: src/addr2line.c:474
#, c-format
msgid "Section syntax requires exactly one module"
msgstr "Sintaxis de sección requiere exactamente un módulo"
-#: src/addr2line.c:460
+#: src/addr2line.c:497
#, c-format
msgid "offset %#<PRIxMAX> lies outside section '%s'"
msgstr "Compensación %#<PRIxMAX> se encuentra fuera de sección '%s'"
-#: src/addr2line.c:525
+#: src/addr2line.c:563
#, c-format
msgid "cannot find symbol '%s'"
msgstr "no se puede encontrar símbolo '%s'"
-#: src/addr2line.c:530
+#: src/addr2line.c:568
#, c-format
msgid "offset %#<PRIxMAX> lies outside contents of '%s'"
msgstr "compensación %#<PRIxMAX> se encuentra fuera de contenido de '%s'"
@@ -4047,17 +4117,17 @@ msgstr "%s%s%s: no se reconoció el formato de fichero"
msgid "cannot create search tree"
msgstr "No se puede crear el árbol de búsqueda"
-#: src/nm.c:757 src/nm.c:1157 src/objdump.c:787 src/readelf.c:536
+#: src/nm.c:757 src/nm.c:1158 src/objdump.c:787 src/readelf.c:536
#: src/readelf.c:1071 src/readelf.c:1214 src/readelf.c:1362 src/readelf.c:1544
#: src/readelf.c:1744 src/readelf.c:1930 src/readelf.c:2140 src/readelf.c:2394
#: src/readelf.c:2460 src/readelf.c:2538 src/readelf.c:3036 src/readelf.c:3072
-#: src/readelf.c:3134 src/readelf.c:7805 src/readelf.c:8882 src/readelf.c:9029
-#: src/readelf.c:9097 src/size.c:417 src/size.c:491 src/strip.c:503
+#: src/readelf.c:3134 src/readelf.c:7805 src/readelf.c:8885 src/readelf.c:9032
+#: src/readelf.c:9100 src/size.c:417 src/size.c:491 src/strip.c:503
#, c-format
msgid "cannot get section header string table index"
msgstr "no se puede obtener índice de cadena de encabezamiento de sección"
-#: src/nm.c:783
+#: src/nm.c:784
#, c-format
msgid ""
"\n"
@@ -4070,7 +4140,7 @@ msgstr ""
"Símbolos de %s:\n"
"\n"
-#: src/nm.c:786
+#: src/nm.c:787
#, c-format
msgid ""
"%*s%-*s %-*s Class Type %-*s %*s Section\n"
@@ -4079,23 +4149,23 @@ msgstr ""
"%*s%-*s %-*s Clase Tipo %-*s %*s Sección\n"
"\n"
-#: src/nm.c:1167
+#: src/nm.c:1168
#, c-format
msgid "%s: entry size in section `%s' is not what we expect"
msgstr ""
"%s: el tamaño de la entrada en la sección `%s' no es el que esperábamos "
-#: src/nm.c:1171
+#: src/nm.c:1172
#, c-format
msgid "%s: size of section `%s' is not multiple of entry size"
msgstr "%s: Tamaño de sección `%s' no es múltiplo de tamaño de entrada"
-#: src/nm.c:1429
+#: src/nm.c:1430
#, c-format
msgid "%s%s%s%s: Invalid operation"
msgstr "%s%s%s%s: Operación inválida"
-#: src/nm.c:1486
+#: src/nm.c:1487
#, c-format
msgid "%s%s%s: no symbols"
msgstr "%s%s%s: No hay símbolos"
@@ -4329,7 +4399,7 @@ msgstr "no se puede crear descriptor ELF: %s"
msgid "cannot get section: %s"
msgstr "No se puede encontrar la sección: %s"
-#: src/readelf.c:554 src/readelf.c:1092 src/readelf.c:1246 src/readelf.c:9049
+#: src/readelf.c:554 src/readelf.c:1092 src/readelf.c:1246 src/readelf.c:9052
#: src/unstrip.c:345 src/unstrip.c:376 src/unstrip.c:425 src/unstrip.c:533
#: src/unstrip.c:550 src/unstrip.c:586 src/unstrip.c:784 src/unstrip.c:1052
#: src/unstrip.c:1242 src/unstrip.c:1302 src/unstrip.c:1423 src/unstrip.c:1476
@@ -5937,12 +6007,12 @@ msgstr ""
msgid "cannot get debug context descriptor: %s"
msgstr "no se puede depurar descriptor de contexto: %s"
-#: src/readelf.c:7952 src/readelf.c:8555 src/readelf.c:8666 src/readelf.c:8724
+#: src/readelf.c:7952 src/readelf.c:8558 src/readelf.c:8669 src/readelf.c:8727
#, c-format
msgid "cannot convert core note data: %s"
msgstr "no es posible convertir datos de la nota principal: %s"
-#: src/readelf.c:8296
+#: src/readelf.c:8299
#, c-format
msgid ""
"\n"
@@ -5951,21 +6021,21 @@ msgstr ""
"\n"
"%*s... <repeats %u more times> ..."
-#: src/readelf.c:8799
+#: src/readelf.c:8802
msgid " Owner Data size Type\n"
msgstr " Owner Data size Type\n"
-#: src/readelf.c:8817
+#: src/readelf.c:8820
#, c-format
msgid " %-13.*s %9<PRId32> %s\n"
msgstr " %-13.*s %9<PRId32> %s\n"
-#: src/readelf.c:8867
+#: src/readelf.c:8870
#, c-format
msgid "cannot get content of note section: %s"
msgstr "no se puede obtener el contenido de sección de nota: %s"
-#: src/readelf.c:8894
+#: src/readelf.c:8897
#, c-format
msgid ""
"\n"
@@ -5974,7 +6044,7 @@ msgstr ""
"\n"
"Sección de nota [%2zu] '%s' de %<PRIu64> bytes en compensación %#0<PRIx64>:\n"
-#: src/readelf.c:8917
+#: src/readelf.c:8920
#, c-format
msgid ""
"\n"
@@ -5983,7 +6053,7 @@ msgstr ""
"\n"
"Segmento de nota de %<PRIu64> bytes en compensación %#0<PRIx64>:\n"
-#: src/readelf.c:8963
+#: src/readelf.c:8966
#, c-format
msgid ""
"\n"
@@ -5992,12 +6062,12 @@ msgstr ""
"\n"
"Sección [%Zu] '%s' no tiene datos para volcar.\n"
-#: src/readelf.c:8969 src/readelf.c:8992
+#: src/readelf.c:8972 src/readelf.c:8995
#, c-format
msgid "cannot get data for section [%Zu] '%s': %s"
msgstr "no se pueden obtener datos para sección [%Zu] '%s': %s"
-#: src/readelf.c:8973
+#: src/readelf.c:8976
#, c-format
msgid ""
"\n"
@@ -6007,7 +6077,7 @@ msgstr ""
"Volcado Hex de sección [%Zu] '%s', %<PRIu64> bytes en compensación "
"%#0<PRIx64>:\n"
-#: src/readelf.c:8986
+#: src/readelf.c:8989
#, c-format
msgid ""
"\n"
@@ -6016,7 +6086,7 @@ msgstr ""
"\n"
"Sección [%Zu] '%s' no tiene datos para volcar.\n"
-#: src/readelf.c:8996
+#: src/readelf.c:8999
#, c-format
msgid ""
"\n"
@@ -6026,7 +6096,7 @@ msgstr ""
"Sección de cadena [%Zu] '%s' contiene %<PRIu64> bytes en compensación "
"%#0<PRIx64>:\n"
-#: src/readelf.c:9044
+#: src/readelf.c:9047
#, c-format
msgid ""
"\n"
@@ -6035,7 +6105,7 @@ msgstr ""
"\n"
"sección [%lu] no existe"
-#: src/readelf.c:9073
+#: src/readelf.c:9076
#, c-format
msgid ""
"\n"
@@ -6044,12 +6114,12 @@ msgstr ""
"\n"
"sección '%s' no existe"
-#: src/readelf.c:9130
+#: src/readelf.c:9133
#, c-format
msgid "cannot get symbol index of archive '%s': %s"
msgstr "no se puede obtener el índice de símbolo de archivo '%s': %s"
-#: src/readelf.c:9133
+#: src/readelf.c:9136
#, c-format
msgid ""
"\n"
@@ -6058,7 +6128,7 @@ msgstr ""
"\n"
"Archivo '%s' no tiene índice de símbolo\n"
-#: src/readelf.c:9137
+#: src/readelf.c:9140
#, c-format
msgid ""
"\n"
@@ -6067,12 +6137,12 @@ msgstr ""
"\n"
"Índice de archivo '%s' tiene %Zu entradas:\n"
-#: src/readelf.c:9155
+#: src/readelf.c:9158
#, c-format
msgid "cannot extract member at offset %Zu in '%s': %s"
msgstr "no es posible extraer miembro en compensación %Zu en '%s': %s"
-#: src/readelf.c:9160
+#: src/readelf.c:9163
#, c-format
msgid "Archive member '%s' contains:\n"
msgstr "Miembro de archivo contiene '%s':\n"
diff --git a/po/ja.po b/po/ja.po
index cf95a9bc..a7cfd01c 100644
--- a/po/ja.po
+++ b/po/ja.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: ja\n"
"Report-Msgid-Bugs-To: http://bugzilla.redhat.com/\n"
-"POT-Creation-Date: 2013-09-30 13:52+0200\n"
+"POT-Creation-Date: 2013-12-31 14:01+0100\n"
"PO-Revision-Date: 2009-09-20 15:32+0900\n"
"Last-Translator: Hyu_gabaru Ryu_ichi <[email protected]>\n"
"Language-Team: Japanese <[email protected]>\n"
@@ -25,12 +25,12 @@ msgstr ""
msgid "memory exhausted"
msgstr "メモリー消費済み"
-#: libasm/asm_error.c:65 libdw/dwarf_error.c:58 libdwfl/libdwflP.h:49
+#: libasm/asm_error.c:65 libdw/dwarf_error.c:58 libdwfl/libdwflP.h:51
#: libelf/elf_error.c:60
msgid "no error"
msgstr "エラー無し"
-#: libasm/asm_error.c:66 libdw/dwarf_error.c:67 libdwfl/libdwflP.h:51
+#: libasm/asm_error.c:66 libdw/dwarf_error.c:67 libdwfl/libdwflP.h:53
#: libelf/elf_error.c:91
msgid "out of memory"
msgstr "メモリー不足"
@@ -69,7 +69,7 @@ msgstr "データの出力中にエラー"
msgid "no backend support available"
msgstr "バックエンドサポートが利用できません"
-#: libasm/asm_error.c:84 libdw/dwarf_error.c:59 libdwfl/libdwflP.h:50
+#: libasm/asm_error.c:84 libdw/dwarf_error.c:59 libdwfl/libdwflP.h:52
#: libelf/elf_error.c:63
msgid "unknown error"
msgstr "不明なエラー"
@@ -166,7 +166,7 @@ msgstr "不当な DWARF バージョン"
msgid "invalid directory index"
msgstr "不当なディレクトリー索引"
-#: libdw/dwarf_error.c:84 libdwfl/libdwflP.h:70
+#: libdw/dwarf_error.c:84 libdwfl/libdwflP.h:72
msgid "address out of range"
msgstr "アドレスが範囲外です"
@@ -186,7 +186,7 @@ msgstr "不当な行索引"
msgid "invalid address range index"
msgstr "不当なアドレス範囲索引"
-#: libdw/dwarf_error.c:89 libdwfl/libdwflP.h:71
+#: libdw/dwarf_error.c:89 libdwfl/libdwflP.h:73
msgid "no matching address range"
msgstr "アドレス範囲に対応しません"
@@ -246,134 +246,199 @@ msgstr "全てのモジュール付きのカーネル"
msgid "Search path for separate debuginfo files"
msgstr "分離した debuginfo ファイルべきパスを探す"
-#: libdwfl/argp-std.c:183
+#: libdwfl/argp-std.c:157
msgid "only one of -e, -p, -k, -K, or --core allowed"
msgstr "-e か、-p、-k、-K、--core のひとつだけが認められます"
-#: libdwfl/argp-std.c:252
+#: libdwfl/argp-std.c:177
+#, fuzzy
+msgid "cannot attach to process"
+msgstr "検索ツリーを生成できません"
+
+#: libdwfl/argp-std.c:231
msgid "cannot load kernel symbols"
msgstr "カーネルシンボルをロードできません"
-#: libdwfl/argp-std.c:256
+#: libdwfl/argp-std.c:235
msgid "cannot find kernel modules"
msgstr "カーネルモジュールを見つけられません"
-#: libdwfl/argp-std.c:273
+#: libdwfl/argp-std.c:252
msgid "cannot find kernel or modules"
msgstr "カーネルかモジュールを見つけられません"
-#: libdwfl/argp-std.c:315
+#: libdwfl/argp-std.c:291
#, c-format
msgid "cannot read ELF core file: %s"
msgstr "ELF コアファイルを読めません: %s"
-#: libdwfl/argp-std.c:333
+#: libdwfl/argp-std.c:307
+#, fuzzy
+msgid "cannot attach to core"
+msgstr "検索ツリーを生成できません"
+
+#: libdwfl/argp-std.c:314
msgid "No modules recognized in core file"
msgstr "コアファイルの中にモジュールを認識できません"
-#: libdwfl/libdwflP.h:52
+#: libdwfl/libdwflP.h:54
msgid "See errno"
msgstr ""
-#: libdwfl/libdwflP.h:53
+#: libdwfl/libdwflP.h:55
msgid "See elf_errno"
msgstr ""
-#: libdwfl/libdwflP.h:54
+#: libdwfl/libdwflP.h:56
msgid "See dwarf_errno"
msgstr ""
-#: libdwfl/libdwflP.h:55
+#: libdwfl/libdwflP.h:57
msgid "See ebl_errno (XXX missing)"
msgstr ""
-#: libdwfl/libdwflP.h:56
+#: libdwfl/libdwflP.h:58
msgid "gzip decompression failed"
msgstr ""
-#: libdwfl/libdwflP.h:57
+#: libdwfl/libdwflP.h:59
msgid "bzip2 decompression failed"
msgstr ""
-#: libdwfl/libdwflP.h:58
+#: libdwfl/libdwflP.h:60
msgid "LZMA decompression failed"
msgstr ""
-#: libdwfl/libdwflP.h:59
+#: libdwfl/libdwflP.h:61
msgid "no support library found for machine"
msgstr ""
-#: libdwfl/libdwflP.h:60
+#: libdwfl/libdwflP.h:62
msgid "Callbacks missing for ET_REL file"
msgstr ""
-#: libdwfl/libdwflP.h:61
+#: libdwfl/libdwflP.h:63
msgid "Unsupported relocation type"
msgstr ""
-#: libdwfl/libdwflP.h:62
+#: libdwfl/libdwflP.h:64
msgid "r_offset is bogus"
msgstr ""
-#: libdwfl/libdwflP.h:63 libelf/elf_error.c:111 libelf/elf_error.c:171
+#: libdwfl/libdwflP.h:65 libelf/elf_error.c:111 libelf/elf_error.c:171
msgid "offset out of range"
msgstr "オフセットが範囲を越えている"
-#: libdwfl/libdwflP.h:64
+#: libdwfl/libdwflP.h:66
#, fuzzy
msgid "relocation refers to undefined symbol"
msgstr "定義されたシンボルの印刷サイズ"
-#: libdwfl/libdwflP.h:65
+#: libdwfl/libdwflP.h:67
msgid "Callback returned failure"
msgstr ""
-#: libdwfl/libdwflP.h:66
+#: libdwfl/libdwflP.h:68
#, fuzzy
msgid "No DWARF information found"
msgstr "DWARF 情報がありません"
-#: libdwfl/libdwflP.h:67
+#: libdwfl/libdwflP.h:69
msgid "No symbol table found"
msgstr ""
-#: libdwfl/libdwflP.h:68
+#: libdwfl/libdwflP.h:70
#, fuzzy
msgid "No ELF program headers"
msgstr "プログラムヘッダーを得られません: %s"
-#: libdwfl/libdwflP.h:69
+#: libdwfl/libdwflP.h:71
msgid "address range overlaps an existing module"
msgstr ""
-#: libdwfl/libdwflP.h:72
+#: libdwfl/libdwflP.h:74
msgid "image truncated"
msgstr ""
-#: libdwfl/libdwflP.h:73
+#: libdwfl/libdwflP.h:75
#, fuzzy
msgid "ELF file opened"
msgstr "ファイルのオープンを追跡します。"
-#: libdwfl/libdwflP.h:74
+#: libdwfl/libdwflP.h:76
#, fuzzy
msgid "not a valid ELF file"
msgstr "不当な ELF ファイル"
-#: libdwfl/libdwflP.h:75
+#: libdwfl/libdwflP.h:77
#, fuzzy
msgid "cannot handle DWARF type description"
msgstr "Elf 記述子を生成できません: %s"
-#: libdwfl/libdwflP.h:76
+#: libdwfl/libdwflP.h:78
msgid "ELF file does not match build ID"
msgstr ""
-#: libdwfl/libdwflP.h:77
+#: libdwfl/libdwflP.h:79
#, fuzzy
msgid "corrupt .gnu.prelink_undo section data"
msgstr "ラインデータセクションデータを得られません: %s"
+#: libdwfl/libdwflP.h:80
+msgid "Internal error due to ebl"
+msgstr ""
+
+#: libdwfl/libdwflP.h:81
+msgid "Missing data in core file"
+msgstr ""
+
+#: libdwfl/libdwflP.h:82
+#, fuzzy
+msgid "Invalid register"
+msgstr "不当なパラメーター"
+
+#: libdwfl/libdwflP.h:83
+msgid "Error reading process memory"
+msgstr ""
+
+#: libdwfl/libdwflP.h:84
+msgid "Couldn't find architecture of any ELF"
+msgstr ""
+
+#: libdwfl/libdwflP.h:85
+msgid "Error parsing /proc filesystem"
+msgstr ""
+
+#: libdwfl/libdwflP.h:86
+#, fuzzy
+msgid "Invalid DWARF"
+msgstr "不当な DWARF"
+
+#: libdwfl/libdwflP.h:87
+msgid "Unsupported DWARF"
+msgstr ""
+
+#: libdwfl/libdwflP.h:88
+msgid "Unable to find more threads"
+msgstr ""
+
+#: libdwfl/libdwflP.h:89
+msgid "Dwfl already has attached state"
+msgstr ""
+
+#: libdwfl/libdwflP.h:90
+msgid "Dwfl has no attached state"
+msgstr ""
+
+#: libdwfl/libdwflP.h:91
+msgid "Unwinding not supported for this architecture"
+msgstr ""
+
+#: libdwfl/libdwflP.h:92
+#, fuzzy
+msgid "Invalid argument"
+msgstr "不当なパラメーター"
+
#: libebl/eblbackendname.c:42
msgid "No backend"
msgstr "バックエンドがありません"
@@ -622,34 +687,38 @@ msgid "Also show symbol or section names"
msgstr ""
#: src/addr2line.c:64
+msgid "Also show symbol and the section names"
+msgstr ""
+
+#: src/addr2line.c:65
msgid "Also show line table flags"
msgstr ""
-#: src/addr2line.c:66
+#: src/addr2line.c:67
msgid "Treat addresses as offsets relative to NAME section."
msgstr ""
-#: src/addr2line.c:68
+#: src/addr2line.c:69
msgid ""
"Show all source locations that caused inline expansion of subroutines at the "
"address."
msgstr ""
-#: src/addr2line.c:71 src/elfcmp.c:72 src/findtextrel.c:67 src/nm.c:100
+#: src/addr2line.c:72 src/elfcmp.c:72 src/findtextrel.c:67 src/nm.c:100
#: src/strings.c:75
msgid "Miscellaneous:"
msgstr "雑則:"
-#: src/addr2line.c:80
+#: src/addr2line.c:81
msgid ""
"Locate source files and line information for ADDRs (in a.out by default)."
msgstr ""
-#: src/addr2line.c:84
+#: src/addr2line.c:85
msgid "[ADDR...]"
msgstr ""
-#: src/addr2line.c:192 src/ar.c:289 src/elfcmp.c:662 src/elflint.c:231
+#: src/addr2line.c:196 src/ar.c:289 src/elfcmp.c:662 src/elflint.c:231
#: src/findtextrel.c:162 src/ld.c:949 src/nm.c:265 src/objdump.c:181
#: src/ranlib.c:128 src/readelf.c:500 src/size.c:211 src/strings.c:219
#: src/strip.c:213 src/unstrip.c:226
@@ -663,7 +732,7 @@ msgstr ""
"This is free software; see the source for copying conditions. There is NO\n"
"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
-#: src/addr2line.c:197 src/ar.c:294 src/elfcmp.c:667 src/elflint.c:236
+#: src/addr2line.c:201 src/ar.c:294 src/elfcmp.c:667 src/elflint.c:236
#: src/findtextrel.c:167 src/ld.c:954 src/nm.c:270 src/objdump.c:186
#: src/ranlib.c:133 src/readelf.c:505 src/size.c:216 src/strings.c:224
#: src/strip.c:218 src/unstrip.c:231
@@ -671,22 +740,22 @@ msgstr ""
msgid "Written by %s.\n"
msgstr "%s によって書かれました。\n"
-#: src/addr2line.c:437
+#: src/addr2line.c:474
#, c-format
msgid "Section syntax requires exactly one module"
msgstr ""
-#: src/addr2line.c:460
+#: src/addr2line.c:497
#, c-format
msgid "offset %#<PRIxMAX> lies outside section '%s'"
msgstr ""
-#: src/addr2line.c:525
+#: src/addr2line.c:563
#, c-format
msgid "cannot find symbol '%s'"
msgstr ""
-#: src/addr2line.c:530
+#: src/addr2line.c:568
#, c-format
msgid "offset %#<PRIxMAX> lies outside contents of '%s'"
msgstr ""
@@ -3803,17 +3872,17 @@ msgstr "%s%s%s: ファイル形式を認識できません"
msgid "cannot create search tree"
msgstr "検索ツリーを生成できません"
-#: src/nm.c:757 src/nm.c:1157 src/objdump.c:787 src/readelf.c:536
+#: src/nm.c:757 src/nm.c:1158 src/objdump.c:787 src/readelf.c:536
#: src/readelf.c:1071 src/readelf.c:1214 src/readelf.c:1362 src/readelf.c:1544
#: src/readelf.c:1744 src/readelf.c:1930 src/readelf.c:2140 src/readelf.c:2394
#: src/readelf.c:2460 src/readelf.c:2538 src/readelf.c:3036 src/readelf.c:3072
-#: src/readelf.c:3134 src/readelf.c:7805 src/readelf.c:8882 src/readelf.c:9029
-#: src/readelf.c:9097 src/size.c:417 src/size.c:491 src/strip.c:503
+#: src/readelf.c:3134 src/readelf.c:7805 src/readelf.c:8885 src/readelf.c:9032
+#: src/readelf.c:9100 src/size.c:417 src/size.c:491 src/strip.c:503
#, c-format
msgid "cannot get section header string table index"
msgstr "セクションヘッダー文字列テーブル索引が得られません"
-#: src/nm.c:783
+#: src/nm.c:784
#, c-format
msgid ""
"\n"
@@ -3826,7 +3895,7 @@ msgstr ""
"%s からのシンボル:\n"
"\n"
-#: src/nm.c:786
+#: src/nm.c:787
#, c-format
msgid ""
"%*s%-*s %-*s Class Type %-*s %*s Section\n"
@@ -3835,22 +3904,22 @@ msgstr ""
"%*s%-*s %-*s クラス タイプ %-*s %*s セクション\n"
"\n"
-#: src/nm.c:1167
+#: src/nm.c:1168
#, c-format
msgid "%s: entry size in section `%s' is not what we expect"
msgstr "%s: セクションの項目の大きさ `%s' は予期したものとは異なります"
-#: src/nm.c:1171
+#: src/nm.c:1172
#, c-format
msgid "%s: size of section `%s' is not multiple of entry size"
msgstr "%s: セクション `%s' の大きさは項目の大きさの整数倍ではありません"
-#: src/nm.c:1429
+#: src/nm.c:1430
#, c-format
msgid "%s%s%s%s: Invalid operation"
msgstr "%s%s%s%s: 不当な操作"
-#: src/nm.c:1486
+#: src/nm.c:1487
#, c-format
msgid "%s%s%s: no symbols"
msgstr "%s%s%s: シンボルがありません"
@@ -4081,7 +4150,7 @@ msgstr "Elf 記述子を生成できません: %s"
msgid "cannot get section: %s"
msgstr "セクションを得られません: %s"
-#: src/readelf.c:554 src/readelf.c:1092 src/readelf.c:1246 src/readelf.c:9049
+#: src/readelf.c:554 src/readelf.c:1092 src/readelf.c:1246 src/readelf.c:9052
#: src/unstrip.c:345 src/unstrip.c:376 src/unstrip.c:425 src/unstrip.c:533
#: src/unstrip.c:550 src/unstrip.c:586 src/unstrip.c:784 src/unstrip.c:1052
#: src/unstrip.c:1242 src/unstrip.c:1302 src/unstrip.c:1423 src/unstrip.c:1476
@@ -5639,12 +5708,12 @@ msgstr ""
msgid "cannot get debug context descriptor: %s"
msgstr "デバッグ内容記述子を得られません: %s"
-#: src/readelf.c:7952 src/readelf.c:8555 src/readelf.c:8666 src/readelf.c:8724
+#: src/readelf.c:7952 src/readelf.c:8558 src/readelf.c:8669 src/readelf.c:8727
#, c-format
msgid "cannot convert core note data: %s"
msgstr "コアノートデータの変換ができません: %s"
-#: src/readelf.c:8296
+#: src/readelf.c:8299
#, c-format
msgid ""
"\n"
@@ -5653,21 +5722,21 @@ msgstr ""
"\n"
"%*s... < %u 回の繰返し> ..."
-#: src/readelf.c:8799
+#: src/readelf.c:8802
msgid " Owner Data size Type\n"
msgstr " 所有者 データ大きさタイプ\n"
-#: src/readelf.c:8817
+#: src/readelf.c:8820
#, c-format
msgid " %-13.*s %9<PRId32> %s\n"
msgstr " %-13.*s %9<PRId32> %s\n"
-#: src/readelf.c:8867
+#: src/readelf.c:8870
#, c-format
msgid "cannot get content of note section: %s"
msgstr "ノートセクションの内容を得られません: %s"
-#: src/readelf.c:8894
+#: src/readelf.c:8897
#, c-format
msgid ""
"\n"
@@ -5677,7 +5746,7 @@ msgstr ""
"オフセット %4$#0<PRIx64> の %3$<PRIu64> バイトのノートセクション [%1$2zu] "
"'%2$s':\n"
-#: src/readelf.c:8917
+#: src/readelf.c:8920
#, c-format
msgid ""
"\n"
@@ -5686,7 +5755,7 @@ msgstr ""
"\n"
"オフセット %2$#0<PRIx64> の %1$<PRIu64> バイトのノートセグメント:\n"
-#: src/readelf.c:8963
+#: src/readelf.c:8966
#, c-format
msgid ""
"\n"
@@ -5695,12 +5764,12 @@ msgstr ""
"\n"
"セクション [%Zu] '%s' にはダンプすべきデータがありません。\n"
-#: src/readelf.c:8969 src/readelf.c:8992
+#: src/readelf.c:8972 src/readelf.c:8995
#, c-format
msgid "cannot get data for section [%Zu] '%s': %s"
msgstr "セクション [%Zu] '%s' からデータが得られません: %s"
-#: src/readelf.c:8973
+#: src/readelf.c:8976
#, c-format
msgid ""
"\n"
@@ -5710,7 +5779,7 @@ msgstr ""
"オフセット %4$#0<PRIx64> のセクション [%1$Zu] '%2$s' の16進ダン"
"プ、%3$<PRIu64> バイト:\n"
-#: src/readelf.c:8986
+#: src/readelf.c:8989
#, fuzzy, c-format
msgid ""
"\n"
@@ -5719,7 +5788,7 @@ msgstr ""
"\n"
"セクション [%Zu] '%s' にはダンプすべきデータがありません。\n"
-#: src/readelf.c:8996
+#: src/readelf.c:8999
#, c-format
msgid ""
"\n"
@@ -5729,7 +5798,7 @@ msgstr ""
"オフセット %4$#0<PRIx64> 文字列セクション [%1$Zu] '%2$s' には %3$<PRIu64> バ"
"イトあります:\n"
-#: src/readelf.c:9044
+#: src/readelf.c:9047
#, c-format
msgid ""
"\n"
@@ -5738,7 +5807,7 @@ msgstr ""
"\n"
"セクション [%lu] がありません"
-#: src/readelf.c:9073
+#: src/readelf.c:9076
#, c-format
msgid ""
"\n"
@@ -5747,12 +5816,12 @@ msgstr ""
"\n"
"セクション '%s' がありません"
-#: src/readelf.c:9130
+#: src/readelf.c:9133
#, c-format
msgid "cannot get symbol index of archive '%s': %s"
msgstr "アーカイブのシンボル索引 '%s' を得られません: %s"
-#: src/readelf.c:9133
+#: src/readelf.c:9136
#, c-format
msgid ""
"\n"
@@ -5761,7 +5830,7 @@ msgstr ""
"\n"
"アーカイブ '%s' にはシンボル索引がありません\n"
-#: src/readelf.c:9137
+#: src/readelf.c:9140
#, c-format
msgid ""
"\n"
@@ -5770,12 +5839,12 @@ msgstr ""
"\n"
"アーカイブ '%s' の索引には %Zu 項目あります:\n"
-#: src/readelf.c:9155
+#: src/readelf.c:9158
#, c-format
msgid "cannot extract member at offset %Zu in '%s': %s"
msgstr "'%2$s' の オフセット %1$Zu のメンバーを抽出できません: %3$s"
-#: src/readelf.c:9160
+#: src/readelf.c:9163
#, c-format
msgid "Archive member '%s' contains:\n"
msgstr "アーカイブメンバー '%s' には以下があります:\n"
diff --git a/po/pl.po b/po/pl.po
index cb12febb..c46e53dd 100644
--- a/po/pl.po
+++ b/po/pl.po
@@ -6,7 +6,7 @@ msgid ""
msgstr ""
"Project-Id-Version: pl\n"
"Report-Msgid-Bugs-To: http://bugzilla.redhat.com/\n"
-"POT-Creation-Date: 2013-09-30 13:52+0200\n"
+"POT-Creation-Date: 2013-12-31 14:01+0100\n"
"PO-Revision-Date: 2012-09-02 19:12+0200\n"
"Last-Translator: Piotr Drąg <[email protected]>\n"
"Language-Team: Polish <[email protected]>\n"
@@ -23,12 +23,12 @@ msgstr ""
msgid "memory exhausted"
msgstr "pamięć wyczerpana"
-#: libasm/asm_error.c:65 libdw/dwarf_error.c:58 libdwfl/libdwflP.h:49
+#: libasm/asm_error.c:65 libdw/dwarf_error.c:58 libdwfl/libdwflP.h:51
#: libelf/elf_error.c:60
msgid "no error"
msgstr "brak błędu"
-#: libasm/asm_error.c:66 libdw/dwarf_error.c:67 libdwfl/libdwflP.h:51
+#: libasm/asm_error.c:66 libdw/dwarf_error.c:67 libdwfl/libdwflP.h:53
#: libelf/elf_error.c:91
msgid "out of memory"
msgstr "brak pamięci"
@@ -67,7 +67,7 @@ msgstr "błąd podczas wyprowadzania danych"
msgid "no backend support available"
msgstr "brak dostępnej obsługi zaplecza"
-#: libasm/asm_error.c:84 libdw/dwarf_error.c:59 libdwfl/libdwflP.h:50
+#: libasm/asm_error.c:84 libdw/dwarf_error.c:59 libdwfl/libdwflP.h:52
#: libelf/elf_error.c:63
msgid "unknown error"
msgstr "nieznany błąd"
@@ -164,7 +164,7 @@ msgstr "nieprawidłowa wersja DWARF"
msgid "invalid directory index"
msgstr "nieprawidłowy indeks katalogu"
-#: libdw/dwarf_error.c:84 libdwfl/libdwflP.h:70
+#: libdw/dwarf_error.c:84 libdwfl/libdwflP.h:72
msgid "address out of range"
msgstr "adres jest spoza zakresu"
@@ -184,7 +184,7 @@ msgstr "nieprawidłowy indeks wiersza"
msgid "invalid address range index"
msgstr "nieprawidłowy indeks zakresu adresów"
-#: libdw/dwarf_error.c:89 libdwfl/libdwflP.h:71
+#: libdw/dwarf_error.c:89 libdwfl/libdwflP.h:73
msgid "no matching address range"
msgstr "brak pasującego zakresu adresów"
@@ -244,127 +244,192 @@ msgstr "Jądro ze wszystkimi modułami"
msgid "Search path for separate debuginfo files"
msgstr "Wyszukuje ścieżkę dla oddzielnych plików debuginfo"
-#: libdwfl/argp-std.c:183
+#: libdwfl/argp-std.c:157
msgid "only one of -e, -p, -k, -K, or --core allowed"
msgstr "dopuszczalna jest tylko jedna z opcji -e, -p, -k, -K lub --core"
-#: libdwfl/argp-std.c:252
+#: libdwfl/argp-std.c:177
+#, fuzzy
+msgid "cannot attach to process"
+msgstr "nie można utworzyć drzewa wyszukiwania"
+
+#: libdwfl/argp-std.c:231
msgid "cannot load kernel symbols"
msgstr "nie można wczytać symboli jądra"
-#: libdwfl/argp-std.c:256
+#: libdwfl/argp-std.c:235
msgid "cannot find kernel modules"
msgstr "nie można odnaleźć modułów jądra"
-#: libdwfl/argp-std.c:273
+#: libdwfl/argp-std.c:252
msgid "cannot find kernel or modules"
msgstr "nie można odnaleźć jądra lub modułów"
-#: libdwfl/argp-std.c:315
+#: libdwfl/argp-std.c:291
#, c-format
msgid "cannot read ELF core file: %s"
msgstr "nie można odczytać pliku core ELF: %s"
-#: libdwfl/argp-std.c:333
+#: libdwfl/argp-std.c:307
+#, fuzzy
+msgid "cannot attach to core"
+msgstr "nie można utworzyć drzewa wyszukiwania"
+
+#: libdwfl/argp-std.c:314
msgid "No modules recognized in core file"
msgstr "Nie rozpoznano żadnych modułów w pliku core"
-#: libdwfl/libdwflP.h:52
+#: libdwfl/libdwflP.h:54
msgid "See errno"
msgstr "Proszę zobaczyć errno"
-#: libdwfl/libdwflP.h:53
+#: libdwfl/libdwflP.h:55
msgid "See elf_errno"
msgstr "Proszę zobaczyć elf_errno"
-#: libdwfl/libdwflP.h:54
+#: libdwfl/libdwflP.h:56
msgid "See dwarf_errno"
msgstr "Proszę zobaczyć dwarf_errno"
-#: libdwfl/libdwflP.h:55
+#: libdwfl/libdwflP.h:57
msgid "See ebl_errno (XXX missing)"
msgstr "Proszę zobaczyć ebl_errno (brak XXX)"
-#: libdwfl/libdwflP.h:56
+#: libdwfl/libdwflP.h:58
msgid "gzip decompression failed"
msgstr "dekompresja gzip nie powiodła się"
-#: libdwfl/libdwflP.h:57
+#: libdwfl/libdwflP.h:59
msgid "bzip2 decompression failed"
msgstr "dekompresja bzip2 nie powiodła się"
-#: libdwfl/libdwflP.h:58
+#: libdwfl/libdwflP.h:60
msgid "LZMA decompression failed"
msgstr "dekompresja LZMA nie powiodła się"
-#: libdwfl/libdwflP.h:59
+#: libdwfl/libdwflP.h:61
msgid "no support library found for machine"
msgstr "nie odnaleziono biblioteki obsługi dla komputera"
-#: libdwfl/libdwflP.h:60
+#: libdwfl/libdwflP.h:62
msgid "Callbacks missing for ET_REL file"
msgstr "Brak wywołań zwrotnych dla pliku ET_REL"
-#: libdwfl/libdwflP.h:61
+#: libdwfl/libdwflP.h:63
msgid "Unsupported relocation type"
msgstr "Nieobsługiwany typ relokacji"
-#: libdwfl/libdwflP.h:62
+#: libdwfl/libdwflP.h:64
msgid "r_offset is bogus"
msgstr "r_offset jest fałszywe"
-#: libdwfl/libdwflP.h:63 libelf/elf_error.c:111 libelf/elf_error.c:171
+#: libdwfl/libdwflP.h:65 libelf/elf_error.c:111 libelf/elf_error.c:171
msgid "offset out of range"
msgstr "offset spoza zakresu"
-#: libdwfl/libdwflP.h:64
+#: libdwfl/libdwflP.h:66
msgid "relocation refers to undefined symbol"
msgstr "relokacja odnosi się do nieokreślonego symbolu"
-#: libdwfl/libdwflP.h:65
+#: libdwfl/libdwflP.h:67
msgid "Callback returned failure"
msgstr "Wywołanie zwrotne zwróciło niepowodzenie"
-#: libdwfl/libdwflP.h:66
+#: libdwfl/libdwflP.h:68
msgid "No DWARF information found"
msgstr "Nie odnaleziono informacji DWARF"
-#: libdwfl/libdwflP.h:67
+#: libdwfl/libdwflP.h:69
msgid "No symbol table found"
msgstr "Nie odnaleziono tabeli symboli"
-#: libdwfl/libdwflP.h:68
+#: libdwfl/libdwflP.h:70
msgid "No ELF program headers"
msgstr "Brak nagłówków programu ELF"
-#: libdwfl/libdwflP.h:69
+#: libdwfl/libdwflP.h:71
msgid "address range overlaps an existing module"
msgstr "zakres adresów pokrywa się z istniejącym modułem"
-#: libdwfl/libdwflP.h:72
+#: libdwfl/libdwflP.h:74
msgid "image truncated"
msgstr "skrócono obraz"
-#: libdwfl/libdwflP.h:73
+#: libdwfl/libdwflP.h:75
msgid "ELF file opened"
msgstr "otwarto plik ELF"
-#: libdwfl/libdwflP.h:74
+#: libdwfl/libdwflP.h:76
msgid "not a valid ELF file"
msgstr "nie jest prawidłowym plikiem ELF"
-#: libdwfl/libdwflP.h:75
+#: libdwfl/libdwflP.h:77
msgid "cannot handle DWARF type description"
msgstr "nie można obsłużyć opisu typu DWARF"
-#: libdwfl/libdwflP.h:76
+#: libdwfl/libdwflP.h:78
msgid "ELF file does not match build ID"
msgstr "plik ELF nie posiada pasującego identyfikatora kopii"
-#: libdwfl/libdwflP.h:77
+#: libdwfl/libdwflP.h:79
msgid "corrupt .gnu.prelink_undo section data"
msgstr "uszkodzone dane sekcji .gnu.prelink_undo"
+#: libdwfl/libdwflP.h:80
+msgid "Internal error due to ebl"
+msgstr ""
+
+#: libdwfl/libdwflP.h:81
+msgid "Missing data in core file"
+msgstr ""
+
+#: libdwfl/libdwflP.h:82
+#, fuzzy
+msgid "Invalid register"
+msgstr "nieprawidłowy parametr"
+
+#: libdwfl/libdwflP.h:83
+msgid "Error reading process memory"
+msgstr ""
+
+#: libdwfl/libdwflP.h:84
+msgid "Couldn't find architecture of any ELF"
+msgstr ""
+
+#: libdwfl/libdwflP.h:85
+msgid "Error parsing /proc filesystem"
+msgstr ""
+
+#: libdwfl/libdwflP.h:86
+#, fuzzy
+msgid "Invalid DWARF"
+msgstr "nieprawidłowy DWARF"
+
+#: libdwfl/libdwflP.h:87
+msgid "Unsupported DWARF"
+msgstr ""
+
+#: libdwfl/libdwflP.h:88
+msgid "Unable to find more threads"
+msgstr ""
+
+#: libdwfl/libdwflP.h:89
+msgid "Dwfl already has attached state"
+msgstr ""
+
+#: libdwfl/libdwflP.h:90
+msgid "Dwfl has no attached state"
+msgstr ""
+
+#: libdwfl/libdwflP.h:91
+msgid "Unwinding not supported for this architecture"
+msgstr ""
+
+#: libdwfl/libdwflP.h:92
+#, fuzzy
+msgid "Invalid argument"
+msgstr "nieprawidłowy parametr"
+
#: libebl/eblbackendname.c:42
msgid "No backend"
msgstr "Brak zaplecza"
@@ -612,36 +677,41 @@ msgid "Also show symbol or section names"
msgstr "Wyświetla także nazwy symboli ub sekcji"
#: src/addr2line.c:64
+#, fuzzy
+msgid "Also show symbol and the section names"
+msgstr "Wyświetla także nazwy symboli ub sekcji"
+
+#: src/addr2line.c:65
msgid "Also show line table flags"
msgstr "Wyświetla także flagi tabeli wierszy"
-#: src/addr2line.c:66
+#: src/addr2line.c:67
msgid "Treat addresses as offsets relative to NAME section."
msgstr "Traktuje adresy jako offsety względne do sekcji NAZWA."
-#: src/addr2line.c:68
+#: src/addr2line.c:69
msgid ""
"Show all source locations that caused inline expansion of subroutines at the "
"address."
msgstr ""
-#: src/addr2line.c:71 src/elfcmp.c:72 src/findtextrel.c:67 src/nm.c:100
+#: src/addr2line.c:72 src/elfcmp.c:72 src/findtextrel.c:67 src/nm.c:100
#: src/strings.c:75
msgid "Miscellaneous:"
msgstr "Różne:"
-#: src/addr2line.c:80
+#: src/addr2line.c:81
msgid ""
"Locate source files and line information for ADDRs (in a.out by default)."
msgstr ""
"Odnajdywanie plików źródłowych i informacji o wierszu dla ADRESU (domyślne w "
"a.out)."
-#: src/addr2line.c:84
+#: src/addr2line.c:85
msgid "[ADDR...]"
msgstr "[ADRES...]"
-#: src/addr2line.c:192 src/ar.c:289 src/elfcmp.c:662 src/elflint.c:231
+#: src/addr2line.c:196 src/ar.c:289 src/elfcmp.c:662 src/elflint.c:231
#: src/findtextrel.c:162 src/ld.c:949 src/nm.c:265 src/objdump.c:181
#: src/ranlib.c:128 src/readelf.c:500 src/size.c:211 src/strings.c:219
#: src/strip.c:213 src/unstrip.c:226
@@ -657,7 +727,7 @@ msgstr ""
"BEZ JAKIEJKOLWIEK GWARANCJI, nawet domyślnej gwarancji PRZYDATNOŚCI\n"
"HANDLOWEJ albo PRZYDATNOŚCI DO OKREŚLONYCH ZASTOSOWAŃ.\n"
-#: src/addr2line.c:197 src/ar.c:294 src/elfcmp.c:667 src/elflint.c:236
+#: src/addr2line.c:201 src/ar.c:294 src/elfcmp.c:667 src/elflint.c:236
#: src/findtextrel.c:167 src/ld.c:954 src/nm.c:270 src/objdump.c:186
#: src/ranlib.c:133 src/readelf.c:505 src/size.c:216 src/strings.c:224
#: src/strip.c:218 src/unstrip.c:231
@@ -665,22 +735,22 @@ msgstr ""
msgid "Written by %s.\n"
msgstr "Napisane przez %s.\n"
-#: src/addr2line.c:437
+#: src/addr2line.c:474
#, c-format
msgid "Section syntax requires exactly one module"
msgstr "Składnia sekcji wymaga dokładnie jednego modułu"
-#: src/addr2line.c:460
+#: src/addr2line.c:497
#, c-format
msgid "offset %#<PRIxMAX> lies outside section '%s'"
msgstr "offset %#<PRIxMAX> leży poza sekcją \"%s\""
-#: src/addr2line.c:525
+#: src/addr2line.c:563
#, c-format
msgid "cannot find symbol '%s'"
msgstr "nie można odnaleźć symbolu \"%s\""
-#: src/addr2line.c:530
+#: src/addr2line.c:568
#, c-format
msgid "offset %#<PRIxMAX> lies outside contents of '%s'"
msgstr "offset %#<PRIxMAX> leży poza zawartością \"%s\""
@@ -3967,17 +4037,17 @@ msgstr "%s%s%s: nie rozpoznano formatu pliku"
msgid "cannot create search tree"
msgstr "nie można utworzyć drzewa wyszukiwania"
-#: src/nm.c:757 src/nm.c:1157 src/objdump.c:787 src/readelf.c:536
+#: src/nm.c:757 src/nm.c:1158 src/objdump.c:787 src/readelf.c:536
#: src/readelf.c:1071 src/readelf.c:1214 src/readelf.c:1362 src/readelf.c:1544
#: src/readelf.c:1744 src/readelf.c:1930 src/readelf.c:2140 src/readelf.c:2394
#: src/readelf.c:2460 src/readelf.c:2538 src/readelf.c:3036 src/readelf.c:3072
-#: src/readelf.c:3134 src/readelf.c:7805 src/readelf.c:8882 src/readelf.c:9029
-#: src/readelf.c:9097 src/size.c:417 src/size.c:491 src/strip.c:503
+#: src/readelf.c:3134 src/readelf.c:7805 src/readelf.c:8885 src/readelf.c:9032
+#: src/readelf.c:9100 src/size.c:417 src/size.c:491 src/strip.c:503
#, c-format
msgid "cannot get section header string table index"
msgstr "nie można uzyskać indeksu tabeli ciągów nagłówków sekcji"
-#: src/nm.c:783
+#: src/nm.c:784
#, c-format
msgid ""
"\n"
@@ -3990,7 +4060,7 @@ msgstr ""
"Symbole z %s:\n"
"\n"
-#: src/nm.c:786
+#: src/nm.c:787
#, c-format
msgid ""
"%*s%-*s %-*s Class Type %-*s %*s Section\n"
@@ -3999,22 +4069,22 @@ msgstr ""
"%*s%-*s %-*s Klasa Typ %-*s %*s Sekcja\n"
"\n"
-#: src/nm.c:1167
+#: src/nm.c:1168
#, c-format
msgid "%s: entry size in section `%s' is not what we expect"
msgstr "%s: rozmiar wpisu w sekcji \"%s\" nie jest tym, czego oczekiwano"
-#: src/nm.c:1171
+#: src/nm.c:1172
#, c-format
msgid "%s: size of section `%s' is not multiple of entry size"
msgstr "%s: rozmiar sekcji \"%s\" nie jest wielokrotnością rozmiaru wpisu"
-#: src/nm.c:1429
+#: src/nm.c:1430
#, c-format
msgid "%s%s%s%s: Invalid operation"
msgstr "%s%s%s%s: nieprawidłowe działanie"
-#: src/nm.c:1486
+#: src/nm.c:1487
#, c-format
msgid "%s%s%s: no symbols"
msgstr "%s%s%s: brak symboli"
@@ -4243,7 +4313,7 @@ msgstr "nie można utworzyć deskryptora ELF: %s"
msgid "cannot get section: %s"
msgstr "nie można uzyskać sekcji: %s"
-#: src/readelf.c:554 src/readelf.c:1092 src/readelf.c:1246 src/readelf.c:9049
+#: src/readelf.c:554 src/readelf.c:1092 src/readelf.c:1246 src/readelf.c:9052
#: src/unstrip.c:345 src/unstrip.c:376 src/unstrip.c:425 src/unstrip.c:533
#: src/unstrip.c:550 src/unstrip.c:586 src/unstrip.c:784 src/unstrip.c:1052
#: src/unstrip.c:1242 src/unstrip.c:1302 src/unstrip.c:1423 src/unstrip.c:1476
@@ -5896,12 +5966,12 @@ msgstr ""
msgid "cannot get debug context descriptor: %s"
msgstr "nie można uzyskać deskryptora kontekstu debugowania: %s"
-#: src/readelf.c:7952 src/readelf.c:8555 src/readelf.c:8666 src/readelf.c:8724
+#: src/readelf.c:7952 src/readelf.c:8558 src/readelf.c:8669 src/readelf.c:8727
#, c-format
msgid "cannot convert core note data: %s"
msgstr "nie można przekonwertować danych notatki core: %s"
-#: src/readelf.c:8296
+#: src/readelf.c:8299
#, c-format
msgid ""
"\n"
@@ -5910,21 +5980,21 @@ msgstr ""
"\n"
"%*s... <powtarza się jeszcze %u razy>..."
-#: src/readelf.c:8799
+#: src/readelf.c:8802
msgid " Owner Data size Type\n"
msgstr " Właściciel Rozmiar danych Typ\n"
-#: src/readelf.c:8817
+#: src/readelf.c:8820
#, c-format
msgid " %-13.*s %9<PRId32> %s\n"
msgstr " %-13.*s %9<PRId32> %s\n"
-#: src/readelf.c:8867
+#: src/readelf.c:8870
#, c-format
msgid "cannot get content of note section: %s"
msgstr "nie można uzyskać zawartości sekcji notatki: %s"
-#: src/readelf.c:8894
+#: src/readelf.c:8897
#, c-format
msgid ""
"\n"
@@ -5934,7 +6004,7 @@ msgstr ""
"Segment notatki [%2zu] \"%s\" o długości %<PRIu64> bajtów pod offsetem "
"%#0<PRIx64>:\n"
-#: src/readelf.c:8917
+#: src/readelf.c:8920
#, c-format
msgid ""
"\n"
@@ -5943,7 +6013,7 @@ msgstr ""
"\n"
"Segment notatki o długości %<PRIu64> bajtów pod offsetem %#0<PRIx64>:\n"
-#: src/readelf.c:8963
+#: src/readelf.c:8966
#, c-format
msgid ""
"\n"
@@ -5952,12 +6022,12 @@ msgstr ""
"\n"
"Sekcja [%Zu] \"%s\" nie posiada danych do zrzucenia.\n"
-#: src/readelf.c:8969 src/readelf.c:8992
+#: src/readelf.c:8972 src/readelf.c:8995
#, c-format
msgid "cannot get data for section [%Zu] '%s': %s"
msgstr "nie można uzyskać danych dla sekcji [%Zu] \"%s\": %s"
-#: src/readelf.c:8973
+#: src/readelf.c:8976
#, c-format
msgid ""
"\n"
@@ -5967,7 +6037,7 @@ msgstr ""
"Segment zrzutu szesnastkowego [%Zu] \"%s\", %<PRIu64> bajtów pod offsetem "
"%#0<PRIx64>:\n"
-#: src/readelf.c:8986
+#: src/readelf.c:8989
#, c-format
msgid ""
"\n"
@@ -5976,7 +6046,7 @@ msgstr ""
"\n"
"Sekcja [%Zu] \"%s\" nie posiada ciągów do zrzucenia.\n"
-#: src/readelf.c:8996
+#: src/readelf.c:8999
#, c-format
msgid ""
"\n"
@@ -5986,7 +6056,7 @@ msgstr ""
"Sekcja ciągów [%Zu] \"%s\" zawiera %<PRIu64> bajtów pod offsetem "
"%#0<PRIx64>:\n"
-#: src/readelf.c:9044
+#: src/readelf.c:9047
#, c-format
msgid ""
"\n"
@@ -5995,7 +6065,7 @@ msgstr ""
"\n"
"sekcja [%lu] nie istnieje"
-#: src/readelf.c:9073
+#: src/readelf.c:9076
#, c-format
msgid ""
"\n"
@@ -6004,12 +6074,12 @@ msgstr ""
"\n"
"sekcja \"%s\" nie istnieje"
-#: src/readelf.c:9130
+#: src/readelf.c:9133
#, c-format
msgid "cannot get symbol index of archive '%s': %s"
msgstr "nie można uzyskać indeksu symboli archiwum \"%s\": %s"
-#: src/readelf.c:9133
+#: src/readelf.c:9136
#, c-format
msgid ""
"\n"
@@ -6018,7 +6088,7 @@ msgstr ""
"\n"
"Archiwum \"%s\" nie posiada indeksu symboli\n"
-#: src/readelf.c:9137
+#: src/readelf.c:9140
#, c-format
msgid ""
"\n"
@@ -6027,12 +6097,12 @@ msgstr ""
"\n"
"Indeks archiwum \"%s\" posiada %Zu wpisów:\n"
-#: src/readelf.c:9155
+#: src/readelf.c:9158
#, c-format
msgid "cannot extract member at offset %Zu in '%s': %s"
msgstr "nie można wydobyć elementów pod offsetem %Zu w \"%s\": %s"
-#: src/readelf.c:9160
+#: src/readelf.c:9163
#, c-format
msgid "Archive member '%s' contains:\n"
msgstr "Element archiwum \"%s\" zawiera:\n"
diff --git a/po/uk.po b/po/uk.po
index 0acadc76..c4eab225 100644
--- a/po/uk.po
+++ b/po/uk.po
@@ -2,13 +2,13 @@
# Copyright (C) 2010 Free Software Foundation, Inc.
# This file is distributed under the same license as the elfutils package.
#
-# Yuri Chornoivan <[email protected]>, 2010, 2011, 2012.
+# Yuri Chornoivan <[email protected]>, 2010, 2011, 2012, 2013.
msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: http://bugzilla.redhat.com/\n"
-"POT-Creation-Date: 2013-09-30 13:52+0200\n"
-"PO-Revision-Date: 2012-08-11 17:59+0300\n"
+"POT-Creation-Date: 2013-12-31 14:01+0100\n"
+"PO-Revision-Date: 2013-10-09 17:50+0300\n"
"Last-Translator: Yuri Chornoivan <[email protected]>\n"
"Language-Team: Ukrainian <[email protected]>\n"
"Language: uk\n"
@@ -25,12 +25,12 @@ msgstr ""
msgid "memory exhausted"
msgstr "пам’ять вичерпано"
-#: libasm/asm_error.c:65 libdw/dwarf_error.c:58 libdwfl/libdwflP.h:49
+#: libasm/asm_error.c:65 libdw/dwarf_error.c:58 libdwfl/libdwflP.h:51
#: libelf/elf_error.c:60
msgid "no error"
msgstr "без помилок"
-#: libasm/asm_error.c:66 libdw/dwarf_error.c:67 libdwfl/libdwflP.h:51
+#: libasm/asm_error.c:66 libdw/dwarf_error.c:67 libdwfl/libdwflP.h:53
#: libelf/elf_error.c:91
msgid "out of memory"
msgstr "нестача пам'яті"
@@ -69,7 +69,7 @@ msgstr "помилка під час спроби виведення даних"
msgid "no backend support available"
msgstr "підтримки серверів не передбачено"
-#: libasm/asm_error.c:84 libdw/dwarf_error.c:59 libdwfl/libdwflP.h:50
+#: libasm/asm_error.c:84 libdw/dwarf_error.c:59 libdwfl/libdwflP.h:52
#: libelf/elf_error.c:63
msgid "unknown error"
msgstr "невідома помилка"
@@ -166,7 +166,7 @@ msgstr "некоректна версія DWARF"
msgid "invalid directory index"
msgstr "некоректний покажчик каталогу"
-#: libdw/dwarf_error.c:84 libdwfl/libdwflP.h:70
+#: libdw/dwarf_error.c:84 libdwfl/libdwflP.h:72
msgid "address out of range"
msgstr "некоректна адреса"
@@ -186,7 +186,7 @@ msgstr "некоректний номер рядка"
msgid "invalid address range index"
msgstr "некоректний індекс діапазону адрес"
-#: libdw/dwarf_error.c:89 libdwfl/libdwflP.h:71
+#: libdw/dwarf_error.c:89 libdwfl/libdwflP.h:73
msgid "no matching address range"
msgstr "не виявлено відповідного діапазону адрес"
@@ -246,128 +246,193 @@ msgstr "Ядро з усіма модулями"
msgid "Search path for separate debuginfo files"
msgstr "Шукати у вказаному каталозі окремі файли debuginfo"
-#: libdwfl/argp-std.c:183
+#: libdwfl/argp-std.c:157
msgid "only one of -e, -p, -k, -K, or --core allowed"
msgstr ""
"можна використовувати лише один за параметрів: -e, -p, -k, -K або --core"
-#: libdwfl/argp-std.c:252
+#: libdwfl/argp-std.c:177
+#, fuzzy
+msgid "cannot attach to process"
+msgstr "не вдалося створити дерево пошуку"
+
+#: libdwfl/argp-std.c:231
msgid "cannot load kernel symbols"
msgstr "не вдалося завантажити символи ядра"
-#: libdwfl/argp-std.c:256
+#: libdwfl/argp-std.c:235
msgid "cannot find kernel modules"
msgstr "не вдалося виявити модулі ядра"
-#: libdwfl/argp-std.c:273
+#: libdwfl/argp-std.c:252
msgid "cannot find kernel or modules"
msgstr "не вдалося виявити ядро або модулі"
-#: libdwfl/argp-std.c:315
+#: libdwfl/argp-std.c:291
#, c-format
msgid "cannot read ELF core file: %s"
msgstr "не вдалося прочитати файл core ELF: %s"
-#: libdwfl/argp-std.c:333
+#: libdwfl/argp-std.c:307
+#, fuzzy
+msgid "cannot attach to core"
+msgstr "не вдалося створити дерево пошуку"
+
+#: libdwfl/argp-std.c:314
msgid "No modules recognized in core file"
msgstr "Не вдалося виявити модулі у файлі core"
-#: libdwfl/libdwflP.h:52
+#: libdwfl/libdwflP.h:54
msgid "See errno"
msgstr "Див. errno"
-#: libdwfl/libdwflP.h:53
+#: libdwfl/libdwflP.h:55
msgid "See elf_errno"
msgstr "Див. elf_errno"
-#: libdwfl/libdwflP.h:54
+#: libdwfl/libdwflP.h:56
msgid "See dwarf_errno"
msgstr "Див. dwarf_errno"
-#: libdwfl/libdwflP.h:55
+#: libdwfl/libdwflP.h:57
msgid "See ebl_errno (XXX missing)"
msgstr "Див. ebl_errno (не виявлено XXX)"
-#: libdwfl/libdwflP.h:56
+#: libdwfl/libdwflP.h:58
msgid "gzip decompression failed"
msgstr "Помилка під час спроби видобування з gzip"
-#: libdwfl/libdwflP.h:57
+#: libdwfl/libdwflP.h:59
msgid "bzip2 decompression failed"
msgstr "Помилка під час спроби видобування з bzip2"
-#: libdwfl/libdwflP.h:58
+#: libdwfl/libdwflP.h:60
msgid "LZMA decompression failed"
msgstr "Помилка під час спроби видобування з LZMA"
-#: libdwfl/libdwflP.h:59
+#: libdwfl/libdwflP.h:61
msgid "no support library found for machine"
msgstr "у системі не виявлено бібліотеки підтримки"
-#: libdwfl/libdwflP.h:60
+#: libdwfl/libdwflP.h:62
msgid "Callbacks missing for ET_REL file"
msgstr "Немає зворотних викликів для файла ET_REL"
-#: libdwfl/libdwflP.h:61
+#: libdwfl/libdwflP.h:63
msgid "Unsupported relocation type"
msgstr "Непідтримуваний тип пересування"
-#: libdwfl/libdwflP.h:62
+#: libdwfl/libdwflP.h:64
msgid "r_offset is bogus"
msgstr "r_offset є фіктивним"
-#: libdwfl/libdwflP.h:63 libelf/elf_error.c:111 libelf/elf_error.c:171
+#: libdwfl/libdwflP.h:65 libelf/elf_error.c:111 libelf/elf_error.c:171
msgid "offset out of range"
msgstr "перевищення можливого зміщення"
-#: libdwfl/libdwflP.h:64
+#: libdwfl/libdwflP.h:66
msgid "relocation refers to undefined symbol"
msgstr "пересування посилається на невизначений символ."
-#: libdwfl/libdwflP.h:65
+#: libdwfl/libdwflP.h:67
msgid "Callback returned failure"
msgstr "Зворотним викликом повернуто помилку"
-#: libdwfl/libdwflP.h:66
+#: libdwfl/libdwflP.h:68
msgid "No DWARF information found"
msgstr "Не виявлено відомостей DWARF"
-#: libdwfl/libdwflP.h:67
+#: libdwfl/libdwflP.h:69
msgid "No symbol table found"
msgstr "Не виявлено таблиці символів"
-#: libdwfl/libdwflP.h:68
+#: libdwfl/libdwflP.h:70
msgid "No ELF program headers"
msgstr "Немає заголовків програми ELF"
-#: libdwfl/libdwflP.h:69
+#: libdwfl/libdwflP.h:71
msgid "address range overlaps an existing module"
msgstr "діапазон адрес перекриває існуючий модуль"
-#: libdwfl/libdwflP.h:72
+#: libdwfl/libdwflP.h:74
msgid "image truncated"
msgstr "образ обрізано"
-#: libdwfl/libdwflP.h:73
+#: libdwfl/libdwflP.h:75
msgid "ELF file opened"
msgstr "Відкритий файл ELF"
-#: libdwfl/libdwflP.h:74
+#: libdwfl/libdwflP.h:76
msgid "not a valid ELF file"
msgstr "не є коректним файлом ELF"
-#: libdwfl/libdwflP.h:75
+#: libdwfl/libdwflP.h:77
msgid "cannot handle DWARF type description"
msgstr "не вдалося обробити опис типу DWARF"
-#: libdwfl/libdwflP.h:76
+#: libdwfl/libdwflP.h:78
msgid "ELF file does not match build ID"
msgstr "Файл ELF не відповідає ідентифікатору збирання"
-#: libdwfl/libdwflP.h:77
+#: libdwfl/libdwflP.h:79
msgid "corrupt .gnu.prelink_undo section data"
msgstr "дані розділу «.gnu.prelink_undo» пошкоджено"
+#: libdwfl/libdwflP.h:80
+msgid "Internal error due to ebl"
+msgstr ""
+
+#: libdwfl/libdwflP.h:81
+msgid "Missing data in core file"
+msgstr ""
+
+#: libdwfl/libdwflP.h:82
+#, fuzzy
+msgid "Invalid register"
+msgstr "некоректний параметр"
+
+#: libdwfl/libdwflP.h:83
+msgid "Error reading process memory"
+msgstr ""
+
+#: libdwfl/libdwflP.h:84
+msgid "Couldn't find architecture of any ELF"
+msgstr ""
+
+#: libdwfl/libdwflP.h:85
+msgid "Error parsing /proc filesystem"
+msgstr ""
+
+#: libdwfl/libdwflP.h:86
+#, fuzzy
+msgid "Invalid DWARF"
+msgstr "некоректний запис DWARF"
+
+#: libdwfl/libdwflP.h:87
+msgid "Unsupported DWARF"
+msgstr ""
+
+#: libdwfl/libdwflP.h:88
+msgid "Unable to find more threads"
+msgstr ""
+
+#: libdwfl/libdwflP.h:89
+msgid "Dwfl already has attached state"
+msgstr ""
+
+#: libdwfl/libdwflP.h:90
+msgid "Dwfl has no attached state"
+msgstr ""
+
+#: libdwfl/libdwflP.h:91
+msgid "Unwinding not supported for this architecture"
+msgstr ""
+
+#: libdwfl/libdwflP.h:92
+#, fuzzy
+msgid "Invalid argument"
+msgstr "некоректний параметр"
+
#: libebl/eblbackendname.c:42
msgid "No backend"
msgstr "Немає сервера"
@@ -412,7 +477,7 @@ msgstr " Семафор: "
#: libebl/eblobjnote.c:129
#, c-format
msgid " Provider: "
-msgstr " остачальник: "
+msgstr " Постачальник: "
#: libebl/eblobjnote.c:131
#, c-format
@@ -615,34 +680,41 @@ msgid "Also show symbol or section names"
msgstr "Показувати також назви символів та розділів"
#: src/addr2line.c:64
+#, fuzzy
+msgid "Also show symbol and the section names"
+msgstr "Показувати також назви символів та розділів"
+
+#: src/addr2line.c:65
msgid "Also show line table flags"
msgstr "Показувати також прапорці рядків таблиці"
-#: src/addr2line.c:66
+#: src/addr2line.c:67
msgid "Treat addresses as offsets relative to NAME section."
msgstr "Вважати адреси зміщеннями відносно розділу НАЗВА."
-#: src/addr2line.c:68
+#: src/addr2line.c:69
msgid ""
"Show all source locations that caused inline expansion of subroutines at the "
"address."
msgstr ""
+"Показати усі місця у початковому коді, у яких було виявлено вбудоване "
+"розгортання підпрограм за вказаною адресою."
-#: src/addr2line.c:71 src/elfcmp.c:72 src/findtextrel.c:67 src/nm.c:100
+#: src/addr2line.c:72 src/elfcmp.c:72 src/findtextrel.c:67 src/nm.c:100
#: src/strings.c:75
msgid "Miscellaneous:"
msgstr "Інше:"
-#: src/addr2line.c:80
+#: src/addr2line.c:81
msgid ""
"Locate source files and line information for ADDRs (in a.out by default)."
msgstr "Шукати АДРЕСИ у файлах кодів та даних про рядки (типово, у a.out)."
-#: src/addr2line.c:84
+#: src/addr2line.c:85
msgid "[ADDR...]"
msgstr "[АДРЕСА...]"
-#: src/addr2line.c:192 src/ar.c:289 src/elfcmp.c:662 src/elflint.c:231
+#: src/addr2line.c:196 src/ar.c:289 src/elfcmp.c:662 src/elflint.c:231
#: src/findtextrel.c:162 src/ld.c:949 src/nm.c:265 src/objdump.c:181
#: src/ranlib.c:128 src/readelf.c:500 src/size.c:211 src/strings.c:219
#: src/strip.c:213 src/unstrip.c:226
@@ -657,7 +729,7 @@ msgstr ""
"початкових кодах. Умовами ліцензування програми НЕ передбачено жодних "
"гарантій, зокрема гарантій працездатності або придатності для певної мети.\n"
-#: src/addr2line.c:197 src/ar.c:294 src/elfcmp.c:667 src/elflint.c:236
+#: src/addr2line.c:201 src/ar.c:294 src/elfcmp.c:667 src/elflint.c:236
#: src/findtextrel.c:167 src/ld.c:954 src/nm.c:270 src/objdump.c:186
#: src/ranlib.c:133 src/readelf.c:505 src/size.c:216 src/strings.c:224
#: src/strip.c:218 src/unstrip.c:231
@@ -665,22 +737,22 @@ msgstr ""
msgid "Written by %s.\n"
msgstr "Автор — %s.\n"
-#: src/addr2line.c:437
+#: src/addr2line.c:474
#, c-format
msgid "Section syntax requires exactly one module"
msgstr "Синтаксис розділів вимагає точного одного модуля"
-#: src/addr2line.c:460
+#: src/addr2line.c:497
#, c-format
msgid "offset %#<PRIxMAX> lies outside section '%s'"
msgstr "зміщення %#<PRIxMAX> розташовано поза межами розділу «%s»"
-#: src/addr2line.c:525
+#: src/addr2line.c:563
#, c-format
msgid "cannot find symbol '%s'"
msgstr "не вдалося знайти символ «%s»"
-#: src/addr2line.c:530
+#: src/addr2line.c:568
#, c-format
msgid "offset %#<PRIxMAX> lies outside contents of '%s'"
msgstr "зміщення %#<PRIxMAX> розташовано поза межами вмісту «%s»"
@@ -3996,17 +4068,17 @@ msgstr "%s%s%s: не вдалося розпізнати формат файла
msgid "cannot create search tree"
msgstr "не вдалося створити дерево пошуку"
-#: src/nm.c:757 src/nm.c:1157 src/objdump.c:787 src/readelf.c:536
+#: src/nm.c:757 src/nm.c:1158 src/objdump.c:787 src/readelf.c:536
#: src/readelf.c:1071 src/readelf.c:1214 src/readelf.c:1362 src/readelf.c:1544
#: src/readelf.c:1744 src/readelf.c:1930 src/readelf.c:2140 src/readelf.c:2394
#: src/readelf.c:2460 src/readelf.c:2538 src/readelf.c:3036 src/readelf.c:3072
-#: src/readelf.c:3134 src/readelf.c:7805 src/readelf.c:8882 src/readelf.c:9029
-#: src/readelf.c:9097 src/size.c:417 src/size.c:491 src/strip.c:503
+#: src/readelf.c:3134 src/readelf.c:7805 src/readelf.c:8885 src/readelf.c:9032
+#: src/readelf.c:9100 src/size.c:417 src/size.c:491 src/strip.c:503
#, c-format
msgid "cannot get section header string table index"
msgstr "не вдалося визначити індекс заголовка розділу у таблиці рядків"
-#: src/nm.c:783
+#: src/nm.c:784
#, c-format
msgid ""
"\n"
@@ -4019,7 +4091,7 @@ msgstr ""
"Символи з %s:\n"
"\n"
-#: src/nm.c:786
+#: src/nm.c:787
#, c-format
msgid ""
"%*s%-*s %-*s Class Type %-*s %*s Section\n"
@@ -4028,22 +4100,22 @@ msgstr ""
"%*s%-*s %-*s Клас Тип %-*s %*s Розділ\n"
"\n"
-#: src/nm.c:1167
+#: src/nm.c:1168
#, c-format
msgid "%s: entry size in section `%s' is not what we expect"
msgstr "%s: розмір запису у розділі «%s» не є очікуваним"
-#: src/nm.c:1171
+#: src/nm.c:1172
#, c-format
msgid "%s: size of section `%s' is not multiple of entry size"
msgstr "%s: розмір розділу «%s» не є кратним до розміру запису"
-#: src/nm.c:1429
+#: src/nm.c:1430
#, c-format
msgid "%s%s%s%s: Invalid operation"
msgstr "%s%s%s%s: некоректна дія"
-#: src/nm.c:1486
+#: src/nm.c:1487
#, c-format
msgid "%s%s%s: no symbols"
msgstr "%s%s%s: немає символів"
@@ -4147,14 +4219,15 @@ msgid "error while freeing sub-ELF descriptor: %s"
msgstr "помилка під час спроби вивільнення дескриптора під-ELF: %s"
#: src/readelf.c:71
-#, fuzzy
msgid "ELF input selection:"
-msgstr "Вибір виводу ELF:"
+msgstr "Вибір вихідних даних ELF:"
#: src/readelf.c:73
msgid ""
"Use the named SECTION (default .gnu_debugdata) as (compressed) ELF input data"
msgstr ""
+"Використовувати вказаний за іменем РОЗДІЛ (типово .gnu_debugdata) як "
+"(стиснені) вхідні дані ELF"
#: src/readelf.c:75
msgid "ELF output selection:"
@@ -4213,15 +4286,14 @@ msgid "Additional output selection:"
msgstr "Додатковий вибір виводу:"
#: src/readelf.c:97
-#, fuzzy
msgid ""
"Display DWARF section content. SECTION can be one of abbrev, aranges, "
"decodedaranges, frame, gdb_index, info, loc, line, decodedline, ranges, "
"pubnames, str, macinfo, macro or exception"
msgstr ""
"Показати вміст розділу DWARF. Значенням РОЗДІЛ може бути abbrev, aranges, "
-"frame, gdb_index, info, loc, line, ranges, pubnames, str, macinfo, macro або "
-"exception"
+"decodedaranges, frame, gdb_index, info, loc, line, decodedline, ranges, "
+"pubnames, str, macinfo, macro або exception"
#: src/readelf.c:101
msgid "Dump the uninterpreted contents of SECTION, by number or name"
@@ -4243,13 +4315,12 @@ msgstr "Керування виводом:"
#: src/readelf.c:110
msgid "Do not find symbol names for addresses in DWARF data"
-msgstr "Не шукати назви символів для адресу у даних DWARF"
+msgstr "Не шукати назви символів для адрес у даних DWARF"
#: src/readelf.c:112
-#, fuzzy
msgid ""
"Display just offsets instead of resolving values to addresses in DWARF data"
-msgstr "Не шукати назви символів для адресу у даних DWARF"
+msgstr "Показати лише зміщення, а не визначені значення адреси у даних DWARF"
#: src/readelf.c:114
msgid "Ignored for compatibility (lines always wide)"
@@ -4274,7 +4345,7 @@ msgstr "не вдалося створити дескриптор Elf: %s"
msgid "cannot get section: %s"
msgstr "не вдалося отримати розділ: %s"
-#: src/readelf.c:554 src/readelf.c:1092 src/readelf.c:1246 src/readelf.c:9049
+#: src/readelf.c:554 src/readelf.c:1092 src/readelf.c:1246 src/readelf.c:9052
#: src/unstrip.c:345 src/unstrip.c:376 src/unstrip.c:425 src/unstrip.c:533
#: src/unstrip.c:550 src/unstrip.c:586 src/unstrip.c:784 src/unstrip.c:1052
#: src/unstrip.c:1242 src/unstrip.c:1302 src/unstrip.c:1423 src/unstrip.c:1476
@@ -4284,9 +4355,9 @@ msgid "cannot get section header: %s"
msgstr "не вдалося отримати заголовок розділу: %s"
#: src/readelf.c:562
-#, fuzzy, c-format
+#, c-format
msgid "cannot get section name"
-msgstr "не вдалося отримати заголовок розділу\n"
+msgstr "не вдалося отримати назву розділу"
#: src/readelf.c:571 src/readelf.c:5126 src/readelf.c:7299 src/readelf.c:7401
#: src/readelf.c:7559
@@ -4295,14 +4366,14 @@ msgid "cannot get %s content: %s"
msgstr "не вдалося отримати дані %s: %s"
#: src/readelf.c:587
-#, fuzzy, c-format
+#, c-format
msgid "cannot create temp file '%s'"
-msgstr "не вдалося створити файл «%s»: %s"
+msgstr "не вдалося створити файл тимчасових даних «%s»"
#: src/readelf.c:596
-#, fuzzy, c-format
+#, c-format
msgid "cannot write section data"
-msgstr "не вдалося прочитати дані розділу: %s"
+msgstr "не вдалося записати дані розділу"
#: src/readelf.c:602 src/readelf.c:619 src/readelf.c:648
#, c-format
@@ -4310,9 +4381,9 @@ msgid "error while closing Elf descriptor: %s"
msgstr "помилка під час спроби закриття дескриптора Elf: %s"
#: src/readelf.c:609
-#, fuzzy, c-format
+#, c-format
msgid "error while rewinding file descriptor"
-msgstr "помилка під час спроби закриття дескриптора Elf: %s"
+msgstr "помилка під час повернення до початкового значення дескриптора файла"
#: src/readelf.c:643
#, c-format
@@ -4320,9 +4391,9 @@ msgid "'%s' is not an archive, cannot print archive index"
msgstr "«%s» не є архівом, виведення покажчика архіву неможливе"
#: src/readelf.c:728
-#, fuzzy, c-format
+#, c-format
msgid "No such section '%s' in '%s'"
-msgstr "не вдалося прочитати розділ нотаток [%zu] «%s» у «%s»: %s"
+msgstr "У «%2$s» немає розділу «%1$s»"
#: src/readelf.c:755
#, c-format
@@ -5140,9 +5211,9 @@ msgid "%s %#<PRIx64> used with different offset sizes"
msgstr "%s %#<PRIx64> використано з різними розмірами зміщень"
#: src/readelf.c:4206
-#, fuzzy, c-format
+#, c-format
msgid "%s %#<PRIx64> used with different base addresses"
-msgstr "%s %#<PRIx64> використано з різними розмірами адрес"
+msgstr "%s %#<PRIx64> використано з різними базовими адресами"
#: src/readelf.c:4288
#, c-format
@@ -5253,63 +5324,67 @@ msgid "invalid data in section [%zu] '%s'"
msgstr "некоректні дані у розділі [%zu] «%s»"
#: src/readelf.c:4497
-#, fuzzy, c-format
+#, c-format
msgid ""
"\n"
" Length: %6<PRIu64>\n"
-msgstr " Довжина зміщення: %<PRIu8>\n"
+msgstr ""
+"\n"
+" Довжина: %6<PRIu64>\n"
#: src/readelf.c:4509
-#, fuzzy, c-format
+#, c-format
msgid " DWARF version: %6<PRIuFAST16>\n"
-msgstr " Версія: %<PRIu16>\n"
+msgstr " версія DWARF: %6<PRIuFAST16>\n"
#: src/readelf.c:4513
#, c-format
msgid "unsupported aranges version"
-msgstr ""
+msgstr "непідтримувана версія aranges"
#: src/readelf.c:4524
-#, fuzzy, c-format
+#, c-format
msgid " CU offset: %6<PRIx64>\n"
-msgstr " зміщення CU: %#<PRIx32>\n"
+msgstr " зміщення CU: %6<PRIx64>\n"
#: src/readelf.c:4530
-#, fuzzy, c-format
+#, c-format
msgid " Address size: %6<PRIu64>\n"
-msgstr " зміщення адреси: %#<PRIx32>\n"
+msgstr " Розмір адреси: %6<PRIu64>\n"
#: src/readelf.c:4534
-#, fuzzy, c-format
+#, c-format
msgid "unsupported address size"
-msgstr "немає значення адреси"
+msgstr "непідтримуваний розмір адреси"
#: src/readelf.c:4539
-#, fuzzy, c-format
+#, c-format
msgid ""
" Segment size: %6<PRIu64>\n"
"\n"
-msgstr " встановити файл у %<PRIu64>\n"
+msgstr ""
+" Розмір сегмента: %6<PRIu64>\n"
+"\n"
#: src/readelf.c:4543
#, c-format
msgid "unsupported segment size"
-msgstr ""
+msgstr "непідтримуваний розмір сегмента"
#: src/readelf.c:4583
-#, fuzzy, c-format
+#, c-format
msgid " %s..%s (%<PRIx64>)\n"
-msgstr " %s: %<PRId64>\n"
+msgstr " %s..%s (%<PRIx64>)\n"
#: src/readelf.c:4586
-#, fuzzy, c-format
+#, c-format
msgid " %s..%s\n"
-msgstr " [%6tx] %s..%s\n"
+msgstr " %s..%s\n"
#: src/readelf.c:4595
#, c-format
msgid " %Zu padding bytes\n"
-msgstr ""
+msgstr " %Zu байтів доповнення\n"
#: src/readelf.c:4613
#, c-format
@@ -5342,9 +5417,9 @@ msgid " %s..%s\n"
msgstr " %s..%s\n"
#: src/readelf.c:5118
-#, fuzzy, c-format
+#, c-format
msgid "cannot get ELF: %s"
-msgstr "не вдалося отримати заголовок ELF: %s"
+msgstr "не вдалося отримати ELF: %s"
#: src/readelf.c:5133
#, c-format
@@ -5469,7 +5544,7 @@ msgid "cannot get next DIE: %s"
msgstr "не вдалося визначити наступний DIE: %s"
#: src/readelf.c:5945
-#, fuzzy, c-format
+#, c-format
msgid ""
"\n"
"DWARF section [%2zu] '%s' at offset %#<PRIx64>:\n"
@@ -5477,6 +5552,7 @@ msgid ""
msgstr ""
"\n"
"Розділ DWARF [%2zu] «%s» зі зміщенням %#<PRIx64>:\n"
+"\n"
#: src/readelf.c:6044
#, c-format
@@ -5697,9 +5773,9 @@ msgid "%*s*** non-terminated string at end of section"
msgstr "%*s*** незавершений рядок наприкінці розділу"
#: src/readelf.c:6858
-#, fuzzy, c-format
+#, c-format
msgid " Offset: 0x%<PRIx64>\n"
-msgstr " Зміщення: 0x%zx\n"
+msgstr " Зміщення: 0x%<PRIx64>\n"
#: src/readelf.c:6870
#, c-format
@@ -5912,12 +5988,12 @@ msgstr ""
msgid "cannot get debug context descriptor: %s"
msgstr "не вдалося отримати дескриптор контексту зневаджування: %s"
-#: src/readelf.c:7952 src/readelf.c:8555 src/readelf.c:8666 src/readelf.c:8724
+#: src/readelf.c:7952 src/readelf.c:8558 src/readelf.c:8669 src/readelf.c:8727
#, c-format
msgid "cannot convert core note data: %s"
msgstr "не вдалося перетворити дані запису ядра: %s"
-#: src/readelf.c:8296
+#: src/readelf.c:8299
#, c-format
msgid ""
"\n"
@@ -5926,21 +6002,21 @@ msgstr ""
"\n"
"%*s... <повторюється %u разів> ..."
-#: src/readelf.c:8799
+#: src/readelf.c:8802
msgid " Owner Data size Type\n"
msgstr " Власник Розм. даних Тип\n"
-#: src/readelf.c:8817
+#: src/readelf.c:8820
#, c-format
msgid " %-13.*s %9<PRId32> %s\n"
msgstr " %-13.*s %9<PRId32> %s\n"
-#: src/readelf.c:8867
+#: src/readelf.c:8870
#, c-format
msgid "cannot get content of note section: %s"
msgstr "не вдалося отримати вміст розділу записів: %s"
-#: src/readelf.c:8894
+#: src/readelf.c:8897
#, c-format
msgid ""
"\n"
@@ -5950,7 +6026,7 @@ msgstr ""
"Розділ записів (note) [%2zu] «%s» з %<PRIu64> байтів за зміщенням "
"%#0<PRIx64>:\n"
-#: src/readelf.c:8917
+#: src/readelf.c:8920
#, c-format
msgid ""
"\n"
@@ -5959,7 +6035,7 @@ msgstr ""
"\n"
"Сегмент записів з %<PRIu64> байтів за зміщенням %#0<PRIx64>:\n"
-#: src/readelf.c:8963
+#: src/readelf.c:8966
#, c-format
msgid ""
"\n"
@@ -5968,12 +6044,12 @@ msgstr ""
"\n"
"У розділі [%Zu] «%s» не міститься даних для створення дампу.\n"
-#: src/readelf.c:8969 src/readelf.c:8992
+#: src/readelf.c:8972 src/readelf.c:8995
#, c-format
msgid "cannot get data for section [%Zu] '%s': %s"
msgstr "не вдалося отримати дані для розділу [%Zu] «%s»: %s"
-#: src/readelf.c:8973
+#: src/readelf.c:8976
#, c-format
msgid ""
"\n"
@@ -5982,7 +6058,7 @@ msgstr ""
"\n"
"Шіст. дамп розділу [%Zu] «%s», %<PRIu64> байтів за зміщенням %#0<PRIx64>:\n"
-#: src/readelf.c:8986
+#: src/readelf.c:8989
#, c-format
msgid ""
"\n"
@@ -5991,7 +6067,7 @@ msgstr ""
"\n"
"У розділі [%Zu] «%s» не міститься рядків для створення дампу.\n"
-#: src/readelf.c:8996
+#: src/readelf.c:8999
#, c-format
msgid ""
"\n"
@@ -6000,7 +6076,7 @@ msgstr ""
"\n"
"Розділ рядків [%Zu] «%s» містить %<PRIu64> байтів за зміщенням %#0<PRIx64>:\n"
-#: src/readelf.c:9044
+#: src/readelf.c:9047
#, c-format
msgid ""
"\n"
@@ -6009,7 +6085,7 @@ msgstr ""
"\n"
"розділу [%lu] не існує"
-#: src/readelf.c:9073
+#: src/readelf.c:9076
#, c-format
msgid ""
"\n"
@@ -6018,12 +6094,12 @@ msgstr ""
"\n"
"розділу «%s» не існує"
-#: src/readelf.c:9130
+#: src/readelf.c:9133
#, c-format
msgid "cannot get symbol index of archive '%s': %s"
msgstr "не вдалося отримати покажчик символів архіву «%s»: %s"
-#: src/readelf.c:9133
+#: src/readelf.c:9136
#, c-format
msgid ""
"\n"
@@ -6032,7 +6108,7 @@ msgstr ""
"\n"
"У архіві «%s» немає покажчика символів\n"
-#: src/readelf.c:9137
+#: src/readelf.c:9140
#, c-format
msgid ""
"\n"
@@ -6041,12 +6117,12 @@ msgstr ""
"\n"
"Покажчик архіву «%s» містить %Zu записів:\n"
-#: src/readelf.c:9155
+#: src/readelf.c:9158
#, c-format
msgid "cannot extract member at offset %Zu in '%s': %s"
msgstr "не вдалося видобути елемент за зміщенням %Zu у «%s»: %s"
-#: src/readelf.c:9160
+#: src/readelf.c:9163
#, c-format
msgid "Archive member '%s' contains:\n"
msgstr "Елемент архіву «%s» містить:\n"
diff --git a/src/ChangeLog b/src/ChangeLog
index 6adfea71..6685fcd2 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,176 @@
+2014-01-02 Mark Wielaard <[email protected]>
+
+ * stack.c (show_raw): Declare unconditionally.
+ (parse_opt): Handle '-r' unconditionally.
+ (main): Show "raw" option even without USE_DEMANGLE.
+
+2014-01-02 Mark Wielaard <[email protected]>
+
+ * stack.c (print_frames): Print 0x before build-id hex-offset.
+
+2014-01-02 Mark Wielaard <[email protected]>
+
+ * stack.c (maxframes): Increase to 2048.
+ (struct frames): Add allocated field.
+ (frame_callback): If frames used is frames allocated, realloc.
+ (print_frames): Show an error if maxframes has been reached.
+ (parse_opt): Allow -n 0 for unlimited frames.
+ (main): Document -n 0 and new default 2048 frames. Allocate initial
+ number of frames with malloc.
+
+2013-12-30 Mark Wielaard <[email protected]>
+
+ * stack.c (parse_opt): Explicitly call dwfl_linux_proc_attach
+ or dwfl_core_file_attach and check for errors.
+
+2013-12-28 Mark Wielaard <[email protected]>
+
+ * stack.c (print_frames): Remove address width code and use...
+ (get_addr_width): ...this new function.
+ (show_modules): New static boolean.
+ (module_callback): New static function.
+ (parse_opt): Handle '-l'.
+ (main): Add 'l' to options. If show_modules then use dwfl_getmodules
+ with module_callback to show all detected modules and possible
+ build_id, elf and dwarf files.
+
+2013-12-27 Mark Wielaard <[email protected]>
+
+ * 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 <[email protected]>
+
+ * 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 <[email protected]>
+
+ * stack.c (OPT_DEBUGINFO): New define.
+ (OPT_COREFILE): Likewise.
+ (pid): New static.
+ (core_fd): Likewise.
+ (core): Likewise.
+ (exec): Likewise.
+ (debuginfo_path): Likewise.
+ (parse_opt): Handle '-p', '--core', '-e' and '--debuginfo-path'.
+ Do argument sanity checking. Setup Dwfl.
+ (main): Add 'p', 'core', 'e' and 'debuginfo-path' to options.
+ Remove argp_child children, simplify argp doc, remove custom
+ usage message and construction of dwfl with dwfl_standard_argp.
+ Use pid directly as tid. close core and core_fd if opened. Print
+ pid of process or core.
+
+2013-12-23 Mark Wielaard <[email protected]>
+
+ * 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 <[email protected]>
+
+ * 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 <[email protected]>
+
+ * 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 <[email protected]>
+
+ * addr2line.c (options): Add symbol-sections, 'x'.
+ (show_symbol_sections): New static bool.
+ (parse_opt): Handle 'x'.
+ (print_addrsym): Use dwfl_module_addrinfo value.r
+ Also show section of address with show_symbol_sections.
+ (find_symbol): Use dwfl_module_getsym_info and set value.
+ (handle_address): Request value and use it instead of sym.st_value.
+ * readelf.c (format_dwarf_addr): Use dwfl_module_addrinfo to get
+ name and offset.
+
+2013-12-17 Masatake YAMATO <[email protected]>
+ Mark Wielaard <[email protected]>
+
+ * stack.c (show_activation, show_module, show_source): New variables.
+ (parse_opt): Set show_activation if -a option is given.
+ Set show_module if -m option is given. Set show_source if -s option
+ is given. Set all show booleans when -v option is given.
+ (main): Added `-a', `-m', `-s', and `-v' to the help message.
+ (frame_callback): Print module and source file information.
+
+2013-11-25 Petr Machata <[email protected]>
+
+ * elflint.c (valid_e_machine): Add EM_AARCH64.
+
+2013-11-14 Petr Machata <[email protected]>
+
+ * readelf.c (handle_core_item) <'h'>: New branch for handling
+ fields that shouldn't be displayed.
+
+2013-11-10 Mark Wielaard <[email protected]>
+
+ * stack.c: Use ARGP_PROGRAM_VERSION_HOOK_DEF and
+ ARGP_PROGRAM_BUG_ADDRESS_DEF.
+ (print_version): New function.
+
+2013-11-09 Mark Wielaard <[email protected]>
+
+ * arlib.c (arlib_init): Call snprintf before using the result
+ with memcpy.
+ (arlib_finalize): Likewise.
+ * nm.c (show_symbols_sysv): Don't modify cnt inside assert.
+
+2013-11-07 Jan Kratochvil <[email protected]>
+
+ * Makefile.am (bin_PROGRAMS): Add stack.
+ (stack_LDADD): New.
+ * stack.c: New file.
+
+2013-11-05 Mark Wielaard <[email protected]>
+
+ * readelf.c (print_debug_ranges_section): Cast address to size_t
+ before comparison.
+ (print_debug_loc_section): Likewise.
+
+2013-10-18 Mark Wielaard <[email protected]>
+
+ * ar.c (main): Correct operation check when instance_specifed is set.
+
2013-09-26 Petr Machata <[email protected]>
* readelf.c (handle_file_note): New function.
diff --git a/src/Makefile.am b/src/Makefile.am
index 674846d8..9a78348f 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,6 +1,6 @@
## Process this file with automake to create Makefile.in
##
-## Copyright (C) 1996-2012 Red Hat, Inc.
+## Copyright (C) 1996-2013 Red Hat, Inc.
## This file is part of elfutils.
##
## This file is free software; you can redistribute it and/or modify
@@ -37,7 +37,7 @@ native_ld = @native_ld@
base_cpu = @base_cpu@
bin_PROGRAMS = readelf nm size strip ld elflint findtextrel addr2line \
- elfcmp objdump ranlib strings ar unstrip
+ elfcmp objdump ranlib strings ar unstrip stack
ld_dsos = libld_elf_i386_pic.a
@@ -115,6 +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 \
+ $(demanglelib)
ldlex.o: ldscript.c
ldlex_no_Werror = yes
diff --git a/src/addr2line.c b/src/addr2line.c
index 82e80b12..0541fb68 100644
--- a/src/addr2line.c
+++ b/src/addr2line.c
@@ -61,6 +61,7 @@ static const struct argp_option options[] =
N_("Show absolute file names using compilation directory"), 0 },
{ "functions", 'f', NULL, 0, N_("Also show function names"), 0 },
{ "symbols", 'S', NULL, 0, N_("Also show symbol or section names"), 0 },
+ { "symbols-sections", 'x', NULL, 0, N_("Also show symbol and the section names"), 0 },
{ "flags", 'F', NULL, 0, N_("Also show line table flags"), 0 },
{ "section", 'j', "NAME", 0,
N_("Treat addresses as offsets relative to NAME section."), 0 },
@@ -114,6 +115,9 @@ static bool show_functions;
/* True if ELF symbol or section info should be shown. */
static bool show_symbols;
+/* True if section associated with a symbol address should be shown. */
+static bool show_symbol_sections;
+
/* If non-null, take address parameters as relative to named section. */
static const char *just_section;
@@ -234,6 +238,11 @@ parse_opt (int key, char *arg, struct argp_state *state)
show_symbols = true;
break;
+ case 'x':
+ show_symbols = true;
+ show_symbol_sections = true;
+ break;
+
case 'j':
just_section = arg;
break;
@@ -342,8 +351,9 @@ static void
print_addrsym (Dwfl_Module *mod, GElf_Addr addr)
{
GElf_Sym s;
- GElf_Word shndx;
- const char *name = dwfl_module_addrsym (mod, addr, &s, &shndx);
+ GElf_Off off;
+ const char *name = dwfl_module_addrinfo (mod, addr, &off, &s,
+ NULL, NULL, NULL);
if (name == NULL)
{
/* No symbol name. Get a section name instead. */
@@ -355,10 +365,34 @@ print_addrsym (Dwfl_Module *mod, GElf_Addr addr)
else
printf ("(%s)+%#" PRIx64 "\n", name, addr);
}
- else if (addr == s.st_value)
- puts (name);
else
- printf ("%s+%#" PRIx64 "\n", name, addr - s.st_value);
+ {
+ if (off == 0)
+ printf ("%s", name);
+ else
+ printf ("%s+%#" PRIx64 "", name, off);
+
+ // Also show section name for address.
+ if (show_symbol_sections)
+ {
+ Dwarf_Addr ebias;
+ Elf_Scn *scn = dwfl_module_address_section (mod, &addr, &ebias);
+ if (scn != NULL)
+ {
+ GElf_Shdr shdr_mem;
+ GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+ if (shdr != NULL)
+ {
+ Elf *elf = dwfl_module_getelf (mod, &ebias);
+ GElf_Ehdr ehdr;
+ if (gelf_getehdr (elf, &ehdr) != NULL)
+ printf (" (%s)", elf_strptr (elf, ehdr.e_shstrndx,
+ shdr->sh_name));
+ }
+ }
+ }
+ puts ("");
+ }
}
static void
@@ -401,11 +435,14 @@ find_symbol (Dwfl_Module *mod,
{
const char *looking_for = ((void **) arg)[0];
GElf_Sym *symbol = ((void **) arg)[1];
+ GElf_Addr *value = ((void **) arg)[2];
int n = dwfl_module_getsymtab (mod);
for (int i = 1; i < n; ++i)
{
- const char *symbol_name = dwfl_module_getsym (mod, i, symbol, NULL);
+ const char *symbol_name = dwfl_module_getsym_info (mod, i, symbol,
+ value, NULL, NULL,
+ NULL);
if (symbol_name == NULL || symbol_name[0] == '\0')
continue;
switch (GELF_ST_TYPE (symbol->st_info))
@@ -519,7 +556,8 @@ handle_address (const char *string, Dwfl *dwfl)
/* It was symbol[+offset]. */
GElf_Sym sym;
- void *arg[2] = { name, &sym };
+ GElf_Addr value = 0;
+ void *arg[3] = { name, &sym, &value };
(void) dwfl_getmodules (dwfl, &find_symbol, arg, 0);
if (arg[0] != NULL)
error (0, 0, gettext ("cannot find symbol '%s'"), name);
@@ -530,7 +568,7 @@ handle_address (const char *string, Dwfl *dwfl)
gettext ("offset %#" PRIxMAX " lies outside"
" contents of '%s'"),
addr, name);
- addr += sym.st_value;
+ addr += value;
parsed = true;
}
break;
diff --git a/src/ar.c b/src/ar.c
index 2d6ad60c..f51f0efd 100644
--- a/src/ar.c
+++ b/src/ar.c
@@ -202,7 +202,7 @@ MEMBER parameter required for 'a', 'b', and 'i' modifiers"));
if (instance_specifed)
{
/* Only valid for certain operations. */
- if (operation == oper_extract && operation == oper_delete)
+ if (operation != oper_extract && operation != oper_delete)
error (1, 0, gettext ("\
'N' is only meaningful with the 'x' and 'd' options"));
diff --git a/src/arlib.c b/src/arlib.c
index 62c517cc..43a9145b 100644
--- a/src/arlib.c
+++ b/src/arlib.c
@@ -59,11 +59,11 @@ arlib_init (void)
_FORTIFY_SOURCE=2 would not let us play these games. Therefore
we play it safe. */
char tmpbuf[sizeof (ar_hdr.ar_date) + 1];
- memcpy (ar_hdr.ar_date, tmpbuf,
- snprintf (tmpbuf, sizeof (tmpbuf), "%-*lld",
+ int s = snprintf (tmpbuf, sizeof (tmpbuf), "%-*lld",
(int) sizeof (ar_hdr.ar_date),
(arlib_deterministic_output ? 0
- : (long long int) time (NULL))));
+ : (long long int) time (NULL)));
+ memcpy (ar_hdr.ar_date, tmpbuf, s);
assert ((sizeof (struct ar_hdr) % sizeof (uint32_t)) == 0);
/* Note the string for the ar_uid and ar_gid cases is longer than
@@ -121,10 +121,10 @@ arlib_finalize (void)
symtab.longnames = obstack_finish (&symtab.longnamesob);
- memcpy (&((struct ar_hdr *) symtab.longnames)->ar_size, tmpbuf,
- snprintf (tmpbuf, sizeof (tmpbuf), "%-*zu",
+ int s = snprintf (tmpbuf, sizeof (tmpbuf), "%-*zu",
(int) sizeof (((struct ar_hdr *) NULL)->ar_size),
- symtab.longnameslen - sizeof (struct ar_hdr)));
+ symtab.longnameslen - sizeof (struct ar_hdr));
+ memcpy (&((struct ar_hdr *) symtab.longnames)->ar_size, tmpbuf, s);
}
symtab.symsofflen = obstack_object_size (&symtab.symsoffob);
diff --git a/src/elflint.c b/src/elflint.c
index efaee266..3171df0b 100644
--- a/src/elflint.c
+++ b/src/elflint.c
@@ -1,5 +1,5 @@
/* Pedantic checking of ELF files compliance with gABI/psABI spec.
- Copyright (C) 2001-2012 Red Hat, Inc.
+ Copyright (C) 2001-2013 Red Hat, Inc.
This file is part of elfutils.
Written by Ulrich Drepper <[email protected]>, 2001.
@@ -344,7 +344,7 @@ static const int valid_e_machine[] =
EM_CRIS, EM_JAVELIN, EM_FIREPATH, EM_ZSP, EM_MMIX, EM_HUANY, EM_PRISM,
EM_AVR, EM_FR30, EM_D10V, EM_D30V, EM_V850, EM_M32R, EM_MN10300,
EM_MN10200, EM_PJ, EM_OPENRISC, EM_ARC_A5, EM_XTENSA, EM_ALPHA,
- EM_TILEGX, EM_TILEPRO
+ EM_TILEGX, EM_TILEPRO, EM_AARCH64
};
#define nvalid_e_machine \
(sizeof (valid_e_machine) / sizeof (valid_e_machine[0]))
diff --git a/src/nm.c b/src/nm.c
index 7aae84b0..d434f44e 100644
--- a/src/nm.c
+++ b/src/nm.c
@@ -763,7 +763,8 @@ show_symbols_sysv (Ebl *ebl, GElf_Word strndx, const char *fullname,
{
GElf_Shdr shdr_mem;
- assert (elf_ndxscn (scn) == cnt++);
+ assert (elf_ndxscn (scn) == cnt);
+ cnt++;
char *name = elf_strptr (ebl->elf, shstrndx,
gelf_getshdr (scn, &shdr_mem)->sh_name);
diff --git a/src/readelf.c b/src/readelf.c
index 7de20f82..f9f2f81e 100644
--- a/src/readelf.c
+++ b/src/readelf.c
@@ -3327,10 +3327,10 @@ format_dwarf_addr (Dwfl_Module *dwflmod,
{
/* See if there is a name we can give for this address. */
GElf_Sym sym;
+ GElf_Off off = 0;
const char *name = (print_address_names && ! print_unresolved_addresses)
- ? dwfl_module_addrsym (dwflmod, address, &sym, NULL) : NULL;
- if (name != NULL)
- sym.st_value = address - sym.st_value;
+ ? dwfl_module_addrinfo (dwflmod, address, &off, &sym, NULL, NULL, NULL)
+ : NULL;
const char *scn;
if (print_unresolved_addresses)
@@ -3351,24 +3351,24 @@ format_dwarf_addr (Dwfl_Module *dwflmod,
char *result;
if ((name != NULL
- ? (sym.st_value != 0
+ ? (off != 0
? (scn != NULL
? (address_size == 0
? asprintf (&result,
gettext ("%s+%#" PRIx64 " <%s+%#" PRIx64 ">"),
- scn, address, name, sym.st_value)
+ scn, address, name, off)
: asprintf (&result,
gettext ("%s+%#0*" PRIx64 " <%s+%#" PRIx64 ">"),
scn, 2 + address_size * 2, address,
- name, sym.st_value))
+ name, off))
: (address_size == 0
? asprintf (&result,
gettext ("%#" PRIx64 " <%s+%#" PRIx64 ">"),
- address, name, sym.st_value)
+ address, name, off)
: asprintf (&result,
gettext ("%#0*" PRIx64 " <%s+%#" PRIx64 ">"),
2 + address_size * 2, address,
- name, sym.st_value)))
+ name, off)))
: (scn != NULL
? (address_size == 0
? asprintf (&result,
@@ -4685,7 +4685,7 @@ print_debug_ranges_section (Dwfl_Module *dwflmod,
offset, &readp, endp))
continue;
- if (unlikely (data->d_size - offset < address_size * 2))
+ if (unlikely (data->d_size - offset < (size_t) address_size * 2))
{
printf (gettext (" [%6tx] <INVALID DATA>\n"), offset);
break;
@@ -6601,7 +6601,7 @@ print_debug_loc_section (Dwfl_Module *dwflmod,
&cu, offset, &readp, endp))
continue;
- if (unlikely (data->d_size - offset < address_size * 2))
+ if (unlikely (data->d_size - offset < (size_t) address_size * 2))
{
printf (gettext (" [%6tx] <INVALID DATA>\n"), offset);
break;
@@ -8216,6 +8216,9 @@ handle_core_item (Elf *core, const Ebl_Core_Item *item, const void *desc,
colno = WRAP_COLUMN;
break;
+ case 'h':
+ break;
+
default:
error (0, 0, "XXX not handling format '%c' for %s",
item->format, item->name);
diff --git a/src/stack.c b/src/stack.c
new file mode 100644
index 00000000..fdf4b074
--- /dev/null
+++ b/src/stack.c
@@ -0,0 +1,607 @@
+/* Unwinding of frames like gstack/pstack.
+ 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 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 <config.h>
+#include <assert.h>
+#include <argp.h>
+#include <error.h>
+#include <stdlib.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdio_ext.h>
+#include <string.h>
+#include <locale.h>
+#include <fcntl.h>
+#include ELFUTILS_HEADER(dwfl)
+
+#include <system.h>
+
+/* Name and version of program. */
+static void print_version (FILE *stream, struct argp_state *state);
+ARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
+
+/* Bug report address. */
+ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT;
+
+/* non-printable argp options. */
+#define OPT_DEBUGINFO 0x100
+#define OPT_COREFILE 0x101
+
+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;
+static bool show_quiet = false;
+static bool show_raw = false;
+static bool show_modules = false;
+
+static int maxframes = 2048;
+
+struct frame
+{
+ Dwarf_Addr pc;
+ bool isactivation;
+};
+
+struct frames
+{
+ int frames;
+ int allocated;
+ struct frame *frame;
+};
+
+static Dwfl *dwfl = NULL;
+static pid_t pid = 0;
+static int core_fd = -1;
+static Elf *core = NULL;
+static const char *exec = NULL;
+static char *debuginfo_path = NULL;
+
+static const Dwfl_Callbacks proc_callbacks =
+ {
+ .find_elf = dwfl_linux_proc_find_elf,
+ .find_debuginfo = dwfl_standard_find_debuginfo,
+ .debuginfo_path = &debuginfo_path,
+ };
+
+static const Dwfl_Callbacks core_callbacks =
+ {
+ .find_elf = dwfl_build_id_find_elf,
+ .find_debuginfo = dwfl_standard_find_debuginfo,
+ .debuginfo_path = &debuginfo_path,
+ };
+
+#ifdef USE_DEMANGLE
+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
+get_addr_width (Dwfl_Module *mod)
+{
+ // Try to find the address wide if possible.
+ static int width = 0;
+ if (width == 0 && mod)
+ {
+ 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;
+
+ return width;
+}
+
+static int
+module_callback (Dwfl_Module *mod, void **userdata __attribute__((unused)),
+ const char *name, Dwarf_Addr start,
+ void *arg __attribute__((unused)))
+{
+ /* Forces resolving of main elf and debug files. */
+ Dwarf_Addr bias;
+ Elf *elf = dwfl_module_getelf (mod, &bias);
+ Dwarf *dwarf = dwfl_module_getdwarf (mod, &bias);
+
+ Dwarf_Addr end;
+ const char *mainfile;
+ const char *debugfile;
+ const char *modname = dwfl_module_info (mod, NULL, NULL, &end, NULL,
+ NULL, &mainfile, &debugfile);
+ assert (strcmp (modname, name) == 0);
+
+ int width = get_addr_width (mod);
+ printf ("0x%0*" PRIx64 "-0x%0*" PRIx64 " %s\n",
+ width, start, width, end, basename (name));
+
+ const unsigned char *id;
+ GElf_Addr id_vaddr;
+ int id_len = dwfl_module_build_id (mod, &id, &id_vaddr);
+ if (id_len > 0)
+ {
+ printf (" [");
+ do
+ printf ("%02" PRIx8, *id++);
+ while (--id_len > 0);
+ printf ("]\n");
+ }
+
+ if (elf != NULL)
+ printf (" %s\n", mainfile != NULL ? mainfile : "-");
+ if (dwarf != NULL)
+ printf (" %s\n", debugfile != NULL ? debugfile : "-");
+
+ return DWARF_CB_OK;
+}
+
+static int
+frame_callback (Dwfl_Frame *state, void *arg)
+{
+ struct frames *frames = (struct frames *) arg;
+ int nr = frames->frames;
+ if (! dwfl_frame_pc (state, &frames->frame[nr].pc,
+ &frames->frame[nr].isactivation))
+ return -1;
+
+ frames->frames++;
+ if (frames->frames == maxframes)
+ return DWARF_CB_ABORT;
+
+ if (frames->frames == frames->allocated)
+ {
+ frames->allocated *= 2;
+ frames->frame = realloc (frames->frame,
+ sizeof (struct frame) * frames->allocated);
+ if (frames->frame == NULL)
+ error (EXIT_BAD, errno, "realloc frames.frame");
+ }
+
+ return DWARF_CB_OK;
+}
+
+static void
+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 (int nr = 0; nr < frames->frames; nr++)
+ {
+ 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 && ! show_quiet)
+ symname = dwfl_module_addrname (mod, pc_adjusted);
+
+ int width = get_addr_width (mod);
+ printf ("#%-2u 0x%0*" PRIx64, nr, width, (uint64_t) pc);
+
+ if (show_activation)
+ printf ("%4s", ! isactivation ? "- 1" : "");
+
+ if (symname != NULL)
+ {
+#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;
+ fname = dwfl_module_info(mod, NULL, &start,
+ NULL, NULL, NULL, NULL, NULL);
+ if (show_module)
+ {
+ 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 "+0x%" PRIx64,
+ start, pc_adjusted - start);
+ }
+ }
+
+ if (show_source)
+ {
+ Dwfl_Line *lineobj = dwfl_module_getsrc(mod, pc_adjusted);
+ if (lineobj)
+ {
+ int line, col;
+ const char* sname;
+ line = col = -1;
+ sname = dwfl_lineinfo (lineobj, NULL, &line, &col, NULL, NULL);
+ if (sname != NULL)
+ {
+ printf ("\n %s", sname);
+ if (line > 0)
+ {
+ printf (":%d", line);
+ if (col > 0)
+ printf (":%d", col);
+ }
+ }
+ }
+ }
+ 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));
+ }
+ else if (frames->frames > 0 && frames->frames == maxframes)
+ error (0, 0, "tid %d: shown max number of frames "
+ "(%d, use -n 0 for unlimited)", tid, maxframes);
+}
+
+static int
+thread_callback (Dwfl_Thread *thread, void *thread_arg)
+{
+ 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))
+ {
+ case DWARF_CB_OK:
+ case DWARF_CB_ABORT:
+ break;
+ case -1:
+ err = dwfl_errno ();
+ break;
+ default:
+ abort ();
+ }
+ print_frames (frames, tid, err, "dwfl_thread_getframes");
+ return DWARF_CB_OK;
+}
+
+static void
+print_version (FILE *stream, struct argp_state *state __attribute__ ((unused)))
+{
+ fprintf (stream, "stack (%s) %s\n", PACKAGE_NAME, PACKAGE_VERSION);
+}
+
+static error_t
+parse_opt (int key, char *arg __attribute__ ((unused)),
+ struct argp_state *state)
+{
+ switch (key)
+ {
+ case 'p':
+ pid = atoi (arg);
+ if (pid == 0)
+ argp_error (state, N_("-p PID should be a positive process id."));
+ break;
+
+ case OPT_COREFILE:
+ core_fd = open (arg, O_RDONLY);
+ if (core_fd < 0)
+ 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 (EXIT_BAD, 0, "core '%s' elf_begin: %s", arg, elf_errmsg(-1));
+ break;
+
+ case 'e':
+ exec = arg;
+ break;
+
+ case OPT_DEBUGINFO:
+ debuginfo_path = arg;
+ break;
+
+ case 'm':
+ show_module = true;
+ break;
+
+ case 's':
+ show_source = true;
+ break;
+
+ case 'a':
+ show_activation = true;
+ break;
+
+ case 'v':
+ show_activation = show_source = show_module = true;
+ break;
+
+ case 'b':
+ show_build_id = true;
+ break;
+
+ case 'q':
+ show_quiet = true;
+ break;
+
+ case 'r':
+ show_raw = true;
+ break;
+
+ case '1':
+ show_one_tid = true;
+ break;
+
+ case 'n':
+ maxframes = atoi (arg);
+ if (maxframes < 0)
+ {
+ argp_error (state, N_("-n MAXFRAMES should be 0 or higher."));
+ return EINVAL;
+ }
+ break;
+
+ case 'l':
+ show_modules = true;
+ break;
+
+ case ARGP_KEY_END:
+ if (core == NULL && exec != NULL)
+ argp_error (state,
+ N_("-e EXEC needs a core given by --core."));
+
+ if (pid == 0 && show_one_tid == true)
+ argp_error (state,
+ N_("-1 needs a thread id given by -p."));
+
+ if ((pid == 0 && core == NULL) || (pid != 0 && core != NULL))
+ argp_error (state,
+ N_("One of -p PID or --core COREFILE should be given."));
+
+ if (pid != 0)
+ {
+ dwfl = dwfl_begin (&proc_callbacks);
+ if (dwfl == NULL)
+ 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 (EXIT_BAD, 0, "dwfl_begin: %s", dwfl_errmsg (-1));
+ if (dwfl_core_file_report (dwfl, core, exec) < 0)
+ error (EXIT_BAD, 0, "dwfl_core_file_report: %s", dwfl_errmsg (-1));
+ }
+
+ if (dwfl_report_end (dwfl, NULL, NULL) != 0)
+ error (EXIT_BAD, 0, "dwfl_report_end: %s", dwfl_errmsg (-1));
+
+ if (pid != 0)
+ {
+ int err = dwfl_linux_proc_attach (dwfl, pid, false);
+ if (err < 0)
+ error (EXIT_BAD, 0, "dwfl_linux_proc_attach pid %d: %s", pid,
+ dwfl_errmsg (-1));
+ else if (err > 0)
+ error (EXIT_BAD, err, "dwfl_linux_proc_attach pid %d", pid);
+ }
+
+ if (core != NULL)
+ {
+ if (dwfl_core_file_attach (dwfl, core) < 0)
+ error (EXIT_BAD, 0, "dwfl_core_file_report: %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:
+ return ARGP_ERR_UNKNOWN;
+ }
+ return 0;
+}
+
+int
+main (int argc, char **argv)
+{
+ /* We use no threads here which can interfere with handling a stream. */
+ __fsetlocking (stdin, FSETLOCKING_BYCALLER);
+ __fsetlocking (stdout, FSETLOCKING_BYCALLER);
+ __fsetlocking (stderr, FSETLOCKING_BYCALLER);
+
+ /* Set locale. */
+ (void) setlocale (LC_ALL, "");
+
+ const struct argp_option options[] =
+ {
+ { NULL, 0, NULL, 0, N_("Input selection options:"), 0 },
+ { "pid", 'p', "PID", 0,
+ N_("Show stack of process PID"), 0 },
+ { "core", OPT_COREFILE, "COREFILE", 0,
+ N_("Show stack found in COREFILE"), 0 },
+ { "executable", 'e', "EXEC", 0, N_("(optional) EXECUTABLE that produced COREFILE"), 0 },
+ { "debuginfo-path", OPT_DEBUGINFO, "PATH", 0,
+ N_("Search path for separate debuginfo files"), 0 },
+
+ { NULL, 0, NULL, 0, N_("Output selection options:"), 0 },
+ { "activation", 'a', NULL, 0,
+ N_("Additionally show frame activation"), 0 },
+ { "module", 'm', NULL, 0,
+ N_("Additionally show module file information"), 0 },
+ { "source", 's', NULL, 0,
+ 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 },
+ { "raw", 'r', NULL, 0,
+ N_("Show raw function symbol names, do not try to demangle names"), 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,
+ N_("Show at most MAXFRAMES per thread (default 2048, use 0 for unlimited)"), 0 },
+ { "list-modules", 'l', NULL, 0,
+ N_("Show module memory map with build-id, elf and debug files detected"), 0 },
+ { NULL, 0, NULL, 0, NULL, 0 }
+ };
+
+ const struct argp argp =
+ {
+ .options = options,
+ .parser = parse_opt,
+ .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);
+
+ if (show_modules)
+ {
+ printf ("PID %d - %s module memory map\n", dwfl_pid (dwfl),
+ pid != 0 ? "process" : "core");
+ if (dwfl_getmodules (dwfl, module_callback, NULL, 0) != 0)
+ error (EXIT_BAD, 0, "dwfl_getmodules: %s", dwfl_errmsg (-1));
+ }
+
+ struct frames frames;
+ frames.allocated = maxframes == 0 ? 2048 : maxframes;
+ frames.frames = 0;
+ frames.frame = malloc (sizeof (struct frame) * frames.allocated);
+ if (frames.frame == NULL)
+ error (EXIT_BAD, errno, "malloc frames.frame");
+
+ if (show_one_tid)
+ {
+ int err = 0;
+ switch (dwfl_getthread_frames (dwfl, pid, frame_callback, &frames))
+ {
+ case DWARF_CB_OK:
+ case DWARF_CB_ABORT:
+ break;
+ case -1:
+ err = dwfl_errno ();
+ break;
+ default:
+ abort ();
+ }
+ print_frames (&frames, pid, err, "dwfl_getthread_frames");
+ }
+ else
+ {
+ printf ("PID %d - %s\n", dwfl_pid (dwfl), pid != 0 ? "process" : "core");
+ 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));
+ break;
+ default:
+ abort ();
+ }
+ }
+ free (frames.frame);
+ dwfl_end (dwfl);
+
+ if (core != NULL)
+ elf_end (core);
+
+ if (core_fd != -1)
+ close (core_fd);
+
+#ifdef USE_DEMANGLE
+ free (demangle_buffer);
+#endif
+
+ if (! frames_shown)
+ error (EXIT_BAD, 0, N_("Couldn't show any frames."));
+
+ return error_message_count != 0 ? EXIT_ERROR : EXIT_OK;
+}
diff --git a/tests/ChangeLog b/tests/ChangeLog
index 622af0c9..c68ae26c 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -1,3 +1,222 @@
+2014-01-03 Mark Wielaard <[email protected]>
+
+ * run-addrcfi.sh: Add case for EM_AARCH64.
+ * testfileaarch64.bz2: New testfile.
+ * Makefile.am (EXTRA_DIST): Add testfilesaarch64.bz2.
+
+2013-12-30 Mark Wielaard <[email protected]>
+
+ * backtrace-dwarf.c (report_pid): Explicitly call
+ dwfl_linux_proc_attach and check for errors.
+ * backtrace.c (report_pid): Likewise.
+
+2013-12-21 Mark Wielaard <[email protected]>
+
+ * backtrace.c (callback_verify): Only assert that case 5 is the last
+ instruction of backtracegen on x86_64 native.
+
+2013-12-18 Jan Kratochvil <[email protected]>
+ Mark Wielaard <[email protected]>
+
+ * Makefile.am (EXTRA_DIST): Add testfile66.bz2, testfile66.core.bz2
+ and testfilebaz*ppc64*.bz2 files.
+ * dwflsyms.c (list_syms): Remove unused from parameter mod_name. Print
+ error on dwfl_module_getsymtab error.
+ (list_syms): Use dwfl_module_getsym and dwfl_module_getsym_info.
+ Compare values for non-ET_REL. Use dwfl_module_addrinfo.
+ Also print section of actual value if different from sym.
+ * run-addrname-test.sh (testfile66, testfile66.core): New tests.
+ Test addr2line -x by showing different sections for address and
+ found name in testfile66.
+ * run-dwflsyms.sh (testfile66, testfile66.core, hello_ppc64.ko,
+ testfilebaz*ppc64): New tests.
+ * testfile66.bz2, testfile66.core.bz2, testfilebazdbgppc64.bz2,
+ testfilebazdbgppc64.debug.bz2, testfilebazdbgppc64_pl.bz2,
+ testfilebazdbgppc64_plr.bz2, testfilebazdynppc64.bz2,
+ testfilebazmdbppc64.bz2, testfilebazminppc64.bz2,
+ testfilebazminppc64_pl.bz2, testfilebazminppc64_plr.bz2,
+ testfilebaztabppc64.bz2: New test files.
+
+2013-12-18 Jan Kratochvil <[email protected]>
+
+ unwinder: s390 and s390x
+ * Makefile.am (TESTS): Add run-backtrace-core-s390x.sh and
+ run-backtrace-core-s390.sh.
+ (EXTRA_DIST): Add backtrace.s390x.core.bz2, backtrace.s390x.exec.bz2,
+ backtrace.s390.core.bz2, backtrace.s390.exec.bz2,
+ run-backtrace-core-s390x.sh and run-backtrace-core-s390.sh.
+ * backtrace.s390.core.bz2: New file.
+ * backtrace.s390.exec.bz2: New file.
+ * backtrace.s390x.core.bz2: New file.
+ * backtrace.s390x.exec.bz2: New file.
+ * run-backtrace-core-s390.sh: New file.
+ * run-backtrace-core-s390x.sh: New file.
+
+2013-12-17 Jan Kratochvil <[email protected]>
+
+ * backtrace-dwarf.c (executable, find_elf, dwfl_offline): Remove unused
+ code.
+
+2013-12-15 Jan Kratochvil <[email protected]>
+
+ unwinder: ppc
+ * Makefile.am (TESTS): Add run-backtrace-core-ppc.sh.
+ (EXTRA_DIST): Add backtrace.ppc.core.bz2,
+ backtrace.ppc.exec.bz2 and run-backtrace-core-ppc.sh.
+ * backtrace.ppc.core.bz2: New file.
+ * backtrace.ppc.exec.bz2: New file.
+ * run-backtrace-core-ppc.sh: New file.
+
+2013-12-10 Mark Wielaard <[email protected]>
+
+ * Makefile.am (backtrace_child_biarch_SOURCES): New backtrace-child.c.
+
+2013-12-10 Mark Wielaard <[email protected]>
+
+ * Makefile.am (valgrind_cmd): Remove --trace-children=yes.
+ * backtrace-subr.sh (check_native_core): Disable valgrind while
+ dumping core.
+ * run-backtrace-data.sh: Disable valgrind.
+ * run-backtrace-dwarf.sh: Likewise.
+
+2013-12-09 Mark Wielaard <[email protected]>
+
+ * varlocs.c (print_expr): Update comment to explain empty location
+ associated with DW_OP_GNU_implicit_pointer.
+
+2013-12-05 Jan Kratochvil <[email protected]>
+
+ Fix test FAIL with -O2.
+ * backtrace-child.c (sigusr2): Add NOINLINE_NOCLONE and final asm stub.
+
+2013-12-05 Mark Wielaard <[email protected]>
+
+ * backtrace-data.c (main): If unsupported also print to stderr.
+ * run-backtrace-dwarf.sh: Add check_unsupported and check_main.
+
+2013-12-04 Mark Wielaard <[email protected]>
+
+ * Makefile.am (backtrace-child-biarch): Add $(EXEEXT).
+
+2013-12-02 Jan Kratochvil <[email protected]>
+
+ * Makefile.am (check_PROGRAMS): Add backtrace, backtrace-child,
+ backtrace-data and backtrace-dwarf.
+ (BUILT_SOURCES, clean-local, backtrace-child-biarch): New.
+ (TESTS): Add run-backtrace-native.sh, run-backtrace-data.sh,
+ run-backtrace-dwarf.sh, run-backtrace-native-biarch.sh,
+ run-backtrace-native-core.sh, run-backtrace-native-core-biarch.sh,
+ run-backtrace-core-x86_64.sh and run-backtrace-core-i386.sh.
+ <!BIARCH> Add export of ELFUTILS_DISABLE_BIARCH.
+ (EXTRA_DIST): Add run-backtrace-data.sh, run-backtrace-dwarf.sh,
+ cleanup-13.c, run-backtrace-native.sh, 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,
+ backtrace-subr.sh, backtrace.i386.core.bz2, backtrace.i386.exec.bz2,
+ backtrace.x86_64.core.bz2, backtrace.x86_64.exec.bz2.
+ (backtrace_LDADD, backtrace_child_CFLAGS, backtrace_child_LDFLAGS)
+ (backtrace_data_LDADD, backtrace_dwarf_CFLAGS, backtrace_dwarf_LDADD):
+ New.
+ * backtrace-child.c: New file.
+ * backtrace-data.c: New file.
+ * backtrace-dwarf.c: New file.
+ * backtrace-subr.sh: New file.
+ * backtrace.c: New file.
+ * cleanup-13.c: New file.
+ * backtrace.i386.core.bz2: New file.
+ * backtrace.i386.exec.bz2: New file.
+ * backtrace.x86_64.core.bz2: New file.
+ * backtrace.x86_64.exec.bz2: New file.
+ * run-backtrace-core-i386.sh: New file.
+ * run-backtrace-core-x86_64.sh: New file.
+ * run-backtrace-native-biarch.sh: New file.
+ * run-backtrace-native-core-biarch.sh: New file.
+ * run-backtrace-native-core.sh: New file.
+ * run-backtrace-native.sh: New file.
+ * run-backtrace-data.sh: New file.
+ * run-backtrace-dwarf.sh: New file.
+
+2013-11-27 Mark Wielaard <[email protected]>
+
+ * dwflsyms.c (gelf_bind_order): New function.
+ (elf_section_name): Likewise.
+ (addr_in_section): Likewise.
+ (list_syms): Use dwfl_module_getsym_elf and dwfl_module_addrsym_elf.
+ Refine assert using gelf_bind_order. Print elf_section_name. Check
+ bias with addr_in_section.
+ * run-dwflsyms.sh: Add section names to expected output.
+
+2013-11-26 Mark Wielaard <[email protected]>
+
+ * Makefile.am (EXTRA_DIST): Add run-funcretval.sh.
+
+2013-11-25 Petr Machata <[email protected]>
+
+ * testfile_aarch64_core.bz2, hello_aarch64.ko.bz2: New files.
+ * funcretval_test.c, funcretval_test_aarch64.bz2: Likewise.
+ * Makefile.am (EXTRA_DIST): Add these.
+ (TESTS): Add run-funcretval.sh.
+ * run-allregs.sh: Use testfile_aarch64_core.bz2 for a regs_test.
+ * run-readelf-mixed-corenote.sh: ... and for a readelf -n test.
+ * run-strip-reloc.sh: Add a test on hello_aarch64.ko.bz2.
+ * run-funcretval.sh: New file.
+
+2013-11-18 Josh Stone <[email protected]>
+
+ * testfilebazdbg_plr.bz2: New testfile.
+ * testfilebazmin_plr.bz2: Likewise.
+ * Makefile.am (EXTRA_DIST): Add the above files.
+ * run-dwflsyms.sh: Add prelink -r tests.
+
+2013-11-15 Mark Wielaard <[email protected]>
+
+ * testfilebazmdb.bz2: Regenerated.
+ * testfilebazmin.bz2: Likewise.
+ * testfilebazdbg_pl.bz2: New testfile.
+ * testfilebazmin_pl.bz2: Likewise.
+ * Makefile.am (EXTRA_DIST): Add testfilebazdbg_pl.bz2 and
+ testfilebazmin_pl.bz2.
+ * dwflsyms.c (list_syms): Call dwfl_module_relocate_address and
+ print relative address of function symbols.
+ * run-dwflsyms.sh: Add prelink tests and adjust expected output.
+
+2013-11-01 Michael Forney <[email protected]>
+
+ * Makefile.am (TESTS_ENVIRONMENT): Use and export NM.
+ * run-arsymtest.sh: Use NM.
+
+2013-11-05 Mark Wielaard <[email protected]>
+
+ * allfcts.c (main): Correct dwarf_getfuncs return value check.
+
+2013-10-10 Mark Wielaard <[email protected]>
+ Josh Stone <[email protected]>
+
+ * run-allfcts-multi.sh: New test.
+ * test-offset-loop.bz2: New testfile.
+ * test-offset-loop.alt.bz2: New testfile.
+ * Makefile.am (TESTS): Add run-allcft-multi.sh if ENABLE_DWZ.
+ (EXTRA_DIST): Add run-allfcts-multi.sh, test-offset-loop.bz2 and
+ test-offset-loop.alt.bz2.
+
+2013-10-15 Mark Wielaard <[email protected]>
+
+ * run-unstrip-M.sh: New test.
+ * Makefile.am (TESTS): Add run-unstrip-M.sh.
+ (EXTRA_DIST): Likewise.
+
+2013-10-06 Mark Wielaard <[email protected]>
+
+ * run-addrcfi.sh: Remove nop from expected ppc and ppc64
+ location expression.
+
+2013-10-03 Josh Stone <[email protected]>
+
+ * typeiter2.c: New file, reversing typeiter.c.
+ * run-typeiter.sh: Also run typeiter2.
+ * Makefile.am (check_PROGRAMS): Add typeiter2.
+ (typeiter2_LDADD): New variable.
+
2013-09-26 Petr Machata <[email protected]>
* run-readelf-mixed-corenote.sh: Update output of testfile71
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 0024395d..eae64a83 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -50,12 +50,25 @@ check_PROGRAMS = arextract arsymtest newfile saridx scnnames sectiondump \
dwfl-addr-sect dwfl-bug-report early-offscn \
dwfl-bug-getmodules dwarf-getmacros addrcfi \
test-flag-nobits dwarf-getstring rerequest_tag \
- alldts md5-sha1-test typeiter low_high_pc \
+ alldts md5-sha1-test typeiter typeiter2 low_high_pc \
test-elf_cntl_gelf_getshdr dwflsyms dwfllines \
- dwfl-report-elf-align varlocs
+ dwfl-report-elf-align varlocs backtrace backtrace-child \
+ backtrace-data backtrace-dwarf
asm_TESTS = asm-tst1 asm-tst2 asm-tst3 asm-tst4 asm-tst5 \
asm-tst6 asm-tst7 asm-tst8 asm-tst9
+if BIARCH
+check_PROGRAMS += backtrace-child-biarch
+endif
+
+# Substitute $(COMPILE).
+backtrace-child-biarch$(EXEEXT): backtrace-child.c
+ $(CC_BIARCH) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS) $(backtrace_child_CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) $(backtrace_child_LDFLAGS) \
+ -o $@ $<
+
TESTS = run-arextract.sh run-arsymtest.sh newfile test-nlist \
update1 update2 update3 update4 \
run-show-die-info.sh run-get-files.sh run-get-lines.sh \
@@ -65,7 +78,7 @@ TESTS = run-arextract.sh run-arsymtest.sh newfile test-nlist \
run-strip-test3.sh run-strip-test4.sh run-strip-test5.sh \
run-strip-test6.sh run-strip-test7.sh run-strip-test8.sh \
run-strip-groups.sh run-strip-reloc.sh \
- run-unstrip-test.sh run-unstrip-test2.sh \
+ run-unstrip-test.sh run-unstrip-test2.sh run-unstrip-M.sh \
run-ecp-test.sh run-ecp-test2.sh run-alldts.sh \
run-elflint-test.sh run-elflint-self.sh run-ranlib-test.sh \
run-ranlib-test2.sh run-ranlib-test3.sh run-ranlib-test4.sh \
@@ -89,7 +102,16 @@ TESTS = run-arextract.sh run-arsymtest.sh newfile test-nlist \
run-test-archive64.sh run-readelf-vmcoreinfo.sh \
run-readelf-mixed-corenote.sh run-dwfllines.sh \
run-dwfl-report-elf-align.sh run-addr2line-test.sh \
- run-addr2line-i-test.sh run-varlocs.sh
+ run-addr2line-i-test.sh run-varlocs.sh run-funcretval.sh \
+ run-backtrace-native.sh run-backtrace-data.sh run-backtrace-dwarf.sh \
+ 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
+
+if !BIARCH
+export ELFUTILS_DISABLE_BIARCH = 1
+endif
if !STANDALONE
check_PROGRAMS += msg_tst md5-sha1-test
@@ -106,7 +128,7 @@ TESTS += $(asm_TESTS)
endif
if ENABLE_DWZ
-TESTS += run-readelf-dwz-multi.sh
+TESTS += run-readelf-dwz-multi.sh run-allfcts-multi.sh
endif
@@ -124,8 +146,8 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh \
run-strip-test4.sh run-strip-test5.sh run-strip-test6.sh \
run-strip-test7.sh run-strip-test8.sh run-strip-groups.sh \
run-strip-reloc.sh hello_i386.ko.bz2 hello_x86_64.ko.bz2 \
- hello_ppc64.ko.bz2 hello_s390.ko.bz2 \
- run-unstrip-test.sh run-unstrip-test2.sh \
+ hello_ppc64.ko.bz2 hello_s390.ko.bz2 hello_aarch64.ko.bz2 \
+ run-unstrip-test.sh run-unstrip-test2.sh run-unstrip-M.sh\
run-elflint-self.sh run-ranlib-test.sh run-ranlib-test2.sh \
run-ranlib-test3.sh run-ranlib-test4.sh \
run-addrscopes.sh run-strings-test.sh run-funcscopes.sh \
@@ -164,6 +186,8 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh \
run-readelf-dwz-multi.sh libtestfile_multi_shared.so.bz2 \
testfile_multi.dwz.bz2 testfile_multi_main.bz2 \
testfile-dwzstr.bz2 testfile-dwzstr.multi.bz2 \
+ run-allfcts-multi.sh \
+ test-offset-loop.bz2 test-offset-loop.alt.bz2 \
run-prelink-addr-test.sh \
testfile52-32.so.bz2 testfile52-32.so.debug.bz2 \
testfile52-32.prelink.so.bz2 testfile52-32.noshdrs.so.bz2 \
@@ -187,6 +211,13 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh \
run-readelf-s.sh testfilebazdbg.bz2 testfilebazdyn.bz2 \
testfilebazmin.bz2 testfilebazdbg.debug.bz2 testfilebazmdb.bz2 \
testfilebaztab.bz2 testfilebasmin.bz2 \
+ testfilebazdbg_pl.bz2 testfilebazmin_pl.bz2 \
+ testfilebazdbg_plr.bz2 testfilebazmin_plr.bz2 \
+ testfilebazdbgppc64.bz2 testfilebazdbgppc64.debug.bz2 \
+ testfilebazdbgppc64_pl.bz2 testfilebazdbgppc64_plr.bz2 \
+ testfilebazdynppc64.bz2 testfilebazmdbppc64.bz2 \
+ testfilebazminppc64.bz2 testfilebazminppc64_pl.bz2 \
+ testfilebazminppc64_plr.bz2 testfilebaztabppc64.bz2 \
run-dwflsyms.sh \
run-unstrip-n.sh testcore-rtlib.bz2 testcore-rtlib-ppc.bz2 \
run-low_high_pc.sh testfile_low_high_pc.bz2 \
@@ -206,16 +237,29 @@ 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 \
testfile_parameter_ref.c testfile_parameter_ref.bz2 \
testfile_entry_value.c testfile_entry_value.bz2 \
- testfile_implicit_value.c testfile_implicit_value.bz2
+ testfile_implicit_value.c testfile_implicit_value.bz2 \
+ testfile_aarch64_core.bz2 \
+ run-funcretval.sh funcretval_test.c funcretval_test_aarch64.bz2 \
+ run-backtrace-data.sh run-backtrace-dwarf.sh cleanup-13.c \
+ run-backtrace-native.sh 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 \
+ backtrace-subr.sh backtrace.i386.core.bz2 backtrace.i386.exec.bz2 \
+ backtrace.x86_64.core.bz2 backtrace.x86_64.exec.bz2 \
+ backtrace.ppc.core.bz2 backtrace.ppc.exec.bz2 \
+ 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
if USE_VALGRIND
-valgrind_cmd='valgrind -q --trace-children=yes --error-exitcode=1 --run-libc-freeres=no'
+valgrind_cmd='valgrind -q --error-exitcode=1 --run-libc-freeres=no'
endif
@@ -229,7 +273,8 @@ installed_TESTS_ENVIRONMENT = libdir=$(DESTDIR)$(libdir); \
export abs_srcdir; export abs_builddir; \
export abs_top_builddir; \
export libdir; export bindir; \
- export LC_ALL; export LANG; export VALGRIND_CMD;
+ export LC_ALL; export LANG; export VALGRIND_CMD; \
+ NM=$(NM); export NM;
installed_LOG_COMPILER = $(abs_srcdir)/test-wrapper.sh \
installed $(tests_rpath) \
'$(program_transform_name)'
@@ -242,7 +287,8 @@ TESTS_ENVIRONMENT = LC_ALL=C; LANG=C; VALGRIND_CMD=$(valgrind_cmd); \
abs_top_builddir=$(abs_top_builddir); \
export abs_srcdir; export abs_builddir; \
export abs_top_builddir; \
- export LC_ALL; export LANG; export VALGRIND_CMD;
+ export LC_ALL; export LANG; export VALGRIND_CMD; \
+ NM=$(NM); export NM;
LOG_COMPILER = $(abs_srcdir)/test-wrapper.sh \
$(abs_top_builddir)/libdw:$(abs_top_builddir)/backends:$(abs_top_builddir)/libelf:$(abs_top_builddir)/libasm
@@ -332,12 +378,21 @@ rerequest_tag_LDADD = $(libdw) $(libmudflap)
alldts_LDADD = $(libebl) $(libelf) $(libmudflap)
md5_sha1_test_LDADD = $(libeu)
typeiter_LDADD = $(libdw) $(libelf) $(libmudflap)
+typeiter2_LDADD = $(libdw) $(libelf) $(libmudflap)
low_high_pc_LDADD = $(libdw) $(libelf) $(libmudflap)
test_elf_cntl_gelf_getshdr_LDADD = $(libelf) $(libmudflap)
dwflsyms_LDADD = $(libdw) $(libelf) $(libmudflap)
dwfllines_LDADD = $(libdw) $(libelf) $(libmudflap)
dwfl_report_elf_align_LDADD = $(libdw) $(libmudflap)
varlocs_LDADD = $(libdw) $(libelf) $(libmudflap)
+backtrace_LDADD = $(libdw) $(libelf) $(libmudflap)
+# backtrace-child-biarch also uses those *_CFLAGS and *_LDLAGS variables:
+backtrace_child_CFLAGS = -fPIE
+backtrace_child_LDFLAGS = -pie -pthread
+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)
if GCOV
check: check-am coverage
diff --git a/tests/allfcts.c b/tests/allfcts.c
index 7803722f..10e0f07b 100644
--- a/tests/allfcts.c
+++ b/tests/allfcts.c
@@ -63,7 +63,7 @@ main (int argc, char *argv[])
{
doff = dwarf_getfuncs (die, cb, NULL, doff);
}
- while (doff > 0);
+ while (doff != 0 && dwarf_errno () == 0);
off = noff;
}
diff --git a/tests/backtrace-child.c b/tests/backtrace-child.c
new file mode 100644
index 00000000..0db12589
--- /dev/null
+++ b/tests/backtrace-child.c
@@ -0,0 +1,223 @@
+/* Test child for parent backtrace test.
+ 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 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/>. */
+
+/* Command line syntax: ./backtrace-child [--ptraceme|--gencore]
+ --ptraceme will call ptrace (PTRACE_TRACEME) in the two threads.
+ --gencore will call abort () at its end.
+ Main thread will signal SIGUSR2. Other thread will signal SIGUSR1.
+ On x86_64 only:
+ PC will get changed to function 'jmp' by backtrace.c function
+ prepare_thread. Then SIGUSR2 will be signalled to backtrace-child
+ which will invoke function sigusr2.
+ This is all done so that signal interrupts execution of the very first
+ instruction of a function. Properly handled unwind should not slip into
+ the previous unrelated function.
+ The tested functionality is arch-independent but the code reproducing it
+ has to be arch-specific.
+ On non-x86_64:
+ sigusr2 gets called by normal function call from function stdarg.
+ On any arch then sigusr2 calls raise (SIGUSR1) for --ptraceme.
+ abort () is called otherwise, expected for --gencore core dump.
+
+ Expected x86_64 output:
+ TID 10276:
+ # 0 0x7f7ab61e9e6b raise
+ # 1 0x7f7ab661af47 - 1 main
+ # 2 0x7f7ab5e3bb45 - 1 __libc_start_main
+ # 3 0x7f7ab661aa09 - 1 _start
+ TID 10278:
+ # 0 0x7f7ab61e9e6b raise
+ # 1 0x7f7ab661ab3c - 1 sigusr2
+ # 2 0x7f7ab5e4fa60 __restore_rt
+ # 3 0x7f7ab661ab47 jmp
+ # 4 0x7f7ab661ac92 - 1 stdarg
+ # 5 0x7f7ab661acba - 1 backtracegen
+ # 6 0x7f7ab661acd1 - 1 start
+ # 7 0x7f7ab61e2c53 - 1 start_thread
+ # 8 0x7f7ab5f0fdbd - 1 __clone
+
+ Expected non-x86_64 (i386) output; __kernel_vsyscall are skipped if found:
+ TID 10408:
+ # 0 0xf779f430 __kernel_vsyscall
+ # 1 0xf7771466 - 1 raise
+ # 2 0xf77c1d07 - 1 main
+ # 3 0xf75bd963 - 1 __libc_start_main
+ # 4 0xf77c1761 - 1 _start
+ TID 10412:
+ # 0 0xf779f430 __kernel_vsyscall
+ # 1 0xf7771466 - 1 raise
+ # 2 0xf77c18f4 - 1 sigusr2
+ # 3 0xf77c1a10 - 1 stdarg
+ # 4 0xf77c1a2c - 1 backtracegen
+ # 5 0xf77c1a48 - 1 start
+ # 6 0xf77699da - 1 start_thread
+ # 7 0xf769bbfe - 1 __clone
+ */
+
+#include <config.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <errno.h>
+#include <sys/ptrace.h>
+#include <string.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)
+#define NOINLINE_NOCLONE __attribute__ ((noinline, noclone))
+#else
+#define NOINLINE_NOCLONE __attribute__ ((noinline))
+#endif
+
+#define NORETURN __attribute__ ((noreturn))
+#define UNUSED __attribute__ ((unused))
+#define USED __attribute__ ((used))
+
+static int ptraceme, gencore;
+
+/* Execution will arrive here from jmp by an artificial ptrace-spawn signal. */
+
+static NOINLINE_NOCLONE void
+sigusr2 (int signo)
+{
+ assert (signo == SIGUSR2);
+ if (! gencore)
+ {
+ raise (SIGUSR1);
+ /* It should not be reached. */
+ abort ();
+ }
+ /* Here we dump the core for --gencore. */
+ raise (SIGABRT);
+ /* Avoid tail call optimization for the raise call. */
+ asm volatile ("");
+}
+
+static NOINLINE_NOCLONE void
+dummy1 (void)
+{
+ asm volatile ("");
+}
+
+#ifdef __x86_64__
+static NOINLINE_NOCLONE USED void
+jmp (void)
+{
+ /* Not reached, signal will get ptrace-spawn to jump into sigusr2. */
+ abort ();
+}
+#endif
+
+static NOINLINE_NOCLONE void
+dummy2 (void)
+{
+ asm volatile ("");
+}
+
+static NOINLINE_NOCLONE NORETURN void
+stdarg (int f UNUSED, ...)
+{
+ sighandler_t sigusr2_orig = signal (SIGUSR2, sigusr2);
+ assert (sigusr2_orig == SIG_DFL);
+ errno = 0;
+ if (ptraceme)
+ {
+ long l = ptrace (PTRACE_TRACEME, 0, NULL, NULL);
+ assert_perror (errno);
+ assert (l == 0);
+ }
+#ifdef __x86_64__
+ if (! gencore)
+ {
+ /* Execution will get PC patched into function jmp. */
+ raise (SIGUSR1);
+ }
+#endif
+ sigusr2 (SIGUSR2);
+ /* Not reached. */
+ abort ();
+}
+
+static NOINLINE_NOCLONE void
+dummy3 (void)
+{
+ asm volatile ("");
+}
+
+static NOINLINE_NOCLONE void
+backtracegen (void)
+{
+ stdarg (1);
+ /* Here should be no instruction after the stdarg call as it is noreturn
+ function. It must be stdarg so that it is a call and not jump (jump as
+ a tail-call). */
+}
+
+static NOINLINE_NOCLONE void
+dummy4 (void)
+{
+ asm volatile ("");
+}
+
+static void *
+start (void *arg UNUSED)
+{
+ backtracegen ();
+ /* Not reached. */
+ abort ();
+}
+
+int
+main (int argc UNUSED, char **argv)
+{
+ setbuf (stdout, NULL);
+ assert (*argv++);
+ ptraceme = (*argv && strcmp (*argv, "--ptraceme") == 0);
+ argv += ptraceme;
+ gencore = (*argv && strcmp (*argv, "--gencore") == 0);
+ argv += gencore;
+ assert (!*argv);
+ /* These dummy* functions are there so that each of their surrounding
+ functions has some unrelated code around. The purpose of some of the
+ tests is verify unwinding the very first / after the very last instruction
+ does not inappropriately slip into the unrelated code around. */
+ dummy1 ();
+ dummy2 ();
+ dummy3 ();
+ dummy4 ();
+ if (gencore)
+ printf ("%ld\n", (long) getpid ());
+ pthread_t thread;
+ int i = pthread_create (&thread, NULL, start, NULL);
+ // pthread_* functions do not set errno.
+ assert (i == 0);
+ if (ptraceme)
+ {
+ errno = 0;
+ long l = ptrace (PTRACE_TRACEME, 0, NULL, NULL);
+ assert_perror (errno);
+ assert (l == 0);
+ }
+ if (gencore)
+ pthread_join (thread, NULL);
+ else
+ raise (SIGUSR2);
+ /* Not reached. */
+ abort ();
+}
diff --git a/tests/backtrace-data.c b/tests/backtrace-data.c
new file mode 100644
index 00000000..9fa3c4a9
--- /dev/null
+++ b/tests/backtrace-data.c
@@ -0,0 +1,328 @@
+/* Test custom provided Dwfl_Thread_Callbacks vector.
+ 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 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/>. */
+
+/* Test custom provided Dwfl_Thread_Callbacks vector. Test mimics what
+ a ptrace based vector would do. */
+
+#include <config.h>
+#include <assert.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdio_ext.h>
+#include <locale.h>
+#include <dirent.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <error.h>
+#include <unistd.h>
+#include <dwarf.h>
+#include <sys/resource.h>
+#include <sys/ptrace.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/user.h>
+#include <fcntl.h>
+#include <string.h>
+#include ELFUTILS_HEADER(dwfl)
+
+#ifndef __x86_64__
+
+int
+main (int argc __attribute__ ((unused)), char **argv)
+{
+ fprintf (stderr, "%s: Unwinding not supported for this architecture\n",
+ argv[0]);
+ return 77;
+}
+
+#else /* __x86_64__ */
+
+/* The only arch specific code is set_initial_registers. */
+
+static int
+find_elf (Dwfl_Module *mod __attribute__ ((unused)),
+ void **userdata __attribute__ ((unused)),
+ const char *modname __attribute__ ((unused)),
+ Dwarf_Addr base __attribute__ ((unused)),
+ char **file_name __attribute__ ((unused)),
+ Elf **elfp __attribute__ ((unused)))
+{
+ /* Not used as modules are reported explicitly. */
+ assert (0);
+}
+
+static bool
+memory_read (Dwfl *dwfl, Dwarf_Addr addr, Dwarf_Word *result,
+ void *dwfl_arg __attribute__ ((unused)))
+{
+ pid_t child = dwfl_pid (dwfl);
+
+ errno = 0;
+ long l = ptrace (PTRACE_PEEKDATA, child, (void *) (uintptr_t) addr, NULL);
+ assert_perror (errno);
+ *result = l;
+
+ /* We could also return false for failed ptrace. */
+ return true;
+}
+
+/* Return filename and VMA address *BASEP where its mapping starts which
+ contains ADDR. */
+
+static char *
+maps_lookup (pid_t pid, Dwarf_Addr addr, GElf_Addr *basep)
+{
+ char *fname;
+ int i = asprintf (&fname, "/proc/%ld/maps", (long) pid);
+ assert_perror (errno);
+ assert (i > 0);
+ FILE *f = fopen (fname, "r");
+ assert_perror (errno);
+ assert (f);
+ free (fname);
+ for (;;)
+ {
+ // 37e3c22000-37e3c23000 rw-p 00022000 00:11 49532 /lib64/ld-2.14.90.so */
+ unsigned long start, end, offset;
+ i = fscanf (f, "%lx-%lx %*s %lx %*x:%*x %*x", &start, &end, &offset);
+ assert_perror (errno);
+ assert (i == 3);
+ char *filename = strdup ("");
+ assert (filename);
+ size_t filename_len = 0;
+ for (;;)
+ {
+ int c = fgetc (f);
+ assert (c != EOF);
+ if (c == '\n')
+ break;
+ if (c == ' ' && *filename == '\0')
+ continue;
+ filename = realloc (filename, filename_len + 2);
+ assert (filename);
+ filename[filename_len++] = c;
+ filename[filename_len] = '\0';
+ }
+ if (start <= addr && addr < end)
+ {
+ i = fclose (f);
+ assert_perror (errno);
+ assert (i == 0);
+
+ *basep = start - offset;
+ return filename;
+ }
+ free (filename);
+ }
+}
+
+/* Add module containing ADDR to the DWFL address space.
+
+ dwfl_report_elf call here violates Dwfl manipulation as one should call
+ dwfl_report only between dwfl_report_begin_add and dwfl_report_end.
+ Current elfutils implementation does not mind as dwfl_report_begin_add is
+ empty. */
+
+static Dwfl_Module *
+report_module (Dwfl *dwfl, pid_t child, Dwarf_Addr addr)
+{
+ GElf_Addr base;
+ char *long_name = maps_lookup (child, addr, &base);
+ Dwfl_Module *mod = dwfl_report_elf (dwfl, long_name, long_name, -1,
+ base, false /* add_p_vaddr */);
+ assert (mod);
+ free (long_name);
+ assert (dwfl_addrmodule (dwfl, addr) == mod);
+ return mod;
+}
+
+static pid_t
+next_thread (Dwfl *dwfl, void *dwfl_arg __attribute__ ((unused)),
+ void **thread_argp)
+{
+ if (*thread_argp != NULL)
+ return 0;
+ /* Put arbitrary non-NULL value into *THREAD_ARGP as a marker so that this
+ function returns non-zero PID only once. */
+ *thread_argp = thread_argp;
+ return dwfl_pid (dwfl);
+}
+
+static bool
+set_initial_registers (Dwfl_Thread *thread,
+ void *thread_arg __attribute__ ((unused)))
+{
+ pid_t child = dwfl_pid (dwfl_thread_dwfl (thread));
+
+ struct user_regs_struct user_regs;
+ long l = ptrace (PTRACE_GETREGS, child, NULL, &user_regs);
+ assert_perror (errno);
+ assert (l == 0);
+
+ Dwarf_Word dwarf_regs[17];
+ dwarf_regs[0] = user_regs.rax;
+ dwarf_regs[1] = user_regs.rdx;
+ dwarf_regs[2] = user_regs.rcx;
+ dwarf_regs[3] = user_regs.rbx;
+ dwarf_regs[4] = user_regs.rsi;
+ dwarf_regs[5] = user_regs.rdi;
+ dwarf_regs[6] = user_regs.rbp;
+ dwarf_regs[7] = user_regs.rsp;
+ dwarf_regs[8] = user_regs.r8;
+ dwarf_regs[9] = user_regs.r9;
+ dwarf_regs[10] = user_regs.r10;
+ dwarf_regs[11] = user_regs.r11;
+ dwarf_regs[12] = user_regs.r12;
+ dwarf_regs[13] = user_regs.r13;
+ dwarf_regs[14] = user_regs.r14;
+ dwarf_regs[15] = user_regs.r15;
+ dwarf_regs[16] = user_regs.rip;
+ bool ok = dwfl_thread_state_registers (thread, 0, 17, dwarf_regs);
+ assert (ok);
+
+ /* x86_64 has PC contained in its CFI subset of DWARF register set so
+ elfutils will figure out the real PC value from REGS.
+ So no need to explicitly call dwfl_thread_state_register_pc. */
+
+ return true;
+}
+
+static const Dwfl_Thread_Callbacks callbacks =
+{
+ next_thread,
+ NULL, /* get_thread */
+ memory_read,
+ set_initial_registers,
+ NULL, /* detach */
+ NULL, /* thread_detach */
+};
+
+static int
+frame_callback (Dwfl_Frame *state, void *arg)
+{
+ unsigned *framenop = arg;
+ Dwarf_Addr pc;
+ bool isactivation;
+ if (! dwfl_frame_pc (state, &pc, &isactivation))
+ {
+ error (1, 0, "%s", dwfl_errmsg (-1));
+ return 1;
+ }
+ 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);
+ if (mod == NULL)
+ mod = report_module (dwfl, dwfl_pid (dwfl), pc_adjusted);
+ const char *symname = NULL;
+ symname = dwfl_module_addrname (mod, pc_adjusted);
+
+ printf ("#%2u %#" PRIx64 "%4s\t%s\n", (*framenop)++, (uint64_t) pc,
+ ! isactivation ? "- 1" : "", symname);
+ return DWARF_CB_OK;
+}
+
+static int
+thread_callback (Dwfl_Thread *thread, void *thread_arg __attribute__ ((unused)))
+{
+ unsigned frameno = 0;
+ switch (dwfl_thread_getframes (thread, frame_callback, &frameno))
+ {
+ case 0:
+ break;
+ case -1:
+ error (1, 0, "dwfl_thread_getframes: %s", dwfl_errmsg (-1));
+ default:
+ abort ();
+ }
+ return DWARF_CB_OK;
+}
+
+int
+main (int argc __attribute__ ((unused)), char **argv __attribute__ ((unused)))
+{
+ /* We use no threads here which can interfere with handling a stream. */
+ __fsetlocking (stdin, FSETLOCKING_BYCALLER);
+ __fsetlocking (stdout, FSETLOCKING_BYCALLER);
+ __fsetlocking (stderr, FSETLOCKING_BYCALLER);
+
+ /* Set locale. */
+ (void) setlocale (LC_ALL, "");
+
+ elf_version (EV_CURRENT);
+
+ pid_t child = fork ();
+ switch (child)
+ {
+ case -1:
+ assert_perror (errno);
+ assert (0);
+ case 0:;
+ long l = ptrace (PTRACE_TRACEME, 0, NULL, NULL);
+ assert_perror (errno);
+ assert (l == 0);
+ raise (SIGUSR1);
+ assert (0);
+ default:
+ break;
+ }
+
+ int status;
+ pid_t pid = waitpid (child, &status, 0);
+ assert_perror (errno);
+ assert (pid == child);
+ assert (WIFSTOPPED (status));
+ assert (WSTOPSIG (status) == SIGUSR1);
+
+ static char *debuginfo_path;
+ static const Dwfl_Callbacks offline_callbacks =
+ {
+ .find_debuginfo = dwfl_standard_find_debuginfo,
+ .debuginfo_path = &debuginfo_path,
+ .section_address = dwfl_offline_section_address,
+ .find_elf = find_elf,
+ };
+ Dwfl *dwfl = dwfl_begin (&offline_callbacks);
+ assert (dwfl);
+
+ struct user_regs_struct user_regs;
+ long l = ptrace (PTRACE_GETREGS, child, NULL, &user_regs);
+ assert_perror (errno);
+ assert (l == 0);
+ report_module (dwfl, child, user_regs.rip);
+
+ bool ok = dwfl_attach_state (dwfl, EM_NONE, child, &callbacks, NULL);
+ assert (ok);
+
+ /* Multiple threads are not handled here. */
+ int err = dwfl_getthreads (dwfl, thread_callback, NULL);
+ assert (! err);
+
+ dwfl_end (dwfl);
+ kill (child, SIGKILL);
+ pid = waitpid (child, &status, 0);
+ assert_perror (errno);
+ assert (pid == child);
+ assert (WIFSIGNALED (status));
+ assert (WTERMSIG (status) == SIGKILL);
+
+ return EXIT_SUCCESS;
+}
+
+#endif /* x86_64 */
diff --git a/tests/backtrace-dwarf.c b/tests/backtrace-dwarf.c
new file mode 100644
index 00000000..3a3e7632
--- /dev/null
+++ b/tests/backtrace-dwarf.c
@@ -0,0 +1,161 @@
+/* Test program for unwinding of complicated DWARF expressions.
+ 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 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 <config.h>
+#include <assert.h>
+#include <signal.h>
+#include <inttypes.h>
+#include <stdio_ext.h>
+#include <locale.h>
+#include <errno.h>
+#include <sys/ptrace.h>
+#include ELFUTILS_HEADER(dwfl)
+
+static void cleanup_13_abort (void);
+#define main cleanup_13_main
+#include "cleanup-13.c"
+#undef main
+
+static void
+report_pid (Dwfl *dwfl, pid_t pid)
+{
+ int result = dwfl_linux_proc_report (dwfl, pid);
+ if (result < 0)
+ error (2, 0, "dwfl_linux_proc_report: %s", dwfl_errmsg (-1));
+ else if (result > 0)
+ error (2, result, "dwfl_linux_proc_report");
+
+ if (dwfl_report_end (dwfl, NULL, NULL) != 0)
+ error (2, 0, "dwfl_report_end: %s", dwfl_errmsg (-1));
+
+ result = dwfl_linux_proc_attach (dwfl, pid, false);
+ if (result < 0)
+ error (2, 0, "dwfl_linux_proc_attach: %s", dwfl_errmsg (-1));
+ else if (result > 0)
+ error (2, result, "dwfl_linux_proc_attach");
+}
+
+static Dwfl *
+pid_to_dwfl (pid_t pid)
+{
+ static char *debuginfo_path;
+ static const Dwfl_Callbacks proc_callbacks =
+ {
+ .find_debuginfo = dwfl_standard_find_debuginfo,
+ .debuginfo_path = &debuginfo_path,
+
+ .find_elf = dwfl_linux_proc_find_elf,
+ };
+ Dwfl *dwfl = dwfl_begin (&proc_callbacks);
+ if (dwfl == NULL)
+ error (2, 0, "dwfl_begin: %s", dwfl_errmsg (-1));
+ report_pid (dwfl, pid);
+ return dwfl;
+}
+
+static int
+frame_callback (Dwfl_Frame *state, void *frame_arg)
+{
+ Dwarf_Addr pc;
+ bool isactivation;
+ if (! dwfl_frame_pc (state, &pc, &isactivation))
+ {
+ error (0, 0, "%s", dwfl_errmsg (-1));
+ return DWARF_CB_ABORT;
+ }
+ Dwarf_Addr pc_adjusted = pc - (isactivation ? 0 : 1);
+
+ /* Get PC->SYMNAME. */
+ Dwfl_Thread *thread = dwfl_frame_thread (state);
+ Dwfl *dwfl = dwfl_thread_dwfl (thread);
+ Dwfl_Module *mod = dwfl_addrmodule (dwfl, pc_adjusted);
+ const char *symname = NULL;
+ if (mod)
+ symname = dwfl_module_addrname (mod, pc_adjusted);
+
+ printf ("%#" PRIx64 "\t%s\n", (uint64_t) pc, symname);
+
+ if (symname && (strcmp (symname, "main") == 0
+ || strcmp (symname, ".main") == 0))
+ {
+ kill (dwfl_pid (dwfl), SIGKILL);
+ exit (0);
+ }
+
+ return DWARF_CB_OK;
+}
+
+static int
+thread_callback (Dwfl_Thread *thread, void *thread_arg)
+{
+ dwfl_thread_getframes (thread, frame_callback, NULL);
+ error (1, 0, "dwfl_thread_getframes: %s", dwfl_errmsg (-1));
+}
+
+static void
+ptrace_detach_stopped (pid_t pid)
+{
+ errno = 0;
+ long l = ptrace (PTRACE_DETACH, pid, NULL, (void *) (intptr_t) SIGSTOP);
+ assert_perror (errno);
+ assert (l == 0);
+}
+
+int
+main (int argc __attribute__ ((unused)), char **argv)
+{
+ /* We use no threads here which can interfere with handling a stream. */
+ __fsetlocking (stdin, FSETLOCKING_BYCALLER);
+ __fsetlocking (stdout, FSETLOCKING_BYCALLER);
+ __fsetlocking (stderr, FSETLOCKING_BYCALLER);
+
+ /* Set locale. */
+ (void) setlocale (LC_ALL, "");
+
+ elf_version (EV_CURRENT);
+
+ pid_t pid = fork ();
+ switch (pid)
+ {
+ case -1:
+ abort ();
+ case 0:;
+ long l = ptrace (PTRACE_TRACEME, 0, NULL, NULL);
+ assert_perror (errno);
+ assert (l == 0);
+ cleanup_13_main ();
+ abort ();
+ default:
+ break;
+ }
+
+ errno = 0;
+ int status;
+ pid_t got = waitpid (pid, &status, 0);
+ assert_perror (errno);
+ assert (got == pid);
+ assert (WIFSTOPPED (status));
+ assert (WSTOPSIG (status) == SIGABRT);
+
+ ptrace_detach_stopped (pid);
+
+ Dwfl *dwfl = pid_to_dwfl (pid);
+ dwfl_getthreads (dwfl, thread_callback, NULL);
+
+ /* There is an exit (0) call if we find the "main" frame, */
+ error (1, 0, "dwfl_getthreads: %s", dwfl_errmsg (-1));
+}
diff --git a/tests/backtrace-subr.sh b/tests/backtrace-subr.sh
new file mode 100644
index 00000000..580a1cea
--- /dev/null
+++ b/tests/backtrace-subr.sh
@@ -0,0 +1,126 @@
+# 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 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/>.
+
+. $srcdir/test-subr.sh
+
+# Verify one of the backtraced threads contains function 'main'.
+check_main()
+{
+ if grep -w main $1; then
+ return
+ fi
+ echo >&2 $2: no main
+ false
+}
+
+# Without proper ELF symbols resolution we could get inappropriate weak
+# symbol "gsignal" with the same address as the correct symbol "raise".
+# It was fixed by GIT commit 78dec228b3cfb2f9300cd0b682ebf416c9674c91 .
+# [patch] Improve ELF symbols preference (global > weak)
+# https://lists.fedorahosted.org/pipermail/elfutils-devel/2012-October/002624.html
+check_gsignal()
+{
+ if ! grep -w gsignal $1; then
+ return
+ fi
+ echo >&2 $2: found gsignal
+ false
+}
+
+# Verify the STDERR output does not contain unexpected errors.
+# In some cases we cannot reliably find out we got behind _start as some
+# operating system do not properly terminate CFI by undefined PC.
+# Ignore it here as it is a bug of OS, not a bug of elfutils.
+check_err()
+{
+ if [ $(egrep -v <$1 'dwfl_thread_getframes: (No DWARF information found|no matching address range)$' \
+ | wc -c) \
+ -eq 0 ]
+ then
+ return
+ fi
+ echo >&2 $2: neither empty nor just out of DWARF
+ false
+}
+
+check_all()
+{
+ bt=$1
+ err=$2
+ testname=$3
+ check_main $bt $testname
+ check_gsignal $bt $testname
+ check_err $err $testname
+}
+
+check_unsupported()
+{
+ err=$1
+ testname=$2
+ if grep -q ': Unwinding not supported for this architecture$' $err; then
+ echo >&2 $testname: arch not supported
+ exit 77
+ fi
+}
+
+check_core()
+{
+ arch=$1
+ testfiles backtrace.$arch.{exec,core}
+ tempfiles backtrace.$arch.{bt,err}
+ echo ./backtrace ./backtrace.$arch.{exec,core}
+ testrun ${abs_builddir}/backtrace -e ./backtrace.$arch.exec --core=./backtrace.$arch.core 1>backtrace.$arch.bt 2>backtrace.$arch.err || true
+ cat backtrace.$arch.{bt,err}
+ check_all backtrace.$arch.{bt,err} backtrace.$arch.core
+}
+
+# Backtrace live process.
+# Do not abort on non-zero exit code due to some warnings of ./backtrace
+# - see function check_err.
+check_native()
+{
+ child=$1
+ tempfiles $child.{bt,err}
+ (set +ex; testrun ${abs_builddir}/backtrace --backtrace-exec=${abs_builddir}/$child 1>$child.bt 2>$child.err; true)
+ cat $child.{bt,err}
+ check_unsupported $child.err $child
+ check_all $child.{bt,err} $child
+}
+
+# Backtrace core file.
+check_native_core()
+{
+ child=$1
+
+ # Disable valgrind while dumping core.
+ SAVED_VALGRIND_CMD="$VALGRIND_CMD"
+ unset VALGRIND_CMD
+
+ core="core.`ulimit -c unlimited; set +ex; testrun ${abs_builddir}/$child --gencore; true`"
+
+ if [ "x$SAVED_VALGRIND_CMD" != "x" ]; then
+ VALGRIND_CMD="$SAVED_VALGRIND_CMD"
+ export VALGRIND_CMD
+ fi
+
+ # Do not abort on non-zero exit code due to some warnings of ./backtrace
+ # - see function check_err.
+ tempfiles $core{,.{bt,err}}
+ (set +ex; testrun ${abs_builddir}/backtrace -e ${abs_builddir}/$child --core=$core 1>$core.bt 2>$core.err; true)
+ cat $core.{bt,err}
+ check_unsupported $core.err $child-$core
+ check_all $core.{bt,err} $child-$core
+}
diff --git a/tests/backtrace.c b/tests/backtrace.c
new file mode 100644
index 00000000..64f90c43
--- /dev/null
+++ b/tests/backtrace.c
@@ -0,0 +1,464 @@
+/* Test program for unwinding of frames.
+ 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 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 <config.h>
+#include <assert.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdio_ext.h>
+#include <locale.h>
+#include <dirent.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <error.h>
+#include <unistd.h>
+#include <dwarf.h>
+#include <sys/resource.h>
+#include <sys/ptrace.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/user.h>
+#include <fcntl.h>
+#include <string.h>
+#include <argp.h>
+#include ELFUTILS_HEADER(dwfl)
+
+static int
+dump_modules (Dwfl_Module *mod, void **userdata __attribute__ ((unused)),
+ const char *name, Dwarf_Addr start,
+ void *arg __attribute__ ((unused)))
+{
+ Dwarf_Addr end;
+ dwfl_module_info (mod, NULL, NULL, &end, NULL, NULL, NULL, NULL);
+ printf ("%#" PRIx64 "\t%#" PRIx64 "\t%s\n", (uint64_t) start, (uint64_t) end,
+ name);
+ return DWARF_CB_OK;
+}
+
+static bool is_x86_64_native;
+static pid_t check_tid;
+
+static void
+callback_verify (pid_t tid, unsigned frameno, Dwarf_Addr pc,
+ const char *symname, Dwfl *dwfl)
+{
+ static bool seen_main = false;
+ if (symname && *symname == '.')
+ symname++;
+ if (symname && strcmp (symname, "main") == 0)
+ seen_main = true;
+ if (pc == 0)
+ {
+ assert (seen_main);
+ return;
+ }
+ if (check_tid == 0)
+ check_tid = tid;
+ if (tid != check_tid)
+ {
+ // For the main thread we are only interested if we can unwind till
+ // we see the "main" symbol.
+ return;
+ }
+ Dwfl_Module *mod;
+ static bool reduce_frameno = false;
+ if (reduce_frameno)
+ frameno--;
+ if (! is_x86_64_native && frameno >= 2)
+ frameno += 2;
+ const char *symname2 = NULL;
+ switch (frameno)
+ {
+ case 0:
+ if (! reduce_frameno && symname
+ && strcmp (symname, "__kernel_vsyscall") == 0)
+ reduce_frameno = true;
+ else
+ assert (symname && strcmp (symname, "raise") == 0);
+ break;
+ case 1:
+ assert (symname != NULL && strcmp (symname, "sigusr2") == 0);
+ break;
+ case 2: // x86_64 only
+ /* __restore_rt - glibc maybe does not have to have this symbol. */
+ break;
+ case 3: // x86_64 only
+ if (is_x86_64_native)
+ {
+ /* Verify we trapped on the very first instruction of jmp. */
+ assert (symname != NULL && strcmp (symname, "jmp") == 0);
+ mod = dwfl_addrmodule (dwfl, pc - 1);
+ if (mod)
+ symname2 = dwfl_module_addrname (mod, pc - 1);
+ assert (symname2 == NULL || strcmp (symname2, "jmp") != 0);
+ break;
+ }
+ /* PASSTHRU */
+ case 4:
+ assert (symname != NULL && strcmp (symname, "stdarg") == 0);
+ break;
+ case 5:
+ /* Verify we trapped on the very last instruction of child. */
+ assert (symname != NULL && strcmp (symname, "backtracegen") == 0);
+ mod = dwfl_addrmodule (dwfl, pc);
+ if (mod)
+ symname2 = dwfl_module_addrname (mod, pc);
+
+ // Note that the following assert might in theory even fail on x86_64,
+ // there is no guarantee that the compiler doesn't reorder the
+ // instructions or even inserts some padding instructions at the end
+ // (which apparently happens on ppc64).
+ if (is_x86_64_native)
+ assert (symname2 == NULL || strcmp (symname2, "backtracegen") != 0);
+ break;
+ }
+}
+
+static int
+frame_callback (Dwfl_Frame *state, void *frame_arg)
+{
+ int *framenop = frame_arg;
+ Dwarf_Addr pc;
+ bool isactivation;
+ if (! dwfl_frame_pc (state, &pc, &isactivation))
+ {
+ error (0, 0, "%s", dwfl_errmsg (-1));
+ return DWARF_CB_ABORT;
+ }
+ Dwarf_Addr pc_adjusted = pc - (isactivation ? 0 : 1);
+
+ /* Get PC->SYMNAME. */
+ Dwfl_Thread *thread = dwfl_frame_thread (state);
+ Dwfl *dwfl = dwfl_thread_dwfl (thread);
+ Dwfl_Module *mod = dwfl_addrmodule (dwfl, pc_adjusted);
+ const char *symname = NULL;
+ if (mod)
+ symname = dwfl_module_addrname (mod, pc_adjusted);
+
+ printf ("#%2d %#" PRIx64 "%4s\t%s\n", *framenop, (uint64_t) pc,
+ ! isactivation ? "- 1" : "", symname);
+ pid_t tid = dwfl_thread_tid (thread);
+ callback_verify (tid, *framenop, pc, symname, dwfl);
+ (*framenop)++;
+
+ return DWARF_CB_OK;
+}
+
+static int
+thread_callback (Dwfl_Thread *thread, void *thread_arg __attribute__((unused)))
+{
+ printf ("TID %ld:\n", (long) dwfl_thread_tid (thread));
+ int frameno = 0;
+ switch (dwfl_thread_getframes (thread, frame_callback, &frameno))
+ {
+ case 0:
+ break;
+ case DWARF_CB_ABORT:
+ return DWARF_CB_ABORT;
+ case -1:
+ error (0, 0, "dwfl_thread_getframes: %s", dwfl_errmsg (-1));
+ /* All platforms do not have yet proper unwind termination. */
+ break;
+ default:
+ abort ();
+ }
+ return DWARF_CB_OK;
+}
+
+static void
+dump (Dwfl *dwfl)
+{
+ ptrdiff_t ptrdiff = dwfl_getmodules (dwfl, dump_modules, NULL, 0);
+ assert (ptrdiff == 0);
+ bool err = false;
+ switch (dwfl_getthreads (dwfl, thread_callback, NULL))
+ {
+ case 0:
+ break;
+ case DWARF_CB_ABORT:
+ err = true;
+ break;
+ case -1:
+ error (0, 0, "dwfl_getthreads: %s", dwfl_errmsg (-1));
+ err = true;
+ break;
+ default:
+ abort ();
+ }
+ callback_verify (0, 0, 0, NULL, dwfl);
+ if (err)
+ exit (EXIT_FAILURE);
+}
+
+struct see_exec_module
+{
+ Dwfl_Module *mod;
+ char selfpath[PATH_MAX + 1];
+};
+
+static int
+see_exec_module (Dwfl_Module *mod, void **userdata __attribute__ ((unused)),
+ const char *name __attribute__ ((unused)),
+ Dwarf_Addr start __attribute__ ((unused)), void *arg)
+{
+ struct see_exec_module *data = arg;
+ if (strcmp (name, data->selfpath) != 0)
+ return DWARF_CB_OK;
+ assert (data->mod == NULL);
+ data->mod = mod;
+ return DWARF_CB_OK;
+}
+
+/* On x86_64 only:
+ PC will get changed to function 'jmp' by backtrace.c function
+ prepare_thread. Then SIGUSR2 will be signalled to backtrace-child
+ which will invoke function sigusr2.
+ This is all done so that signal interrupts execution of the very first
+ instruction of a function. Properly handled unwind should not slip into
+ the previous unrelated function. */
+
+static void
+prepare_thread (pid_t pid2 __attribute__ ((unused)),
+ void (*jmp) (void) __attribute__ ((unused)))
+{
+#ifndef __x86_64__
+ abort ();
+#else /* x86_64 */
+ long l;
+ errno = 0;
+ l = ptrace (PTRACE_POKEUSER, pid2,
+ (void *) (intptr_t) offsetof (struct user_regs_struct, rip), jmp);
+ assert_perror (errno);
+ assert (l == 0);
+ l = ptrace (PTRACE_CONT, pid2, NULL, (void *) (intptr_t) SIGUSR2);
+ int status;
+ pid_t got = waitpid (pid2, &status, __WALL);
+ assert_perror (errno);
+ assert (got == pid2);
+ assert (WIFSTOPPED (status));
+ assert (WSTOPSIG (status) == SIGUSR1);
+#endif /* __x86_64__ */
+}
+
+#include <asm/unistd.h>
+#include <unistd.h>
+#define tgkill(pid, tid, sig) syscall (__NR_tgkill, (pid), (tid), (sig))
+
+static void
+ptrace_detach_stopped (pid_t pid)
+{
+ errno = 0;
+ long l = ptrace (PTRACE_DETACH, pid, NULL, (void *) (intptr_t) SIGSTOP);
+ assert_perror (errno);
+ assert (l == 0);
+}
+
+static void
+report_pid (Dwfl *dwfl, pid_t pid)
+{
+ int result = dwfl_linux_proc_report (dwfl, pid);
+ if (result < 0)
+ error (2, 0, "dwfl_linux_proc_report: %s", dwfl_errmsg (-1));
+ else if (result > 0)
+ error (2, result, "dwfl_linux_proc_report");
+
+ if (dwfl_report_end (dwfl, NULL, NULL) != 0)
+ error (2, 0, "dwfl_report_end: %s", dwfl_errmsg (-1));
+
+ result = dwfl_linux_proc_attach (dwfl, pid, false);
+ if (result < 0)
+ error (2, 0, "dwfl_linux_proc_attach: %s", dwfl_errmsg (-1));
+ else if (result > 0)
+ error (2, result, "dwfl_linux_proc_attach");
+}
+
+static Dwfl *
+pid_to_dwfl (pid_t pid)
+{
+ static char *debuginfo_path;
+ static const Dwfl_Callbacks proc_callbacks =
+ {
+ .find_debuginfo = dwfl_standard_find_debuginfo,
+ .debuginfo_path = &debuginfo_path,
+
+ .find_elf = dwfl_linux_proc_find_elf,
+ };
+ Dwfl *dwfl = dwfl_begin (&proc_callbacks);
+ if (dwfl == NULL)
+ error (2, 0, "dwfl_begin: %s", dwfl_errmsg (-1));
+ report_pid (dwfl, pid);
+ return dwfl;
+}
+
+static void
+exec_dump (const char *exec)
+{
+ pid_t pid = fork ();
+ switch (pid)
+ {
+ case -1:
+ abort ();
+ case 0:
+ execl (exec, exec, "--ptraceme", NULL);
+ abort ();
+ default:
+ break;
+ }
+
+ /* Catch the main thread. Catch it first otherwise the /proc evaluation of
+ PID may have caught still ourselves before executing execl above. */
+ errno = 0;
+ int status;
+ pid_t got = waitpid (pid, &status, 0);
+ assert_perror (errno);
+ assert (got == pid);
+ assert (WIFSTOPPED (status));
+ // Main thread will signal SIGUSR2. Other thread will signal SIGUSR1.
+ assert (WSTOPSIG (status) == SIGUSR2);
+
+ /* Catch the spawned thread. Do not use __WCLONE as we could get racy
+ __WCLONE, probably despite pthread_create already had to be called the new
+ task is not yet alive enough for waitpid. */
+ pid_t pid2 = waitpid (-1, &status, __WALL);
+ assert_perror (errno);
+ assert (pid2 > 0);
+ assert (pid2 != pid);
+ assert (WIFSTOPPED (status));
+ // Main thread will signal SIGUSR2. Other thread will signal SIGUSR1.
+ assert (WSTOPSIG (status) == SIGUSR1);
+
+ Dwfl *dwfl = pid_to_dwfl (pid);
+ char *selfpathname;
+ int i = asprintf (&selfpathname, "/proc/%ld/exe", (long) pid);
+ assert (i > 0);
+ struct see_exec_module data;
+ ssize_t ssize = readlink (selfpathname, data.selfpath,
+ sizeof (data.selfpath));
+ free (selfpathname);
+ assert (ssize > 0 && ssize < (ssize_t) sizeof (data.selfpath));
+ data.selfpath[ssize] = '\0';
+ data.mod = NULL;
+ ptrdiff_t ptrdiff = dwfl_getmodules (dwfl, see_exec_module, &data, 0);
+ assert (ptrdiff == 0);
+ assert (data.mod != NULL);
+ GElf_Addr loadbase;
+ Elf *elf = dwfl_module_getelf (data.mod, &loadbase);
+ GElf_Ehdr ehdr_mem, *ehdr = gelf_getehdr (elf, &ehdr_mem);
+ assert (ehdr != NULL);
+ /* It is false also on x86_64 with i386 inferior. */
+#ifndef __x86_64__
+ is_x86_64_native = false;
+#else /* __x86_64__ */
+ is_x86_64_native = ehdr->e_ident[EI_CLASS] == ELFCLASS64;
+#endif /* __x86_64__ */
+ void (*jmp) (void);
+ if (is_x86_64_native)
+ {
+ // Find inferior symbol named "jmp".
+ int nsym = dwfl_module_getsymtab (data.mod);
+ int symi;
+ for (symi = 1; symi < nsym; ++symi)
+ {
+ GElf_Sym symbol;
+ const char *symbol_name = dwfl_module_getsym (data.mod, symi, &symbol, NULL);
+ if (symbol_name == NULL)
+ continue;
+ switch (GELF_ST_TYPE (symbol.st_info))
+ {
+ case STT_SECTION:
+ case STT_FILE:
+ case STT_TLS:
+ continue;
+ default:
+ if (strcmp (symbol_name, "jmp") != 0)
+ continue;
+ break;
+ }
+ /* LOADBASE is already applied here. */
+ jmp = (void (*) (void)) (uintptr_t) symbol.st_value;
+ break;
+ }
+ assert (symi < nsym);
+ prepare_thread (pid2, jmp);
+ }
+ dwfl_end (dwfl);
+ ptrace_detach_stopped (pid);
+ ptrace_detach_stopped (pid2);
+ check_tid = pid2;
+ dwfl = pid_to_dwfl (pid);
+ dump (dwfl);
+ dwfl_end (dwfl);
+}
+
+#define OPT_BACKTRACE_EXEC 0x100
+
+static const struct argp_option options[] =
+ {
+ { "backtrace-exec", OPT_BACKTRACE_EXEC, "EXEC", 0, N_("Run executable"), 0 },
+ { NULL, 0, NULL, 0, NULL, 0 }
+ };
+
+
+static error_t
+parse_opt (int key, char *arg, struct argp_state *state)
+{
+ switch (key)
+ {
+ case ARGP_KEY_INIT:
+ state->child_inputs[0] = state->input;
+ break;
+
+ case OPT_BACKTRACE_EXEC:
+ exec_dump (arg);
+ exit (0);
+
+ default:
+ return ARGP_ERR_UNKNOWN;
+ }
+ return 0;
+}
+
+int
+main (int argc __attribute__ ((unused)), char **argv)
+{
+ /* We use no threads here which can interfere with handling a stream. */
+ __fsetlocking (stdin, FSETLOCKING_BYCALLER);
+ __fsetlocking (stdout, FSETLOCKING_BYCALLER);
+ __fsetlocking (stderr, FSETLOCKING_BYCALLER);
+
+ /* Set locale. */
+ (void) setlocale (LC_ALL, "");
+
+ elf_version (EV_CURRENT);
+
+ Dwfl *dwfl = NULL;
+ const struct argp_child argp_children[] =
+ {
+ { .argp = dwfl_standard_argp () },
+ { .argp = NULL }
+ };
+ const struct argp argp =
+ {
+ options, parse_opt, NULL, NULL, argp_children, NULL, NULL
+ };
+ (void) argp_parse (&argp, argc, argv, 0, NULL, &dwfl);
+ assert (dwfl != NULL);
+ dump (dwfl);
+ dwfl_end (dwfl);
+ return 0;
+}
diff --git a/tests/backtrace.i386.core.bz2 b/tests/backtrace.i386.core.bz2
new file mode 100644
index 00000000..e120d9bd
--- /dev/null
+++ b/tests/backtrace.i386.core.bz2
Binary files differ
diff --git a/tests/backtrace.i386.exec.bz2 b/tests/backtrace.i386.exec.bz2
new file mode 100644
index 00000000..1b0f001c
--- /dev/null
+++ b/tests/backtrace.i386.exec.bz2
Binary files differ
diff --git a/tests/backtrace.ppc.core.bz2 b/tests/backtrace.ppc.core.bz2
new file mode 100644
index 00000000..f20cd9f3
--- /dev/null
+++ b/tests/backtrace.ppc.core.bz2
Binary files differ
diff --git a/tests/backtrace.ppc.exec.bz2 b/tests/backtrace.ppc.exec.bz2
new file mode 100644
index 00000000..057c25a6
--- /dev/null
+++ b/tests/backtrace.ppc.exec.bz2
Binary files differ
diff --git a/tests/backtrace.s390.core.bz2 b/tests/backtrace.s390.core.bz2
new file mode 100644
index 00000000..db346948
--- /dev/null
+++ b/tests/backtrace.s390.core.bz2
Binary files differ
diff --git a/tests/backtrace.s390.exec.bz2 b/tests/backtrace.s390.exec.bz2
new file mode 100644
index 00000000..4c1b4aee
--- /dev/null
+++ b/tests/backtrace.s390.exec.bz2
Binary files differ
diff --git a/tests/backtrace.s390x.core.bz2 b/tests/backtrace.s390x.core.bz2
new file mode 100644
index 00000000..61c23ec4
--- /dev/null
+++ b/tests/backtrace.s390x.core.bz2
Binary files differ
diff --git a/tests/backtrace.s390x.exec.bz2 b/tests/backtrace.s390x.exec.bz2
new file mode 100644
index 00000000..8009239d
--- /dev/null
+++ b/tests/backtrace.s390x.exec.bz2
Binary files differ
diff --git a/tests/backtrace.x86_64.core.bz2 b/tests/backtrace.x86_64.core.bz2
new file mode 100644
index 00000000..1f34e206
--- /dev/null
+++ b/tests/backtrace.x86_64.core.bz2
Binary files differ
diff --git a/tests/backtrace.x86_64.exec.bz2 b/tests/backtrace.x86_64.exec.bz2
new file mode 100644
index 00000000..70a151be
--- /dev/null
+++ b/tests/backtrace.x86_64.exec.bz2
Binary files differ
diff --git a/tests/cleanup-13.c b/tests/cleanup-13.c
new file mode 100644
index 00000000..b87c6965
--- /dev/null
+++ b/tests/cleanup-13.c
@@ -0,0 +1,334 @@
+// http://gcc.gnu.org/viewcvs/gcc/trunk/gcc/testsuite/gcc.dg/cleanup-13.c?view=co&content-type=text%2Fplain
+
+/* HP-UX libunwind.so doesn't provide _UA_END_OF_STACK */
+/* { dg-do run } */
+/* { dg-options "-fexceptions" } */
+/* { dg-skip-if "" { "ia64-*-hpux11.*" } { "*" } { "" } } */
+/* Verify DW_OP_* handling in the unwinder. */
+
+#include <unwind.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* #define OP_addr(x) 0x06, ... */
+#define OP_deref 0x06,
+#define SLEB128(x) (x)&0x7f /* Assume here the value is -0x40 ... 0x3f. */
+#define ULEB128(x) (x)&0x7f /* Assume here the value is 0 ... 0x7f. */
+#define VAL1(x) (x)&0xff
+#if defined (__BIG_ENDIAN__)
+#define VAL2(x) ((x)>>8)&0xff,(x)&0xff
+#define VAL4(x) ((x)>>24)&0xff,((x)>>16)&0xff,((x)>>8)&0xff,(x)&0xff
+#define VAL8(x) ((x)>>56)&0xff,((x)>>48)&0xff,((x)>>40)&0xff,((x)>>32)&0xff,((x)>>24)&0xff,((x)>>16)&0xff,((x)>>8)&0xff,(x)&0xff
+#elif defined(__LITTLE_ENDIAN__) || defined(__x86_64__) || defined(__i386__)
+#define VAL2(x) (x)&0xff,((x)>>8)&0xff
+#define VAL4(x) (x)&0xff,((x)>>8)&0xff,((x)>>16)&0xff,((x)>>24)&0xff
+#define VAL8(x) (x)&0xff,((x)>>8)&0xff,((x)>>16)&0xff,((x)>>24)&0xff,((x)>>32)&0xff,((x)>>40)&0xff,((x)>>48)&0xff,((x)>>56)&0xff
+#endif
+#define OP_const1u(x) 0x08,VAL1(x),
+#define OP_const1s(x) 0x09,VAL1(x),
+#define OP_const2u(x) 0x0a,VAL2(x),
+#define OP_const2s(x) 0x0b,VAL2(x),
+#define OP_const4u(x) 0x0c,VAL4(x),
+#define OP_const4s(x) 0x0d,VAL4(x),
+#define OP_const8u(x) 0x0e,VAL8(x),
+#define OP_const8s(x) 0x0f,VAL8(x),
+#define OP_constu(x) 0x10,ULEB128(x),
+#define OP_consts(x) 0x11,SLEB128(x),
+#define OP_dup 0x12,
+#define OP_drop 0x13,
+#define OP_over 0x14,
+#define OP_pick(x) 0x15,VAL1(x),
+#define OP_swap 0x16,
+#define OP_rot 0x17,
+#define OP_xderef 0x18,
+#define OP_abs 0x19,
+#define OP_and 0x1a,
+#define OP_div 0x1b,
+#define OP_minus 0x1c,
+#define OP_mod 0x1d,
+#define OP_mul 0x1e,
+#define OP_neg 0x1f,
+#define OP_not 0x20,
+#define OP_or 0x21,
+#define OP_plus 0x22,
+#define OP_plus_uconst(x) 0x23,ULEB128(x),
+#define OP_shl 0x24,
+#define OP_shr 0x25,
+#define OP_shra 0x26,
+#define OP_xor 0x27,
+#define OP_bra(x) 0x28,VAL2(x),
+#define OP_eq 0x29,
+#define OP_ge 0x2a,
+#define OP_gt 0x2b,
+#define OP_le 0x2c,
+#define OP_lt 0x2d,
+#define OP_ne 0x2e,
+#define OP_skip(x) 0x2f,VAL2(x),
+#define OP_lit0 0x30,
+#define OP_lit1 0x31,
+#define OP_lit2 0x32,
+#define OP_lit3 0x33,
+#define OP_lit4 0x34,
+#define OP_lit5 0x35,
+#define OP_lit6 0x36,
+#define OP_lit7 0x37,
+#define OP_lit8 0x38,
+#define OP_lit9 0x39,
+#define OP_lit10 0x3a,
+#define OP_lit11 0x3b,
+#define OP_lit12 0x3c,
+#define OP_lit13 0x3d,
+#define OP_lit14 0x3e,
+#define OP_lit15 0x3f,
+#define OP_lit16 0x40,
+#define OP_lit17 0x41,
+#define OP_lit18 0x42,
+#define OP_lit19 0x43,
+#define OP_lit20 0x44,
+#define OP_lit21 0x45,
+#define OP_lit22 0x46,
+#define OP_lit23 0x47,
+#define OP_lit24 0x48,
+#define OP_lit25 0x49,
+#define OP_lit26 0x4a,
+#define OP_lit27 0x4b,
+#define OP_lit28 0x4c,
+#define OP_lit29 0x4d,
+#define OP_lit30 0x4e,
+#define OP_lit31 0x4f,
+#define OP_reg0 0x50,
+#define OP_reg1 0x51,
+#define OP_reg2 0x52,
+#define OP_reg3 0x53,
+#define OP_reg4 0x54,
+#define OP_reg5 0x55,
+#define OP_reg6 0x56,
+#define OP_reg7 0x57,
+#define OP_reg8 0x58,
+#define OP_reg9 0x59,
+#define OP_reg10 0x5a,
+#define OP_reg11 0x5b,
+#define OP_reg12 0x5c,
+#define OP_reg13 0x5d,
+#define OP_reg14 0x5e,
+#define OP_reg15 0x5f,
+#define OP_reg16 0x60,
+#define OP_reg17 0x61,
+#define OP_reg18 0x62,
+#define OP_reg19 0x63,
+#define OP_reg20 0x64,
+#define OP_reg21 0x65,
+#define OP_reg22 0x66,
+#define OP_reg23 0x67,
+#define OP_reg24 0x68,
+#define OP_reg25 0x69,
+#define OP_reg26 0x6a,
+#define OP_reg27 0x6b,
+#define OP_reg28 0x6c,
+#define OP_reg29 0x6d,
+#define OP_reg30 0x6e,
+#define OP_reg31 0x6f,
+#define OP_breg0(x) 0x70,SLEB128(x),
+#define OP_breg1(x) 0x71,SLEB128(x),
+#define OP_breg2(x) 0x72,SLEB128(x),
+#define OP_breg3(x) 0x73,SLEB128(x),
+#define OP_breg4(x) 0x74,SLEB128(x),
+#define OP_breg5(x) 0x75,SLEB128(x),
+#define OP_breg6(x) 0x76,SLEB128(x),
+#define OP_breg7(x) 0x77,SLEB128(x),
+#define OP_breg8(x) 0x78,SLEB128(x),
+#define OP_breg9(x) 0x79,SLEB128(x),
+#define OP_breg10(x) 0x7a,SLEB128(x),
+#define OP_breg11(x) 0x7b,SLEB128(x),
+#define OP_breg12(x) 0x7c,SLEB128(x),
+#define OP_breg13(x) 0x7d,SLEB128(x),
+#define OP_breg14(x) 0x7e,SLEB128(x),
+#define OP_breg15(x) 0x7f,SLEB128(x),
+#define OP_breg16(x) 0x80,SLEB128(x),
+#define OP_breg17(x) 0x81,SLEB128(x),
+#define OP_breg18(x) 0x82,SLEB128(x),
+#define OP_breg19(x) 0x83,SLEB128(x),
+#define OP_breg20(x) 0x84,SLEB128(x),
+#define OP_breg21(x) 0x85,SLEB128(x),
+#define OP_breg22(x) 0x86,SLEB128(x),
+#define OP_breg23(x) 0x87,SLEB128(x),
+#define OP_breg24(x) 0x88,SLEB128(x),
+#define OP_breg25(x) 0x89,SLEB128(x),
+#define OP_breg26(x) 0x8a,SLEB128(x),
+#define OP_breg27(x) 0x8b,SLEB128(x),
+#define OP_breg28(x) 0x8c,SLEB128(x),
+#define OP_breg29(x) 0x8d,SLEB128(x),
+#define OP_breg30(x) 0x8e,SLEB128(x),
+#define OP_breg31(x) 0x8f,SLEB128(x),
+#define OP_regx(x) 0x90,SLEB128(x),
+#define OP_fbreg(x) 0x91,SLEB128(x),
+#define OP_bregx(x,y) 0x92,ULEB128(x),SLEB128(y),
+#define OP_piece(x) 0x93,ULEB128(x),
+#define OP_deref_size(x) 0x94,VAL1(x),
+#define OP_xderef_size(x) 0x95,VAL1(x),
+#define OP_nop 0x96,
+#define OP_nop_termination 0x96
+#define OP_push_object_address 0x97,
+#define OP_call2(x) 0x98,VAL2(x),
+#define OP_call4(x) 0x99,VAL4(x),
+/* #define OP_call_ref(x) 0x9a,... */
+#define OP_form_tls_address(x) 0x9b,
+#define OP_call_frame_cfa 0x9c,
+#define OP_bit_piece(x) 0x9d,ULEB128(x),
+/* #define OP_implicit_value(x...) 0x9e,... */
+#define OP_stack_value 0x9f,
+#define OP_GNU_push_tls_address 0xe0,
+/* #define OP_GNU_encoded_addr(x...) 0xf1, */
+
+#define ASSERT_TOS_NON0 OP_bra(3) OP_skip(-3)
+#define ASSERT_TOS_0 OP_lit0 OP_eq ASSERT_TOS_NON0
+
+/* Initially there is CFA value on the stack, we want to
+ keep it there at the end. */
+#define CFI_PROGRAM \
+OP_lit0 OP_nop ASSERT_TOS_0 \
+OP_lit1 ASSERT_TOS_NON0 \
+OP_lit1 OP_const1u(1) OP_eq ASSERT_TOS_NON0 \
+OP_lit16 OP_const2u(16) OP_eq ASSERT_TOS_NON0 \
+OP_lit31 OP_const4u(31) OP_ne ASSERT_TOS_0 \
+OP_lit1 OP_neg OP_const1s(-1) OP_eq ASSERT_TOS_NON0 \
+OP_lit16 OP_neg OP_const2s(-16) OP_ne ASSERT_TOS_0 \
+OP_lit31 OP_const4s(-31) OP_neg OP_ne ASSERT_TOS_0 \
+OP_lit7 OP_dup OP_plus_uconst(2) OP_lit9 OP_eq ASSERT_TOS_NON0 \
+ OP_lit7 OP_eq ASSERT_TOS_NON0 \
+OP_lit20 OP_lit1 OP_drop OP_lit20 OP_eq ASSERT_TOS_NON0 \
+OP_lit17 OP_lit19 OP_over OP_lit17 OP_eq ASSERT_TOS_NON0 \
+ OP_lit19 OP_eq ASSERT_TOS_NON0 OP_lit17 OP_eq ASSERT_TOS_NON0 \
+OP_lit1 OP_lit2 OP_lit3 OP_lit4 OP_pick(2) OP_lit2 OP_eq ASSERT_TOS_NON0\
+ OP_lit4 OP_eq ASSERT_TOS_NON0 OP_lit3 OP_eq ASSERT_TOS_NON0 \
+ OP_pick(0) OP_lit2 OP_eq ASSERT_TOS_NON0 \
+ OP_lit2 OP_eq ASSERT_TOS_NON0 OP_lit1 OP_eq ASSERT_TOS_NON0 \
+OP_lit6 OP_lit12 OP_swap OP_lit6 OP_eq ASSERT_TOS_NON0 \
+ OP_lit12 OP_eq ASSERT_TOS_NON0 \
+OP_lit7 OP_lit8 OP_lit9 OP_rot OP_lit8 OP_eq ASSERT_TOS_NON0 \
+ OP_lit7 OP_eq ASSERT_TOS_NON0 OP_lit9 OP_eq ASSERT_TOS_NON0 \
+OP_lit7 OP_abs OP_lit7 OP_eq ASSERT_TOS_NON0 \
+OP_const1s(-123) OP_abs OP_const1u(123) OP_eq ASSERT_TOS_NON0 \
+OP_lit3 OP_lit6 OP_and OP_lit2 OP_eq ASSERT_TOS_NON0 \
+OP_lit3 OP_lit6 OP_or OP_lit7 OP_eq ASSERT_TOS_NON0 \
+OP_lit17 OP_lit2 OP_minus OP_lit15 OP_eq ASSERT_TOS_NON0 \
+/* Divide is signed truncating toward zero. */ \
+OP_const1s(-6) OP_const1s(-2) OP_div OP_lit3 OP_eq ASSERT_TOS_NON0 \
+OP_const1s(-7) OP_const1s(3) OP_div OP_const1s(-2) \
+ OP_eq ASSERT_TOS_NON0 \
+/* Modulo is unsigned. */ \
+OP_const1s(-6) OP_const1s(-4) OP_mod OP_const1s(-6) \
+ OP_eq ASSERT_TOS_NON0 \
+OP_const1s(-6) OP_lit4 OP_mod OP_lit2 OP_eq ASSERT_TOS_NON0 \
+OP_lit6 OP_const1s(-4) OP_mod OP_lit6 OP_eq ASSERT_TOS_NON0 \
+/* Signed modulo can be implemented using "over over div mul minus". */\
+OP_const1s(-6) OP_const1s(-4) OP_over OP_over OP_div OP_mul OP_minus \
+ OP_const1s(-2) OP_eq ASSERT_TOS_NON0 \
+OP_const1s(-7) OP_lit3 OP_over OP_over OP_div OP_mul OP_minus \
+ OP_const1s(-1) OP_eq ASSERT_TOS_NON0 \
+OP_lit7 OP_const1s(-3) OP_over OP_over OP_div OP_mul OP_minus \
+ OP_lit1 OP_eq ASSERT_TOS_NON0 \
+OP_lit16 OP_lit31 OP_plus_uconst(1) OP_mul OP_const2u(512) \
+ OP_eq ASSERT_TOS_NON0 \
+OP_lit5 OP_not OP_lit31 OP_and OP_lit26 OP_eq ASSERT_TOS_NON0 \
+OP_lit12 OP_lit31 OP_plus OP_const1u(43) OP_eq ASSERT_TOS_NON0 \
+OP_const1s(-6) OP_lit2 OP_plus OP_const1s(-4) OP_eq ASSERT_TOS_NON0 \
+OP_const1s(-6) OP_plus_uconst(3) OP_const1s(-3) OP_eq ASSERT_TOS_NON0 \
+OP_lit16 OP_lit4 OP_shl OP_const2u(256) OP_eq ASSERT_TOS_NON0 \
+OP_lit16 OP_lit3 OP_shr OP_lit2 OP_eq ASSERT_TOS_NON0 \
+OP_const1s(-16) OP_lit3 OP_shra OP_const1s(-2) OP_eq ASSERT_TOS_NON0 \
+OP_lit3 OP_lit6 OP_xor OP_lit5 OP_eq ASSERT_TOS_NON0 \
+OP_lit3 OP_lit6 OP_le ASSERT_TOS_NON0 \
+OP_lit3 OP_lit3 OP_le ASSERT_TOS_NON0 \
+OP_lit6 OP_lit3 OP_le ASSERT_TOS_0 \
+OP_lit3 OP_lit6 OP_lt ASSERT_TOS_NON0 \
+OP_lit3 OP_lit3 OP_lt ASSERT_TOS_0 \
+OP_lit6 OP_lit3 OP_lt ASSERT_TOS_0 \
+OP_lit3 OP_lit6 OP_ge ASSERT_TOS_0 \
+OP_lit3 OP_lit3 OP_ge ASSERT_TOS_NON0 \
+OP_lit6 OP_lit3 OP_ge ASSERT_TOS_NON0 \
+OP_lit3 OP_lit6 OP_gt ASSERT_TOS_0 \
+OP_lit3 OP_lit3 OP_gt ASSERT_TOS_0 \
+OP_lit6 OP_lit3 OP_gt ASSERT_TOS_NON0 \
+OP_const1s(-6) OP_lit1 OP_shr OP_lit0 OP_gt ASSERT_TOS_NON0 \
+OP_const1s(-6) OP_lit1 OP_shra OP_lit0 OP_lt ASSERT_TOS_NON0
+
+#define CFI_ESCAPE_VAL_2(VALUES...) #VALUES
+#define CFI_ESCAPE_VAL_1(VALUES...) CFI_ESCAPE_VAL_2(VALUES)
+#define CFI_ESCAPE_VAL(VALUES...) CFI_ESCAPE_VAL_1(VALUES)
+#define CFI_ESCAPE do { } while (0)
+#define CFI_ARCH_PROGRAM OP_nop_termination
+#ifdef __GCC_HAVE_DWARF2_CFI_ASM
+#if defined (__x86_64__)
+#undef CFI_ESCAPE
+#undef CFI_ARCH_PROGRAM
+#define CFI_ARCH_PROGRAM CFI_PROGRAM OP_lit8 OP_minus OP_nop_termination
+unsigned char cfi_arch_program[] = { CFI_ARCH_PROGRAM };
+extern char verify_it[sizeof (cfi_arch_program) - 0x80 < 0x3f80 ? 1 : -1];
+/* DW_CFA_expression %rip, uleb128(l2-l1), l1: program DW_OP_lit8 DW_OP_minus DW_OP_nop l2: */
+#define CFI_ESCAPE \
+ asm volatile (".cfi_escape 0x10, 0x10, (%P0&0x7f)+0x80, %P0>>7, " \
+ CFI_ESCAPE_VAL (CFI_ARCH_PROGRAM) \
+ : : "i" (sizeof (cfi_arch_program)))
+#elif defined (__i386__)
+#undef CFI_ESCAPE
+#undef CFI_ARCH_PROGRAM
+#define CFI_ARCH_PROGRAM CFI_PROGRAM OP_lit4 OP_minus OP_nop_termination
+unsigned char cfi_arch_program[] = { CFI_ARCH_PROGRAM };
+extern char verify_it[sizeof (cfi_arch_program) - 0x80 < 0x3f80 ? 1 : -1];
+/* DW_CFA_expression %eip, uleb128(l2-l1), l1: program DW_OP_lit4 DW_OP_minus DW_OP_nop l2: */
+#define CFI_ESCAPE \
+ asm volatile (".cfi_escape 0x10, 8, (%P0&0x7f)+0x80, %P0>>7, " \
+ CFI_ESCAPE_VAL (CFI_ARCH_PROGRAM) \
+ : : "i" (sizeof (cfi_arch_program)))
+#endif
+#endif
+static _Unwind_Reason_Code
+force_unwind_stop (int version, _Unwind_Action actions,
+ _Unwind_Exception_Class exc_class,
+ struct _Unwind_Exception *exc_obj,
+ struct _Unwind_Context *context,
+ void *stop_parameter)
+{
+ if (actions & _UA_END_OF_STACK)
+ abort ();
+ return _URC_NO_REASON;
+}
+
+static void force_unwind ()
+{
+ struct _Unwind_Exception *exc = malloc (sizeof (*exc));
+ memset (&exc->exception_class, 0, sizeof (exc->exception_class));
+ exc->exception_cleanup = 0;
+
+#ifndef __USING_SJLJ_EXCEPTIONS__
+ _Unwind_ForcedUnwind (exc, force_unwind_stop, 0);
+#else
+ _Unwind_SjLj_ForcedUnwind (exc, force_unwind_stop, 0);
+#endif
+
+ abort ();
+}
+
+static void handler (void *p __attribute__((unused)))
+{
+ exit (0);
+}
+
+__attribute__((noinline)) static void callme ()
+{
+ CFI_ESCAPE;
+ force_unwind ();
+}
+
+__attribute__((noinline)) static void doit ()
+{
+ char dummy __attribute__((cleanup (handler)));
+ callme ();
+}
+
+int main()
+{
+ doit ();
+ abort ();
+}
diff --git a/tests/dwflsyms.c b/tests/dwflsyms.c
index cae3fbea..49ac3346 100644
--- a/tests/dwflsyms.c
+++ b/tests/dwflsyms.c
@@ -69,35 +69,137 @@ gelf_bind (GElf_Sym *sym)
}
static int
+gelf_bind_order (GElf_Sym *sym)
+{
+ switch (GELF_ST_BIND (sym->st_info))
+ {
+ case STB_LOCAL:
+ return 1;
+ case STB_WEAK:
+ return 2;
+ case STB_GLOBAL:
+ return 3;
+ default:
+ return 0;
+ }
+}
+
+static const char *
+elf_section_name (Elf *elf, GElf_Word shndx)
+{
+ GElf_Ehdr ehdr;
+ GElf_Shdr shdr;
+ Elf_Scn *scn = elf_getscn (elf, shndx);
+ gelf_getshdr (scn, &shdr);
+ gelf_getehdr (elf, &ehdr);
+ return elf_strptr (elf, ehdr.e_shstrndx, shdr.sh_name);
+}
+
+bool
+addr_in_section (Elf *elf, GElf_Word shndx, GElf_Addr addr)
+{
+ GElf_Shdr shdr;
+ Elf_Scn *scn = elf_getscn (elf, shndx);
+ gelf_getshdr (scn, &shdr);
+ return addr >= shdr.sh_addr && addr < shdr.sh_addr + shdr.sh_size;
+}
+
+static int
list_syms (struct Dwfl_Module *mod,
- void **user __attribute__ ((unused)),
- const char *mod_name __attribute__ ((unused)),
+ void **user __attribute__ ((unused)), const char *mod_name,
Dwarf_Addr low_addr __attribute__ ((unused)),
void *arg __attribute__ ((unused)))
{
int syms = dwfl_module_getsymtab (mod);
- assert (syms >= 0);
+ if (syms < 0)
+ {
+ printf ("%s: %s\n", mod_name, dwfl_errmsg (-1));
+ return DWARF_CB_OK;
+ }
for (int ndx = 0; ndx < syms; ndx++)
{
GElf_Sym sym;
GElf_Word shndxp;
+ Elf *elf;
+ Dwarf_Addr bias;
const char *name = dwfl_module_getsym (mod, ndx, &sym, &shndxp);
- printf("%4d: %s\t%s\t%s (%" PRIu64 ") %#" PRIx64 "\n",
+
+ printf("%4d: %s\t%s\t%s (%" PRIu64 ") %#" PRIx64,
ndx, gelf_type (&sym), gelf_bind (&sym), name,
sym.st_size, sym.st_value);
+ /* The info variant doesn't adjust st_value but returns the (possible)
+ adjusted value separately. */
+ GElf_Addr value;
+ GElf_Sym isym;
+ name = dwfl_module_getsym_info (mod, ndx, &isym, &value, &shndxp,
+ &elf, &bias);
+
+ GElf_Ehdr ehdr;
+ gelf_getehdr (elf, &ehdr);
+
+ // getsym st_values might or might not be adjusted depending on section.
+ // For ET_REL the adjustment is section relative.
+ assert (sym.st_value == isym.st_value
+ || sym.st_value == isym.st_value + bias
+ || ehdr.e_type == ET_REL);
+
/* And the reverse, which works for function symbols at least.
Note this only works because the st.value is adjusted by
dwfl_module_getsym (). */
if (GELF_ST_TYPE (sym.st_info) == STT_FUNC && shndxp != SHN_UNDEF)
{
- GElf_Addr addr = sym.st_value;
+ /* Make sure the adjusted value really falls in the elf section. */
+ assert (addr_in_section (elf, shndxp, sym.st_value - bias));
+
+ GElf_Addr addr = value;
GElf_Sym asym;
GElf_Word ashndxp;
- const char *aname = dwfl_module_addrsym (mod, addr, &asym, &ashndxp);
- assert (strcmp (name, aname) == 0);
+ Elf *aelf;
+ Dwarf_Addr abias;
+ GElf_Off off;
+ const char *aname = dwfl_module_addrinfo (mod, addr, &off, &asym,
+ &ashndxp, &aelf, &abias);
+
+ /* Make sure the adjusted value really falls in the elf section. */
+ assert (addr_in_section (aelf, ashndxp, asym.st_value)
+ || ehdr.e_type == ET_REL);
+
+ /* Either they are the same symbol (name), the binding of
+ asym is "stronger" (or equal) to sym or asym is more specific
+ (has a lower address) than sym. */
+ assert ((strcmp (name, aname) == 0
+ || gelf_bind_order (&asym) >= gelf_bind_order (&sym))
+ && value <= sym.st_value);
+
+ addr = sym.st_value;
+ int res = dwfl_module_relocate_address (mod, &addr);
+ assert (res != -1);
+ if (shndxp < SHN_LORESERVE)
+ printf(", rel: %#" PRIx64 " (%s)", addr,
+ elf_section_name (elf, shndxp));
+ else
+ printf(", rel: %#" PRIx64 "", addr);
+
+ /* Print the section of the actual value if different from sym. */
+ if (value != isym.st_value + bias && ehdr.e_type != ET_REL)
+ {
+ GElf_Addr ebias;
+ addr = value;
+ Elf_Scn *scn = dwfl_module_address_section (mod, &addr, &ebias);
+ GElf_Shdr shdr_mem;
+ GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+ Elf *melf = dwfl_module_getelf (mod, &ebias);
+ gelf_getehdr (melf, &ehdr);
+ const char *sname = elf_strptr (melf, ehdr.e_shstrndx,
+ shdr->sh_name);
+ printf (" [%#" PRIx64 ", rel: %#" PRIx64 " (%s)]",
+ value, addr, sname);
+ }
+
}
+ printf ("\n");
}
return DWARF_CB_OK;
diff --git a/tests/funcretval_test.c b/tests/funcretval_test.c
new file mode 100644
index 00000000..7e20f526
--- /dev/null
+++ b/tests/funcretval_test.c
@@ -0,0 +1,828 @@
+signed char fun_char (void) { return 5; }
+short fun_short (void) { return 6; }
+int fun_int (void) { return 7; }
+void *fun_ptr (void) { return &fun_ptr; }
+int fun_iptr (void) { return 8; }
+long fun_long (void) { return 9; }
+__int128 fun_int128 (void) { return 10; }
+
+typedef struct { int i[10]; } large_struct1_t;
+large_struct1_t fun_large_struct1 (void) {
+ large_struct1_t ret = { { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 } };
+ return ret;
+}
+
+typedef struct { int i1; int i2; int i3; int i4; int i5;
+ int i6; int i7; int i8; int i9; int i10; } large_struct2_t;
+large_struct2_t fun_large_struct2 (void) {
+ large_struct2_t ret = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
+ return ret;
+}
+
+float fun_float (void) { return 1.5; }
+float _Complex fun_float_complex (void) { return 1.5 + 2.5i; }
+
+double fun_double (void) { return 2.5; }
+double _Complex fun_double_complex (void) { return 2.5 + 3.5i; }
+
+long double fun_long_double (void) { return 3.5; }
+long double _Complex fun_long_double_complex (void) { return 4.5 + 5.5i; }
+
+#ifdef FLOAT128
+__float128 fun_float128 (void) { return 3.5; }
+#endif
+
+// 8 byte vectors.
+
+typedef signed char __attribute__ ((vector_size (8))) vec_char_8_t;
+vec_char_8_t fun_vec_char_8 (void) {
+ vec_char_8_t ret = { 1, 2, 3, 4, 5, 6, 7, 8 };
+ return ret;
+}
+
+typedef short __attribute__ ((vector_size (8))) vec_short_8_t;
+vec_short_8_t fun_vec_short_8 (void) {
+ vec_short_8_t ret = { 2, 3, 4, 5 };
+ return ret;
+}
+
+typedef int __attribute__ ((vector_size (8))) vec_int_8_t;
+vec_int_8_t fun_vec_int_8 (void) {
+ vec_int_8_t ret = { 3, 4 };
+ return ret;
+}
+
+typedef long __attribute__ ((vector_size (8))) vec_long_8_t;
+vec_long_8_t fun_vec_long_8 (void) {
+ vec_long_8_t ret = { 5 };
+ return ret;
+}
+
+typedef float __attribute__ ((vector_size (8))) vec_float_8_t;
+vec_float_8_t fun_vec_float_8 (void) {
+ vec_float_8_t ret = { 1.5, 2.5 };
+ return ret;
+}
+
+typedef double __attribute__ ((vector_size (8))) vec_double_8_t;
+#ifndef AARCH64_BUG_1032854
+// https://bugzilla.redhat.com/show_bug.cgi?id=1032854
+vec_double_8_t fun_vec_double_8 (void) {
+ vec_double_8_t ret = { 3.5 };
+ return ret;
+}
+#endif
+
+// 16 byte vectors.
+
+typedef signed char __attribute__ ((vector_size (16))) vec_char_16_t;
+vec_char_16_t fun_vec_char_16 (void) {
+ vec_char_16_t ret = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
+ return ret;
+}
+
+typedef short __attribute__ ((vector_size (16))) vec_short_16_t;
+vec_short_16_t fun_vec_short_16 (void) {
+ vec_short_16_t ret = { 2, 3, 4, 5, 6, 7, 8 };
+ return ret;
+}
+
+typedef int __attribute__ ((vector_size (16))) vec_int_16_t;
+vec_int_16_t fun_vec_int_16 (void) {
+ vec_int_16_t ret = { 2, 3, 4 };
+ return ret;
+}
+
+typedef long __attribute__ ((vector_size (16))) vec_long_16_t;
+vec_long_16_t fun_vec_long_16 (void) {
+ vec_long_16_t ret = { 3, 4 };
+ return ret;
+}
+
+typedef __int128 __attribute__ ((vector_size (16))) vec_int128_16_t;
+vec_int128_16_t fun_vec_int128_16 (void) {
+ vec_int128_16_t ret = { 999 };
+ return ret;
+}
+
+typedef float __attribute__ ((vector_size (16))) vec_float_16_t;
+vec_float_16_t fun_vec_float_16 (void) {
+ vec_float_16_t ret = { 1.5, 2.5, 3.5, 4.5 };
+ return ret;
+}
+
+typedef double __attribute__ ((vector_size (16))) vec_double_16_t;
+vec_double_16_t fun_vec_double_16 (void) {
+ vec_double_16_t ret = { 2.5, 5 };
+ return ret;
+}
+
+#ifdef FLOAT128
+typedef __float128 __attribute__ ((vector_size (16))) vec_float128_16_t;
+vec_float128_16_t fun_vec_float128_16 (void) {
+ vec_float128_16_t ret = { 7.5 };
+ return ret;
+}
+#endif
+
+// Homogeneous floating-point aggregates.
+
+typedef struct { float f; } hfa1_float_t;
+hfa1_float_t fun_hfa1_float (void) {
+ hfa1_float_t ret = { 1.5 };
+ return ret;
+}
+
+typedef struct { double f; } hfa1_double_t;
+hfa1_double_t fun_hfa1_double (void) {
+ hfa1_double_t ret = { 3.0 };
+ return ret;
+}
+
+typedef struct { long double f; } hfa1_long_double_t;
+hfa1_long_double_t fun_hfa1_long_double (void) {
+ hfa1_long_double_t ret = { 3.0 };
+ return ret;
+}
+
+typedef struct { float f[1]; } hfa1_float_a_t;
+hfa1_float_a_t fun_hfa1_float_a (void) {
+ hfa1_float_a_t ret = { { 1.5 } };
+ return ret;
+}
+
+typedef struct { double f[1]; } hfa1_double_a_t;
+hfa1_double_a_t fun_hfa1_double_a (void) {
+ hfa1_double_a_t ret = { { 3.0 } };
+ return ret;
+}
+
+typedef struct { long double f[1]; } hfa1_long_double_a_t;
+hfa1_long_double_a_t fun_hfa1_long_double_a (void) {
+ hfa1_long_double_a_t ret = { { 3.0 } };
+ return ret;
+}
+
+typedef struct { float f; float g; } hfa2_float_t;
+hfa2_float_t fun_hfa2_float (void) {
+ hfa2_float_t ret = { 1.5, 3.0 };
+ return ret;
+}
+
+typedef struct { double f; double g; } hfa2_double_t;
+hfa2_double_t fun_hfa2_double (void) {
+ hfa2_double_t ret = { 3.0, 4.5 };
+ return ret;
+}
+
+typedef struct { long double f; long double g; } hfa2_long_double_t;
+hfa2_long_double_t fun_hfa2_long_double (void) {
+ hfa2_long_double_t ret = { 3.0, 4.5 };
+ return ret;
+}
+
+typedef struct { float f[2]; } hfa2_float_a_t;
+hfa2_float_a_t fun_hfa2_float_a (void) {
+ hfa2_float_a_t ret = { { 2.5, 3.5 } };
+ return ret;
+}
+
+typedef struct { double f[2]; } hfa2_double_a_t;
+hfa2_double_a_t fun_hfa2_double_a (void) {
+ hfa2_double_a_t ret = { { 3.0, 3.5 } };
+ return ret;
+}
+
+typedef struct { long double f[2]; } hfa2_long_double_a_t;
+hfa2_long_double_a_t fun_hfa2_long_double_a (void) {
+ hfa2_long_double_a_t ret = { { 3.0, 4.0 } };
+ return ret;
+}
+
+typedef struct { float f; float g; float h; } hfa3_float_t;
+hfa3_float_t fun_hfa3_float (void) {
+ hfa3_float_t ret = { 1.5, 3.0, 4.5 };
+ return ret;
+}
+
+typedef struct { double f; double g; double h; } hfa3_double_t;
+hfa3_double_t fun_hfa3_double (void) {
+ hfa3_double_t ret = { 3.0, 4.5, 9.5 };
+ return ret;
+}
+
+typedef struct { long double f; long double g; long double h; } hfa3_long_double_t;
+hfa3_long_double_t fun_hfa3_long_double (void) {
+ hfa3_long_double_t ret = { 3.0, 4.5, 9.5 };
+ return ret;
+}
+
+typedef struct { float f[3]; } hfa3_float_a_t;
+hfa3_float_a_t fun_hfa3_float_a (void) {
+ hfa3_float_a_t ret = { { 3.5, 4.5, 5.5 } };
+ return ret;
+}
+
+typedef struct { double f[3]; } hfa3_double_a_t;
+hfa3_double_a_t fun_hfa3_double_a (void) {
+ hfa3_double_a_t ret = { { 3.0, 3.5, 4.0 } };
+ return ret;
+}
+
+typedef struct { long double f[3]; } hfa3_long_double_a_t;
+hfa3_long_double_a_t fun_hfa3_long_double_a (void) {
+ hfa3_long_double_a_t ret = { { 3.0, 4.0, 5.0 } };
+ return ret;
+}
+
+typedef struct { float f; float g; float h; float i; } hfa4_float_t;
+hfa4_float_t fun_hfa4_float (void) {
+ hfa4_float_t ret = { 1.5, 3.5, 4.5, 9.5 };
+ return ret;
+}
+
+typedef struct { double f; double g; double h; double i; } hfa4_double_t;
+hfa4_double_t fun_hfa4_double (void) {
+ hfa4_double_t ret = { 3.5, 4.5, 9.5, 1.5 };
+ return ret;
+}
+
+typedef struct { long double f; long double g; long double h; long double i; } hfa4_long_double_t;
+hfa4_long_double_t fun_hfa4_long_double (void) {
+ hfa4_long_double_t ret = { 3.5, 4.5, 9.5, 1.5 };
+ return ret;
+}
+
+typedef struct { float f[4]; } hfa4_float_a_t;
+hfa4_float_a_t fun_hfa4_float_a (void) {
+ hfa4_float_a_t ret = { { 4.5, 5.5, 6.5, 7.5 } };
+ return ret;
+}
+
+typedef struct { double f[4]; } hfa4_double_a_t;
+hfa4_double_a_t fun_hfa4_double_a (void) {
+ hfa4_double_a_t ret = { { 3.0, 4.5, 5.0, 5.5 } };
+ return ret;
+}
+
+typedef struct { long double f[4]; } hfa4_long_double_a_t;
+hfa4_long_double_a_t fun_hfa4_long_double_a (void) {
+ hfa4_long_double_a_t ret = { { 3.0, 4.0, 5.0, 6.0 } };
+ return ret;
+}
+
+typedef struct { float f; float g; float h; float i; float j; } nfa5_float_t;
+nfa5_float_t fun_nfa5_float (void) {
+ nfa5_float_t ret = { 1.5, 3.5, 4.5, 9.5, 10.5 };
+ return ret;
+}
+
+typedef struct { double f; double g; double h; double i; double j; } nfa5_double_t;
+nfa5_double_t fun_nfa5_double (void) {
+ nfa5_double_t ret = { 3.5, 4.5, 9.5, 1.5, 2.5 };
+ return ret;
+}
+
+typedef struct { long double f; long double g; long double h; long double i; long double j; } nfa5_long_double_t;
+nfa5_long_double_t fun_nfa5_long_double (void) {
+ nfa5_long_double_t ret = { 3.5, 4.5, 9.5, 1.5, 2.5 };
+ return ret;
+}
+
+typedef struct { float f[5]; } nfa5_float_a_t;
+nfa5_float_a_t fun_nfa5_float_a (void) {
+ nfa5_float_a_t ret = { { 4.5, 5.5, 6.5, 7.5, 9.5 } };
+ return ret;
+}
+
+typedef struct { double f[5]; } nfa5_double_a_t;
+nfa5_double_a_t fun_nfa5_double_a (void) {
+ nfa5_double_a_t ret = { { 3.0, 4.5, 5.0, 5.5, 6.5 } };
+ return ret;
+}
+
+typedef struct { long double f[5]; } nfa5_long_double_a_t;
+nfa5_long_double_a_t fun_nfa5_long_double_a (void) {
+ nfa5_long_double_a_t ret = { { 3.0, 4.0, 5.0, 6.0, 7.0 } };
+ return ret;
+}
+
+#ifdef FLOAT128
+typedef struct { __float128 f; } hfa1_float128_t;
+hfa1_float128_t fun_hfa1_float128 (void) {
+ hfa1_float128_t ret = { 4.5 };
+ return ret;
+}
+
+typedef struct { __float128 f; __float128 g; } hfa2_float128_t;
+hfa2_float128_t fun_hfa2_float128 (void) {
+ hfa2_float128_t ret = { 4.5, 9.5 };
+ return ret;
+}
+
+typedef struct { __float128 f; __float128 g; __float128 h; } hfa3_float128_t;
+hfa3_float128_t fun_hfa3_float128 (void) {
+ hfa3_float128_t ret = { 4.5, 9.5, 12.5 };
+ return ret;
+}
+
+typedef struct { __float128 f; __float128 g; __float128 h; __float128 i; } hfa4_float128_t;
+hfa4_float128_t fun_hfa4_float128 (void) {
+ hfa4_float128_t ret = { 4.5, 9.5, 3.5, 1.5 };
+ return ret;
+}
+#endif
+
+// Homogeneous vector aggregates of 1 element.
+
+typedef struct { vec_char_8_t a; } hva1_vec_char_8_t;
+hva1_vec_char_8_t fun_hva1_vec_char_8 (void) {
+ hva1_vec_char_8_t ret = { { 1, 2, 3, 4, 5, 6, 7, 8 } };
+ return ret;
+}
+
+typedef struct { vec_short_8_t a; } hva1_vec_short_8_t;
+hva1_vec_short_8_t fun_hva1_vec_short_8 (void) {
+ hva1_vec_short_8_t ret = { { 2, 3, 4, 5 } };
+ return ret;
+}
+
+typedef struct { vec_int_8_t a; } hva1_vec_int_8_t;
+hva1_vec_int_8_t fun_hva1_vec_int_8 (void) {
+ hva1_vec_int_8_t ret = { { 3, 4 } };
+ return ret;
+}
+
+typedef struct { vec_long_8_t a; } hva1_vec_long_8_t;
+hva1_vec_long_8_t fun_hva1_vec_long_8 (void) {
+ hva1_vec_long_8_t ret = { { 5 } };
+ return ret;
+}
+
+typedef struct { vec_float_8_t a; } hva1_vec_float_8_t;
+hva1_vec_float_8_t fun_hva1_vec_float_8 (void) {
+ hva1_vec_float_8_t ret = { { 1.5, 2.5 } };
+ return ret;
+}
+
+typedef struct { vec_double_8_t a; } hva1_vec_double_8_t;
+hva1_vec_double_8_t fun_hva1_vec_double_8 (void) {
+ hva1_vec_double_8_t ret = { { 3.5 } };
+ return ret;
+}
+
+typedef struct { vec_char_16_t a; } hva1_vec_char_16_t;
+hva1_vec_char_16_t fun_hva1_vec_char_16_t (void) {
+ hva1_vec_char_16_t ret = { { 1, 2, 3, 4, 5, 6, 7, 8,
+ 9, 10, 11, 12, 13, 14, 15, 16 } };
+ return ret;
+}
+
+typedef struct { vec_short_16_t a; } hva1_vec_short_16_t;
+hva1_vec_short_16_t fun_hva1_vec_short_16_t (void) {
+ hva1_vec_short_16_t ret = { { 2, 3, 4, 5, 6, 7, 8, 9 } };
+ return ret;
+}
+
+typedef struct { vec_int_16_t a; } hva1_vec_int_16_t;
+hva1_vec_int_16_t fun_hva1_vec_int_16_t (void) {
+ hva1_vec_int_16_t ret = { { 3, 4, 5, 6 } };
+ return ret;
+}
+
+typedef struct { vec_long_16_t a; } hva1_vec_long_16_t;
+hva1_vec_long_16_t fun_hva1_vec_long_16_t (void) {
+ hva1_vec_long_16_t ret = { { 4, 5 } };
+ return ret;
+}
+
+typedef struct { vec_int128_16_t a; } hva1_vec_int128_16_t;
+hva1_vec_int128_16_t fun_hva1_vec_int128_16_t (void) {
+ hva1_vec_int128_16_t ret = { { 6 } };
+ return ret;
+}
+
+typedef struct { vec_float_16_t a; } hva1_vec_float_16_t;
+hva1_vec_float_16_t fun_hva1_vec_float_16_t (void) {
+ hva1_vec_float_16_t ret = { { 1.5, 2.5, 3.5, 4.5 } };
+ return ret;
+}
+
+typedef struct { vec_double_16_t a; } hva1_vec_double_16_t;
+hva1_vec_double_16_t fun_hva1_vec_double_16_t (void) {
+ hva1_vec_double_16_t ret = { { 2.5, 3.5 } };
+ return ret;
+}
+
+#ifdef FLOAT128
+typedef struct { vec_float128_16_t a; } hva1_vec_float128_16_t;
+hva1_vec_float128_16_t fun_hva1_vec_float128_16_t (void) {
+ hva1_vec_float128_16_t ret = { { 4.5 } };
+ return ret;
+}
+#endif
+
+// Homogeneous vector aggregates of 2 elements.
+
+typedef struct { vec_char_8_t a; vec_char_8_t b; } hva2_vec_char_8_t;
+hva2_vec_char_8_t fun_hva2_vec_char_8 (void) {
+ hva2_vec_char_8_t ret = { { 1, 2, 3, 4, 5, 6, 7, 8 },
+ { 2, 3, 4, 5, 6, 7, 8, 9 } };
+ return ret;
+}
+
+typedef struct { vec_short_8_t a; vec_short_8_t b; } hva2_vec_short_8_t;
+hva2_vec_short_8_t fun_hva2_vec_short_8 (void) {
+ hva2_vec_short_8_t ret = { { 2, 3, 4, 5 },
+ { 3, 4, 5, 6 } };
+ return ret;
+}
+
+typedef struct { vec_int_8_t a; vec_int_8_t b; } hva2_vec_int_8_t;
+hva2_vec_int_8_t fun_hva2_vec_int_8 (void) {
+ hva2_vec_int_8_t ret = { { 3, 4 },
+ { 4, 5 } };
+ return ret;
+}
+
+typedef struct { vec_long_8_t a; vec_long_8_t b; } hva2_vec_long_8_t;
+hva2_vec_long_8_t fun_hva2_vec_long_8 (void) {
+ hva2_vec_long_8_t ret = { { 5 },
+ { 6 } };
+ return ret;
+}
+
+typedef struct { vec_float_8_t a; vec_float_8_t b; } hva2_vec_float_8_t;
+hva2_vec_float_8_t fun_hva2_vec_float_8 (void) {
+ hva2_vec_float_8_t ret = { { 1.5, 2.5 },
+ { 2.5, 3.5 } };
+ return ret;
+}
+
+typedef struct { vec_double_8_t a; vec_double_8_t b; } hva2_vec_double_8_t;
+hva2_vec_double_8_t fun_hva2_vec_double_8 (void) {
+ hva2_vec_double_8_t ret = { { 3.5 },
+ { 4.5 } };
+ return ret;
+}
+
+typedef struct { vec_char_16_t a; vec_char_16_t b; } hva2_vec_char_16_t;
+hva2_vec_char_16_t fun_hva2_vec_char_16_t (void) {
+ hva2_vec_char_16_t ret = { { 1, 2, 3, 4, 5, 6, 7, 8,
+ 9, 10, 11, 12, 13, 14, 15, 16 },
+ { 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17 } };
+ return ret;
+}
+
+typedef struct { vec_short_16_t a; vec_short_16_t b; } hva2_vec_short_16_t;
+hva2_vec_short_16_t fun_hva2_vec_short_16_t (void) {
+ hva2_vec_short_16_t ret = { { 2, 3, 4, 5, 6, 7, 8, 9 },
+ { 3, 4, 5, 6, 7, 8, 9, 10 } };
+ return ret;
+}
+
+typedef struct { vec_int_16_t a; vec_int_16_t b; } hva2_vec_int_16_t;
+hva2_vec_int_16_t fun_hva2_vec_int_16_t (void) {
+ hva2_vec_int_16_t ret = { { 3, 4, 5, 6 },
+ { 4, 5, 6, 7 } };
+ return ret;
+}
+
+typedef struct { vec_long_16_t a; vec_long_16_t b; } hva2_vec_long_16_t;
+hva2_vec_long_16_t fun_hva2_vec_long_16_t (void) {
+ hva2_vec_long_16_t ret = { { 4, 5 },
+ { 5, 6 } };
+ return ret;
+}
+
+typedef struct { vec_int128_16_t a; vec_int128_16_t b; } hva2_vec_int128_16_t;
+hva2_vec_int128_16_t fun_hva2_vec_int128_16_t (void) {
+ hva2_vec_int128_16_t ret = { { 6 },
+ { 7 } };
+ return ret;
+}
+
+typedef struct { vec_float_16_t a; vec_float_16_t b; } hva2_vec_float_16_t;
+hva2_vec_float_16_t fun_hva2_vec_float_16_t (void) {
+ hva2_vec_float_16_t ret = { { 1.5, 2.5, 3.5, 4.5 },
+ { 2.5, 3.5, 4.5, 5.5 } };
+ return ret;
+}
+
+typedef struct { vec_double_16_t a; vec_double_16_t b; } hva2_vec_double_16_t;
+hva2_vec_double_16_t fun_hva2_vec_double_16_t (void) {
+ hva2_vec_double_16_t ret = { { 2.5, 3.5 },
+ { 3.5, 4.5 } };
+ return ret;
+}
+
+#ifdef FLOAT128
+typedef struct { vec_float128_16_t a; vec_float128_16_t b; } hva2_vec_float128_16_t;
+hva2_vec_float128_16_t fun_hva2_vec_float128_16_t (void) {
+ hva2_vec_float128_16_t ret = { { 4.5 },
+ { 5.5 } };
+ return ret;
+}
+#endif
+
+// Homogeneous vector aggregates of 3 elements.
+
+typedef struct { vec_char_8_t a; vec_char_8_t b; vec_char_8_t c; } hva3_vec_char_8_t;
+hva3_vec_char_8_t fun_hva3_vec_char_8 (void) {
+ hva3_vec_char_8_t ret = { { 1, 2, 3, 4, 5, 6, 7, 8 },
+ { 2, 3, 4, 5, 6, 7, 8, 9 },
+ { 3, 4, 5, 6, 7, 8, 9, 10 } };
+ return ret;
+}
+
+typedef struct { vec_short_8_t a; vec_short_8_t b; vec_short_8_t c; } hva3_vec_short_8_t;
+hva3_vec_short_8_t fun_hva3_vec_short_8 (void) {
+ hva3_vec_short_8_t ret = { { 2, 3, 4, 5 },
+ { 3, 4, 5, 6 },
+ { 4, 5, 6, 7 } };
+ return ret;
+}
+
+typedef struct { vec_int_8_t a; vec_int_8_t b; vec_int_8_t c; } hva3_vec_int_8_t;
+hva3_vec_int_8_t fun_hva3_vec_int_8 (void) {
+ hva3_vec_int_8_t ret = { { 3, 4 },
+ { 4, 5 },
+ { 5, 6 } };
+ return ret;
+}
+
+typedef struct { vec_long_8_t a; vec_long_8_t b; vec_long_8_t c; } hva3_vec_long_8_t;
+hva3_vec_long_8_t fun_hva3_vec_long_8 (void) {
+ hva3_vec_long_8_t ret = { { 5 },
+ { 6 },
+ { 7 } };
+ return ret;
+}
+
+typedef struct { vec_float_8_t a; vec_float_8_t b; vec_float_8_t c; } hva3_vec_float_8_t;
+hva3_vec_float_8_t fun_hva3_vec_float_8 (void) {
+ hva3_vec_float_8_t ret = { { 1.5, 2.5 },
+ { 2.5, 3.5 },
+ { 3.5, 4.5 } };
+ return ret;
+}
+
+typedef struct { vec_double_8_t a; vec_double_8_t b; vec_double_8_t c; } hva3_vec_double_8_t;
+hva3_vec_double_8_t fun_hva3_vec_double_8 (void) {
+ hva3_vec_double_8_t ret = { { 3.5 },
+ { 4.5 },
+ { 5.5 } };
+ return ret;
+}
+
+typedef struct { vec_char_16_t a; vec_char_16_t b; vec_char_16_t c; } hva3_vec_char_16_t;
+hva3_vec_char_16_t fun_hva3_vec_char_16_t (void) {
+ hva3_vec_char_16_t ret = { { 1, 2, 3, 4, 5, 6, 7, 8,
+ 9, 10, 11, 12, 13, 14, 15, 16 },
+ { 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17 },
+ { 3, 4, 5, 6, 7, 8, 9, 10,
+ 11, 12, 13, 14, 15, 16, 17, 18 } };
+ return ret;
+}
+
+typedef struct { vec_short_16_t a; vec_short_16_t b; vec_short_16_t c; } hva3_vec_short_16_t;
+hva3_vec_short_16_t fun_hva3_vec_short_16_t (void) {
+ hva3_vec_short_16_t ret = { { 2, 3, 4, 5, 6, 7, 8, 9 },
+ { 3, 4, 5, 6, 7, 8, 9, 10 },
+ { 4, 5, 6, 7, 8, 9, 10, 11 } };
+ return ret;
+}
+
+typedef struct { vec_int_16_t a; vec_int_16_t b; vec_int_16_t c; } hva3_vec_int_16_t;
+hva3_vec_int_16_t fun_hva3_vec_int_16_t (void) {
+ hva3_vec_int_16_t ret = { { 3, 4, 5, 6 },
+ { 4, 5, 6, 7 },
+ { 5, 6, 7, 8 } };
+ return ret;
+}
+
+typedef struct { vec_long_16_t a; vec_long_16_t b; vec_long_16_t c; } hva3_vec_long_16_t;
+hva3_vec_long_16_t fun_hva3_vec_long_16_t (void) {
+ hva3_vec_long_16_t ret = { { 3, 4 },
+ { 4, 5 },
+ { 5, 6 } };
+ return ret;
+}
+
+typedef struct { vec_int128_16_t a; vec_int128_16_t b; vec_int128_16_t c; } hva3_vec_int128_16_t;
+hva3_vec_int128_16_t fun_hva3_vec_int128_16_t (void) {
+ hva3_vec_int128_16_t ret = { { 6 },
+ { 7 },
+ { 8 } };
+ return ret;
+}
+
+typedef struct { vec_float_16_t a; vec_float_16_t b; vec_float_16_t c; } hva3_vec_float_16_t;
+hva3_vec_float_16_t fun_hva3_vec_float_16_t (void) {
+ hva3_vec_float_16_t ret = { { 1.5, 2.5, 3.5, 4.5 },
+ { 2.5, 3.5, 4.5, 5.5 },
+ { 3.5, 4.5, 5.5, 6.5 } };
+ return ret;
+}
+
+typedef struct { vec_double_16_t a; vec_double_16_t b; vec_double_16_t c; } hva3_vec_double_16_t;
+hva3_vec_double_16_t fun_hva3_vec_double_16_t (void) {
+ hva3_vec_double_16_t ret = { { 2.5, 3.5 },
+ { 3.5, 4.5 },
+ { 4.5, 5.5 } };
+ return ret;
+}
+
+#ifdef FLOAT128
+typedef struct { vec_float128_16_t a; vec_float128_16_t b; vec_float128_16_t c; } hva3_vec_float128_16_t;
+hva3_vec_float128_16_t fun_hva3_vec_float128_16_t (void) {
+ hva3_vec_float128_16_t ret = { { 4.5 },
+ { 5.5 },
+ { 6.5 } };
+ return ret;
+}
+#endif
+
+// Homogeneous vector aggregates of 3 elements.
+
+typedef struct { vec_char_8_t a; vec_char_8_t b; vec_char_8_t c; vec_char_8_t d; } hva4_vec_char_8_t;
+hva4_vec_char_8_t fun_hva4_vec_char_8 (void) {
+ hva4_vec_char_8_t ret = { { 1, 2, 3, 4, 5, 6, 7, 8 },
+ { 2, 3, 4, 5, 6, 7, 8, 9 },
+ { 3, 4, 5, 6, 7, 8, 9, 10 },
+ { 4, 5, 6, 7, 8, 9, 10, 11 } };
+ return ret;
+}
+
+typedef struct { vec_short_8_t a; vec_short_8_t b; vec_short_8_t c; vec_short_8_t d; } hva4_vec_short_8_t;
+hva4_vec_short_8_t fun_hva4_vec_short_8 (void) {
+ hva4_vec_short_8_t ret = { { 2, 3, 4, 5 },
+ { 3, 4, 5, 6 },
+ { 4, 5, 6, 7 },
+ { 5, 6, 7, 8 } };
+ return ret;
+}
+
+typedef struct { vec_int_8_t a; vec_int_8_t b; vec_int_8_t c; vec_int_8_t d; } hva4_vec_int_8_t;
+hva4_vec_int_8_t fun_hva4_vec_int_8 (void) {
+ hva4_vec_int_8_t ret = { { 3, 4 },
+ { 4, 5 },
+ { 5, 6 },
+ { 6, 7 } };
+ return ret;
+}
+
+typedef struct { vec_long_8_t a; vec_long_8_t b; vec_long_8_t c; vec_long_8_t d; } hva4_vec_long_8_t;
+hva4_vec_long_8_t fun_hva4_vec_long_8 (void) {
+ hva4_vec_long_8_t ret = { { 5 },
+ { 6 },
+ { 7 },
+ { 8 } };
+ return ret;
+}
+
+typedef struct { vec_float_8_t a; vec_float_8_t b; vec_float_8_t c; vec_float_8_t d; } hva4_vec_float_8_t;
+hva4_vec_float_8_t fun_hva4_vec_float_8 (void) {
+ hva4_vec_float_8_t ret = { { 1.5, 2.5 },
+ { 2.5, 3.5 },
+ { 3.5, 4.5 },
+ { 4.5, 5.5 } };
+ return ret;
+}
+
+typedef struct { vec_double_8_t a; vec_double_8_t b; vec_double_8_t c; vec_double_8_t d; } hva4_vec_double_8_t;
+hva4_vec_double_8_t fun_hva4_vec_double_8 (void) {
+ hva4_vec_double_8_t ret = { { 3.5 },
+ { 4.5 },
+ { 5.5 },
+ { 6.5 } };
+ return ret;
+}
+
+typedef struct { vec_char_16_t a; vec_char_16_t b; vec_char_16_t c; vec_char_16_t d; } hva4_vec_char_16_t;
+hva4_vec_char_16_t fun_hva4_vec_char_16_t (void) {
+ hva4_vec_char_16_t ret = { { 1, 2, 3, 4, 5, 6, 7, 8,
+ 9, 10, 11, 12, 13, 14, 15, 16 },
+ { 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17 },
+ { 3, 4, 5, 6, 7, 8, 9, 10,
+ 11, 12, 13, 14, 15, 16, 17, 18 },
+ { 4, 5, 6, 7, 8, 9, 10, 11,
+ 12, 13, 14, 15, 16, 17, 18, 19 } };
+ return ret;
+}
+
+typedef struct { vec_short_16_t a; vec_short_16_t b; vec_short_16_t c; vec_short_16_t d; } hva4_vec_short_16_t;
+hva4_vec_short_16_t fun_hva4_vec_short_16_t (void) {
+ hva4_vec_short_16_t ret = { { 2, 3, 4, 5, 6, 7, 8, 9 },
+ { 3, 4, 5, 6, 7, 8, 9, 10 },
+ { 4, 5, 6, 7, 8, 9, 10, 11 },
+ { 5, 6, 7, 8, 9, 10, 11, 12 } };
+ return ret;
+}
+
+typedef struct { vec_int_16_t a; vec_int_16_t b; vec_int_16_t c; vec_int_16_t d; } hva4_vec_int_16_t;
+hva4_vec_int_16_t fun_hva4_vec_int_16_t (void) {
+ hva4_vec_int_16_t ret = { { 3, 4, 5, 6 },
+ { 4, 5, 6, 7 },
+ { 5, 6, 7, 8 },
+ { 6, 7, 8, 9 } };
+ return ret;
+}
+
+typedef struct { vec_long_16_t a; vec_long_16_t b; vec_long_16_t c; vec_long_16_t d; } hva4_vec_long_16_t;
+hva4_vec_long_16_t fun_hva4_vec_long_16_t (void) {
+ hva4_vec_long_16_t ret = { { 3, 4 },
+ { 4, 5 },
+ { 5, 6 },
+ { 6, 7 } };
+ return ret;
+}
+
+typedef struct { vec_int128_16_t a; vec_int128_16_t b; vec_int128_16_t c; vec_int128_16_t d; } hva4_vec_int128_16_t;
+hva4_vec_int128_16_t fun_hva4_vec_int128_16_t (void) {
+ hva4_vec_int128_16_t ret = { { 6 },
+ { 7 },
+ { 8 },
+ { 9 } };
+ return ret;
+}
+
+typedef struct { vec_float_16_t a; vec_float_16_t b; vec_float_16_t c; vec_float_16_t d; } hva4_vec_float_16_t;
+hva4_vec_float_16_t fun_hva4_vec_float_16_t (void) {
+ hva4_vec_float_16_t ret = { { 1.5, 2.5, 3.5, 4.5 },
+ { 2.5, 3.5, 4.5, 5.5 },
+ { 3.5, 4.5, 5.5, 6.5 },
+ { 4.5, 5.5, 6.5, 7.5 } };
+ return ret;
+}
+
+typedef struct { vec_double_16_t a; vec_double_16_t b; vec_double_16_t c; vec_double_16_t d; } hva4_vec_double_16_t;
+hva4_vec_double_16_t fun_hva4_vec_double_16_t (void) {
+ hva4_vec_double_16_t ret = { { 2.5, 3.5 },
+ { 3.5, 4.5 },
+ { 4.5, 5.5 },
+ { 5.5, 6.5 } };
+ return ret;
+}
+
+#ifdef FLOAT128
+typedef struct { vec_float128_16_t a; vec_float128_16_t b; vec_float128_16_t c; vec_float128_16_t d; } hva4_vec_float128_16_t;
+hva4_vec_float128_16_t fun_hva4_vec_float128_16_t (void) {
+ hva4_vec_float128_16_t ret = { { 4.5 },
+ { 5.5 },
+ { 6.5 },
+ { 7.5 } };
+ return ret;
+}
+#endif
+
+// Mixed HFA.
+typedef struct { float _Complex a; float b; } mixed_hfa3_cff_t;
+mixed_hfa3_cff_t fun_mixed_hfa3_cff (void) {
+ mixed_hfa3_cff_t ret = { 1.5 + 2.5i, 3.5 };
+ return ret;
+}
+
+typedef struct { double _Complex a; double b; } mixed_hfa3_cdd_t;
+mixed_hfa3_cdd_t fun_mixed_hfa3_cdd (void) {
+ mixed_hfa3_cdd_t ret = { 1.5 + 2.5i, 3.5 };
+ return ret;
+}
+
+typedef struct { long double _Complex a; long double b; } mixed_hfa3_cldld_t;
+mixed_hfa3_cldld_t fun_mixed_hfa3_cldld (void) {
+ mixed_hfa3_cldld_t ret = { 1.5 + 2.5i, 3.5 };
+ return ret;
+}
+
+typedef struct { float b; float _Complex a; } mixed_hfa3_fcf_t;
+mixed_hfa3_fcf_t fun_mixed_hfa3_fcf (void) {
+ mixed_hfa3_fcf_t ret = { 3.5, 1.5 + 2.5i };
+ return ret;
+}
+
+typedef struct { double b; double _Complex a; } mixed_hfa3_dcd_t;
+mixed_hfa3_dcd_t fun_mixed_hfa3_dcd (void) {
+ mixed_hfa3_dcd_t ret = { 3.5, 1.5 + 2.5i };
+ return ret;
+}
+
+typedef struct { long double b; long double _Complex a; } mixed_hfa3_ldcld_t;
+mixed_hfa3_ldcld_t fun_mixed_hfa3_ldcld (void) {
+ mixed_hfa3_ldcld_t ret = { 3.5, 1.5 + 2.5i };
+ return ret;
+}
+
+typedef struct { vec_float_8_t a; vec_short_8_t b; } mixed_hfa2_fltsht_t;
+mixed_hfa2_fltsht_t fun_mixed_hfa2_fltsht_t (void) {
+ mixed_hfa2_fltsht_t ret = { { 3.5, 4.5 }, { 1, 2, 3, 4 } };
+ return ret;
+}
+
+int main(int argc, char *argv[])
+{
+ return 0;
+}
diff --git a/tests/funcretval_test_aarch64.bz2 b/tests/funcretval_test_aarch64.bz2
new file mode 100755
index 00000000..5494e102
--- /dev/null
+++ b/tests/funcretval_test_aarch64.bz2
Binary files differ
diff --git a/tests/hello_aarch64.ko.bz2 b/tests/hello_aarch64.ko.bz2
new file mode 100644
index 00000000..431d89f9
--- /dev/null
+++ b/tests/hello_aarch64.ko.bz2
Binary files differ
diff --git a/tests/run-addrcfi.sh b/tests/run-addrcfi.sh
index 70e85ed7..a4225ac0 100755
--- a/tests/run-addrcfi.sh
+++ b/tests/run-addrcfi.sh
@@ -299,7 +299,7 @@ dwarf_cfi_addrframe (.eh_frame): no matching address range
return address in reg65
CFA location expression: bregx(1)
integer reg0 (r0): undefined
- integer reg1 (r1): location expression: call_frame_cfa nop stack_value
+ integer reg1 (r1): location expression: call_frame_cfa stack_value
integer reg2 (r2): same_value
integer reg3 (r3): undefined
integer reg4 (r4): undefined
@@ -1326,7 +1326,7 @@ dwarf_cfi_addrframe (.eh_frame): no matching address range
return address in reg65
CFA location expression: bregx(1)
integer reg0 (r0): undefined
- integer reg1 (r1): location expression: call_frame_cfa nop stack_value
+ integer reg1 (r1): location expression: call_frame_cfa stack_value
integer reg2 (r2): same_value
integer reg3 (r3): undefined
integer reg4 (r4): undefined
@@ -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/run-addrname-test.sh b/tests/run-addrname-test.sh
index 8624074f..f954ee45 100755
--- a/tests/run-addrname-test.sh
+++ b/tests/run-addrname-test.sh
@@ -298,6 +298,41 @@ __vdso_time
??:0
EOF
+# .section ".text"
+# .globl _start
+# .section ".opd","aw"
+#_start: .quad .L._start,.TOC.@tocbase
+# .previous
+# .type _start, @function
+#.L._start:
+# .byte 0x7d, 0x82, 0x10, 0x08
+# .size _start,.-.L._start
+testfiles testfile66 testfile66.core
+testrun_compare ${abs_top_builddir}/src/addr2line -x -e testfile66 _start 0x2d8 0x2db 0x2dc 0x103d0 0x103d3 0x103d4<<EOF
+_start (.text)
+??:0
+_start (.text)
+??:0
+_start+0x3 (.text)
+??:0
+()+0x2dc
+??:0
+_start (.opd)
+??:0
+_start+0x3 (.opd)
+??:0
+()+0x103d4
+??:0
+EOF
+testrun_compare ${abs_top_builddir}/src/addr2line -x -e testfile66 --core=testfile66.core _start 0x461b02d8 0x461c03d0<<\EOF
+_start (.text)
+??:0
+_start (.text)
+??:0
+_start (.opd)
+??:0
+EOF
+
testfiles testfile69.core testfile69.so
testrun_compare ${abs_top_builddir}/src/addr2line --core=./testfile69.core -S 0x7f0bc6a33535 0x7f0bc6a33546 <<\EOF
libstatic+0x9
diff --git a/tests/run-allfcts-multi.sh b/tests/run-allfcts-multi.sh
new file mode 100755
index 00000000..727b76ee
--- /dev/null
+++ b/tests/run-allfcts-multi.sh
@@ -0,0 +1,56 @@
+#! /bin/sh
+# 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 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/>.
+
+. $srcdir/test-subr.sh
+
+# See run-readelf-dwz-multi.sh
+testfiles libtestfile_multi_shared.so testfile_multi_main testfile_multi.dwz
+testfiles testfile-dwzstr testfile-dwzstr.multi
+
+testrun_compare ${abs_builddir}/allfcts testfile_multi_main libtestfile_multi_shared.so testfile-dwzstr <<\EOF
+/home/mark/src/tests/dwz/main.c:3:main
+/home/mark/src/tests/dwz/shared.c:3:call_foo
+/home/mark/src/tests/main.c:8:main
+EOF
+
+# - test-offset-loop.c
+#
+# #include <stdbool.h>
+# #include <string.h>
+# #include <errno.h>
+# void padding (int x, int y, int z) { }
+# static inline bool is_error (int err) { return err != 0; }
+# static inline int get_errno (void) { return errno; }
+# int main () { return is_error (get_errno ()); }
+#
+# gcc -g -O2 test-offset-loop.c -o test-offset-loop
+# cp test-offset-loop test-offset-loop2
+# dwz test-offset-loop test-offset-loop2 -m test-offset-loop.alt
+
+testfiles test-offset-loop test-offset-loop.alt
+tempfiles 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
+/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
+
+exit 0
diff --git a/tests/run-allregs.sh b/tests/run-allregs.sh
index 885a1d13..6f3862ec 100755
--- a/tests/run-allregs.sh
+++ b/tests/run-allregs.sh
@@ -1,5 +1,5 @@
#! /bin/sh
-# Copyright (C) 2005, 2006, 2007, 2012 Red Hat, Inc.
+# Copyright (C) 2005, 2006, 2007, 2012, 2013 Red Hat, Inc.
# This file is part of elfutils.
#
# This file is free software; you can redistribute it and/or modify
@@ -2724,4 +2724,76 @@ VFP registers:
287: d31 (d31), float 64 bits
EOF
+# See run-readelf-mixed-corenote.sh for instructions to regenerate
+# this core file.
+regs_test testfile_aarch64_core <<\EOF
+integer registers:
+ 0: x0 (x0), signed 64 bits
+ 1: x1 (x1), signed 64 bits
+ 2: x2 (x2), signed 64 bits
+ 3: x3 (x3), signed 64 bits
+ 4: x4 (x4), signed 64 bits
+ 5: x5 (x5), signed 64 bits
+ 6: x6 (x6), signed 64 bits
+ 7: x7 (x7), signed 64 bits
+ 8: x8 (x8), signed 64 bits
+ 9: x9 (x9), signed 64 bits
+ 10: x10 (x10), signed 64 bits
+ 11: x11 (x11), signed 64 bits
+ 12: x12 (x12), signed 64 bits
+ 13: x13 (x13), signed 64 bits
+ 14: x14 (x14), signed 64 bits
+ 15: x15 (x15), signed 64 bits
+ 16: x16 (x16), signed 64 bits
+ 17: x17 (x17), signed 64 bits
+ 18: x18 (x18), signed 64 bits
+ 19: x19 (x19), signed 64 bits
+ 20: x20 (x20), signed 64 bits
+ 21: x21 (x21), signed 64 bits
+ 22: x22 (x22), signed 64 bits
+ 23: x23 (x23), signed 64 bits
+ 24: x24 (x24), signed 64 bits
+ 25: x25 (x25), signed 64 bits
+ 26: x26 (x26), signed 64 bits
+ 27: x27 (x27), signed 64 bits
+ 28: x28 (x28), signed 64 bits
+ 29: x29 (x29), signed 64 bits
+ 30: x30 (x30), signed 64 bits
+ 31: sp (sp), address 64 bits
+ 33: elr (elr), address 64 bits
+FP/SIMD registers:
+ 64: v0 (v0), unsigned 128 bits
+ 65: v1 (v1), unsigned 128 bits
+ 66: v2 (v2), unsigned 128 bits
+ 67: v3 (v3), unsigned 128 bits
+ 68: v4 (v4), unsigned 128 bits
+ 69: v5 (v5), unsigned 128 bits
+ 70: v6 (v6), unsigned 128 bits
+ 71: v7 (v7), unsigned 128 bits
+ 72: v8 (v8), unsigned 128 bits
+ 73: v9 (v9), unsigned 128 bits
+ 74: v10 (v10), unsigned 128 bits
+ 75: v11 (v11), unsigned 128 bits
+ 76: v12 (v12), unsigned 128 bits
+ 77: v13 (v13), unsigned 128 bits
+ 78: v14 (v14), unsigned 128 bits
+ 79: v15 (v15), unsigned 128 bits
+ 80: v16 (v16), unsigned 128 bits
+ 81: v17 (v17), unsigned 128 bits
+ 82: v18 (v18), unsigned 128 bits
+ 83: v19 (v19), unsigned 128 bits
+ 84: v20 (v20), unsigned 128 bits
+ 85: v21 (v21), unsigned 128 bits
+ 86: v22 (v22), unsigned 128 bits
+ 87: v23 (v23), unsigned 128 bits
+ 88: v24 (v24), unsigned 128 bits
+ 89: v25 (v25), unsigned 128 bits
+ 90: v26 (v26), unsigned 128 bits
+ 91: v27 (v27), unsigned 128 bits
+ 92: v28 (v28), unsigned 128 bits
+ 93: v29 (v29), unsigned 128 bits
+ 94: v30 (v30), unsigned 128 bits
+ 95: v31 (v31), unsigned 128 bits
+EOF
+
exit 0
diff --git a/tests/run-arsymtest.sh b/tests/run-arsymtest.sh
index dc016e1f..b0fdfcd6 100755
--- a/tests/run-arsymtest.sh
+++ b/tests/run-arsymtest.sh
@@ -28,7 +28,7 @@ tempfiles $okfile $tmpfile $testfile
result=77
if test -f $lib; then
# Generate list using `nm' we check against.
- nm -s $lib |
+ ${NM} -s $lib |
sed -e '1,/^Arch/d' -e '/^$/,$d' |
sort > $okfile
diff --git a/tests/run-backtrace-core-i386.sh b/tests/run-backtrace-core-i386.sh
new file mode 100755
index 00000000..7294ec3d
--- /dev/null
+++ b/tests/run-backtrace-core-i386.sh
@@ -0,0 +1,20 @@
+#! /bin/bash
+# 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 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/>.
+
+. $srcdir/backtrace-subr.sh
+
+check_core i386
diff --git a/tests/run-backtrace-core-ppc.sh b/tests/run-backtrace-core-ppc.sh
new file mode 100755
index 00000000..65c92795
--- /dev/null
+++ b/tests/run-backtrace-core-ppc.sh
@@ -0,0 +1,20 @@
+#! /bin/bash
+# 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 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/>.
+
+. $srcdir/backtrace-subr.sh
+
+check_core ppc
diff --git a/tests/run-backtrace-core-s390.sh b/tests/run-backtrace-core-s390.sh
new file mode 100755
index 00000000..d3b6dc9c
--- /dev/null
+++ b/tests/run-backtrace-core-s390.sh
@@ -0,0 +1,20 @@
+#! /bin/bash
+# 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 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/>.
+
+. $srcdir/backtrace-subr.sh
+
+check_core s390
diff --git a/tests/run-backtrace-core-s390x.sh b/tests/run-backtrace-core-s390x.sh
new file mode 100755
index 00000000..c3e236d4
--- /dev/null
+++ b/tests/run-backtrace-core-s390x.sh
@@ -0,0 +1,20 @@
+#! /bin/bash
+# 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 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/>.
+
+. $srcdir/backtrace-subr.sh
+
+check_core s390x
diff --git a/tests/run-backtrace-core-x86_64.sh b/tests/run-backtrace-core-x86_64.sh
new file mode 100755
index 00000000..d00cd6d6
--- /dev/null
+++ b/tests/run-backtrace-core-x86_64.sh
@@ -0,0 +1,20 @@
+#! /bin/bash
+# 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 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/>.
+
+. $srcdir/backtrace-subr.sh
+
+check_core x86_64
diff --git a/tests/run-backtrace-data.sh b/tests/run-backtrace-data.sh
new file mode 100755
index 00000000..34a4f01d
--- /dev/null
+++ b/tests/run-backtrace-data.sh
@@ -0,0 +1,28 @@
+#! /bin/bash
+# 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 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/>.
+
+. $srcdir/backtrace-subr.sh
+
+# This test really cannot be run under valgrind, it tries to introspect
+# its own maps and registers and will find valgrinds instead.
+unset VALGRIND_CMD
+
+tempfiles data.{bt,err}
+(set +ex; testrun ${abs_builddir}/backtrace-data 1>data.bt 2>data.err; true)
+cat data.{bt,err}
+check_unsupported data.err data
+check_all data.{bt,err} data
diff --git a/tests/run-backtrace-dwarf.sh b/tests/run-backtrace-dwarf.sh
new file mode 100755
index 00000000..a133b32d
--- /dev/null
+++ b/tests/run-backtrace-dwarf.sh
@@ -0,0 +1,30 @@
+#! /bin/bash
+# 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 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/>.
+
+. $srcdir/backtrace-subr.sh
+
+# This test really cannot be run under valgrind, it tries to introspect
+# itself through ptrace and will find bits and pieces of valgrind.
+# On top of that valgrind also tries to read all the unwind info and
+# will warn and complain about various opcodes it doesn't understand...
+unset VALGRIND_CMD
+
+tempfiles dwarf.{bt,err}
+(set +ex; testrun ${abs_builddir}/backtrace-dwarf 1>dwarf.bt 2>dwarf.err; true)
+cat dwarf.{bt,err}
+check_unsupported dwarf.err dwarf
+check_main dwarf.bt dwarf
diff --git a/tests/run-backtrace-native-biarch.sh b/tests/run-backtrace-native-biarch.sh
new file mode 100755
index 00000000..3a407c89
--- /dev/null
+++ b/tests/run-backtrace-native-biarch.sh
@@ -0,0 +1,24 @@
+#! /bin/bash
+# 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 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_BIARCH"; then
+ exit 77
+fi
+
+. $srcdir/backtrace-subr.sh
+
+check_native backtrace-child-biarch
diff --git a/tests/run-backtrace-native-core-biarch.sh b/tests/run-backtrace-native-core-biarch.sh
new file mode 100755
index 00000000..fbd80256
--- /dev/null
+++ b/tests/run-backtrace-native-core-biarch.sh
@@ -0,0 +1,24 @@
+#! /bin/bash
+# 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 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_BIARCH"; then
+ exit 77
+fi
+
+. $srcdir/backtrace-subr.sh
+
+check_native_core backtrace-child-biarch
diff --git a/tests/run-backtrace-native-core.sh b/tests/run-backtrace-native-core.sh
new file mode 100755
index 00000000..cb025a56
--- /dev/null
+++ b/tests/run-backtrace-native-core.sh
@@ -0,0 +1,20 @@
+#! /bin/bash
+# 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 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/>.
+
+. $srcdir/backtrace-subr.sh
+
+check_native_core backtrace-child
diff --git a/tests/run-backtrace-native.sh b/tests/run-backtrace-native.sh
new file mode 100755
index 00000000..ddae345d
--- /dev/null
+++ b/tests/run-backtrace-native.sh
@@ -0,0 +1,20 @@
+#! /bin/bash
+# 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 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/>.
+
+. $srcdir/backtrace-subr.sh
+
+check_native backtrace-child
diff --git a/tests/run-dwflsyms.sh b/tests/run-dwflsyms.sh
index c440bf73..452b9617 100755
--- a/tests/run-dwflsyms.sh
+++ b/tests/run-dwflsyms.sh
@@ -17,17 +17,24 @@
. $srcdir/test-subr.sh
-# Tests dwfl_module_addrsym and dwfl_module_getsym.
+# Tests dwfl_module_{addrsym,getsym,relocate_address}
# See run-readelf-s.sh for how to generate test binaries.
+# In addition, *_pl files were created from their base file
+# with prelink -N, and *_plr with prelink -r 0x4200000000.
testfiles testfilebaztab
testfiles testfilebazdbg testfilebazdbg.debug
+testfiles testfilebazdbg_pl
+testfiles testfilebazdbg_plr
testfiles testfilebazdyn
testfiles testfilebazmdb
testfiles testfilebazmin
+testfiles testfilebazmin_pl
+testfiles testfilebazmin_plr
testfiles testfilebasmin
tempfiles testfile.dynsym.in testfile.symtab.in testfile.minsym.in dwflsyms.out
+tempfiles testfile.symtab_pl.in testfile.minsym_pl.in
cat > testfile.symtab.in <<\EOF
0: NOTYPE LOCAL (0) 0
@@ -65,17 +72,17 @@ cat > testfile.symtab.in <<\EOF
32: SECTION LOCAL (0) 0
33: FILE LOCAL crtstuff.c (0) 0
34: OBJECT LOCAL __JCR_LIST__ (0) 0x200de0
- 35: FUNC LOCAL deregister_tm_clones (0) 0x710
- 36: FUNC LOCAL register_tm_clones (0) 0x740
- 37: FUNC LOCAL __do_global_dtors_aux (0) 0x780
+ 35: FUNC LOCAL deregister_tm_clones (0) 0x710, rel: 0x710 (.text)
+ 36: FUNC LOCAL register_tm_clones (0) 0x740, rel: 0x740 (.text)
+ 37: FUNC LOCAL __do_global_dtors_aux (0) 0x780, rel: 0x780 (.text)
38: OBJECT LOCAL completed.6137 (1) 0x20103c
39: OBJECT LOCAL __do_global_dtors_aux_fini_array_entry (0) 0x200dd8
- 40: FUNC LOCAL frame_dummy (0) 0x7c0
+ 40: FUNC LOCAL frame_dummy (0) 0x7c0, rel: 0x7c0 (.text)
41: OBJECT LOCAL __frame_dummy_init_array_entry (0) 0x200dd0
42: FILE LOCAL foo.c (0) 0
43: FILE LOCAL bar.c (0) 0
44: OBJECT LOCAL b1 (4) 0x201034
- 45: FUNC LOCAL foo (20) 0x814
+ 45: FUNC LOCAL foo (20) 0x814, rel: 0x814 (.text)
46: FILE LOCAL crtstuff.c (0) 0
47: OBJECT LOCAL __FRAME_END__ (0) 0xa58
48: OBJECT LOCAL __JCR_END__ (0) 0x200de0
@@ -84,28 +91,107 @@ cat > testfile.symtab.in <<\EOF
51: OBJECT LOCAL _DYNAMIC (0) 0x200df0
52: NOTYPE LOCAL __init_array_start (0) 0x200dd0
53: OBJECT LOCAL _GLOBAL_OFFSET_TABLE_ (0) 0x201000
- 54: FUNC GLOBAL __libc_csu_fini (2) 0x8f0
+ 54: FUNC GLOBAL __libc_csu_fini (2) 0x8f0, rel: 0x8f0 (.text)
55: NOTYPE WEAK _ITM_deregisterTMCloneTable (0) 0
56: NOTYPE WEAK data_start (0) 0x201030
57: NOTYPE GLOBAL _edata (0) 0x20103c
- 58: FUNC GLOBAL bar (44) 0x828
- 59: FUNC GLOBAL _fini (0) 0x8f4
+ 58: FUNC GLOBAL bar (44) 0x828, rel: 0x828 (.text)
+ 59: FUNC GLOBAL _fini (0) 0x8f4, rel: 0x8f4 (.fini)
60: FUNC GLOBAL __libc_start_main@@GLIBC_2.2.5 (0) 0
61: NOTYPE GLOBAL __data_start (0) 0x201030
62: NOTYPE WEAK __gmon_start__ (0) 0
63: OBJECT GLOBAL __dso_handle (0) 0x200de8
64: OBJECT GLOBAL _IO_stdin_used (4) 0x900
65: OBJECT GLOBAL b2 (4) 0x201038
- 66: FUNC GLOBAL __libc_csu_init (137) 0x860
+ 66: FUNC GLOBAL __libc_csu_init (137) 0x860, rel: 0x860 (.text)
67: NOTYPE GLOBAL _end (0) 0x201040
- 68: FUNC GLOBAL _start (0) 0x6e0
+ 68: FUNC GLOBAL _start (0) 0x6e0, rel: 0x6e0 (.text)
69: NOTYPE GLOBAL __bss_start (0) 0x20103c
- 70: FUNC GLOBAL main (35) 0x7f0
+ 70: FUNC GLOBAL main (35) 0x7f0, rel: 0x7f0 (.text)
71: NOTYPE WEAK _Jv_RegisterClasses (0) 0
72: OBJECT GLOBAL __TMC_END__ (0) 0x201040
73: NOTYPE WEAK _ITM_registerTMCloneTable (0) 0
74: FUNC WEAK __cxa_finalize@@GLIBC_2.2.5 (0) 0
- 75: FUNC GLOBAL _init (0) 0x680
+ 75: FUNC GLOBAL _init (0) 0x680, rel: 0x680 (.init)
+EOF
+
+cat > testfile.symtab_pl.in <<\EOF
+ 0: NOTYPE LOCAL (0) 0
+ 1: SECTION LOCAL (0) 0x3000000238
+ 2: SECTION LOCAL (0) 0x3000000254
+ 3: SECTION LOCAL (0) 0x3000000274
+ 4: SECTION LOCAL (0) 0x3000000298
+ 5: SECTION LOCAL (0) 0x30000002d8
+ 6: SECTION LOCAL (0) 0x3000000428
+ 7: SECTION LOCAL (0) 0x30000004f2
+ 8: SECTION LOCAL (0) 0x3000000510
+ 9: SECTION LOCAL (0) 0x3000000530
+ 10: SECTION LOCAL (0) 0x3000000638
+ 11: SECTION LOCAL (0) 0x3000000680
+ 12: SECTION LOCAL (0) 0x30000006a0
+ 13: SECTION LOCAL (0) 0x30000006e0
+ 14: SECTION LOCAL (0) 0x30000008f4
+ 15: SECTION LOCAL (0) 0x3000000900
+ 16: SECTION LOCAL (0) 0x3000000904
+ 17: SECTION LOCAL (0) 0x3000000948
+ 18: SECTION LOCAL (0) 0x3000200dd0
+ 19: SECTION LOCAL (0) 0x3000200dd8
+ 20: SECTION LOCAL (0) 0x3000200de0
+ 21: SECTION LOCAL (0) 0x3000200de8
+ 22: SECTION LOCAL (0) 0x3000200df0
+ 23: SECTION LOCAL (0) 0x3000200fc0
+ 24: SECTION LOCAL (0) 0x3000201000
+ 25: SECTION LOCAL (0) 0x3000201030
+ 26: SECTION LOCAL (0) 0x300020103c
+ 27: SECTION LOCAL (0) 0
+ 28: SECTION LOCAL (0) 0
+ 29: SECTION LOCAL (0) 0
+ 30: SECTION LOCAL (0) 0
+ 31: SECTION LOCAL (0) 0
+ 32: SECTION LOCAL (0) 0
+ 33: FILE LOCAL crtstuff.c (0) 0
+ 34: OBJECT LOCAL __JCR_LIST__ (0) 0x3000200de0
+ 35: FUNC LOCAL deregister_tm_clones (0) 0x3000000710, rel: 0x710 (.text)
+ 36: FUNC LOCAL register_tm_clones (0) 0x3000000740, rel: 0x740 (.text)
+ 37: FUNC LOCAL __do_global_dtors_aux (0) 0x3000000780, rel: 0x780 (.text)
+ 38: OBJECT LOCAL completed.6137 (1) 0x300020103c
+ 39: OBJECT LOCAL __do_global_dtors_aux_fini_array_entry (0) 0x3000200dd8
+ 40: FUNC LOCAL frame_dummy (0) 0x30000007c0, rel: 0x7c0 (.text)
+ 41: OBJECT LOCAL __frame_dummy_init_array_entry (0) 0x3000200dd0
+ 42: FILE LOCAL foo.c (0) 0
+ 43: FILE LOCAL bar.c (0) 0
+ 44: OBJECT LOCAL b1 (4) 0x3000201034
+ 45: FUNC LOCAL foo (20) 0x3000000814, rel: 0x814 (.text)
+ 46: FILE LOCAL crtstuff.c (0) 0
+ 47: OBJECT LOCAL __FRAME_END__ (0) 0x3000000a58
+ 48: OBJECT LOCAL __JCR_END__ (0) 0x3000200de0
+ 49: FILE LOCAL (0) 0
+ 50: NOTYPE LOCAL __init_array_end (0) 0x3000200dd8
+ 51: OBJECT LOCAL _DYNAMIC (0) 0x3000200df0
+ 52: NOTYPE LOCAL __init_array_start (0) 0x3000200dd0
+ 53: OBJECT LOCAL _GLOBAL_OFFSET_TABLE_ (0) 0x3000201000
+ 54: FUNC GLOBAL __libc_csu_fini (2) 0x30000008f0, rel: 0x8f0 (.text)
+ 55: NOTYPE WEAK _ITM_deregisterTMCloneTable (0) 0
+ 56: NOTYPE WEAK data_start (0) 0x3000201030
+ 57: NOTYPE GLOBAL _edata (0) 0x300020103c
+ 58: FUNC GLOBAL bar (44) 0x3000000828, rel: 0x828 (.text)
+ 59: FUNC GLOBAL _fini (0) 0x30000008f4, rel: 0x8f4 (.fini)
+ 60: FUNC GLOBAL __libc_start_main@@GLIBC_2.2.5 (0) 0
+ 61: NOTYPE GLOBAL __data_start (0) 0x3000201030
+ 62: NOTYPE WEAK __gmon_start__ (0) 0
+ 63: OBJECT GLOBAL __dso_handle (0) 0x3000200de8
+ 64: OBJECT GLOBAL _IO_stdin_used (4) 0x3000000900
+ 65: OBJECT GLOBAL b2 (4) 0x3000201038
+ 66: FUNC GLOBAL __libc_csu_init (137) 0x3000000860, rel: 0x860 (.text)
+ 67: NOTYPE GLOBAL _end (0) 0x3000201040
+ 68: FUNC GLOBAL _start (0) 0x30000006e0, rel: 0x6e0 (.text)
+ 69: NOTYPE GLOBAL __bss_start (0) 0x300020103c
+ 70: FUNC GLOBAL main (35) 0x30000007f0, rel: 0x7f0 (.text)
+ 71: NOTYPE WEAK _Jv_RegisterClasses (0) 0
+ 72: OBJECT GLOBAL __TMC_END__ (0) 0x3000201040
+ 73: NOTYPE WEAK _ITM_registerTMCloneTable (0) 0
+ 74: FUNC WEAK __cxa_finalize@@GLIBC_2.2.5 (0) 0
+ 75: FUNC GLOBAL _init (0) 0x3000000680, rel: 0x680 (.init)
EOF
cat > testfile.dynsym.in <<\EOF
@@ -119,61 +205,122 @@ cat > testfile.dynsym.in <<\EOF
7: FUNC WEAK __cxa_finalize (0) 0
8: NOTYPE GLOBAL _edata (0) 0x20103c
9: NOTYPE GLOBAL _end (0) 0x201040
- 10: FUNC GLOBAL __libc_csu_init (137) 0x860
+ 10: FUNC GLOBAL __libc_csu_init (137) 0x860, rel: 0x860 (.text)
11: NOTYPE GLOBAL __bss_start (0) 0x20103c
- 12: FUNC GLOBAL main (35) 0x7f0
- 13: FUNC GLOBAL __libc_csu_fini (2) 0x8f0
+ 12: FUNC GLOBAL main (35) 0x7f0, rel: 0x7f0 (.text)
+ 13: FUNC GLOBAL __libc_csu_fini (2) 0x8f0, rel: 0x8f0 (.text)
EOF
cat > testfile.minsym.in <<\EOF
0: NOTYPE LOCAL (0) 0
1: SECTION LOCAL (0) 0x238
- 2: FUNC LOCAL call_gmon_start (0) 0x4003bc
- 3: FUNC LOCAL __do_global_dtors_aux (0) 0x4003e0
- 4: FUNC LOCAL frame_dummy (0) 0x400450
- 5: FUNC LOCAL __do_global_ctors_aux (0) 0x400580
- 6: FUNC LOCAL foo (18) 0x400498
- 7: SECTION LOCAL (0) 0x400200
- 8: SECTION LOCAL (0) 0x40021c
- 9: SECTION LOCAL (0) 0x40023c
- 10: SECTION LOCAL (0) 0x400260
- 11: SECTION LOCAL (0) 0x400280
- 12: SECTION LOCAL (0) 0x4002c8
- 13: SECTION LOCAL (0) 0x400300
- 14: SECTION LOCAL (0) 0x400308
- 15: SECTION LOCAL (0) 0x400328
- 16: SECTION LOCAL (0) 0x400340
- 17: SECTION LOCAL (0) 0x400358
- 18: SECTION LOCAL (0) 0x400370
- 19: SECTION LOCAL (0) 0x400390
- 20: SECTION LOCAL (0) 0x4005b8
- 21: SECTION LOCAL (0) 0x4005c8
- 22: SECTION LOCAL (0) 0x4005d8
- 23: SECTION LOCAL (0) 0x400610
- 24: SECTION LOCAL (0) 0x6006d0
- 25: SECTION LOCAL (0) 0x6006e0
- 26: SECTION LOCAL (0) 0x6006f0
- 27: SECTION LOCAL (0) 0x6006f8
- 28: SECTION LOCAL (0) 0x600888
- 29: SECTION LOCAL (0) 0x600890
- 30: SECTION LOCAL (0) 0x6008b0
- 31: SECTION LOCAL (0) 0x6008c0
- 32: NOTYPE WEAK _ITM_deregisterTMCloneTable (0) 0
- 33: FUNC GLOBAL __libc_start_main (0) 0
- 34: NOTYPE WEAK __gmon_start__ (0) 0
- 35: NOTYPE WEAK _Jv_RegisterClasses (0) 0
- 36: NOTYPE WEAK _ITM_registerTMCloneTable (0) 0
- 37: FUNC WEAK __cxa_finalize (0) 0
- 38: NOTYPE GLOBAL _edata (0) 0x20103c
- 39: NOTYPE GLOBAL _end (0) 0x201040
- 40: FUNC GLOBAL __libc_csu_init (137) 0x860
- 41: NOTYPE GLOBAL __bss_start (0) 0x20103c
- 42: FUNC GLOBAL main (35) 0x7f0
- 43: FUNC GLOBAL __libc_csu_fini (2) 0x8f0
- 44: FUNC GLOBAL _start (0) 0x400390
- 45: FUNC GLOBAL bar (44) 0x4004aa
- 46: FUNC GLOBAL _fini (0) 0x4005b8
- 47: FUNC GLOBAL _init (0) 0x400358
+ 2: FUNC LOCAL deregister_tm_clones (0) 0x710, rel: 0x710 (.text)
+ 3: FUNC LOCAL register_tm_clones (0) 0x740, rel: 0x740 (.text)
+ 4: FUNC LOCAL __do_global_dtors_aux (0) 0x780, rel: 0x780 (.text)
+ 5: OBJECT LOCAL __do_global_dtors_aux_fini_array_entry (0) 0x200dd8
+ 6: FUNC LOCAL frame_dummy (0) 0x7c0, rel: 0x7c0 (.text)
+ 7: OBJECT LOCAL __frame_dummy_init_array_entry (0) 0x200dd0
+ 8: FUNC LOCAL foo (20) 0x814, rel: 0x814 (.text)
+ 9: NOTYPE LOCAL __init_array_end (0) 0x200dd8
+ 10: NOTYPE LOCAL __init_array_start (0) 0x200dd0
+ 11: SECTION LOCAL (0) 0x238
+ 12: SECTION LOCAL (0) 0x254
+ 13: SECTION LOCAL (0) 0x274
+ 14: SECTION LOCAL (0) 0x298
+ 15: SECTION LOCAL (0) 0x2d8
+ 16: SECTION LOCAL (0) 0x428
+ 17: SECTION LOCAL (0) 0x4f2
+ 18: SECTION LOCAL (0) 0x510
+ 19: SECTION LOCAL (0) 0x530
+ 20: SECTION LOCAL (0) 0x638
+ 21: SECTION LOCAL (0) 0x680
+ 22: SECTION LOCAL (0) 0x6a0
+ 23: SECTION LOCAL (0) 0x6e0
+ 24: SECTION LOCAL (0) 0x8f4
+ 25: SECTION LOCAL (0) 0x900
+ 26: SECTION LOCAL (0) 0x904
+ 27: SECTION LOCAL (0) 0x948
+ 28: SECTION LOCAL (0) 0x200dd0
+ 29: SECTION LOCAL (0) 0x200dd8
+ 30: SECTION LOCAL (0) 0x200de0
+ 31: SECTION LOCAL (0) 0x200de8
+ 32: SECTION LOCAL (0) 0x200df0
+ 33: SECTION LOCAL (0) 0x200fc0
+ 34: SECTION LOCAL (0) 0x201000
+ 35: SECTION LOCAL (0) 0x201030
+ 36: SECTION LOCAL (0) 0x20103c
+ 37: NOTYPE WEAK _ITM_deregisterTMCloneTable (0) 0
+ 38: FUNC GLOBAL __libc_start_main (0) 0
+ 39: NOTYPE WEAK __gmon_start__ (0) 0
+ 40: NOTYPE WEAK _Jv_RegisterClasses (0) 0
+ 41: NOTYPE WEAK _ITM_registerTMCloneTable (0) 0
+ 42: FUNC WEAK __cxa_finalize (0) 0
+ 43: NOTYPE GLOBAL _edata (0) 0x20103c
+ 44: NOTYPE GLOBAL _end (0) 0x201040
+ 45: FUNC GLOBAL __libc_csu_init (137) 0x860, rel: 0x860 (.text)
+ 46: NOTYPE GLOBAL __bss_start (0) 0x20103c
+ 47: FUNC GLOBAL main (35) 0x7f0, rel: 0x7f0 (.text)
+ 48: FUNC GLOBAL __libc_csu_fini (2) 0x8f0, rel: 0x8f0 (.text)
+ 49: FUNC GLOBAL bar (44) 0x828, rel: 0x828 (.text)
+ 50: FUNC GLOBAL _fini (0) 0x8f4, rel: 0x8f4 (.fini)
+ 51: FUNC GLOBAL _start (0) 0x6e0, rel: 0x6e0 (.text)
+ 52: FUNC GLOBAL _init (0) 0x680, rel: 0x680 (.init)
+EOF
+
+cat > testfile.minsym_pl.in <<\EOF
+ 0: NOTYPE LOCAL (0) 0
+ 1: SECTION LOCAL (0) 0x3000000238
+ 2: FUNC LOCAL deregister_tm_clones (0) 0x3000000710, rel: 0x710 (.text)
+ 3: FUNC LOCAL register_tm_clones (0) 0x3000000740, rel: 0x740 (.text)
+ 4: FUNC LOCAL __do_global_dtors_aux (0) 0x3000000780, rel: 0x780 (.text)
+ 5: OBJECT LOCAL __do_global_dtors_aux_fini_array_entry (0) 0x3000200dd8
+ 6: FUNC LOCAL frame_dummy (0) 0x30000007c0, rel: 0x7c0 (.text)
+ 7: OBJECT LOCAL __frame_dummy_init_array_entry (0) 0x3000200dd0
+ 8: FUNC LOCAL foo (20) 0x3000000814, rel: 0x814 (.text)
+ 9: NOTYPE LOCAL __init_array_end (0) 0x3000200dd8
+ 10: NOTYPE LOCAL __init_array_start (0) 0x3000200dd0
+ 11: SECTION LOCAL (0) 0x3000000238
+ 12: SECTION LOCAL (0) 0x3000000254
+ 13: SECTION LOCAL (0) 0x3000000274
+ 14: SECTION LOCAL (0) 0x3000000298
+ 15: SECTION LOCAL (0) 0x30000002d8
+ 16: SECTION LOCAL (0) 0x3000000428
+ 17: SECTION LOCAL (0) 0x30000004f2
+ 18: SECTION LOCAL (0) 0x3000000510
+ 19: SECTION LOCAL (0) 0x3000000530
+ 20: SECTION LOCAL (0) 0x3000000638
+ 21: SECTION LOCAL (0) 0x3000000680
+ 22: SECTION LOCAL (0) 0x30000006a0
+ 23: SECTION LOCAL (0) 0x30000006e0
+ 24: SECTION LOCAL (0) 0x30000008f4
+ 25: SECTION LOCAL (0) 0x3000000900
+ 26: SECTION LOCAL (0) 0x3000000904
+ 27: SECTION LOCAL (0) 0x3000000948
+ 28: SECTION LOCAL (0) 0x3000200dd0
+ 29: SECTION LOCAL (0) 0x3000200dd8
+ 30: SECTION LOCAL (0) 0x3000200de0
+ 31: SECTION LOCAL (0) 0x3000200de8
+ 32: SECTION LOCAL (0) 0x3000200df0
+ 33: SECTION LOCAL (0) 0x3000200fc0
+ 34: SECTION LOCAL (0) 0x3000201000
+ 35: SECTION LOCAL (0) 0x3000201030
+ 36: SECTION LOCAL (0) 0x300020103c
+ 37: NOTYPE WEAK _ITM_deregisterTMCloneTable (0) 0
+ 38: FUNC GLOBAL __libc_start_main (0) 0
+ 39: NOTYPE WEAK __gmon_start__ (0) 0
+ 40: NOTYPE WEAK _Jv_RegisterClasses (0) 0
+ 41: NOTYPE WEAK _ITM_registerTMCloneTable (0) 0
+ 42: FUNC WEAK __cxa_finalize (0) 0
+ 43: NOTYPE GLOBAL _edata (0) 0x300020103c
+ 44: NOTYPE GLOBAL _end (0) 0x3000201040
+ 45: FUNC GLOBAL __libc_csu_init (137) 0x3000000860, rel: 0x860 (.text)
+ 46: NOTYPE GLOBAL __bss_start (0) 0x300020103c
+ 47: FUNC GLOBAL main (35) 0x30000007f0, rel: 0x7f0 (.text)
+ 48: FUNC GLOBAL __libc_csu_fini (2) 0x30000008f0, rel: 0x8f0 (.text)
+ 49: FUNC GLOBAL bar (44) 0x3000000828, rel: 0x828 (.text)
+ 50: FUNC GLOBAL _fini (0) 0x30000008f4, rel: 0x8f4 (.fini)
+ 51: FUNC GLOBAL _start (0) 0x30000006e0, rel: 0x6e0 (.text)
+ 52: FUNC GLOBAL _init (0) 0x3000000680, rel: 0x680 (.init)
EOF
cat testfile.symtab.in \
@@ -182,6 +329,12 @@ cat testfile.symtab.in \
cat testfile.symtab.in \
| testrun_compare ${abs_builddir}/dwflsyms -e testfilebazdbg
+cat testfile.symtab_pl.in \
+ | testrun_compare ${abs_builddir}/dwflsyms -e testfilebazdbg_pl
+
+sed s/0x3000/0x4200/g testfile.symtab_pl.in \
+ | testrun_compare ${abs_builddir}/dwflsyms -e testfilebazdbg_plr
+
cat testfile.dynsym.in \
| testrun_compare ${abs_builddir}/dwflsyms -e testfilebazdyn
@@ -191,16 +344,435 @@ cat testfile.symtab.in \
cat testfile.minsym.in \
| testrun_compare ${abs_builddir}/dwflsyms -e testfilebazmin
+cat testfile.minsym_pl.in \
+ | testrun_compare ${abs_builddir}/dwflsyms -e testfilebazmin_pl
+
+sed s/0x3000/0x4200/g testfile.minsym_pl.in \
+ | testrun_compare ${abs_builddir}/dwflsyms -e testfilebazmin_plr
+
testrun_compare ${abs_builddir}/dwflsyms -e testfilebasmin <<\EOF
0: NOTYPE LOCAL (0) 0
- 1: FUNC LOCAL foo (18) 0x400168
+ 1: FUNC LOCAL foo (18) 0x400168, rel: 0x400168 (.text)
2: SECTION LOCAL (0) 0x400120
3: SECTION LOCAL (0) 0x400144
4: SECTION LOCAL (0) 0x4001c0
5: SECTION LOCAL (0) 0x600258
- 6: FUNC GLOBAL _start (21) 0x4001a8
- 7: FUNC GLOBAL main (33) 0x400144
- 8: FUNC GLOBAL bar (44) 0x40017a
+ 6: FUNC GLOBAL _start (21) 0x4001a8, rel: 0x4001a8 (.text)
+ 7: FUNC GLOBAL main (33) 0x400144, rel: 0x400144 (.text)
+ 8: FUNC GLOBAL bar (44) 0x40017a, rel: 0x40017a (.text)
+EOF
+
+testfiles testfile66
+testrun_compare ${abs_builddir}/dwflsyms -e testfile66 <<\EOF
+ 0: NOTYPE LOCAL (0) 0
+ 1: SECTION LOCAL (0) 0x190
+ 2: SECTION LOCAL (0) 0x1a4
+ 3: SECTION LOCAL (0) 0x1c8
+ 4: SECTION LOCAL (0) 0x1f8
+ 5: SECTION LOCAL (0) 0x288
+ 6: SECTION LOCAL (0) 0x2a8
+ 7: SECTION LOCAL (0) 0x2d8
+ 8: SECTION LOCAL (0) 0x102e0
+ 9: SECTION LOCAL (0) 0x103d0
+ 10: SECTION LOCAL (0) 0x103e8
+ 11: SECTION LOCAL (0) 0x103e8
+ 12: OBJECT LOCAL _DYNAMIC (0) 0x102e0
+ 13: FUNC GLOBAL _start (4) 0x103d0, rel: 0x103d0 (.opd) [0x2d8, rel: 0 (.text)]
+ 14: NOTYPE GLOBAL __bss_start (0) 0x103f0
+ 15: NOTYPE GLOBAL _edata (0) 0x103f0
+ 16: NOTYPE GLOBAL _end (0) 0x103f0
+EOF
+
+testfiles testfile66.core
+testrun_compare ${abs_builddir}/dwflsyms -e testfile66 --core=testfile66.core <<\EOF
+ 0: NOTYPE LOCAL (0) 0
+ 1: SECTION LOCAL (0) 0xfffb1af0410
+ 2: NOTYPE GLOBAL __kernel_datapage_offset (0) 0xfffb1af05dc
+ 3: OBJECT GLOBAL LINUX_2.6.15 (0) 0
+ 4: NOTYPE GLOBAL __kernel_clock_getres (64) 0xfffb1af052c
+ 5: NOTYPE GLOBAL __kernel_get_tbfreq (24) 0xfffb1af0620
+ 6: NOTYPE GLOBAL __kernel_gettimeofday (84) 0xfffb1af0440
+ 7: NOTYPE GLOBAL __kernel_sync_dicache (20) 0xfffb1af06c4
+ 8: NOTYPE GLOBAL __kernel_sync_dicache_p5 (20) 0xfffb1af06c4
+ 9: NOTYPE GLOBAL __kernel_sigtramp_rt64 (12) 0xfffb1af0418
+ 10: NOTYPE GLOBAL __kernel_clock_gettime (152) 0xfffb1af0494
+ 11: NOTYPE GLOBAL __kernel_get_syscall_map (44) 0xfffb1af05f4
+ld64.so.1: Callback returned failure
+ 0: NOTYPE LOCAL (0) 0
+ 1: SECTION LOCAL (0) 0x461b0190
+ 2: SECTION LOCAL (0) 0x461b01a4
+ 3: SECTION LOCAL (0) 0x461b01c8
+ 4: SECTION LOCAL (0) 0x461b01f8
+ 5: SECTION LOCAL (0) 0x461b0288
+ 6: SECTION LOCAL (0) 0x461b02a8
+ 7: SECTION LOCAL (0) 0x461b02d8
+ 8: SECTION LOCAL (0) 0x461c02e0
+ 9: SECTION LOCAL (0) 0x461c03d0
+ 10: SECTION LOCAL (0) 0x461c03e8
+ 11: SECTION LOCAL (0) 0x461c03e8
+ 12: OBJECT LOCAL _DYNAMIC (0) 0x102e0
+ 13: FUNC GLOBAL _start (4) 0x461c03d0, rel: 0x103d0 (.opd) [0x461b02d8, rel: 0 (.text)]
+ 14: NOTYPE GLOBAL __bss_start (0) 0x103f0
+ 15: NOTYPE GLOBAL _edata (0) 0x103f0
+ 16: NOTYPE GLOBAL _end (0) 0x103f0
+EOF
+
+# Test the already present dot-prefixed names do not get duplicated.
+testfiles hello_ppc64.ko
+testrun_compare ${abs_builddir}/dwflsyms -e hello_ppc64.ko <<\EOF
+ 0: NOTYPE LOCAL (0) 0
+ 1: SECTION LOCAL (0) 0
+ 2: SECTION LOCAL (0) 0x94
+ 3: SECTION LOCAL (0) 0xba
+ 4: SECTION LOCAL (0) 0xd0
+ 5: SECTION LOCAL (0) 0x13a
+ 6: SECTION LOCAL (0) 0x13a
+ 7: SECTION LOCAL (0) 0x150
+ 8: SECTION LOCAL (0) 0x170
+ 9: SECTION LOCAL (0) 0x188
+ 10: SECTION LOCAL (0) 0x410
+ 11: SECTION LOCAL (0) 0x434
+ 12: SECTION LOCAL (0) 0x438
+ 13: SECTION LOCAL (0) 0x438
+ 14: SECTION LOCAL (0) 0
+ 15: SECTION LOCAL (0) 0
+ 16: SECTION LOCAL (0) 0
+ 17: SECTION LOCAL (0) 0
+ 18: SECTION LOCAL (0) 0
+ 19: SECTION LOCAL (0) 0
+ 20: SECTION LOCAL (0) 0
+ 21: SECTION LOCAL (0) 0
+ 22: SECTION LOCAL (0) 0
+ 23: SECTION LOCAL (0) 0
+ 24: FILE LOCAL init.c (0) 0
+ 25: FILE LOCAL exit.c (0) 0
+ 26: FILE LOCAL hello.mod.c (0) 0
+ 27: OBJECT LOCAL __mod_srcversion23 (35) 0xd0
+ 28: OBJECT LOCAL __module_depends (9) 0xf8
+ 29: OBJECT LOCAL __mod_vermagic5 (50) 0x108
+ 30: OBJECT GLOBAL __this_module (648) 0x188
+ 31: FUNC GLOBAL .cleanup_module (72) 0x4c, rel: 0x4c (.text)
+ 32: FUNC GLOBAL cleanup_module (24) 0x160, rel: 0x10 (.opd)
+ 33: NOTYPE GLOBAL .printk (0) 0
+ 34: FUNC GLOBAL init_module (24) 0x150, rel: 0 (.opd)
+ 35: NOTYPE GLOBAL ._mcount (0) 0
+ 36: FUNC GLOBAL .init_module (76) 0, rel: 0 (.text)
+ 37: NOTYPE GLOBAL _mcount (0) 0
EOF
+# Same test files as above, but now generated on ppc64.
+# ppc64 uses function descriptors to make things more "interesting".
+
+testfiles testfilebaztabppc64
+testfiles testfilebazdbgppc64 testfilebazdbgppc64.debug
+testfiles testfilebazdbgppc64_pl
+testfiles testfilebazdbgppc64_plr
+testfiles testfilebazdynppc64
+testfiles testfilebazmdbppc64
+testfiles testfilebazminppc64
+testfiles testfilebazminppc64_pl
+testfiles testfilebazminppc64_plr
+
+cat > testfile.symtab.in <<\EOF
+ 0: NOTYPE LOCAL (0) 0
+ 1: SECTION LOCAL (0) 0x238
+ 2: SECTION LOCAL (0) 0x24c
+ 3: SECTION LOCAL (0) 0x26c
+ 4: SECTION LOCAL (0) 0x290
+ 5: SECTION LOCAL (0) 0x2c0
+ 6: SECTION LOCAL (0) 0x3e0
+ 7: SECTION LOCAL (0) 0x488
+ 8: SECTION LOCAL (0) 0x4a0
+ 9: SECTION LOCAL (0) 0x4c0
+ 10: SECTION LOCAL (0) 0x820
+ 11: SECTION LOCAL (0) 0x850
+ 12: SECTION LOCAL (0) 0x8a0
+ 13: SECTION LOCAL (0) 0xd30
+ 14: SECTION LOCAL (0) 0xd4c
+ 15: SECTION LOCAL (0) 0xd50
+ 16: SECTION LOCAL (0) 0xd70
+ 17: SECTION LOCAL (0) 0x1fde0
+ 18: SECTION LOCAL (0) 0x1fde8
+ 19: SECTION LOCAL (0) 0x1fdf0
+ 20: SECTION LOCAL (0) 0x1fdf8
+ 21: SECTION LOCAL (0) 0x1fe20
+ 22: SECTION LOCAL (0) 0x20000
+ 23: SECTION LOCAL (0) 0x20010
+ 24: SECTION LOCAL (0) 0x200d8
+ 25: SECTION LOCAL (0) 0x20110
+ 26: SECTION LOCAL (0) 0x20158
+ 27: SECTION LOCAL (0) 0
+ 28: SECTION LOCAL (0) 0
+ 29: SECTION LOCAL (0) 0
+ 30: SECTION LOCAL (0) 0
+ 31: SECTION LOCAL (0) 0
+ 32: SECTION LOCAL (0) 0
+ 33: SECTION LOCAL (0) 0
+ 34: FILE LOCAL crtstuff.c (0) 0
+ 35: OBJECT LOCAL __JCR_LIST__ (0) 0x1fdf0
+ 36: FUNC LOCAL deregister_tm_clones (0) 0x20040, rel: 0x20040 (.opd) [0x910, rel: 0x70 (.text)]
+ 37: FUNC LOCAL register_tm_clones (0) 0x20050, rel: 0x20050 (.opd) [0x980, rel: 0xe0 (.text)]
+ 38: FUNC LOCAL __do_global_dtors_aux (0) 0x20060, rel: 0x20060 (.opd) [0x9f0, rel: 0x150 (.text)]
+ 39: OBJECT LOCAL completed.7711 (1) 0x20158
+ 40: OBJECT LOCAL __do_global_dtors_aux_fini_array_entry (0) 0x1fde8
+ 41: FUNC LOCAL frame_dummy (0) 0x20070, rel: 0x20070 (.opd) [0xa50, rel: 0x1b0 (.text)]
+ 42: OBJECT LOCAL __frame_dummy_init_array_entry (0) 0x1fde0
+ 43: FILE LOCAL foo.c (0) 0
+ 44: FILE LOCAL bar.c (0) 0
+ 45: OBJECT LOCAL b1 (4) 0x20004
+ 46: FUNC LOCAL foo (76) 0x20090, rel: 0x20090 (.opd) [0xb34, rel: 0x294 (.text)]
+ 47: FILE LOCAL crtstuff.c (0) 0
+ 48: OBJECT LOCAL __FRAME_END__ (0) 0xe18
+ 49: OBJECT LOCAL __JCR_END__ (0) 0x1fdf0
+ 50: FILE LOCAL (0) 0
+ 51: NOTYPE LOCAL __glink_PLTresolve (0) 0xce8
+ 52: NOTYPE LOCAL 00000011.plt_call.__libc_start_main@@GLIBC_2.3 (0) 0x8a0
+ 53: NOTYPE LOCAL 00000011.plt_call.__cxa_finalize@@GLIBC_2.3 (0) 0x8b4
+ 54: NOTYPE LOCAL __init_array_end (0) 0x1fde8
+ 55: OBJECT LOCAL _DYNAMIC (0) 0x1fe20
+ 56: NOTYPE LOCAL __init_array_start (0) 0x1fde0
+ 57: FUNC GLOBAL __libc_csu_fini (16) 0x200c0, rel: 0x200c0 (.opd) [0xcd0, rel: 0x430 (.text)]
+ 58: FUNC GLOBAL __libc_start_main@@GLIBC_2.3 (0) 0
+ 59: NOTYPE WEAK _ITM_deregisterTMCloneTable (0) 0
+ 60: NOTYPE WEAK data_start (0) 0x20000
+ 61: NOTYPE GLOBAL _edata (0) 0x20110
+ 62: FUNC GLOBAL bar (116) 0x200a0, rel: 0x200a0 (.opd) [0xb80, rel: 0x2e0 (.text)]
+ 63: FUNC GLOBAL _fini (0) 0x20030, rel: 0x20030 (.opd) [0xd30, rel: 0 (.fini)]
+ 64: NOTYPE GLOBAL __data_start (0) 0x20000
+ 65: NOTYPE WEAK __gmon_start__ (0) 0
+ 66: OBJECT GLOBAL __dso_handle (0) 0x1fe18
+ 67: OBJECT GLOBAL _IO_stdin_used (4) 0xd4c
+ 68: OBJECT GLOBAL b2 (4) 0x20008
+ 69: FUNC WEAK __cxa_finalize@@GLIBC_2.3 (0) 0
+ 70: FUNC GLOBAL __libc_csu_init (204) 0x200b0, rel: 0x200b0 (.opd) [0xc00, rel: 0x360 (.text)]
+ 71: NOTYPE GLOBAL _end (0) 0x20160
+ 72: FUNC GLOBAL _start (60) 0x20010, rel: 0x20010 (.opd) [0x8c8, rel: 0x28 (.text)]
+ 73: NOTYPE GLOBAL __bss_start (0) 0x20110
+ 74: FUNC GLOBAL main (128) 0x20080, rel: 0x20080 (.opd) [0xab4, rel: 0x214 (.text)]
+ 75: NOTYPE WEAK _Jv_RegisterClasses (0) 0
+ 76: OBJECT GLOBAL __TMC_END__ (0) 0x20010
+ 77: NOTYPE WEAK _ITM_registerTMCloneTable (0) 0
+ 78: FUNC GLOBAL _init (0) 0x20020, rel: 0x20020 (.opd) [0x850, rel: 0 (.init)]
+EOF
+
+cat > testfile.symtab_pl.in <<\EOF
+ 0: NOTYPE LOCAL (0) 0
+ 1: SECTION LOCAL (0) 0x8001000238
+ 2: SECTION LOCAL (0) 0x800100024c
+ 3: SECTION LOCAL (0) 0x800100026c
+ 4: SECTION LOCAL (0) 0x8001000290
+ 5: SECTION LOCAL (0) 0x80010002c0
+ 6: SECTION LOCAL (0) 0x80010003e0
+ 7: SECTION LOCAL (0) 0x8001000488
+ 8: SECTION LOCAL (0) 0x80010004a0
+ 9: SECTION LOCAL (0) 0x80010004c0
+ 10: SECTION LOCAL (0) 0x8001000820
+ 11: SECTION LOCAL (0) 0x8001000850
+ 12: SECTION LOCAL (0) 0x80010008a0
+ 13: SECTION LOCAL (0) 0x8001000d30
+ 14: SECTION LOCAL (0) 0x8001000d4c
+ 15: SECTION LOCAL (0) 0x8001000d50
+ 16: SECTION LOCAL (0) 0x8001000d70
+ 17: SECTION LOCAL (0) 0x800101fde0
+ 18: SECTION LOCAL (0) 0x800101fde8
+ 19: SECTION LOCAL (0) 0x800101fdf0
+ 20: SECTION LOCAL (0) 0x800101fdf8
+ 21: SECTION LOCAL (0) 0x800101fe20
+ 22: SECTION LOCAL (0) 0x8001020000
+ 23: SECTION LOCAL (0) 0x8001020010
+ 24: SECTION LOCAL (0) 0x80010200d8
+ 25: SECTION LOCAL (0) 0x8001020110
+ 26: SECTION LOCAL (0) 0x8001020158
+ 27: SECTION LOCAL (0) 0
+ 28: SECTION LOCAL (0) 0
+ 29: SECTION LOCAL (0) 0
+ 30: SECTION LOCAL (0) 0
+ 31: SECTION LOCAL (0) 0
+ 32: SECTION LOCAL (0) 0
+ 33: SECTION LOCAL (0) 0
+ 34: FILE LOCAL crtstuff.c (0) 0
+ 35: OBJECT LOCAL __JCR_LIST__ (0) 0x800101fdf0
+ 36: FUNC LOCAL deregister_tm_clones (0) 0x8001020040, rel: 0x20040 (.opd) [0x8001000910, rel: 0x70 (.text)]
+ 37: FUNC LOCAL register_tm_clones (0) 0x8001020050, rel: 0x20050 (.opd) [0x8001000980, rel: 0xe0 (.text)]
+ 38: FUNC LOCAL __do_global_dtors_aux (0) 0x8001020060, rel: 0x20060 (.opd) [0x80010009f0, rel: 0x150 (.text)]
+ 39: OBJECT LOCAL completed.7711 (1) 0x8001020158
+ 40: OBJECT LOCAL __do_global_dtors_aux_fini_array_entry (0) 0x800101fde8
+ 41: FUNC LOCAL frame_dummy (0) 0x8001020070, rel: 0x20070 (.opd) [0x8001000a50, rel: 0x1b0 (.text)]
+ 42: OBJECT LOCAL __frame_dummy_init_array_entry (0) 0x800101fde0
+ 43: FILE LOCAL foo.c (0) 0
+ 44: FILE LOCAL bar.c (0) 0
+ 45: OBJECT LOCAL b1 (4) 0x8001020004
+ 46: FUNC LOCAL foo (76) 0x8001020090, rel: 0x20090 (.opd) [0x8001000b34, rel: 0x294 (.text)]
+ 47: FILE LOCAL crtstuff.c (0) 0
+ 48: OBJECT LOCAL __FRAME_END__ (0) 0x8001000e18
+ 49: OBJECT LOCAL __JCR_END__ (0) 0x800101fdf0
+ 50: FILE LOCAL (0) 0
+ 51: NOTYPE LOCAL __glink_PLTresolve (0) 0x8001000ce8
+ 52: NOTYPE LOCAL 00000011.plt_call.__libc_start_main@@GLIBC_2.3 (0) 0x80010008a0
+ 53: NOTYPE LOCAL 00000011.plt_call.__cxa_finalize@@GLIBC_2.3 (0) 0x80010008b4
+ 54: NOTYPE LOCAL __init_array_end (0) 0x800101fde8
+ 55: OBJECT LOCAL _DYNAMIC (0) 0x800101fe20
+ 56: NOTYPE LOCAL __init_array_start (0) 0x800101fde0
+ 57: FUNC GLOBAL __libc_csu_fini (16) 0x80010200c0, rel: 0x200c0 (.opd) [0x8001000cd0, rel: 0x430 (.text)]
+ 58: FUNC GLOBAL __libc_start_main@@GLIBC_2.3 (0) 0
+ 59: NOTYPE WEAK _ITM_deregisterTMCloneTable (0) 0
+ 60: NOTYPE WEAK data_start (0) 0x8001020000
+ 61: NOTYPE GLOBAL _edata (0) 0x8001020110
+ 62: FUNC GLOBAL bar (116) 0x80010200a0, rel: 0x200a0 (.opd) [0x8001000b80, rel: 0x2e0 (.text)]
+ 63: FUNC GLOBAL _fini (0) 0x8001020030, rel: 0x20030 (.opd) [0x8001000d30, rel: 0 (.fini)]
+ 64: NOTYPE GLOBAL __data_start (0) 0x8001020000
+ 65: NOTYPE WEAK __gmon_start__ (0) 0
+ 66: OBJECT GLOBAL __dso_handle (0) 0x800101fe18
+ 67: OBJECT GLOBAL _IO_stdin_used (4) 0x8001000d4c
+ 68: OBJECT GLOBAL b2 (4) 0x8001020008
+ 69: FUNC WEAK __cxa_finalize@@GLIBC_2.3 (0) 0
+ 70: FUNC GLOBAL __libc_csu_init (204) 0x80010200b0, rel: 0x200b0 (.opd) [0x8001000c00, rel: 0x360 (.text)]
+ 71: NOTYPE GLOBAL _end (0) 0x8001020160
+ 72: FUNC GLOBAL _start (60) 0x8001020010, rel: 0x20010 (.opd) [0x80010008c8, rel: 0x28 (.text)]
+ 73: NOTYPE GLOBAL __bss_start (0) 0x8001020110
+ 74: FUNC GLOBAL main (128) 0x8001020080, rel: 0x20080 (.opd) [0x8001000ab4, rel: 0x214 (.text)]
+ 75: NOTYPE WEAK _Jv_RegisterClasses (0) 0
+ 76: OBJECT GLOBAL __TMC_END__ (0) 0x8001020010
+ 77: NOTYPE WEAK _ITM_registerTMCloneTable (0) 0
+ 78: FUNC GLOBAL _init (0) 0x8001020020, rel: 0x20020 (.opd) [0x8001000850, rel: 0 (.init)]
+EOF
+
+cat > testfile.dynsym.in <<\EOF
+ 0: NOTYPE LOCAL (0) 0
+ 1: SECTION LOCAL (0) 0x238
+ 2: SECTION LOCAL (0) 0x1fdf0
+ 3: FUNC GLOBAL __libc_start_main (0) 0
+ 4: NOTYPE WEAK _ITM_deregisterTMCloneTable (0) 0
+ 5: NOTYPE WEAK __gmon_start__ (0) 0
+ 6: FUNC WEAK __cxa_finalize (0) 0
+ 7: NOTYPE WEAK _Jv_RegisterClasses (0) 0
+ 8: NOTYPE WEAK _ITM_registerTMCloneTable (0) 0
+ 9: NOTYPE GLOBAL _edata (0) 0x20110
+ 10: NOTYPE GLOBAL _end (0) 0x20160
+ 11: NOTYPE GLOBAL __bss_start (0) 0x20110
+EOF
+
+cat > testfile.minsym.in <<\EOF
+ 0: NOTYPE LOCAL (0) 0
+ 1: SECTION LOCAL (0) 0x238
+ 2: SECTION LOCAL (0) 0x1fdf0
+ 3: OBJECT LOCAL __do_global_dtors_aux_fini_array_entry (0) 0x1fde8
+ 4: OBJECT LOCAL __frame_dummy_init_array_entry (0) 0x1fde0
+ 5: NOTYPE LOCAL __glink_PLTresolve (0) 0xce8
+ 6: NOTYPE LOCAL 00000011.plt_call.__libc_start_main@@GLIBC_2.3 (0) 0x8a0
+ 7: NOTYPE LOCAL 00000011.plt_call.__cxa_finalize@@GLIBC_2.3 (0) 0x8b4
+ 8: NOTYPE LOCAL __init_array_end (0) 0x1fde8
+ 9: NOTYPE LOCAL __init_array_start (0) 0x1fde0
+ 10: SECTION LOCAL (0) 0x238
+ 11: SECTION LOCAL (0) 0x24c
+ 12: SECTION LOCAL (0) 0x26c
+ 13: SECTION LOCAL (0) 0x290
+ 14: SECTION LOCAL (0) 0x2c0
+ 15: SECTION LOCAL (0) 0x3e0
+ 16: SECTION LOCAL (0) 0x488
+ 17: SECTION LOCAL (0) 0x4a0
+ 18: SECTION LOCAL (0) 0x4c0
+ 19: SECTION LOCAL (0) 0x820
+ 20: SECTION LOCAL (0) 0x850
+ 21: SECTION LOCAL (0) 0x8a0
+ 22: SECTION LOCAL (0) 0xd30
+ 23: SECTION LOCAL (0) 0xd4c
+ 24: SECTION LOCAL (0) 0xd50
+ 25: SECTION LOCAL (0) 0xd70
+ 26: SECTION LOCAL (0) 0x1fde0
+ 27: SECTION LOCAL (0) 0x1fde8
+ 28: SECTION LOCAL (0) 0x1fdf0
+ 29: SECTION LOCAL (0) 0x1fdf8
+ 30: SECTION LOCAL (0) 0x1fe20
+ 31: SECTION LOCAL (0) 0x20000
+ 32: SECTION LOCAL (0) 0x20010
+ 33: SECTION LOCAL (0) 0x200d8
+ 34: SECTION LOCAL (0) 0x20110
+ 35: SECTION LOCAL (0) 0x20158
+ 36: FUNC GLOBAL __libc_start_main (0) 0
+ 37: NOTYPE WEAK _ITM_deregisterTMCloneTable (0) 0
+ 38: NOTYPE WEAK __gmon_start__ (0) 0
+ 39: FUNC WEAK __cxa_finalize (0) 0
+ 40: NOTYPE WEAK _Jv_RegisterClasses (0) 0
+ 41: NOTYPE WEAK _ITM_registerTMCloneTable (0) 0
+ 42: NOTYPE GLOBAL _edata (0) 0x20110
+ 43: NOTYPE GLOBAL _end (0) 0x20160
+ 44: NOTYPE GLOBAL __bss_start (0) 0x20110
+EOF
+
+cat > testfile.minsym_pl.in <<\EOF
+ 0: NOTYPE LOCAL (0) 0
+ 1: SECTION LOCAL (0) 0x8001000238
+ 2: SECTION LOCAL (0) 0x800101fdf0
+ 3: OBJECT LOCAL __do_global_dtors_aux_fini_array_entry (0) 0x800101fde8
+ 4: OBJECT LOCAL __frame_dummy_init_array_entry (0) 0x800101fde0
+ 5: NOTYPE LOCAL __glink_PLTresolve (0) 0x8001000ce8
+ 6: NOTYPE LOCAL 00000011.plt_call.__libc_start_main@@GLIBC_2.3 (0) 0x80010008a0
+ 7: NOTYPE LOCAL 00000011.plt_call.__cxa_finalize@@GLIBC_2.3 (0) 0x80010008b4
+ 8: NOTYPE LOCAL __init_array_end (0) 0x800101fde8
+ 9: NOTYPE LOCAL __init_array_start (0) 0x800101fde0
+ 10: SECTION LOCAL (0) 0x8001000238
+ 11: SECTION LOCAL (0) 0x800100024c
+ 12: SECTION LOCAL (0) 0x800100026c
+ 13: SECTION LOCAL (0) 0x8001000290
+ 14: SECTION LOCAL (0) 0x80010002c0
+ 15: SECTION LOCAL (0) 0x80010003e0
+ 16: SECTION LOCAL (0) 0x8001000488
+ 17: SECTION LOCAL (0) 0x80010004a0
+ 18: SECTION LOCAL (0) 0x80010004c0
+ 19: SECTION LOCAL (0) 0x8001000820
+ 20: SECTION LOCAL (0) 0x8001000850
+ 21: SECTION LOCAL (0) 0x80010008a0
+ 22: SECTION LOCAL (0) 0x8001000d30
+ 23: SECTION LOCAL (0) 0x8001000d4c
+ 24: SECTION LOCAL (0) 0x8001000d50
+ 25: SECTION LOCAL (0) 0x8001000d70
+ 26: SECTION LOCAL (0) 0x800101fde0
+ 27: SECTION LOCAL (0) 0x800101fde8
+ 28: SECTION LOCAL (0) 0x800101fdf0
+ 29: SECTION LOCAL (0) 0x800101fdf8
+ 30: SECTION LOCAL (0) 0x800101fe20
+ 31: SECTION LOCAL (0) 0x8001020000
+ 32: SECTION LOCAL (0) 0x8001020010
+ 33: SECTION LOCAL (0) 0x80010200d8
+ 34: SECTION LOCAL (0) 0x8001020110
+ 35: SECTION LOCAL (0) 0x8001020158
+ 36: FUNC GLOBAL __libc_start_main (0) 0
+ 37: NOTYPE WEAK _ITM_deregisterTMCloneTable (0) 0
+ 38: NOTYPE WEAK __gmon_start__ (0) 0
+ 39: FUNC WEAK __cxa_finalize (0) 0
+ 40: NOTYPE WEAK _Jv_RegisterClasses (0) 0
+ 41: NOTYPE WEAK _ITM_registerTMCloneTable (0) 0
+ 42: NOTYPE GLOBAL _edata (0) 0x8001020110
+ 43: NOTYPE GLOBAL _end (0) 0x8001020160
+ 44: NOTYPE GLOBAL __bss_start (0) 0x8001020110
+EOF
+
+cat testfile.symtab.in \
+ | testrun_compare ${abs_builddir}/dwflsyms -e testfilebaztabppc64
+
+cat testfile.symtab.in \
+ | testrun_compare ${abs_builddir}/dwflsyms -e testfilebazdbgppc64
+
+cat testfile.symtab_pl.in \
+ | testrun_compare ${abs_builddir}/dwflsyms -e testfilebazdbgppc64_pl
+
+sed s/0x8001/0x4200/g testfile.symtab_pl.in \
+ | testrun_compare ${abs_builddir}/dwflsyms -e testfilebazdbgppc64_plr
+
+cat testfile.dynsym.in \
+ | testrun_compare ${abs_builddir}/dwflsyms -e testfilebazdynppc64
+
+cat testfile.symtab.in \
+ | testrun_compare ${abs_builddir}/dwflsyms -e testfilebazmdbppc64
+
+cat testfile.minsym.in \
+ | testrun_compare ${abs_builddir}/dwflsyms -e testfilebazminppc64
+
+cat testfile.minsym_pl.in \
+ | testrun_compare ${abs_builddir}/dwflsyms -e testfilebazminppc64_pl
+
+sed s/0x8001/0x4200/g testfile.minsym_pl.in \
+ | testrun_compare ${abs_builddir}/dwflsyms -e testfilebazminppc64_plr
+
exit 0
diff --git a/tests/run-funcretval.sh b/tests/run-funcretval.sh
new file mode 100755
index 00000000..779bd473
--- /dev/null
+++ b/tests/run-funcretval.sh
@@ -0,0 +1,153 @@
+#! /bin/sh
+# 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 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/>.
+
+. $srcdir/test-subr.sh
+
+# The following files were obtaining by compiling funcretval_test.c
+# from this directory as follows:
+#
+# gcc -g funcretval_test.c -o funcretval_test_<YOURARCH>
+#
+# Pass -DFLOAT128 if the given arch supports __float128.
+
+testfiles funcretval_test_aarch64
+
+# funcretval_test_aarch64 was built with additional flag:
+# -DAARCH64_BUG_1032854
+# hence no fun_vec_double_8.
+testrun_compare ${abs_top_builddir}/tests/funcretval \
+ -e funcretval_test_aarch64 <<\EOF
+() fun_char: return value location: {0x50, 0}
+() fun_short: return value location: {0x50, 0}
+() fun_int: return value location: {0x50, 0}
+() fun_ptr: return value location: {0x50, 0}
+() fun_iptr: return value location: {0x50, 0}
+() fun_long: return value location: {0x50, 0}
+() fun_int128: return value location: {0x50, 0} {0x93, 0x8} {0x51, 0} {0x93, 0x8}
+() fun_large_struct1: return value location: {0x70, 0}
+() fun_large_struct2: return value location: {0x70, 0}
+() fun_float: return value location: {0x90, 0x40}
+() fun_float_complex: return value location: {0x90, 0x40} {0x93, 0x4} {0x90, 0x41} {0x93, 0x4}
+() fun_double: return value location: {0x90, 0x40}
+() fun_double_complex: return value location: {0x90, 0x40} {0x93, 0x8} {0x90, 0x41} {0x93, 0x8}
+() fun_long_double: return value location: {0x90, 0x40}
+() fun_long_double_complex: return value location: {0x90, 0x40} {0x93, 0x10} {0x90, 0x41} {0x93, 0x10}
+() fun_vec_char_8: return value location: {0x90, 0x40}
+() fun_vec_short_8: return value location: {0x90, 0x40}
+() fun_vec_int_8: return value location: {0x90, 0x40}
+() fun_vec_long_8: return value location: {0x90, 0x40}
+() fun_vec_float_8: return value location: {0x90, 0x40}
+() fun_vec_char_16: return value location: {0x90, 0x40}
+() fun_vec_short_16: return value location: {0x90, 0x40}
+() fun_vec_int_16: return value location: {0x90, 0x40}
+() fun_vec_long_16: return value location: {0x90, 0x40}
+() fun_vec_int128_16: return value location: {0x90, 0x40}
+() fun_vec_float_16: return value location: {0x90, 0x40}
+() fun_vec_double_16: return value location: {0x90, 0x40}
+() fun_hfa1_float: return value location: {0x90, 0x40}
+() fun_hfa1_double: return value location: {0x90, 0x40}
+() fun_hfa1_long_double: return value location: {0x90, 0x40}
+() fun_hfa1_float_a: return value location: {0x90, 0x40}
+() fun_hfa1_double_a: return value location: {0x90, 0x40}
+() fun_hfa1_long_double_a: return value location: {0x90, 0x40}
+() fun_hfa2_float: return value location: {0x90, 0x40} {0x93, 0x4} {0x90, 0x41} {0x93, 0x4}
+() fun_hfa2_double: return value location: {0x90, 0x40} {0x93, 0x8} {0x90, 0x41} {0x93, 0x8}
+() fun_hfa2_long_double: return value location: {0x90, 0x40} {0x93, 0x10} {0x90, 0x41} {0x93, 0x10}
+() fun_hfa2_float_a: return value location: {0x90, 0x40} {0x93, 0x4} {0x90, 0x41} {0x93, 0x4}
+() fun_hfa2_double_a: return value location: {0x90, 0x40} {0x93, 0x8} {0x90, 0x41} {0x93, 0x8}
+() fun_hfa2_long_double_a: return value location: {0x90, 0x40} {0x93, 0x10} {0x90, 0x41} {0x93, 0x10}
+() fun_hfa3_float: return value location: {0x90, 0x40} {0x93, 0x4} {0x90, 0x41} {0x93, 0x4} {0x90, 0x42} {0x93, 0x4}
+() fun_hfa3_double: return value location: {0x90, 0x40} {0x93, 0x8} {0x90, 0x41} {0x93, 0x8} {0x90, 0x42} {0x93, 0x8}
+() fun_hfa3_long_double: return value location: {0x90, 0x40} {0x93, 0x10} {0x90, 0x41} {0x93, 0x10} {0x90, 0x42} {0x93, 0x10}
+() fun_hfa3_float_a: return value location: {0x90, 0x40} {0x93, 0x4} {0x90, 0x41} {0x93, 0x4} {0x90, 0x42} {0x93, 0x4}
+() fun_hfa3_double_a: return value location: {0x90, 0x40} {0x93, 0x8} {0x90, 0x41} {0x93, 0x8} {0x90, 0x42} {0x93, 0x8}
+() fun_hfa3_long_double_a: return value location: {0x90, 0x40} {0x93, 0x10} {0x90, 0x41} {0x93, 0x10} {0x90, 0x42} {0x93, 0x10}
+() fun_hfa4_float: return value location: {0x90, 0x40} {0x93, 0x4} {0x90, 0x41} {0x93, 0x4} {0x90, 0x42} {0x93, 0x4} {0x90, 0x43} {0x93, 0x4}
+() fun_hfa4_double: return value location: {0x90, 0x40} {0x93, 0x8} {0x90, 0x41} {0x93, 0x8} {0x90, 0x42} {0x93, 0x8} {0x90, 0x43} {0x93, 0x8}
+() fun_hfa4_long_double: return value location: {0x90, 0x40} {0x93, 0x10} {0x90, 0x41} {0x93, 0x10} {0x90, 0x42} {0x93, 0x10} {0x90, 0x43} {0x93, 0x10}
+() fun_hfa4_float_a: return value location: {0x90, 0x40} {0x93, 0x4} {0x90, 0x41} {0x93, 0x4} {0x90, 0x42} {0x93, 0x4} {0x90, 0x43} {0x93, 0x4}
+() fun_hfa4_double_a: return value location: {0x90, 0x40} {0x93, 0x8} {0x90, 0x41} {0x93, 0x8} {0x90, 0x42} {0x93, 0x8} {0x90, 0x43} {0x93, 0x8}
+() fun_hfa4_long_double_a: return value location: {0x90, 0x40} {0x93, 0x10} {0x90, 0x41} {0x93, 0x10} {0x90, 0x42} {0x93, 0x10} {0x90, 0x43} {0x93, 0x10}
+() fun_nfa5_float: return value location: {0x70, 0}
+() fun_nfa5_double: return value location: {0x70, 0}
+() fun_nfa5_long_double: return value location: {0x70, 0}
+() fun_nfa5_float_a: return value location: {0x70, 0}
+() fun_nfa5_double_a: return value location: {0x70, 0}
+() fun_nfa5_long_double_a: return value location: {0x70, 0}
+() fun_hva1_vec_char_8: return value location: {0x90, 0x40}
+() fun_hva1_vec_short_8: return value location: {0x90, 0x40}
+() fun_hva1_vec_int_8: return value location: {0x90, 0x40}
+() fun_hva1_vec_long_8: return value location: {0x90, 0x40}
+() fun_hva1_vec_float_8: return value location: {0x90, 0x40}
+() fun_hva1_vec_double_8: return value location: {0x90, 0x40}
+() fun_hva1_vec_char_16_t: return value location: {0x90, 0x40}
+() fun_hva1_vec_short_16_t: return value location: {0x90, 0x40}
+() fun_hva1_vec_int_16_t: return value location: {0x90, 0x40}
+() fun_hva1_vec_long_16_t: return value location: {0x90, 0x40}
+() fun_hva1_vec_int128_16_t: return value location: {0x90, 0x40}
+() fun_hva1_vec_float_16_t: return value location: {0x90, 0x40}
+() fun_hva1_vec_double_16_t: return value location: {0x90, 0x40}
+() fun_hva2_vec_char_8: return value location: {0x90, 0x40} {0x93, 0x8} {0x90, 0x41} {0x93, 0x8}
+() fun_hva2_vec_short_8: return value location: {0x90, 0x40} {0x93, 0x8} {0x90, 0x41} {0x93, 0x8}
+() fun_hva2_vec_int_8: return value location: {0x90, 0x40} {0x93, 0x8} {0x90, 0x41} {0x93, 0x8}
+() fun_hva2_vec_long_8: return value location: {0x90, 0x40} {0x93, 0x8} {0x90, 0x41} {0x93, 0x8}
+() fun_hva2_vec_float_8: return value location: {0x90, 0x40} {0x93, 0x8} {0x90, 0x41} {0x93, 0x8}
+() fun_hva2_vec_double_8: return value location: {0x90, 0x40} {0x93, 0x8} {0x90, 0x41} {0x93, 0x8}
+() fun_hva2_vec_char_16_t: return value location: {0x90, 0x40} {0x93, 0x10} {0x90, 0x41} {0x93, 0x10}
+() fun_hva2_vec_short_16_t: return value location: {0x90, 0x40} {0x93, 0x10} {0x90, 0x41} {0x93, 0x10}
+() fun_hva2_vec_int_16_t: return value location: {0x90, 0x40} {0x93, 0x10} {0x90, 0x41} {0x93, 0x10}
+() fun_hva2_vec_long_16_t: return value location: {0x90, 0x40} {0x93, 0x10} {0x90, 0x41} {0x93, 0x10}
+() fun_hva2_vec_int128_16_t: return value location: {0x90, 0x40} {0x93, 0x10} {0x90, 0x41} {0x93, 0x10}
+() fun_hva2_vec_float_16_t: return value location: {0x90, 0x40} {0x93, 0x10} {0x90, 0x41} {0x93, 0x10}
+() fun_hva2_vec_double_16_t: return value location: {0x90, 0x40} {0x93, 0x10} {0x90, 0x41} {0x93, 0x10}
+() fun_hva3_vec_char_8: return value location: {0x90, 0x40} {0x93, 0x8} {0x90, 0x41} {0x93, 0x8} {0x90, 0x42} {0x93, 0x8}
+() fun_hva3_vec_short_8: return value location: {0x90, 0x40} {0x93, 0x8} {0x90, 0x41} {0x93, 0x8} {0x90, 0x42} {0x93, 0x8}
+() fun_hva3_vec_int_8: return value location: {0x90, 0x40} {0x93, 0x8} {0x90, 0x41} {0x93, 0x8} {0x90, 0x42} {0x93, 0x8}
+() fun_hva3_vec_long_8: return value location: {0x90, 0x40} {0x93, 0x8} {0x90, 0x41} {0x93, 0x8} {0x90, 0x42} {0x93, 0x8}
+() fun_hva3_vec_float_8: return value location: {0x90, 0x40} {0x93, 0x8} {0x90, 0x41} {0x93, 0x8} {0x90, 0x42} {0x93, 0x8}
+() fun_hva3_vec_double_8: return value location: {0x90, 0x40} {0x93, 0x8} {0x90, 0x41} {0x93, 0x8} {0x90, 0x42} {0x93, 0x8}
+() fun_hva3_vec_char_16_t: return value location: {0x90, 0x40} {0x93, 0x10} {0x90, 0x41} {0x93, 0x10} {0x90, 0x42} {0x93, 0x10}
+() fun_hva3_vec_short_16_t: return value location: {0x90, 0x40} {0x93, 0x10} {0x90, 0x41} {0x93, 0x10} {0x90, 0x42} {0x93, 0x10}
+() fun_hva3_vec_int_16_t: return value location: {0x90, 0x40} {0x93, 0x10} {0x90, 0x41} {0x93, 0x10} {0x90, 0x42} {0x93, 0x10}
+() fun_hva3_vec_long_16_t: return value location: {0x90, 0x40} {0x93, 0x10} {0x90, 0x41} {0x93, 0x10} {0x90, 0x42} {0x93, 0x10}
+() fun_hva3_vec_int128_16_t: return value location: {0x90, 0x40} {0x93, 0x10} {0x90, 0x41} {0x93, 0x10} {0x90, 0x42} {0x93, 0x10}
+() fun_hva3_vec_float_16_t: return value location: {0x90, 0x40} {0x93, 0x10} {0x90, 0x41} {0x93, 0x10} {0x90, 0x42} {0x93, 0x10}
+() fun_hva3_vec_double_16_t: return value location: {0x90, 0x40} {0x93, 0x10} {0x90, 0x41} {0x93, 0x10} {0x90, 0x42} {0x93, 0x10}
+() fun_hva4_vec_char_8: return value location: {0x90, 0x40} {0x93, 0x8} {0x90, 0x41} {0x93, 0x8} {0x90, 0x42} {0x93, 0x8} {0x90, 0x43} {0x93, 0x8}
+() fun_hva4_vec_short_8: return value location: {0x90, 0x40} {0x93, 0x8} {0x90, 0x41} {0x93, 0x8} {0x90, 0x42} {0x93, 0x8} {0x90, 0x43} {0x93, 0x8}
+() fun_hva4_vec_int_8: return value location: {0x90, 0x40} {0x93, 0x8} {0x90, 0x41} {0x93, 0x8} {0x90, 0x42} {0x93, 0x8} {0x90, 0x43} {0x93, 0x8}
+() fun_hva4_vec_long_8: return value location: {0x90, 0x40} {0x93, 0x8} {0x90, 0x41} {0x93, 0x8} {0x90, 0x42} {0x93, 0x8} {0x90, 0x43} {0x93, 0x8}
+() fun_hva4_vec_float_8: return value location: {0x90, 0x40} {0x93, 0x8} {0x90, 0x41} {0x93, 0x8} {0x90, 0x42} {0x93, 0x8} {0x90, 0x43} {0x93, 0x8}
+() fun_hva4_vec_double_8: return value location: {0x90, 0x40} {0x93, 0x8} {0x90, 0x41} {0x93, 0x8} {0x90, 0x42} {0x93, 0x8} {0x90, 0x43} {0x93, 0x8}
+() fun_hva4_vec_char_16_t: return value location: {0x90, 0x40} {0x93, 0x10} {0x90, 0x41} {0x93, 0x10} {0x90, 0x42} {0x93, 0x10} {0x90, 0x43} {0x93, 0x10}
+() fun_hva4_vec_short_16_t: return value location: {0x90, 0x40} {0x93, 0x10} {0x90, 0x41} {0x93, 0x10} {0x90, 0x42} {0x93, 0x10} {0x90, 0x43} {0x93, 0x10}
+() fun_hva4_vec_int_16_t: return value location: {0x90, 0x40} {0x93, 0x10} {0x90, 0x41} {0x93, 0x10} {0x90, 0x42} {0x93, 0x10} {0x90, 0x43} {0x93, 0x10}
+() fun_hva4_vec_long_16_t: return value location: {0x90, 0x40} {0x93, 0x10} {0x90, 0x41} {0x93, 0x10} {0x90, 0x42} {0x93, 0x10} {0x90, 0x43} {0x93, 0x10}
+() fun_hva4_vec_int128_16_t: return value location: {0x90, 0x40} {0x93, 0x10} {0x90, 0x41} {0x93, 0x10} {0x90, 0x42} {0x93, 0x10} {0x90, 0x43} {0x93, 0x10}
+() fun_hva4_vec_float_16_t: return value location: {0x90, 0x40} {0x93, 0x10} {0x90, 0x41} {0x93, 0x10} {0x90, 0x42} {0x93, 0x10} {0x90, 0x43} {0x93, 0x10}
+() fun_hva4_vec_double_16_t: return value location: {0x90, 0x40} {0x93, 0x10} {0x90, 0x41} {0x93, 0x10} {0x90, 0x42} {0x93, 0x10} {0x90, 0x43} {0x93, 0x10}
+() fun_mixed_hfa3_cff: return value location: {0x90, 0x40} {0x93, 0x4} {0x90, 0x41} {0x93, 0x4} {0x90, 0x42} {0x93, 0x4}
+() fun_mixed_hfa3_cdd: return value location: {0x90, 0x40} {0x93, 0x8} {0x90, 0x41} {0x93, 0x8} {0x90, 0x42} {0x93, 0x8}
+() fun_mixed_hfa3_cldld: return value location: {0x90, 0x40} {0x93, 0x10} {0x90, 0x41} {0x93, 0x10} {0x90, 0x42} {0x93, 0x10}
+() fun_mixed_hfa3_fcf: return value location: {0x90, 0x40} {0x93, 0x4} {0x90, 0x41} {0x93, 0x4} {0x90, 0x42} {0x93, 0x4}
+() fun_mixed_hfa3_dcd: return value location: {0x90, 0x40} {0x93, 0x8} {0x90, 0x41} {0x93, 0x8} {0x90, 0x42} {0x93, 0x8}
+() fun_mixed_hfa3_ldcld: return value location: {0x90, 0x40} {0x93, 0x10} {0x90, 0x41} {0x93, 0x10} {0x90, 0x42} {0x93, 0x10}
+() fun_mixed_hfa2_fltsht_t: return value location: {0x90, 0x40} {0x93, 0x8} {0x90, 0x41} {0x93, 0x8}
+() main: return value location: {0x50, 0}
+EOF
+
+exit 0
diff --git a/tests/run-readelf-mixed-corenote.sh b/tests/run-readelf-mixed-corenote.sh
index 9a438095..c176e283 100755
--- a/tests/run-readelf-mixed-corenote.sh
+++ b/tests/run-readelf-mixed-corenote.sh
@@ -285,4 +285,144 @@ Note segment of 1476 bytes at offset 0x430:
3e001ba000-3e001bc000 001ba000 8192 /usr/lib64/libc-2.17.so
EOF
+# To reproduce this core dump, do this on an aarch64 machine:
+# $ gcc -x c <(echo 'int main () { return *(int *)0x12345678; }')
+# $ ./a.out
+testfiles testfile_aarch64_core
+testrun_compare ${abs_top_builddir}/src/readelf -n testfile_aarch64_core <<\EOF
+
+Note segment of 2512 bytes at offset 0x270:
+ Owner Data size Type
+ CORE 392 PRSTATUS
+ info.si_signo: 11, info.si_code: 0, info.si_errno: 0, cursig: 11
+ sigpend: <>
+ sighold: <>
+ pid: 16547, ppid: 3822, pgrp: 16547, sid: 3822
+ utime: 0.010000, stime: 0.000000, cutime: 0.000000, cstime: 0.000000
+ pc: 0x0000000000400548, pstate: 0x0000000060000000, fpvalid: 1
+ x0: 305419896 x1: 548685596648
+ x2: 548685596664 x3: 4195648
+ x4: 0 x5: 548536191688
+ x6: 0 x7: -6341196323062964528
+ x8: 135 x9: 4294967295
+ x10: 4195026 x11: 184256
+ x12: 144 x13: 15
+ x14: 548536635328 x15: 0
+ x16: 548534815304 x17: 4262024
+ x18: 548685596000 x19: 0
+ x20: 0 x21: 4195296
+ x22: 0 x23: 0
+ x24: 0 x25: 0
+ x26: 0 x27: 0
+ x28: 0 x29: 548685596320
+ x30: 548534815544 sp: 0x0000007fc035c6a0
+ CORE 136 PRPSINFO
+ state: 0, sname: R, zomb: 0, nice: 0, flag: 0x0000000000400400
+ uid: 0, gid: 0, pid: 16547, ppid: 3822, pgrp: 16547, sid: 3822
+ fname: a.out, psargs: ./a.out
+ CORE 128 SIGINFO
+ si_signo: 11, si_errno: 0, si_code: 1
+ fault address: 0x12345678
+ CORE 304 AUXV
+ SYSINFO_EHDR: 0x7fb7500000
+ HWCAP: 0x3
+ PAGESZ: 65536
+ CLKTCK: 100
+ PHDR: 0x400040
+ PHENT: 56
+ PHNUM: 7
+ BASE: 0x7fb7520000
+ FLAGS: 0
+ ENTRY: 0x4003e0
+ UID: 0
+ EUID: 0
+ GID: 0
+ EGID: 0
+ SECURE: 0
+ RANDOM: 0x7fc035c9e8
+ EXECFN: 0x7fc035fff0
+ PLATFORM: 0x7fc035c9f8
+ NULL
+ CORE 306 FILE
+ 6 files:
+ 00400000-00410000 00000000 65536 /root/elfutils/build/a.out
+ 00410000-00420000 00000000 65536 /root/elfutils/build/a.out
+ 7fb7370000-7fb74d0000 00000000 1441792 /usr/lib64/libc-2.17.so
+ 7fb74d0000-7fb74f0000 00150000 131072 /usr/lib64/libc-2.17.so
+ 7fb7520000-7fb7540000 00000000 131072 /usr/lib64/ld-2.17.so
+ 7fb7540000-7fb7550000 00010000 65536 /usr/lib64/ld-2.17.so
+ CORE 528 FPREGSET
+ fpsr: 0x00000000, fpcr: 0x00000000
+ v0: 0x00000000000af54b000000000000fe02
+ v1: 0x00000000000000000000000000000000
+ v2: 0x00000000000000000000000000000000
+ v3: 0x00000000000000000000000000000000
+ v4: 0x00000000000000000000000000000000
+ v5: 0x00000000000000000000000000000000
+ v6: 0x00000000000000000000000000000000
+ v7: 0x00000000000000000000000000000000
+ v8: 0x00000000000000000000000000000000
+ v9: 0x00000000000000000000000000000000
+ v10: 0x00000000000000000000000000000000
+ v11: 0x00000000000000000000000000000000
+ v12: 0x00000000000000000000000000000000
+ v13: 0x00000000000000000000000000000000
+ v14: 0x00000000000000000000000000000000
+ v15: 0x00000000000000000000000000000000
+ v16: 0x00000000000000000000000000000000
+ v17: 0x00000000000000000000000000000000
+ v18: 0x00000000000000000000000000000000
+ v19: 0x00000000000000000000000000000000
+ v20: 0x00000000000000000000000000000000
+ v21: 0x00000000000000000000000000000000
+ v22: 0x00000000000000000000000000000000
+ v23: 0x00000000000000000000000000000000
+ v24: 0x00000000000000000000000000000000
+ v25: 0x00000000000000000000000000000000
+ v26: 0x00000000000000000000000000000000
+ v27: 0x00000000000000000000000000000000
+ v28: 0x00000000000000000000000000000000
+ v29: 0x00000000000000000000000000000000
+ v30: 0x00000000000000000000000000000000
+ v31: 0x00000000000000000000000000000000
+ LINUX 8 ARM_TLS
+ tls: 0x0000007fb73606f0
+ LINUX 264 ARM_HW_BREAK
+ dbg_info: 0x00000610
+ DBGBVR0_EL1: 0x0000000000000000, DBGBCR0_EL1: 0x00000000
+ DBGBVR1_EL1: 0x0000000000000000, DBGBCR1_EL1: 0x00000000
+ DBGBVR2_EL1: 0x0000000000000000, DBGBCR2_EL1: 0x00000000
+ DBGBVR3_EL1: 0x0000000000000000, DBGBCR3_EL1: 0x00000000
+ DBGBVR4_EL1: 0x0000000000000000, DBGBCR4_EL1: 0x00000000
+ DBGBVR5_EL1: 0x0000000000000000, DBGBCR5_EL1: 0x00000000
+ DBGBVR6_EL1: 0x0000000000000000, DBGBCR6_EL1: 0x00000000
+ DBGBVR7_EL1: 0x0000000000000000, DBGBCR7_EL1: 0x00000000
+ DBGBVR8_EL1: 0x0000000000000000, DBGBCR8_EL1: 0x00000000
+ DBGBVR9_EL1: 0x0000000000000000, DBGBCR9_EL1: 0x00000000
+ DBGBVR10_EL1: 0x0000000000000000, DBGBCR10_EL1: 0x00000000
+ DBGBVR11_EL1: 0x0000000000000000, DBGBCR11_EL1: 0x00000000
+ DBGBVR12_EL1: 0x0000000000000000, DBGBCR12_EL1: 0x00000000
+ DBGBVR13_EL1: 0x0000000000000000, DBGBCR13_EL1: 0x00000000
+ DBGBVR14_EL1: 0x0000000000000000, DBGBCR14_EL1: 0x00000000
+ DBGBVR15_EL1: 0x0000000000000000, DBGBCR15_EL1: 0x00000000
+ LINUX 264 ARM_HW_WATCH
+ dbg_info: 0x00000610
+ DBGWVR0_EL1: 0x0000000000000000, DBGWCR0_EL1: 0x00000000
+ DBGWVR1_EL1: 0x0000000000000000, DBGWCR1_EL1: 0x00000000
+ DBGWVR2_EL1: 0x0000000000000000, DBGWCR2_EL1: 0x00000000
+ DBGWVR3_EL1: 0x0000000000000000, DBGWCR3_EL1: 0x00000000
+ DBGWVR4_EL1: 0x0000000000000000, DBGWCR4_EL1: 0x00000000
+ DBGWVR5_EL1: 0x0000000000000000, DBGWCR5_EL1: 0x00000000
+ DBGWVR6_EL1: 0x0000000000000000, DBGWCR6_EL1: 0x00000000
+ DBGWVR7_EL1: 0x0000000000000000, DBGWCR7_EL1: 0x00000000
+ DBGWVR8_EL1: 0x0000000000000000, DBGWCR8_EL1: 0x00000000
+ DBGWVR9_EL1: 0x0000000000000000, DBGWCR9_EL1: 0x00000000
+ DBGWVR10_EL1: 0x0000000000000000, DBGWCR10_EL1: 0x00000000
+ DBGWVR11_EL1: 0x0000000000000000, DBGWCR11_EL1: 0x00000000
+ DBGWVR12_EL1: 0x0000000000000000, DBGWCR12_EL1: 0x00000000
+ DBGWVR13_EL1: 0x0000000000000000, DBGWCR13_EL1: 0x00000000
+ DBGWVR14_EL1: 0x0000000000000000, DBGWCR14_EL1: 0x00000000
+ DBGWVR15_EL1: 0x0000000000000000, DBGWCR15_EL1: 0x00000000
+EOF
+
exit 0
diff --git a/tests/run-readelf-s.sh b/tests/run-readelf-s.sh
index 4373b5f0..931516da 100755
--- a/tests/run-readelf-s.sh
+++ b/tests/run-readelf-s.sh
@@ -210,44 +210,49 @@ EOF
cat > testfile.minsym.in <<\EOF
-Symbol table [27] '.symtab' contains 35 entries:
- 31 local symbols String table: [28] '.strtab'
+Symbol table [28] '.symtab' contains 40 entries:
+ 36 local symbols String table: [29] '.strtab'
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UNDEF
- 1: 00000000004003bc 0 FUNC LOCAL DEFAULT 13 call_gmon_start
- 2: 00000000004003e0 0 FUNC LOCAL DEFAULT 13 __do_global_dtors_aux
- 3: 0000000000400450 0 FUNC LOCAL DEFAULT 13 frame_dummy
- 4: 0000000000400580 0 FUNC LOCAL DEFAULT 13 __do_global_ctors_aux
- 5: 0000000000400498 18 FUNC LOCAL DEFAULT 13 foo
- 6: 0000000000400200 0 SECTION LOCAL DEFAULT 1
- 7: 000000000040021c 0 SECTION LOCAL DEFAULT 2
- 8: 000000000040023c 0 SECTION LOCAL DEFAULT 3
- 9: 0000000000400260 0 SECTION LOCAL DEFAULT 4
- 10: 0000000000400280 0 SECTION LOCAL DEFAULT 5
- 11: 00000000004002c8 0 SECTION LOCAL DEFAULT 6
- 12: 0000000000400300 0 SECTION LOCAL DEFAULT 7
- 13: 0000000000400308 0 SECTION LOCAL DEFAULT 8
- 14: 0000000000400328 0 SECTION LOCAL DEFAULT 9
- 15: 0000000000400340 0 SECTION LOCAL DEFAULT 10
- 16: 0000000000400358 0 SECTION LOCAL DEFAULT 11
- 17: 0000000000400370 0 SECTION LOCAL DEFAULT 12
- 18: 0000000000400390 0 SECTION LOCAL DEFAULT 13
- 19: 00000000004005b8 0 SECTION LOCAL DEFAULT 14
- 20: 00000000004005c8 0 SECTION LOCAL DEFAULT 15
- 21: 00000000004005d8 0 SECTION LOCAL DEFAULT 16
- 22: 0000000000400610 0 SECTION LOCAL DEFAULT 17
- 23: 00000000006006d0 0 SECTION LOCAL DEFAULT 18
- 24: 00000000006006e0 0 SECTION LOCAL DEFAULT 19
- 25: 00000000006006f0 0 SECTION LOCAL DEFAULT 20
- 26: 00000000006006f8 0 SECTION LOCAL DEFAULT 21
- 27: 0000000000600888 0 SECTION LOCAL DEFAULT 22
- 28: 0000000000600890 0 SECTION LOCAL DEFAULT 23
- 29: 00000000006008b0 0 SECTION LOCAL DEFAULT 24
- 30: 00000000006008c0 0 SECTION LOCAL DEFAULT 25
- 31: 0000000000400390 0 FUNC GLOBAL DEFAULT 13 _start
- 32: 00000000004004aa 44 FUNC GLOBAL DEFAULT 13 bar
- 33: 00000000004005b8 0 FUNC GLOBAL DEFAULT 14 _fini
- 34: 0000000000400358 0 FUNC GLOBAL DEFAULT 11 _init
+ 1: 0000000000000710 0 FUNC LOCAL DEFAULT 13 deregister_tm_clones
+ 2: 0000000000000740 0 FUNC LOCAL DEFAULT 13 register_tm_clones
+ 3: 0000000000000780 0 FUNC LOCAL DEFAULT 13 __do_global_dtors_aux
+ 4: 0000000000200dd8 0 OBJECT LOCAL DEFAULT 19 __do_global_dtors_aux_fini_array_entry
+ 5: 00000000000007c0 0 FUNC LOCAL DEFAULT 13 frame_dummy
+ 6: 0000000000200dd0 0 OBJECT LOCAL DEFAULT 18 __frame_dummy_init_array_entry
+ 7: 0000000000000814 20 FUNC LOCAL DEFAULT 13 foo
+ 8: 0000000000200dd8 0 NOTYPE LOCAL DEFAULT 18 __init_array_end
+ 9: 0000000000200dd0 0 NOTYPE LOCAL DEFAULT 18 __init_array_start
+ 10: 0000000000000238 0 SECTION LOCAL DEFAULT 1
+ 11: 0000000000000254 0 SECTION LOCAL DEFAULT 2
+ 12: 0000000000000274 0 SECTION LOCAL DEFAULT 3
+ 13: 0000000000000298 0 SECTION LOCAL DEFAULT 4
+ 14: 00000000000002d8 0 SECTION LOCAL DEFAULT 5
+ 15: 0000000000000428 0 SECTION LOCAL DEFAULT 6
+ 16: 00000000000004f2 0 SECTION LOCAL DEFAULT 7
+ 17: 0000000000000510 0 SECTION LOCAL DEFAULT 8
+ 18: 0000000000000530 0 SECTION LOCAL DEFAULT 9
+ 19: 0000000000000638 0 SECTION LOCAL DEFAULT 10
+ 20: 0000000000000680 0 SECTION LOCAL DEFAULT 11
+ 21: 00000000000006a0 0 SECTION LOCAL DEFAULT 12
+ 22: 00000000000006e0 0 SECTION LOCAL DEFAULT 13
+ 23: 00000000000008f4 0 SECTION LOCAL DEFAULT 14
+ 24: 0000000000000900 0 SECTION LOCAL DEFAULT 15
+ 25: 0000000000000904 0 SECTION LOCAL DEFAULT 16
+ 26: 0000000000000948 0 SECTION LOCAL DEFAULT 17
+ 27: 0000000000200dd0 0 SECTION LOCAL DEFAULT 18
+ 28: 0000000000200dd8 0 SECTION LOCAL DEFAULT 19
+ 29: 0000000000200de0 0 SECTION LOCAL DEFAULT 20
+ 30: 0000000000200de8 0 SECTION LOCAL DEFAULT 21
+ 31: 0000000000200df0 0 SECTION LOCAL DEFAULT 22
+ 32: 0000000000200fc0 0 SECTION LOCAL DEFAULT 23
+ 33: 0000000000201000 0 SECTION LOCAL DEFAULT 24
+ 34: 0000000000201030 0 SECTION LOCAL DEFAULT 25
+ 35: 000000000020103c 0 SECTION LOCAL DEFAULT 26
+ 36: 0000000000000828 44 FUNC GLOBAL DEFAULT 13 bar
+ 37: 00000000000008f4 0 FUNC GLOBAL DEFAULT 14 _fini
+ 38: 00000000000006e0 0 FUNC GLOBAL DEFAULT 13 _start
+ 39: 0000000000000680 0 FUNC GLOBAL DEFAULT 11 _init
EOF
cat testfile.dynsym.in testfile.symtab.in \
diff --git a/tests/run-strip-reloc.sh b/tests/run-strip-reloc.sh
index 221eefbf..a3245fd8 100755
--- a/tests/run-strip-reloc.sh
+++ b/tests/run-strip-reloc.sh
@@ -1,5 +1,5 @@
#! /bin/sh
-# Copyright (C) 2011 Red Hat, Inc.
+# Copyright (C) 2011, 2013 Red Hat, Inc.
# This file is part of elfutils.
#
# This file is free software; you can redistribute it and/or modify
@@ -17,7 +17,8 @@
. $srcdir/test-subr.sh
-testfiles hello_i386.ko hello_x86_64.ko hello_ppc64.ko hello_s390.ko
+testfiles hello_i386.ko hello_x86_64.ko hello_ppc64.ko hello_s390.ko \
+ hello_aarch64.ko
tempfiles readelf.out readelf.out1 readelf.out2
tempfiles out.stripped1 out.debug1 out.stripped2 out.debug2
@@ -100,6 +101,7 @@ runtest hello_i386.ko 1
runtest hello_x86_64.ko 1
runtest hello_ppc64.ko 1
runtest hello_s390.ko 1
+runtest hello_aarch64.ko 1
# self test, shouldn't impact non-ET_REL files at all.
runtest ${abs_top_builddir}/src/strip 0
diff --git a/tests/run-typeiter.sh b/tests/run-typeiter.sh
index b85839ce..605ee2a2 100755
--- a/tests/run-typeiter.sh
+++ b/tests/run-typeiter.sh
@@ -47,4 +47,8 @@ testrun_compare ${abs_builddir}/typeiter testfile59 <<\EOF
ok
EOF
+testrun_compare ${abs_builddir}/typeiter2 testfile59 <<\EOF
+ok
+EOF
+
exit 0
diff --git a/tests/run-unstrip-M.sh b/tests/run-unstrip-M.sh
new file mode 100755
index 00000000..614a8aa5
--- /dev/null
+++ b/tests/run-unstrip-M.sh
@@ -0,0 +1,51 @@
+#! /bin/sh
+# 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 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/>.
+
+. $srcdir/test-subr.sh
+
+# Linux /proc/PID/maps file with some non-file entries (and fake exe/lib names).
+tempfiles testmaps
+cat > testmaps <<EOF
+00400000-024aa000 r-xp 00000000 08:02 159659 /opt/TestBins/bin/arwijn
+026aa000-026b2000 rwxp 020aa000 08:02 159659 /opt/TestBins/bin/arwijn
+026b2000-026bf000 rwxp 00000000 00:00 0
+0335a000-03e6f000 rwxp 00000000 00:00 0 [heap]
+2b7b38282000-2b7b38302000 rwxs 00000000 00:06 493872 socket:[493872]
+2b7b38302000-2b7b38312000 rwxs 00000000 00:06 493872 socket:[493872]
+2b7b38312000-2b7b38b12000 r-xs 00000000 00:06 493872 socket:[493872]
+2b7b38b12000-2b7b38b22000 rwxs 00000000 00:06 493872 socket:[493872]
+2b7b38b22000-2b7b39322000 rwxs 00000000 00:06 493872 socket:[493872]
+2b7b4439f000-2b7b45ea1000 rwxp 00000000 00:00 0
+7f31e7d9f000-7f31e7f29000 r-xp 00000000 fd:00 917531 /lib64/libc-1.13.so
+7f31e7f29000-7f31e8128000 ---p 0018a000 fd:00 917531 /lib64/libc-1.13.so
+7f31e8128000-7f31e812c000 r--p 00189000 fd:00 917531 /lib64/libc-1.13.so
+7f31e812c000-7f31e812d000 rw-p 0018d000 fd:00 917531 /lib64/libc-1.13.so
+7f31e812d000-7f31e8132000 rw-p 00000000 00:00 0
+7f31ea3f9000-7f31ea3fc000 rw-s 00000000 00:09 3744 anon_inode:kvm-vcpu
+7f31ea3fc000-7f31ea3ff000 rw-s 00000000 00:09 3744 anon_inode:kvm-vcpu
+7f31ea400000-7f31ea402000 rw-p 00000000 00:00 0
+7fff26cf7000-7fff26d0c000 rwxp 00000000 00:00 0 [stack]
+7fff26dff000-7fff26e00000 r-xp 00000000 00:00 0 [vdso]
+ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
+EOF
+
+testrun_compare ${abs_top_builddir}/src/unstrip -n -M testmaps <<\EOF
+0x400000+0x22b2000 - - - /opt/TestBins/bin/arwijn
+0x7f31e7d9f000+0x38e000 - - - /lib64/libc-1.13.so
+EOF
+
+exit 0
diff --git a/tests/test-offset-loop.alt.bz2 b/tests/test-offset-loop.alt.bz2
new file mode 100644
index 00000000..c1906b6d
--- /dev/null
+++ b/tests/test-offset-loop.alt.bz2
Binary files differ
diff --git a/tests/test-offset-loop.bz2 b/tests/test-offset-loop.bz2
new file mode 100755
index 00000000..62185c0a
--- /dev/null
+++ b/tests/test-offset-loop.bz2
Binary files differ
diff --git a/tests/testfile66.bz2 b/tests/testfile66.bz2
new file mode 100755
index 00000000..4797590e
--- /dev/null
+++ b/tests/testfile66.bz2
Binary files differ
diff --git a/tests/testfile66.core.bz2 b/tests/testfile66.core.bz2
new file mode 100644
index 00000000..12e2d444
--- /dev/null
+++ b/tests/testfile66.core.bz2
Binary files differ
diff --git a/tests/testfile_aarch64_core.bz2 b/tests/testfile_aarch64_core.bz2
new file mode 100644
index 00000000..9d562688
--- /dev/null
+++ b/tests/testfile_aarch64_core.bz2
Binary files differ
diff --git a/tests/testfileaarch64.bz2 b/tests/testfileaarch64.bz2
new file mode 100755
index 00000000..72e5ef0d
--- /dev/null
+++ b/tests/testfileaarch64.bz2
Binary files differ
diff --git a/tests/testfilebazdbg_pl.bz2 b/tests/testfilebazdbg_pl.bz2
new file mode 100755
index 00000000..9e06a806
--- /dev/null
+++ b/tests/testfilebazdbg_pl.bz2
Binary files differ
diff --git a/tests/testfilebazdbg_plr.bz2 b/tests/testfilebazdbg_plr.bz2
new file mode 100755
index 00000000..1bc43dd2
--- /dev/null
+++ b/tests/testfilebazdbg_plr.bz2
Binary files differ
diff --git a/tests/testfilebazdbgppc64.bz2 b/tests/testfilebazdbgppc64.bz2
new file mode 100755
index 00000000..17e77d6d
--- /dev/null
+++ b/tests/testfilebazdbgppc64.bz2
Binary files differ
diff --git a/tests/testfilebazdbgppc64.debug.bz2 b/tests/testfilebazdbgppc64.debug.bz2
new file mode 100755
index 00000000..8faa17af
--- /dev/null
+++ b/tests/testfilebazdbgppc64.debug.bz2
Binary files differ
diff --git a/tests/testfilebazdbgppc64_pl.bz2 b/tests/testfilebazdbgppc64_pl.bz2
new file mode 100755
index 00000000..9f372fb9
--- /dev/null
+++ b/tests/testfilebazdbgppc64_pl.bz2
Binary files differ
diff --git a/tests/testfilebazdbgppc64_plr.bz2 b/tests/testfilebazdbgppc64_plr.bz2
new file mode 100755
index 00000000..70f8e005
--- /dev/null
+++ b/tests/testfilebazdbgppc64_plr.bz2
Binary files differ
diff --git a/tests/testfilebazdynppc64.bz2 b/tests/testfilebazdynppc64.bz2
new file mode 100755
index 00000000..2e01699e
--- /dev/null
+++ b/tests/testfilebazdynppc64.bz2
Binary files differ
diff --git a/tests/testfilebazmdb.bz2 b/tests/testfilebazmdb.bz2
index c486365c..561eca11 100755
--- a/tests/testfilebazmdb.bz2
+++ b/tests/testfilebazmdb.bz2
Binary files differ
diff --git a/tests/testfilebazmdbppc64.bz2 b/tests/testfilebazmdbppc64.bz2
new file mode 100755
index 00000000..16c2dd0a
--- /dev/null
+++ b/tests/testfilebazmdbppc64.bz2
Binary files differ
diff --git a/tests/testfilebazmin.bz2 b/tests/testfilebazmin.bz2
index f7286d62..12bcc6b5 100755
--- a/tests/testfilebazmin.bz2
+++ b/tests/testfilebazmin.bz2
Binary files differ
diff --git a/tests/testfilebazmin_pl.bz2 b/tests/testfilebazmin_pl.bz2
new file mode 100755
index 00000000..73cef4ae
--- /dev/null
+++ b/tests/testfilebazmin_pl.bz2
Binary files differ
diff --git a/tests/testfilebazmin_plr.bz2 b/tests/testfilebazmin_plr.bz2
new file mode 100755
index 00000000..e4fcf85d
--- /dev/null
+++ b/tests/testfilebazmin_plr.bz2
Binary files differ
diff --git a/tests/testfilebazminppc64.bz2 b/tests/testfilebazminppc64.bz2
new file mode 100755
index 00000000..364d84c4
--- /dev/null
+++ b/tests/testfilebazminppc64.bz2
Binary files differ
diff --git a/tests/testfilebazminppc64_pl.bz2 b/tests/testfilebazminppc64_pl.bz2
new file mode 100755
index 00000000..66863403
--- /dev/null
+++ b/tests/testfilebazminppc64_pl.bz2
Binary files differ
diff --git a/tests/testfilebazminppc64_plr.bz2 b/tests/testfilebazminppc64_plr.bz2
new file mode 100755
index 00000000..46102853
--- /dev/null
+++ b/tests/testfilebazminppc64_plr.bz2
Binary files differ
diff --git a/tests/testfilebaztabppc64.bz2 b/tests/testfilebaztabppc64.bz2
new file mode 100755
index 00000000..03afb8c9
--- /dev/null
+++ b/tests/testfilebaztabppc64.bz2
Binary files differ
diff --git a/tests/typeiter2.c b/tests/typeiter2.c
new file mode 100644
index 00000000..6ddfa388
--- /dev/null
+++ b/tests/typeiter2.c
@@ -0,0 +1,89 @@
+/* Copyright (C) 2012, 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 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/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <fcntl.h>
+#include ELFUTILS_HEADER(dw)
+#include <stdio.h>
+#include <unistd.h>
+#include <dwarf.h>
+
+int
+main (int argc, char *argv[])
+{
+ for (int i = 1; i < argc; ++i)
+ {
+ int fd = open (argv[i], O_RDONLY);
+
+ Dwarf *dbg = dwarf_begin (fd, DWARF_C_READ);
+ if (dbg != NULL)
+ {
+ Dwarf_Off off = 0;
+ size_t cuhl;
+ Dwarf_Off noff;
+ uint64_t type_sig;
+
+ while (dwarf_next_unit (dbg, off, &noff, &cuhl, NULL, NULL, NULL,
+ NULL, &type_sig, NULL) == 0)
+ {
+ Dwarf_Die die_mem;
+ dwarf_offdie_types (dbg, off + cuhl, &die_mem);
+ off = noff;
+ }
+
+ off = 0;
+
+ while (dwarf_nextcu (dbg, off, &noff, &cuhl, NULL, NULL, NULL) == 0)
+ {
+ Dwarf_Die die_mem;
+ Dwarf_Die *die = dwarf_offdie (dbg, off + cuhl, &die_mem);
+
+ Dwarf_Die iter_mem;
+ Dwarf_Die *iter = &iter_mem;
+ dwarf_child (die, &iter_mem);
+
+ while (1)
+ {
+ if (dwarf_tag (iter) == DW_TAG_variable)
+ {
+ Dwarf_Attribute attr_mem;
+ Dwarf_Die form_mem, *form;
+ form = dwarf_formref_die (dwarf_attr (iter, DW_AT_type,
+ &attr_mem),
+ &form_mem);
+
+ if (form == NULL)
+ printf ("fail\n");
+ else
+ printf ("ok\n");
+ }
+
+ if (dwarf_siblingof (iter, &iter_mem) != 0)
+ break;
+ }
+
+ off = noff;
+ }
+
+ dwarf_end (dbg);
+ }
+
+ close (fd);
+ }
+}
diff --git a/tests/varlocs.c b/tests/varlocs.c
index 6f4d4901..04f17ff2 100644
--- a/tests/varlocs.c
+++ b/tests/varlocs.c
@@ -404,7 +404,7 @@ print_expr (Dwarf_Attribute *attr, Dwarf_Op *expr, Dwarf_Addr addr)
int locs = dwarf_getlocation_addr (&attrval, addr,
&exprval, &exprval_len, 1);
if (locs == 0)
- printf ("<no location>"); // XXX should that be flagged?
+ printf ("<no location>"); // This means "optimized out".
else if (locs == 1)
print_expr_block (&attrval, exprval, exprval_len, addr);
else