X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=gdbstub.c;h=61c12b168e7e4cb3845e70055ececf963caa6550;hb=78e24f235eda4d3313917a50e135b7e06a046407;hp=75563db79df7f7763bdc8219b0f4c225685d1b8f;hpb=ce0274f730eacbd24c706523ddbbabb6b95d0659;p=mirror_qemu.git
diff --git a/gdbstub.c b/gdbstub.c
index 75563db79d..61c12b168e 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -16,16 +16,9 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see .
*/
-#include "config.h"
+#include "qemu/osdep.h"
#include "qemu-common.h"
#ifdef CONFIG_USER_ONLY
-#include
-#include
-#include
-#include
-#include
-#include
-#include
#include "qemu.h"
#else
@@ -40,6 +33,7 @@
#include "cpu.h"
#include "qemu/sockets.h"
#include "sysemu/kvm.h"
+#include "exec/semihost.h"
#ifdef CONFIG_USER_ONLY
#define GDB_ATTACHED "0"
@@ -323,8 +317,6 @@ static GDBState *gdbserver_state;
bool gdb_has_xml;
-int semihosting_target = SEMIHOSTING_TARGET_AUTO;
-
#ifdef CONFIG_USER_ONLY
/* XXX: This is not thread safe. Do we care? */
static int gdbserver_fd = -1;
@@ -362,10 +354,11 @@ static enum {
/* Decide if either remote gdb syscalls or native file IO should be used. */
int use_gdb_syscalls(void)
{
- if (semihosting_target == SEMIHOSTING_TARGET_NATIVE) {
+ SemihostingTarget target = semihosting_get_target();
+ if (target == SEMIHOSTING_TARGET_NATIVE) {
/* -semihosting-config target=native */
return false;
- } else if (semihosting_target == SEMIHOSTING_TARGET_GDB) {
+ } else if (target == SEMIHOSTING_TARGET_GDB) {
/* -semihosting-config target=gdb */
return true;
}
@@ -540,13 +533,20 @@ static const char *get_feature_xml(const char *p, const char **newp,
GDBRegisterState *r;
CPUState *cpu = first_cpu;
- snprintf(target_xml, sizeof(target_xml),
- ""
- ""
- ""
- "",
- cc->gdb_core_xml_file);
-
+ pstrcat(target_xml, sizeof(target_xml),
+ ""
+ ""
+ "");
+ if (cc->gdb_arch_name) {
+ gchar *arch = cc->gdb_arch_name(cpu);
+ pstrcat(target_xml, sizeof(target_xml), "");
+ pstrcat(target_xml, sizeof(target_xml), arch);
+ pstrcat(target_xml, sizeof(target_xml), "");
+ g_free(arch);
+ }
+ pstrcat(target_xml, sizeof(target_xml), "gdb_core_xml_file);
+ pstrcat(target_xml, sizeof(target_xml), "\"/>");
for (r = cpu->gdb_regs; r; r = r->next) {
pstrcat(target_xml, sizeof(target_xml), "xml);
@@ -754,12 +754,9 @@ static void gdb_breakpoint_remove_all(void)
static void gdb_set_cpu_pc(GDBState *s, target_ulong pc)
{
CPUState *cpu = s->c_cpu;
- CPUClass *cc = CPU_GET_CLASS(cpu);
cpu_synchronize_state(cpu);
- if (cc->set_pc) {
- cc->set_pc(cpu, pc);
- }
+ cpu_set_pc(cpu, pc);
}
static CPUState *find_cpu(uint32_t thread_id)
@@ -959,6 +956,13 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
if (*p == ',')
p++;
len = strtoull(p, NULL, 16);
+
+ /* memtohex() doubles the required space */
+ if (len > MAX_PACKET_LENGTH / 2) {
+ put_packet (s, "E22");
+ break;
+ }
+
if (target_memory_rw_debug(s->g_cpu, addr, mem_buf, len, false) != 0) {
put_packet (s, "E14");
} else {
@@ -973,6 +977,12 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
len = strtoull(p, (char **)&p, 16);
if (*p == ':')
p++;
+
+ /* hextomem() reads 2*len bytes */
+ if (len > strlen(p) / 2) {
+ put_packet (s, "E22");
+ break;
+ }
hextomem(mem_buf, p, len);
if (target_memory_rw_debug(s->g_cpu, addr, mem_buf, len,
true) != 0) {
@@ -1110,7 +1120,8 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
cpu = find_cpu(thread);
if (cpu != NULL) {
cpu_synchronize_state(cpu);
- len = snprintf((char *)mem_buf, sizeof(mem_buf),
+ /* memtohex() doubles the required space */
+ len = snprintf((char *)mem_buf, sizeof(buf) / 2,
"CPU#%d [%s]", cpu->cpu_index,
cpu->halted ? "halted " : "running");
memtohex(buf, mem_buf, len);
@@ -1139,8 +1150,8 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
put_packet(s, "E01");
break;
}
- hextomem(mem_buf, p + 5, len);
len = len / 2;
+ hextomem(mem_buf, p + 5, len);
mem_buf[len++] = 0;
qemu_chr_be_write(s->mon_chr, mem_buf, len);
put_packet(s, "OK");
@@ -1226,7 +1237,6 @@ void gdb_set_stop_cpu(CPUState *cpu)
static void gdb_vm_state_change(void *opaque, int running, RunState state)
{
GDBState *s = gdbserver_state;
- CPUArchState *env = s->c_cpu->env_ptr;
CPUState *cpu = s->c_cpu;
char buf[256];
const char *type;
@@ -1261,7 +1271,7 @@ static void gdb_vm_state_change(void *opaque, int running, RunState state)
cpu->watchpoint_hit = NULL;
goto send_packet;
}
- tb_flush(env);
+ tb_flush(cpu);
ret = GDB_SIGNAL_TRAP;
break;
case RUN_STATE_PAUSED:
@@ -1289,6 +1299,7 @@ static void gdb_vm_state_change(void *opaque, int running, RunState state)
ret = GDB_SIGNAL_UNKNOWN;
break;
}
+ gdb_set_stop_cpu(cpu);
snprintf(buf, sizeof(buf), "T%02xthread:%02x;", ret, cpu_index(cpu));
send_packet:
@@ -1304,9 +1315,8 @@ send_packet:
%x - target_ulong argument printed in hex.
%lx - 64-bit argument printed in hex.
%s - string pointer (target_ulong) and length (int) pair. */
-void gdb_do_syscall(gdb_syscall_complete_cb cb, const char *fmt, ...)
+void gdb_do_syscallv(gdb_syscall_complete_cb cb, const char *fmt, va_list va)
{
- va_list va;
char *p;
char *p_end;
target_ulong addr;
@@ -1320,7 +1330,6 @@ void gdb_do_syscall(gdb_syscall_complete_cb cb, const char *fmt, ...)
#ifndef CONFIG_USER_ONLY
vm_stop(RUN_STATE_DEBUG);
#endif
- va_start(va, fmt);
p = s->syscall_buf;
p_end = &s->syscall_buf[sizeof(s->syscall_buf)];
*(p++) = 'F';
@@ -1354,7 +1363,6 @@ void gdb_do_syscall(gdb_syscall_complete_cb cb, const char *fmt, ...)
}
}
*p = 0;
- va_end(va);
#ifdef CONFIG_USER_ONLY
put_packet(s, s->syscall_buf);
gdb_handlesig(s->c_cpu, 0);
@@ -1365,10 +1373,19 @@ void gdb_do_syscall(gdb_syscall_complete_cb cb, const char *fmt, ...)
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);
+ qemu_cpu_kick(s->c_cpu);
#endif
}
+void gdb_do_syscall(gdb_syscall_complete_cb cb, const char *fmt, ...)
+{
+ va_list va;
+
+ va_start(va, fmt);
+ gdb_do_syscallv(cb, fmt, va);
+ va_end(va);
+}
+
static void gdb_read_byte(GDBState *s, int ch)
{
int i, csum;
@@ -1490,7 +1507,6 @@ gdb_queuesig (void)
int
gdb_handlesig(CPUState *cpu, int sig)
{
- CPUArchState *env = cpu->env_ptr;
GDBState *s;
char buf[256];
int n;
@@ -1502,7 +1518,7 @@ gdb_handlesig(CPUState *cpu, int sig)
/* disable single step if it was enabled */
cpu_single_step(cpu, 0);
- tb_flush(env);
+ tb_flush(cpu);
if (sig != 0) {
snprintf(buf, sizeof(buf), "S%02x", target_signal_to_gdb(sig));
@@ -1631,9 +1647,8 @@ int gdbserver_start(int port)
}
/* Disable gdb stub for child processes. */
-void gdbserver_fork(CPUArchState *env)
+void gdbserver_fork(CPUState *cpu)
{
- CPUState *cpu = ENV_GET_CPU(env);
GDBState *s = gdbserver_state;
if (gdbserver_fd < 0 || s->fd < 0) {
@@ -1717,6 +1732,7 @@ int gdbserver_start(const char *device)
char gdbstub_device_name[128];
CharDriverState *chr = NULL;
CharDriverState *mon_chr;
+ ChardevCommon common = { 0 };
if (!device)
return -1;
@@ -1753,7 +1769,7 @@ int gdbserver_start(const char *device)
qemu_add_vm_change_state_handler(gdb_vm_state_change, NULL);
/* Initialize a monitor terminal for gdb */
- mon_chr = qemu_chr_alloc();
+ mon_chr = qemu_chr_alloc(&common, &error_abort);
mon_chr->chr_write = gdb_monitor_write;
monitor_init(mon_chr, 0);
} else {