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 + -
显示快捷键?