aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2013-02-16 00:23:40 +1030
committerAlan Modra <amodra@gcc.gnu.org>2013-02-16 00:23:40 +1030
commit110207ad17b7fd10fc4c50a75e221831f372be6b (patch)
treec410c8f5af39ea8c001ef62fae6399b9fc3f6749
parent45e4e1e9585a9a0437c7b7eeaad552b77f9d29b3 (diff)
downloadgcc-110207ad17b7fd10fc4c50a75e221831f372be6b.zip
gcc-110207ad17b7fd10fc4c50a75e221831f372be6b.tar.gz
gcc-110207ad17b7fd10fc4c50a75e221831f372be6b.tar.bz2
re PR target/55431 (Invalid auxv search in ppc linux-unwind code.)
PR target/55431 * config/rs6000/linux-unwind.h (ppc_linux_aux_vector): Delete. (ppc_fallback_frame_state): Always set up save locations for fp and altivec. Don't bother with non-callee-saved regs, r0-r13 except for r2 on ppc64, fr0-fr13, v0-v19, vscr. From-SVN: r196077
-rw-r--r--libgcc/ChangeLog8
-rw-r--r--libgcc/config/rs6000/linux-unwind.h102
2 files changed, 33 insertions, 77 deletions
diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog
index e484e04..d4bc810 100644
--- a/libgcc/ChangeLog
+++ b/libgcc/ChangeLog
@@ -1,3 +1,11 @@
+2013-02-16 Alan Modra <amodra@gmail.com>
+
+ PR target/55431
+ * config/rs6000/linux-unwind.h (ppc_linux_aux_vector): Delete.
+ (ppc_fallback_frame_state): Always set up save locations for fp
+ and altivec. Don't bother with non-callee-saved regs, r0-r13
+ except for r2 on ppc64, fr0-fr13, v0-v19, vscr.
+
2013-02-12 Georg-Johann Lay <avr@gjlay.de>
PR target/54222
diff --git a/libgcc/config/rs6000/linux-unwind.h b/libgcc/config/rs6000/linux-unwind.h
index 3a2da6e..c9273c4 100644
--- a/libgcc/config/rs6000/linux-unwind.h
+++ b/libgcc/config/rs6000/linux-unwind.h
@@ -26,7 +26,6 @@
#define R_CR2 70
#define R_VR0 77
#define R_VRSAVE 109
-#define R_VSCR 110
struct gcc_vregs
{
@@ -175,38 +174,6 @@ get_regs (struct _Unwind_Context *context)
}
#endif
-/* Find an entry in the process auxiliary vector. The canonical way to
- test for VMX is to look at AT_HWCAP. */
-
-static long
-ppc_linux_aux_vector (long which)
-{
- /* __libc_stack_end holds the original stack passed to a process. */
- extern long *__libc_stack_end;
- long argc;
- char **argv;
- char **envp;
- struct auxv
- {
- long a_type;
- long a_val;
- } *auxp;
-
- /* The Linux kernel puts argc first on the stack. */
- argc = __libc_stack_end[0];
- /* Followed by argv, NULL terminated. */
- argv = (char **) __libc_stack_end + 1;
- /* Followed by environment string pointers, NULL terminated. */
- envp = argv + argc + 1;
- while (*envp++)
- continue;
- /* Followed by the aux vector, zero terminated. */
- for (auxp = (struct auxv *) envp; auxp->a_type != 0; ++auxp)
- if (auxp->a_type == which)
- return auxp->a_val;
- return 0;
-}
-
/* Do code reading to identify a signal frame, and set the frame
state data appropriately. See unwind-dw2.c for the structs. */
@@ -216,8 +183,8 @@ static _Unwind_Reason_Code
ppc_fallback_frame_state (struct _Unwind_Context *context,
_Unwind_FrameState *fs)
{
- static long hwcap = 0;
struct gcc_regs *regs = get_regs (context);
+ struct gcc_vregs *vregs;
long new_cfa;
int i;
@@ -229,12 +196,15 @@ ppc_fallback_frame_state (struct _Unwind_Context *context,
fs->regs.cfa_reg = STACK_POINTER_REGNUM;
fs->regs.cfa_offset = new_cfa - (long) context->cfa;
- for (i = 0; i < 32; i++)
- if (i != STACK_POINTER_REGNUM)
- {
- fs->regs.reg[i].how = REG_SAVED_OFFSET;
- fs->regs.reg[i].loc.offset = (long) &regs->gpr[i] - new_cfa;
- }
+#ifdef __powerpc64__
+ fs->regs.reg[2].how = REG_SAVED_OFFSET;
+ fs->regs.reg[2].loc.offset = (long) &regs->gpr[2] - new_cfa;
+#endif
+ for (i = 14; i < 32; i++)
+ {
+ fs->regs.reg[i].how = REG_SAVED_OFFSET;
+ fs->regs.reg[i].loc.offset = (long) &regs->gpr[i] - new_cfa;
+ }
fs->regs.reg[R_CR2].how = REG_SAVED_OFFSET;
/* CR? regs are always 32-bit and PPC is big-endian, so in 64-bit
@@ -250,57 +220,35 @@ ppc_fallback_frame_state (struct _Unwind_Context *context,
fs->retaddr_column = ARG_POINTER_REGNUM;
fs->signal_frame = 1;
- if (hwcap == 0)
+ /* If we have a FPU... */
+ for (i = 14; i < 32; i++)
{
- hwcap = ppc_linux_aux_vector (16);
- /* These will already be set if we found AT_HWCAP. A nonzero
- value stops us looking again if for some reason we couldn't
- find AT_HWCAP. */
-#ifdef __powerpc64__
- hwcap |= 0xc0000000;
-#else
- hwcap |= 0x80000000;
-#endif
+ fs->regs.reg[i + 32].how = REG_SAVED_OFFSET;
+ fs->regs.reg[i + 32].loc.offset = (long) &regs->fpr[i] - new_cfa;
}
- /* If we have a FPU... */
- if (hwcap & 0x08000000)
- for (i = 0; i < 32; i++)
- {
- fs->regs.reg[i + 32].how = REG_SAVED_OFFSET;
- fs->regs.reg[i + 32].loc.offset = (long) &regs->fpr[i] - new_cfa;
- }
-
/* If we have a VMX unit... */
- if (hwcap & 0x10000000)
- {
- struct gcc_vregs *vregs;
#ifdef __powerpc64__
- vregs = regs->vp;
+ vregs = regs->vp;
#else
- vregs = &regs->vregs;
+ vregs = &regs->vregs;
#endif
- if (regs->msr & (1 << 25))
+ if (regs->msr & (1 << 25))
+ {
+ for (i = 20; i < 32; i++)
{
- for (i = 0; i < 32; i++)
- {
- fs->regs.reg[i + R_VR0].how = REG_SAVED_OFFSET;
- fs->regs.reg[i + R_VR0].loc.offset
- = (long) &vregs->vr[i] - new_cfa;
- }
-
- fs->regs.reg[R_VSCR].how = REG_SAVED_OFFSET;
- fs->regs.reg[R_VSCR].loc.offset = (long) &vregs->vscr - new_cfa;
+ fs->regs.reg[i + R_VR0].how = REG_SAVED_OFFSET;
+ fs->regs.reg[i + R_VR0].loc.offset = (long) &vregs->vr[i] - new_cfa;
}
-
- fs->regs.reg[R_VRSAVE].how = REG_SAVED_OFFSET;
- fs->regs.reg[R_VRSAVE].loc.offset = (long) &vregs->vsave - new_cfa;
}
+ fs->regs.reg[R_VRSAVE].how = REG_SAVED_OFFSET;
+ fs->regs.reg[R_VRSAVE].loc.offset = (long) &vregs->vsave - new_cfa;
+
/* If we have SPE register high-parts... we check at compile-time to
avoid expanding the code for all other PowerPC. */
#ifdef __SPE__
- for (i = 0; i < 32; i++)
+ for (i = 14; i < 32; i++)
{
fs->regs.reg[i + FIRST_PSEUDO_REGISTER - 1].how = REG_SAVED_OFFSET;
fs->regs.reg[i + FIRST_PSEUDO_REGISTER - 1].loc.offset