diff options
author | Jan Kratochvil <jan.kratochvil@redhat.com> | 2012-11-13 18:55:19 +0100 |
---|---|---|
committer | Jan Kratochvil <jan.kratochvil@redhat.com> | 2012-11-13 18:55:19 +0100 |
commit | e1cda0b1dc62832558dda5c5e7542c655f09de81 (patch) | |
tree | bc06e714792fcd7d86de07414c064f11b8961c2e | |
parent | 999516e5ab073c66d681134e8956df9ca3680f80 (diff) | |
download | elfutils-e1cda0b1dc62832558dda5c5e7542c655f09de81.tar.gz |
Revert "Remove non-x86* EBL hooks."
This reverts commit f1bb4153196650a09048d05056f282e49addfed3.
-rw-r--r-- | libdwfl/dwfl_frame_state_pc.c | 1 | ||||
-rw-r--r-- | libdwfl/dwfl_frame_unwind.c | 10 | ||||
-rw-r--r-- | libdwfl/libdwflP.h | 6 | ||||
-rw-r--r-- | libebl/Makefile.am | 3 | ||||
-rw-r--r-- | libebl/ebl-hooks.h | 13 | ||||
-rw-r--r-- | libebl/eblframedwarftoregno.c | 42 | ||||
-rw-r--r-- | libebl/eblframeunwind.c | 41 | ||||
-rw-r--r-- | libebl/eblnormalizepc.c | 40 | ||||
-rw-r--r-- | libebl/libebl.h | 14 |
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, ®no)) + 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, ®no)) + 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 |