summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Wielaard <mjw@redhat.com>2014-01-05 20:37:30 +0100
committerMark Wielaard <mjw@redhat.com>2014-01-05 20:49:24 +0100
commit27aae18ce872409b70afef8503941c7e75c8d93d (patch)
tree8fa89611a6f71bc51e9f4c74ceda01d4feab6a5f
parent70c3a53baa06b6cdee6e92bd673c1cf977066bc1 (diff)
libdwfl: Only skip reset of return register for non-CIE-return regno (ppc64).elfutils-0.158
For PPC64 we skip resetting the return register if it is already set. This is because on PPC64 there are two DWARF registers numbers that can represent the same register. Setting the return address again confuses the unwinder. But we do want to reset it if the register number (non-translated by the ppc64 ebl) is equal to the actual register number as set in the CIE as return address. This happens on older toolchains in .debug_frame where the return address is set to 108, but the ebl abi_cfi also sets register number 65. Signed-off-by: Mark Wielaard <mjw@redhat.com>
-rw-r--r--libdwfl/ChangeLog5
-rw-r--r--libdwfl/frame_unwind.c5
2 files changed, 8 insertions, 2 deletions
diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog
index 766fb18a..55980a57 100644
--- a/libdwfl/ChangeLog
+++ b/libdwfl/ChangeLog
@@ -1,3 +1,8 @@
+2014-01-05 Mark Wielaard <mjw@redhat.com>
+
+ * frame_unwind.c (handle_cfi): Only skip resetting return register
+ if the regno is not the actual CIE return address register.
+
2014-01-02 Mark Wielaard <mjw@redhat.com>
* linux-pid-attach.c (dwfl_linux_proc_attach): Use strtol, not atoi.
diff --git a/libdwfl/frame_unwind.c b/libdwfl/frame_unwind.c
index 3ce45479..dc99e40b 100644
--- a/libdwfl/frame_unwind.c
+++ b/libdwfl/frame_unwind.c
@@ -585,8 +585,9 @@ handle_cfi (Dwfl_Frame *state, Dwarf_Addr pc, Dwarf_CFI *cfi, Dwarf_Addr bias)
/* This is another strange PPC[64] case. There are two
registers numbers that can represent the same DWARF return
register number. We only want one to actually set the return
- register value. */
- if (ra_set)
+ register value. But we always want to override the value if
+ the register is the actual CIE return address register. */
+ if (ra_set && regno != frame->fde->cie->return_address_register)
{
unsigned r = regno;
if (ebl_dwarf_to_regno (ebl, &r) && r == ra)