unwind-ia64.c (struct _Unwind_Context): Add new field 'signal_pfs_loc'.
* config/ia64/unwind-ia64.c (struct _Unwind_Context): Add new field 'signal_pfs_loc'. (uw_frame_state_for): Remove duplicate code dealing with leaf procedures without unwind info. If in the frame after unwinding through a signal handler, restore the AR.PFS register instead of the CFM if AR.PFS has not been saved. * config/ia64/linux-unwind.h (ia64_fallback_frame_state): Do not set 'pfs_loc' to the AR.PFS location in the signal context; instead set 'signal_pfs_loc'. Manually generate the unwind info for the AR.PFS register. (ABI_MARKER_OLD_LINUX_SIGTRAMP, ABI_MARKER_OLD_LINUX_INTERRUPT, ABI_MARKER_LINUX_SIGTRAMP, ABI_MARKER_LINUX_INTERRUPT): Define. (ia64_handle_unwabi): Test 'fs->unwabi' against them. Do not set 'pfs_loc' to the AR.PFS location in the signal context; instead set 'signal_pfs_loc'. Remove code preventing the AR.PFS register from being restored from the signal context. From-SVN: r150777
This commit is contained in:
parent
c24db30451
commit
ac77b88e52
3 changed files with 69 additions and 17 deletions
|
@ -1,3 +1,23 @@
|
|||
2009-08-14 Eric Botcazou <ebotcazou@adacore.com>
|
||||
|
||||
* config/ia64/unwind-ia64.c (struct _Unwind_Context): Add new
|
||||
field 'signal_pfs_loc'.
|
||||
(uw_frame_state_for): Remove duplicate code dealing with leaf
|
||||
procedures without unwind info.
|
||||
If in the frame after unwinding through a signal handler, restore
|
||||
the AR.PFS register instead of the CFM if AR.PFS has not been saved.
|
||||
* config/ia64/linux-unwind.h (ia64_fallback_frame_state): Do not set
|
||||
'pfs_loc' to the AR.PFS location in the signal context; instead
|
||||
set 'signal_pfs_loc'.
|
||||
Manually generate the unwind info for the AR.PFS register.
|
||||
(ABI_MARKER_OLD_LINUX_SIGTRAMP, ABI_MARKER_OLD_LINUX_INTERRUPT,
|
||||
ABI_MARKER_LINUX_SIGTRAMP, ABI_MARKER_LINUX_INTERRUPT): Define.
|
||||
(ia64_handle_unwabi): Test 'fs->unwabi' against them.
|
||||
Do not set 'pfs_loc' to the AR.PFS location in the signal context;
|
||||
instead set 'signal_pfs_loc'.
|
||||
Remove code preventing the AR.PFS register from being restored
|
||||
from the signal context.
|
||||
|
||||
2009-08-14 Douglas B Rupp <rupp@gnat.com>
|
||||
Tristan Gingold <gingold@adacore.com>
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
/* Do code reading to identify a signal frame, and set the frame
|
||||
state data appropriately. See unwind-dw2.c for the structs. */
|
||||
state data appropriately. See unwind-ia64.c for the structs. */
|
||||
|
||||
/* This works only for glibc-2.3 and later, because sigcontext is different
|
||||
in glibc-2.2.4. */
|
||||
|
@ -66,7 +66,7 @@ ia64_fallback_frame_state (struct _Unwind_Context *context,
|
|||
}
|
||||
|
||||
context->fpsr_loc = &(sc->sc_ar_fpsr);
|
||||
context->pfs_loc = &(sc->sc_ar_pfs);
|
||||
context->signal_pfs_loc = &(sc->sc_ar_pfs);
|
||||
context->lc_loc = &(sc->sc_ar_lc);
|
||||
context->unat_loc = &(sc->sc_ar_unat);
|
||||
context->br_loc[0] = &(sc->sc_br[0]);
|
||||
|
@ -105,11 +105,17 @@ ia64_fallback_frame_state (struct _Unwind_Context *context,
|
|||
ia64_rse_skip_regs ((unsigned long *)(sc->sc_ar_bsp), -sof);
|
||||
}
|
||||
|
||||
/* Account for use of br.ret to resume execution of user code. */
|
||||
fs->curr.reg[UNW_REG_RP].where = UNW_WHERE_SPREL;
|
||||
fs->curr.reg[UNW_REG_RP].val
|
||||
= (unsigned long)&(sc->sc_ip) - context->psp;
|
||||
fs->curr.reg[UNW_REG_RP].when = -1;
|
||||
|
||||
fs->curr.reg[UNW_REG_PFS].where = UNW_WHERE_SPREL;
|
||||
fs->curr.reg[UNW_REG_PFS].val
|
||||
= (unsigned long)&(sc->sc_cfm) - context->psp;
|
||||
fs ->curr.reg[UNW_REG_PFS].when = -1;
|
||||
|
||||
return _URC_NO_REASON;
|
||||
}
|
||||
return _URC_END_OF_STACK;
|
||||
|
@ -117,11 +123,16 @@ ia64_fallback_frame_state (struct _Unwind_Context *context,
|
|||
|
||||
#define MD_HANDLE_UNWABI ia64_handle_unwabi
|
||||
|
||||
#define ABI_MARKER_OLD_LINUX_SIGTRAMP ((0 << 8) | 's')
|
||||
#define ABI_MARKER_OLD_LINUX_INTERRUPT ((0 << 8) | 'i')
|
||||
#define ABI_MARKER_LINUX_SIGTRAMP ((3 << 8) | 's')
|
||||
#define ABI_MARKER_LINUX_INTERRUPT ((3 << 8) | 'i')
|
||||
|
||||
static void
|
||||
ia64_handle_unwabi (struct _Unwind_Context *context, _Unwind_FrameState *fs)
|
||||
{
|
||||
if (fs->unwabi == ((3 << 8) | 's')
|
||||
|| fs->unwabi == ((0 << 8) | 's'))
|
||||
if (fs->unwabi == ABI_MARKER_LINUX_SIGTRAMP
|
||||
|| fs->unwabi == ABI_MARKER_OLD_LINUX_SIGTRAMP)
|
||||
{
|
||||
struct sigframe {
|
||||
char scratch[16];
|
||||
|
@ -144,7 +155,7 @@ ia64_handle_unwabi (struct _Unwind_Context *context, _Unwind_FrameState *fs)
|
|||
context->ireg[i - 2].loc = &sc->sc_gr[i];
|
||||
}
|
||||
|
||||
context->pfs_loc = &(sc->sc_ar_pfs);
|
||||
context->signal_pfs_loc = &(sc->sc_ar_pfs);
|
||||
context->lc_loc = &(sc->sc_ar_lc);
|
||||
context->unat_loc = &(sc->sc_ar_unat);
|
||||
context->br_loc[0] = &(sc->sc_br[0]);
|
||||
|
@ -181,9 +192,8 @@ ia64_handle_unwabi (struct _Unwind_Context *context, _Unwind_FrameState *fs)
|
|||
ia64_rse_skip_regs ((unsigned long *)(sc->sc_ar_bsp), -sof);
|
||||
}
|
||||
|
||||
/* pfs_loc already set above. Without this pfs_loc would point
|
||||
incorrectly to sc_cfm instead of sc_ar_pfs. */
|
||||
fs->curr.reg[UNW_REG_PFS].where = UNW_WHERE_NONE;
|
||||
/* The use of br.ret to resume execution of user code is already
|
||||
accounted for in the unwind ABI. */
|
||||
}
|
||||
}
|
||||
#endif /* glibc-2.3 or better */
|
||||
|
|
|
@ -204,6 +204,9 @@ struct _Unwind_Context
|
|||
unsigned long *pfs_loc; /* Save location for pfs in current
|
||||
(corr. to sp) frame. Target
|
||||
contains cfm for caller. */
|
||||
unsigned long *signal_pfs_loc;/* Save location for pfs in current
|
||||
signal frame. Target contains
|
||||
pfs for caller. */
|
||||
unsigned long *pri_unat_loc;
|
||||
unsigned long *unat_loc;
|
||||
unsigned long *lc_loc;
|
||||
|
@ -1786,6 +1789,7 @@ uw_frame_state_for (struct _Unwind_Context *context, _Unwind_FrameState *fs)
|
|||
#ifdef MD_FALLBACK_FRAME_STATE_FOR
|
||||
if (MD_FALLBACK_FRAME_STATE_FOR (context, fs) == _URC_NO_REASON)
|
||||
return _URC_NO_REASON;
|
||||
#endif
|
||||
|
||||
/* [SCRA 11.4.1] A leaf function with no memory stack, no exception
|
||||
handlers, and which keeps the return value in B0 does not need
|
||||
|
@ -1794,15 +1798,11 @@ uw_frame_state_for (struct _Unwind_Context *context, _Unwind_FrameState *fs)
|
|||
This can only happen in the frame after unwinding through a signal
|
||||
handler. Avoid infinite looping by requiring that B0 != RP.
|
||||
RP == 0 terminates the chain. */
|
||||
if (context->br_loc[0] && *context->br_loc[0] != context->rp
|
||||
if (context->br_loc[0]
|
||||
&& *context->br_loc[0] != context->rp
|
||||
&& context->rp != 0)
|
||||
{
|
||||
fs->curr.reg[UNW_REG_RP].where = UNW_WHERE_BR;
|
||||
fs->curr.reg[UNW_REG_RP].when = -1;
|
||||
fs->curr.reg[UNW_REG_RP].val = 0;
|
||||
return _URC_NO_REASON;
|
||||
}
|
||||
#endif
|
||||
goto skip_unwind_info;
|
||||
|
||||
return _URC_END_OF_STACK;
|
||||
}
|
||||
|
||||
|
@ -1850,7 +1850,8 @@ uw_frame_state_for (struct _Unwind_Context *context, _Unwind_FrameState *fs)
|
|||
r->where = UNW_WHERE_NONE;
|
||||
}
|
||||
|
||||
/* If RP did't get saved, generate entry for the return link register. */
|
||||
skip_unwind_info:
|
||||
/* If RP didn't get saved, generate entry for the return link register. */
|
||||
if (fs->curr.reg[UNW_REG_RP].when >= fs->when_target)
|
||||
{
|
||||
fs->curr.reg[UNW_REG_RP].where = UNW_WHERE_BR;
|
||||
|
@ -1858,6 +1859,27 @@ uw_frame_state_for (struct _Unwind_Context *context, _Unwind_FrameState *fs)
|
|||
fs->curr.reg[UNW_REG_RP].val = fs->return_link_reg;
|
||||
}
|
||||
|
||||
/* There is a subtlety for the frame after unwinding through a signal
|
||||
handler: should we restore the cfm as usual or the pfs? We can't
|
||||
restore both because we use br.ret to resume execution of user code.
|
||||
For other frames the procedure is by definition non-leaf so the pfs
|
||||
is saved and restored and thus effectively dead in the body; only
|
||||
the cfm need therefore be restored.
|
||||
|
||||
Here we have 2 cases:
|
||||
- either the pfs is saved and restored and thus effectively dead
|
||||
like in regular frames; then we do nothing special and restore
|
||||
the cfm.
|
||||
- or the pfs is not saved and thus live; but in that case the
|
||||
procedure is necessarily leaf so the cfm is effectively dead
|
||||
and we restore the pfs. */
|
||||
if (context->signal_pfs_loc)
|
||||
{
|
||||
if (fs->curr.reg[UNW_REG_PFS].when >= fs->when_target)
|
||||
context->pfs_loc = context->signal_pfs_loc;
|
||||
context->signal_pfs_loc = NULL;
|
||||
}
|
||||
|
||||
return _URC_NO_REASON;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue