Revision 28be6234
b/linux-user/signal.c | ||
---|---|---|
667 | 667 |
/* XXX: save x87 state */ |
668 | 668 |
static int |
669 | 669 |
setup_sigcontext(struct target_sigcontext *sc, struct target_fpstate *fpstate, |
670 |
CPUX86State *env, unsigned long mask)
|
|
670 |
CPUX86State *env, abi_ulong mask, abi_ulong fpstate_addr)
|
|
671 | 671 |
{ |
672 | 672 |
int err = 0; |
673 | 673 |
uint16_t magic; |
... | ... | |
693 | 693 |
err |= __put_user(env->regs[R_ESP], &sc->esp_at_signal); |
694 | 694 |
err |= __put_user(env->segs[R_SS].selector, (unsigned int *)&sc->ss); |
695 | 695 |
|
696 |
cpu_x86_fsave(env, (void *)fpstate, 1);
|
|
696 |
cpu_x86_fsave(env, fpstate_addr, 1);
|
|
697 | 697 |
fpstate->status = fpstate->sw; |
698 | 698 |
magic = 0xffff; |
699 | 699 |
err |= __put_user(magic, &fpstate->magic); |
700 |
err |= __put_user(fpstate, &sc->fpstate); |
|
700 |
err |= __put_user(fpstate_addr, &sc->fpstate);
|
|
701 | 701 |
|
702 | 702 |
/* non-iBCS2 extensions.. */ |
703 | 703 |
err |= __put_user(mask, &sc->oldmask); |
... | ... | |
754 | 754 |
if (err) |
755 | 755 |
goto give_sigsegv; |
756 | 756 |
|
757 |
setup_sigcontext(&frame->sc, &frame->fpstate, env, set->sig[0]); |
|
757 |
setup_sigcontext(&frame->sc, &frame->fpstate, env, set->sig[0], |
|
758 |
frame_addr + offsetof(struct sigframe, fpstate)); |
|
758 | 759 |
if (err) |
759 | 760 |
goto give_sigsegv; |
760 | 761 |
|
... | ... | |
769 | 770 |
err |= __put_user(ka->sa.sa_restorer, &frame->pretcode); |
770 | 771 |
} else { |
771 | 772 |
uint16_t val16; |
772 |
err |= __put_user(frame->retcode, &frame->pretcode); |
|
773 |
abi_ulong retcode_addr; |
|
774 |
retcode_addr = frame_addr + offsetof(struct sigframe, retcode); |
|
775 |
err |= __put_user(retcode_addr, &frame->pretcode); |
|
773 | 776 |
/* This is popl %eax ; movl $,%eax ; int $0x80 */ |
774 | 777 |
val16 = 0xb858; |
775 | 778 |
err |= __put_user(val16, (uint16_t *)(frame->retcode+0)); |
... | ... | |
782 | 785 |
goto give_sigsegv; |
783 | 786 |
|
784 | 787 |
/* Set up registers for signal handler */ |
785 |
env->regs[R_ESP] = h2g(frame);
|
|
786 |
env->eip = (unsigned long) ka->sa._sa_handler;
|
|
788 |
env->regs[R_ESP] = frame_addr;
|
|
789 |
env->eip = ka->sa._sa_handler; |
|
787 | 790 |
|
788 | 791 |
cpu_x86_load_seg(env, R_DS, __USER_DS); |
789 | 792 |
cpu_x86_load_seg(env, R_ES, __USER_DS); |
... | ... | |
807 | 810 |
target_siginfo_t *info, |
808 | 811 |
target_sigset_t *set, CPUX86State *env) |
809 | 812 |
{ |
810 |
abi_ulong frame_addr;
|
|
813 |
abi_ulong frame_addr, addr;
|
|
811 | 814 |
struct rt_sigframe *frame; |
812 | 815 |
int i, err = 0; |
813 | 816 |
|
... | ... | |
822 | 825 |
? current->exec_domain->signal_invmap[sig] |
823 | 826 |
: */sig), |
824 | 827 |
&frame->sig); |
825 |
err |= __put_user((abi_ulong)&frame->info, &frame->pinfo); |
|
826 |
err |= __put_user((abi_ulong)&frame->uc, &frame->puc); |
|
828 |
addr = frame_addr + offsetof(struct rt_sigframe, info); |
|
829 |
err |= __put_user(addr, &frame->pinfo); |
|
830 |
addr = frame_addr + offsetof(struct rt_sigframe, uc); |
|
831 |
err |= __put_user(addr, &frame->puc); |
|
827 | 832 |
err |= copy_siginfo_to_user(&frame->info, info); |
828 | 833 |
if (err) |
829 | 834 |
goto give_sigsegv; |
... | ... | |
838 | 843 |
err |= __put_user(target_sigaltstack_used.ss_size, |
839 | 844 |
&frame->uc.tuc_stack.ss_size); |
840 | 845 |
err |= setup_sigcontext(&frame->uc.tuc_mcontext, &frame->fpstate, |
841 |
env, set->sig[0]); |
|
846 |
env, set->sig[0], |
|
847 |
frame_addr + offsetof(struct rt_sigframe, fpstate)); |
|
842 | 848 |
for(i = 0; i < TARGET_NSIG_WORDS; i++) { |
843 | 849 |
if (__put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i])) |
844 | 850 |
goto give_sigsegv; |
... | ... | |
850 | 856 |
err |= __put_user(ka->sa.sa_restorer, &frame->pretcode); |
851 | 857 |
} else { |
852 | 858 |
uint16_t val16; |
853 |
|
|
854 |
err |= __put_user(frame->retcode, &frame->pretcode);
|
|
859 |
addr = frame_addr + offsetof(struct rt_sigframe, retcode); |
|
860 |
err |= __put_user(addr, &frame->pretcode);
|
|
855 | 861 |
/* This is movl $,%eax ; int $0x80 */ |
856 | 862 |
err |= __put_user(0xb8, (char *)(frame->retcode+0)); |
857 | 863 |
err |= __put_user(TARGET_NR_rt_sigreturn, (int *)(frame->retcode+1)); |
... | ... | |
863 | 869 |
goto give_sigsegv; |
864 | 870 |
|
865 | 871 |
/* Set up registers for signal handler */ |
866 |
env->regs[R_ESP] = (unsigned long) frame;
|
|
867 |
env->eip = (unsigned long) ka->sa._sa_handler;
|
|
872 |
env->regs[R_ESP] = frame_addr;
|
|
873 |
env->eip = ka->sa._sa_handler; |
|
868 | 874 |
|
869 | 875 |
cpu_x86_load_seg(env, R_DS, __USER_DS); |
870 | 876 |
cpu_x86_load_seg(env, R_ES, __USER_DS); |
... | ... | |
887 | 893 |
restore_sigcontext(CPUX86State *env, struct target_sigcontext *sc, int *peax) |
888 | 894 |
{ |
889 | 895 |
unsigned int err = 0; |
890 |
|
|
891 |
cpu_x86_load_seg(env, R_GS, lduw(&sc->gs)); |
|
892 |
cpu_x86_load_seg(env, R_FS, lduw(&sc->fs)); |
|
893 |
cpu_x86_load_seg(env, R_ES, lduw(&sc->es)); |
|
894 |
cpu_x86_load_seg(env, R_DS, lduw(&sc->ds)); |
|
895 |
|
|
896 |
env->regs[R_EDI] = ldl(&sc->edi); |
|
897 |
env->regs[R_ESI] = ldl(&sc->esi); |
|
898 |
env->regs[R_EBP] = ldl(&sc->ebp); |
|
899 |
env->regs[R_ESP] = ldl(&sc->esp); |
|
900 |
env->regs[R_EBX] = ldl(&sc->ebx); |
|
901 |
env->regs[R_EDX] = ldl(&sc->edx); |
|
902 |
env->regs[R_ECX] = ldl(&sc->ecx); |
|
903 |
env->eip = ldl(&sc->eip); |
|
896 |
abi_ulong fpstate_addr; |
|
897 |
unsigned int tmpflags; |
|
898 |
|
|
899 |
cpu_x86_load_seg(env, R_GS, tswap16(sc->gs)); |
|
900 |
cpu_x86_load_seg(env, R_FS, tswap16(sc->fs)); |
|
901 |
cpu_x86_load_seg(env, R_ES, tswap16(sc->es)); |
|
902 |
cpu_x86_load_seg(env, R_DS, tswap16(sc->ds)); |
|
903 |
|
|
904 |
env->regs[R_EDI] = tswapl(sc->edi); |
|
905 |
env->regs[R_ESI] = tswapl(sc->esi); |
|
906 |
env->regs[R_EBP] = tswapl(sc->ebp); |
|
907 |
env->regs[R_ESP] = tswapl(sc->esp); |
|
908 |
env->regs[R_EBX] = tswapl(sc->ebx); |
|
909 |
env->regs[R_EDX] = tswapl(sc->edx); |
|
910 |
env->regs[R_ECX] = tswapl(sc->ecx); |
|
911 |
env->eip = tswapl(sc->eip); |
|
904 | 912 |
|
905 | 913 |
cpu_x86_load_seg(env, R_CS, lduw(&sc->cs) | 3); |
906 | 914 |
cpu_x86_load_seg(env, R_SS, lduw(&sc->ss) | 3); |
907 | 915 |
|
908 |
{ |
|
909 |
unsigned int tmpflags; |
|
910 |
tmpflags = ldl(&sc->eflags); |
|
911 |
env->eflags = (env->eflags & ~0x40DD5) | (tmpflags & 0x40DD5); |
|
912 |
// regs->orig_eax = -1; /* disable syscall checks */ |
|
913 |
} |
|
916 |
tmpflags = tswapl(sc->eflags); |
|
917 |
env->eflags = (env->eflags & ~0x40DD5) | (tmpflags & 0x40DD5); |
|
918 |
// regs->orig_eax = -1; /* disable syscall checks */ |
|
914 | 919 |
|
915 |
{ |
|
916 |
struct _fpstate * buf; |
|
917 |
buf = (void *)ldl(&sc->fpstate); |
|
918 |
if (buf) { |
|
919 |
#if 0 |
|
920 |
if (verify_area(VERIFY_READ, buf, sizeof(*buf))) |
|
921 |
goto badframe; |
|
922 |
#endif |
|
923 |
cpu_x86_frstor(env, (void *)buf, 1); |
|
924 |
} |
|
920 |
fpstate_addr = tswapl(sc->fpstate); |
|
921 |
if (fpstate_addr != 0) { |
|
922 |
if (!access_ok(VERIFY_READ, fpstate_addr, |
|
923 |
sizeof(struct target_fpstate))) |
|
924 |
goto badframe; |
|
925 |
cpu_x86_frstor(env, fpstate_addr, 1); |
|
925 | 926 |
} |
926 | 927 |
|
927 |
*peax = ldl(&sc->eax);
|
|
928 |
*peax = tswapl(sc->eax);
|
|
928 | 929 |
return err; |
929 |
#if 0 |
|
930 | 930 |
badframe: |
931 | 931 |
return 1; |
932 |
#endif |
|
933 | 932 |
} |
934 | 933 |
|
935 | 934 |
long do_sigreturn(CPUX86State *env) |
... | ... | |
970 | 969 |
|
971 | 970 |
long do_rt_sigreturn(CPUX86State *env) |
972 | 971 |
{ |
973 |
struct rt_sigframe *frame = (struct rt_sigframe *)g2h(env->regs[R_ESP] - 4); |
|
972 |
abi_ulong frame_addr; |
|
973 |
struct rt_sigframe *frame; |
|
974 | 974 |
sigset_t set; |
975 | 975 |
int eax; |
976 | 976 |
|
977 |
#if 0 |
|
978 |
if (verify_area(VERIFY_READ, frame, sizeof(*frame))) |
|
979 |
goto badframe; |
|
980 |
#endif |
|
977 |
frame_addr = env->regs[R_ESP] - 4; |
|
978 |
if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) |
|
979 |
goto badframe; |
|
981 | 980 |
target_to_host_sigset(&set, &frame->uc.tuc_sigmask); |
982 | 981 |
sigprocmask(SIG_SETMASK, &set, NULL); |
983 | 982 |
|
984 | 983 |
if (restore_sigcontext(env, &frame->uc.tuc_mcontext, &eax)) |
985 | 984 |
goto badframe; |
986 | 985 |
|
987 |
if (do_sigaltstack(h2g(&frame->uc.tuc_stack), 0, get_sp_from_cpustate(env)) == -EFAULT) |
|
986 |
if (do_sigaltstack(frame_addr + offsetof(struct rt_sigframe, uc.tuc_stack), 0, |
|
987 |
get_sp_from_cpustate(env)) == -EFAULT) |
|
988 | 988 |
goto badframe; |
989 | 989 |
|
990 |
unlock_user_struct(frame, frame_addr, 0); |
|
990 | 991 |
return eax; |
991 | 992 |
|
992 | 993 |
badframe: |
993 |
force_sig(TARGET_SIGSEGV); |
|
994 |
unlock_user_struct(frame, frame_addr, 0); |
|
995 |
force_sig(TARGET_SIGSEGV); |
|
994 | 996 |
return 0; |
995 | 997 |
} |
996 | 998 |
|
Also available in: Unified diff