#include "qemu.h"
#else
#include "monitor/monitor.h"
-#include "char/char.h"
+#include "sysemu/char.h"
#include "sysemu/sysemu.h"
#include "exec/gdbstub.h"
#endif
#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,
- uint8_t *buf, int len, int is_write)
+static inline int target_memory_rw_debug(CPUState *cpu, target_ulong addr,
+ uint8_t *buf, int len, bool is_write)
{
- return cpu_memory_rw_debug(env, addr, buf, len, is_write);
+ CPUClass *cc = CPU_GET_CLASS(cpu);
+
+ if (cc->memory_rw_debug) {
+ return cc->memory_rw_debug(cpu, addr, buf, len, is_write);
+ }
+ return cpu_memory_rw_debug(cpu, addr, buf, len, is_write);
}
-#else
-/* target_memory_rw_debug() defined in cpu.h */
-#endif
enum {
GDB_SIGNAL_0 = 0,
RS_CHKSUM2,
};
typedef struct GDBState {
- CPUArchState *c_cpu; /* current CPU for step/continue ops */
- CPUArchState *g_cpu; /* current CPU for other ops */
- CPUArchState *query_cpu; /* for q{f|s}ThreadInfo */
+ CPUState *c_cpu; /* current CPU for step/continue ops */
+ CPUState *g_cpu; /* current CPU for other ops */
+ CPUState *query_cpu; /* for q{f|s}ThreadInfo */
enum RSState state; /* parsing state */
char line_buf[MAX_PACKET_LENGTH];
int line_buf_index;
#ifdef CONFIG_USER_ONLY
s->running_state = 1;
#else
- vm_start();
+ if (runstate_check(RUN_STATE_GUEST_PANICKED)) {
+ runstate_set(RUN_STATE_DEBUG);
+ }
+ if (!runstate_needs_reset()) {
+ vm_start();
+ }
#endif
}
/* fpscr */
if (gdb_has_xml)
return 0;
- return 4;
+ store_fpscr(env, ldtul_p(mem_buf), 0xffffffff);
+ return sizeof(target_ulong);
}
}
return 0;
}
#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)
/* Generate the XML description for this CPU. */
if (!target_xml[0]) {
GDBRegisterState *r;
+ CPUState *cpu = first_cpu;
snprintf(target_xml, sizeof(target_xml),
"<?xml version=\"1.0\"?>"
"<xi:include href=\"%s\"/>",
GDB_CORE_XML);
- for (r = first_cpu->gdb_regs; r; r = r->next) {
+ for (r = cpu->gdb_regs; r; r = r->next) {
pstrcat(target_xml, sizeof(target_xml), "<xi:include href=\"");
pstrcat(target_xml, sizeof(target_xml), r->xml);
pstrcat(target_xml, sizeof(target_xml), "\"/>");
}
#endif
-static int gdb_read_register(CPUArchState *env, uint8_t *mem_buf, int reg)
+static int gdb_read_register(CPUState *cpu, uint8_t *mem_buf, int reg)
{
+ CPUArchState *env = cpu->env_ptr;
GDBRegisterState *r;
if (reg < NUM_CORE_REGS)
return cpu_gdb_read_register(env, mem_buf, reg);
- for (r = env->gdb_regs; r; r = r->next) {
+ for (r = cpu->gdb_regs; r; r = r->next) {
if (r->base_reg <= reg && reg < r->base_reg + r->num_regs) {
return r->get_reg(env, mem_buf, reg - r->base_reg);
}
return 0;
}
-static int gdb_write_register(CPUArchState *env, uint8_t *mem_buf, int reg)
+static int gdb_write_register(CPUState *cpu, uint8_t *mem_buf, int reg)
{
+ CPUArchState *env = cpu->env_ptr;
GDBRegisterState *r;
if (reg < NUM_CORE_REGS)
return cpu_gdb_write_register(env, mem_buf, reg);
- for (r = env->gdb_regs; r; r = r->next) {
+ for (r = cpu->gdb_regs; r; r = r->next) {
if (r->base_reg <= reg && reg < r->base_reg + r->num_regs) {
return r->set_reg(env, mem_buf, reg - r->base_reg);
}
gdb reading a CPU register, and set_reg is gdb modifying a CPU register.
*/
-void gdb_register_coprocessor(CPUArchState * env,
- gdb_reg_cb get_reg, gdb_reg_cb set_reg,
- int num_regs, const char *xml, int g_pos)
+void gdb_register_coprocessor(CPUState *cpu,
+ gdb_reg_cb get_reg, gdb_reg_cb set_reg,
+ int num_regs, const char *xml, int g_pos)
{
GDBRegisterState *s;
GDBRegisterState **p;
static int last_reg = NUM_CORE_REGS;
- p = &env->gdb_regs;
+ p = &cpu->gdb_regs;
while (*p) {
/* Check for duplicates. */
if (strcmp((*p)->xml, xml) == 0)
static int gdb_breakpoint_insert(target_ulong addr, target_ulong len, int type)
{
+ CPUState *cpu;
CPUArchState *env;
int err = 0;
- if (kvm_enabled())
+ if (kvm_enabled()) {
return kvm_insert_breakpoint(gdbserver_state->c_cpu, addr, len, type);
+ }
switch (type) {
case GDB_BREAKPOINT_SW:
case GDB_BREAKPOINT_HW:
- for (env = first_cpu; env != NULL; env = env->next_cpu) {
+ for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
+ env = cpu->env_ptr;
err = cpu_breakpoint_insert(env, addr, BP_GDB, NULL);
if (err)
break;
case GDB_WATCHPOINT_WRITE:
case GDB_WATCHPOINT_READ:
case GDB_WATCHPOINT_ACCESS:
- for (env = first_cpu; env != NULL; env = env->next_cpu) {
+ for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
+ env = cpu->env_ptr;
err = cpu_watchpoint_insert(env, addr, len, xlat_gdb_type[type],
NULL);
if (err)
static int gdb_breakpoint_remove(target_ulong addr, target_ulong len, int type)
{
+ CPUState *cpu;
CPUArchState *env;
int err = 0;
- if (kvm_enabled())
+ if (kvm_enabled()) {
return kvm_remove_breakpoint(gdbserver_state->c_cpu, addr, len, type);
+ }
switch (type) {
case GDB_BREAKPOINT_SW:
case GDB_BREAKPOINT_HW:
- for (env = first_cpu; env != NULL; env = env->next_cpu) {
+ for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
+ env = cpu->env_ptr;
err = cpu_breakpoint_remove(env, addr, BP_GDB);
if (err)
break;
case GDB_WATCHPOINT_WRITE:
case GDB_WATCHPOINT_READ:
case GDB_WATCHPOINT_ACCESS:
- for (env = first_cpu; env != NULL; env = env->next_cpu) {
+ for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
+ env = cpu->env_ptr;
err = cpu_watchpoint_remove(env, addr, len, xlat_gdb_type[type]);
if (err)
break;
static void gdb_breakpoint_remove_all(void)
{
+ CPUState *cpu;
CPUArchState *env;
if (kvm_enabled()) {
return;
}
- for (env = first_cpu; env != NULL; env = env->next_cpu) {
+ for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
+ env = cpu->env_ptr;
cpu_breakpoint_remove_all(env, BP_GDB);
#ifndef CONFIG_USER_ONLY
cpu_watchpoint_remove_all(env, BP_GDB);
static void gdb_set_cpu_pc(GDBState *s, target_ulong pc)
{
- cpu_synchronize_state(s->c_cpu);
-#if defined(TARGET_I386)
- s->c_cpu->eip = pc;
-#elif defined (TARGET_PPC)
- s->c_cpu->nip = pc;
-#elif defined (TARGET_SPARC)
- s->c_cpu->pc = pc;
- s->c_cpu->npc = pc + 4;
-#elif defined (TARGET_ARM)
- s->c_cpu->regs[15] = pc;
-#elif defined (TARGET_SH4)
- s->c_cpu->pc = pc;
-#elif defined (TARGET_MIPS)
- 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);
+ CPUState *cpu = s->c_cpu;
+ CPUClass *cc = CPU_GET_CLASS(cpu);
+
+ cpu_synchronize_state(cpu);
+ if (cc->set_pc) {
+ cc->set_pc(cpu, 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)
- s->c_cpu->psw.addr = pc;
-#elif defined (TARGET_LM32)
- s->c_cpu->pc = pc;
-#elif defined(TARGET_XTENSA)
- s->c_cpu->pc = pc;
-#endif
}
-static CPUArchState *find_cpu(uint32_t thread_id)
+static CPUState *find_cpu(uint32_t thread_id)
{
- CPUArchState *env;
+ CPUState *cpu;
- for (env = first_cpu; env != NULL; env = env->next_cpu) {
- if (cpu_index(env) == thread_id) {
- return env;
+ for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
+ if (cpu_index(cpu) == thread_id) {
+ return cpu;
}
}
static int gdb_handle_packet(GDBState *s, const char *line_buf)
{
+#ifdef TARGET_XTENSA
CPUArchState *env;
+#endif
+ CPUState *cpu;
const char *p;
uint32_t thread;
int ch, reg_size, type, res;
}
if (res) {
if (res_thread != -1 && res_thread != 0) {
- env = find_cpu(res_thread);
- if (env == NULL) {
+ cpu = find_cpu(res_thread);
+ if (cpu == NULL) {
put_packet(s, "E22");
break;
}
- s->c_cpu = env;
+ s->c_cpu = cpu;
}
if (res == 's') {
cpu_single_step(s->c_cpu, sstep_flags);
break;
case 'g':
cpu_synchronize_state(s->g_cpu);
- env = s->g_cpu;
+#ifdef TARGET_XTENSA
+ env = s->g_cpu->env_ptr;
+#endif
len = 0;
for (addr = 0; addr < num_g_regs; addr++) {
reg_size = gdb_read_register(s->g_cpu, mem_buf + len, addr);
break;
case 'G':
cpu_synchronize_state(s->g_cpu);
- env = s->g_cpu;
+#ifdef TARGET_XTENSA
+ env = s->g_cpu->env_ptr;
+#endif
registers = mem_buf;
len = strlen(p) / 2;
hextomem((uint8_t *)registers, p, len);
if (*p == ',')
p++;
len = strtoull(p, NULL, 16);
- if (target_memory_rw_debug(s->g_cpu, addr, mem_buf, len, 0) != 0) {
+ if (target_memory_rw_debug(s->g_cpu, addr, mem_buf, len, false) != 0) {
put_packet (s, "E14");
} else {
memtohex(buf, mem_buf, len);
if (*p == ':')
p++;
hextomem(mem_buf, p, len);
- if (target_memory_rw_debug(s->g_cpu, addr, mem_buf, len, 1) != 0) {
+ if (target_memory_rw_debug(s->g_cpu, addr, mem_buf, len,
+ true) != 0) {
put_packet(s, "E14");
} else {
put_packet(s, "OK");
put_packet(s, "OK");
break;
}
- env = find_cpu(thread);
- if (env == NULL) {
+ cpu = find_cpu(thread);
+ if (cpu == NULL) {
put_packet(s, "E22");
break;
}
switch (type) {
case 'c':
- s->c_cpu = env;
+ s->c_cpu = cpu;
put_packet(s, "OK");
break;
case 'g':
- s->g_cpu = env;
+ s->g_cpu = cpu;
put_packet(s, "OK");
break;
default:
break;
case 'T':
thread = strtoull(p, (char **)&p, 16);
- env = find_cpu(thread);
+ cpu = find_cpu(thread);
- if (env != NULL) {
+ if (cpu != NULL) {
put_packet(s, "OK");
} else {
put_packet(s, "E22");
break;
} else if (strncmp(p,"ThreadExtraInfo,", 16) == 0) {
thread = strtoull(p+16, (char **)&p, 16);
- env = find_cpu(thread);
- if (env != NULL) {
- CPUState *cpu = ENV_GET_CPU(env);
- cpu_synchronize_state(env);
+ cpu = find_cpu(thread);
+ if (cpu != NULL) {
+ cpu_synchronize_state(cpu);
len = snprintf((char *)mem_buf, sizeof(mem_buf),
"CPU#%d [%s]", cpu->cpu_index,
- env->halted ? "halted " : "running");
+ cpu->halted ? "halted " : "running");
memtohex(buf, mem_buf, len);
put_packet(s, buf);
}
}
#ifdef CONFIG_USER_ONLY
else if (strncmp(p, "Offsets", 7) == 0) {
- TaskState *ts = s->c_cpu->opaque;
+ CPUArchState *env = s->c_cpu->env_ptr;
+ TaskState *ts = env->opaque;
snprintf(buf, sizeof(buf),
"Text=" TARGET_ABI_FMT_lx ";Data=" TARGET_ABI_FMT_lx
return RS_IDLE;
}
-void gdb_set_stop_cpu(CPUArchState *env)
+void gdb_set_stop_cpu(CPUState *cpu)
{
- gdbserver_state->c_cpu = env;
- gdbserver_state->g_cpu = env;
+ gdbserver_state->c_cpu = cpu;
+ gdbserver_state->g_cpu = cpu;
}
#ifndef CONFIG_USER_ONLY
static void gdb_vm_state_change(void *opaque, int running, RunState state)
{
GDBState *s = gdbserver_state;
- CPUArchState *env = s->c_cpu;
+ CPUArchState *env = s->c_cpu->env_ptr;
+ CPUState *cpu = s->c_cpu;
char buf[256];
const char *type;
int ret;
}
snprintf(buf, sizeof(buf),
"T%02xthread:%02x;%swatch:" TARGET_FMT_lx ";",
- GDB_SIGNAL_TRAP, cpu_index(env), type,
+ GDB_SIGNAL_TRAP, cpu_index(cpu), type,
env->watchpoint_hit->vaddr);
env->watchpoint_hit = NULL;
goto send_packet;
ret = GDB_SIGNAL_UNKNOWN;
break;
}
- snprintf(buf, sizeof(buf), "T%02xthread:%02x;", ret, cpu_index(env));
+ snprintf(buf, sizeof(buf), "T%02xthread:%02x;", ret, cpu_index(cpu));
send_packet:
put_packet(s, buf);
/* disable single step if it was enabled */
- cpu_single_step(env, 0);
+ cpu_single_step(cpu, 0);
}
#endif
}
int
-gdb_handlesig (CPUArchState *env, int sig)
+gdb_handlesig(CPUState *cpu, int sig)
{
- GDBState *s;
- char buf[256];
- int n;
+ CPUArchState *env = cpu->env_ptr;
+ GDBState *s;
+ char buf[256];
+ int n;
- s = gdbserver_state;
- if (gdbserver_fd < 0 || s->fd < 0)
- return sig;
+ s = gdbserver_state;
+ if (gdbserver_fd < 0 || s->fd < 0) {
+ return sig;
+ }
+
+ /* disable single step if it was enabled */
+ cpu_single_step(cpu, 0);
+ tb_flush(env);
- /* disable single step if it was enabled */
- cpu_single_step(env, 0);
- tb_flush(env);
+ if (sig != 0) {
+ snprintf(buf, sizeof(buf), "S%02x", target_signal_to_gdb(sig));
+ put_packet(s, buf);
+ }
+ /* put_packet() might have detected that the peer terminated the
+ connection. */
+ if (s->fd < 0) {
+ return sig;
+ }
- if (sig != 0)
- {
- snprintf(buf, sizeof(buf), "S%02x", target_signal_to_gdb (sig));
- put_packet(s, buf);
- }
- /* put_packet() might have detected that the peer terminated the
- connection. */
- if (s->fd < 0)
- return sig;
-
- sig = 0;
- s->state = RS_IDLE;
- s->running_state = 0;
- while (s->running_state == 0) {
- n = read (s->fd, buf, 256);
- if (n > 0)
- {
- int i;
+ sig = 0;
+ s->state = RS_IDLE;
+ s->running_state = 0;
+ while (s->running_state == 0) {
+ n = read(s->fd, buf, 256);
+ if (n > 0) {
+ int i;
- for (i = 0; i < n; i++)
- gdb_read_byte (s, buf[i]);
- }
- else if (n == 0 || errno != EAGAIN)
- {
- /* XXX: Connection closed. Should probably wait for another
- connection before continuing. */
- return sig;
+ for (i = 0; i < n; i++) {
+ gdb_read_byte(s, buf[i]);
+ }
+ } else if (n == 0 || errno != EAGAIN) {
+ /* XXX: Connection closed. Should probably wait for another
+ connection before continuing. */
+ return sig;
}
- }
- sig = s->signal;
- s->signal = 0;
- return sig;
+ }
+ sig = s->signal;
+ s->signal = 0;
+ return sig;
}
/* Tell the remote gdb that the process has exited due to SIG. */
void gdb_signalled(CPUArchState *env, int sig)
{
- GDBState *s;
- char buf[4];
+ GDBState *s;
+ char buf[4];
- s = gdbserver_state;
- if (gdbserver_fd < 0 || s->fd < 0)
- return;
+ s = gdbserver_state;
+ if (gdbserver_fd < 0 || s->fd < 0) {
+ return;
+ }
- snprintf(buf, sizeof(buf), "X%02x", target_signal_to_gdb (sig));
- put_packet(s, buf);
+ snprintf(buf, sizeof(buf), "X%02x", target_signal_to_gdb(sig));
+ put_packet(s, buf);
}
static void gdb_accept(void)
GDBState *s;
struct sockaddr_in sockaddr;
socklen_t len;
- int val, fd;
+ int fd;
for(;;) {
len = sizeof(sockaddr);
}
/* 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;
/* 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);
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);
}