diff options
| author | Mark Wielaard <[email protected]> | 2014-01-03 22:49:44 +0100 |
|---|---|---|
| committer | Mark Wielaard <[email protected]> | 2014-01-03 22:49:44 +0100 |
| commit | 14e5056319def0555bc4183488e7af5c14a3fb28 (patch) | |
| tree | de729f791c5ec247d90d95f0b97cee91bcbaebbd | |
| parent | 7cd12085203e55f063f8a9b048d6102bc774d0e5 (diff) | |
| parent | 70db4cc41d7e0516aecc477fd6aab2ba693029af (diff) | |
Merge branch 'master' into robustify
179 files changed, 12216 insertions, 1015 deletions
@@ -25,6 +25,7 @@ config.h config.h.in config.log config.status +config/ar-lib config/config.guess config/config.sub config/depcomp @@ -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. @@ -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 @@ -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, ¬es_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, ®no)) + 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, ®no)) + 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, ®_ops, + ®_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, ®val)) + continue; + } + else + { + __libdwfl_seterrno (DWFL_E_INVALID_DWARF); + continue; + } + } + else if (! expr_eval (state, frame, reg_ops, reg_nops, ®val, 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, + ®s_offset, &nregloc, ®locs, &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, ®s_offset, + &nregloc, ®locs, &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, + ®s_offset, &nregloc, ®locs, &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. @@ -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 "" @@ -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" @@ -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" @@ -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" @@ -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; @@ -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])) @@ -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 Binary files differnew file mode 100644 index 00000000..e120d9bd --- /dev/null +++ b/tests/backtrace.i386.core.bz2 diff --git a/tests/backtrace.i386.exec.bz2 b/tests/backtrace.i386.exec.bz2 Binary files differnew file mode 100644 index 00000000..1b0f001c --- /dev/null +++ b/tests/backtrace.i386.exec.bz2 diff --git a/tests/backtrace.ppc.core.bz2 b/tests/backtrace.ppc.core.bz2 Binary files differnew file mode 100644 index 00000000..f20cd9f3 --- /dev/null +++ b/tests/backtrace.ppc.core.bz2 diff --git a/tests/backtrace.ppc.exec.bz2 b/tests/backtrace.ppc.exec.bz2 Binary files differnew file mode 100644 index 00000000..057c25a6 --- /dev/null +++ b/tests/backtrace.ppc.exec.bz2 diff --git a/tests/backtrace.s390.core.bz2 b/tests/backtrace.s390.core.bz2 Binary files differnew file mode 100644 index 00000000..db346948 --- /dev/null +++ b/tests/backtrace.s390.core.bz2 diff --git a/tests/backtrace.s390.exec.bz2 b/tests/backtrace.s390.exec.bz2 Binary files differnew file mode 100644 index 00000000..4c1b4aee --- /dev/null +++ b/tests/backtrace.s390.exec.bz2 diff --git a/tests/backtrace.s390x.core.bz2 b/tests/backtrace.s390x.core.bz2 Binary files differnew file mode 100644 index 00000000..61c23ec4 --- /dev/null +++ b/tests/backtrace.s390x.core.bz2 diff --git a/tests/backtrace.s390x.exec.bz2 b/tests/backtrace.s390x.exec.bz2 Binary files differnew file mode 100644 index 00000000..8009239d --- /dev/null +++ b/tests/backtrace.s390x.exec.bz2 diff --git a/tests/backtrace.x86_64.core.bz2 b/tests/backtrace.x86_64.core.bz2 Binary files differnew file mode 100644 index 00000000..1f34e206 --- /dev/null +++ b/tests/backtrace.x86_64.core.bz2 diff --git a/tests/backtrace.x86_64.exec.bz2 b/tests/backtrace.x86_64.exec.bz2 Binary files differnew file mode 100644 index 00000000..70a151be --- /dev/null +++ b/tests/backtrace.x86_64.exec.bz2 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 Binary files differnew file mode 100755 index 00000000..5494e102 --- /dev/null +++ b/tests/funcretval_test_aarch64.bz2 diff --git a/tests/hello_aarch64.ko.bz2 b/tests/hello_aarch64.ko.bz2 Binary files differnew file mode 100644 index 00000000..431d89f9 --- /dev/null +++ b/tests/hello_aarch64.ko.bz2 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 Binary files differnew file mode 100644 index 00000000..c1906b6d --- /dev/null +++ b/tests/test-offset-loop.alt.bz2 diff --git a/tests/test-offset-loop.bz2 b/tests/test-offset-loop.bz2 Binary files differnew file mode 100755 index 00000000..62185c0a --- /dev/null +++ b/tests/test-offset-loop.bz2 diff --git a/tests/testfile66.bz2 b/tests/testfile66.bz2 Binary files differnew file mode 100755 index 00000000..4797590e --- /dev/null +++ b/tests/testfile66.bz2 diff --git a/tests/testfile66.core.bz2 b/tests/testfile66.core.bz2 Binary files differnew file mode 100644 index 00000000..12e2d444 --- /dev/null +++ b/tests/testfile66.core.bz2 diff --git a/tests/testfile_aarch64_core.bz2 b/tests/testfile_aarch64_core.bz2 Binary files differnew file mode 100644 index 00000000..9d562688 --- /dev/null +++ b/tests/testfile_aarch64_core.bz2 diff --git a/tests/testfileaarch64.bz2 b/tests/testfileaarch64.bz2 Binary files differnew file mode 100755 index 00000000..72e5ef0d --- /dev/null +++ b/tests/testfileaarch64.bz2 diff --git a/tests/testfilebazdbg_pl.bz2 b/tests/testfilebazdbg_pl.bz2 Binary files differnew file mode 100755 index 00000000..9e06a806 --- /dev/null +++ b/tests/testfilebazdbg_pl.bz2 diff --git a/tests/testfilebazdbg_plr.bz2 b/tests/testfilebazdbg_plr.bz2 Binary files differnew file mode 100755 index 00000000..1bc43dd2 --- /dev/null +++ b/tests/testfilebazdbg_plr.bz2 diff --git a/tests/testfilebazdbgppc64.bz2 b/tests/testfilebazdbgppc64.bz2 Binary files differnew file mode 100755 index 00000000..17e77d6d --- /dev/null +++ b/tests/testfilebazdbgppc64.bz2 diff --git a/tests/testfilebazdbgppc64.debug.bz2 b/tests/testfilebazdbgppc64.debug.bz2 Binary files differnew file mode 100755 index 00000000..8faa17af --- /dev/null +++ b/tests/testfilebazdbgppc64.debug.bz2 diff --git a/tests/testfilebazdbgppc64_pl.bz2 b/tests/testfilebazdbgppc64_pl.bz2 Binary files differnew file mode 100755 index 00000000..9f372fb9 --- /dev/null +++ b/tests/testfilebazdbgppc64_pl.bz2 diff --git a/tests/testfilebazdbgppc64_plr.bz2 b/tests/testfilebazdbgppc64_plr.bz2 Binary files differnew file mode 100755 index 00000000..70f8e005 --- /dev/null +++ b/tests/testfilebazdbgppc64_plr.bz2 diff --git a/tests/testfilebazdynppc64.bz2 b/tests/testfilebazdynppc64.bz2 Binary files differnew file mode 100755 index 00000000..2e01699e --- /dev/null +++ b/tests/testfilebazdynppc64.bz2 diff --git a/tests/testfilebazmdb.bz2 b/tests/testfilebazmdb.bz2 Binary files differindex c486365c..561eca11 100755 --- a/tests/testfilebazmdb.bz2 +++ b/tests/testfilebazmdb.bz2 diff --git a/tests/testfilebazmdbppc64.bz2 b/tests/testfilebazmdbppc64.bz2 Binary files differnew file mode 100755 index 00000000..16c2dd0a --- /dev/null +++ b/tests/testfilebazmdbppc64.bz2 diff --git a/tests/testfilebazmin.bz2 b/tests/testfilebazmin.bz2 Binary files differindex f7286d62..12bcc6b5 100755 --- a/tests/testfilebazmin.bz2 +++ b/tests/testfilebazmin.bz2 diff --git a/tests/testfilebazmin_pl.bz2 b/tests/testfilebazmin_pl.bz2 Binary files differnew file mode 100755 index 00000000..73cef4ae --- /dev/null +++ b/tests/testfilebazmin_pl.bz2 diff --git a/tests/testfilebazmin_plr.bz2 b/tests/testfilebazmin_plr.bz2 Binary files differnew file mode 100755 index 00000000..e4fcf85d --- /dev/null +++ b/tests/testfilebazmin_plr.bz2 diff --git a/tests/testfilebazminppc64.bz2 b/tests/testfilebazminppc64.bz2 Binary files differnew file mode 100755 index 00000000..364d84c4 --- /dev/null +++ b/tests/testfilebazminppc64.bz2 diff --git a/tests/testfilebazminppc64_pl.bz2 b/tests/testfilebazminppc64_pl.bz2 Binary files differnew file mode 100755 index 00000000..66863403 --- /dev/null +++ b/tests/testfilebazminppc64_pl.bz2 diff --git a/tests/testfilebazminppc64_plr.bz2 b/tests/testfilebazminppc64_plr.bz2 Binary files differnew file mode 100755 index 00000000..46102853 --- /dev/null +++ b/tests/testfilebazminppc64_plr.bz2 diff --git a/tests/testfilebaztabppc64.bz2 b/tests/testfilebaztabppc64.bz2 Binary files differnew file mode 100755 index 00000000..03afb8c9 --- /dev/null +++ b/tests/testfilebaztabppc64.bz2 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 |
