Commit 447db2139a6f6883183a7a750c5849145fd29899
1 parent
564c8f99
sigtrap support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@147 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
5 changed files
with
43 additions
and
6 deletions
linux-user/main.c
| @@ -166,7 +166,7 @@ void cpu_loop(CPUX86State *env) | @@ -166,7 +166,7 @@ void cpu_loop(CPUX86State *env) | ||
| 166 | break; | 166 | break; |
| 167 | case EXCP00_DIVZ: | 167 | case EXCP00_DIVZ: |
| 168 | if (env->eflags & VM_MASK) { | 168 | if (env->eflags & VM_MASK) { |
| 169 | - do_int(env, trapnr); | 169 | + handle_vm86_trap(env, trapnr); |
| 170 | } else { | 170 | } else { |
| 171 | /* division by zero */ | 171 | /* division by zero */ |
| 172 | info.si_signo = SIGFPE; | 172 | info.si_signo = SIGFPE; |
| @@ -176,10 +176,27 @@ void cpu_loop(CPUX86State *env) | @@ -176,10 +176,27 @@ void cpu_loop(CPUX86State *env) | ||
| 176 | queue_signal(info.si_signo, &info); | 176 | queue_signal(info.si_signo, &info); |
| 177 | } | 177 | } |
| 178 | break; | 178 | break; |
| 179 | + case EXCP01_SSTP: | ||
| 180 | + case EXCP03_INT3: | ||
| 181 | + if (env->eflags & VM_MASK) { | ||
| 182 | + handle_vm86_trap(env, trapnr); | ||
| 183 | + } else { | ||
| 184 | + info.si_signo = SIGTRAP; | ||
| 185 | + info.si_errno = 0; | ||
| 186 | + if (trapnr == EXCP01_SSTP) { | ||
| 187 | + info.si_code = TARGET_TRAP_BRKPT; | ||
| 188 | + info._sifields._sigfault._addr = env->eip; | ||
| 189 | + } else { | ||
| 190 | + info.si_code = TARGET_SI_KERNEL; | ||
| 191 | + info._sifields._sigfault._addr = 0; | ||
| 192 | + } | ||
| 193 | + queue_signal(info.si_signo, &info); | ||
| 194 | + } | ||
| 195 | + break; | ||
| 179 | case EXCP04_INTO: | 196 | case EXCP04_INTO: |
| 180 | case EXCP05_BOUND: | 197 | case EXCP05_BOUND: |
| 181 | if (env->eflags & VM_MASK) { | 198 | if (env->eflags & VM_MASK) { |
| 182 | - do_int(env, trapnr); | 199 | + handle_vm86_trap(env, trapnr); |
| 183 | } else { | 200 | } else { |
| 184 | info.si_signo = SIGSEGV; | 201 | info.si_signo = SIGSEGV; |
| 185 | info.si_errno = 0; | 202 | info.si_errno = 0; |
linux-user/qemu.h
| @@ -83,7 +83,7 @@ extern FILE *logfile; | @@ -83,7 +83,7 @@ extern FILE *logfile; | ||
| 83 | 83 | ||
| 84 | /* vm86.c */ | 84 | /* vm86.c */ |
| 85 | void save_v86_state(CPUX86State *env); | 85 | void save_v86_state(CPUX86State *env); |
| 86 | -void do_int(CPUX86State *env, int intno); | 86 | +void handle_vm86_trap(CPUX86State *env, int trapno); |
| 87 | void handle_vm86_fault(CPUX86State *env); | 87 | void handle_vm86_fault(CPUX86State *env); |
| 88 | int do_vm86(CPUX86State *env, long subfunction, | 88 | int do_vm86(CPUX86State *env, long subfunction, |
| 89 | struct target_vm86plus_struct * target_v86); | 89 | struct target_vm86plus_struct * target_v86); |
linux-user/signal.c
| @@ -110,7 +110,8 @@ static inline void host_to_target_siginfo_noswap(target_siginfo_t *tinfo, | @@ -110,7 +110,8 @@ static inline void host_to_target_siginfo_noswap(target_siginfo_t *tinfo, | ||
| 110 | tinfo->si_signo = sig; | 110 | tinfo->si_signo = sig; |
| 111 | tinfo->si_errno = 0; | 111 | tinfo->si_errno = 0; |
| 112 | tinfo->si_code = 0; | 112 | tinfo->si_code = 0; |
| 113 | - if (sig == SIGILL || sig == SIGFPE || sig == SIGSEGV || sig == SIGBUS) { | 113 | + if (sig == SIGILL || sig == SIGFPE || sig == SIGSEGV || |
| 114 | + sig == SIGBUS || sig == SIGTRAP) { | ||
| 114 | /* should never come here, but who knows. The information for | 115 | /* should never come here, but who knows. The information for |
| 115 | the target is irrelevant */ | 116 | the target is irrelevant */ |
| 116 | tinfo->_sifields._sigfault._addr = 0; | 117 | tinfo->_sifields._sigfault._addr = 0; |
| @@ -131,7 +132,8 @@ static void tswap_siginfo(target_siginfo_t *tinfo, | @@ -131,7 +132,8 @@ static void tswap_siginfo(target_siginfo_t *tinfo, | ||
| 131 | tinfo->si_signo = tswap32(sig); | 132 | tinfo->si_signo = tswap32(sig); |
| 132 | tinfo->si_errno = tswap32(info->si_errno); | 133 | tinfo->si_errno = tswap32(info->si_errno); |
| 133 | tinfo->si_code = tswap32(info->si_code); | 134 | tinfo->si_code = tswap32(info->si_code); |
| 134 | - if (sig == SIGILL || sig == SIGFPE || sig == SIGSEGV || sig == SIGBUS) { | 135 | + if (sig == SIGILL || sig == SIGFPE || sig == SIGSEGV || |
| 136 | + sig == SIGBUS || sig == SIGTRAP) { | ||
| 135 | tinfo->_sifields._sigfault._addr = | 137 | tinfo->_sifields._sigfault._addr = |
| 136 | tswapl(info->_sifields._sigfault._addr); | 138 | tswapl(info->_sifields._sigfault._addr); |
| 137 | } else if (sig >= TARGET_SIGRTMIN) { | 139 | } else if (sig >= TARGET_SIGRTMIN) { |
| @@ -788,6 +790,9 @@ long do_sigreturn(CPUX86State *env) | @@ -788,6 +790,9 @@ long do_sigreturn(CPUX86State *env) | ||
| 788 | sigset_t set; | 790 | sigset_t set; |
| 789 | int eax, i; | 791 | int eax, i; |
| 790 | 792 | ||
| 793 | +#if defined(DEBUG_SIGNAL) | ||
| 794 | + fprintf(stderr, "do_sigreturn\n"); | ||
| 795 | +#endif | ||
| 791 | /* set blocked signals */ | 796 | /* set blocked signals */ |
| 792 | target_set.sig[0] = frame->sc.oldmask; | 797 | target_set.sig[0] = frame->sc.oldmask; |
| 793 | for(i = 1; i < TARGET_NSIG_WORDS; i++) | 798 | for(i = 1; i < TARGET_NSIG_WORDS; i++) |
linux-user/vm86.c
| @@ -178,7 +178,7 @@ static inline unsigned int get_vflags(CPUX86State *env) | @@ -178,7 +178,7 @@ static inline unsigned int get_vflags(CPUX86State *env) | ||
| 178 | 178 | ||
| 179 | /* handle VM86 interrupt (NOTE: the CPU core currently does not | 179 | /* handle VM86 interrupt (NOTE: the CPU core currently does not |
| 180 | support TSS interrupt revectoring, so this code is always executed) */ | 180 | support TSS interrupt revectoring, so this code is always executed) */ |
| 181 | -void do_int(CPUX86State *env, int intno) | 181 | +static void do_int(CPUX86State *env, int intno) |
| 182 | { | 182 | { |
| 183 | TaskState *ts = env->opaque; | 183 | TaskState *ts = env->opaque; |
| 184 | uint32_t *int_ptr, segoffs; | 184 | uint32_t *int_ptr, segoffs; |
| @@ -225,6 +225,15 @@ void do_int(CPUX86State *env, int intno) | @@ -225,6 +225,15 @@ void do_int(CPUX86State *env, int intno) | ||
| 225 | return_to_32bit(env, TARGET_VM86_INTx | (intno << 8)); | 225 | return_to_32bit(env, TARGET_VM86_INTx | (intno << 8)); |
| 226 | } | 226 | } |
| 227 | 227 | ||
| 228 | +void handle_vm86_trap(CPUX86State *env, int trapno) | ||
| 229 | +{ | ||
| 230 | + if (trapno == 1 || trapno == 3) { | ||
| 231 | + return_to_32bit(env, TARGET_VM86_TRAP + (trapno << 8)); | ||
| 232 | + } else { | ||
| 233 | + do_int(env, trapno); | ||
| 234 | + } | ||
| 235 | +} | ||
| 236 | + | ||
| 228 | #define CHECK_IF_IN_TRAP(disp) \ | 237 | #define CHECK_IF_IN_TRAP(disp) \ |
| 229 | if ((tswap32(ts->target_v86->vm86plus.flags) & TARGET_vm86dbg_active) && \ | 238 | if ((tswap32(ts->target_v86->vm86plus.flags) & TARGET_vm86dbg_active) && \ |
| 230 | (tswap32(ts->target_v86->vm86plus.flags) & TARGET_vm86dbg_TFpendig)) \ | 239 | (tswap32(ts->target_v86->vm86plus.flags) & TARGET_vm86dbg_TFpendig)) \ |
syscall-i386.h
| @@ -480,6 +480,12 @@ typedef struct target_siginfo { | @@ -480,6 +480,12 @@ typedef struct target_siginfo { | ||
| 480 | #define TARGET_SEGV_MAPERR (1) /* address not mapped to object */ | 480 | #define TARGET_SEGV_MAPERR (1) /* address not mapped to object */ |
| 481 | #define TARGET_SEGV_ACCERR (2) /* invalid permissions for mapped object */ | 481 | #define TARGET_SEGV_ACCERR (2) /* invalid permissions for mapped object */ |
| 482 | 482 | ||
| 483 | +/* | ||
| 484 | + * SIGTRAP si_codes | ||
| 485 | + */ | ||
| 486 | +#define TARGET_TRAP_BRKPT (1) /* process breakpoint */ | ||
| 487 | +#define TARGET_TRAP_TRACE (2) /* process trace trap */ | ||
| 488 | + | ||
| 483 | /* default linux values for the selectors */ | 489 | /* default linux values for the selectors */ |
| 484 | #define __USER_CS (0x23) | 490 | #define __USER_CS (0x23) |
| 485 | #define __USER_DS (0x2B) | 491 | #define __USER_DS (0x2B) |