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(a)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(a)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(a)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(a)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(a)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, ®no))
+ 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, ®no))
+ 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