X-Git-Url: http://vcs.maemo.org/git/?a=blobdiff_plain;f=gdbstub.c;h=bca9b1e2a647005e792a6e23a7b4819671e931f6;hb=7ef4da1c3a753888e2678388150f1b846b025168;hp=cbae3208cfccf9c548e68fe1e8c2e7673a5216ef;hpb=3fc6c082e3aad85addf25d36740030982963c0c8;p=qemu diff --git a/gdbstub.c b/gdbstub.c index cbae320..bca9b1e 100644 --- a/gdbstub.c +++ b/gdbstub.c @@ -47,6 +47,7 @@ enum RSState { static int gdbserver_fd = -1; typedef struct GDBState { + CPUState *env; /* current CPU */ enum RSState state; /* parsing state */ int fd; char line_buf[4096]; @@ -297,7 +298,7 @@ static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf) int i; /* fill in g0..g7 */ - for(i = 0; i < 7; i++) { + for(i = 0; i < 8; i++) { registers[i] = tswapl(env->gregs[i]); } /* fill in register window */ @@ -398,7 +399,7 @@ static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf) memset (ptr, 0, 8 * 12 + 4); ptr += 8 * 12 + 4; /* CPSR (4 bytes). */ - *(uint32_t *)ptr = tswapl (env->cpsr); + *(uint32_t *)ptr = tswapl (cpsr_read(env)); ptr += 4; return ptr - mem_buf; @@ -418,7 +419,112 @@ static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size) } /* Ignore FPA regs and scr. */ ptr += 8 * 12 + 4; - env->cpsr = tswapl(*(uint32_t *)ptr); + cpsr_write (env, tswapl(*(uint32_t *)ptr), 0xffffffff); +} +#elif defined (TARGET_MIPS) +static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf) +{ + int i; + uint8_t *ptr; + + ptr = mem_buf; + for (i = 0; i < 32; i++) + { + *(uint32_t *)ptr = tswapl(env->gpr[i]); + ptr += 4; + } + + *(uint32_t *)ptr = tswapl(env->CP0_Status); + ptr += 4; + + *(uint32_t *)ptr = tswapl(env->LO); + ptr += 4; + + *(uint32_t *)ptr = tswapl(env->HI); + ptr += 4; + + *(uint32_t *)ptr = tswapl(env->CP0_BadVAddr); + ptr += 4; + + *(uint32_t *)ptr = tswapl(env->CP0_Cause); + ptr += 4; + + *(uint32_t *)ptr = tswapl(env->PC); + ptr += 4; + + /* 32 FP registers, fsr, fir, fp. Not yet implemented. */ + + return ptr - mem_buf; +} + +static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size) +{ + int i; + uint8_t *ptr; + + ptr = mem_buf; + for (i = 0; i < 32; i++) + { + env->gpr[i] = tswapl(*(uint32_t *)ptr); + ptr += 4; + } + + env->CP0_Status = tswapl(*(uint32_t *)ptr); + ptr += 4; + + env->LO = tswapl(*(uint32_t *)ptr); + ptr += 4; + + env->HI = tswapl(*(uint32_t *)ptr); + ptr += 4; + + env->CP0_BadVAddr = tswapl(*(uint32_t *)ptr); + ptr += 4; + + env->CP0_Cause = tswapl(*(uint32_t *)ptr); + ptr += 4; + + env->PC = tswapl(*(uint32_t *)ptr); + ptr += 4; +} +#elif defined (TARGET_SH4) +static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf) +{ + uint32_t *ptr = (uint32_t *)mem_buf; + int i; + +#define SAVE(x) *ptr++=tswapl(x) + for (i = 0; i < 16; i++) SAVE(env->gregs[i]); + SAVE (env->pc); + SAVE (env->pr); + SAVE (env->gbr); + SAVE (env->vbr); + SAVE (env->mach); + SAVE (env->macl); + SAVE (env->sr); + SAVE (0); /* TICKS */ + SAVE (0); /* STALLS */ + SAVE (0); /* CYCLES */ + SAVE (0); /* INSTS */ + SAVE (0); /* PLR */ + + return ((uint8_t *)ptr - mem_buf); +} + +static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size) +{ + uint32_t *ptr = (uint32_t *)mem_buf; + int i; + +#define LOAD(x) (x)=*ptr++; + for (i = 0; i < 16; i++) LOAD(env->gregs[i]); + LOAD (env->pc); + LOAD (env->pr); + LOAD (env->gbr); + LOAD (env->vbr); + LOAD (env->mach); + LOAD (env->macl); + LOAD (env->sr); } #else static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf) @@ -462,6 +568,10 @@ static int gdb_handle_packet(GDBState *s, CPUState *env, const char *line_buf) #elif defined (TARGET_SPARC) env->pc = addr; env->npc = addr + 4; +#elif defined (TARGET_ARM) + env->regs[15] = addr; +#elif defined (TARGET_SH4) + env->pc = addr; #endif } #ifdef CONFIG_USER_ONLY @@ -480,6 +590,10 @@ static int gdb_handle_packet(GDBState *s, CPUState *env, const char *line_buf) #elif defined (TARGET_SPARC) env->pc = addr; env->npc = addr + 4; +#elif defined (TARGET_ARM) + env->regs[15] = addr; +#elif defined (TARGET_SH4) + env->pc = addr; #endif } cpu_single_step(env, 1); @@ -506,10 +620,12 @@ static int gdb_handle_packet(GDBState *s, CPUState *env, const char *line_buf) if (*p == ',') p++; len = strtoul(p, NULL, 16); - if (cpu_memory_rw_debug(env, addr, mem_buf, len, 0) != 0) - memset(mem_buf, 0, len); - memtohex(buf, mem_buf, len); - put_packet(s, buf); + if (cpu_memory_rw_debug(env, addr, mem_buf, len, 0) != 0) { + put_packet (s, "E14"); + } else { + memtohex(buf, mem_buf, len); + put_packet(s, buf); + } break; case 'M': addr = strtoul(p, (char **)&p, 16); @@ -576,21 +692,24 @@ static void gdb_vm_stopped(void *opaque, int reason) int ret; /* disable single step if it was enable */ - cpu_single_step(cpu_single_env, 0); + cpu_single_step(s->env, 0); if (reason == EXCP_DEBUG) { - tb_flush(cpu_single_env); + tb_flush(s->env); ret = SIGTRAP; - } - else + } else if (reason == EXCP_INTERRUPT) { + ret = SIGINT; + } else { ret = 0; + } snprintf(buf, sizeof(buf), "S%02x", ret); put_packet(s, buf); } #endif -static void gdb_read_byte(GDBState *s, CPUState *env, int ch) +static void gdb_read_byte(GDBState *s, int ch) { + CPUState *env = s->env; int i, csum; char reply[1]; @@ -676,7 +795,7 @@ gdb_handlesig (CPUState *env, int sig) int i; for (i = 0; i < n; i++) - gdb_read_byte (s, env, buf[i]); + gdb_read_byte (s, buf[i]); } else if (n == 0 || errno != EAGAIN) { @@ -704,30 +823,30 @@ void gdb_exit(CPUState *env, int code) } #else -static int gdb_can_read(void *opaque) -{ - return 256; -} - -static void gdb_read(void *opaque, const uint8_t *buf, int size) +static void gdb_read(void *opaque) { GDBState *s = opaque; - int i; + int i, size; + uint8_t buf[4096]; + + size = read(s->fd, buf, sizeof(buf)); + if (size < 0) + return; if (size == 0) { /* end of connection */ qemu_del_vm_stop_handler(gdb_vm_stopped, s); - qemu_del_fd_read_handler(s->fd); + qemu_set_fd_handler(s->fd, NULL, NULL, NULL); qemu_free(s); vm_start(); } else { for(i = 0; i < size; i++) - gdb_read_byte(s, cpu_single_env, buf[i]); + gdb_read_byte(s, buf[i]); } } #endif -static void gdb_accept(void *opaque, const uint8_t *buf, int size) +static void gdb_accept(void *opaque) { GDBState *s; struct sockaddr_in sockaddr; @@ -759,6 +878,7 @@ static void gdb_accept(void *opaque, const uint8_t *buf, int size) return; } #endif + s->env = first_cpu; /* XXX: allow to change CPU */ s->fd = fd; fcntl(fd, F_SETFL, O_NONBLOCK); @@ -768,7 +888,7 @@ static void gdb_accept(void *opaque, const uint8_t *buf, int size) vm_stop(EXCP_INTERRUPT); /* start handling I/O */ - qemu_add_fd_read_handler(s->fd, gdb_can_read, gdb_read, s); + qemu_set_fd_handler(s->fd, gdb_read, NULL, s); /* when the VM is stopped, the following callback is called */ qemu_add_vm_stop_handler(gdb_vm_stopped, s); #endif @@ -815,9 +935,9 @@ int gdbserver_start(int port) return -1; /* accept connections */ #ifdef CONFIG_USER_ONLY - gdb_accept (NULL, NULL, 0); + gdb_accept (NULL); #else - qemu_add_fd_read_handler(gdbserver_fd, NULL, gdb_accept, NULL); + qemu_set_fd_handler(gdbserver_fd, gdb_accept, NULL, NULL); #endif return 0; }