>From 54780555f3d98f40c3866789b9be514bdcc494af Mon Sep 17 00:00:00 2001
From: Mark Wielaard <mjw@redhat.com>
Date: Sun, 26 Jan 2014 20:16:48 +0100
Subject: [PATCH] backends: Add arm frame_nregs and set_initial_registers_tid.

This allows CFI unwinding for ARM. It relies on having .debug_frame around
which is always the case in our testsuite. All native backtrace tests PASS
on arm if debuginfo (for glibc) is installed on the system. Otherwise the
tests SKIP.

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_initreg.c  | 58 +++++++++++++++++++++++++++++++++++++++++++++++++
 tests/ChangeLog         |  4 ++++
 tests/backtrace-subr.sh | 12 ++++++++++
 6 files changed, 87 insertions(+), 2 deletions(-)
 create mode 100644 backends/arm_initreg.c

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_initreg.c b/backends/arm_initreg.c
new file mode 100644
index 0000000..c03146e
--- /dev/null
+++ b/backends/arm_initreg.c
@@ -0,0 +1,58 @@
+/* Fetch live process registers from TID.
+   Copyright (C) 2014 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 __arm__
+# include <sys/types.h>
+# include <sys/user.h>
+# include <sys/ptrace.h>
+#endif
+
+#define BACKEND arm_
+#include "libebl_CPU.h"
+
+bool
+arm_set_initial_registers_tid (pid_t tid __attribute__ ((unused)),
+			  ebl_tid_registers_t *setfunc __attribute__ ((unused)),
+			       void *arg __attribute__ ((unused)))
+{
+#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
+}
diff --git a/tests/ChangeLog b/tests/ChangeLog
index fa8a42a..a279982 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -1,3 +1,7 @@
+2014-01-26  Mark Wielaard  <mjw@redhat.com>
+
+	* backtrace-subr.sh (check_unsupported): Special case arm*.
+
 2014-01-25  Mark Wielaard  <mjw@redhat.com>
 
 	* run-addrcfi.sh (EM_ARM): Change reg13 (sp) from undefined to
diff --git a/tests/backtrace-subr.sh b/tests/backtrace-subr.sh
index 62b873c..1df9356 100644
--- a/tests/backtrace-subr.sh
+++ b/tests/backtrace-subr.sh
@@ -74,6 +74,18 @@ check_unsupported()
     echo >&2 $testname: arch not supported
     exit 77
   fi
+
+  # ARM is special. It is supported, but it doesn't use .eh_frame by default
+  # making the native tests fail unless debuginfo (for glibc) is installed
+  # and we can fall back on .debug_frame for the CFI.
+  case "`uname -m`" in
+    arm* )
+      if grep 'dwfl_thread_getframes: No DWARF information found' $1; then
+	echo >&2 $testname: arm needs debuginfo installed for all libraries
+	exit 77
+      fi
+    ;;
+  esac
 }
 
 check_core()
-- 
1.8.5.3

