1ae7467b1SAlex Bennée /* 2ae7467b1SAlex Bennée * gdbstub user-mode helper routines. 3ae7467b1SAlex Bennée * 4ae7467b1SAlex Bennée * We know for user-mode we are using TCG so we can call stuff directly. 5ae7467b1SAlex Bennée * 69455762fSAlex Bennée * Copyright (c) 2003-2005 Fabrice Bellard 7ae7467b1SAlex Bennée * Copyright (c) 2022 Linaro Ltd 8ae7467b1SAlex Bennée * 99455762fSAlex Bennée * SPDX-License-Identifier: LGPL-2.0+ 10ae7467b1SAlex Bennée */ 11ae7467b1SAlex Bennée 12ae7467b1SAlex Bennée #include "qemu/osdep.h" 13046f143cSIlya Leoshkevich #include "qemu/bitops.h" 14d96bf49bSAlex Bennée #include "qemu/cutils.h" 15d96bf49bSAlex Bennée #include "qemu/sockets.h" 16d96bf49bSAlex Bennée #include "exec/hwaddr.h" 17d96bf49bSAlex Bennée #include "exec/tb-flush.h" 18ae7467b1SAlex Bennée #include "exec/gdbstub.h" 19c566080cSAlex Bennée #include "gdbstub/syscalls.h" 20d96bf49bSAlex Bennée #include "gdbstub/user.h" 21ae7467b1SAlex Bennée #include "hw/core/cpu.h" 22d96bf49bSAlex Bennée #include "trace.h" 23ae7467b1SAlex Bennée #include "internals.h" 24ae7467b1SAlex Bennée 25046f143cSIlya Leoshkevich #define GDB_NR_SYSCALLS 1024 26046f143cSIlya Leoshkevich typedef unsigned long GDBSyscallsMask[BITS_TO_LONGS(GDB_NR_SYSCALLS)]; 27046f143cSIlya Leoshkevich 28d96bf49bSAlex Bennée /* User-mode specific state */ 29d96bf49bSAlex Bennée typedef struct { 30d96bf49bSAlex Bennée int fd; 31d96bf49bSAlex Bennée char *socket_path; 32d96bf49bSAlex Bennée int running_state; 33046f143cSIlya Leoshkevich /* 34046f143cSIlya Leoshkevich * Store syscalls mask without memory allocation in order to avoid 35046f143cSIlya Leoshkevich * implementing synchronization. 36046f143cSIlya Leoshkevich */ 37046f143cSIlya Leoshkevich bool catch_all_syscalls; 38046f143cSIlya Leoshkevich GDBSyscallsMask catch_syscalls_mask; 39d96bf49bSAlex Bennée } GDBUserState; 40d96bf49bSAlex Bennée 41d96bf49bSAlex Bennée static GDBUserState gdbserver_user_state; 42d96bf49bSAlex Bennée 43d96bf49bSAlex Bennée int gdb_get_char(void) 44d96bf49bSAlex Bennée { 45d96bf49bSAlex Bennée uint8_t ch; 46d96bf49bSAlex Bennée int ret; 47d96bf49bSAlex Bennée 48d96bf49bSAlex Bennée for (;;) { 49d96bf49bSAlex Bennée ret = recv(gdbserver_user_state.fd, &ch, 1, 0); 50d96bf49bSAlex Bennée if (ret < 0) { 51d96bf49bSAlex Bennée if (errno == ECONNRESET) { 52d96bf49bSAlex Bennée gdbserver_user_state.fd = -1; 53d96bf49bSAlex Bennée } 54d96bf49bSAlex Bennée if (errno != EINTR) { 55d96bf49bSAlex Bennée return -1; 56d96bf49bSAlex Bennée } 57d96bf49bSAlex Bennée } else if (ret == 0) { 58d96bf49bSAlex Bennée close(gdbserver_user_state.fd); 59d96bf49bSAlex Bennée gdbserver_user_state.fd = -1; 60d96bf49bSAlex Bennée return -1; 61d96bf49bSAlex Bennée } else { 62d96bf49bSAlex Bennée break; 63d96bf49bSAlex Bennée } 64d96bf49bSAlex Bennée } 65d96bf49bSAlex Bennée return ch; 66d96bf49bSAlex Bennée } 67d96bf49bSAlex Bennée 68a7e0f9bdSAlex Bennée bool gdb_got_immediate_ack(void) 69a7e0f9bdSAlex Bennée { 70a7e0f9bdSAlex Bennée int i; 71a7e0f9bdSAlex Bennée 72a7e0f9bdSAlex Bennée i = gdb_get_char(); 73a7e0f9bdSAlex Bennée if (i < 0) { 74a7e0f9bdSAlex Bennée /* no response, continue anyway */ 75a7e0f9bdSAlex Bennée return true; 76a7e0f9bdSAlex Bennée } 77a7e0f9bdSAlex Bennée 78a7e0f9bdSAlex Bennée if (i == '+') { 79a7e0f9bdSAlex Bennée /* received correctly, continue */ 80a7e0f9bdSAlex Bennée return true; 81a7e0f9bdSAlex Bennée } 82a7e0f9bdSAlex Bennée 83a7e0f9bdSAlex Bennée /* anything else, including '-' then try again */ 84a7e0f9bdSAlex Bennée return false; 85a7e0f9bdSAlex Bennée } 86a7e0f9bdSAlex Bennée 87d96bf49bSAlex Bennée void gdb_put_buffer(const uint8_t *buf, int len) 88d96bf49bSAlex Bennée { 89d96bf49bSAlex Bennée int ret; 90d96bf49bSAlex Bennée 91d96bf49bSAlex Bennée while (len > 0) { 92d96bf49bSAlex Bennée ret = send(gdbserver_user_state.fd, buf, len, 0); 93d96bf49bSAlex Bennée if (ret < 0) { 94d96bf49bSAlex Bennée if (errno != EINTR) { 95d96bf49bSAlex Bennée return; 96d96bf49bSAlex Bennée } 97d96bf49bSAlex Bennée } else { 98d96bf49bSAlex Bennée buf += ret; 99d96bf49bSAlex Bennée len -= ret; 100d96bf49bSAlex Bennée } 101d96bf49bSAlex Bennée } 102d96bf49bSAlex Bennée } 103d96bf49bSAlex Bennée 104d96bf49bSAlex Bennée /* Tell the remote gdb that the process has exited. */ 105d96bf49bSAlex Bennée void gdb_exit(int code) 106d96bf49bSAlex Bennée { 107d96bf49bSAlex Bennée char buf[4]; 108d96bf49bSAlex Bennée 109d96bf49bSAlex Bennée if (!gdbserver_state.init) { 110d96bf49bSAlex Bennée return; 111d96bf49bSAlex Bennée } 112d96bf49bSAlex Bennée if (gdbserver_user_state.socket_path) { 113d96bf49bSAlex Bennée unlink(gdbserver_user_state.socket_path); 114d96bf49bSAlex Bennée } 115d96bf49bSAlex Bennée if (gdbserver_user_state.fd < 0) { 116d96bf49bSAlex Bennée return; 117d96bf49bSAlex Bennée } 118d96bf49bSAlex Bennée 119d96bf49bSAlex Bennée trace_gdbstub_op_exiting((uint8_t)code); 120d96bf49bSAlex Bennée 12175837005SMatheus Tavares Bernardino if (gdbserver_state.allow_stop_reply) { 122d96bf49bSAlex Bennée snprintf(buf, sizeof(buf), "W%02x", (uint8_t)code); 123d96bf49bSAlex Bennée gdb_put_packet(buf); 12475837005SMatheus Tavares Bernardino gdbserver_state.allow_stop_reply = false; 12575837005SMatheus Tavares Bernardino } 126e216256aSClément Chigot 127e216256aSClément Chigot } 128e216256aSClément Chigot 129e216256aSClément Chigot void gdb_qemu_exit(int code) 130e216256aSClément Chigot { 131e216256aSClément Chigot exit(code); 132d96bf49bSAlex Bennée } 133d96bf49bSAlex Bennée 1348b7fcb8eSIlya Leoshkevich int gdb_handlesig_reason(CPUState *cpu, int sig, const char *reason) 135d96bf49bSAlex Bennée { 136d96bf49bSAlex Bennée char buf[256]; 137d96bf49bSAlex Bennée int n; 138d96bf49bSAlex Bennée 139d96bf49bSAlex Bennée if (!gdbserver_state.init || gdbserver_user_state.fd < 0) { 140d96bf49bSAlex Bennée return sig; 141d96bf49bSAlex Bennée } 142d96bf49bSAlex Bennée 143d96bf49bSAlex Bennée /* disable single step if it was enabled */ 144d96bf49bSAlex Bennée cpu_single_step(cpu, 0); 145d96bf49bSAlex Bennée tb_flush(cpu); 146d96bf49bSAlex Bennée 147d96bf49bSAlex Bennée if (sig != 0) { 148d96bf49bSAlex Bennée gdb_set_stop_cpu(cpu); 14975837005SMatheus Tavares Bernardino if (gdbserver_state.allow_stop_reply) { 150d96bf49bSAlex Bennée g_string_printf(gdbserver_state.str_buf, 151d96bf49bSAlex Bennée "T%02xthread:", gdb_target_signal_to_gdb(sig)); 152d96bf49bSAlex Bennée gdb_append_thread_id(cpu, gdbserver_state.str_buf); 153d96bf49bSAlex Bennée g_string_append_c(gdbserver_state.str_buf, ';'); 1548b7fcb8eSIlya Leoshkevich if (reason) { 1558b7fcb8eSIlya Leoshkevich g_string_append(gdbserver_state.str_buf, reason); 1568b7fcb8eSIlya Leoshkevich } 157d96bf49bSAlex Bennée gdb_put_strbuf(); 15875837005SMatheus Tavares Bernardino gdbserver_state.allow_stop_reply = false; 15975837005SMatheus Tavares Bernardino } 160d96bf49bSAlex Bennée } 161d96bf49bSAlex Bennée /* 162d96bf49bSAlex Bennée * gdb_put_packet() might have detected that the peer terminated the 163d96bf49bSAlex Bennée * connection. 164d96bf49bSAlex Bennée */ 165d96bf49bSAlex Bennée if (gdbserver_user_state.fd < 0) { 166d96bf49bSAlex Bennée return sig; 167d96bf49bSAlex Bennée } 168d96bf49bSAlex Bennée 169d96bf49bSAlex Bennée sig = 0; 170d96bf49bSAlex Bennée gdbserver_state.state = RS_IDLE; 171d96bf49bSAlex Bennée gdbserver_user_state.running_state = 0; 172d96bf49bSAlex Bennée while (gdbserver_user_state.running_state == 0) { 173d96bf49bSAlex Bennée n = read(gdbserver_user_state.fd, buf, 256); 174d96bf49bSAlex Bennée if (n > 0) { 175d96bf49bSAlex Bennée int i; 176d96bf49bSAlex Bennée 177d96bf49bSAlex Bennée for (i = 0; i < n; i++) { 178d96bf49bSAlex Bennée gdb_read_byte(buf[i]); 179d96bf49bSAlex Bennée } 180d96bf49bSAlex Bennée } else { 181d96bf49bSAlex Bennée /* 182d96bf49bSAlex Bennée * XXX: Connection closed. Should probably wait for another 183d96bf49bSAlex Bennée * connection before continuing. 184d96bf49bSAlex Bennée */ 185d96bf49bSAlex Bennée if (n == 0) { 186d96bf49bSAlex Bennée close(gdbserver_user_state.fd); 187d96bf49bSAlex Bennée } 188d96bf49bSAlex Bennée gdbserver_user_state.fd = -1; 189d96bf49bSAlex Bennée return sig; 190d96bf49bSAlex Bennée } 191d96bf49bSAlex Bennée } 192d96bf49bSAlex Bennée sig = gdbserver_state.signal; 193d96bf49bSAlex Bennée gdbserver_state.signal = 0; 194d96bf49bSAlex Bennée return sig; 195d96bf49bSAlex Bennée } 196d96bf49bSAlex Bennée 197d96bf49bSAlex Bennée /* Tell the remote gdb that the process has exited due to SIG. */ 198d96bf49bSAlex Bennée void gdb_signalled(CPUArchState *env, int sig) 199d96bf49bSAlex Bennée { 200d96bf49bSAlex Bennée char buf[4]; 201d96bf49bSAlex Bennée 20275837005SMatheus Tavares Bernardino if (!gdbserver_state.init || gdbserver_user_state.fd < 0 || 20375837005SMatheus Tavares Bernardino !gdbserver_state.allow_stop_reply) { 204d96bf49bSAlex Bennée return; 205d96bf49bSAlex Bennée } 206d96bf49bSAlex Bennée 207d96bf49bSAlex Bennée snprintf(buf, sizeof(buf), "X%02x", gdb_target_signal_to_gdb(sig)); 208d96bf49bSAlex Bennée gdb_put_packet(buf); 20975837005SMatheus Tavares Bernardino gdbserver_state.allow_stop_reply = false; 210d96bf49bSAlex Bennée } 211d96bf49bSAlex Bennée 212d96bf49bSAlex Bennée static void gdb_accept_init(int fd) 213d96bf49bSAlex Bennée { 214d96bf49bSAlex Bennée gdb_init_gdbserver_state(); 215d96bf49bSAlex Bennée gdb_create_default_process(&gdbserver_state); 216d96bf49bSAlex Bennée gdbserver_state.processes[0].attached = true; 217d96bf49bSAlex Bennée gdbserver_state.c_cpu = gdb_first_attached_cpu(); 218d96bf49bSAlex Bennée gdbserver_state.g_cpu = gdbserver_state.c_cpu; 219d96bf49bSAlex Bennée gdbserver_user_state.fd = fd; 220d96bf49bSAlex Bennée } 221d96bf49bSAlex Bennée 222d96bf49bSAlex Bennée static bool gdb_accept_socket(int gdb_fd) 223d96bf49bSAlex Bennée { 224d96bf49bSAlex Bennée int fd; 225d96bf49bSAlex Bennée 226d96bf49bSAlex Bennée for (;;) { 227d96bf49bSAlex Bennée fd = accept(gdb_fd, NULL, NULL); 228d96bf49bSAlex Bennée if (fd < 0 && errno != EINTR) { 229d96bf49bSAlex Bennée perror("accept socket"); 230d96bf49bSAlex Bennée return false; 231d96bf49bSAlex Bennée } else if (fd >= 0) { 232d96bf49bSAlex Bennée qemu_set_cloexec(fd); 233d96bf49bSAlex Bennée break; 234d96bf49bSAlex Bennée } 235d96bf49bSAlex Bennée } 236d96bf49bSAlex Bennée 237d96bf49bSAlex Bennée gdb_accept_init(fd); 238d96bf49bSAlex Bennée return true; 239d96bf49bSAlex Bennée } 240d96bf49bSAlex Bennée 241d96bf49bSAlex Bennée static int gdbserver_open_socket(const char *path) 242d96bf49bSAlex Bennée { 243d96bf49bSAlex Bennée struct sockaddr_un sockaddr = {}; 244d96bf49bSAlex Bennée int fd, ret; 245d96bf49bSAlex Bennée 246d96bf49bSAlex Bennée fd = socket(AF_UNIX, SOCK_STREAM, 0); 247d96bf49bSAlex Bennée if (fd < 0) { 248d96bf49bSAlex Bennée perror("create socket"); 249d96bf49bSAlex Bennée return -1; 250d96bf49bSAlex Bennée } 251d96bf49bSAlex Bennée 252d96bf49bSAlex Bennée sockaddr.sun_family = AF_UNIX; 253d96bf49bSAlex Bennée pstrcpy(sockaddr.sun_path, sizeof(sockaddr.sun_path) - 1, path); 254d96bf49bSAlex Bennée ret = bind(fd, (struct sockaddr *)&sockaddr, sizeof(sockaddr)); 255d96bf49bSAlex Bennée if (ret < 0) { 256d96bf49bSAlex Bennée perror("bind socket"); 257d96bf49bSAlex Bennée close(fd); 258d96bf49bSAlex Bennée return -1; 259d96bf49bSAlex Bennée } 260d96bf49bSAlex Bennée ret = listen(fd, 1); 261d96bf49bSAlex Bennée if (ret < 0) { 262d96bf49bSAlex Bennée perror("listen socket"); 263d96bf49bSAlex Bennée close(fd); 264d96bf49bSAlex Bennée return -1; 265d96bf49bSAlex Bennée } 266d96bf49bSAlex Bennée 267d96bf49bSAlex Bennée return fd; 268d96bf49bSAlex Bennée } 269d96bf49bSAlex Bennée 270d96bf49bSAlex Bennée static bool gdb_accept_tcp(int gdb_fd) 271d96bf49bSAlex Bennée { 272d96bf49bSAlex Bennée struct sockaddr_in sockaddr = {}; 273d96bf49bSAlex Bennée socklen_t len; 274d96bf49bSAlex Bennée int fd; 275d96bf49bSAlex Bennée 276d96bf49bSAlex Bennée for (;;) { 277d96bf49bSAlex Bennée len = sizeof(sockaddr); 278d96bf49bSAlex Bennée fd = accept(gdb_fd, (struct sockaddr *)&sockaddr, &len); 279d96bf49bSAlex Bennée if (fd < 0 && errno != EINTR) { 280d96bf49bSAlex Bennée perror("accept"); 281d96bf49bSAlex Bennée return false; 282d96bf49bSAlex Bennée } else if (fd >= 0) { 283d96bf49bSAlex Bennée qemu_set_cloexec(fd); 284d96bf49bSAlex Bennée break; 285d96bf49bSAlex Bennée } 286d96bf49bSAlex Bennée } 287d96bf49bSAlex Bennée 288d96bf49bSAlex Bennée /* set short latency */ 289d96bf49bSAlex Bennée if (socket_set_nodelay(fd)) { 290d96bf49bSAlex Bennée perror("setsockopt"); 291d96bf49bSAlex Bennée close(fd); 292d96bf49bSAlex Bennée return false; 293d96bf49bSAlex Bennée } 294d96bf49bSAlex Bennée 295d96bf49bSAlex Bennée gdb_accept_init(fd); 296d96bf49bSAlex Bennée return true; 297d96bf49bSAlex Bennée } 298d96bf49bSAlex Bennée 299d96bf49bSAlex Bennée static int gdbserver_open_port(int port) 300d96bf49bSAlex Bennée { 301d96bf49bSAlex Bennée struct sockaddr_in sockaddr; 302d96bf49bSAlex Bennée int fd, ret; 303d96bf49bSAlex Bennée 304d96bf49bSAlex Bennée fd = socket(PF_INET, SOCK_STREAM, 0); 305d96bf49bSAlex Bennée if (fd < 0) { 306d96bf49bSAlex Bennée perror("socket"); 307d96bf49bSAlex Bennée return -1; 308d96bf49bSAlex Bennée } 309d96bf49bSAlex Bennée qemu_set_cloexec(fd); 310d96bf49bSAlex Bennée 311d96bf49bSAlex Bennée socket_set_fast_reuse(fd); 312d96bf49bSAlex Bennée 313d96bf49bSAlex Bennée sockaddr.sin_family = AF_INET; 314d96bf49bSAlex Bennée sockaddr.sin_port = htons(port); 315d96bf49bSAlex Bennée sockaddr.sin_addr.s_addr = 0; 316d96bf49bSAlex Bennée ret = bind(fd, (struct sockaddr *)&sockaddr, sizeof(sockaddr)); 317d96bf49bSAlex Bennée if (ret < 0) { 318d96bf49bSAlex Bennée perror("bind"); 319d96bf49bSAlex Bennée close(fd); 320d96bf49bSAlex Bennée return -1; 321d96bf49bSAlex Bennée } 322d96bf49bSAlex Bennée ret = listen(fd, 1); 323d96bf49bSAlex Bennée if (ret < 0) { 324d96bf49bSAlex Bennée perror("listen"); 325d96bf49bSAlex Bennée close(fd); 326d96bf49bSAlex Bennée return -1; 327d96bf49bSAlex Bennée } 328d96bf49bSAlex Bennée 329d96bf49bSAlex Bennée return fd; 330d96bf49bSAlex Bennée } 331d96bf49bSAlex Bennée 332d96bf49bSAlex Bennée int gdbserver_start(const char *port_or_path) 333d96bf49bSAlex Bennée { 334d96bf49bSAlex Bennée int port = g_ascii_strtoull(port_or_path, NULL, 10); 335d96bf49bSAlex Bennée int gdb_fd; 336d96bf49bSAlex Bennée 337d96bf49bSAlex Bennée if (port > 0) { 338d96bf49bSAlex Bennée gdb_fd = gdbserver_open_port(port); 339d96bf49bSAlex Bennée } else { 340d96bf49bSAlex Bennée gdb_fd = gdbserver_open_socket(port_or_path); 341d96bf49bSAlex Bennée } 342d96bf49bSAlex Bennée 343d96bf49bSAlex Bennée if (gdb_fd < 0) { 344d96bf49bSAlex Bennée return -1; 345d96bf49bSAlex Bennée } 346d96bf49bSAlex Bennée 347d96bf49bSAlex Bennée if (port > 0 && gdb_accept_tcp(gdb_fd)) { 348d96bf49bSAlex Bennée return 0; 349d96bf49bSAlex Bennée } else if (gdb_accept_socket(gdb_fd)) { 350d96bf49bSAlex Bennée gdbserver_user_state.socket_path = g_strdup(port_or_path); 351d96bf49bSAlex Bennée return 0; 352d96bf49bSAlex Bennée } 353d96bf49bSAlex Bennée 354d96bf49bSAlex Bennée /* gone wrong */ 355d96bf49bSAlex Bennée close(gdb_fd); 356d96bf49bSAlex Bennée return -1; 357d96bf49bSAlex Bennée } 358d96bf49bSAlex Bennée 3593d6ed98dSIlya Leoshkevich void gdbserver_fork_start(void) 3603d6ed98dSIlya Leoshkevich { 3613d6ed98dSIlya Leoshkevich } 3623d6ed98dSIlya Leoshkevich 3631ea96f1dSIlya Leoshkevich static void disable_gdbstub(CPUState *thread_cpu) 3641ea96f1dSIlya Leoshkevich { 3651ea96f1dSIlya Leoshkevich CPUState *cpu; 3661ea96f1dSIlya Leoshkevich 3671ea96f1dSIlya Leoshkevich close(gdbserver_user_state.fd); 3681ea96f1dSIlya Leoshkevich gdbserver_user_state.fd = -1; 3691ea96f1dSIlya Leoshkevich CPU_FOREACH(cpu) { 3701ea96f1dSIlya Leoshkevich cpu_breakpoint_remove_all(cpu, BP_GDB); 3711ea96f1dSIlya Leoshkevich /* no cpu_watchpoint_remove_all for user-mode */ 3721ea96f1dSIlya Leoshkevich cpu_single_step(cpu, 0); 3731ea96f1dSIlya Leoshkevich } 3741ea96f1dSIlya Leoshkevich tb_flush(thread_cpu); 3751ea96f1dSIlya Leoshkevich } 3761ea96f1dSIlya Leoshkevich 3776604b057SIlya Leoshkevich void gdbserver_fork_end(CPUState *cpu, pid_t pid) 378d96bf49bSAlex Bennée { 3796604b057SIlya Leoshkevich if (pid != 0 || !gdbserver_state.init || gdbserver_user_state.fd < 0) { 380d96bf49bSAlex Bennée return; 381d96bf49bSAlex Bennée } 3821ea96f1dSIlya Leoshkevich disable_gdbstub(cpu); 383d96bf49bSAlex Bennée } 384d96bf49bSAlex Bennée 3856d923112SIlya Leoshkevich void gdb_handle_query_supported_user(const char *gdb_supported) 3866d923112SIlya Leoshkevich { 3876d923112SIlya Leoshkevich } 3886d923112SIlya Leoshkevich 389e454f2feSIlya Leoshkevich bool gdb_handle_set_thread_user(uint32_t pid, uint32_t tid) 390e454f2feSIlya Leoshkevich { 391e454f2feSIlya Leoshkevich return false; 392e454f2feSIlya Leoshkevich } 393e454f2feSIlya Leoshkevich 394*539cb4ecSIlya Leoshkevich bool gdb_handle_detach_user(uint32_t pid) 395*539cb4ecSIlya Leoshkevich { 396*539cb4ecSIlya Leoshkevich return false; 397*539cb4ecSIlya Leoshkevich } 398*539cb4ecSIlya Leoshkevich 399d96bf49bSAlex Bennée /* 400d96bf49bSAlex Bennée * Execution state helpers 401d96bf49bSAlex Bennée */ 402d96bf49bSAlex Bennée 4038a2025b3SAlex Bennée void gdb_handle_query_attached(GArray *params, void *user_ctx) 4048a2025b3SAlex Bennée { 4058a2025b3SAlex Bennée gdb_put_packet("0"); 4068a2025b3SAlex Bennée } 4078a2025b3SAlex Bennée 408d96bf49bSAlex Bennée void gdb_continue(void) 409d96bf49bSAlex Bennée { 410d96bf49bSAlex Bennée gdbserver_user_state.running_state = 1; 411d96bf49bSAlex Bennée trace_gdbstub_op_continue(); 412d96bf49bSAlex Bennée } 413d96bf49bSAlex Bennée 414d96bf49bSAlex Bennée /* 415d96bf49bSAlex Bennée * Resume execution, for user-mode emulation it's equivalent to 416d96bf49bSAlex Bennée * gdb_continue. 417d96bf49bSAlex Bennée */ 418d96bf49bSAlex Bennée int gdb_continue_partial(char *newstates) 419d96bf49bSAlex Bennée { 420d96bf49bSAlex Bennée CPUState *cpu; 421d96bf49bSAlex Bennée int res = 0; 422d96bf49bSAlex Bennée /* 423d96bf49bSAlex Bennée * This is not exactly accurate, but it's an improvement compared to the 424d96bf49bSAlex Bennée * previous situation, where only one CPU would be single-stepped. 425d96bf49bSAlex Bennée */ 426d96bf49bSAlex Bennée CPU_FOREACH(cpu) { 427d96bf49bSAlex Bennée if (newstates[cpu->cpu_index] == 's') { 428d96bf49bSAlex Bennée trace_gdbstub_op_stepping(cpu->cpu_index); 429d96bf49bSAlex Bennée cpu_single_step(cpu, gdbserver_state.sstep_flags); 430d96bf49bSAlex Bennée } 431d96bf49bSAlex Bennée } 432d96bf49bSAlex Bennée gdbserver_user_state.running_state = 1; 433d96bf49bSAlex Bennée return res; 434d96bf49bSAlex Bennée } 435d96bf49bSAlex Bennée 436d96bf49bSAlex Bennée /* 437589a5867SAlex Bennée * Memory access helpers 438589a5867SAlex Bennée */ 439589a5867SAlex Bennée int gdb_target_memory_rw_debug(CPUState *cpu, hwaddr addr, 440589a5867SAlex Bennée uint8_t *buf, int len, bool is_write) 441589a5867SAlex Bennée { 442589a5867SAlex Bennée CPUClass *cc; 443589a5867SAlex Bennée 444589a5867SAlex Bennée cc = CPU_GET_CLASS(cpu); 445589a5867SAlex Bennée if (cc->memory_rw_debug) { 446589a5867SAlex Bennée return cc->memory_rw_debug(cpu, addr, buf, len, is_write); 447589a5867SAlex Bennée } 448589a5867SAlex Bennée return cpu_memory_rw_debug(cpu, addr, buf, len, is_write); 449589a5867SAlex Bennée } 450589a5867SAlex Bennée 451589a5867SAlex Bennée /* 4527ea0c33dSAlex Bennée * cpu helpers 4537ea0c33dSAlex Bennée */ 4547ea0c33dSAlex Bennée 4557ea0c33dSAlex Bennée unsigned int gdb_get_max_cpus(void) 4567ea0c33dSAlex Bennée { 4577ea0c33dSAlex Bennée CPUState *cpu; 4587ea0c33dSAlex Bennée unsigned int max_cpus = 1; 4597ea0c33dSAlex Bennée 4607ea0c33dSAlex Bennée CPU_FOREACH(cpu) { 4617ea0c33dSAlex Bennée max_cpus = max_cpus <= cpu->cpu_index ? cpu->cpu_index + 1 : max_cpus; 4627ea0c33dSAlex Bennée } 4637ea0c33dSAlex Bennée 4647ea0c33dSAlex Bennée return max_cpus; 4657ea0c33dSAlex Bennée } 4667ea0c33dSAlex Bennée 467505601d5SAlex Bennée /* replay not supported for user-mode */ 468505601d5SAlex Bennée bool gdb_can_reverse(void) 469505601d5SAlex Bennée { 470505601d5SAlex Bennée return false; 471505601d5SAlex Bennée } 4727ea0c33dSAlex Bennée 4737ea0c33dSAlex Bennée /* 474d96bf49bSAlex Bennée * Break/Watch point helpers 475d96bf49bSAlex Bennée */ 476d96bf49bSAlex Bennée 477a48e7d9eSAlex Bennée bool gdb_supports_guest_debug(void) 478a48e7d9eSAlex Bennée { 479a48e7d9eSAlex Bennée /* user-mode == TCG == supported */ 480a48e7d9eSAlex Bennée return true; 481a48e7d9eSAlex Bennée } 482a48e7d9eSAlex Bennée 48355b5b8e9SPhilippe Mathieu-Daudé int gdb_breakpoint_insert(CPUState *cs, int type, vaddr addr, vaddr len) 484ae7467b1SAlex Bennée { 485ae7467b1SAlex Bennée CPUState *cpu; 486ae7467b1SAlex Bennée int err = 0; 487ae7467b1SAlex Bennée 488ae7467b1SAlex Bennée switch (type) { 489ae7467b1SAlex Bennée case GDB_BREAKPOINT_SW: 490ae7467b1SAlex Bennée case GDB_BREAKPOINT_HW: 491ae7467b1SAlex Bennée CPU_FOREACH(cpu) { 492ae7467b1SAlex Bennée err = cpu_breakpoint_insert(cpu, addr, BP_GDB, NULL); 493ae7467b1SAlex Bennée if (err) { 494ae7467b1SAlex Bennée break; 495ae7467b1SAlex Bennée } 496ae7467b1SAlex Bennée } 497ae7467b1SAlex Bennée return err; 498ae7467b1SAlex Bennée default: 499ae7467b1SAlex Bennée /* user-mode doesn't support watchpoints */ 500ae7467b1SAlex Bennée return -ENOSYS; 501ae7467b1SAlex Bennée } 502ae7467b1SAlex Bennée } 503ae7467b1SAlex Bennée 50455b5b8e9SPhilippe Mathieu-Daudé int gdb_breakpoint_remove(CPUState *cs, int type, vaddr addr, vaddr len) 505ae7467b1SAlex Bennée { 506ae7467b1SAlex Bennée CPUState *cpu; 507ae7467b1SAlex Bennée int err = 0; 508ae7467b1SAlex Bennée 509ae7467b1SAlex Bennée switch (type) { 510ae7467b1SAlex Bennée case GDB_BREAKPOINT_SW: 511ae7467b1SAlex Bennée case GDB_BREAKPOINT_HW: 512ae7467b1SAlex Bennée CPU_FOREACH(cpu) { 513ae7467b1SAlex Bennée err = cpu_breakpoint_remove(cpu, addr, BP_GDB); 514ae7467b1SAlex Bennée if (err) { 515ae7467b1SAlex Bennée break; 516ae7467b1SAlex Bennée } 517ae7467b1SAlex Bennée } 518ae7467b1SAlex Bennée return err; 519ae7467b1SAlex Bennée default: 520ae7467b1SAlex Bennée /* user-mode doesn't support watchpoints */ 521ae7467b1SAlex Bennée return -ENOSYS; 522ae7467b1SAlex Bennée } 523ae7467b1SAlex Bennée } 524ae7467b1SAlex Bennée 525ae7467b1SAlex Bennée void gdb_breakpoint_remove_all(CPUState *cs) 526ae7467b1SAlex Bennée { 527ae7467b1SAlex Bennée cpu_breakpoint_remove_all(cs, BP_GDB); 528ae7467b1SAlex Bennée } 529131f387dSAlex Bennée 530131f387dSAlex Bennée /* 531131f387dSAlex Bennée * For user-mode syscall support we send the system call immediately 532131f387dSAlex Bennée * and then return control to gdb for it to process the syscall request. 533131f387dSAlex Bennée * Since the protocol requires that gdb hands control back to us 534131f387dSAlex Bennée * using a "here are the results" F packet, we don't need to check 535131f387dSAlex Bennée * gdb_handlesig's return value (which is the signal to deliver if 536131f387dSAlex Bennée * execution was resumed via a continue packet). 537131f387dSAlex Bennée */ 538131f387dSAlex Bennée void gdb_syscall_handling(const char *syscall_packet) 539131f387dSAlex Bennée { 540131f387dSAlex Bennée gdb_put_packet(syscall_packet); 541131f387dSAlex Bennée gdb_handlesig(gdbserver_state.c_cpu, 0); 542131f387dSAlex Bennée } 5430a0d87c9SIlya Leoshkevich 544046f143cSIlya Leoshkevich static bool should_catch_syscall(int num) 545046f143cSIlya Leoshkevich { 546046f143cSIlya Leoshkevich if (gdbserver_user_state.catch_all_syscalls) { 547046f143cSIlya Leoshkevich return true; 548046f143cSIlya Leoshkevich } 549046f143cSIlya Leoshkevich if (num < 0 || num >= GDB_NR_SYSCALLS) { 550046f143cSIlya Leoshkevich return false; 551046f143cSIlya Leoshkevich } 552046f143cSIlya Leoshkevich return test_bit(num, gdbserver_user_state.catch_syscalls_mask); 553046f143cSIlya Leoshkevich } 554046f143cSIlya Leoshkevich 5550a0d87c9SIlya Leoshkevich void gdb_syscall_entry(CPUState *cs, int num) 5560a0d87c9SIlya Leoshkevich { 557046f143cSIlya Leoshkevich if (should_catch_syscall(num)) { 558046f143cSIlya Leoshkevich g_autofree char *reason = g_strdup_printf("syscall_entry:%x;", num); 559046f143cSIlya Leoshkevich gdb_handlesig_reason(cs, gdb_target_sigtrap(), reason); 560046f143cSIlya Leoshkevich } 5610a0d87c9SIlya Leoshkevich } 5620a0d87c9SIlya Leoshkevich 5630a0d87c9SIlya Leoshkevich void gdb_syscall_return(CPUState *cs, int num) 5640a0d87c9SIlya Leoshkevich { 565046f143cSIlya Leoshkevich if (should_catch_syscall(num)) { 566046f143cSIlya Leoshkevich g_autofree char *reason = g_strdup_printf("syscall_return:%x;", num); 567046f143cSIlya Leoshkevich gdb_handlesig_reason(cs, gdb_target_sigtrap(), reason); 568046f143cSIlya Leoshkevich } 569046f143cSIlya Leoshkevich } 570046f143cSIlya Leoshkevich 571046f143cSIlya Leoshkevich void gdb_handle_set_catch_syscalls(GArray *params, void *user_ctx) 572046f143cSIlya Leoshkevich { 573046f143cSIlya Leoshkevich const char *param = get_param(params, 0)->data; 574046f143cSIlya Leoshkevich GDBSyscallsMask catch_syscalls_mask; 575046f143cSIlya Leoshkevich bool catch_all_syscalls; 576046f143cSIlya Leoshkevich unsigned int num; 577046f143cSIlya Leoshkevich const char *p; 578046f143cSIlya Leoshkevich 579046f143cSIlya Leoshkevich /* "0" means not catching any syscalls. */ 580046f143cSIlya Leoshkevich if (strcmp(param, "0") == 0) { 581046f143cSIlya Leoshkevich gdbserver_user_state.catch_all_syscalls = false; 582046f143cSIlya Leoshkevich memset(gdbserver_user_state.catch_syscalls_mask, 0, 583046f143cSIlya Leoshkevich sizeof(gdbserver_user_state.catch_syscalls_mask)); 584046f143cSIlya Leoshkevich gdb_put_packet("OK"); 585046f143cSIlya Leoshkevich return; 586046f143cSIlya Leoshkevich } 587046f143cSIlya Leoshkevich 588046f143cSIlya Leoshkevich /* "1" means catching all syscalls. */ 589046f143cSIlya Leoshkevich if (strcmp(param, "1") == 0) { 590046f143cSIlya Leoshkevich gdbserver_user_state.catch_all_syscalls = true; 591046f143cSIlya Leoshkevich gdb_put_packet("OK"); 592046f143cSIlya Leoshkevich return; 593046f143cSIlya Leoshkevich } 594046f143cSIlya Leoshkevich 595046f143cSIlya Leoshkevich /* 596046f143cSIlya Leoshkevich * "1;..." means catching only the specified syscalls. 597046f143cSIlya Leoshkevich * The syscall list must not be empty. 598046f143cSIlya Leoshkevich */ 599046f143cSIlya Leoshkevich if (param[0] == '1' && param[1] == ';') { 600046f143cSIlya Leoshkevich catch_all_syscalls = false; 601046f143cSIlya Leoshkevich memset(catch_syscalls_mask, 0, sizeof(catch_syscalls_mask)); 602046f143cSIlya Leoshkevich for (p = ¶m[2];; p++) { 603046f143cSIlya Leoshkevich if (qemu_strtoui(p, &p, 16, &num) || (*p && *p != ';')) { 604046f143cSIlya Leoshkevich goto err; 605046f143cSIlya Leoshkevich } 606046f143cSIlya Leoshkevich if (num >= GDB_NR_SYSCALLS) { 607046f143cSIlya Leoshkevich /* 608046f143cSIlya Leoshkevich * Fall back to reporting all syscalls. Reporting extra 609046f143cSIlya Leoshkevich * syscalls is inefficient, but the spec explicitly allows it. 610046f143cSIlya Leoshkevich * Keep parsing in case there is a syntax error ahead. 611046f143cSIlya Leoshkevich */ 612046f143cSIlya Leoshkevich catch_all_syscalls = true; 613046f143cSIlya Leoshkevich } else { 614046f143cSIlya Leoshkevich set_bit(num, catch_syscalls_mask); 615046f143cSIlya Leoshkevich } 616046f143cSIlya Leoshkevich if (!*p) { 617046f143cSIlya Leoshkevich break; 618046f143cSIlya Leoshkevich } 619046f143cSIlya Leoshkevich } 620046f143cSIlya Leoshkevich gdbserver_user_state.catch_all_syscalls = catch_all_syscalls; 621046f143cSIlya Leoshkevich if (!catch_all_syscalls) { 622046f143cSIlya Leoshkevich memcpy(gdbserver_user_state.catch_syscalls_mask, 623046f143cSIlya Leoshkevich catch_syscalls_mask, sizeof(catch_syscalls_mask)); 624046f143cSIlya Leoshkevich } 625046f143cSIlya Leoshkevich gdb_put_packet("OK"); 626046f143cSIlya Leoshkevich return; 627046f143cSIlya Leoshkevich } 628046f143cSIlya Leoshkevich 629046f143cSIlya Leoshkevich err: 630046f143cSIlya Leoshkevich gdb_put_packet("E00"); 6310a0d87c9SIlya Leoshkevich } 632