sigtrap support


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@147 c046a42c-6fe2-441c-8c8c-71466251a162
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 @@
             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 @@
                 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 @@
 
 /* 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 @@
     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 @@
     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 @@
     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 @@
 
 /* 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 @@
     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 @@
 #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)