1
0
Fork 0
mirror of https://github.com/tobast/libunwind-eh_elf.git synced 2024-11-17 13:47:37 +01:00

Adjust for save-loc member renaming.

Adjust for renaming of Linux sigcontext offset macros.
(check_rbs_switch): Handle Linux-case only if abi_marker==ABI_MARKER_LINUX_SIGTRAMP.
(update_frame_state): For cursor's with a non-zero abi_marker, do special
	Linux or HP-UX sigtramp handling as appropriate.
	Clear abi_marker instead of is_signal_frame.

(Logical change 1.84)
This commit is contained in:
mostang.com!davidm 2003-04-23 05:56:59 +00:00
parent f24e3d70a0
commit 237a66bc21

View file

@ -38,12 +38,14 @@ check_rbs_switch (struct cursor *c)
{ {
/* Got ourselves a frame that has saved ar.bspstore, ar.bsp, /* Got ourselves a frame that has saved ar.bspstore, ar.bsp,
and ar.rnat, so we're all set for rbs-switching: */ and ar.rnat, so we're all set for rbs-switching: */
if ((ret = ia64_get (c, c->bsp_loc, &saved_bsp)) < 0 if ((ret = ia64_get (c, c->loc[IA64_REG_BSP], &saved_bsp)) < 0
|| (ret = ia64_get (c, c->bspstore_loc, &saved_bspstore))) || (ret = ia64_get (c, c->loc[IA64_REG_BSPSTORE], &saved_bspstore)))
return ret; return ret;
} }
else if (c->is_signal_frame else if (c->abi_marker == ABI_MARKER_LINUX_SIGTRAMP
&& c->bsp_loc == c->sigcontext_loc + SIGCONTEXT_AR_BSP_OFF) && !IA64_IS_REG_LOC (c->loc[IA64_REG_BSP])
&& (IA64_GET_ADDR (c->loc[IA64_REG_BSP])
== c->sigcontext_addr + LINUX_SC_AR_BSP_OFF))
{ {
/* When Linux delivers a signal on an alternate stack, it /* When Linux delivers a signal on an alternate stack, it
does things a bit differently from what the unwind does things a bit differently from what the unwind
@ -57,9 +59,11 @@ check_rbs_switch (struct cursor *c)
not equal to the saved value, then we know for sure that not equal to the saved value, then we know for sure that
we're past the point where the backing store has been we're past the point where the backing store has been
switched (and before the point where it's restored). */ switched (and before the point where it's restored). */
if ((ret = ia64_get (c, c->sigcontext_loc + SIGCONTEXT_AR_BSP_OFF, if ((ret = ia64_get (c, IA64_LOC_ADDR (c->sigcontext_addr
+ LINUX_SC_AR_BSP_OFF, 0),
&saved_bsp) < 0) &saved_bsp) < 0)
|| (ret = ia64_get (c, c->sigcontext_loc + SIGCONTEXT_LOADRS_OFF, || (ret = ia64_get (c, IA64_LOC_ADDR (c->sigcontext_addr
+ LINUX_SC_LOADRS_OFF, 0),
&loadrs) < 0)) &loadrs) < 0))
return ret; return ret;
loadrs >>= 16; loadrs >>= 16;
@ -70,7 +74,7 @@ check_rbs_switch (struct cursor *c)
if (saved_bsp == c->bsp) if (saved_bsp == c->bsp)
return 0; return 0;
return rbs_switch (c, saved_bsp, saved_bspstore, c->rnat_loc); return rbs_switch (c, saved_bsp, saved_bspstore, c->loc[IA64_REG_RNAT]);
} }
static inline int static inline int
@ -86,7 +90,7 @@ update_frame_state (struct cursor *c)
/* Update the IP cache (do this first: if we reach the end of the /* Update the IP cache (do this first: if we reach the end of the
frame-chain, the rest of the info may not be valid/useful frame-chain, the rest of the info may not be valid/useful
anymore. */ anymore. */
ret = ia64_get (c, c->ip_loc, &ip); ret = ia64_get (c, c->loc[IA64_REG_IP], &ip);
if (ret < 0) if (ret < 0)
return ret; return ret;
c->ip = ip; c->ip = ip;
@ -101,62 +105,80 @@ update_frame_state (struct cursor *c)
/* end of frame-chain reached */ /* end of frame-chain reached */
return 0; return 0;
c->cfm_loc = c->pfs_loc; c->cfm_loc = c->loc[IA64_REG_PFS];
/* update the CFM cache: */ /* update the CFM cache: */
ret = ia64_get (c, c->cfm_loc, &c->cfm); ret = ia64_get (c, c->cfm_loc, &c->cfm);
if (ret < 0) if (ret < 0)
return ret; return ret;
num_regs = 0; num_regs = 0;
if (c->is_signal_frame) if (c->abi_marker)
{ {
/* Caveat: #ifdef __hpux is wrong here. The code below is just switch (c->abi_marker)
a placeholder until HP-UX is fully supported. Once this gets
fixed, we need to check the unwind cursor to see if the
target is running HP-UX or Linux. We can infer that from the
.unwabi directive associated with a signal trampoline. */
#ifdef __hpux
/* HP-UX passes the address of ucontext_t in r32: */
ret = ia64_get_stacked (c, 32, &c->sigcontext_loc, NULL);
#else
ret = ia64_get (c, c->sp + 0x10 + SIGFRAME_ARG2_OFF, &c->sigcontext_loc);
#endif
debug (100, "%s: sigcontext_loc=%lx (ret=%d)\n",
__FUNCTION__, c->sigcontext_loc, ret);
if (ret < 0)
return ret;
c->sigcontext_off = c->sigcontext_loc - c->sp;
if (c->ip_loc == c->sigcontext_loc + SIGCONTEXT_BR_OFF + 0*8)
{ {
/* Earlier kernels (before 2.4.19 and 2.5.10) had buggy #if !defined(UNW_LOCAL_ONLY) || defined(__linux)
unwind info for sigtramp. Fix it up here. */ case ABI_MARKER_LINUX_SIGTRAMP:
c->ip_loc = (c->sigcontext_loc + SIGCONTEXT_IP_OFF); if ((ret = ia64_get (c, IA64_LOC_ADDR (c->sp + 0x10
c->cfm_loc = (c->sigcontext_loc + SIGCONTEXT_CFM_OFF); + LINUX_SIGFRAME_ARG2_OFF, 0),
/* update the IP cache: */ &c->sigcontext_addr)) < 0)
ret = ia64_get (c, c->ip_loc, &ip);
if (ret < 0)
return ret;
c->ip = ip;
if (ip == 0)
/* end of frame-chain reached */
return 0;
/* update the CFM cache: */
ret = ia64_get (c, c->cfm_loc, &c->cfm);
if (ret < 0)
return ret; return ret;
if (!IA64_IS_REG_LOC (c->loc[IA64_REG_IP])
&& (IA64_GET_ADDR (c->loc[IA64_REG_IP])
== c->sigcontext_addr + LINUX_SC_BR_OFF + 0*8))
{
/* Linux kernels before 2.4.19 and 2.5.10 had buggy
unwind info for sigtramp. Fix it up here. */
c->loc[IA64_REG_IP] = IA64_LOC_ADDR (c->sigcontext_addr
+ LINUX_SC_IP_OFF, 0);
c->cfm_loc = IA64_LOC_ADDR (c->sigcontext_addr
+ LINUX_SC_CFM_OFF, 0);
/* update the IP cache: */
if ((ret = ia64_get (c, c->loc[IA64_REG_IP], &ip)) < 0)
return ret;
c->ip = ip;
if (ip == 0)
/* end of frame-chain reached */
return 0;
/* update the CFM cache: */
if ((ret = ia64_get (c, c->cfm_loc, &c->cfm)) < 0)
return ret;
}
/* do what can't be described by unwind directives: */
c->loc[IA64_REG_PFS] = IA64_LOC_ADDR (c->sigcontext_addr
+ LINUX_SC_AR_PFS_OFF, 0);
break;
#endif
#if !defined(UNW_LOCAL_ONLY) || defined(__hpux)
case ABI_MARKER_HP_UX_SIGTRAMP:
{
ia64_loc_t sc_loc;
/* HP-UX passes the address of ucontext_t in r32: */
if ((ret = ia64_get_stacked (c, 32, &sc_loc, NULL)) < 0)
return ret;
c->sigcontext_addr = IA64_GET_ADDR (sc_loc);
}
break;
#endif
default:
debug (1, "%s: unknown ABI marker: ABI=%u, context=%u\n",
__FUNCTION__, c->abi_marker >> 8, c->abi_marker & 0xff);
return -UNW_EINVAL;
} }
debug (100, "%s: sigcontext_addr=%lx (ret=%d)\n",
__FUNCTION__, c->sigcontext_addr, ret);
/* do what can't be described by unwind directives: */ c->sigcontext_off = c->sigcontext_addr - c->sp;
c->pfs_loc = (c->sigcontext_loc + SIGCONTEXT_AR_PFS_OFF);
num_regs = c->cfm & 0x7f; /* size of frame */ num_regs = c->cfm & 0x7f; /* size of frame */
} }
else else
num_regs = (c->cfm >> 7) & 0x7f; /* size of locals */ num_regs = (c->cfm >> 7) & 0x7f; /* size of locals */
if (c->bsp_loc) if (!IA64_IS_NULL_LOC (c->loc[IA64_REG_BSP]))
{ {
ret = check_rbs_switch (c); ret = check_rbs_switch (c);
if (ret < 0) if (ret < 0)
@ -167,7 +189,7 @@ update_frame_state (struct cursor *c)
pr = c->pr; pr = c->pr;
c->sp = c->psp; c->sp = c->psp;
c->is_signal_frame = 0; c->abi_marker = 0;
if (c->ip == prev_ip && c->sp == prev_sp && c->bsp == prev_bsp) if (c->ip == prev_ip && c->sp == prev_sp && c->bsp == prev_bsp)
{ {
@ -177,10 +199,10 @@ update_frame_state (struct cursor *c)
} }
/* as we unwind, the saved ar.unat becomes the primary unat: */ /* as we unwind, the saved ar.unat becomes the primary unat: */
c->pri_unat_loc = c->unat_loc; c->loc[IA64_REG_PRI_UNAT_MEM] = c->loc[IA64_REG_UNAT];
/* restore the predicates: */ /* restore the predicates: */
ret = ia64_get (c, c->pr_loc, &c->pr); ret = ia64_get (c, c->loc[IA64_REG_PR], &c->pr);
if (ret < 0) if (ret < 0)
return ret; return ret;