diff options
author | Jose E. Marchesi <jose.marchesi@oracle.com> | 2015-12-08 19:10:41 +0100 |
---|---|---|
committer | Mark Wielaard <mjw@redhat.com> | 2016-01-03 10:31:41 +0100 |
commit | 73be3d2d1a5dbdb6aa954b244524d21346af27d8 (patch) | |
tree | 384f0300c08062cee789c5e63d2ad0220eef309c | |
parent | 42f0df13d7c0b3ec1a547eca84eca694f6d42310 (diff) | |
download | elfutils-73be3d2d1a5dbdb6aa954b244524d21346af27d8.tar.gz |
libdwfl: make the unwinder aware of the backend defined ra_offset.
Ebl backends can define an offset that must be applied to the value of
the "return address register" defined in the CFI ABI information.
This patch makes the unwinder to use that offset when reading the RA
CFI register.
Signed-off-by: Jose E. Marchesi <jose.marchesi@oracle.com>
-rw-r--r-- | libdwfl/ChangeLog | 7 | ||||
-rw-r--r-- | libdwfl/dwfl_frame.c | 2 | ||||
-rw-r--r-- | libdwfl/frame_unwind.c | 9 |
3 files changed, 16 insertions, 2 deletions
diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog index d815f3e5..8657da45 100644 --- a/libdwfl/ChangeLog +++ b/libdwfl/ChangeLog @@ -1,3 +1,10 @@ +2015-12-08 Jose E. Marchesi <jose.marchesi@oracle.com> + + * dwfl_frame.c (state_fetch_pc): Add a backend-defined offset to + the value of the return address register as defined by the CFI + abi. + * frame_unwind.c (handle_cfi): Likewise. + 2015-12-01 Mark Wielaard <mjw@redhat.com> * link_map.c (dwfl_link_map_report): Track whether in.d_buf comes diff --git a/libdwfl/dwfl_frame.c b/libdwfl/dwfl_frame.c index a91a1d68..d6399398 100644 --- a/libdwfl/dwfl_frame.c +++ b/libdwfl/dwfl_frame.c @@ -57,7 +57,7 @@ state_fetch_pc (Dwfl_Frame *state) __libdwfl_seterrno (DWFL_E_LIBEBL_BAD); return false; } - state->pc = state->regs[ra]; + state->pc = state->regs[ra] + ebl_ra_offset (ebl); state->pc_state = DWFL_FRAME_STATE_PC_SET; } return true; diff --git a/libdwfl/frame_unwind.c b/libdwfl/frame_unwind.c index 39509b70..0e470b97 100644 --- a/libdwfl/frame_unwind.c +++ b/libdwfl/frame_unwind.c @@ -637,7 +637,14 @@ handle_cfi (Dwfl_Frame *state, Dwarf_Addr pc, Dwarf_CFI *cfi, Dwarf_Addr bias) if (unwound->pc == 0) unwound->pc_state = DWFL_FRAME_STATE_PC_UNDEFINED; else - unwound->pc_state = DWFL_FRAME_STATE_PC_SET; + { + unwound->pc_state = DWFL_FRAME_STATE_PC_SET; + /* In SPARC the return address register actually contains + the address of the call instruction instead of the return + address. Therefore we add here an offset defined by the + backend. Most likely 0. */ + unwound->pc += ebl_ra_offset (ebl); + } } free (frame); } |