📄 signal.c
字号:
oact->sa_restorer = tswapl(k->sa.sa_restorer); oact->sa_mask = k->sa.sa_mask; } if (act) { k->sa._sa_handler = tswapl(act->_sa_handler); k->sa.sa_flags = tswapl(act->sa_flags); k->sa.sa_restorer = tswapl(act->sa_restorer); k->sa.sa_mask = act->sa_mask; /* we update the host linux signal state */ host_sig = target_to_host_signal(sig); if (host_sig != SIGSEGV && host_sig != SIGBUS) { sigfillset(&act1.sa_mask); act1.sa_flags = SA_SIGINFO; if (k->sa.sa_flags & TARGET_SA_RESTART) act1.sa_flags |= SA_RESTART; /* NOTE: it is important to update the host kernel signal ignore state to avoid getting unexpected interrupted syscalls */ if (k->sa._sa_handler == TARGET_SIG_IGN) { act1.sa_sigaction = (void *)SIG_IGN; } else if (k->sa._sa_handler == TARGET_SIG_DFL) { act1.sa_sigaction = (void *)SIG_DFL; } else { act1.sa_sigaction = host_signal_handler; } sigaction(host_sig, &act1, NULL); } } return 0;}#ifndef offsetof#define offsetof(type, field) ((size_t) &((type *)0)->field)#endifstatic inline int copy_siginfo_to_user(target_siginfo_t *tinfo, const target_siginfo_t *info){ tswap_siginfo(tinfo, info); return 0;}#ifdef TARGET_I386/* from the Linux kernel */struct target_fpreg { uint16_t significand[4]; uint16_t exponent;};struct target_fpxreg { uint16_t significand[4]; uint16_t exponent; uint16_t padding[3];};struct target_xmmreg { target_ulong element[4];};struct target_fpstate { /* Regular FPU environment */ target_ulong cw; target_ulong sw; target_ulong tag; target_ulong ipoff; target_ulong cssel; target_ulong dataoff; target_ulong datasel; struct target_fpreg _st[8]; uint16_t status; uint16_t magic; /* 0xffff = regular FPU data only */ /* FXSR FPU environment */ target_ulong _fxsr_env[6]; /* FXSR FPU env is ignored */ target_ulong mxcsr; target_ulong reserved; struct target_fpxreg _fxsr_st[8]; /* FXSR FPU reg data is ignored */ struct target_xmmreg _xmm[8]; target_ulong padding[56];};#define X86_FXSR_MAGIC 0x0000struct target_sigcontext { uint16_t gs, __gsh; uint16_t fs, __fsh; uint16_t es, __esh; uint16_t ds, __dsh; target_ulong edi; target_ulong esi; target_ulong ebp; target_ulong esp; target_ulong ebx; target_ulong edx; target_ulong ecx; target_ulong eax; target_ulong trapno; target_ulong err; target_ulong eip; uint16_t cs, __csh; target_ulong eflags; target_ulong esp_at_signal; uint16_t ss, __ssh; target_ulong fpstate; /* pointer */ target_ulong oldmask; target_ulong cr2;};typedef struct target_sigaltstack { target_ulong ss_sp; int ss_flags; target_ulong ss_size;} target_stack_t;struct target_ucontext { target_ulong tuc_flags; target_ulong tuc_link; target_stack_t tuc_stack; struct target_sigcontext tuc_mcontext; target_sigset_t tuc_sigmask; /* mask last for extensibility */};struct sigframe{ target_ulong pretcode; int sig; struct target_sigcontext sc; struct target_fpstate fpstate; target_ulong extramask[TARGET_NSIG_WORDS-1]; char retcode[8];};struct rt_sigframe{ target_ulong pretcode; int sig; target_ulong pinfo; target_ulong puc; struct target_siginfo info; struct target_ucontext uc; struct target_fpstate fpstate; char retcode[8];};/* * Set up a signal frame. *//* XXX: save x87 state */static intsetup_sigcontext(struct target_sigcontext *sc, struct target_fpstate *fpstate, CPUX86State *env, unsigned long mask){ int err = 0; err |= __put_user(env->segs[R_GS].selector, (unsigned int *)&sc->gs); err |= __put_user(env->segs[R_FS].selector, (unsigned int *)&sc->fs); err |= __put_user(env->segs[R_ES].selector, (unsigned int *)&sc->es); err |= __put_user(env->segs[R_DS].selector, (unsigned int *)&sc->ds); err |= __put_user(env->regs[R_EDI], &sc->edi); err |= __put_user(env->regs[R_ESI], &sc->esi); err |= __put_user(env->regs[R_EBP], &sc->ebp); err |= __put_user(env->regs[R_ESP], &sc->esp); err |= __put_user(env->regs[R_EBX], &sc->ebx); err |= __put_user(env->regs[R_EDX], &sc->edx); err |= __put_user(env->regs[R_ECX], &sc->ecx); err |= __put_user(env->regs[R_EAX], &sc->eax); err |= __put_user(env->exception_index, &sc->trapno); err |= __put_user(env->error_code, &sc->err); err |= __put_user(env->eip, &sc->eip); err |= __put_user(env->segs[R_CS].selector, (unsigned int *)&sc->cs); err |= __put_user(env->eflags, &sc->eflags); err |= __put_user(env->regs[R_ESP], &sc->esp_at_signal); err |= __put_user(env->segs[R_SS].selector, (unsigned int *)&sc->ss); cpu_x86_fsave(env, (void *)fpstate, 1); fpstate->status = fpstate->sw; err |= __put_user(0xffff, &fpstate->magic); err |= __put_user(fpstate, &sc->fpstate); /* non-iBCS2 extensions.. */ err |= __put_user(mask, &sc->oldmask); err |= __put_user(env->cr[2], &sc->cr2); return err;}/* * Determine which stack to use.. */static inline void *get_sigframe(struct emulated_sigaction *ka, CPUX86State *env, size_t frame_size){ unsigned long esp; /* Default to using normal stack */ esp = env->regs[R_ESP];#if 0 /* This is the X/Open sanctioned signal stack switching. */ if (ka->sa.sa_flags & SA_ONSTACK) { if (sas_ss_flags(esp) == 0) esp = current->sas_ss_sp + current->sas_ss_size; } /* This is the legacy signal stack switching. */ else #endif if ((env->segs[R_SS].selector & 0xffff) != __USER_DS && !(ka->sa.sa_flags & TARGET_SA_RESTORER) && ka->sa.sa_restorer) { esp = (unsigned long) ka->sa.sa_restorer; } return g2h((esp - frame_size) & -8ul);}static void setup_frame(int sig, struct emulated_sigaction *ka, target_sigset_t *set, CPUX86State *env){ struct sigframe *frame; int i, err = 0; frame = get_sigframe(ka, env, sizeof(*frame)); if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) goto give_sigsegv; err |= __put_user((/*current->exec_domain && current->exec_domain->signal_invmap && sig < 32 ? current->exec_domain->signal_invmap[sig] : */ sig), &frame->sig); if (err) goto give_sigsegv; setup_sigcontext(&frame->sc, &frame->fpstate, env, set->sig[0]); if (err) goto give_sigsegv; for(i = 1; i < TARGET_NSIG_WORDS; i++) { if (__put_user(set->sig[i], &frame->extramask[i - 1])) goto give_sigsegv; } /* Set up to return from userspace. If provided, use a stub already in userspace. */ if (ka->sa.sa_flags & TARGET_SA_RESTORER) { err |= __put_user(ka->sa.sa_restorer, &frame->pretcode); } else { err |= __put_user(frame->retcode, &frame->pretcode); /* This is popl %eax ; movl $,%eax ; int $0x80 */ err |= __put_user(0xb858, (short *)(frame->retcode+0)); err |= __put_user(TARGET_NR_sigreturn, (int *)(frame->retcode+2)); err |= __put_user(0x80cd, (short *)(frame->retcode+6)); } if (err) goto give_sigsegv; /* Set up registers for signal handler */ env->regs[R_ESP] = h2g(frame); env->eip = (unsigned long) ka->sa._sa_handler; cpu_x86_load_seg(env, R_DS, __USER_DS); cpu_x86_load_seg(env, R_ES, __USER_DS); cpu_x86_load_seg(env, R_SS, __USER_DS); cpu_x86_load_seg(env, R_CS, __USER_CS); env->eflags &= ~TF_MASK; return;give_sigsegv: if (sig == TARGET_SIGSEGV) ka->sa._sa_handler = TARGET_SIG_DFL; force_sig(TARGET_SIGSEGV /* , current */);}static void setup_rt_frame(int sig, struct emulated_sigaction *ka, target_siginfo_t *info, target_sigset_t *set, CPUX86State *env){ struct rt_sigframe *frame; int i, err = 0; frame = get_sigframe(ka, env, sizeof(*frame)); if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) goto give_sigsegv; err |= __put_user((/*current->exec_domain && current->exec_domain->signal_invmap && sig < 32 ? current->exec_domain->signal_invmap[sig] : */sig), &frame->sig); err |= __put_user((target_ulong)&frame->info, &frame->pinfo); err |= __put_user((target_ulong)&frame->uc, &frame->puc); err |= copy_siginfo_to_user(&frame->info, info); if (err) goto give_sigsegv; /* Create the ucontext. */ err |= __put_user(0, &frame->uc.tuc_flags); err |= __put_user(0, &frame->uc.tuc_link); err |= __put_user(/*current->sas_ss_sp*/ 0, &frame->uc.tuc_stack.ss_sp); err |= __put_user(/* sas_ss_flags(regs->esp) */ 0, &frame->uc.tuc_stack.ss_flags); err |= __put_user(/* current->sas_ss_size */ 0, &frame->uc.tuc_stack.ss_size); err |= setup_sigcontext(&frame->uc.tuc_mcontext, &frame->fpstate, env, set->sig[0]); for(i = 0; i < TARGET_NSIG_WORDS; i++) { if (__put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i])) goto give_sigsegv; } /* Set up to return from userspace. If provided, use a stub already in userspace. */ if (ka->sa.sa_flags & TARGET_SA_RESTORER) { err |= __put_user(ka->sa.sa_restorer, &frame->pretcode); } else { err |= __put_user(frame->retcode, &frame->pretcode); /* This is movl $,%eax ; int $0x80 */ err |= __put_user(0xb8, (char *)(frame->retcode+0)); err |= __put_user(TARGET_NR_rt_sigreturn, (int *)(frame->retcode+1)); err |= __put_user(0x80cd, (short *)(frame->retcode+5)); } if (err) goto give_sigsegv; /* Set up registers for signal handler */ env->regs[R_ESP] = (unsigned long) frame; env->eip = (unsigned long) ka->sa._sa_handler; cpu_x86_load_seg(env, R_DS, __USER_DS); cpu_x86_load_seg(env, R_ES, __USER_DS); cpu_x86_load_seg(env, R_SS, __USER_DS); cpu_x86_load_seg(env, R_CS, __USER_CS); env->eflags &= ~TF_MASK; return;give_sigsegv: if (sig == TARGET_SIGSEGV) ka->sa._sa_handler = TARGET_SIG_DFL; force_sig(TARGET_SIGSEGV /* , current */);}static intrestore_sigcontext(CPUX86State *env, struct target_sigcontext *sc, int *peax){ unsigned int err = 0; cpu_x86_load_seg(env, R_GS, lduw(&sc->gs)); cpu_x86_load_seg(env, R_FS, lduw(&sc->fs)); cpu_x86_load_seg(env, R_ES, lduw(&sc->es)); cpu_x86_load_seg(env, R_DS, lduw(&sc->ds)); env->regs[R_EDI] = ldl(&sc->edi); env->regs[R_ESI] = ldl(&sc->esi); env->regs[R_EBP] = ldl(&sc->ebp); env->regs[R_ESP] = ldl(&sc->esp); env->regs[R_EBX] = ldl(&sc->ebx); env->regs[R_EDX] = ldl(&sc->edx); env->regs[R_ECX] = ldl(&sc->ecx); env->eip = ldl(&sc->eip); cpu_x86_load_seg(env, R_CS, lduw(&sc->cs) | 3); cpu_x86_load_seg(env, R_SS, lduw(&sc->ss) | 3); { unsigned int tmpflags; tmpflags = ldl(&sc->eflags); env->eflags = (env->eflags & ~0x40DD5) | (tmpflags & 0x40DD5); // regs->orig_eax = -1; /* disable syscall checks */ } { struct _fpstate * buf; buf = (void *)ldl(&sc->fpstate); if (buf) {#if 0 if (verify_area(VERIFY_READ, buf, sizeof(*buf))) goto badframe;#endif cpu_x86_frstor(env, (void *)buf, 1); } } *peax = ldl(&sc->eax); return err;#if 0badframe: return 1;#endif}long do_sigreturn(CPUX86State *env){ struct sigframe *frame = (struct sigframe *)g2h(env->regs[R_ESP] - 8); target_sigset_t target_set; sigset_t set; int eax, i;#if defined(DEBUG_SIGNAL) fprintf(stderr, "do_sigreturn\n");#endif /* set blocked signals */ if (__get_user(target_set.sig[0], &frame->sc.oldmask)) goto badframe; for(i = 1; i < TARGET_NSIG_WORDS; i++) { if (__get_user(target_set.sig[i], &frame->extramask[i - 1])) goto badframe; } target_to_host_sigset_internal(&set, &target_set); sigprocmask(SIG_SETMASK, &set, NULL); /* restore registers */ if (restore_sigcontext(env, &frame->sc, &eax)) goto badframe; return eax;badframe: force_sig(TARGET_SIGSEGV); return 0;}long do_rt_sigreturn(CPUX86State *env){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -