]> git.proxmox.com Git - qemu.git/blobdiff - gdbstub.c
slirp: Canonicalize restrict syntax
[qemu.git] / gdbstub.c
index 33d79ebcb9eb70bc98e1bfa29a135d11adfe111a..c085a5afb33cc0ae2cab61cfe087cfa6da51a428 100644 (file)
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -37,6 +37,7 @@
 
 #define MAX_PACKET_LENGTH 4096
 
+#include "cpu.h"
 #include "qemu_socket.h"
 #include "kvm.h"
 
 enum {
     GDB_SIGNAL_0 = 0,
     GDB_SIGNAL_INT = 2,
+    GDB_SIGNAL_QUIT = 3,
     GDB_SIGNAL_TRAP = 5,
+    GDB_SIGNAL_ABRT = 6,
+    GDB_SIGNAL_ALRM = 14,
+    GDB_SIGNAL_IO = 23,
+    GDB_SIGNAL_XCPU = 24,
     GDB_SIGNAL_UNKNOWN = 143
 };
 
@@ -505,8 +511,9 @@ static const int gpr_map[16] = {
     8, 9, 10, 11, 12, 13, 14, 15
 };
 #else
-static const int gpr_map[8] = {0, 1, 2, 3, 4, 5, 6, 7};
+#define gpr_map gpr_map32
 #endif
+static const int gpr_map32[8] = { 0, 1, 2, 3, 4, 5, 6, 7 };
 
 #define NUM_CORE_REGS (CPU_NB_REGS * 2 + 25)
 
@@ -520,7 +527,11 @@ static const int gpr_map[8] = {0, 1, 2, 3, 4, 5, 6, 7};
 static int cpu_gdb_read_register(CPUState *env, uint8_t *mem_buf, int n)
 {
     if (n < CPU_NB_REGS) {
-        GET_REGL(env->regs[gpr_map[n]]);
+        if (TARGET_LONG_BITS == 64 && env->hflags & HF_CS64_MASK) {
+            GET_REG64(env->regs[gpr_map[n]]);
+        } else if (n < CPU_NB_REGS32) {
+            GET_REG32(env->regs[gpr_map32[n]]);
+        }
     } else if (n >= IDX_FP_REGS && n < IDX_FP_REGS + 8) {
 #ifdef USE_X86LDOUBLE
         /* FIXME: byteswap float values - after fixing fpregs layout. */
@@ -531,12 +542,20 @@ static int cpu_gdb_read_register(CPUState *env, uint8_t *mem_buf, int n)
         return 10;
     } else if (n >= IDX_XMM_REGS && n < IDX_XMM_REGS + CPU_NB_REGS) {
         n -= IDX_XMM_REGS;
-        stq_p(mem_buf, env->xmm_regs[n].XMM_Q(0));
-        stq_p(mem_buf + 8, env->xmm_regs[n].XMM_Q(1));
-        return 16;
+        if (n < CPU_NB_REGS32 ||
+            (TARGET_LONG_BITS == 64 && env->hflags & HF_CS64_MASK)) {
+            stq_p(mem_buf, env->xmm_regs[n].XMM_Q(0));
+            stq_p(mem_buf + 8, env->xmm_regs[n].XMM_Q(1));
+            return 16;
+        }
     } else {
         switch (n) {
-        case IDX_IP_REG:    GET_REGL(env->eip);
+        case IDX_IP_REG:
+            if (TARGET_LONG_BITS == 64 && env->hflags & HF_CS64_MASK) {
+                GET_REG64(env->eip);
+            } else {
+                GET_REG32(env->eip);
+            }
         case IDX_FLAGS_REG: GET_REG32(env->eflags);
 
         case IDX_SEG_REGS:     GET_REG32(env->segs[R_CS].selector);
@@ -592,8 +611,15 @@ static int cpu_gdb_write_register(CPUState *env, uint8_t *mem_buf, int n)
     uint32_t tmp;
 
     if (n < CPU_NB_REGS) {
-        env->regs[gpr_map[n]] = ldtul_p(mem_buf);
-        return sizeof(target_ulong);
+        if (TARGET_LONG_BITS == 64 && env->hflags & HF_CS64_MASK) {
+            env->regs[gpr_map[n]] = ldtul_p(mem_buf);
+            return sizeof(target_ulong);
+        } else if (n < CPU_NB_REGS32) {
+            n = gpr_map32[n];
+            env->regs[n] &= ~0xffffffffUL;
+            env->regs[n] |= (uint32_t)ldl_p(mem_buf);
+            return 4;
+        }
     } else if (n >= IDX_FP_REGS && n < IDX_FP_REGS + 8) {
 #ifdef USE_X86LDOUBLE
         /* FIXME: byteswap float values - after fixing fpregs layout. */
@@ -602,14 +628,23 @@ static int cpu_gdb_write_register(CPUState *env, uint8_t *mem_buf, int n)
         return 10;
     } else if (n >= IDX_XMM_REGS && n < IDX_XMM_REGS + CPU_NB_REGS) {
         n -= IDX_XMM_REGS;
-        env->xmm_regs[n].XMM_Q(0) = ldq_p(mem_buf);
-        env->xmm_regs[n].XMM_Q(1) = ldq_p(mem_buf + 8);
-        return 16;
+        if (n < CPU_NB_REGS32 ||
+            (TARGET_LONG_BITS == 64 && env->hflags & HF_CS64_MASK)) {
+            env->xmm_regs[n].XMM_Q(0) = ldq_p(mem_buf);
+            env->xmm_regs[n].XMM_Q(1) = ldq_p(mem_buf + 8);
+            return 16;
+        }
     } else {
         switch (n) {
         case IDX_IP_REG:
-            env->eip = ldtul_p(mem_buf);
-            return sizeof(target_ulong);
+            if (TARGET_LONG_BITS == 64 && env->hflags & HF_CS64_MASK) {
+                env->eip = ldq_p(mem_buf);
+                return 8;
+            } else {
+                env->eip &= ~0xffffffffUL;
+                env->eip |= (uint32_t)ldl_p(mem_buf);
+                return 4;
+            }
         case IDX_FLAGS_REG:
             env->eflags = ldl_p(mem_buf);
             return 4;
@@ -775,7 +810,7 @@ static int cpu_gdb_read_register(CPUState *env, uint8_t *mem_buf, int n)
     /* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */
     switch (n) {
     case 64: GET_REGA(env->y);
-    case 65: GET_REGA(GET_PSR(env));
+    case 65: GET_REGA(cpu_get_psr(env));
     case 66: GET_REGA(env->wim);
     case 67: GET_REGA(env->tbr);
     case 68: GET_REGA(env->pc);
@@ -800,10 +835,10 @@ static int cpu_gdb_read_register(CPUState *env, uint8_t *mem_buf, int n)
     switch (n) {
     case 80: GET_REGL(env->pc);
     case 81: GET_REGL(env->npc);
-    case 82: GET_REGL(((uint64_t)GET_CCR(env) << 32) |
-                           ((env->asi & 0xff) << 24) |
-                           ((env->pstate & 0xfff) << 8) |
-                           GET_CWP64(env));
+    case 82: GET_REGL((cpu_get_ccr(env) << 32) |
+                      ((env->asi & 0xff) << 24) |
+                      ((env->pstate & 0xfff) << 8) |
+                      cpu_get_cwp64(env));
     case 83: GET_REGL(env->fsr);
     case 84: GET_REGL(env->fprs);
     case 85: GET_REGL(env->y);
@@ -839,7 +874,7 @@ static int cpu_gdb_write_register(CPUState *env, uint8_t *mem_buf, int n)
         /* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */
         switch (n) {
         case 64: env->y = tmp; break;
-        case 65: PUT_PSR(env, tmp); break;
+        case 65: cpu_put_psr(env, tmp); break;
         case 66: env->wim = tmp; break;
         case 67: env->tbr = tmp; break;
         case 68: env->pc = tmp; break;
@@ -863,10 +898,10 @@ static int cpu_gdb_write_register(CPUState *env, uint8_t *mem_buf, int n)
         case 80: env->pc = tmp; break;
         case 81: env->npc = tmp; break;
         case 82:
-           PUT_CCR(env, tmp >> 32);
+            cpu_put_ccr(env, tmp >> 32);
            env->asi = (tmp >> 24) & 0xff;
            env->pstate = (tmp >> 8) & 0xfff;
-           PUT_CWP64(env, tmp & 0xff);
+            cpu_put_cwp64(env, tmp & 0xff);
            break;
         case 83: env->fsr = tmp; break;
         case 84: env->fprs = tmp; break;
@@ -985,7 +1020,7 @@ static int cpu_gdb_write_register(CPUState *env, uint8_t *mem_buf, int n)
     if (n < 8) {
         /* D0-D7 */
         env->dregs[n] = tmp;
-    } else if (n < 8) {
+    } else if (n < 16) {
         /* A0-A7 */
         env->aregs[n - 8] = tmp;
     } else {
@@ -1024,7 +1059,7 @@ static int cpu_gdb_read_register(CPUState *env, uint8_t *mem_buf, int n)
     case 34: GET_REGL(env->active_tc.HI[0]);
     case 35: GET_REGL(env->CP0_BadVAddr);
     case 36: GET_REGL((int32_t)env->CP0_Cause);
-    case 37: GET_REGL(env->active_tc.PC);
+    case 37: GET_REGL(env->active_tc.PC | !!(env->hflags & MIPS_HFLAG_M16));
     case 72: GET_REGL(0); /* fp */
     case 89: GET_REGL((int32_t)env->CP0_PRid);
     }
@@ -1070,10 +1105,6 @@ static int cpu_gdb_write_register(CPUState *env, uint8_t *mem_buf, int n)
             env->active_fpu.fcr31 = tmp & 0xFF83FFFF;
             /* set rounding mode */
             RESTORE_ROUNDING_MODE;
-#ifndef CONFIG_SOFTFLOAT
-            /* no floating point exception for native float */
-            SET_FP_ENABLE(env->active_fpu.fcr31, 0);
-#endif
             break;
         case 71: env->active_fpu.fcr0 = tmp; break;
         }
@@ -1085,7 +1116,14 @@ static int cpu_gdb_write_register(CPUState *env, uint8_t *mem_buf, int n)
     case 34: env->active_tc.HI[0] = tmp; break;
     case 35: env->CP0_BadVAddr = tmp; break;
     case 36: env->CP0_Cause = tmp; break;
-    case 37: env->active_tc.PC = tmp; break;
+    case 37:
+        env->active_tc.PC = tmp & ~(target_ulong)1;
+        if (tmp & 1) {
+            env->hflags |= MIPS_HFLAG_M16;
+        } else {
+            env->hflags &= ~(MIPS_HFLAG_M16);
+        }
+        break;
     case 72: /* fp, ignored */ break;
     default: 
        if (n > 89)
@@ -1112,7 +1150,7 @@ static int cpu_gdb_read_register(CPUState *env, uint8_t *mem_buf, int n)
             GET_REGL(env->gregs[n]);
         }
     } else if (n < 16) {
-        GET_REGL(env->gregs[n - 8]);
+        GET_REGL(env->gregs[n]);
     } else if (n >= 25 && n < 41) {
        GET_REGL(env->fregs[(n - 25) + ((env->fpscr & FPSCR_FR) ? 16 : 0)]);
     } else if (n >= 43 && n < 51) {
@@ -1151,10 +1189,11 @@ static int cpu_gdb_write_register(CPUState *env, uint8_t *mem_buf, int n)
         }
        return 4;
     } else if (n < 16) {
-        env->gregs[n - 8] = tmp;
+        env->gregs[n] = tmp;
        return 4;
     } else if (n >= 25 && n < 41) {
        env->fregs[(n - 25) + ((env->fpscr & FPSCR_FR) ? 16 : 0)] = tmp;
+       return 4;
     } else if (n >= 43 && n < 51) {
        env->gregs[n - 43] = tmp;
        return 4;
@@ -1163,17 +1202,17 @@ static int cpu_gdb_write_register(CPUState *env, uint8_t *mem_buf, int n)
        return 4;
     }
     switch (n) {
-    case 16: env->pc = tmp;
-    case 17: env->pr = tmp;
-    case 18: env->gbr = tmp;
-    case 19: env->vbr = tmp;
-    case 20: env->mach = tmp;
-    case 21: env->macl = tmp;
-    case 22: env->sr = tmp;
-    case 23: env->fpul = tmp;
-    case 24: env->fpscr = tmp;
-    case 41: env->ssr = tmp;
-    case 42: env->spc = tmp;
+    case 16: env->pc = tmp; break;
+    case 17: env->pr = tmp; break;
+    case 18: env->gbr = tmp; break;
+    case 19: env->vbr = tmp; break;
+    case 20: env->mach = tmp; break;
+    case 21: env->macl = tmp; break;
+    case 22: env->sr = tmp; break;
+    case 23: env->fpul = tmp; break;
+    case 24: env->fpscr = tmp; break;
+    case 41: env->ssr = tmp; break;
+    case 42: env->spc = tmp; break;
     default: return 0;
     }
 
@@ -1213,10 +1252,46 @@ static int cpu_gdb_write_register(CPUState *env, uint8_t *mem_buf, int n)
 
 #define NUM_CORE_REGS 49
 
+static int
+read_register_crisv10(CPUState *env, uint8_t *mem_buf, int n)
+{
+    if (n < 15) {
+        GET_REG32(env->regs[n]);
+    }
+
+    if (n == 15) {
+        GET_REG32(env->pc);
+    }
+
+    if (n < 32) {
+        switch (n) {
+        case 16:
+            GET_REG8(env->pregs[n - 16]);
+            break;
+        case 17:
+            GET_REG8(env->pregs[n - 16]);
+            break;
+        case 20:
+        case 21:
+            GET_REG16(env->pregs[n - 16]);
+            break;
+        default:
+            if (n >= 23) {
+                GET_REG32(env->pregs[n - 16]);
+            }
+            break;
+        }
+    }
+    return 0;
+}
+
 static int cpu_gdb_read_register(CPUState *env, uint8_t *mem_buf, int n)
 {
     uint8_t srs;
 
+    if (env->pregs[PR_VR] < 32)
+        return read_register_crisv10(env, mem_buf, n);
+
     srs = env->pregs[PR_SRS];
     if (n < 16) {
        GET_REG32(env->regs[n]);
@@ -1271,30 +1346,97 @@ static int cpu_gdb_write_register(CPUState *env, uint8_t *mem_buf, int n)
 }
 #elif defined (TARGET_ALPHA)
 
-#define NUM_CORE_REGS 65
+#define NUM_CORE_REGS 67
 
 static int cpu_gdb_read_register(CPUState *env, uint8_t *mem_buf, int n)
 {
-    if (n < 31) {
-       GET_REGL(env->ir[n]);
-    }
-    else if (n == 31) {
-       GET_REGL(0);
-    }
-    else if (n<63) {
-       uint64_t val;
+    uint64_t val;
+    CPU_DoubleU d;
 
-       val=*((uint64_t *)&env->fir[n-32]);
-       GET_REGL(val);
-    }
-    else if (n==63) {
-       GET_REGL(env->fpcr);
+    switch (n) {
+    case 0 ... 30:
+        val = env->ir[n];
+        break;
+    case 32 ... 62:
+        d.d = env->fir[n - 32];
+        val = d.ll;
+        break;
+    case 63:
+        val = cpu_alpha_load_fpcr(env);
+        break;
+    case 64:
+        val = env->pc;
+        break;
+    case 66:
+        val = env->unique;
+        break;
+    case 31:
+    case 65:
+        /* 31 really is the zero register; 65 is unassigned in the
+           gdb protocol, but is still required to occupy 8 bytes. */
+        val = 0;
+        break;
+    default:
+        return 0;
     }
-    else if (n==64) {
-       GET_REGL(env->pc);
+    GET_REGL(val);
+}
+
+static int cpu_gdb_write_register(CPUState *env, uint8_t *mem_buf, int n)
+{
+    target_ulong tmp = ldtul_p(mem_buf);
+    CPU_DoubleU d;
+
+    switch (n) {
+    case 0 ... 30:
+        env->ir[n] = tmp;
+        break;
+    case 32 ... 62:
+        d.ll = tmp;
+        env->fir[n - 32] = d.d;
+        break;
+    case 63:
+        cpu_alpha_store_fpcr(env, tmp);
+        break;
+    case 64:
+        env->pc = tmp;
+        break;
+    case 66:
+        env->unique = tmp;
+        break;
+    case 31:
+    case 65:
+        /* 31 really is the zero register; 65 is unassigned in the
+           gdb protocol, but is still required to occupy 8 bytes. */
+        break;
+    default:
+        return 0;
     }
-    else {
-       GET_REGL(0);
+    return 8;
+}
+#elif defined (TARGET_S390X)
+
+#define NUM_CORE_REGS S390_NUM_TOTAL_REGS
+
+static int cpu_gdb_read_register(CPUState *env, uint8_t *mem_buf, int n)
+{
+    switch (n) {
+        case S390_PSWM_REGNUM: GET_REGL(env->psw.mask); break;
+        case S390_PSWA_REGNUM: GET_REGL(env->psw.addr); break;
+        case S390_R0_REGNUM ... S390_R15_REGNUM:
+            GET_REGL(env->regs[n-S390_R0_REGNUM]); break;
+        case S390_A0_REGNUM ... S390_A15_REGNUM:
+            GET_REG32(env->aregs[n-S390_A0_REGNUM]); break;
+        case S390_FPC_REGNUM: GET_REG32(env->fpc); break;
+        case S390_F0_REGNUM ... S390_F15_REGNUM:
+            /* XXX */
+            break;
+        case S390_PC_REGNUM: GET_REGL(env->psw.addr); break;
+        case S390_CC_REGNUM:
+            env->cc_op = calc_cc(env, env->cc_op, env->cc_src, env->cc_dst,
+                                 env->cc_vr);
+            GET_REG32(env->cc_op);
+            break;
     }
 
     return 0;
@@ -1302,22 +1444,102 @@ static int cpu_gdb_read_register(CPUState *env, uint8_t *mem_buf, int n)
 
 static int cpu_gdb_write_register(CPUState *env, uint8_t *mem_buf, int n)
 {
-    target_ulong tmp;
-    tmp = ldtul_p(mem_buf);
+    target_ulong tmpl;
+    uint32_t tmp32;
+    int r = 8;
+    tmpl = ldtul_p(mem_buf);
+    tmp32 = ldl_p(mem_buf);
 
-    if (n < 31) {
-        env->ir[n] = tmp;
+    switch (n) {
+        case S390_PSWM_REGNUM: env->psw.mask = tmpl; break;
+        case S390_PSWA_REGNUM: env->psw.addr = tmpl; break;
+        case S390_R0_REGNUM ... S390_R15_REGNUM:
+            env->regs[n-S390_R0_REGNUM] = tmpl; break;
+        case S390_A0_REGNUM ... S390_A15_REGNUM:
+            env->aregs[n-S390_A0_REGNUM] = tmp32; r=4; break;
+        case S390_FPC_REGNUM: env->fpc = tmp32; r=4; break;
+        case S390_F0_REGNUM ... S390_F15_REGNUM:
+            /* XXX */
+            break;
+        case S390_PC_REGNUM: env->psw.addr = tmpl; break;
+        case S390_CC_REGNUM: env->cc_op = tmp32; r=4; break;
     }
 
-    if (n > 31 && n < 63) {
-        env->fir[n - 32] = ldfl_p(mem_buf);
+    return r;
+}
+#elif defined (TARGET_LM32)
+
+#include "hw/lm32_pic.h"
+#define NUM_CORE_REGS (32 + 7)
+
+static int cpu_gdb_read_register(CPUState *env, uint8_t *mem_buf, int n)
+{
+    if (n < 32) {
+        GET_REG32(env->regs[n]);
+    } else {
+        switch (n) {
+        case 32:
+            GET_REG32(env->pc);
+            break;
+        /* FIXME: put in right exception ID */
+        case 33:
+            GET_REG32(0);
+            break;
+        case 34:
+            GET_REG32(env->eba);
+            break;
+        case 35:
+            GET_REG32(env->deba);
+            break;
+        case 36:
+            GET_REG32(env->ie);
+            break;
+        case 37:
+            GET_REG32(lm32_pic_get_im(env->pic_state));
+            break;
+        case 38:
+            GET_REG32(lm32_pic_get_ip(env->pic_state));
+            break;
+        }
     }
+    return 0;
+}
+
+static int cpu_gdb_write_register(CPUState *env, uint8_t *mem_buf, int n)
+{
+    uint32_t tmp;
 
-    if (n == 64 ) {
-       env->pc=tmp;
+    if (n > NUM_CORE_REGS) {
+        return 0;
     }
 
-    return 8;
+    tmp = ldl_p(mem_buf);
+
+    if (n < 32) {
+        env->regs[n] = tmp;
+    } else {
+        switch (n) {
+        case 32:
+            env->pc = tmp;
+            break;
+        case 34:
+            env->eba = tmp;
+            break;
+        case 35:
+            env->deba = tmp;
+            break;
+        case 36:
+            env->ie = tmp;
+            break;
+        case 37:
+            lm32_pic_set_im(env->pic_state, tmp);
+            break;
+        case 38:
+            lm32_pic_set_ip(env->pic_state, tmp);
+            break;
+        }
+    }
+    return 4;
 }
 #else
 
@@ -1361,7 +1583,6 @@ static int memtox(char *buf, const char *mem, int len)
 
 static const char *get_feature_xml(const char *p, const char **newp)
 {
-    extern const char *const xml_builtin[][2];
     size_t len;
     int i;
     const char *name;
@@ -1580,13 +1801,23 @@ static void gdb_set_cpu_pc(GDBState *s, target_ulong pc)
 #elif defined (TARGET_SH4)
     s->c_cpu->pc = pc;
 #elif defined (TARGET_MIPS)
-    s->c_cpu->active_tc.PC = pc;
+    s->c_cpu->active_tc.PC = pc & ~(target_ulong)1;
+    if (pc & 1) {
+        s->c_cpu->hflags |= MIPS_HFLAG_M16;
+    } else {
+        s->c_cpu->hflags &= ~(MIPS_HFLAG_M16);
+    }
 #elif defined (TARGET_MICROBLAZE)
     s->c_cpu->sregs[SR_PC] = pc;
 #elif defined (TARGET_CRIS)
     s->c_cpu->pc = pc;
 #elif defined (TARGET_ALPHA)
     s->c_cpu->pc = pc;
+#elif defined (TARGET_S390X)
+    cpu_synchronize_state(s->c_cpu);
+    s->c_cpu->psw.addr = pc;
+#elif defined (TARGET_LM32)
+    s->c_cpu->pc = pc;
 #endif
 }
 
@@ -1719,6 +1950,7 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
     case 'D':
         /* Detach packet */
         gdb_breakpoint_remove_all();
+        gdb_syscall_mode = GDB_SYS_DISABLED;
         gdb_continue(s);
         put_packet(s, "OK");
         break;
@@ -2043,14 +2275,11 @@ static void gdb_vm_state_change(void *opaque, int running, int reason)
     const char *type;
     int ret;
 
-    if (running || (reason != EXCP_DEBUG && reason != EXCP_INTERRUPT) ||
-        s->state == RS_INACTIVE || s->state == RS_SYSCALL)
+    if (running || s->state == RS_INACTIVE || s->state == RS_SYSCALL) {
         return;
-
-    /* disable single step if it was enable */
-    cpu_single_step(env, 0);
-
-    if (reason == EXCP_DEBUG) {
+    }
+    switch (reason) {
+    case VMSTOP_DEBUG:
         if (env->watchpoint_hit) {
             switch (env->watchpoint_hit->flags & BP_MEM_ACCESS) {
             case BP_MEM_READ:
@@ -2067,17 +2296,44 @@ static void gdb_vm_state_change(void *opaque, int running, int reason)
                      "T%02xthread:%02x;%swatch:" TARGET_FMT_lx ";",
                      GDB_SIGNAL_TRAP, gdb_id(env), type,
                      env->watchpoint_hit->vaddr);
-            put_packet(s, buf);
             env->watchpoint_hit = NULL;
-            return;
+            goto send_packet;
         }
-       tb_flush(env);
+        tb_flush(env);
         ret = GDB_SIGNAL_TRAP;
-    } else {
+        break;
+    case VMSTOP_USER:
         ret = GDB_SIGNAL_INT;
+        break;
+    case VMSTOP_SHUTDOWN:
+        ret = GDB_SIGNAL_QUIT;
+        break;
+    case VMSTOP_DISKFULL:
+        ret = GDB_SIGNAL_IO;
+        break;
+    case VMSTOP_WATCHDOG:
+        ret = GDB_SIGNAL_ALRM;
+        break;
+    case VMSTOP_PANIC:
+        ret = GDB_SIGNAL_ABRT;
+        break;
+    case VMSTOP_SAVEVM:
+    case VMSTOP_LOADVM:
+        return;
+    case VMSTOP_MIGRATE:
+        ret = GDB_SIGNAL_XCPU;
+        break;
+    default:
+        ret = GDB_SIGNAL_UNKNOWN;
+        break;
     }
     snprintf(buf, sizeof(buf), "T%02xthread:%02x;", ret, gdb_id(env));
+
+send_packet:
     put_packet(s, buf);
+
+    /* disable single step if it was enabled */
+    cpu_single_step(env, 0);
 }
 #endif
 
@@ -2101,7 +2357,7 @@ void gdb_do_syscall(gdb_syscall_complete_cb cb, const char *fmt, ...)
     gdb_current_syscall_cb = cb;
     s->state = RS_SYSCALL;
 #ifndef CONFIG_USER_ONLY
-    vm_stop(EXCP_DEBUG);
+    vm_stop(VMSTOP_DEBUG);
 #endif
     s->state = RS_IDLE;
     va_start(va, fmt);
@@ -2175,7 +2431,7 @@ static void gdb_read_byte(GDBState *s, int ch)
     if (vm_running) {
         /* when the CPU is running, we cannot do anything except stop
            it when receiving a char */
-        vm_stop(EXCP_INTERRUPT);
+        vm_stop(VMSTOP_USER);
     } else
 #endif
     {
@@ -2222,6 +2478,32 @@ static void gdb_read_byte(GDBState *s, int ch)
     }
 }
 
+/* Tell the remote gdb that the process has exited.  */
+void gdb_exit(CPUState *env, int code)
+{
+  GDBState *s;
+  char buf[4];
+
+  s = gdbserver_state;
+  if (!s) {
+      return;
+  }
+#ifdef CONFIG_USER_ONLY
+  if (gdbserver_fd < 0 || s->fd < 0) {
+      return;
+  }
+#endif
+
+  snprintf(buf, sizeof(buf), "W%02x", (uint8_t)code);
+  put_packet(s, buf);
+
+#ifndef CONFIG_USER_ONLY
+  if (s->chr) {
+      qemu_chr_close(s->chr);
+  }
+#endif
+}
+
 #ifdef CONFIG_USER_ONLY
 int
 gdb_queuesig (void)
@@ -2285,20 +2567,6 @@ gdb_handlesig (CPUState *env, int sig)
   return sig;
 }
 
-/* Tell the remote gdb that the process has exited.  */
-void gdb_exit(CPUState *env, int code)
-{
-  GDBState *s;
-  char buf[4];
-
-  s = gdbserver_state;
-  if (gdbserver_fd < 0 || s->fd < 0)
-    return;
-
-  snprintf(buf, sizeof(buf), "W%02x", code);
-  put_packet(s, buf);
-}
-
 /* Tell the remote gdb that the process has exited due to SIG.  */
 void gdb_signalled(CPUState *env, int sig)
 {
@@ -2327,6 +2595,9 @@ static void gdb_accept(void)
             perror("accept");
             return;
         } else if (fd >= 0) {
+#ifndef _WIN32
+            fcntl(fd, F_SETFD, FD_CLOEXEC);
+#endif
             break;
         }
     }
@@ -2356,6 +2627,9 @@ static int gdbserver_open(int port)
         perror("socket");
         return -1;
     }
+#ifndef _WIN32
+    fcntl(fd, F_SETFD, FD_CLOEXEC);
+#endif
 
     /* allow fast reuse */
     val = 1;
@@ -2418,8 +2692,8 @@ static void gdb_chr_receive(void *opaque, const uint8_t *buf, int size)
 static void gdb_chr_event(void *opaque, int event)
 {
     switch (event) {
-    case CHR_EVENT_RESET:
-        vm_stop(EXCP_INTERRUPT);
+    case CHR_EVENT_OPENED:
+        vm_stop(VMSTOP_USER);
         gdb_has_xml = 0;
         break;
     default:
@@ -2459,8 +2733,9 @@ static int gdb_monitor_write(CharDriverState *chr, const uint8_t *buf, int len)
 #ifndef _WIN32
 static void gdb_sigterm_handler(int signal)
 {
-    if (vm_running)
-        vm_stop(EXCP_INTERRUPT);
+    if (vm_running) {
+        vm_stop(VMSTOP_USER);
+    }
 }
 #endif