summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Kratochvil <jan.kratochvil@redhat.com>2012-11-13 18:55:19 +0100
committerJan Kratochvil <jan.kratochvil@redhat.com>2012-11-13 18:55:19 +0100
commite1cda0b1dc62832558dda5c5e7542c655f09de81 (patch)
treebc06e714792fcd7d86de07414c064f11b8961c2e
parent999516e5ab073c66d681134e8956df9ca3680f80 (diff)
downloadelfutils-e1cda0b1dc62832558dda5c5e7542c655f09de81.tar.gz
Revert "Remove non-x86* EBL hooks."
This reverts commit f1bb4153196650a09048d05056f282e49addfed3.
-rw-r--r--libdwfl/dwfl_frame_state_pc.c1
-rw-r--r--libdwfl/dwfl_frame_unwind.c10
-rw-r--r--libdwfl/libdwflP.h6
-rw-r--r--libebl/Makefile.am3
-rw-r--r--libebl/ebl-hooks.h13
-rw-r--r--libebl/eblframedwarftoregno.c42
-rw-r--r--libebl/eblframeunwind.c41
-rw-r--r--libebl/eblnormalizepc.c40
-rw-r--r--libebl/libebl.h14
9 files changed, 168 insertions, 2 deletions
diff --git a/libdwfl/dwfl_frame_state_pc.c b/libdwfl/dwfl_frame_state_pc.c
index 6e9928b5..4d6fc8bd 100644
--- a/libdwfl/dwfl_frame_state_pc.c
+++ b/libdwfl/dwfl_frame_state_pc.c
@@ -37,6 +37,7 @@ dwfl_frame_state_pc (Dwfl_Frame_State *state, Dwarf_Addr *pc, bool *minusone)
{
assert (state->pc_state == DWFL_FRAME_STATE_PC_SET);
*pc = state->pc;
+ ebl_normalize_pc (state->thread->process->ebl, pc);
if (minusone)
{
/* Bottom frame? */
diff --git a/libdwfl/dwfl_frame_unwind.c b/libdwfl/dwfl_frame_unwind.c
index 5705f515..e35ccb5d 100644
--- a/libdwfl/dwfl_frame_unwind.c
+++ b/libdwfl/dwfl_frame_unwind.c
@@ -410,7 +410,7 @@ handle_cfi (Dwfl_Frame_State **statep, Dwarf_Addr pc, Dwfl_Module *mod,
{
/* REGNO is undefined. */
unsigned ra = frame->fde->cie->return_address_register;
- if (regno == ra)
+ if (ebl_frame_dwarf_to_regno (ebl, &ra) && regno == ra)
unwound->pc_state = DWFL_FRAME_STATE_PC_UNDEFINED;
continue;
}
@@ -494,6 +494,14 @@ dwfl_frame_unwind (Dwfl_Frame_State **statep)
}
}
}
+ *statep = state;
+ if (ebl_frame_unwind (state->thread->process->ebl, statep, pc))
+ return true;
+ if (state->unwound)
+ {
+ assert (state->unwound->pc_state == DWFL_FRAME_STATE_ERROR);
+ return false;
+ }
__libdwfl_seterrno (DWFL_E_NO_DWARF);
return false;
}
diff --git a/libdwfl/libdwflP.h b/libdwfl/libdwflP.h
index 3999d666..fb2f839b 100644
--- a/libdwfl/libdwflP.h
+++ b/libdwfl/libdwflP.h
@@ -265,6 +265,9 @@ dwfl_frame_state_reg_get (Dwfl_Frame_State *state, unsigned regno,
Dwarf_Addr *val)
{
Ebl *ebl = state->thread->process->ebl;
+ if (ebl->frame_dwarf_to_regno != NULL
+ && ! ebl->frame_dwarf_to_regno (ebl, &regno))
+ return false;
if (regno >= ebl->frame_state_nregs)
return false;
if ((state->regs_set[regno / sizeof (*state->regs_set) / 8]
@@ -283,6 +286,9 @@ dwfl_frame_state_reg_set (Dwfl_Frame_State *state, unsigned regno,
Dwarf_Addr val)
{
Ebl *ebl = state->thread->process->ebl;
+ if (ebl->frame_dwarf_to_regno != NULL
+ && ! ebl->frame_dwarf_to_regno (ebl, &regno))
+ return false;
if (regno >= ebl->frame_state_nregs)
return false;
/* For example i386 user_regs_struct has signed fields. */
diff --git a/libebl/Makefile.am b/libebl/Makefile.am
index 1e396896..92497c3d 100644
--- a/libebl/Makefile.am
+++ b/libebl/Makefile.am
@@ -55,7 +55,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 eblgetfuncpc.c eblframestate.c
+ eblstother.c eblgetfuncpc.c eblframestate.c eblnormalizepc.c \
+ eblframeunwind.c eblframedwarftoregno.c
libebl_a_SOURCES = $(gen_SOURCES)
diff --git a/libebl/ebl-hooks.h b/libebl/ebl-hooks.h
index 5b77f921..72f1aadc 100644
--- a/libebl/ebl-hooks.h
+++ b/libebl/ebl-hooks.h
@@ -168,5 +168,18 @@ bool EBLHOOK(frame_state) (struct Dwfl_Frame_State *state);
above. */
size_t EBLHOOKVAR(frame_state_nregs);
+/* Convert *REGNO as is in DWARF to a lower range suitable for
+ Dwarf_Frame_State->REGS indexing. RETURN_ADDRESS_REGISTER should not change
+ on second call; other registers may map to numbers invalid on input. */
+bool EBLHOOK(frame_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);
+
+/* See dwfl_frame_unwind. */
+bool EBLHOOK(frame_unwind) (Ebl *ebl, struct Dwfl_Frame_State **statep,
+ Dwarf_Addr pc);
+
/* Destructor for ELF backend handle. */
void EBLHOOK(destr) (struct ebl *);
diff --git a/libebl/eblframedwarftoregno.c b/libebl/eblframedwarftoregno.c
new file mode 100644
index 00000000..4cfbd468
--- /dev/null
+++ b/libebl/eblframedwarftoregno.c
@@ -0,0 +1,42 @@
+/* Convert *REGNO as is in DWARF to a lower range.
+ Copyright (C) 2012 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_frame_dwarf_to_regno (Ebl *ebl, unsigned *regno)
+{
+ if (ebl == NULL)
+ return false;
+ return (ebl->frame_dwarf_to_regno == NULL
+ ? true : ebl->frame_dwarf_to_regno (ebl, regno));
+}
diff --git a/libebl/eblframeunwind.c b/libebl/eblframeunwind.c
new file mode 100644
index 00000000..adc658b8
--- /dev/null
+++ b/libebl/eblframeunwind.c
@@ -0,0 +1,41 @@
+/* Get previous frame state for an existing frame state.
+ Copyright (C) 2012 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_frame_unwind (Ebl *ebl, struct Dwfl_Frame_State **statep, Dwarf_Addr pc)
+{
+ if (ebl == NULL || ebl->frame_unwind == NULL)
+ return false;
+ return ebl->frame_unwind (ebl, statep, pc);
+}
diff --git a/libebl/eblnormalizepc.c b/libebl/eblnormalizepc.c
new file mode 100644
index 00000000..abe6352c
--- /dev/null
+++ b/libebl/eblnormalizepc.c
@@ -0,0 +1,40 @@
+/* Modify PC as fetched from inferior data into valid PC.
+ Copyright (C) 2012 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/libebl.h b/libebl/libebl.h
index 09b7bfb2..967980e5 100644
--- a/libebl/libebl.h
+++ b/libebl/libebl.h
@@ -393,6 +393,20 @@ extern bool ebl_frame_state (struct Dwfl_Frame_State *state)
extern size_t ebl_frame_state_nregs (Ebl *ebl)
__nonnull_attribute__ (1);
+/* Modify PC as fetched from inferior data into valid PC. */
+extern void ebl_normalize_pc (Ebl *ebl, Dwarf_Addr *pc)
+ __nonnull_attribute__ (1, 2);
+
+/* Get previous frame state for an existing frame state. */
+struct Dwfl_Frame_State_Process;
+extern bool
+ ebl_frame_unwind (Ebl *ebl, struct Dwfl_Frame_State **statep, Dwarf_Addr pc)
+ __nonnull_attribute__ (1, 2);
+
+/* Convert *REGNO as is in DWARF to a lower range. */
+extern bool ebl_frame_dwarf_to_regno (Ebl *ebl, unsigned *regno)
+ __nonnull_attribute__ (1, 2);
+
#ifdef __cplusplus
}
#endif