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:
Eric Botcazou 2009-08-14 20:49:40 +00:00 committed by Douglas Rupp
parent c24db30451
commit ac77b88e52
3 changed files with 69 additions and 17 deletions

View File

@ -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>

View File

@ -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 */

View File

@ -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;
}