+2013-12-21 Mark Wielaard <mjw@redhat.com>
+
+ * frame_unwind.c (handle_cfi): Track whether the return register
+ has been set and only allow it to be set once.
+
2013-12-20 Mark Wielaard <mjw@redhat.com>
* dwfl_frame.c (one_arg): New struct.
Ebl *ebl = process->ebl;
size_t nregs = ebl_frame_nregs (ebl);
assert (nregs > 0);
+
+ /* The return register is special for setting the unwound->pc_state. */
+ unsigned ra = frame->fde->cie->return_address_register;
+ bool ra_set = false;
+ ebl_dwarf_to_regno (ebl, &ra);
+
for (unsigned regno = 0; regno < nregs; regno++)
{
Dwarf_Op reg_ops_mem[3], *reg_ops;
if (reg_ops == reg_ops_mem)
{
/* REGNO is undefined. */
- unsigned ra = frame->fde->cie->return_address_register;
- if (ebl_dwarf_to_regno (ebl, &ra) && regno == ra)
+ if (regno == ra)
unwound->pc_state = DWFL_FRAME_STATE_PC_UNDEFINED;
continue;
}
But PPC32 does not use such registers. */
continue;
}
+
+ /* 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)
+ {
+ unsigned r = regno;
+ if (ebl_dwarf_to_regno (ebl, &r) && r == ra)
+ continue;
+ }
+
if (! __libdwfl_frame_reg_set (unwound, regno, regval))
{
__libdwfl_seterrno (DWFL_E_INVALID_REGISTER);
continue;
}
+ else if (! ra_set)
+ {
+ unsigned r = regno;
+ if (ebl_dwarf_to_regno (ebl, &r) && r == ra)
+ ra_set = true;
+ }
}
if (unwound->pc_state == DWFL_FRAME_STATE_ERROR
&& __libdwfl_frame_reg_get (unwound,