Signed-off-by: Mark Wielaard mjw@redhat.com --- backends/ChangeLog | 4 ++++ backends/arm_cfi.c | 3 +++ tests/ChangeLog | 5 +++++ tests/run-addrcfi.sh | 2 +- 4 files changed, 13 insertions(+), 1 deletion(-)
diff --git a/backends/ChangeLog b/backends/ChangeLog index 045fa9d..c8e2b30 100644 --- a/backends/ChangeLog +++ b/backends/ChangeLog @@ -1,3 +1,7 @@ +2014-01-25 Mark Wielaard mjw@redhat.com + + * arm_cfi.c (arm_abi_cfi): Restore SP (r13) from CFA. + 2014-01-24 Mark Wielaard mjw@redhat.com
* arm_reloc.def: Update list. diff --git a/backends/arm_cfi.c b/backends/arm_cfi.c index e0cc44b..971a1fc 100644 --- a/backends/arm_cfi.c +++ b/backends/arm_cfi.c @@ -54,6 +54,9 @@ arm_abi_cfi (Ebl *ebl __attribute__ ((unused)), Dwarf_CIE *abi_info) Stack Pointer (r13) as setup in the previous frame. */ DW_CFA_def_cfa, ULEB128_7 (13), ULEB128_7 (0),
+ /* The Stack Pointer (r13) is restored from CFA address by default. */ + DW_CFA_val_offset, ULEB128_7 (13), ULEB128_7 (0), + #define SV(n) DW_CFA_same_value, ULEB128_7 (n) /* Callee-saved regs r4-r8, r10, r11. */ SV (4), SV (5), SV (6), SV (7), SV (8), SV (10), SV (11), diff --git a/tests/ChangeLog b/tests/ChangeLog index cbf2672..fa8a42a 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,3 +1,8 @@ +2014-01-25 Mark Wielaard mjw@redhat.com + + * run-addrcfi.sh (EM_ARM): Change reg13 (sp) from undefined to + location expression: call_frame_cfa stack_value. + 2014-01-22 Mark Wielaard mjw@redhat.com
* Makefile.am (line2addr_no_Wformat): Removed. diff --git a/tests/run-addrcfi.sh b/tests/run-addrcfi.sh index a4225ac..5d33246 100755 --- a/tests/run-addrcfi.sh +++ b/tests/run-addrcfi.sh @@ -2519,7 +2519,7 @@ dwarf_cfi_addrframe (.eh_frame): no matching address range integer reg10 (r10): same_value integer reg11 (r11): same_value integer reg12 (r12): undefined - integer reg13 (sp): undefined + integer reg13 (sp): location expression: call_frame_cfa stack_value integer reg14 (lr): same_value integer reg15 (pc): location expression: regx(14) FPA reg16 (f0): undefined
This allows CFI unwinding for ARM. It relies on having .debug_frame around which is always the case in our testsuite. All backtrace tests PASS.
For non-debug unwinding ARM uses EXIDX tables, not .eh_frames, which would have to be translated to CFI to do unwinding without .debug_frame available.
Signed-off-by: Mark Wielaard mjw@redhat.com --- backends/ChangeLog | 7 ++++ backends/Makefile.am | 2 +- backends/arm_init.c | 6 +++- backends/{arm_init.c => arm_initreg.c} | 58 ++++++++++++++-------------------- 4 files changed, 37 insertions(+), 36 deletions(-) copy backends/{arm_init.c => arm_initreg.c} (51%)
diff --git a/backends/ChangeLog b/backends/ChangeLog index c8e2b30..212b9f6 100644 --- a/backends/ChangeLog +++ b/backends/ChangeLog @@ -1,3 +1,10 @@ +2014-01-26 Mark Wielaard mjw@redhat.com + + * Makefile.am (arm_SRCS): Add arm_initreg.c. + * arm_init.c (arm_init): Define frame_nregs and hook + set_initial_registers_tid. + * arm_initreg.c: New file. + 2014-01-25 Mark Wielaard mjw@redhat.com
* arm_cfi.c (arm_abi_cfi): Restore SP (r13) from CFA. diff --git a/backends/Makefile.am b/backends/Makefile.am index 90e93a8..4129eee 100644 --- a/backends/Makefile.am +++ b/backends/Makefile.am @@ -78,7 +78,7 @@ libebl_alpha_pic_a_SOURCES = $(alpha_SRCS) am_libebl_alpha_pic_a_OBJECTS = $(alpha_SRCS:.c=.os)
arm_SRCS = arm_init.c arm_symbol.c arm_regs.c arm_corenote.c \ - arm_auxv.c arm_attrs.c arm_retval.c arm_cfi.c + arm_auxv.c arm_attrs.c arm_retval.c arm_cfi.c arm_initreg.c libebl_arm_pic_a_SOURCES = $(arm_SRCS) am_libebl_arm_pic_a_OBJECTS = $(arm_SRCS:.c=.os)
diff --git a/backends/arm_init.c b/backends/arm_init.c index cf661ce..14b2635 100644 --- a/backends/arm_init.c +++ b/backends/arm_init.c @@ -1,5 +1,5 @@ /* Initialization of Arm specific backend library. - Copyright (C) 2002, 2005, 2009, 2013 Red Hat, Inc. + Copyright (C) 2002, 2005, 2009, 2013, 2014 Red Hat, Inc. This file is part of elfutils. Written by Ulrich Drepper drepper@redhat.com, 2002.
@@ -64,5 +64,9 @@ arm_init (elf, machine, eh, ehlen) HOOK (eh, return_value_location); HOOK (eh, abi_cfi);
+ /* We only unwind the core integer registers. */ + eh->frame_nregs = 16; + HOOK (eh, set_initial_registers_tid); + return MODVERSION; } diff --git a/backends/arm_init.c b/backends/arm_initreg.c similarity index 51% copy from backends/arm_init.c copy to backends/arm_initreg.c index cf661ce..c03146e 100644 --- a/backends/arm_init.c +++ b/backends/arm_initreg.c @@ -1,7 +1,6 @@ -/* Initialization of Arm specific backend library. - Copyright (C) 2002, 2005, 2009, 2013 Red Hat, Inc. +/* Fetch live process registers from TID. + Copyright (C) 2014 Red Hat, Inc. This file is part of elfutils. - Written by Ulrich Drepper drepper@redhat.com, 2002.
This file is free software; you can redistribute it and/or modify it under the terms of either @@ -31,38 +30,29 @@ # include <config.h> #endif
-#define BACKEND arm_ -#define RELOC_PREFIX R_ARM_ -#include "libebl_CPU.h" - -/* This defines the common reloc hooks based on arm_reloc.def. */ -#include "common-reloc.c" +#if defined __arm__ +# include <sys/types.h> +# include <sys/user.h> +# include <sys/ptrace.h> +#endif
+#define BACKEND arm_ +#include "libebl_CPU.h"
-const char * -arm_init (elf, machine, eh, ehlen) - Elf *elf __attribute__ ((unused)); - GElf_Half machine __attribute__ ((unused)); - Ebl *eh; - size_t ehlen; +bool +arm_set_initial_registers_tid (pid_t tid __attribute__ ((unused)), + ebl_tid_registers_t *setfunc __attribute__ ((unused)), + void *arg __attribute__ ((unused))) { - /* Check whether the Elf_BH object has a sufficent size. */ - if (ehlen < sizeof (Ebl)) - return NULL; - - /* We handle it. */ - eh->name = "ARM"; - arm_init_reloc (eh); - HOOK (eh, segment_type_name); - HOOK (eh, section_type_name); - HOOK (eh, machine_flag_check); - HOOK (eh, reloc_simple_type); - HOOK (eh, register_info); - HOOK (eh, core_note); - HOOK (eh, auxv_info); - HOOK (eh, check_object_attribute); - HOOK (eh, return_value_location); - HOOK (eh, abi_cfi); - - return MODVERSION; +#if ! defined __arm__ + return false; +#else + struct user_regs user_regs; + if (ptrace (PTRACE_GETREGS, tid, NULL, &user_regs) != 0) + return false; + Dwarf_Word dwarf_regs[16]; + for (int i = 0; i < 16; i++) + dwarf_regs[i] = user_regs.uregs[i]; + return setfunc (0, 16, dwarf_regs, arg); +#endif }
On Sun, 2014-01-26 at 20:37 +0100, Mark Wielaard wrote:
This allows CFI unwinding for ARM. It relies on having .debug_frame around which is always the case in our testsuite. All backtrace tests PASS.
If only things were that simple... All native backtrace tests PASS IF all debuginfo for the libraries (glibc) is installed on the system (since only then can it use the .debug_frame fallback to find the correct CFI). So in the patch pushed to master (as attached) I added a special case for arm* in backtrace-subr.sh (check_unsupported) to SKIP the native tests if DWARF could not be found.
Cheers,
Mark
On Sun, 2014-01-26 at 20:37 +0100, Mark Wielaard wrote:
+2014-01-25 Mark Wielaard mjw@redhat.com
- arm_cfi.c (arm_abi_cfi): Restore SP (r13) from CFA.
2014-01-24 Mark Wielaard mjw@redhat.com [...] +2014-01-25 Mark Wielaard mjw@redhat.com
- run-addrcfi.sh (EM_ARM): Change reg13 (sp) from undefined to
- location expression: call_frame_cfa stack_value.
I pushed this to master now.
elfutils-devel@lists.fedorahosted.org