This is the mail archive of the elfutils-devel@sourceware.org mailing list for the elfutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH 4/4] backends: sparc: support for live backtraces


This patch implements the set_initial_registers_tid hook for sparc.
It works in both sparcv9-*-* and sparc64-*-* targets.

Signed-off-by: Jose E. Marchesi <jose.marchesi@oracle.com>
---
 backends/ChangeLog       |   6 +++
 backends/Makefile.am     |   2 +-
 backends/sparc_init.c    |   1 +
 backends/sparc_initreg.c | 129 +++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 137 insertions(+), 1 deletion(-)
 create mode 100644 backends/sparc_initreg.c

diff --git a/backends/ChangeLog b/backends/ChangeLog
index 7ee8c2c..4b604fd 100644
--- a/backends/ChangeLog
+++ b/backends/ChangeLog
@@ -1,5 +1,11 @@
 2015-12-08  Jose E. Marchesi  <jose.marchesi@oracle.com>
 
+	* sparc_init.c (sparc_init): Hook sparc_set_initial_registers_tid.
+	* sparc_initreg.c: New file.
+	* Makefile.am (sparc_SRCS): Added sparc_initreg.c.
+
+2015-12-08  Jose E. Marchesi  <jose.marchesi@oracle.com>
+
 	* sparc_corenote.c: Header comment typo fixed.
 	(PRSTATUS_REGSET_ITEMS): Defined, so the PC can be fetched from
 	core files.
diff --git a/backends/Makefile.am b/backends/Makefile.am
index f07b202..b16f948 100644
--- a/backends/Makefile.am
+++ b/backends/Makefile.am
@@ -85,7 +85,7 @@ am_libebl_aarch64_pic_a_OBJECTS = $(aarch64_SRCS:.c=.os)
 
 sparc_SRCS = sparc_init.c sparc_symbol.c sparc_regs.c sparc_retval.c \
 	     sparc_corenote.c sparc64_corenote.c sparc_auxv.c sparc_attrs.c \
-             sparc_cfi.c
+             sparc_cfi.c sparc_initreg.c
 libebl_sparc_pic_a_SOURCES = $(sparc_SRCS)
 am_libebl_sparc_pic_a_OBJECTS = $(sparc_SRCS:.c=.os)
 
diff --git a/backends/sparc_init.c b/backends/sparc_init.c
index 98b697c..8e946fb 100644
--- a/backends/sparc_init.c
+++ b/backends/sparc_init.c
@@ -83,6 +83,7 @@ sparc_init (Elf *elf __attribute__ ((unused)),
      actually contains the call address.  The return address is
      located 8 bytes after it.  */
   eh->ra_offset = 8;
+  HOOK (eh, set_initial_registers_tid);
 
   return MODVERSION;
 }
diff --git a/backends/sparc_initreg.c b/backends/sparc_initreg.c
new file mode 100644
index 0000000..c2a9b32
--- /dev/null
+++ b/backends/sparc_initreg.c
@@ -0,0 +1,129 @@
+/* Fetch live process registers from TID.
+   Copyright (C) 2015 Oracle, In
+   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 __sparc__
+# include <asm/ptrace.h>
+# include <sys/ptrace.h>
+#endif
+
+#define BACKEND sparc_
+#include "libebl_CPU.h"
+
+bool
+EBLHOOK (set_initial_registers_tid) (pid_t tid __attribute__ ((unused)),
+                                     ebl_tid_registers_t *setfunc __attribute__ ((unused)),
+                                     void *arg __attribute__ ((unused)))
+{
+#ifndef __sparc__
+  return false;
+#else /* __sparc__ */
+
+
+  /* The pt_regs structure filled in by PTRACE_GETREGS provides the
+     PC, the global registers and the output registers.  Note how the
+     %g0 register is not explicitly provided in the structure (it's
+     value is always 0) and the resulting weird packing in the u_regs
+     array: the last element is not used.  */
+  
+  struct pt_regs regs;
+  if (ptrace (PTRACE_GETREGS, tid, &regs, 0) == -1)
+    return false;
+
+  /* PC: no DWARF number  */
+  if (!setfunc (-1, 1, (Dwarf_Word *) &regs.tpc, arg))
+    return false;
+  
+  /* Global registers: DWARF 0 .. 7  */
+  Dwarf_Word zero = 0;
+  if (!setfunc (0, 1, &zero, arg))
+    return false;
+  if (!setfunc (1, 7, (Dwarf_Word *) &regs.u_regs[0], arg))
+    return false;
+
+  /* Output registers: DWARF  8 .. 15  */
+  if (!setfunc (8, 8, (Dwarf_Word *) &regs.u_regs[7], arg))
+    return false;
+
+  /* Local and input registers must be read from the stack.  They are
+     saved in the previous stack frame.  The stack pointer is %o6,
+     read above.  */
+
+  Dwarf_Word locals_outs[16];
+  Dwarf_Word sp = regs.u_regs[13];
+
+  if (sp & 1)
+    {
+      /* Registers are 64 bits, and we need to apply the 2047 stack
+         bias in order to get the real stack pointer.  */
+
+      sp += 2047;
+
+      for (unsigned i = 0; i < 16; i++)
+        {
+          locals_outs[i] = ptrace (PTRACE_PEEKDATA, tid,
+                                   (void *) (uintptr_t) (sp + (i * 8)),
+                                   NULL);
+          if (errno != 0)
+            return false;
+        }
+    }
+  else
+    {
+      /* Registers are 32 bits.  */
+
+      for (unsigned i = 0; i < 8; i++)
+        {
+          Dwarf_Word tuple = ptrace (PTRACE_PEEKDATA, tid,
+                                     (void *) (uintptr_t) (sp + (i * 8)),
+                                     NULL);
+          if (errno != 0)
+            return false;
+
+          locals_outs[2*i] = (tuple >> 32) & 0xffffffff;
+          locals_outs[2*i+1] = tuple & 0xffffffff;
+        }
+    }
+
+  
+  /* Local registers:  DWARF 16 .. 23 */
+  if (!setfunc (16, 8, &locals_outs[0], arg))
+    return false;
+  
+  /* Input registers: DWARF 24 .. 31 */
+  if (!setfunc (24, 8, &locals_outs[8], arg))
+    return false;
+
+  return true;
+#endif
+}
-- 
2.3.4

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]