X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=gdbstub.c;h=e80e1d32b10b15aefac006e398ee7101f3642c66;hb=5f5a1318653c08e435cfa52f60b6a712815b659d;hp=f4e97f7370d054cd9c1518c79726e761a962b908;hpb=aea6ff7fa07b046fb9f43d6262d6e34b77e8437e;p=qemu.git diff --git a/gdbstub.c b/gdbstub.c index f4e97f737..e80e1d32b 100644 --- a/gdbstub.c +++ b/gdbstub.c @@ -29,17 +29,18 @@ #include "qemu.h" #else -#include "monitor.h" -#include "qemu-char.h" -#include "sysemu.h" -#include "gdbstub.h" +#include "monitor/monitor.h" +#include "sysemu/char.h" +#include "sysemu/sysemu.h" +#include "exec/gdbstub.h" #endif #define MAX_PACKET_LENGTH 4096 #include "cpu.h" -#include "qemu_socket.h" -#include "kvm.h" +#include "qemu/sockets.h" +#include "sysemu/kvm.h" +#include "qemu/bitops.h" #ifndef TARGET_CPU_MEMORY_RW_DEBUG static inline int target_memory_rw_debug(CPUArchState *env, target_ulong addr, @@ -284,7 +285,6 @@ enum RSState { RS_GETLINE, RS_CHKSUM1, RS_CHKSUM2, - RS_SYSCALL, }; typedef struct GDBState { CPUArchState *c_cpu; /* current CPU for step/continue ops */ @@ -304,6 +304,8 @@ typedef struct GDBState { CharDriverState *chr; CharDriverState *mon_chr; #endif + char syscall_buf[256]; + gdb_syscall_complete_cb current_syscall_cb; } GDBState; /* By default use no IRQs and no timers while single stepping so as to @@ -346,8 +348,6 @@ static int get_char(GDBState *s) } #endif -static gdb_syscall_complete_cb gdb_current_syscall_cb; - static enum { GDB_SYS_UNKNOWN, GDB_SYS_ENABLED, @@ -781,7 +781,8 @@ static int cpu_gdb_write_register(CPUPPCState *env, uint8_t *mem_buf, int n) /* fpscr */ if (gdb_has_xml) return 0; - return 4; + store_fpscr(env, ldtul_p(mem_buf), 0xffffffff); + return sizeof(target_ulong); } } return 0; @@ -1156,6 +1157,68 @@ static int cpu_gdb_write_register(CPUMIPSState *env, uint8_t *mem_buf, int n) return sizeof(target_ulong); } +#elif defined(TARGET_OPENRISC) + +#define NUM_CORE_REGS (32 + 3) + +static int cpu_gdb_read_register(CPUOpenRISCState *env, uint8_t *mem_buf, int n) +{ + if (n < 32) { + GET_REG32(env->gpr[n]); + } else { + switch (n) { + case 32: /* PPC */ + GET_REG32(env->ppc); + break; + + case 33: /* NPC */ + GET_REG32(env->npc); + break; + + case 34: /* SR */ + GET_REG32(env->sr); + break; + + default: + break; + } + } + return 0; +} + +static int cpu_gdb_write_register(CPUOpenRISCState *env, + uint8_t *mem_buf, int n) +{ + uint32_t tmp; + + if (n > NUM_CORE_REGS) { + return 0; + } + + tmp = ldl_p(mem_buf); + + if (n < 32) { + env->gpr[n] = tmp; + } else { + switch (n) { + case 32: /* PPC */ + env->ppc = tmp; + break; + + case 33: /* NPC */ + env->npc = tmp; + break; + + case 34: /* SR */ + env->sr = tmp; + break; + + default: + break; + } + } + return 4; +} #elif defined (TARGET_SH4) /* Hint: Use "set architecture sh4" in GDB to see fpu registers */ @@ -1165,33 +1228,48 @@ static int cpu_gdb_write_register(CPUMIPSState *env, uint8_t *mem_buf, int n) static int cpu_gdb_read_register(CPUSH4State *env, uint8_t *mem_buf, int n) { - if (n < 8) { + switch (n) { + case 0 ... 7: if ((env->sr & (SR_MD | SR_RB)) == (SR_MD | SR_RB)) { GET_REGL(env->gregs[n + 16]); } else { GET_REGL(env->gregs[n]); } - } else if (n < 16) { + case 8 ... 15: 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) { - GET_REGL(env->gregs[n - 43]); - } else if (n >= 51 && n < 59) { - GET_REGL(env->gregs[n - (51 - 16)]); - } - switch (n) { - case 16: GET_REGL(env->pc); - case 17: GET_REGL(env->pr); - case 18: GET_REGL(env->gbr); - case 19: GET_REGL(env->vbr); - case 20: GET_REGL(env->mach); - case 21: GET_REGL(env->macl); - case 22: GET_REGL(env->sr); - case 23: GET_REGL(env->fpul); - case 24: GET_REGL(env->fpscr); - case 41: GET_REGL(env->ssr); - case 42: GET_REGL(env->spc); + case 16: + GET_REGL(env->pc); + case 17: + GET_REGL(env->pr); + case 18: + GET_REGL(env->gbr); + case 19: + GET_REGL(env->vbr); + case 20: + GET_REGL(env->mach); + case 21: + GET_REGL(env->macl); + case 22: + GET_REGL(env->sr); + case 23: + GET_REGL(env->fpul); + case 24: + GET_REGL(env->fpscr); + case 25 ... 40: + if (env->fpscr & FPSCR_FR) { + stfl_p(mem_buf, env->fregs[n - 9]); + } else { + stfl_p(mem_buf, env->fregs[n - 25]); + } + return 4; + case 41: + GET_REGL(env->ssr); + case 42: + GET_REGL(env->spc); + case 43 ... 50: + GET_REGL(env->gregs[n - 43]); + case 51 ... 58: + GET_REGL(env->gregs[n - (51 - 16)]); } return 0; @@ -1199,42 +1277,63 @@ static int cpu_gdb_read_register(CPUSH4State *env, uint8_t *mem_buf, int n) static int cpu_gdb_write_register(CPUSH4State *env, uint8_t *mem_buf, int n) { - uint32_t tmp; - - tmp = ldl_p(mem_buf); - - if (n < 8) { + switch (n) { + case 0 ... 7: if ((env->sr & (SR_MD | SR_RB)) == (SR_MD | SR_RB)) { - env->gregs[n + 16] = tmp; + env->gregs[n + 16] = ldl_p(mem_buf); } else { - env->gregs[n] = tmp; + env->gregs[n] = ldl_p(mem_buf); } - return 4; - } else if (n < 16) { - 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; - } else if (n >= 51 && n < 59) { - env->gregs[n - (51 - 16)] = tmp; - return 4; - } - switch (n) { - 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; + break; + case 8 ... 15: + env->gregs[n] = ldl_p(mem_buf); + break; + case 16: + env->pc = ldl_p(mem_buf); + break; + case 17: + env->pr = ldl_p(mem_buf); + break; + case 18: + env->gbr = ldl_p(mem_buf); + break; + case 19: + env->vbr = ldl_p(mem_buf); + break; + case 20: + env->mach = ldl_p(mem_buf); + break; + case 21: + env->macl = ldl_p(mem_buf); + break; + case 22: + env->sr = ldl_p(mem_buf); + break; + case 23: + env->fpul = ldl_p(mem_buf); + break; + case 24: + env->fpscr = ldl_p(mem_buf); + break; + case 25 ... 40: + if (env->fpscr & FPSCR_FR) { + env->fregs[n - 9] = ldfl_p(mem_buf); + } else { + env->fregs[n - 25] = ldfl_p(mem_buf); + } + break; + case 41: + env->ssr = ldl_p(mem_buf); + break; + case 42: + env->spc = ldl_p(mem_buf); + break; + case 43 ... 50: + env->gregs[n - 43] = ldl_p(mem_buf); + break; + case 51 ... 58: + env->gregs[n - (51 - 16)] = ldl_p(mem_buf); + break; default: return 0; } @@ -1438,27 +1537,34 @@ static int cpu_gdb_write_register(CPUAlphaState *env, uint8_t *mem_buf, int n) } #elif defined (TARGET_S390X) -#define NUM_CORE_REGS S390_NUM_TOTAL_REGS +#define NUM_CORE_REGS S390_NUM_REGS static int cpu_gdb_read_register(CPUS390XState *env, uint8_t *mem_buf, int n) { + uint64_t val; + int cc_op; + 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; + case S390_PSWM_REGNUM: + cc_op = calc_cc(env, env->cc_op, env->cc_src, env->cc_dst, env->cc_vr); + val = deposit64(env->psw.mask, 44, 2, cc_op); + GET_REGL(val); + 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: + GET_REG64(env->fregs[n-S390_F0_REGNUM].ll); + break; } return 0; @@ -1473,25 +1579,35 @@ static int cpu_gdb_write_register(CPUS390XState *env, uint8_t *mem_buf, int n) tmp32 = ldl_p(mem_buf); 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; + case S390_PSWM_REGNUM: + env->psw.mask = tmpl; + env->cc_op = extract64(tmpl, 44, 2); + 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: + env->fregs[n-S390_F0_REGNUM].ll = tmpl; + break; + default: + return 0; } - return r; } #elif defined (TARGET_LM32) -#include "hw/lm32_pic.h" +#include "hw/lm32/lm32_pic.h" #define NUM_CORE_REGS (32 + 7) static int cpu_gdb_read_register(CPULM32State *env, uint8_t *mem_buf, int n) @@ -1599,6 +1715,10 @@ static int cpu_gdb_read_register(CPUXtensaState *env, uint8_t *mem_buf, int n) GET_REG32(env->uregs[reg->targno & 0xff]); break; + case 4: /*f*/ + GET_REG32(float32_val(env->fregs[reg->targno & 0x0f])); + break; + case 8: /*a*/ GET_REG32(env->regs[reg->targno & 0x0f]); break; @@ -1639,6 +1759,10 @@ static int cpu_gdb_write_register(CPUXtensaState *env, uint8_t *mem_buf, int n) env->uregs[reg->targno & 0xff] = tmp; break; + case 4: /*f*/ + env->fregs[reg->targno & 0x0f] = make_float32(tmp); + break; + case 8: /*a*/ env->regs[reg->targno & 0x0f] = tmp; break; @@ -1904,8 +2028,8 @@ static void gdb_breakpoint_remove_all(void) static void gdb_set_cpu_pc(GDBState *s, target_ulong pc) { -#if defined(TARGET_I386) cpu_synchronize_state(s->c_cpu); +#if defined(TARGET_I386) s->c_cpu->eip = pc; #elif defined (TARGET_PPC) s->c_cpu->nip = pc; @@ -1925,12 +2049,13 @@ static void gdb_set_cpu_pc(GDBState *s, target_ulong pc) } #elif defined (TARGET_MICROBLAZE) s->c_cpu->sregs[SR_PC] = pc; +#elif defined(TARGET_OPENRISC) + s->c_cpu->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; @@ -1939,21 +2064,14 @@ static void gdb_set_cpu_pc(GDBState *s, target_ulong pc) #endif } -static inline int gdb_id(CPUArchState *env) -{ -#if defined(CONFIG_USER_ONLY) && defined(CONFIG_USE_NPTL) - return env->host_tid; -#else - return env->cpu_index + 1; -#endif -} - static CPUArchState *find_cpu(uint32_t thread_id) { CPUArchState *env; + CPUState *cpu; for (env = first_cpu; env != NULL; env = env->next_cpu) { - if (gdb_id(env) == thread_id) { + cpu = ENV_GET_CPU(env); + if (cpu_index(cpu) == thread_id) { return env; } } @@ -1981,7 +2099,7 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf) case '?': /* TODO: Make this return the correct value for user-mode. */ snprintf(buf, sizeof(buf), "T%02xthread:%02x;", GDB_SIGNAL_TRAP, - gdb_id(s->c_cpu)); + cpu_index(ENV_GET_CPU(s->c_cpu))); put_packet(s, buf); /* Remove all the breakpoints when this query is issued, * because gdb is doing and initial connect and the state @@ -2097,8 +2215,10 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf) if (*p == ',') p++; type = *p; - if (gdb_current_syscall_cb) - gdb_current_syscall_cb(s->c_cpu, ret, err); + if (s->current_syscall_cb) { + s->current_syscall_cb(s->c_cpu, ret, err); + s->current_syscall_cb = NULL; + } if (type == 'C') { put_packet(s, "T02"); } else { @@ -2274,7 +2394,8 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf) } else if (strcmp(p,"sThreadInfo") == 0) { report_cpuinfo: if (s->query_cpu) { - snprintf(buf, sizeof(buf), "m%x", gdb_id(s->query_cpu)); + snprintf(buf, sizeof(buf), "m%x", + cpu_index(ENV_GET_CPU(s->query_cpu))); put_packet(s, buf); s->query_cpu = s->query_cpu->next_cpu; } else @@ -2284,10 +2405,11 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf) thread = strtoull(p+16, (char **)&p, 16); env = find_cpu(thread); if (env != NULL) { + CPUState *cpu = ENV_GET_CPU(env); cpu_synchronize_state(env); len = snprintf((char *)mem_buf, sizeof(mem_buf), - "CPU#%d [%s]", env->cpu_index, - env->halted ? "halted " : "running"); + "CPU#%d [%s]", cpu->cpu_index, + cpu->halted ? "halted " : "running"); memtohex(buf, mem_buf, len); put_packet(s, buf); } @@ -2394,11 +2516,17 @@ static void gdb_vm_state_change(void *opaque, int running, RunState state) { GDBState *s = gdbserver_state; CPUArchState *env = s->c_cpu; + CPUState *cpu = ENV_GET_CPU(env); char buf[256]; const char *type; int ret; - if (running || s->state == RS_INACTIVE || s->state == RS_SYSCALL) { + if (running || s->state == RS_INACTIVE) { + return; + } + /* Is there a GDB syscall waiting to be sent? */ + if (s->current_syscall_cb) { + put_packet(s, s->syscall_buf); return; } switch (state) { @@ -2417,7 +2545,7 @@ static void gdb_vm_state_change(void *opaque, int running, RunState state) } snprintf(buf, sizeof(buf), "T%02xthread:%02x;%swatch:" TARGET_FMT_lx ";", - GDB_SIGNAL_TRAP, gdb_id(env), type, + GDB_SIGNAL_TRAP, cpu_index(cpu), type, env->watchpoint_hit->vaddr); env->watchpoint_hit = NULL; goto send_packet; @@ -2450,7 +2578,7 @@ static void gdb_vm_state_change(void *opaque, int running, RunState state) ret = GDB_SIGNAL_UNKNOWN; break; } - snprintf(buf, sizeof(buf), "T%02xthread:%02x;", ret, gdb_id(env)); + snprintf(buf, sizeof(buf), "T%02xthread:%02x;", ret, cpu_index(cpu)); send_packet: put_packet(s, buf); @@ -2468,8 +2596,8 @@ send_packet: void gdb_do_syscall(gdb_syscall_complete_cb cb, const char *fmt, ...) { va_list va; - char buf[256]; char *p; + char *p_end; target_ulong addr; uint64_t i64; GDBState *s; @@ -2477,14 +2605,13 @@ void gdb_do_syscall(gdb_syscall_complete_cb cb, const char *fmt, ...) s = gdbserver_state; if (!s) return; - gdb_current_syscall_cb = cb; - s->state = RS_SYSCALL; + s->current_syscall_cb = cb; #ifndef CONFIG_USER_ONLY vm_stop(RUN_STATE_DEBUG); #endif - s->state = RS_IDLE; va_start(va, fmt); - p = buf; + p = s->syscall_buf; + p_end = &s->syscall_buf[sizeof(s->syscall_buf)]; *(p++) = 'F'; while (*fmt) { if (*fmt == '%') { @@ -2492,17 +2619,17 @@ void gdb_do_syscall(gdb_syscall_complete_cb cb, const char *fmt, ...) switch (*fmt++) { case 'x': addr = va_arg(va, target_ulong); - p += snprintf(p, &buf[sizeof(buf)] - p, TARGET_FMT_lx, addr); + p += snprintf(p, p_end - p, TARGET_FMT_lx, addr); break; case 'l': if (*(fmt++) != 'x') goto bad_format; i64 = va_arg(va, uint64_t); - p += snprintf(p, &buf[sizeof(buf)] - p, "%" PRIx64, i64); + p += snprintf(p, p_end - p, "%" PRIx64, i64); break; case 's': addr = va_arg(va, target_ulong); - p += snprintf(p, &buf[sizeof(buf)] - p, TARGET_FMT_lx "/%x", + p += snprintf(p, p_end - p, TARGET_FMT_lx "/%x", addr, va_arg(va, int)); break; default: @@ -2517,10 +2644,16 @@ void gdb_do_syscall(gdb_syscall_complete_cb cb, const char *fmt, ...) } *p = 0; va_end(va); - put_packet(s, buf); #ifdef CONFIG_USER_ONLY + put_packet(s, s->syscall_buf); gdb_handlesig(s->c_cpu, 0); #else + /* In this case wait to send the syscall packet until notification that + the CPU has stopped. This must be done because if the packet is sent + now the reply from the syscall request could be received while the CPU + is still in the running state, which can cause packets to be dropped + and state transition 'T' packets to be sent while the syscall is still + being processed. */ cpu_exit(s->c_cpu); #endif } @@ -2709,7 +2842,7 @@ static void gdb_accept(void) GDBState *s; struct sockaddr_in sockaddr; socklen_t len; - int val, fd; + int fd; for(;;) { len = sizeof(sockaddr); @@ -2726,8 +2859,7 @@ static void gdb_accept(void) } /* set short latency */ - val = 1; - setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *)&val, sizeof(val)); + socket_set_nodelay(fd); s = g_malloc0(sizeof(GDBState)); s->c_cpu = first_cpu; @@ -2756,7 +2888,7 @@ static int gdbserver_open(int port) /* allow fast reuse */ val = 1; - setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&val, sizeof(val)); + qemu_setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)); sockaddr.sin_family = AF_INET; sockaddr.sin_port = htons(port); @@ -2893,6 +3025,7 @@ int gdbserver_start(const char *device) if (!chr) return -1; + qemu_chr_fe_claim_no_fail(chr); qemu_chr_add_handlers(chr, gdb_chr_can_receive, gdb_chr_receive, gdb_chr_event, NULL); } @@ -2919,6 +3052,7 @@ int gdbserver_start(const char *device) s->chr = chr; s->state = chr ? RS_IDLE : RS_INACTIVE; s->mon_chr = mon_chr; + s->current_syscall_cb = NULL; return 0; }