aboutsummaryrefslogtreecommitdiff
path: root/gdbstub
diff options
context:
space:
mode:
Diffstat (limited to 'gdbstub')
-rw-r--r--gdbstub/gdbstub.c72
-rw-r--r--gdbstub/meson.build38
-rw-r--r--gdbstub/syscalls.c4
-rw-r--r--gdbstub/system.c45
-rw-r--r--gdbstub/user-target.c18
-rw-r--r--gdbstub/user.c173
6 files changed, 218 insertions, 132 deletions
diff --git a/gdbstub/gdbstub.c b/gdbstub/gdbstub.c
index d08568c..dd5fb56 100644
--- a/gdbstub/gdbstub.c
+++ b/gdbstub/gdbstub.c
@@ -20,7 +20,7 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*
- * SPDX-License-Identifier: LGPL-2.0+
+ * SPDX-License-Identifier: LGPL-2.0-or-later
*/
#include "qemu/osdep.h"
@@ -28,6 +28,7 @@
#include "qemu/cutils.h"
#include "qemu/module.h"
#include "qemu/error-report.h"
+#include "qemu/target-info.h"
#include "trace.h"
#include "exec/gdbstub.h"
#include "gdbstub/commands.h"
@@ -41,8 +42,8 @@
#endif
#include "hw/core/cpu.h"
-#include "sysemu/hw_accel.h"
-#include "sysemu/runstate.h"
+#include "system/hw_accel.h"
+#include "system/runstate.h"
#include "exec/replay-core.h"
#include "exec/hwaddr.h"
@@ -354,7 +355,6 @@ static const char *get_feature_xml(const char *p, const char **newp,
GDBProcess *process)
{
CPUState *cpu = gdb_get_first_cpu_in_process(process);
- CPUClass *cc = CPU_GET_CLASS(cpu);
GDBRegisterState *r;
size_t len;
@@ -377,11 +377,11 @@ static const char *get_feature_xml(const char *p, const char **newp,
"<!DOCTYPE target SYSTEM \"gdb-target.dtd\">"
"<target>"));
- if (cc->gdb_arch_name) {
+ if (cpu->cc->gdb_arch_name) {
g_ptr_array_add(
xml,
g_markup_printf_escaped("<architecture>%s</architecture>",
- cc->gdb_arch_name(cpu)));
+ cpu->cc->gdb_arch_name(cpu)));
}
for (guint i = 0; i < cpu->gdb_regs->len; i++) {
r = &g_array_index(cpu->gdb_regs, GDBRegisterState, i);
@@ -520,11 +520,10 @@ GArray *gdb_get_register_list(CPUState *cpu)
int gdb_read_register(CPUState *cpu, GByteArray *buf, int reg)
{
- CPUClass *cc = CPU_GET_CLASS(cpu);
GDBRegisterState *r;
- if (reg < cc->gdb_num_core_regs) {
- return cc->gdb_read_register(cpu, buf, reg);
+ if (reg < cpu->cc->gdb_num_core_regs) {
+ return cpu->cc->gdb_read_register(cpu, buf, reg);
}
for (guint i = 0; i < cpu->gdb_regs->len; i++) {
@@ -536,13 +535,12 @@ int gdb_read_register(CPUState *cpu, GByteArray *buf, int reg)
return 0;
}
-static int gdb_write_register(CPUState *cpu, uint8_t *mem_buf, int reg)
+int gdb_write_register(CPUState *cpu, uint8_t *mem_buf, int reg)
{
- CPUClass *cc = CPU_GET_CLASS(cpu);
GDBRegisterState *r;
- if (reg < cc->gdb_num_core_regs) {
- return cc->gdb_write_register(cpu, mem_buf, reg);
+ if (reg < cpu->cc->gdb_num_core_regs) {
+ return cpu->cc->gdb_write_register(cpu, mem_buf, reg);
}
for (guint i = 0; i < cpu->gdb_regs->len; i++) {
@@ -568,15 +566,30 @@ static void gdb_register_feature(CPUState *cpu, int base_reg,
g_array_append_val(cpu->gdb_regs, s);
}
+static const char *gdb_get_core_xml_file(CPUState *cpu)
+{
+ CPUClass *cc = cpu->cc;
+
+ /*
+ * The CPU class can provide the XML filename via a method,
+ * or as a simple fixed string field.
+ */
+ if (cc->gdb_get_core_xml_file) {
+ return cc->gdb_get_core_xml_file(cpu);
+ }
+ return cc->gdb_core_xml_file;
+}
+
void gdb_init_cpu(CPUState *cpu)
{
- CPUClass *cc = CPU_GET_CLASS(cpu);
+ CPUClass *cc = cpu->cc;
const GDBFeature *feature;
+ const char *xmlfile = gdb_get_core_xml_file(cpu);
cpu->gdb_regs = g_array_new(false, false, sizeof(GDBRegisterState));
- if (cc->gdb_core_xml_file) {
- feature = gdb_find_static_feature(cc->gdb_core_xml_file);
+ if (xmlfile) {
+ feature = gdb_find_static_feature(xmlfile);
gdb_register_feature(cpu, 0,
cc->gdb_read_register, cc->gdb_write_register,
feature);
@@ -1331,8 +1344,8 @@ static void handle_read_all_regs(GArray *params, void *user_ctx)
len += gdb_read_register(gdbserver_state.g_cpu,
gdbserver_state.mem_buf,
reg_id);
+ g_assert(len == gdbserver_state.mem_buf->len);
}
- g_assert(len == gdbserver_state.mem_buf->len);
gdb_memtohex(gdbserver_state.str_buf, gdbserver_state.mem_buf->data, len);
gdb_put_strbuf();
@@ -1585,6 +1598,18 @@ static void handle_query_threads(GArray *params, void *user_ctx)
gdbserver_state.query_cpu = gdb_next_attached_cpu(gdbserver_state.query_cpu);
}
+static void handle_query_gdb_server_version(GArray *params, void *user_ctx)
+{
+#if defined(CONFIG_USER_ONLY)
+ g_string_printf(gdbserver_state.str_buf, "name:qemu-%s;version:%s;",
+ target_name(), QEMU_VERSION);
+#else
+ g_string_printf(gdbserver_state.str_buf, "name:qemu-system-%s;version:%s;",
+ target_name(), QEMU_VERSION);
+#endif
+ gdb_put_strbuf();
+}
+
static void handle_query_first_threads(GArray *params, void *user_ctx)
{
gdbserver_state.query_cpu = gdb_first_attached_cpu();
@@ -1646,11 +1671,8 @@ void gdb_extend_qsupported_features(char *qflags)
static void handle_query_supported(GArray *params, void *user_ctx)
{
- CPUClass *cc;
-
g_string_printf(gdbserver_state.str_buf, "PacketSize=%x", MAX_PACKET_LENGTH);
- cc = CPU_GET_CLASS(first_cpu);
- if (cc->gdb_core_xml_file) {
+ if (gdb_get_core_xml_file(first_cpu)) {
g_string_append(gdbserver_state.str_buf, ";qXfer:features:read+");
}
@@ -1697,7 +1719,6 @@ static void handle_query_supported(GArray *params, void *user_ctx)
static void handle_query_xfer_features(GArray *params, void *user_ctx)
{
GDBProcess *process;
- CPUClass *cc;
unsigned long len, total_len, addr;
const char *xml;
const char *p;
@@ -1708,8 +1729,7 @@ static void handle_query_xfer_features(GArray *params, void *user_ctx)
}
process = gdb_get_cpu_process(gdbserver_state.g_cpu);
- cc = CPU_GET_CLASS(gdbserver_state.g_cpu);
- if (!cc->gdb_core_xml_file) {
+ if (!gdb_get_core_xml_file(gdbserver_state.g_cpu)) {
gdb_put_packet("");
return;
}
@@ -1836,6 +1856,10 @@ static const GdbCmdParseEntry gdb_gen_query_table[] = {
.cmd = "sThreadInfo",
},
{
+ .handler = handle_query_gdb_server_version,
+ .cmd = "GDBServerVersion",
+ },
+ {
.handler = handle_query_first_threads,
.cmd = "fThreadInfo",
},
diff --git a/gdbstub/meson.build b/gdbstub/meson.build
index dff741d..15c666f 100644
--- a/gdbstub/meson.build
+++ b/gdbstub/meson.build
@@ -4,34 +4,18 @@
# types such as hwaddr.
#
-# We need to build the core gdb code via a library to be able to tweak
-# cflags so:
-
-gdb_user_ss = ss.source_set()
-gdb_system_ss = ss.source_set()
-
# We build two versions of gdbstub, one for each mode
-gdb_user_ss.add(files('gdbstub.c', 'user.c'))
-gdb_system_ss.add(files('gdbstub.c', 'system.c'))
-
-gdb_user_ss = gdb_user_ss.apply({})
-gdb_system_ss = gdb_system_ss.apply({})
-
-libgdb_user = static_library('gdb_user',
- gdb_user_ss.sources() + genh,
- c_args: '-DCONFIG_USER_ONLY',
- build_by_default: false)
-
-libgdb_system = static_library('gdb_system',
- gdb_system_ss.sources() + genh,
- build_by_default: false)
-
-gdb_user = declare_dependency(objects: libgdb_user.extract_all_objects(recursive: false))
-user_ss.add(gdb_user)
-gdb_system = declare_dependency(objects: libgdb_system.extract_all_objects(recursive: false))
-system_ss.add(gdb_system)
-
-common_ss.add(files('syscalls.c'))
+user_ss.add(files(
+ 'gdbstub.c',
+ 'syscalls.c',
+ 'user.c'
+))
+
+system_ss.add(files(
+ 'gdbstub.c',
+ 'syscalls.c',
+ 'system.c'
+))
# The user-target is specialised by the guest
specific_ss.add(when: 'CONFIG_USER_ONLY', if_true: files('user-target.c'))
diff --git a/gdbstub/syscalls.c b/gdbstub/syscalls.c
index 4e1295b..e855df2 100644
--- a/gdbstub/syscalls.c
+++ b/gdbstub/syscalls.c
@@ -7,13 +7,13 @@
* Copyright (c) 2003-2005 Fabrice Bellard
* Copyright (c) 2023 Linaro Ltd
*
- * SPDX-License-Identifier: LGPL-2.0+
+ * SPDX-License-Identifier: LGPL-2.0-or-later
*/
#include "qemu/osdep.h"
#include "qemu/error-report.h"
#include "semihosting/semihost.h"
-#include "sysemu/runstate.h"
+#include "system/runstate.h"
#include "gdbstub/user.h"
#include "gdbstub/syscalls.h"
#include "gdbstub/commands.h"
diff --git a/gdbstub/system.c b/gdbstub/system.c
index 1ad87fe..8a32d8e 100644
--- a/gdbstub/system.c
+++ b/gdbstub/system.c
@@ -7,7 +7,7 @@
* Copyright (c) 2003-2005 Fabrice Bellard
* Copyright (c) 2022 Linaro Ltd
*
- * SPDX-License-Identifier: LGPL-2.0+
+ * SPDX-License-Identifier: LGPL-2.0-or-later
*/
#include "qemu/osdep.h"
@@ -19,9 +19,11 @@
#include "gdbstub/commands.h"
#include "exec/hwaddr.h"
#include "exec/tb-flush.h"
-#include "sysemu/cpus.h"
-#include "sysemu/runstate.h"
-#include "sysemu/replay.h"
+#include "system/accel-ops.h"
+#include "system/cpus.h"
+#include "system/runstate.h"
+#include "system/replay.h"
+#include "system/tcg.h"
#include "hw/core/cpu.h"
#include "hw/cpu/cluster.h"
#include "hw/boards.h"
@@ -171,7 +173,9 @@ static void gdb_vm_state_change(void *opaque, bool running, RunState state)
} else {
trace_gdbstub_hit_break();
}
- tb_flush(cpu);
+ if (tcg_enabled()) {
+ tb_flush(cpu);
+ }
ret = GDB_SIGNAL_TRAP;
break;
case RUN_STATE_PAUSED:
@@ -239,7 +243,7 @@ static void gdb_monitor_open(Chardev *chr, ChardevBackend *backend,
*be_opened = false;
}
-static void char_gdb_class_init(ObjectClass *oc, void *data)
+static void char_gdb_class_init(ObjectClass *oc, const void *data)
{
ChardevClass *cc = CHARDEV_CLASS(oc);
@@ -330,26 +334,27 @@ static void create_processes(GDBState *s)
gdb_create_default_process(s);
}
-int gdbserver_start(const char *device)
+bool gdbserver_start(const char *device, Error **errp)
{
Chardev *chr = NULL;
Chardev *mon_chr;
g_autoptr(GString) cs = g_string_new(device);
if (!first_cpu) {
- error_report("gdbstub: meaningless to attach gdb to a "
- "machine without any CPU.");
- return -1;
+ error_setg(errp, "gdbstub: meaningless to attach gdb to a "
+ "machine without any CPU.");
+ return false;
}
if (!gdb_supports_guest_debug()) {
- error_report("gdbstub: current accelerator doesn't "
- "support guest debugging");
- return -1;
+ error_setg(errp, "gdbstub: current accelerator doesn't "
+ "support guest debugging");
+ return false;
}
if (cs->len == 0) {
- return -1;
+ error_setg(errp, "gdbstub: missing connection string");
+ return false;
}
trace_gdbstub_op_start(cs->str);
@@ -374,7 +379,8 @@ int gdbserver_start(const char *device)
*/
chr = qemu_chr_new_noreplay("gdb", cs->str, true, NULL);
if (!chr) {
- return -1;
+ error_setg(errp, "gdbstub: couldn't create chardev");
+ return false;
}
}
@@ -406,7 +412,7 @@ int gdbserver_start(const char *device)
gdbserver_system_state.mon_chr = mon_chr;
gdb_syscall_reset();
- return 0;
+ return true;
}
static void register_types(void)
@@ -450,8 +456,6 @@ static int phy_memory_mode;
int gdb_target_memory_rw_debug(CPUState *cpu, hwaddr addr,
uint8_t *buf, int len, bool is_write)
{
- CPUClass *cc;
-
if (phy_memory_mode) {
if (is_write) {
cpu_physical_memory_write(addr, buf, len);
@@ -461,9 +465,8 @@ int gdb_target_memory_rw_debug(CPUState *cpu, hwaddr addr,
return 0;
}
- cc = CPU_GET_CLASS(cpu);
- if (cc->memory_rw_debug) {
- return cc->memory_rw_debug(cpu, addr, buf, len, is_write);
+ if (cpu->cc->memory_rw_debug) {
+ return cpu->cc->memory_rw_debug(cpu, addr, buf, len, is_write);
}
return cpu_memory_rw_debug(cpu, addr, buf, len, is_write);
diff --git a/gdbstub/user-target.c b/gdbstub/user-target.c
index b5e01fd..43231e6 100644
--- a/gdbstub/user-target.c
+++ b/gdbstub/user-target.c
@@ -4,7 +4,7 @@
* Copyright (c) 2003-2005 Fabrice Bellard
* Copyright (c) 2022 Linaro Ltd
*
- * SPDX-License-Identifier: LGPL-2.0+
+ * SPDX-License-Identifier: LGPL-2.0-or-later
*/
#include "qemu/osdep.h"
@@ -233,10 +233,8 @@ void gdb_handle_query_offsets(GArray *params, void *user_ctx)
static inline int target_memory_rw_debug(CPUState *cpu, target_ulong addr,
uint8_t *buf, int len, bool is_write)
{
- CPUClass *cc;
- cc = CPU_GET_CLASS(cpu);
- if (cc->memory_rw_debug) {
- return cc->memory_rw_debug(cpu, addr, buf, len, is_write);
+ if (cpu->cc->memory_rw_debug) {
+ return cpu->cc->memory_rw_debug(cpu, addr, buf, len, is_write);
}
return cpu_memory_rw_debug(cpu, addr, buf, len, is_write);
}
@@ -317,9 +315,9 @@ void gdb_handle_v_file_open(GArray *params, void *user_ctx)
int fd = open(filename, flags, mode);
#endif
if (fd < 0) {
- g_string_printf(gdbserver_state.str_buf, "F-1,%d", errno);
+ g_string_printf(gdbserver_state.str_buf, "F-1,%x", errno);
} else {
- g_string_printf(gdbserver_state.str_buf, "F%d", fd);
+ g_string_printf(gdbserver_state.str_buf, "F%x", fd);
}
gdb_put_strbuf();
}
@@ -329,7 +327,7 @@ void gdb_handle_v_file_close(GArray *params, void *user_ctx)
int fd = gdb_get_cmd_param(params, 0)->val_ul;
if (close(fd) == -1) {
- g_string_printf(gdbserver_state.str_buf, "F-1,%d", errno);
+ g_string_printf(gdbserver_state.str_buf, "F-1,%x", errno);
gdb_put_strbuf();
return;
}
@@ -352,7 +350,7 @@ void gdb_handle_v_file_pread(GArray *params, void *user_ctx)
ssize_t n = pread(fd, buf, bufsiz, offset);
if (n < 0) {
- g_string_printf(gdbserver_state.str_buf, "F-1,%d", errno);
+ g_string_printf(gdbserver_state.str_buf, "F-1,%x", errno);
gdb_put_strbuf();
return;
}
@@ -375,7 +373,7 @@ void gdb_handle_v_file_readlink(GArray *params, void *user_ctx)
ssize_t n = readlink(filename, buf, BUFSIZ);
#endif
if (n < 0) {
- g_string_printf(gdbserver_state.str_buf, "F-1,%d", errno);
+ g_string_printf(gdbserver_state.str_buf, "F-1,%x", errno);
gdb_put_strbuf();
return;
}
diff --git a/gdbstub/user.c b/gdbstub/user.c
index b36033b..67403e5 100644
--- a/gdbstub/user.c
+++ b/gdbstub/user.c
@@ -6,13 +6,14 @@
* Copyright (c) 2003-2005 Fabrice Bellard
* Copyright (c) 2022 Linaro Ltd
*
- * SPDX-License-Identifier: LGPL-2.0+
+ * SPDX-License-Identifier: LGPL-2.0-or-later
*/
#include "qemu/osdep.h"
#include "qemu/bitops.h"
#include "qemu/cutils.h"
#include "qemu/sockets.h"
+#include "qapi/error.h"
#include "exec/hwaddr.h"
#include "exec/tb-flush.h"
#include "exec/gdbstub.h"
@@ -21,6 +22,7 @@
#include "gdbstub/user.h"
#include "gdbstub/enums.h"
#include "hw/core/cpu.h"
+#include "user/signal.h"
#include "trace.h"
#include "internals.h"
@@ -314,33 +316,20 @@ static bool gdb_accept_socket(int gdb_fd)
return true;
}
-static int gdbserver_open_socket(const char *path)
+static int gdbserver_open_socket(const char *path, Error **errp)
{
- struct sockaddr_un sockaddr = {};
- int fd, ret;
+ g_autoptr(GString) buf = g_string_new("");
+ char *pid_placeholder;
- fd = socket(AF_UNIX, SOCK_STREAM, 0);
- if (fd < 0) {
- perror("create socket");
- return -1;
+ pid_placeholder = strstr(path, "%d");
+ if (pid_placeholder != NULL) {
+ g_string_append_len(buf, path, pid_placeholder - path);
+ g_string_append_printf(buf, "%d", qemu_get_thread_id());
+ g_string_append(buf, pid_placeholder + 2);
+ path = buf->str;
}
- sockaddr.sun_family = AF_UNIX;
- pstrcpy(sockaddr.sun_path, sizeof(sockaddr.sun_path) - 1, path);
- ret = bind(fd, (struct sockaddr *)&sockaddr, sizeof(sockaddr));
- if (ret < 0) {
- perror("bind socket");
- close(fd);
- return -1;
- }
- ret = listen(fd, 1);
- if (ret < 0) {
- perror("listen socket");
- close(fd);
- return -1;
- }
-
- return fd;
+ return unix_listen(path, errp);
}
static bool gdb_accept_tcp(int gdb_fd)
@@ -372,14 +361,14 @@ static bool gdb_accept_tcp(int gdb_fd)
return true;
}
-static int gdbserver_open_port(int port)
+static int gdbserver_open_port(int port, Error **errp)
{
struct sockaddr_in sockaddr;
int fd, ret;
fd = socket(PF_INET, SOCK_STREAM, 0);
if (fd < 0) {
- perror("socket");
+ error_setg_errno(errp, errno, "Failed to create socket");
return -1;
}
qemu_set_cloexec(fd);
@@ -391,13 +380,13 @@ static int gdbserver_open_port(int port)
sockaddr.sin_addr.s_addr = 0;
ret = bind(fd, (struct sockaddr *)&sockaddr, sizeof(sockaddr));
if (ret < 0) {
- perror("bind");
+ error_setg_errno(errp, errno, "Failed to bind socket");
close(fd);
return -1;
}
ret = listen(fd, 1);
if (ret < 0) {
- perror("listen");
+ error_setg_errno(errp, errno, "Failed to listen to socket");
close(fd);
return -1;
}
@@ -405,31 +394,122 @@ static int gdbserver_open_port(int port)
return fd;
}
-int gdbserver_start(const char *port_or_path)
+static bool gdbserver_accept(int port, int gdb_fd, const char *path)
{
- int port = g_ascii_strtoull(port_or_path, NULL, 10);
- int gdb_fd;
+ bool ret;
if (port > 0) {
- gdb_fd = gdbserver_open_port(port);
+ ret = gdb_accept_tcp(gdb_fd);
} else {
- gdb_fd = gdbserver_open_socket(port_or_path);
+ ret = gdb_accept_socket(gdb_fd);
+ if (ret) {
+ gdbserver_user_state.socket_path = g_strdup(path);
+ }
}
- if (gdb_fd < 0) {
- return -1;
+ if (!ret) {
+ close(gdb_fd);
+ }
+
+ return ret;
+}
+
+struct {
+ int port;
+ int gdb_fd;
+ char *path;
+} gdbserver_args;
+
+static void do_gdb_handlesig(CPUState *cs, run_on_cpu_data arg)
+{
+ int sig;
+
+ sig = target_to_host_signal(gdb_handlesig(cs, 0, NULL, NULL, 0));
+ if (sig >= 1 && sig < NSIG) {
+ qemu_kill_thread(gdb_get_cpu_index(cs), sig);
+ }
+}
+
+static void *gdbserver_accept_thread(void *arg)
+{
+ if (gdbserver_accept(gdbserver_args.port, gdbserver_args.gdb_fd,
+ gdbserver_args.path)) {
+ CPUState *cs = first_cpu;
+
+ async_safe_run_on_cpu(cs, do_gdb_handlesig, RUN_ON_CPU_NULL);
+ qemu_kill_thread(gdb_get_cpu_index(cs), host_interrupt_signal);
+ }
+
+ g_free(gdbserver_args.path);
+ gdbserver_args.path = NULL;
+
+ return NULL;
+}
+
+#define USAGE "\nUsage: -g {port|path}[,suspend={y|n}]"
+
+bool gdbserver_start(const char *args, Error **errp)
+{
+ g_auto(GStrv) argv = g_strsplit(args, ",", 0);
+ const char *port_or_path = NULL;
+ bool suspend = true;
+ int gdb_fd, port;
+ GStrv arg;
+
+ for (arg = argv; *arg; arg++) {
+ g_auto(GStrv) tokens = g_strsplit(*arg, "=", 2);
+
+ if (g_strcmp0(tokens[0], "suspend") == 0) {
+ if (tokens[1] == NULL) {
+ error_setg(errp,
+ "gdbstub: missing \"suspend\" option value" USAGE);
+ return false;
+ } else if (!qapi_bool_parse(tokens[0], tokens[1],
+ &suspend, errp)) {
+ return false;
+ }
+ } else {
+ if (port_or_path) {
+ error_setg(errp, "gdbstub: unknown option \"%s\"" USAGE, *arg);
+ return false;
+ }
+ port_or_path = *arg;
+ }
+ }
+ if (!port_or_path) {
+ error_setg(errp, "gdbstub: port or path not specified" USAGE);
+ return false;
}
- if (port > 0 && gdb_accept_tcp(gdb_fd)) {
- return 0;
- } else if (gdb_accept_socket(gdb_fd)) {
- gdbserver_user_state.socket_path = g_strdup(port_or_path);
- return 0;
+ port = g_ascii_strtoull(port_or_path, NULL, 10);
+ if (port > 0) {
+ gdb_fd = gdbserver_open_port(port, errp);
+ } else {
+ gdb_fd = gdbserver_open_socket(port_or_path, errp);
+ }
+ if (gdb_fd < 0) {
+ return false;
}
- /* gone wrong */
- close(gdb_fd);
- return -1;
+ if (suspend) {
+ if (gdbserver_accept(port, gdb_fd, port_or_path)) {
+ gdb_handlesig(first_cpu, 0, NULL, NULL, 0);
+ return true;
+ } else {
+ error_setg(errp, "gdbstub: failed to accept connection");
+ return false;
+ }
+ } else {
+ QemuThread thread;
+
+ gdbserver_args.port = port;
+ gdbserver_args.gdb_fd = gdb_fd;
+ gdbserver_args.path = g_strdup(port_or_path);
+ qemu_thread_create(&thread, "gdb-accept",
+ &gdbserver_accept_thread, NULL,
+ QEMU_THREAD_DETACHED);
+ return true;
+ }
}
void gdbserver_fork_start(void)
@@ -663,11 +743,8 @@ int gdb_continue_partial(char *newstates)
int gdb_target_memory_rw_debug(CPUState *cpu, hwaddr addr,
uint8_t *buf, int len, bool is_write)
{
- CPUClass *cc;
-
- cc = CPU_GET_CLASS(cpu);
- if (cc->memory_rw_debug) {
- return cc->memory_rw_debug(cpu, addr, buf, len, is_write);
+ if (cpu->cc->memory_rw_debug) {
+ return cpu->cc->memory_rw_debug(cpu, addr, buf, len, is_write);
}
return cpu_memory_rw_debug(cpu, addr, buf, len, is_write);
}