aboutsummaryrefslogtreecommitdiff
path: root/linux-user
diff options
context:
space:
mode:
authorChen Gang <chengang@emindsoft.com.cn>2016-03-29 21:53:49 +0800
committerRiku Voipio <riku.voipio@linaro.org>2016-05-27 14:50:39 +0300
commitf1d9d1071c01bc5852750b0a829cf45f32cde709 (patch)
tree119a1baabb767fe656f85710595bb7fd37ca871b /linux-user
parent167e4cdc29985e69769452fade698c5b9df78b3d (diff)
linux-user/signal.c: Generate opcode data for restorer in setup_rt_frame
Original implementation uses do_rt_sigreturn directly in host space, when a guest program is in unwind procedure in guest space, it will get an incorrect restore address, then causes unwind failure. Also cleanup the original incorrect indentation. Reviewed-by: Laurent Vivier <laurent@vivier.eu> Signed-off-by: Chen Gang <gang.chen.5i5j@gmail.com> Signed-off-by: Riku Voipio <riku.voipio@linaro.org>
Diffstat (limited to 'linux-user')
-rw-r--r--linux-user/signal.c12
1 files changed, 10 insertions, 2 deletions
diff --git a/linux-user/signal.c b/linux-user/signal.c
index ff4de4fb8f..a072fa6efd 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -5599,8 +5599,13 @@ struct target_rt_sigframe {
unsigned char save_area[16]; /* caller save area */
struct target_siginfo info;
struct target_ucontext uc;
+ abi_ulong retcode[2];
};
+#define INSN_MOVELI_R10_139 0x00045fe551483000ULL /* { moveli r10, 139 } */
+#define INSN_SWINT1 0x286b180051485000ULL /* { swint1 } */
+
+
static void setup_sigcontext(struct target_sigcontext *sc,
CPUArchState *env, int signo)
{
@@ -5676,9 +5681,12 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka,
__put_user(target_sigaltstack_used.ss_size, &frame->uc.tuc_stack.ss_size);
setup_sigcontext(&frame->uc.tuc_mcontext, env, info->si_signo);
- restorer = (unsigned long) do_rt_sigreturn;
if (ka->sa_flags & TARGET_SA_RESTORER) {
- restorer = (unsigned long) ka->sa_restorer;
+ restorer = (unsigned long) ka->sa_restorer;
+ } else {
+ __put_user(INSN_MOVELI_R10_139, &frame->retcode[0]);
+ __put_user(INSN_SWINT1, &frame->retcode[1]);
+ restorer = frame_addr + offsetof(struct target_rt_sigframe, retcode);
}
env->pc = (unsigned long) ka->_sa_handler;
env->regs[TILEGX_R_SP] = (unsigned long) frame;