diff options
author | bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162> | 2003-05-10 15:10:36 +0000 |
---|---|---|
committer | bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162> | 2003-05-10 15:10:36 +0000 |
commit | 447db2139a6f6883183a7a750c5849145fd29899 (patch) | |
tree | 116ab50e4e595e67ea93e7d19daef38aa3223bf4 | |
parent | 564c8f9978499a12fc8efd8d3c4af54060d1adcf (diff) | |
download | qemu-447db2139a6f6883183a7a750c5849145fd29899.zip qemu-447db2139a6f6883183a7a750c5849145fd29899.tar.gz qemu-447db2139a6f6883183a7a750c5849145fd29899.tar.bz2 |
sigtrap support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@147 c046a42c-6fe2-441c-8c8c-71466251a162
-rw-r--r-- | linux-user/main.c | 21 | ||||
-rw-r--r-- | linux-user/qemu.h | 2 | ||||
-rw-r--r-- | linux-user/signal.c | 9 | ||||
-rw-r--r-- | linux-user/vm86.c | 11 | ||||
-rw-r--r-- | syscall-i386.h | 6 |
5 files changed, 43 insertions, 6 deletions
diff --git a/linux-user/main.c b/linux-user/main.c index c9d0c98..00dc271 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -166,7 +166,7 @@ void cpu_loop(CPUX86State *env) break; case EXCP00_DIVZ: if (env->eflags & VM_MASK) { - do_int(env, trapnr); + handle_vm86_trap(env, trapnr); } else { /* division by zero */ info.si_signo = SIGFPE; @@ -176,10 +176,27 @@ void cpu_loop(CPUX86State *env) queue_signal(info.si_signo, &info); } break; + case EXCP01_SSTP: + case EXCP03_INT3: + if (env->eflags & VM_MASK) { + handle_vm86_trap(env, trapnr); + } else { + info.si_signo = SIGTRAP; + info.si_errno = 0; + if (trapnr == EXCP01_SSTP) { + info.si_code = TARGET_TRAP_BRKPT; + info._sifields._sigfault._addr = env->eip; + } else { + info.si_code = TARGET_SI_KERNEL; + info._sifields._sigfault._addr = 0; + } + queue_signal(info.si_signo, &info); + } + break; case EXCP04_INTO: case EXCP05_BOUND: if (env->eflags & VM_MASK) { - do_int(env, trapnr); + handle_vm86_trap(env, trapnr); } else { info.si_signo = SIGSEGV; info.si_errno = 0; diff --git a/linux-user/qemu.h b/linux-user/qemu.h index 5613c3e..0f004ff 100644 --- a/linux-user/qemu.h +++ b/linux-user/qemu.h @@ -83,7 +83,7 @@ extern FILE *logfile; /* vm86.c */ void save_v86_state(CPUX86State *env); -void do_int(CPUX86State *env, int intno); +void handle_vm86_trap(CPUX86State *env, int trapno); void handle_vm86_fault(CPUX86State *env); int do_vm86(CPUX86State *env, long subfunction, struct target_vm86plus_struct * target_v86); diff --git a/linux-user/signal.c b/linux-user/signal.c index 9873071..145dc29 100644 --- a/linux-user/signal.c +++ b/linux-user/signal.c @@ -110,7 +110,8 @@ static inline void host_to_target_siginfo_noswap(target_siginfo_t *tinfo, tinfo->si_signo = sig; tinfo->si_errno = 0; tinfo->si_code = 0; - if (sig == SIGILL || sig == SIGFPE || sig == SIGSEGV || sig == SIGBUS) { + if (sig == SIGILL || sig == SIGFPE || sig == SIGSEGV || + sig == SIGBUS || sig == SIGTRAP) { /* should never come here, but who knows. The information for the target is irrelevant */ tinfo->_sifields._sigfault._addr = 0; @@ -131,7 +132,8 @@ static void tswap_siginfo(target_siginfo_t *tinfo, tinfo->si_signo = tswap32(sig); tinfo->si_errno = tswap32(info->si_errno); tinfo->si_code = tswap32(info->si_code); - if (sig == SIGILL || sig == SIGFPE || sig == SIGSEGV || sig == SIGBUS) { + if (sig == SIGILL || sig == SIGFPE || sig == SIGSEGV || + sig == SIGBUS || sig == SIGTRAP) { tinfo->_sifields._sigfault._addr = tswapl(info->_sifields._sigfault._addr); } else if (sig >= TARGET_SIGRTMIN) { @@ -788,6 +790,9 @@ long do_sigreturn(CPUX86State *env) sigset_t set; int eax, i; +#if defined(DEBUG_SIGNAL) + fprintf(stderr, "do_sigreturn\n"); +#endif /* set blocked signals */ target_set.sig[0] = frame->sc.oldmask; for(i = 1; i < TARGET_NSIG_WORDS; i++) diff --git a/linux-user/vm86.c b/linux-user/vm86.c index 8316117..f243af8 100644 --- a/linux-user/vm86.c +++ b/linux-user/vm86.c @@ -178,7 +178,7 @@ static inline unsigned int get_vflags(CPUX86State *env) /* handle VM86 interrupt (NOTE: the CPU core currently does not support TSS interrupt revectoring, so this code is always executed) */ -void do_int(CPUX86State *env, int intno) +static void do_int(CPUX86State *env, int intno) { TaskState *ts = env->opaque; uint32_t *int_ptr, segoffs; @@ -225,6 +225,15 @@ void do_int(CPUX86State *env, int intno) return_to_32bit(env, TARGET_VM86_INTx | (intno << 8)); } +void handle_vm86_trap(CPUX86State *env, int trapno) +{ + if (trapno == 1 || trapno == 3) { + return_to_32bit(env, TARGET_VM86_TRAP + (trapno << 8)); + } else { + do_int(env, trapno); + } +} + #define CHECK_IF_IN_TRAP(disp) \ if ((tswap32(ts->target_v86->vm86plus.flags) & TARGET_vm86dbg_active) && \ (tswap32(ts->target_v86->vm86plus.flags) & TARGET_vm86dbg_TFpendig)) \ diff --git a/syscall-i386.h b/syscall-i386.h index 30e8bc3..fbe8610 100644 --- a/syscall-i386.h +++ b/syscall-i386.h @@ -480,6 +480,12 @@ typedef struct target_siginfo { #define TARGET_SEGV_MAPERR (1) /* address not mapped to object */ #define TARGET_SEGV_ACCERR (2) /* invalid permissions for mapped object */ +/* + * SIGTRAP si_codes + */ +#define TARGET_TRAP_BRKPT (1) /* process breakpoint */ +#define TARGET_TRAP_TRACE (2) /* process trace trap */ + /* default linux values for the selectors */ #define __USER_CS (0x23) #define __USER_DS (0x2B) |