summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJose E. Marchesi <jose.marchesi@oracle.com>2015-12-08 19:10:41 +0100
committerMark Wielaard <mjw@redhat.com>2016-01-03 10:31:41 +0100
commit73be3d2d1a5dbdb6aa954b244524d21346af27d8 (patch)
tree384f0300c08062cee789c5e63d2ad0220eef309c
parent42f0df13d7c0b3ec1a547eca84eca694f6d42310 (diff)
downloadelfutils-73be3d2d1a5dbdb6aa954b244524d21346af27d8.tar.gz
elfutils-73be3d2d1a5dbdb6aa954b244524d21346af27d8.tar.xz
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/ChangeLog7
-rw-r--r--libdwfl/dwfl_frame.c2
-rw-r--r--libdwfl/frame_unwind.c9
3 files changed, 16 insertions, 2 deletions
diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog
index d815f3e..8657da4 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 a91a1d6..d639939 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 39509b7..0e470b9 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);
}