1
0
Fork 0
mirror of https://github.com/tobast/libunwind-eh_elf.git synced 2024-09-29 18:09:29 +02: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,
and ar.rnat, so we're all set for rbs-switching: */
if ((ret = ia64_get (c, c->bsp_loc, &saved_bsp)) < 0
|| (ret = ia64_get (c, c->bspstore_loc, &saved_bspstore)))
if ((ret = ia64_get (c, c->loc[IA64_REG_BSP], &saved_bsp)) < 0
|| (ret = ia64_get (c, c->loc[IA64_REG_BSPSTORE], &saved_bspstore)))
return ret;
}
else if (c->is_signal_frame
&& c->bsp_loc == c->sigcontext_loc + SIGCONTEXT_AR_BSP_OFF)
else if (c->abi_marker == ABI_MARKER_LINUX_SIGTRAMP
&& !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
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
we're past the point where the backing store has been
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)
|| (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))
return ret;
loadrs >>= 16;
@ -70,7 +74,7 @@ check_rbs_switch (struct cursor *c)
if (saved_bsp == c->bsp)
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
@ -86,7 +90,7 @@ update_frame_state (struct cursor *c)
/* 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
anymore. */
ret = ia64_get (c, c->ip_loc, &ip);
ret = ia64_get (c, c->loc[IA64_REG_IP], &ip);
if (ret < 0)
return ret;
c->ip = ip;
@ -101,62 +105,80 @@ update_frame_state (struct cursor *c)
/* end of frame-chain reached */
return 0;
c->cfm_loc = c->pfs_loc;
c->cfm_loc = c->loc[IA64_REG_PFS];
/* update the CFM cache: */
ret = ia64_get (c, c->cfm_loc, &c->cfm);
if (ret < 0)
return ret;
num_regs = 0;
if (c->is_signal_frame)
if (c->abi_marker)
{
/* Caveat: #ifdef __hpux is wrong here. The code below is just
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)
switch (c->abi_marker)
{
/* Earlier kernels (before 2.4.19 and 2.5.10) had buggy
unwind info for sigtramp. Fix it up here. */
c->ip_loc = (c->sigcontext_loc + SIGCONTEXT_IP_OFF);
c->cfm_loc = (c->sigcontext_loc + SIGCONTEXT_CFM_OFF);
/* update the IP cache: */
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)
#if !defined(UNW_LOCAL_ONLY) || defined(__linux)
case ABI_MARKER_LINUX_SIGTRAMP:
if ((ret = ia64_get (c, IA64_LOC_ADDR (c->sp + 0x10
+ LINUX_SIGFRAME_ARG2_OFF, 0),
&c->sigcontext_addr)) < 0)
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->pfs_loc = (c->sigcontext_loc + SIGCONTEXT_AR_PFS_OFF);
c->sigcontext_off = c->sigcontext_addr - c->sp;
num_regs = c->cfm & 0x7f; /* size of frame */
}
else
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);
if (ret < 0)
@ -167,7 +189,7 @@ update_frame_state (struct cursor *c)
pr = c->pr;
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)
{
@ -177,10 +199,10 @@ update_frame_state (struct cursor *c)
}
/* 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: */
ret = ia64_get (c, c->pr_loc, &c->pr);
ret = ia64_get (c, c->loc[IA64_REG_PR], &c->pr);
if (ret < 0)
return ret;