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 }