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]

[patchv2 3/4] unwinder: ppc and ppc64


Hi Mark,

jankratochvil/ynonx86base-attach-firstreg..jankratochvil/ynonx86base-attach-firstreg-ppc

Not a single commit, it has dependency on various pending patches.  Therefore
also not a git format-patch attachment.  I can fix it up after approval of:
	jankratochvil/ppc64bidir
	jankratochvil/unwindx86 (=the testcases)


On Mon, 18 Nov 2013 22:40:18 +0100, Mark Wielaard wrote:
> Please do add a short description on why the extensions were needed in
> this case to the commit message (or in the intro of an email). It really
> makes things easier to review and might be useful for people looking
> back on this code/commit later.

OK, sorry.


> Given the "interesting" DWARF register numbering on ppc, I see why we
> want a dwarf_to_regno () to flatten things out. The firstreg -1
> indicating PC seems reasonable, if the architecture doesn't define a
> PC/return address DWARF register number.

Yes.


> I had some trouble
> understanding the core_pc_offset one at first though.

It is gone now.


> > --- a/backends/ppc64_init.c
> > +++ b/backends/ppc64_init.c
> > @@ -68,6 +68,11 @@ ppc64_init (elf, machine, eh, ehlen)
> >    HOOK (eh, init_symbols);
> >    HOOK (eh, get_symbol);
> >    HOOK (eh, destr);
> > +  /* gcc/config/ #define DWARF_FRAME_REGISTERS.  */
> > +  eh->frame_nregs = (114 - 1) + 32;
> > +  eh->core_pc_offset = 0x170;
> > +  HOOK (eh, set_initial_registers_tid);
> > +  HOOK (eh, dwarf_to_regno);
> 
> OK, but the 0x170 magic number really should have a comment where it was
> specified.

It is gone now.


> OK, but again do add a comment for the core_pc_offset magic value.

Gone now.


> > +bool
> > +ppc_dwarf_to_regno (Ebl *ebl __attribute__ ((unused)), unsigned *regno)
> > +{
> > +  switch (*regno)
> > +  {
> > +    case 108:
> > +      *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")));
> 
> OK. The abort () really means unreachable here.

Yes.


> > +  /* PTRACE_GETREGS is EIO on kernel-2.6.18-308.el5.ppc64.  */
> 
> You could try it anyway as optimization and fallback on the iteration
> over PTRACE_PEEKUSER if it fails. But if you feel that is just a
> micro-optimization don't. The comment shows we could do it later if we
> really care.

It could be useful but I find it OK to add only later.


> > +  if (! setfunc (65, 1, dwarf_regs, arg)) // or 108
> > +    return false;
> 
> This might need an extra comment. If I remember right 108 is the
> official DWARF register number, but GCC always produces 65?

I do not know what is the real reason.  I tried to read some docs but 65 vs.
108 seems to me just as a bug/mess.  I can add

// LR uses both 65 and 108 numbers, there is no consistency for it.


> 
> > +  /* 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__ */
> > +}
> 
> Nitpick. You could probably use &user_regs.r.link and &user_regs.r.nip
> instead of reusing dwarf_regs[0]. Though maybe the compiler will
> complain about that. But again a micro optimization that is probably not
> worth it.

Yes, I do not find it somehow clean to mix types when passing a pointer.


> > +  size_t core_pc_offset = ebl_core_pc_offset (core_arg->ebl);
> > +  if (core_pc_offset)
> > +    {
> > +      Dwarf_Word pc;
> > +      switch (gelf_getclass (core) == ELFCLASS32 ? 32 : 64)
> > +      {
> > +	case 32:;
> > +	  uint32_t val32 = *(const uint32_t *) (desc + core_pc_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 + core_pc_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);
> > +    }
> >    return true;
> >  }
> 
> hmmm. I think I now understand the core_pc_offset.
> It is the offset into the PRSTATUS note where to find the register that
> represents the pc. But you reparse that location here instead of using
> Ebl_Register_Location which you have just iterated through just above.
> 
> Why don't you use the loop above and check the regloc->offset there
> before calling either dwfl_thread_state_registers or
> dwfl_thread_state_register_pc on the value?

One cannot use regloc, backends/ppc_corenote.c does not list PC in
Ebl_Register_Location prstatus_regs[].  But you are right it is listed in
PRSTATUS_REGSET_ITEMS so I use it now.  And the whole ebl->core_pc_offset
could be removed.


> > --- a/libdwfl/linux-pid-attach.c
> > +++ b/libdwfl/linux-pid-attach.c
> > @@ -202,6 +202,17 @@ 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 > 0);
> > +      INTUSE(dwfl_thread_state_register_pc) (thread, *regs);
> > +      firstreg++;
> > +      nregs--;
> > +      regs++;
> > +    }
> > +  if (! nregs)
> > +    return true;
> >    return INTUSE(dwfl_thread_state_registers) (thread, firstreg, nregs, regs);
> >  }
> 
> OK. Though in practice I assume it will always be firstreg == -1 &&
> nregs == 1. Which would result it slightly simpler code.

OK, simplified the code.


> > --- a/libebl/libebl.h
> > +++ b/libebl/libebl.h
> > @@ -383,7 +383,8 @@ 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.  */
> > +/* Callback type for ebl_set_initial_registers_tid.
> > +   Register -1 is mapped to PC (if arch PC has no DWARF number).  */
> >  typedef bool (ebl_tid_registers_t) (int firstreg, unsigned nregs,
> >  				    const Dwarf_Word *regs, void *arg)
> 
> OK. I would suggest to just say that if firstreg == -1 then nregs == 1.
> To simplify the code. If that makes sense.

Done.


> > +/* PC register location stored in core file.  It is a number of bytes from
> > +   descriptor of NT_PRSTATUS core note.  It is 0 if unused.  */
> > +extern size_t ebl_core_pc_offset (Ebl *ebl)
> > +  __nonnull_attribute__ (1);
> 
> It really should mention that the offset is one of the valid offsets of
> the Ebl_Register_Location returned by ebl_core_note.
> 
> Or better. It should be named ebl_core_pc_regno. If not zero, it is the
> Ebl_Register_Location regno that (double) as initial pc value.

It is gone now.


> > --- a/libebl/libeblP.h
> > +++ b/libebl/libeblP.h
> > @@ -64,6 +64,10 @@ struct ebl
> >       Ebl architecture can unwind iff FRAME_NREGS > 0.  */
> >    size_t frame_nregs;
> >  
> > +  /* PC register location stored in core file.  It is a number of bytes from
> > +     descriptor of NT_PRSTATUS core note.  It is 0 if unused.  */
> > +  size_t core_pc_offset;
> 
> See above. Would it make sense to rename/define it as core_pc_regno?

It is gone now.


> > --- a/tests/run-backtrace.sh
> > +++ b/tests/run-backtrace.sh
> > @@ -91,4 +91,12 @@ for child in backtrace-child{,-biarch}; do
> >  
> >  done
> >  
> > +for arch in ppc ppc64; do
> > +  testfiles backtrace.$arch.{exec,core}
> > +  tempfiles backtrace.$arch.{bt,err}
> > +  echo ./backtrace ./backtrace.$arch.{exec,core}
> > +  testrun ${abs_builddir}/backtrace ./backtrace.$arch.{exec,core} 1>backtrace.$arch.bt 2>backtrace.$arch.err || true
> > +  check_all backtrace.$arch.{bt,err} backtrace.$arch.core
> > +done
> 
> Do see the comments I made about the tests in an earlier email.

It is very different now.


Thanks,
Jan


unwinder: ppc and ppc64

backends/
2013-11-10  Jan Kratochvil  <jan.kratochvil@redhat.com>

	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.

libdwfl/
2013-11-10  Jan Kratochvil  <jan.kratochvil@redhat.com>

	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.

libebl/
2013-11-10  Jan Kratochvil  <jan.kratochvil@redhat.com>

	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.

tests/
2013-11-10  Jan Kratochvil  <jan.kratochvil@redhat.com>

	* Makefile.am (TESTS): Add run-backtrace-core-ppc64.sh and
	run-backtrace-core-ppc.sh.
	(EXTRA_DIST): Add backtrace.ppc.core.bz2,
	backtrace.ppc.exec.bz2, backtrace.ppc64.core.bz2,
	backtrace.ppc64.exec.bz2, run-backtrace-core-ppc64.sh and
	run-backtrace-core-ppc.sh.
	* backtrace.ppc.core.bz2: New file.
	* backtrace.ppc.exec.bz2: New file.
	* backtrace.ppc64.core.bz2: New file.
	* backtrace.ppc64.exec.bz2: New file.
	* run-backtrace-core-ppc.sh: New file.
	* run-backtrace-core-ppc64.sh: New file.

Signed-off-by: Jan Kratochvil <jan.kratochvil@redhat.com>

diff --git a/backends/Makefile.am b/backends/Makefile.am
index 0e00329..653b56e 100644
--- a/backends/Makefile.am
+++ b/backends/Makefile.am
@@ -88,13 +88,13 @@ 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 ppc64_get_symbol.c
+	     ppc_cfi.c ppc64_get_symbol.c ppc_initreg.c
 libebl_ppc64_pic_a_SOURCES = $(ppc64_SRCS)
 am_libebl_ppc64_pic_a_OBJECTS = $(ppc64_SRCS:.c=.os)
 
diff --git a/backends/ppc64_init.c b/backends/ppc64_init.c
index 3ed882b..8fd4575 100644
--- a/backends/ppc64_init.c
+++ b/backends/ppc64_init.c
@@ -68,6 +68,10 @@ ppc64_init (elf, machine, eh, ehlen)
   HOOK (eh, init_symbols);
   HOOK (eh, get_symbol);
   HOOK (eh, destr);
+  /* 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_corenote.c b/backends/ppc_corenote.c
index 707a395..9ac8871 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 004c601..ad92765 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 0000000..ae3f138
--- /dev/null
+++ b/backends/ppc_initreg.c
@@ -0,0 +1,112 @@
+/* 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:
+      *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;
+  if (! setfunc (65, 1, dwarf_regs, arg)) // or 108
+    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/libdwfl/frame_unwind.c b/libdwfl/frame_unwind.c
index 1aed8cb..2973f95 100644
--- a/libdwfl/frame_unwind.c
+++ b/libdwfl/frame_unwind.c
@@ -52,6 +52,8 @@ 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, &regno))
+    return false;
   if (regno >= ebl_frame_nregs (ebl))
     return false;
   if ((state->regs_set[regno / sizeof (*state->regs_set) / 8]
@@ -67,6 +69,8 @@ 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, &regno))
+    return false;
   if (regno >= ebl_frame_nregs (ebl))
     return false;
   /* For example i386 user_regs_struct has signed fields.  */
diff --git a/libdwfl/linux-core-attach.c b/libdwfl/linux-core-attach.c
index b2d703f..2853c3c 100644
--- a/libdwfl/linux-core-attach.c
+++ b/libdwfl/linux-core-attach.c
@@ -198,6 +198,32 @@ core_set_initial_registers (Dwfl_Thread *thread, void *thread_arg_voidp)
   }
   /* 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++)
     {
diff --git a/libdwfl/linux-pid-attach.c b/libdwfl/linux-pid-attach.c
index e4eb621..45a0732 100644
--- a/libdwfl/linux-pid-attach.c
+++ b/libdwfl/linux-pid-attach.c
@@ -205,6 +205,14 @@ 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);
 }
 
diff --git a/libebl/Makefile.am b/libebl/Makefile.am
index 1fb3da3..6c03af8 100644
--- a/libebl/Makefile.am
+++ b/libebl/Makefile.am
@@ -54,7 +54,7 @@ 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 eblinitreg.c eblgetsymbol.c
+	      eblstother.c eblinitreg.c eblgetsymbol.c ebldwarftoregno.c
 
 libebl_a_SOURCES = $(gen_SOURCES)
 
diff --git a/libebl/ebl-hooks.h b/libebl/ebl-hooks.h
index 2ad18ec..f2b3857 100644
--- a/libebl/ebl-hooks.h
+++ b/libebl/ebl-hooks.h
@@ -172,5 +172,9 @@ void EBLHOOK(init_symbols) (Ebl *ebl, size_t syments, int first_global,
 const char *EBLHOOK(get_symbol) (Ebl *ebl, size_t ndx, GElf_Sym *symp,
 				 GElf_Word *shndxp);
 
+/* 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);
+
 /* Destructor for ELF backend handle.  */
 void EBLHOOK(destr) (struct ebl *);
diff --git a/libebl/ebldwarftoregno.c b/libebl/ebldwarftoregno.c
new file mode 100644
index 0000000..8fb8540
--- /dev/null
+++ b/libebl/ebldwarftoregno.c
@@ -0,0 +1,41 @@
+/* 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
+   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_dwarf_to_regno (Ebl *ebl, unsigned *regno)
+{
+  if (ebl == NULL)
+    return false;
+  return ebl->dwarf_to_regno == NULL ? true : ebl->dwarf_to_regno (ebl, regno);
+}
diff --git a/libebl/libebl.h b/libebl/libebl.h
index 2446cc9..7fe5456 100644
--- a/libebl/libebl.h
+++ b/libebl/libebl.h
@@ -368,6 +368,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.
@@ -383,7 +384,9 @@ 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.  */
+/* 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);
@@ -428,6 +431,11 @@ extern const char *ebl_get_symbol (Ebl *ebl, size_t ndx, GElf_Sym *symp,
 				   GElf_Word *shndxp)
   __nonnull_attribute__ (1, 3);
 
+/* 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);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 10fdc21..50a1f94 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -109,7 +109,8 @@ TESTS = run-arextract.sh run-arsymtest.sh newfile test-nlist \
 	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-i386.sh run-backtrace-core-ppc64.sh \
+	run-backtrace-core-ppc.sh
 if !BIARCH
 export ELFUTILS_DISABLE_BIARCH = 1
 endif
@@ -246,7 +247,10 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.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.x86_64.core.bz2 backtrace.x86_64.exec.bz2 \
+	     backtrace.ppc64.core.bz2 backtrace.ppc64.exec.bz2 \
+	     backtrace.ppc.core.bz2 backtrace.ppc.exec.bz2 \
+	     run-backtrace-core-ppc64.sh run-backtrace-core-ppc.sh
 
 if USE_VALGRIND
 valgrind_cmd='valgrind -q --trace-children=yes --error-exitcode=1 --run-libc-freeres=no'
diff --git a/tests/backtrace.ppc.core.bz2 b/tests/backtrace.ppc.core.bz2
new file mode 100644
index 0000000..2dca8f1
Binary files /dev/null and b/tests/backtrace.ppc.core.bz2 differ
diff --git a/tests/backtrace.ppc.exec.bz2 b/tests/backtrace.ppc.exec.bz2
new file mode 100644
index 0000000..15070a9
Binary files /dev/null and b/tests/backtrace.ppc.exec.bz2 differ
diff --git a/tests/backtrace.ppc64.core.bz2 b/tests/backtrace.ppc64.core.bz2
new file mode 100644
index 0000000..a07aa61
Binary files /dev/null and b/tests/backtrace.ppc64.core.bz2 differ
diff --git a/tests/backtrace.ppc64.exec.bz2 b/tests/backtrace.ppc64.exec.bz2
new file mode 100644
index 0000000..21a7e0d
Binary files /dev/null and b/tests/backtrace.ppc64.exec.bz2 differ
diff --git a/tests/run-backtrace-core-ppc.sh b/tests/run-backtrace-core-ppc.sh
new file mode 100755
index 0000000..65c9279
--- /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-ppc64.sh b/tests/run-backtrace-core-ppc64.sh
new file mode 100755
index 0000000..aaf186e
--- /dev/null
+++ b/tests/run-backtrace-core-ppc64.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 ppc64

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