summaryrefslogtreecommitdiffstats
path: root/libebl
diff options
context:
space:
mode:
authorJan Kratochvil <[email protected]>2013-12-17 18:49:54 +0100
committerJan Kratochvil <[email protected]>2013-12-18 13:01:05 +0100
commitc6a41483f2986d5542c554981348f75b815ef9b1 (patch)
treeafbd87ebb664bfe07a7d03790920fdbbc3be9e38 /libebl
parentc8c610bcfb9e90ab2d43c019da7eaade7017baec (diff)
unwinder: s390 and s390x
Signed-off-by: Jan Kratochvil <[email protected]>
Diffstat (limited to 'libebl')
-rw-r--r--libebl/ChangeLog12
-rw-r--r--libebl/Makefile.am3
-rw-r--r--libebl/ebl-hooks.h17
-rw-r--r--libebl/eblnormalizepc.c40
-rw-r--r--libebl/eblunwind.c43
-rw-r--r--libebl/libebl.h29
6 files changed, 143 insertions, 1 deletions
diff --git a/libebl/ChangeLog b/libebl/ChangeLog
index a27de82d..f1aa242b 100644
--- a/libebl/ChangeLog
+++ b/libebl/ChangeLog
@@ -1,3 +1,15 @@
+2013-12-18 Jan Kratochvil <[email protected]>
+
+ unwinder: s390 and s390x
+ * Makefile.am (gen_SOURCES): Add eblnormalizepc.c and eblunwind.c.
+ * ebl-hooks.h (normalize_pc, unwind): New.
+ * eblnormalizepc.c: New file.
+ * eblunwind.c: New file.
+ * libebl.h (Ebl_Register_Location): Add field pc_register.
+ (ebl_normalize_pc): New declaration.
+ (ebl_tid_registers_get_t, ebl_pid_memory_read_t): New definitions.
+ (ebl_unwind): New declaration.
+
2013-12-15 Jan Kratochvil <[email protected]>
unwinder: ppc and ppc64
diff --git a/libebl/Makefile.am b/libebl/Makefile.am
index 2f3b7308..fc4f1b6f 100644
--- a/libebl/Makefile.am
+++ b/libebl/Makefile.am
@@ -54,7 +54,8 @@ 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 ebldwarftoregno.c
+ eblstother.c eblinitreg.c ebldwarftoregno.c eblnormalizepc.c \
+ eblunwind.c
libebl_a_SOURCES = $(gen_SOURCES)
diff --git a/libebl/ebl-hooks.h b/libebl/ebl-hooks.h
index f721bc49..22438953 100644
--- a/libebl/ebl-hooks.h
+++ b/libebl/ebl-hooks.h
@@ -166,5 +166,22 @@ bool EBLHOOK(set_initial_registers_tid) (pid_t tid,
Dwarf_Frame->REGS indexing. */
bool EBLHOOK(dwarf_to_regno) (Ebl *ebl, unsigned *regno);
+/* Optionally modify *PC as fetched from inferior data into valid PC
+ instruction pointer. */
+void EBLHOOK(normalize_pc) (Ebl *ebl, Dwarf_Addr *pc);
+
+/* Get previous frame state for an existing frame state. Method is called only
+ if unwinder could not find CFI for current PC. PC is for the
+ existing frame. SETFUNC sets register in the previous frame. GETFUNC gets
+ register from the existing frame. Note that GETFUNC vs. SETFUNC act on
+ a disjunct set of registers. READFUNC reads memory. ARG has to be passed
+ for SETFUNC, GETFUNC and READFUNC. *SIGNAL_FRAMEP is initialized to false,
+ it can be set to true if existing frame is a signal frame. SIGNAL_FRAMEP is
+ never NULL. */
+bool EBLHOOK(unwind) (Ebl *ebl, Dwarf_Addr pc, ebl_tid_registers_t *setfunc,
+ ebl_tid_registers_get_t *getfunc,
+ ebl_pid_memory_read_t *readfunc, void *arg,
+ bool *signal_framep);
+
/* Destructor for ELF backend handle. */
void EBLHOOK(destr) (struct ebl *);
diff --git a/libebl/eblnormalizepc.c b/libebl/eblnormalizepc.c
new file mode 100644
index 00000000..a5fea77e
--- /dev/null
+++ b/libebl/eblnormalizepc.c
@@ -0,0 +1,40 @@
+/* Modify PC as fetched from inferior data into valid PC.
+ 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>
+
+void
+ebl_normalize_pc (Ebl *ebl, Dwarf_Addr *pc)
+{
+ if (ebl != NULL && ebl->normalize_pc != NULL)
+ ebl->normalize_pc (ebl, pc);
+}
diff --git a/libebl/eblunwind.c b/libebl/eblunwind.c
new file mode 100644
index 00000000..1251c1b5
--- /dev/null
+++ b/libebl/eblunwind.c
@@ -0,0 +1,43 @@
+/* Get previous frame state for an existing frame state.
+ 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_unwind (Ebl *ebl, Dwarf_Addr pc, ebl_tid_registers_t *setfunc,
+ ebl_tid_registers_get_t *getfunc, ebl_pid_memory_read_t *readfunc,
+ void *arg, bool *signal_framep)
+{
+ if (ebl == NULL || ebl->unwind == NULL)
+ return false;
+ return ebl->unwind (ebl, pc, setfunc, getfunc, readfunc, arg, signal_framep);
+}
diff --git a/libebl/libebl.h b/libebl/libebl.h
index 7080b4a5..84c2f4cd 100644
--- a/libebl/libebl.h
+++ b/libebl/libebl.h
@@ -356,6 +356,7 @@ typedef struct
uint8_t bits; /* Bits of data for one register. */
uint8_t pad; /* Bytes of padding after register's data. */
Dwarf_Half count; /* Consecutive register numbers here. */
+ bool pc_register;
} Ebl_Register_Location;
/* Non-register data items in core notes. */
@@ -410,6 +411,34 @@ extern size_t ebl_frame_nregs (Ebl *ebl)
extern bool ebl_dwarf_to_regno (Ebl *ebl, unsigned *regno)
__nonnull_attribute__ (1, 2);
+/* Modify PC as fetched from inferior data into valid PC. */
+extern void ebl_normalize_pc (Ebl *ebl, Dwarf_Addr *pc)
+ __nonnull_attribute__ (1, 2);
+
+/* Callback type for ebl_unwind's parameter getfunc. */
+typedef bool (ebl_tid_registers_get_t) (int firstreg, unsigned nregs,
+ Dwarf_Word *regs, void *arg)
+ __nonnull_attribute__ (3);
+
+/* Callback type for ebl_unwind's parameter readfunc. */
+typedef bool (ebl_pid_memory_read_t) (Dwarf_Addr addr, Dwarf_Word *data,
+ void *arg)
+ __nonnull_attribute__ (3);
+
+/* Get previous frame state for an existing frame state. Method is called only
+ if unwinder could not find CFI for current PC. PC is for the
+ existing frame. SETFUNC sets register in the previous frame. GETFUNC gets
+ register from the existing frame. Note that GETFUNC vs. SETFUNC act on
+ a disjunct set of registers. READFUNC reads memory. ARG has to be passed
+ for SETFUNC, GETFUNC and READFUNC. *SIGNAL_FRAMEP is initialized to false,
+ it can be set to true if existing frame is a signal frame. SIGNAL_FRAMEP is
+ never NULL. */
+extern bool ebl_unwind (Ebl *ebl, Dwarf_Addr pc, ebl_tid_registers_t *setfunc,
+ ebl_tid_registers_get_t *getfunc,
+ ebl_pid_memory_read_t *readfunc, void *arg,
+ bool *signal_framep)
+ __nonnull_attribute__ (1, 3, 4, 5, 7);
+
#ifdef __cplusplus
}
#endif