signal.c

来自「xen虚拟机源代码安装包」· C语言 代码 · 共 2,221 行 · 第 1/5 页

C
2,221
字号
restore_sigcontext(CPUX86State *env, struct target_sigcontext *sc, int *peax){	unsigned int err = 0;        abi_ulong fpstate_addr;        unsigned int tmpflags;        cpu_x86_load_seg(env, R_GS, tswap16(sc->gs));        cpu_x86_load_seg(env, R_FS, tswap16(sc->fs));        cpu_x86_load_seg(env, R_ES, tswap16(sc->es));        cpu_x86_load_seg(env, R_DS, tswap16(sc->ds));        env->regs[R_EDI] = tswapl(sc->edi);        env->regs[R_ESI] = tswapl(sc->esi);        env->regs[R_EBP] = tswapl(sc->ebp);        env->regs[R_ESP] = tswapl(sc->esp);        env->regs[R_EBX] = tswapl(sc->ebx);        env->regs[R_EDX] = tswapl(sc->edx);        env->regs[R_ECX] = tswapl(sc->ecx);        env->eip = tswapl(sc->eip);        cpu_x86_load_seg(env, R_CS, lduw(&sc->cs) | 3);        cpu_x86_load_seg(env, R_SS, lduw(&sc->ss) | 3);        tmpflags = tswapl(sc->eflags);        env->eflags = (env->eflags & ~0x40DD5) | (tmpflags & 0x40DD5);        //		regs->orig_eax = -1;		/* disable syscall checks */        fpstate_addr = tswapl(sc->fpstate);	if (fpstate_addr != 0) {                if (!access_ok(VERIFY_READ, fpstate_addr,                                sizeof(struct target_fpstate)))                        goto badframe;                cpu_x86_frstor(env, fpstate_addr, 1);	}        *peax = tswapl(sc->eax);	return err;badframe:	return 1;}long do_sigreturn(CPUX86State *env){    struct sigframe *frame;    abi_ulong frame_addr = 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    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))        goto badframe;    /* 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;    unlock_user_struct(frame, frame_addr, 0);    return eax;badframe:    unlock_user_struct(frame, frame_addr, 0);    force_sig(TARGET_SIGSEGV);    return 0;}long do_rt_sigreturn(CPUX86State *env){        abi_ulong frame_addr;	struct rt_sigframe *frame;        sigset_t set;	int eax;        frame_addr = env->regs[R_ESP] - 4;        if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))                goto badframe;        target_to_host_sigset(&set, &frame->uc.tuc_sigmask);        sigprocmask(SIG_SETMASK, &set, NULL);	if (restore_sigcontext(env, &frame->uc.tuc_mcontext, &eax))		goto badframe;	if (do_sigaltstack(frame_addr + offsetof(struct rt_sigframe, uc.tuc_stack), 0,                            get_sp_from_cpustate(env)) == -EFAULT)		goto badframe;        unlock_user_struct(frame, frame_addr, 0);	return eax;badframe:        unlock_user_struct(frame, frame_addr, 0);        force_sig(TARGET_SIGSEGV);	return 0;}#elif defined(TARGET_ARM)struct target_sigcontext {	abi_ulong trap_no;	abi_ulong error_code;	abi_ulong oldmask;	abi_ulong arm_r0;	abi_ulong arm_r1;	abi_ulong arm_r2;	abi_ulong arm_r3;	abi_ulong arm_r4;	abi_ulong arm_r5;	abi_ulong arm_r6;	abi_ulong arm_r7;	abi_ulong arm_r8;	abi_ulong arm_r9;	abi_ulong arm_r10;	abi_ulong arm_fp;	abi_ulong arm_ip;	abi_ulong arm_sp;	abi_ulong arm_lr;	abi_ulong arm_pc;	abi_ulong arm_cpsr;	abi_ulong fault_address;};struct target_ucontext_v1 {    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 target_ucontext_v2 {    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 */    char __unused[128 - sizeof(sigset_t)];    abi_ulong tuc_regspace[128] __attribute__((__aligned__(8)));};struct sigframe_v1{    struct target_sigcontext sc;    abi_ulong extramask[TARGET_NSIG_WORDS-1];    abi_ulong retcode;};struct sigframe_v2{    struct target_ucontext_v2 uc;    abi_ulong retcode;};struct rt_sigframe_v1{    abi_ulong pinfo;    abi_ulong puc;    struct target_siginfo info;    struct target_ucontext_v1 uc;    abi_ulong retcode;};struct rt_sigframe_v2{    struct target_siginfo info;    struct target_ucontext_v2 uc;    abi_ulong retcode;};#define TARGET_CONFIG_CPU_32 1/* * For ARM syscalls, we encode the syscall number into the instruction. */#define SWI_SYS_SIGRETURN	(0xef000000|(TARGET_NR_sigreturn + ARM_SYSCALL_BASE))#define SWI_SYS_RT_SIGRETURN	(0xef000000|(TARGET_NR_rt_sigreturn + ARM_SYSCALL_BASE))/* * For Thumb syscalls, we pass the syscall number via r7.  We therefore * need two 16-bit instructions. */#define SWI_THUMB_SIGRETURN	(0xdf00 << 16 | 0x2700 | (TARGET_NR_sigreturn))#define SWI_THUMB_RT_SIGRETURN	(0xdf00 << 16 | 0x2700 | (TARGET_NR_rt_sigreturn))static const abi_ulong retcodes[4] = {	SWI_SYS_SIGRETURN,	SWI_THUMB_SIGRETURN,	SWI_SYS_RT_SIGRETURN,	SWI_THUMB_RT_SIGRETURN};#define __get_user_error(x,p,e) __get_user(x, p)static inline int valid_user_regs(CPUState *regs){    return 1;}static voidsetup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/		 CPUState *env, abi_ulong mask){	__put_user(env->regs[0], &sc->arm_r0);	__put_user(env->regs[1], &sc->arm_r1);	__put_user(env->regs[2], &sc->arm_r2);	__put_user(env->regs[3], &sc->arm_r3);	__put_user(env->regs[4], &sc->arm_r4);	__put_user(env->regs[5], &sc->arm_r5);	__put_user(env->regs[6], &sc->arm_r6);	__put_user(env->regs[7], &sc->arm_r7);	__put_user(env->regs[8], &sc->arm_r8);	__put_user(env->regs[9], &sc->arm_r9);	__put_user(env->regs[10], &sc->arm_r10);	__put_user(env->regs[11], &sc->arm_fp);	__put_user(env->regs[12], &sc->arm_ip);	__put_user(env->regs[13], &sc->arm_sp);	__put_user(env->regs[14], &sc->arm_lr);	__put_user(env->regs[15], &sc->arm_pc);#ifdef TARGET_CONFIG_CPU_32	__put_user(cpsr_read(env), &sc->arm_cpsr);#endif	__put_user(/* current->thread.trap_no */ 0, &sc->trap_no);	__put_user(/* current->thread.error_code */ 0, &sc->error_code);	__put_user(/* current->thread.address */ 0, &sc->fault_address);	__put_user(mask, &sc->oldmask);}static inline abi_ulongget_sigframe(struct emulated_sigaction *ka, CPUState *regs, int framesize){	unsigned long sp = regs->regs[13];	/*	 * This is the X/Open sanctioned signal stack switching.	 */	if ((ka->sa.sa_flags & TARGET_SA_ONSTACK) && !sas_ss_flags(sp))            sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;	/*	 * ATPCS B01 mandates 8-byte alignment	 */	return (sp - framesize) & ~7;}static intsetup_return(CPUState *env, struct emulated_sigaction *ka,	     abi_ulong *rc, abi_ulong frame_addr, int usig, abi_ulong rc_addr){	abi_ulong handler = ka->sa._sa_handler;	abi_ulong retcode;	int thumb = handler & 1;	if (ka->sa.sa_flags & TARGET_SA_RESTORER) {		retcode = ka->sa.sa_restorer;	} else {		unsigned int idx = thumb;		if (ka->sa.sa_flags & TARGET_SA_SIGINFO)			idx += 2;		if (__put_user(retcodes[idx], rc))			return 1;#if 0		flush_icache_range((abi_ulong)rc,				   (abi_ulong)(rc + 1));#endif		retcode = rc_addr + thumb;	}	env->regs[0] = usig;	env->regs[13] = frame_addr;	env->regs[14] = retcode;	env->regs[15] = handler & (thumb ? ~1 : ~3);	env->thumb = thumb;#if 0#ifdef TARGET_CONFIG_CPU_32	env->cpsr = cpsr;#endif#endif	return 0;}static void setup_sigframe_v2(struct target_ucontext_v2 *uc,                              target_sigset_t *set, CPUState *env){    struct target_sigaltstack stack;    int i;    /* Clear all the bits of the ucontext we don't use.  */    memset(uc, 0, offsetof(struct target_ucontext_v2, tuc_mcontext));    memset(&stack, 0, sizeof(stack));    __put_user(target_sigaltstack_used.ss_sp, &stack.ss_sp);    __put_user(target_sigaltstack_used.ss_size, &stack.ss_size);    __put_user(sas_ss_flags(get_sp_from_cpustate(env)), &stack.ss_flags);    memcpy(&uc->tuc_stack, &stack, sizeof(stack));    setup_sigcontext(&uc->tuc_mcontext, env, set->sig[0]);    /* FIXME: Save coprocessor signal frame.  */    for(i = 0; i < TARGET_NSIG_WORDS; i++) {        __put_user(set->sig[i], &uc->tuc_sigmask.sig[i]);    }}/* compare linux/arch/arm/kernel/signal.c:setup_frame() */static void setup_frame_v1(int usig, struct emulated_sigaction *ka,			   target_sigset_t *set, CPUState *regs){	struct sigframe_v1 *frame;	abi_ulong frame_addr = get_sigframe(ka, regs, sizeof(*frame));	int i;	if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))		return;	setup_sigcontext(&frame->sc, regs, set->sig[0]);        for(i = 1; i < TARGET_NSIG_WORDS; i++) {            if (__put_user(set->sig[i], &frame->extramask[i - 1]))                goto end;	}        setup_return(regs, ka, &frame->retcode, frame_addr, usig,                     frame_addr + offsetof(struct sigframe_v1, retcode));end:	unlock_user_struct(frame, frame_addr, 1);}static void setup_frame_v2(int usig, struct emulated_sigaction *ka,			   target_sigset_t *set, CPUState *regs){	struct sigframe_v2 *frame;	abi_ulong frame_addr = get_sigframe(ka, regs, sizeof(*frame));	if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))		return;        setup_sigframe_v2(&frame->uc, set, regs);        setup_return(regs, ka, &frame->retcode, frame_addr, usig,                     frame_addr + offsetof(struct sigframe_v2, retcode));	unlock_user_struct(frame, frame_addr, 1);}static void setup_frame(int usig, struct emulated_sigaction *ka,			target_sigset_t *set, CPUState *regs){    if (get_osversion() >= 0x020612) {        setup_frame_v2(usig, ka, set, regs);    } else {        setup_frame_v1(usig, ka, set, regs);    }}/* compare linux/arch/arm/kernel/signal.c:setup_rt_frame() */static void setup_rt_frame_v1(int usig, struct emulated_sigaction *ka,                              target_siginfo_t *info,			      target_sigset_t *set, CPUState *env){	struct rt_sigframe_v1 *frame;	abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame));	struct target_sigaltstack stack;	int i;        abi_ulong info_addr, uc_addr;	if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))            return /* 1 */;        info_addr = frame_addr + offsetof(struct rt_sigframe_v1, info);	__put_user(info_addr, &frame->pinfo);        uc_addr = frame_addr + offsetof(struct rt_sigframe_v1, uc);	__put_user(uc_addr, &frame->puc);	copy_siginfo_to_user(&frame->info, info);	/* Clear all the bits of the ucontext we don't use.  */	memset(&frame->uc, 0, offsetof(struct target_ucontext_v1, tuc_mcontext));        memset(&stack, 0, sizeof(stack));        __put_user(target_sigaltstack_used.ss_sp, &stack.ss_sp);        __put_user(target_sigaltstack_used.ss_size, &stack.ss_size);        __put_user(sas_ss_flags(get_sp_from_cpustate(env)), &stack.ss_flags);        memcpy(&frame->uc.tuc_stack, &stack, sizeof(stack));	setup_sigcontext(&frame->uc.tuc_mcontext, 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 end;        }        setup_return(env, ka, &frame->retcode, frame_addr, usig,                     frame_addr + offsetof(struct rt_sigframe_v1, retcode));        env->regs[1] = info_addr;        env->regs[2] = uc_addr;end:	unlock_user_struct(frame, frame_addr, 1);}static void setup_rt_frame_v2(int usig, struct emulated_sigaction *ka,                              target_siginfo_t *info,                              target_sigset_t *set, CPUState *env){	struct rt_sigframe_v2 *frame;	abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame));        abi_ulong info_addr, uc_addr;	if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))            return /* 1 */;        info_addr = frame_addr + offsetof(struct rt_sigframe_v2, info);        uc_addr = frame_addr + offsetof(struct rt_sigframe_v2, uc);	copy_siginfo_to_user(&frame->info, info);        setup_sigframe_v2(&frame->uc, set, env);        setup_return(env, ka, &frame->retcode, frame_addr, usig,                     frame_addr + offsetof(struct rt_sigframe_v2, retcode));        env->regs[1] = info_addr;        env->regs[2] = uc_addr;	unlock_user_struct(frame, frame_addr, 1);}static void setup_rt_frame(int usig, struct emulated_sigaction *ka,                           target_siginfo_t *info,			   target_sigset_t *set, CPUState *env){    if (get_osversion() >= 0x020612) {        setup_rt_frame_v2(usig, ka, info, set, env);    } else {

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?