diff options
author | Tom Musta <tommusta@gmail.com> | 2014-06-30 08:13:39 -0500 |
---|---|---|
committer | Alexander Graf <agraf@suse.de> | 2014-09-08 12:50:46 +0200 |
commit | 8d6ab333ebf2751d2467bd7dae94a04742052e26 (patch) | |
tree | 09786e24fa43cdef45e711b98cc1b2d962267d6f /linux-user | |
parent | 61e75fecef17aff4b0ecef26b300b90de410aaa2 (diff) |
linux-user: Properly Dereference PPC64 ELFv1 Signal Handler Pointer
Properly dereference 64-bit PPC ELF V1 ABIT function pointers to signal handlers.
On this platform, function pointers are pointers to structures and the first 64
bits of such a structure contains the function's entry point. The second 64 bits
contains the TOC pointer, which must be placed into GPR 2.
Signed-off-by: Tom Musta <tommusta@gmail.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
Diffstat (limited to 'linux-user')
-rw-r--r-- | linux-user/signal.c | 29 |
1 files changed, 29 insertions, 0 deletions
diff --git a/linux-user/signal.c b/linux-user/signal.c index 56c38db4b3..e8e49db9dd 100644 --- a/linux-user/signal.c +++ b/linux-user/signal.c @@ -4483,6 +4483,15 @@ struct target_rt_sigframe { #endif +#if defined(TARGET_PPC64) + +struct target_func_ptr { + target_ulong entry; + target_ulong toc; +}; + +#endif + /* We use the mc_pad field for the signal return trampoline. */ #define tramp mc_pad @@ -4714,7 +4723,17 @@ static void setup_frame(int sig, struct target_sigaction *ka, env->gpr[1] = newsp; env->gpr[3] = signal; env->gpr[4] = frame_addr + offsetof(struct target_sigframe, sctx); + +#if defined(TARGET_PPC64) + /* PPC64 function pointers are pointers to OPD entries. */ + struct target_func_ptr *handler = + (struct target_func_ptr *)g2h(ka->_sa_handler); + env->nip = tswapl(handler->entry); + env->gpr[2] = tswapl(handler->toc); +#else env->nip = (target_ulong) ka->_sa_handler; +#endif + /* Signal handlers are entered in big-endian mode. */ env->msr &= ~MSR_LE; @@ -4793,7 +4812,17 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka, env->gpr[4] = (target_ulong) h2g(&rt_sf->info); env->gpr[5] = (target_ulong) h2g(&rt_sf->uc); env->gpr[6] = (target_ulong) h2g(rt_sf); + +#if defined(TARGET_PPC64) + /* PPC64 function pointers are pointers to OPD entries. */ + struct target_func_ptr *handler = + (struct target_func_ptr *)g2h(ka->_sa_handler); + env->nip = tswapl(handler->entry); + env->gpr[2] = tswapl(handler->toc); +#else env->nip = (target_ulong) ka->_sa_handler; +#endif + /* Signal handlers are entered in big-endian mode. */ env->msr &= ~MSR_LE; |