?? signal.c
字號:
/* XXX: test errors */ if(uoss_addr) { __put_user(target_sigaltstack_used.ss_sp, &oss.ss_sp); __put_user(target_sigaltstack_used.ss_size, &oss.ss_size); __put_user(sas_ss_flags(sp), &oss.ss_flags); } if(uss_addr) { struct target_sigaltstack *uss; struct target_sigaltstack ss; ret = -TARGET_EFAULT; if (!lock_user_struct(VERIFY_READ, uss, uss_addr, 1) || __get_user(ss.ss_sp, &uss->ss_sp) || __get_user(ss.ss_size, &uss->ss_size) || __get_user(ss.ss_flags, &uss->ss_flags)) goto out; unlock_user_struct(uss, uss_addr, 0); ret = -TARGET_EPERM; if (on_sig_stack(sp)) goto out; ret = -TARGET_EINVAL; if (ss.ss_flags != TARGET_SS_DISABLE && ss.ss_flags != TARGET_SS_ONSTACK && ss.ss_flags != 0) goto out; if (ss.ss_flags == TARGET_SS_DISABLE) { ss.ss_size = 0; ss.ss_sp = 0; } else { ret = -TARGET_ENOMEM; if (ss.ss_size < MINSIGSTKSZ) goto out; } target_sigaltstack_used.ss_sp = ss.ss_sp; target_sigaltstack_used.ss_size = ss.ss_size; } if (uoss_addr) { ret = -TARGET_EFAULT; if (copy_to_user(uoss_addr, &oss, sizeof(oss))) goto out; } ret = 0;out: return ret;}/* do_sigaction() return host values and errnos */int do_sigaction(int sig, const struct target_sigaction *act, struct target_sigaction *oact){ struct emulated_sigaction *k; struct sigaction act1; int host_sig; int ret = 0; if (sig < 1 || sig > TARGET_NSIG || sig == SIGKILL || sig == SIGSTOP) return -EINVAL; k = &sigact_table[sig - 1];#if defined(DEBUG_SIGNAL) fprintf(stderr, "sigaction sig=%d act=0x%08x, oact=0x%08x\n", sig, (int)act, (int)oact);#endif if (oact) { oact->_sa_handler = tswapl(k->sa._sa_handler); oact->sa_flags = tswapl(k->sa.sa_flags);#if !defined(TARGET_MIPS) oact->sa_restorer = tswapl(k->sa.sa_restorer);#endif 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);#if !defined(TARGET_MIPS) k->sa.sa_restorer = tswapl(act->sa_restorer);#endif 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; } ret = sigaction(host_sig, &act1, NULL); } } return ret;}#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;}static inline int current_exec_domain_sig(int sig){ return /* current->exec_domain && current->exec_domain->signal_invmap && sig < 32 ? current->exec_domain->signal_invmap[sig] : */ sig;}#if defined(TARGET_I386) && TARGET_ABI_BITS == 32/* 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 { abi_ulong element[4];};struct target_fpstate { /* Regular FPU environment */ abi_ulong cw; abi_ulong sw; abi_ulong tag; abi_ulong ipoff; abi_ulong cssel; abi_ulong dataoff; abi_ulong datasel; struct target_fpreg _st[8]; uint16_t status; uint16_t magic; /* 0xffff = regular FPU data only */ /* FXSR FPU environment */ abi_ulong _fxsr_env[6]; /* FXSR FPU env is ignored */ abi_ulong mxcsr; abi_ulong reserved; struct target_fpxreg _fxsr_st[8]; /* FXSR FPU reg data is ignored */ struct target_xmmreg _xmm[8]; abi_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; abi_ulong edi; abi_ulong esi; abi_ulong ebp; abi_ulong esp; abi_ulong ebx; abi_ulong edx; abi_ulong ecx; abi_ulong eax; abi_ulong trapno; abi_ulong err; abi_ulong eip; uint16_t cs, __csh; abi_ulong eflags; abi_ulong esp_at_signal; uint16_t ss, __ssh; abi_ulong fpstate; /* pointer */ abi_ulong oldmask; abi_ulong cr2;};struct target_ucontext { abi_ulong tuc_flags; abi_ulong tuc_link; target_stack_t tuc_stack; struct target_sigcontext tuc_mcontext; target_sigset_t tuc_sigmask; /* mask last for extensibility */};struct sigframe{ abi_ulong pretcode; int sig; struct target_sigcontext sc; struct target_fpstate fpstate; abi_ulong extramask[TARGET_NSIG_WORDS-1]; char retcode[8];};struct rt_sigframe{ abi_ulong pretcode; int sig; abi_ulong pinfo; abi_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, abi_ulong mask, abi_ulong fpstate_addr){ int err = 0; uint16_t magic; /* already locked in setup_frame() */ 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, fpstate_addr, 1); fpstate->status = fpstate->sw; magic = 0xffff; err |= __put_user(magic, &fpstate->magic); err |= __put_user(fpstate_addr, &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 abi_ulongget_sigframe(struct emulated_sigaction *ka, CPUX86State *env, size_t frame_size){ unsigned long esp; /* Default to using normal stack */ esp = env->regs[R_ESP]; /* This is the X/Open sanctioned signal stack switching. */ if (ka->sa.sa_flags & TARGET_SA_ONSTACK) { if (sas_ss_flags(esp) == 0) esp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size; } /* This is the legacy signal stack switching. */ else 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 (esp - frame_size) & -8ul;}/* compare linux/arch/i386/kernel/signal.c:setup_frame() */static void setup_frame(int sig, struct emulated_sigaction *ka, target_sigset_t *set, CPUX86State *env){ abi_ulong frame_addr; struct sigframe *frame; int i, err = 0; frame_addr = get_sigframe(ka, env, sizeof(*frame)); if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) goto give_sigsegv; err |= __put_user(current_exec_domain_sig(sig), &frame->sig); if (err) goto give_sigsegv; setup_sigcontext(&frame->sc, &frame->fpstate, env, set->sig[0], frame_addr + offsetof(struct sigframe, fpstate)); 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 { uint16_t val16; abi_ulong retcode_addr; retcode_addr = frame_addr + offsetof(struct sigframe, retcode); err |= __put_user(retcode_addr, &frame->pretcode); /* This is popl %eax ; movl $,%eax ; int $0x80 */ val16 = 0xb858; err |= __put_user(val16, (uint16_t *)(frame->retcode+0)); err |= __put_user(TARGET_NR_sigreturn, (int *)(frame->retcode+2)); val16 = 0x80cd; err |= __put_user(val16, (uint16_t *)(frame->retcode+6)); } if (err) goto give_sigsegv; /* Set up registers for signal handler */ env->regs[R_ESP] = frame_addr; env->eip = 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; unlock_user_struct(frame, frame_addr, 1); return;give_sigsegv: unlock_user_struct(frame, frame_addr, 1); if (sig == TARGET_SIGSEGV) ka->sa._sa_handler = TARGET_SIG_DFL; force_sig(TARGET_SIGSEGV /* , current */);}/* compare linux/arch/i386/kernel/signal.c:setup_rt_frame() */static void setup_rt_frame(int sig, struct emulated_sigaction *ka, target_siginfo_t *info, target_sigset_t *set, CPUX86State *env){ abi_ulong frame_addr, addr; struct rt_sigframe *frame; int i, err = 0; frame_addr = get_sigframe(ka, env, sizeof(*frame)); if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) goto give_sigsegv; err |= __put_user(current_exec_domain_sig(sig), &frame->sig); addr = frame_addr + offsetof(struct rt_sigframe, info); err |= __put_user(addr, &frame->pinfo); addr = frame_addr + offsetof(struct rt_sigframe, uc); err |= __put_user(addr, &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(target_sigaltstack_used.ss_sp, &frame->uc.tuc_stack.ss_sp); err |= __put_user(sas_ss_flags(get_sp_from_cpustate(env)), &frame->uc.tuc_stack.ss_flags); err |= __put_user(target_sigaltstack_used.ss_size, &frame->uc.tuc_stack.ss_size); err |= setup_sigcontext(&frame->uc.tuc_mcontext, &frame->fpstate, env, set->sig[0], frame_addr + offsetof(struct rt_sigframe, fpstate)); 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 { uint16_t val16; addr = frame_addr + offsetof(struct rt_sigframe, retcode); err |= __put_user(addr, &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)); val16 = 0x80cd; err |= __put_user(val16, (uint16_t *)(frame->retcode+5)); } if (err) goto give_sigsegv; /* Set up registers for signal handler */ env->regs[R_ESP] = frame_addr; env->eip = 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; unlock_user_struct(frame, frame_addr, 1); return;give_sigsegv: unlock_user_struct(frame, frame_addr, 1); if (sig == TARGET_SIGSEGV) ka->sa._sa_handler = TARGET_SIG_DFL;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -