1842b42dfSAlex Bennée /* 2842b42dfSAlex Bennée * gdb server stub 3842b42dfSAlex Bennée * 4842b42dfSAlex Bennée * This implements a subset of the remote protocol as described in: 5842b42dfSAlex Bennée * 6842b42dfSAlex Bennée * https://sourceware.org/gdb/onlinedocs/gdb/Remote-Protocol.html 7842b42dfSAlex Bennée * 8842b42dfSAlex Bennée * Copyright (c) 2003-2005 Fabrice Bellard 9842b42dfSAlex Bennée * 10842b42dfSAlex Bennée * This library is free software; you can redistribute it and/or 11842b42dfSAlex Bennée * modify it under the terms of the GNU Lesser General Public 12842b42dfSAlex Bennée * License as published by the Free Software Foundation; either 13842b42dfSAlex Bennée * version 2 of the License, or (at your option) any later version. 14842b42dfSAlex Bennée * 15842b42dfSAlex Bennée * This library is distributed in the hope that it will be useful, 16842b42dfSAlex Bennée * but WITHOUT ANY WARRANTY; without even the implied warranty of 17842b42dfSAlex Bennée * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18842b42dfSAlex Bennée * Lesser General Public License for more details. 19842b42dfSAlex Bennée * 20842b42dfSAlex Bennée * You should have received a copy of the GNU Lesser General Public 21842b42dfSAlex Bennée * License along with this library; if not, see <http://www.gnu.org/licenses/>. 22842b42dfSAlex Bennée * 23842b42dfSAlex Bennée * SPDX-License-Identifier: LGPL-2.0+ 24842b42dfSAlex Bennée */ 25842b42dfSAlex Bennée 26842b42dfSAlex Bennée #include "qemu/osdep.h" 27842b42dfSAlex Bennée #include "qemu/ctype.h" 28842b42dfSAlex Bennée #include "qemu/cutils.h" 29842b42dfSAlex Bennée #include "qemu/module.h" 30842b42dfSAlex Bennée #include "trace.h" 31842b42dfSAlex Bennée #include "exec/gdbstub.h" 32842b42dfSAlex Bennée #ifdef CONFIG_USER_ONLY 33d96bf49bSAlex Bennée #include "gdbstub/user.h" 34842b42dfSAlex Bennée #else 35842b42dfSAlex Bennée #include "hw/cpu/cluster.h" 36842b42dfSAlex Bennée #include "hw/boards.h" 37842b42dfSAlex Bennée #endif 38842b42dfSAlex Bennée 39842b42dfSAlex Bennée #include "sysemu/hw_accel.h" 40842b42dfSAlex Bennée #include "sysemu/runstate.h" 41842b42dfSAlex Bennée #include "semihosting/semihost.h" 42842b42dfSAlex Bennée #include "exec/exec-all.h" 435b5968c4SPhilippe Mathieu-Daudé #include "exec/replay-core.h" 44548c9609SAlex Bennée #include "exec/tb-flush.h" 45548c9609SAlex Bennée #include "exec/hwaddr.h" 46842b42dfSAlex Bennée 47ae7467b1SAlex Bennée #include "internals.h" 48ae7467b1SAlex Bennée 49842b42dfSAlex Bennée typedef struct GDBRegisterState { 50842b42dfSAlex Bennée int base_reg; 51842b42dfSAlex Bennée int num_regs; 52842b42dfSAlex Bennée gdb_get_reg_cb get_reg; 53842b42dfSAlex Bennée gdb_set_reg_cb set_reg; 54842b42dfSAlex Bennée const char *xml; 55842b42dfSAlex Bennée struct GDBRegisterState *next; 56842b42dfSAlex Bennée } GDBRegisterState; 57842b42dfSAlex Bennée 58b6fa2ec2SAlex Bennée GDBState gdbserver_state; 59842b42dfSAlex Bennée 6036e067b2SAlex Bennée void gdb_init_gdbserver_state(void) 61842b42dfSAlex Bennée { 62842b42dfSAlex Bennée g_assert(!gdbserver_state.init); 63842b42dfSAlex Bennée memset(&gdbserver_state, 0, sizeof(GDBState)); 64842b42dfSAlex Bennée gdbserver_state.init = true; 65842b42dfSAlex Bennée gdbserver_state.str_buf = g_string_new(NULL); 66842b42dfSAlex Bennée gdbserver_state.mem_buf = g_byte_array_sized_new(MAX_PACKET_LENGTH); 67842b42dfSAlex Bennée gdbserver_state.last_packet = g_byte_array_sized_new(MAX_PACKET_LENGTH + 4); 68842b42dfSAlex Bennée 69842b42dfSAlex Bennée /* 703b7a9388SAlex Bennée * What single-step modes are supported is accelerator dependent. 713b7a9388SAlex Bennée * By default try to use no IRQs and no timers while single 723b7a9388SAlex Bennée * stepping so as to make single stepping like a typical ICE HW step. 73842b42dfSAlex Bennée */ 743b7a9388SAlex Bennée gdbserver_state.supported_sstep_flags = accel_supported_gdbstub_sstep_flags(); 75842b42dfSAlex Bennée gdbserver_state.sstep_flags = SSTEP_ENABLE | SSTEP_NOIRQ | SSTEP_NOTIMER; 76842b42dfSAlex Bennée gdbserver_state.sstep_flags &= gdbserver_state.supported_sstep_flags; 77842b42dfSAlex Bennée } 78842b42dfSAlex Bennée 79842b42dfSAlex Bennée bool gdb_has_xml; 80842b42dfSAlex Bennée 81842b42dfSAlex Bennée /* 82842b42dfSAlex Bennée * Return true if there is a GDB currently connected to the stub 83842b42dfSAlex Bennée * and attached to a CPU 84842b42dfSAlex Bennée */ 85842b42dfSAlex Bennée static bool gdb_attached(void) 86842b42dfSAlex Bennée { 87842b42dfSAlex Bennée return gdbserver_state.init && gdbserver_state.c_cpu; 88842b42dfSAlex Bennée } 89842b42dfSAlex Bennée 90842b42dfSAlex Bennée static enum { 91842b42dfSAlex Bennée GDB_SYS_UNKNOWN, 92842b42dfSAlex Bennée GDB_SYS_ENABLED, 93842b42dfSAlex Bennée GDB_SYS_DISABLED, 94842b42dfSAlex Bennée } gdb_syscall_mode; 95842b42dfSAlex Bennée 96842b42dfSAlex Bennée /* Decide if either remote gdb syscalls or native file IO should be used. */ 97842b42dfSAlex Bennée int use_gdb_syscalls(void) 98842b42dfSAlex Bennée { 99842b42dfSAlex Bennée SemihostingTarget target = semihosting_get_target(); 100842b42dfSAlex Bennée if (target == SEMIHOSTING_TARGET_NATIVE) { 101842b42dfSAlex Bennée /* -semihosting-config target=native */ 102842b42dfSAlex Bennée return false; 103842b42dfSAlex Bennée } else if (target == SEMIHOSTING_TARGET_GDB) { 104842b42dfSAlex Bennée /* -semihosting-config target=gdb */ 105842b42dfSAlex Bennée return true; 106842b42dfSAlex Bennée } 107842b42dfSAlex Bennée 108842b42dfSAlex Bennée /* -semihosting-config target=auto */ 109842b42dfSAlex Bennée /* On the first call check if gdb is connected and remember. */ 110842b42dfSAlex Bennée if (gdb_syscall_mode == GDB_SYS_UNKNOWN) { 111842b42dfSAlex Bennée gdb_syscall_mode = gdb_attached() ? GDB_SYS_ENABLED : GDB_SYS_DISABLED; 112842b42dfSAlex Bennée } 113842b42dfSAlex Bennée return gdb_syscall_mode == GDB_SYS_ENABLED; 114842b42dfSAlex Bennée } 115842b42dfSAlex Bennée 116842b42dfSAlex Bennée /* writes 2*len+1 bytes in buf */ 11736e067b2SAlex Bennée void gdb_memtohex(GString *buf, const uint8_t *mem, int len) 118842b42dfSAlex Bennée { 119842b42dfSAlex Bennée int i, c; 120842b42dfSAlex Bennée for(i = 0; i < len; i++) { 121842b42dfSAlex Bennée c = mem[i]; 122842b42dfSAlex Bennée g_string_append_c(buf, tohex(c >> 4)); 123842b42dfSAlex Bennée g_string_append_c(buf, tohex(c & 0xf)); 124842b42dfSAlex Bennée } 125842b42dfSAlex Bennée g_string_append_c(buf, '\0'); 126842b42dfSAlex Bennée } 127842b42dfSAlex Bennée 12836e067b2SAlex Bennée void gdb_hextomem(GByteArray *mem, const char *buf, int len) 129842b42dfSAlex Bennée { 130842b42dfSAlex Bennée int i; 131842b42dfSAlex Bennée 132842b42dfSAlex Bennée for(i = 0; i < len; i++) { 133842b42dfSAlex Bennée guint8 byte = fromhex(buf[0]) << 4 | fromhex(buf[1]); 134842b42dfSAlex Bennée g_byte_array_append(mem, &byte, 1); 135842b42dfSAlex Bennée buf += 2; 136842b42dfSAlex Bennée } 137842b42dfSAlex Bennée } 138842b42dfSAlex Bennée 139842b42dfSAlex Bennée static void hexdump(const char *buf, int len, 140842b42dfSAlex Bennée void (*trace_fn)(size_t ofs, char const *text)) 141842b42dfSAlex Bennée { 142842b42dfSAlex Bennée char line_buffer[3 * 16 + 4 + 16 + 1]; 143842b42dfSAlex Bennée 144842b42dfSAlex Bennée size_t i; 145842b42dfSAlex Bennée for (i = 0; i < len || (i & 0xF); ++i) { 146842b42dfSAlex Bennée size_t byte_ofs = i & 15; 147842b42dfSAlex Bennée 148842b42dfSAlex Bennée if (byte_ofs == 0) { 149842b42dfSAlex Bennée memset(line_buffer, ' ', 3 * 16 + 4 + 16); 150842b42dfSAlex Bennée line_buffer[3 * 16 + 4 + 16] = 0; 151842b42dfSAlex Bennée } 152842b42dfSAlex Bennée 153842b42dfSAlex Bennée size_t col_group = (i >> 2) & 3; 154842b42dfSAlex Bennée size_t hex_col = byte_ofs * 3 + col_group; 155842b42dfSAlex Bennée size_t txt_col = 3 * 16 + 4 + byte_ofs; 156842b42dfSAlex Bennée 157842b42dfSAlex Bennée if (i < len) { 158842b42dfSAlex Bennée char value = buf[i]; 159842b42dfSAlex Bennée 160842b42dfSAlex Bennée line_buffer[hex_col + 0] = tohex((value >> 4) & 0xF); 161842b42dfSAlex Bennée line_buffer[hex_col + 1] = tohex((value >> 0) & 0xF); 162842b42dfSAlex Bennée line_buffer[txt_col + 0] = (value >= ' ' && value < 127) 163842b42dfSAlex Bennée ? value 164842b42dfSAlex Bennée : '.'; 165842b42dfSAlex Bennée } 166842b42dfSAlex Bennée 167842b42dfSAlex Bennée if (byte_ofs == 0xF) 168842b42dfSAlex Bennée trace_fn(i & -16, line_buffer); 169842b42dfSAlex Bennée } 170842b42dfSAlex Bennée } 171842b42dfSAlex Bennée 172842b42dfSAlex Bennée /* return -1 if error, 0 if OK */ 17336e067b2SAlex Bennée int gdb_put_packet_binary(const char *buf, int len, bool dump) 174842b42dfSAlex Bennée { 175842b42dfSAlex Bennée int csum, i; 176842b42dfSAlex Bennée uint8_t footer[3]; 177842b42dfSAlex Bennée 178842b42dfSAlex Bennée if (dump && trace_event_get_state_backends(TRACE_GDBSTUB_IO_BINARYREPLY)) { 179842b42dfSAlex Bennée hexdump(buf, len, trace_gdbstub_io_binaryreply); 180842b42dfSAlex Bennée } 181842b42dfSAlex Bennée 182842b42dfSAlex Bennée for(;;) { 183842b42dfSAlex Bennée g_byte_array_set_size(gdbserver_state.last_packet, 0); 184842b42dfSAlex Bennée g_byte_array_append(gdbserver_state.last_packet, 185842b42dfSAlex Bennée (const uint8_t *) "$", 1); 186842b42dfSAlex Bennée g_byte_array_append(gdbserver_state.last_packet, 187842b42dfSAlex Bennée (const uint8_t *) buf, len); 188842b42dfSAlex Bennée csum = 0; 189842b42dfSAlex Bennée for(i = 0; i < len; i++) { 190842b42dfSAlex Bennée csum += buf[i]; 191842b42dfSAlex Bennée } 192842b42dfSAlex Bennée footer[0] = '#'; 193842b42dfSAlex Bennée footer[1] = tohex((csum >> 4) & 0xf); 194842b42dfSAlex Bennée footer[2] = tohex((csum) & 0xf); 195842b42dfSAlex Bennée g_byte_array_append(gdbserver_state.last_packet, footer, 3); 196842b42dfSAlex Bennée 19736e067b2SAlex Bennée gdb_put_buffer(gdbserver_state.last_packet->data, 198842b42dfSAlex Bennée gdbserver_state.last_packet->len); 199842b42dfSAlex Bennée 200a7e0f9bdSAlex Bennée if (gdb_got_immediate_ack()) { 201842b42dfSAlex Bennée break; 202a7e0f9bdSAlex Bennée } 203842b42dfSAlex Bennée } 204842b42dfSAlex Bennée return 0; 205842b42dfSAlex Bennée } 206842b42dfSAlex Bennée 207842b42dfSAlex Bennée /* return -1 if error, 0 if OK */ 20836e067b2SAlex Bennée int gdb_put_packet(const char *buf) 209842b42dfSAlex Bennée { 210842b42dfSAlex Bennée trace_gdbstub_io_reply(buf); 211842b42dfSAlex Bennée 21236e067b2SAlex Bennée return gdb_put_packet_binary(buf, strlen(buf), false); 213842b42dfSAlex Bennée } 214842b42dfSAlex Bennée 21536e067b2SAlex Bennée void gdb_put_strbuf(void) 216842b42dfSAlex Bennée { 21736e067b2SAlex Bennée gdb_put_packet(gdbserver_state.str_buf->str); 218842b42dfSAlex Bennée } 219842b42dfSAlex Bennée 220842b42dfSAlex Bennée /* Encode data using the encoding for 'x' packets. */ 22136e067b2SAlex Bennée void gdb_memtox(GString *buf, const char *mem, int len) 222842b42dfSAlex Bennée { 223842b42dfSAlex Bennée char c; 224842b42dfSAlex Bennée 225842b42dfSAlex Bennée while (len--) { 226842b42dfSAlex Bennée c = *(mem++); 227842b42dfSAlex Bennée switch (c) { 228842b42dfSAlex Bennée case '#': case '$': case '*': case '}': 229842b42dfSAlex Bennée g_string_append_c(buf, '}'); 230842b42dfSAlex Bennée g_string_append_c(buf, c ^ 0x20); 231842b42dfSAlex Bennée break; 232842b42dfSAlex Bennée default: 233842b42dfSAlex Bennée g_string_append_c(buf, c); 234842b42dfSAlex Bennée break; 235842b42dfSAlex Bennée } 236842b42dfSAlex Bennée } 237842b42dfSAlex Bennée } 238842b42dfSAlex Bennée 239842b42dfSAlex Bennée static uint32_t gdb_get_cpu_pid(CPUState *cpu) 240842b42dfSAlex Bennée { 241842b42dfSAlex Bennée /* TODO: In user mode, we should use the task state PID */ 242842b42dfSAlex Bennée if (cpu->cluster_index == UNASSIGNED_CLUSTER_INDEX) { 243842b42dfSAlex Bennée /* Return the default process' PID */ 244842b42dfSAlex Bennée int index = gdbserver_state.process_num - 1; 245842b42dfSAlex Bennée return gdbserver_state.processes[index].pid; 246842b42dfSAlex Bennée } 247842b42dfSAlex Bennée return cpu->cluster_index + 1; 248842b42dfSAlex Bennée } 249842b42dfSAlex Bennée 250842b42dfSAlex Bennée static GDBProcess *gdb_get_process(uint32_t pid) 251842b42dfSAlex Bennée { 252842b42dfSAlex Bennée int i; 253842b42dfSAlex Bennée 254842b42dfSAlex Bennée if (!pid) { 255842b42dfSAlex Bennée /* 0 means any process, we take the first one */ 256842b42dfSAlex Bennée return &gdbserver_state.processes[0]; 257842b42dfSAlex Bennée } 258842b42dfSAlex Bennée 259842b42dfSAlex Bennée for (i = 0; i < gdbserver_state.process_num; i++) { 260842b42dfSAlex Bennée if (gdbserver_state.processes[i].pid == pid) { 261842b42dfSAlex Bennée return &gdbserver_state.processes[i]; 262842b42dfSAlex Bennée } 263842b42dfSAlex Bennée } 264842b42dfSAlex Bennée 265842b42dfSAlex Bennée return NULL; 266842b42dfSAlex Bennée } 267842b42dfSAlex Bennée 268842b42dfSAlex Bennée static GDBProcess *gdb_get_cpu_process(CPUState *cpu) 269842b42dfSAlex Bennée { 270842b42dfSAlex Bennée return gdb_get_process(gdb_get_cpu_pid(cpu)); 271842b42dfSAlex Bennée } 272842b42dfSAlex Bennée 273842b42dfSAlex Bennée static CPUState *find_cpu(uint32_t thread_id) 274842b42dfSAlex Bennée { 275842b42dfSAlex Bennée CPUState *cpu; 276842b42dfSAlex Bennée 277842b42dfSAlex Bennée CPU_FOREACH(cpu) { 27836e067b2SAlex Bennée if (gdb_get_cpu_index(cpu) == thread_id) { 279842b42dfSAlex Bennée return cpu; 280842b42dfSAlex Bennée } 281842b42dfSAlex Bennée } 282842b42dfSAlex Bennée 283842b42dfSAlex Bennée return NULL; 284842b42dfSAlex Bennée } 285842b42dfSAlex Bennée 286842b42dfSAlex Bennée static CPUState *get_first_cpu_in_process(GDBProcess *process) 287842b42dfSAlex Bennée { 288842b42dfSAlex Bennée CPUState *cpu; 289842b42dfSAlex Bennée 290842b42dfSAlex Bennée CPU_FOREACH(cpu) { 291842b42dfSAlex Bennée if (gdb_get_cpu_pid(cpu) == process->pid) { 292842b42dfSAlex Bennée return cpu; 293842b42dfSAlex Bennée } 294842b42dfSAlex Bennée } 295842b42dfSAlex Bennée 296842b42dfSAlex Bennée return NULL; 297842b42dfSAlex Bennée } 298842b42dfSAlex Bennée 299842b42dfSAlex Bennée static CPUState *gdb_next_cpu_in_process(CPUState *cpu) 300842b42dfSAlex Bennée { 301842b42dfSAlex Bennée uint32_t pid = gdb_get_cpu_pid(cpu); 302842b42dfSAlex Bennée cpu = CPU_NEXT(cpu); 303842b42dfSAlex Bennée 304842b42dfSAlex Bennée while (cpu) { 305842b42dfSAlex Bennée if (gdb_get_cpu_pid(cpu) == pid) { 306842b42dfSAlex Bennée break; 307842b42dfSAlex Bennée } 308842b42dfSAlex Bennée 309842b42dfSAlex Bennée cpu = CPU_NEXT(cpu); 310842b42dfSAlex Bennée } 311842b42dfSAlex Bennée 312842b42dfSAlex Bennée return cpu; 313842b42dfSAlex Bennée } 314842b42dfSAlex Bennée 315842b42dfSAlex Bennée /* Return the cpu following @cpu, while ignoring unattached processes. */ 316842b42dfSAlex Bennée static CPUState *gdb_next_attached_cpu(CPUState *cpu) 317842b42dfSAlex Bennée { 318842b42dfSAlex Bennée cpu = CPU_NEXT(cpu); 319842b42dfSAlex Bennée 320842b42dfSAlex Bennée while (cpu) { 321842b42dfSAlex Bennée if (gdb_get_cpu_process(cpu)->attached) { 322842b42dfSAlex Bennée break; 323842b42dfSAlex Bennée } 324842b42dfSAlex Bennée 325842b42dfSAlex Bennée cpu = CPU_NEXT(cpu); 326842b42dfSAlex Bennée } 327842b42dfSAlex Bennée 328842b42dfSAlex Bennée return cpu; 329842b42dfSAlex Bennée } 330842b42dfSAlex Bennée 331842b42dfSAlex Bennée /* Return the first attached cpu */ 33236e067b2SAlex Bennée CPUState *gdb_first_attached_cpu(void) 333842b42dfSAlex Bennée { 334842b42dfSAlex Bennée CPUState *cpu = first_cpu; 335842b42dfSAlex Bennée GDBProcess *process = gdb_get_cpu_process(cpu); 336842b42dfSAlex Bennée 337842b42dfSAlex Bennée if (!process->attached) { 338842b42dfSAlex Bennée return gdb_next_attached_cpu(cpu); 339842b42dfSAlex Bennée } 340842b42dfSAlex Bennée 341842b42dfSAlex Bennée return cpu; 342842b42dfSAlex Bennée } 343842b42dfSAlex Bennée 344842b42dfSAlex Bennée static CPUState *gdb_get_cpu(uint32_t pid, uint32_t tid) 345842b42dfSAlex Bennée { 346842b42dfSAlex Bennée GDBProcess *process; 347842b42dfSAlex Bennée CPUState *cpu; 348842b42dfSAlex Bennée 349842b42dfSAlex Bennée if (!pid && !tid) { 350842b42dfSAlex Bennée /* 0 means any process/thread, we take the first attached one */ 351842b42dfSAlex Bennée return gdb_first_attached_cpu(); 352842b42dfSAlex Bennée } else if (pid && !tid) { 353842b42dfSAlex Bennée /* any thread in a specific process */ 354842b42dfSAlex Bennée process = gdb_get_process(pid); 355842b42dfSAlex Bennée 356842b42dfSAlex Bennée if (process == NULL) { 357842b42dfSAlex Bennée return NULL; 358842b42dfSAlex Bennée } 359842b42dfSAlex Bennée 360842b42dfSAlex Bennée if (!process->attached) { 361842b42dfSAlex Bennée return NULL; 362842b42dfSAlex Bennée } 363842b42dfSAlex Bennée 364842b42dfSAlex Bennée return get_first_cpu_in_process(process); 365842b42dfSAlex Bennée } else { 366842b42dfSAlex Bennée /* a specific thread */ 367842b42dfSAlex Bennée cpu = find_cpu(tid); 368842b42dfSAlex Bennée 369842b42dfSAlex Bennée if (cpu == NULL) { 370842b42dfSAlex Bennée return NULL; 371842b42dfSAlex Bennée } 372842b42dfSAlex Bennée 373842b42dfSAlex Bennée process = gdb_get_cpu_process(cpu); 374842b42dfSAlex Bennée 375842b42dfSAlex Bennée if (pid && process->pid != pid) { 376842b42dfSAlex Bennée return NULL; 377842b42dfSAlex Bennée } 378842b42dfSAlex Bennée 379842b42dfSAlex Bennée if (!process->attached) { 380842b42dfSAlex Bennée return NULL; 381842b42dfSAlex Bennée } 382842b42dfSAlex Bennée 383842b42dfSAlex Bennée return cpu; 384842b42dfSAlex Bennée } 385842b42dfSAlex Bennée } 386842b42dfSAlex Bennée 387842b42dfSAlex Bennée static const char *get_feature_xml(const char *p, const char **newp, 388842b42dfSAlex Bennée GDBProcess *process) 389842b42dfSAlex Bennée { 390842b42dfSAlex Bennée size_t len; 391842b42dfSAlex Bennée int i; 392842b42dfSAlex Bennée const char *name; 393842b42dfSAlex Bennée CPUState *cpu = get_first_cpu_in_process(process); 394842b42dfSAlex Bennée CPUClass *cc = CPU_GET_CLASS(cpu); 395842b42dfSAlex Bennée 396842b42dfSAlex Bennée len = 0; 397842b42dfSAlex Bennée while (p[len] && p[len] != ':') 398842b42dfSAlex Bennée len++; 399842b42dfSAlex Bennée *newp = p + len; 400842b42dfSAlex Bennée 401842b42dfSAlex Bennée name = NULL; 402842b42dfSAlex Bennée if (strncmp(p, "target.xml", len) == 0) { 403842b42dfSAlex Bennée char *buf = process->target_xml; 404842b42dfSAlex Bennée const size_t buf_sz = sizeof(process->target_xml); 405842b42dfSAlex Bennée 406842b42dfSAlex Bennée /* Generate the XML description for this CPU. */ 407842b42dfSAlex Bennée if (!buf[0]) { 408842b42dfSAlex Bennée GDBRegisterState *r; 409842b42dfSAlex Bennée 410842b42dfSAlex Bennée pstrcat(buf, buf_sz, 411842b42dfSAlex Bennée "<?xml version=\"1.0\"?>" 412842b42dfSAlex Bennée "<!DOCTYPE target SYSTEM \"gdb-target.dtd\">" 413842b42dfSAlex Bennée "<target>"); 414842b42dfSAlex Bennée if (cc->gdb_arch_name) { 415842b42dfSAlex Bennée gchar *arch = cc->gdb_arch_name(cpu); 416842b42dfSAlex Bennée pstrcat(buf, buf_sz, "<architecture>"); 417842b42dfSAlex Bennée pstrcat(buf, buf_sz, arch); 418842b42dfSAlex Bennée pstrcat(buf, buf_sz, "</architecture>"); 419842b42dfSAlex Bennée g_free(arch); 420842b42dfSAlex Bennée } 421842b42dfSAlex Bennée pstrcat(buf, buf_sz, "<xi:include href=\""); 422842b42dfSAlex Bennée pstrcat(buf, buf_sz, cc->gdb_core_xml_file); 423842b42dfSAlex Bennée pstrcat(buf, buf_sz, "\"/>"); 424842b42dfSAlex Bennée for (r = cpu->gdb_regs; r; r = r->next) { 425842b42dfSAlex Bennée pstrcat(buf, buf_sz, "<xi:include href=\""); 426842b42dfSAlex Bennée pstrcat(buf, buf_sz, r->xml); 427842b42dfSAlex Bennée pstrcat(buf, buf_sz, "\"/>"); 428842b42dfSAlex Bennée } 429842b42dfSAlex Bennée pstrcat(buf, buf_sz, "</target>"); 430842b42dfSAlex Bennée } 431842b42dfSAlex Bennée return buf; 432842b42dfSAlex Bennée } 433842b42dfSAlex Bennée if (cc->gdb_get_dynamic_xml) { 434842b42dfSAlex Bennée char *xmlname = g_strndup(p, len); 435842b42dfSAlex Bennée const char *xml = cc->gdb_get_dynamic_xml(cpu, xmlname); 436842b42dfSAlex Bennée 437842b42dfSAlex Bennée g_free(xmlname); 438842b42dfSAlex Bennée if (xml) { 439842b42dfSAlex Bennée return xml; 440842b42dfSAlex Bennée } 441842b42dfSAlex Bennée } 442842b42dfSAlex Bennée for (i = 0; ; i++) { 443842b42dfSAlex Bennée name = xml_builtin[i][0]; 444842b42dfSAlex Bennée if (!name || (strncmp(name, p, len) == 0 && strlen(name) == len)) 445842b42dfSAlex Bennée break; 446842b42dfSAlex Bennée } 447842b42dfSAlex Bennée return name ? xml_builtin[i][1] : NULL; 448842b42dfSAlex Bennée } 449842b42dfSAlex Bennée 450842b42dfSAlex Bennée static int gdb_read_register(CPUState *cpu, GByteArray *buf, int reg) 451842b42dfSAlex Bennée { 452842b42dfSAlex Bennée CPUClass *cc = CPU_GET_CLASS(cpu); 453842b42dfSAlex Bennée CPUArchState *env = cpu->env_ptr; 454842b42dfSAlex Bennée GDBRegisterState *r; 455842b42dfSAlex Bennée 456842b42dfSAlex Bennée if (reg < cc->gdb_num_core_regs) { 457842b42dfSAlex Bennée return cc->gdb_read_register(cpu, buf, reg); 458842b42dfSAlex Bennée } 459842b42dfSAlex Bennée 460842b42dfSAlex Bennée for (r = cpu->gdb_regs; r; r = r->next) { 461842b42dfSAlex Bennée if (r->base_reg <= reg && reg < r->base_reg + r->num_regs) { 462842b42dfSAlex Bennée return r->get_reg(env, buf, reg - r->base_reg); 463842b42dfSAlex Bennée } 464842b42dfSAlex Bennée } 465842b42dfSAlex Bennée return 0; 466842b42dfSAlex Bennée } 467842b42dfSAlex Bennée 468842b42dfSAlex Bennée static int gdb_write_register(CPUState *cpu, uint8_t *mem_buf, int reg) 469842b42dfSAlex Bennée { 470842b42dfSAlex Bennée CPUClass *cc = CPU_GET_CLASS(cpu); 471842b42dfSAlex Bennée CPUArchState *env = cpu->env_ptr; 472842b42dfSAlex Bennée GDBRegisterState *r; 473842b42dfSAlex Bennée 474842b42dfSAlex Bennée if (reg < cc->gdb_num_core_regs) { 475842b42dfSAlex Bennée return cc->gdb_write_register(cpu, mem_buf, reg); 476842b42dfSAlex Bennée } 477842b42dfSAlex Bennée 478842b42dfSAlex Bennée for (r = cpu->gdb_regs; r; r = r->next) { 479842b42dfSAlex Bennée if (r->base_reg <= reg && reg < r->base_reg + r->num_regs) { 480842b42dfSAlex Bennée return r->set_reg(env, mem_buf, reg - r->base_reg); 481842b42dfSAlex Bennée } 482842b42dfSAlex Bennée } 483842b42dfSAlex Bennée return 0; 484842b42dfSAlex Bennée } 485842b42dfSAlex Bennée 486842b42dfSAlex Bennée /* Register a supplemental set of CPU registers. If g_pos is nonzero it 487842b42dfSAlex Bennée specifies the first register number and these registers are included in 488842b42dfSAlex Bennée a standard "g" packet. Direction is relative to gdb, i.e. get_reg is 489842b42dfSAlex Bennée gdb reading a CPU register, and set_reg is gdb modifying a CPU register. 490842b42dfSAlex Bennée */ 491842b42dfSAlex Bennée 492842b42dfSAlex Bennée void gdb_register_coprocessor(CPUState *cpu, 493842b42dfSAlex Bennée gdb_get_reg_cb get_reg, gdb_set_reg_cb set_reg, 494842b42dfSAlex Bennée int num_regs, const char *xml, int g_pos) 495842b42dfSAlex Bennée { 496842b42dfSAlex Bennée GDBRegisterState *s; 497842b42dfSAlex Bennée GDBRegisterState **p; 498842b42dfSAlex Bennée 499842b42dfSAlex Bennée p = &cpu->gdb_regs; 500842b42dfSAlex Bennée while (*p) { 501842b42dfSAlex Bennée /* Check for duplicates. */ 502842b42dfSAlex Bennée if (strcmp((*p)->xml, xml) == 0) 503842b42dfSAlex Bennée return; 504842b42dfSAlex Bennée p = &(*p)->next; 505842b42dfSAlex Bennée } 506842b42dfSAlex Bennée 507842b42dfSAlex Bennée s = g_new0(GDBRegisterState, 1); 508842b42dfSAlex Bennée s->base_reg = cpu->gdb_num_regs; 509842b42dfSAlex Bennée s->num_regs = num_regs; 510842b42dfSAlex Bennée s->get_reg = get_reg; 511842b42dfSAlex Bennée s->set_reg = set_reg; 512842b42dfSAlex Bennée s->xml = xml; 513842b42dfSAlex Bennée 514842b42dfSAlex Bennée /* Add to end of list. */ 515842b42dfSAlex Bennée cpu->gdb_num_regs += num_regs; 516842b42dfSAlex Bennée *p = s; 517842b42dfSAlex Bennée if (g_pos) { 518842b42dfSAlex Bennée if (g_pos != s->base_reg) { 519842b42dfSAlex Bennée error_report("Error: Bad gdb register numbering for '%s', " 520842b42dfSAlex Bennée "expected %d got %d", xml, g_pos, s->base_reg); 521842b42dfSAlex Bennée } else { 522842b42dfSAlex Bennée cpu->gdb_num_g_regs = cpu->gdb_num_regs; 523842b42dfSAlex Bennée } 524842b42dfSAlex Bennée } 525842b42dfSAlex Bennée } 526842b42dfSAlex Bennée 527842b42dfSAlex Bennée static void gdb_process_breakpoint_remove_all(GDBProcess *p) 528842b42dfSAlex Bennée { 529842b42dfSAlex Bennée CPUState *cpu = get_first_cpu_in_process(p); 530842b42dfSAlex Bennée 531842b42dfSAlex Bennée while (cpu) { 532ae7467b1SAlex Bennée gdb_breakpoint_remove_all(cpu); 533842b42dfSAlex Bennée cpu = gdb_next_cpu_in_process(cpu); 534842b42dfSAlex Bennée } 535842b42dfSAlex Bennée } 536842b42dfSAlex Bennée 537842b42dfSAlex Bennée 538b428ad12SAlex Bennée static void gdb_set_cpu_pc(vaddr pc) 539842b42dfSAlex Bennée { 540842b42dfSAlex Bennée CPUState *cpu = gdbserver_state.c_cpu; 541842b42dfSAlex Bennée 542842b42dfSAlex Bennée cpu_synchronize_state(cpu); 543842b42dfSAlex Bennée cpu_set_pc(cpu, pc); 544842b42dfSAlex Bennée } 545842b42dfSAlex Bennée 54636e067b2SAlex Bennée void gdb_append_thread_id(CPUState *cpu, GString *buf) 547842b42dfSAlex Bennée { 548842b42dfSAlex Bennée if (gdbserver_state.multiprocess) { 549842b42dfSAlex Bennée g_string_append_printf(buf, "p%02x.%02x", 55036e067b2SAlex Bennée gdb_get_cpu_pid(cpu), gdb_get_cpu_index(cpu)); 551842b42dfSAlex Bennée } else { 55236e067b2SAlex Bennée g_string_append_printf(buf, "%02x", gdb_get_cpu_index(cpu)); 553842b42dfSAlex Bennée } 554842b42dfSAlex Bennée } 555842b42dfSAlex Bennée 556842b42dfSAlex Bennée static GDBThreadIdKind read_thread_id(const char *buf, const char **end_buf, 557842b42dfSAlex Bennée uint32_t *pid, uint32_t *tid) 558842b42dfSAlex Bennée { 559842b42dfSAlex Bennée unsigned long p, t; 560842b42dfSAlex Bennée int ret; 561842b42dfSAlex Bennée 562842b42dfSAlex Bennée if (*buf == 'p') { 563842b42dfSAlex Bennée buf++; 564842b42dfSAlex Bennée ret = qemu_strtoul(buf, &buf, 16, &p); 565842b42dfSAlex Bennée 566842b42dfSAlex Bennée if (ret) { 567842b42dfSAlex Bennée return GDB_READ_THREAD_ERR; 568842b42dfSAlex Bennée } 569842b42dfSAlex Bennée 570842b42dfSAlex Bennée /* Skip '.' */ 571842b42dfSAlex Bennée buf++; 572842b42dfSAlex Bennée } else { 573842b42dfSAlex Bennée p = 1; 574842b42dfSAlex Bennée } 575842b42dfSAlex Bennée 576842b42dfSAlex Bennée ret = qemu_strtoul(buf, &buf, 16, &t); 577842b42dfSAlex Bennée 578842b42dfSAlex Bennée if (ret) { 579842b42dfSAlex Bennée return GDB_READ_THREAD_ERR; 580842b42dfSAlex Bennée } 581842b42dfSAlex Bennée 582842b42dfSAlex Bennée *end_buf = buf; 583842b42dfSAlex Bennée 584842b42dfSAlex Bennée if (p == -1) { 585842b42dfSAlex Bennée return GDB_ALL_PROCESSES; 586842b42dfSAlex Bennée } 587842b42dfSAlex Bennée 588842b42dfSAlex Bennée if (pid) { 589842b42dfSAlex Bennée *pid = p; 590842b42dfSAlex Bennée } 591842b42dfSAlex Bennée 592842b42dfSAlex Bennée if (t == -1) { 593842b42dfSAlex Bennée return GDB_ALL_THREADS; 594842b42dfSAlex Bennée } 595842b42dfSAlex Bennée 596842b42dfSAlex Bennée if (tid) { 597842b42dfSAlex Bennée *tid = t; 598842b42dfSAlex Bennée } 599842b42dfSAlex Bennée 600842b42dfSAlex Bennée return GDB_ONE_THREAD; 601842b42dfSAlex Bennée } 602842b42dfSAlex Bennée 603842b42dfSAlex Bennée /** 604842b42dfSAlex Bennée * gdb_handle_vcont - Parses and handles a vCont packet. 605842b42dfSAlex Bennée * returns -ENOTSUP if a command is unsupported, -EINVAL or -ERANGE if there is 606842b42dfSAlex Bennée * a format error, 0 on success. 607842b42dfSAlex Bennée */ 608842b42dfSAlex Bennée static int gdb_handle_vcont(const char *p) 609842b42dfSAlex Bennée { 610842b42dfSAlex Bennée int res, signal = 0; 611842b42dfSAlex Bennée char cur_action; 612842b42dfSAlex Bennée char *newstates; 613842b42dfSAlex Bennée unsigned long tmp; 614842b42dfSAlex Bennée uint32_t pid, tid; 615842b42dfSAlex Bennée GDBProcess *process; 616842b42dfSAlex Bennée CPUState *cpu; 617842b42dfSAlex Bennée GDBThreadIdKind kind; 6187ea0c33dSAlex Bennée unsigned int max_cpus = gdb_get_max_cpus(); 619842b42dfSAlex Bennée /* uninitialised CPUs stay 0 */ 620842b42dfSAlex Bennée newstates = g_new0(char, max_cpus); 621842b42dfSAlex Bennée 622842b42dfSAlex Bennée /* mark valid CPUs with 1 */ 623842b42dfSAlex Bennée CPU_FOREACH(cpu) { 624842b42dfSAlex Bennée newstates[cpu->cpu_index] = 1; 625842b42dfSAlex Bennée } 626842b42dfSAlex Bennée 627842b42dfSAlex Bennée /* 628842b42dfSAlex Bennée * res keeps track of what error we are returning, with -ENOTSUP meaning 629842b42dfSAlex Bennée * that the command is unknown or unsupported, thus returning an empty 630842b42dfSAlex Bennée * packet, while -EINVAL and -ERANGE cause an E22 packet, due to invalid, 631842b42dfSAlex Bennée * or incorrect parameters passed. 632842b42dfSAlex Bennée */ 633842b42dfSAlex Bennée res = 0; 634842b42dfSAlex Bennée while (*p) { 635842b42dfSAlex Bennée if (*p++ != ';') { 636842b42dfSAlex Bennée res = -ENOTSUP; 637842b42dfSAlex Bennée goto out; 638842b42dfSAlex Bennée } 639842b42dfSAlex Bennée 640842b42dfSAlex Bennée cur_action = *p++; 641842b42dfSAlex Bennée if (cur_action == 'C' || cur_action == 'S') { 642842b42dfSAlex Bennée cur_action = qemu_tolower(cur_action); 643842b42dfSAlex Bennée res = qemu_strtoul(p, &p, 16, &tmp); 644842b42dfSAlex Bennée if (res) { 645842b42dfSAlex Bennée goto out; 646842b42dfSAlex Bennée } 647842b42dfSAlex Bennée signal = gdb_signal_to_target(tmp); 648842b42dfSAlex Bennée } else if (cur_action != 'c' && cur_action != 's') { 649842b42dfSAlex Bennée /* unknown/invalid/unsupported command */ 650842b42dfSAlex Bennée res = -ENOTSUP; 651842b42dfSAlex Bennée goto out; 652842b42dfSAlex Bennée } 653842b42dfSAlex Bennée 654842b42dfSAlex Bennée if (*p == '\0' || *p == ';') { 655842b42dfSAlex Bennée /* 656842b42dfSAlex Bennée * No thread specifier, action is on "all threads". The 657842b42dfSAlex Bennée * specification is unclear regarding the process to act on. We 658842b42dfSAlex Bennée * choose all processes. 659842b42dfSAlex Bennée */ 660842b42dfSAlex Bennée kind = GDB_ALL_PROCESSES; 661842b42dfSAlex Bennée } else if (*p++ == ':') { 662842b42dfSAlex Bennée kind = read_thread_id(p, &p, &pid, &tid); 663842b42dfSAlex Bennée } else { 664842b42dfSAlex Bennée res = -ENOTSUP; 665842b42dfSAlex Bennée goto out; 666842b42dfSAlex Bennée } 667842b42dfSAlex Bennée 668842b42dfSAlex Bennée switch (kind) { 669842b42dfSAlex Bennée case GDB_READ_THREAD_ERR: 670842b42dfSAlex Bennée res = -EINVAL; 671842b42dfSAlex Bennée goto out; 672842b42dfSAlex Bennée 673842b42dfSAlex Bennée case GDB_ALL_PROCESSES: 674842b42dfSAlex Bennée cpu = gdb_first_attached_cpu(); 675842b42dfSAlex Bennée while (cpu) { 676842b42dfSAlex Bennée if (newstates[cpu->cpu_index] == 1) { 677842b42dfSAlex Bennée newstates[cpu->cpu_index] = cur_action; 678842b42dfSAlex Bennée } 679842b42dfSAlex Bennée 680842b42dfSAlex Bennée cpu = gdb_next_attached_cpu(cpu); 681842b42dfSAlex Bennée } 682842b42dfSAlex Bennée break; 683842b42dfSAlex Bennée 684842b42dfSAlex Bennée case GDB_ALL_THREADS: 685842b42dfSAlex Bennée process = gdb_get_process(pid); 686842b42dfSAlex Bennée 687842b42dfSAlex Bennée if (!process->attached) { 688842b42dfSAlex Bennée res = -EINVAL; 689842b42dfSAlex Bennée goto out; 690842b42dfSAlex Bennée } 691842b42dfSAlex Bennée 692842b42dfSAlex Bennée cpu = get_first_cpu_in_process(process); 693842b42dfSAlex Bennée while (cpu) { 694842b42dfSAlex Bennée if (newstates[cpu->cpu_index] == 1) { 695842b42dfSAlex Bennée newstates[cpu->cpu_index] = cur_action; 696842b42dfSAlex Bennée } 697842b42dfSAlex Bennée 698842b42dfSAlex Bennée cpu = gdb_next_cpu_in_process(cpu); 699842b42dfSAlex Bennée } 700842b42dfSAlex Bennée break; 701842b42dfSAlex Bennée 702842b42dfSAlex Bennée case GDB_ONE_THREAD: 703842b42dfSAlex Bennée cpu = gdb_get_cpu(pid, tid); 704842b42dfSAlex Bennée 705842b42dfSAlex Bennée /* invalid CPU/thread specified */ 706842b42dfSAlex Bennée if (!cpu) { 707842b42dfSAlex Bennée res = -EINVAL; 708842b42dfSAlex Bennée goto out; 709842b42dfSAlex Bennée } 710842b42dfSAlex Bennée 711842b42dfSAlex Bennée /* only use if no previous match occourred */ 712842b42dfSAlex Bennée if (newstates[cpu->cpu_index] == 1) { 713842b42dfSAlex Bennée newstates[cpu->cpu_index] = cur_action; 714842b42dfSAlex Bennée } 715842b42dfSAlex Bennée break; 716842b42dfSAlex Bennée } 717842b42dfSAlex Bennée } 718842b42dfSAlex Bennée gdbserver_state.signal = signal; 719842b42dfSAlex Bennée gdb_continue_partial(newstates); 720842b42dfSAlex Bennée 721842b42dfSAlex Bennée out: 722842b42dfSAlex Bennée g_free(newstates); 723842b42dfSAlex Bennée 724842b42dfSAlex Bennée return res; 725842b42dfSAlex Bennée } 726842b42dfSAlex Bennée 727842b42dfSAlex Bennée static const char *cmd_next_param(const char *param, const char delimiter) 728842b42dfSAlex Bennée { 729842b42dfSAlex Bennée static const char all_delimiters[] = ",;:="; 730842b42dfSAlex Bennée char curr_delimiters[2] = {0}; 731842b42dfSAlex Bennée const char *delimiters; 732842b42dfSAlex Bennée 733842b42dfSAlex Bennée if (delimiter == '?') { 734842b42dfSAlex Bennée delimiters = all_delimiters; 735842b42dfSAlex Bennée } else if (delimiter == '0') { 736842b42dfSAlex Bennée return strchr(param, '\0'); 737842b42dfSAlex Bennée } else if (delimiter == '.' && *param) { 738842b42dfSAlex Bennée return param + 1; 739842b42dfSAlex Bennée } else { 740842b42dfSAlex Bennée curr_delimiters[0] = delimiter; 741842b42dfSAlex Bennée delimiters = curr_delimiters; 742842b42dfSAlex Bennée } 743842b42dfSAlex Bennée 744842b42dfSAlex Bennée param += strcspn(param, delimiters); 745842b42dfSAlex Bennée if (*param) { 746842b42dfSAlex Bennée param++; 747842b42dfSAlex Bennée } 748842b42dfSAlex Bennée return param; 749842b42dfSAlex Bennée } 750842b42dfSAlex Bennée 751842b42dfSAlex Bennée static int cmd_parse_params(const char *data, const char *schema, 752842b42dfSAlex Bennée GArray *params) 753842b42dfSAlex Bennée { 754842b42dfSAlex Bennée const char *curr_schema, *curr_data; 755842b42dfSAlex Bennée 756842b42dfSAlex Bennée g_assert(schema); 757842b42dfSAlex Bennée g_assert(params->len == 0); 758842b42dfSAlex Bennée 759842b42dfSAlex Bennée curr_schema = schema; 760842b42dfSAlex Bennée curr_data = data; 761842b42dfSAlex Bennée while (curr_schema[0] && curr_schema[1] && *curr_data) { 762842b42dfSAlex Bennée GdbCmdVariant this_param; 763842b42dfSAlex Bennée 764842b42dfSAlex Bennée switch (curr_schema[0]) { 765842b42dfSAlex Bennée case 'l': 766842b42dfSAlex Bennée if (qemu_strtoul(curr_data, &curr_data, 16, 767842b42dfSAlex Bennée &this_param.val_ul)) { 768842b42dfSAlex Bennée return -EINVAL; 769842b42dfSAlex Bennée } 770842b42dfSAlex Bennée curr_data = cmd_next_param(curr_data, curr_schema[1]); 771842b42dfSAlex Bennée g_array_append_val(params, this_param); 772842b42dfSAlex Bennée break; 773842b42dfSAlex Bennée case 'L': 774842b42dfSAlex Bennée if (qemu_strtou64(curr_data, &curr_data, 16, 775842b42dfSAlex Bennée (uint64_t *)&this_param.val_ull)) { 776842b42dfSAlex Bennée return -EINVAL; 777842b42dfSAlex Bennée } 778842b42dfSAlex Bennée curr_data = cmd_next_param(curr_data, curr_schema[1]); 779842b42dfSAlex Bennée g_array_append_val(params, this_param); 780842b42dfSAlex Bennée break; 781842b42dfSAlex Bennée case 's': 782842b42dfSAlex Bennée this_param.data = curr_data; 783842b42dfSAlex Bennée curr_data = cmd_next_param(curr_data, curr_schema[1]); 784842b42dfSAlex Bennée g_array_append_val(params, this_param); 785842b42dfSAlex Bennée break; 786842b42dfSAlex Bennée case 'o': 787842b42dfSAlex Bennée this_param.opcode = *(uint8_t *)curr_data; 788842b42dfSAlex Bennée curr_data = cmd_next_param(curr_data, curr_schema[1]); 789842b42dfSAlex Bennée g_array_append_val(params, this_param); 790842b42dfSAlex Bennée break; 791842b42dfSAlex Bennée case 't': 792842b42dfSAlex Bennée this_param.thread_id.kind = 793842b42dfSAlex Bennée read_thread_id(curr_data, &curr_data, 794842b42dfSAlex Bennée &this_param.thread_id.pid, 795842b42dfSAlex Bennée &this_param.thread_id.tid); 796842b42dfSAlex Bennée curr_data = cmd_next_param(curr_data, curr_schema[1]); 797842b42dfSAlex Bennée g_array_append_val(params, this_param); 798842b42dfSAlex Bennée break; 799842b42dfSAlex Bennée case '?': 800842b42dfSAlex Bennée curr_data = cmd_next_param(curr_data, curr_schema[1]); 801842b42dfSAlex Bennée break; 802842b42dfSAlex Bennée default: 803842b42dfSAlex Bennée return -EINVAL; 804842b42dfSAlex Bennée } 805842b42dfSAlex Bennée curr_schema += 2; 806842b42dfSAlex Bennée } 807842b42dfSAlex Bennée 808842b42dfSAlex Bennée return 0; 809842b42dfSAlex Bennée } 810842b42dfSAlex Bennée 811842b42dfSAlex Bennée typedef void (*GdbCmdHandler)(GArray *params, void *user_ctx); 812842b42dfSAlex Bennée 813842b42dfSAlex Bennée /* 814842b42dfSAlex Bennée * cmd_startswith -> cmd is compared using startswith 815842b42dfSAlex Bennée * 816842b42dfSAlex Bennée * 817842b42dfSAlex Bennée * schema definitions: 818842b42dfSAlex Bennée * Each schema parameter entry consists of 2 chars, 819842b42dfSAlex Bennée * the first char represents the parameter type handling 820842b42dfSAlex Bennée * the second char represents the delimiter for the next parameter 821842b42dfSAlex Bennée * 822842b42dfSAlex Bennée * Currently supported schema types: 823842b42dfSAlex Bennée * 'l' -> unsigned long (stored in .val_ul) 824842b42dfSAlex Bennée * 'L' -> unsigned long long (stored in .val_ull) 825842b42dfSAlex Bennée * 's' -> string (stored in .data) 826842b42dfSAlex Bennée * 'o' -> single char (stored in .opcode) 827842b42dfSAlex Bennée * 't' -> thread id (stored in .thread_id) 828842b42dfSAlex Bennée * '?' -> skip according to delimiter 829842b42dfSAlex Bennée * 830842b42dfSAlex Bennée * Currently supported delimiters: 831842b42dfSAlex Bennée * '?' -> Stop at any delimiter (",;:=\0") 832842b42dfSAlex Bennée * '0' -> Stop at "\0" 833842b42dfSAlex Bennée * '.' -> Skip 1 char unless reached "\0" 834842b42dfSAlex Bennée * Any other value is treated as the delimiter value itself 835842b42dfSAlex Bennée */ 836842b42dfSAlex Bennée typedef struct GdbCmdParseEntry { 837842b42dfSAlex Bennée GdbCmdHandler handler; 838842b42dfSAlex Bennée const char *cmd; 839842b42dfSAlex Bennée bool cmd_startswith; 840842b42dfSAlex Bennée const char *schema; 841842b42dfSAlex Bennée } GdbCmdParseEntry; 842842b42dfSAlex Bennée 843842b42dfSAlex Bennée static inline int startswith(const char *string, const char *pattern) 844842b42dfSAlex Bennée { 845842b42dfSAlex Bennée return !strncmp(string, pattern, strlen(pattern)); 846842b42dfSAlex Bennée } 847842b42dfSAlex Bennée 848842b42dfSAlex Bennée static int process_string_cmd(void *user_ctx, const char *data, 849842b42dfSAlex Bennée const GdbCmdParseEntry *cmds, int num_cmds) 850842b42dfSAlex Bennée { 851842b42dfSAlex Bennée int i; 852842b42dfSAlex Bennée g_autoptr(GArray) params = g_array_new(false, true, sizeof(GdbCmdVariant)); 853842b42dfSAlex Bennée 854842b42dfSAlex Bennée if (!cmds) { 855842b42dfSAlex Bennée return -1; 856842b42dfSAlex Bennée } 857842b42dfSAlex Bennée 858842b42dfSAlex Bennée for (i = 0; i < num_cmds; i++) { 859842b42dfSAlex Bennée const GdbCmdParseEntry *cmd = &cmds[i]; 860842b42dfSAlex Bennée g_assert(cmd->handler && cmd->cmd); 861842b42dfSAlex Bennée 862842b42dfSAlex Bennée if ((cmd->cmd_startswith && !startswith(data, cmd->cmd)) || 863842b42dfSAlex Bennée (!cmd->cmd_startswith && strcmp(cmd->cmd, data))) { 864842b42dfSAlex Bennée continue; 865842b42dfSAlex Bennée } 866842b42dfSAlex Bennée 867842b42dfSAlex Bennée if (cmd->schema) { 868842b42dfSAlex Bennée if (cmd_parse_params(&data[strlen(cmd->cmd)], 869842b42dfSAlex Bennée cmd->schema, params)) { 870842b42dfSAlex Bennée return -1; 871842b42dfSAlex Bennée } 872842b42dfSAlex Bennée } 873842b42dfSAlex Bennée 874842b42dfSAlex Bennée cmd->handler(params, user_ctx); 875842b42dfSAlex Bennée return 0; 876842b42dfSAlex Bennée } 877842b42dfSAlex Bennée 878842b42dfSAlex Bennée return -1; 879842b42dfSAlex Bennée } 880842b42dfSAlex Bennée 881842b42dfSAlex Bennée static void run_cmd_parser(const char *data, const GdbCmdParseEntry *cmd) 882842b42dfSAlex Bennée { 883842b42dfSAlex Bennée if (!data) { 884842b42dfSAlex Bennée return; 885842b42dfSAlex Bennée } 886842b42dfSAlex Bennée 887842b42dfSAlex Bennée g_string_set_size(gdbserver_state.str_buf, 0); 888842b42dfSAlex Bennée g_byte_array_set_size(gdbserver_state.mem_buf, 0); 889842b42dfSAlex Bennée 890842b42dfSAlex Bennée /* In case there was an error during the command parsing we must 891842b42dfSAlex Bennée * send a NULL packet to indicate the command is not supported */ 892842b42dfSAlex Bennée if (process_string_cmd(NULL, data, cmd, 1)) { 89336e067b2SAlex Bennée gdb_put_packet(""); 894842b42dfSAlex Bennée } 895842b42dfSAlex Bennée } 896842b42dfSAlex Bennée 897842b42dfSAlex Bennée static void handle_detach(GArray *params, void *user_ctx) 898842b42dfSAlex Bennée { 899842b42dfSAlex Bennée GDBProcess *process; 900842b42dfSAlex Bennée uint32_t pid = 1; 901842b42dfSAlex Bennée 902842b42dfSAlex Bennée if (gdbserver_state.multiprocess) { 903842b42dfSAlex Bennée if (!params->len) { 90436e067b2SAlex Bennée gdb_put_packet("E22"); 905842b42dfSAlex Bennée return; 906842b42dfSAlex Bennée } 907842b42dfSAlex Bennée 908842b42dfSAlex Bennée pid = get_param(params, 0)->val_ul; 909842b42dfSAlex Bennée } 910842b42dfSAlex Bennée 911842b42dfSAlex Bennée process = gdb_get_process(pid); 912842b42dfSAlex Bennée gdb_process_breakpoint_remove_all(process); 913842b42dfSAlex Bennée process->attached = false; 914842b42dfSAlex Bennée 915842b42dfSAlex Bennée if (pid == gdb_get_cpu_pid(gdbserver_state.c_cpu)) { 916842b42dfSAlex Bennée gdbserver_state.c_cpu = gdb_first_attached_cpu(); 917842b42dfSAlex Bennée } 918842b42dfSAlex Bennée 919842b42dfSAlex Bennée if (pid == gdb_get_cpu_pid(gdbserver_state.g_cpu)) { 920842b42dfSAlex Bennée gdbserver_state.g_cpu = gdb_first_attached_cpu(); 921842b42dfSAlex Bennée } 922842b42dfSAlex Bennée 923842b42dfSAlex Bennée if (!gdbserver_state.c_cpu) { 924842b42dfSAlex Bennée /* No more process attached */ 925842b42dfSAlex Bennée gdb_syscall_mode = GDB_SYS_DISABLED; 926842b42dfSAlex Bennée gdb_continue(); 927842b42dfSAlex Bennée } 92836e067b2SAlex Bennée gdb_put_packet("OK"); 929842b42dfSAlex Bennée } 930842b42dfSAlex Bennée 931842b42dfSAlex Bennée static void handle_thread_alive(GArray *params, void *user_ctx) 932842b42dfSAlex Bennée { 933842b42dfSAlex Bennée CPUState *cpu; 934842b42dfSAlex Bennée 935842b42dfSAlex Bennée if (!params->len) { 93636e067b2SAlex Bennée gdb_put_packet("E22"); 937842b42dfSAlex Bennée return; 938842b42dfSAlex Bennée } 939842b42dfSAlex Bennée 940842b42dfSAlex Bennée if (get_param(params, 0)->thread_id.kind == GDB_READ_THREAD_ERR) { 94136e067b2SAlex Bennée gdb_put_packet("E22"); 942842b42dfSAlex Bennée return; 943842b42dfSAlex Bennée } 944842b42dfSAlex Bennée 945842b42dfSAlex Bennée cpu = gdb_get_cpu(get_param(params, 0)->thread_id.pid, 946842b42dfSAlex Bennée get_param(params, 0)->thread_id.tid); 947842b42dfSAlex Bennée if (!cpu) { 94836e067b2SAlex Bennée gdb_put_packet("E22"); 949842b42dfSAlex Bennée return; 950842b42dfSAlex Bennée } 951842b42dfSAlex Bennée 95236e067b2SAlex Bennée gdb_put_packet("OK"); 953842b42dfSAlex Bennée } 954842b42dfSAlex Bennée 955842b42dfSAlex Bennée static void handle_continue(GArray *params, void *user_ctx) 956842b42dfSAlex Bennée { 957842b42dfSAlex Bennée if (params->len) { 958842b42dfSAlex Bennée gdb_set_cpu_pc(get_param(params, 0)->val_ull); 959842b42dfSAlex Bennée } 960842b42dfSAlex Bennée 961842b42dfSAlex Bennée gdbserver_state.signal = 0; 962842b42dfSAlex Bennée gdb_continue(); 963842b42dfSAlex Bennée } 964842b42dfSAlex Bennée 965842b42dfSAlex Bennée static void handle_cont_with_sig(GArray *params, void *user_ctx) 966842b42dfSAlex Bennée { 967842b42dfSAlex Bennée unsigned long signal = 0; 968842b42dfSAlex Bennée 969842b42dfSAlex Bennée /* 970842b42dfSAlex Bennée * Note: C sig;[addr] is currently unsupported and we simply 971842b42dfSAlex Bennée * omit the addr parameter 972842b42dfSAlex Bennée */ 973842b42dfSAlex Bennée if (params->len) { 974842b42dfSAlex Bennée signal = get_param(params, 0)->val_ul; 975842b42dfSAlex Bennée } 976842b42dfSAlex Bennée 977842b42dfSAlex Bennée gdbserver_state.signal = gdb_signal_to_target(signal); 978842b42dfSAlex Bennée if (gdbserver_state.signal == -1) { 979842b42dfSAlex Bennée gdbserver_state.signal = 0; 980842b42dfSAlex Bennée } 981842b42dfSAlex Bennée gdb_continue(); 982842b42dfSAlex Bennée } 983842b42dfSAlex Bennée 984842b42dfSAlex Bennée static void handle_set_thread(GArray *params, void *user_ctx) 985842b42dfSAlex Bennée { 986842b42dfSAlex Bennée CPUState *cpu; 987842b42dfSAlex Bennée 988842b42dfSAlex Bennée if (params->len != 2) { 98936e067b2SAlex Bennée gdb_put_packet("E22"); 990842b42dfSAlex Bennée return; 991842b42dfSAlex Bennée } 992842b42dfSAlex Bennée 993842b42dfSAlex Bennée if (get_param(params, 1)->thread_id.kind == GDB_READ_THREAD_ERR) { 99436e067b2SAlex Bennée gdb_put_packet("E22"); 995842b42dfSAlex Bennée return; 996842b42dfSAlex Bennée } 997842b42dfSAlex Bennée 998842b42dfSAlex Bennée if (get_param(params, 1)->thread_id.kind != GDB_ONE_THREAD) { 99936e067b2SAlex Bennée gdb_put_packet("OK"); 1000842b42dfSAlex Bennée return; 1001842b42dfSAlex Bennée } 1002842b42dfSAlex Bennée 1003842b42dfSAlex Bennée cpu = gdb_get_cpu(get_param(params, 1)->thread_id.pid, 1004842b42dfSAlex Bennée get_param(params, 1)->thread_id.tid); 1005842b42dfSAlex Bennée if (!cpu) { 100636e067b2SAlex Bennée gdb_put_packet("E22"); 1007842b42dfSAlex Bennée return; 1008842b42dfSAlex Bennée } 1009842b42dfSAlex Bennée 1010842b42dfSAlex Bennée /* 1011842b42dfSAlex Bennée * Note: This command is deprecated and modern gdb's will be using the 1012842b42dfSAlex Bennée * vCont command instead. 1013842b42dfSAlex Bennée */ 1014842b42dfSAlex Bennée switch (get_param(params, 0)->opcode) { 1015842b42dfSAlex Bennée case 'c': 1016842b42dfSAlex Bennée gdbserver_state.c_cpu = cpu; 101736e067b2SAlex Bennée gdb_put_packet("OK"); 1018842b42dfSAlex Bennée break; 1019842b42dfSAlex Bennée case 'g': 1020842b42dfSAlex Bennée gdbserver_state.g_cpu = cpu; 102136e067b2SAlex Bennée gdb_put_packet("OK"); 1022842b42dfSAlex Bennée break; 1023842b42dfSAlex Bennée default: 102436e067b2SAlex Bennée gdb_put_packet("E22"); 1025842b42dfSAlex Bennée break; 1026842b42dfSAlex Bennée } 1027842b42dfSAlex Bennée } 1028842b42dfSAlex Bennée 1029842b42dfSAlex Bennée static void handle_insert_bp(GArray *params, void *user_ctx) 1030842b42dfSAlex Bennée { 1031842b42dfSAlex Bennée int res; 1032842b42dfSAlex Bennée 1033842b42dfSAlex Bennée if (params->len != 3) { 103436e067b2SAlex Bennée gdb_put_packet("E22"); 1035842b42dfSAlex Bennée return; 1036842b42dfSAlex Bennée } 1037842b42dfSAlex Bennée 1038ae7467b1SAlex Bennée res = gdb_breakpoint_insert(gdbserver_state.c_cpu, 1039ae7467b1SAlex Bennée get_param(params, 0)->val_ul, 1040842b42dfSAlex Bennée get_param(params, 1)->val_ull, 1041842b42dfSAlex Bennée get_param(params, 2)->val_ull); 1042842b42dfSAlex Bennée if (res >= 0) { 104336e067b2SAlex Bennée gdb_put_packet("OK"); 1044842b42dfSAlex Bennée return; 1045842b42dfSAlex Bennée } else if (res == -ENOSYS) { 104636e067b2SAlex Bennée gdb_put_packet(""); 1047842b42dfSAlex Bennée return; 1048842b42dfSAlex Bennée } 1049842b42dfSAlex Bennée 105036e067b2SAlex Bennée gdb_put_packet("E22"); 1051842b42dfSAlex Bennée } 1052842b42dfSAlex Bennée 1053842b42dfSAlex Bennée static void handle_remove_bp(GArray *params, void *user_ctx) 1054842b42dfSAlex Bennée { 1055842b42dfSAlex Bennée int res; 1056842b42dfSAlex Bennée 1057842b42dfSAlex Bennée if (params->len != 3) { 105836e067b2SAlex Bennée gdb_put_packet("E22"); 1059842b42dfSAlex Bennée return; 1060842b42dfSAlex Bennée } 1061842b42dfSAlex Bennée 1062ae7467b1SAlex Bennée res = gdb_breakpoint_remove(gdbserver_state.c_cpu, 1063ae7467b1SAlex Bennée get_param(params, 0)->val_ul, 1064842b42dfSAlex Bennée get_param(params, 1)->val_ull, 1065842b42dfSAlex Bennée get_param(params, 2)->val_ull); 1066842b42dfSAlex Bennée if (res >= 0) { 106736e067b2SAlex Bennée gdb_put_packet("OK"); 1068842b42dfSAlex Bennée return; 1069842b42dfSAlex Bennée } else if (res == -ENOSYS) { 107036e067b2SAlex Bennée gdb_put_packet(""); 1071842b42dfSAlex Bennée return; 1072842b42dfSAlex Bennée } 1073842b42dfSAlex Bennée 107436e067b2SAlex Bennée gdb_put_packet("E22"); 1075842b42dfSAlex Bennée } 1076842b42dfSAlex Bennée 1077842b42dfSAlex Bennée /* 1078842b42dfSAlex Bennée * handle_set/get_reg 1079842b42dfSAlex Bennée * 1080842b42dfSAlex Bennée * Older gdb are really dumb, and don't use 'G/g' if 'P/p' is available. 1081842b42dfSAlex Bennée * This works, but can be very slow. Anything new enough to understand 1082842b42dfSAlex Bennée * XML also knows how to use this properly. However to use this we 1083842b42dfSAlex Bennée * need to define a local XML file as well as be talking to a 1084842b42dfSAlex Bennée * reasonably modern gdb. Responding with an empty packet will cause 1085842b42dfSAlex Bennée * the remote gdb to fallback to older methods. 1086842b42dfSAlex Bennée */ 1087842b42dfSAlex Bennée 1088842b42dfSAlex Bennée static void handle_set_reg(GArray *params, void *user_ctx) 1089842b42dfSAlex Bennée { 1090842b42dfSAlex Bennée int reg_size; 1091842b42dfSAlex Bennée 1092842b42dfSAlex Bennée if (!gdb_has_xml) { 109336e067b2SAlex Bennée gdb_put_packet(""); 1094842b42dfSAlex Bennée return; 1095842b42dfSAlex Bennée } 1096842b42dfSAlex Bennée 1097842b42dfSAlex Bennée if (params->len != 2) { 109836e067b2SAlex Bennée gdb_put_packet("E22"); 1099842b42dfSAlex Bennée return; 1100842b42dfSAlex Bennée } 1101842b42dfSAlex Bennée 1102842b42dfSAlex Bennée reg_size = strlen(get_param(params, 1)->data) / 2; 110336e067b2SAlex Bennée gdb_hextomem(gdbserver_state.mem_buf, get_param(params, 1)->data, reg_size); 1104842b42dfSAlex Bennée gdb_write_register(gdbserver_state.g_cpu, gdbserver_state.mem_buf->data, 1105842b42dfSAlex Bennée get_param(params, 0)->val_ull); 110636e067b2SAlex Bennée gdb_put_packet("OK"); 1107842b42dfSAlex Bennée } 1108842b42dfSAlex Bennée 1109842b42dfSAlex Bennée static void handle_get_reg(GArray *params, void *user_ctx) 1110842b42dfSAlex Bennée { 1111842b42dfSAlex Bennée int reg_size; 1112842b42dfSAlex Bennée 1113842b42dfSAlex Bennée if (!gdb_has_xml) { 111436e067b2SAlex Bennée gdb_put_packet(""); 1115842b42dfSAlex Bennée return; 1116842b42dfSAlex Bennée } 1117842b42dfSAlex Bennée 1118842b42dfSAlex Bennée if (!params->len) { 111936e067b2SAlex Bennée gdb_put_packet("E14"); 1120842b42dfSAlex Bennée return; 1121842b42dfSAlex Bennée } 1122842b42dfSAlex Bennée 1123842b42dfSAlex Bennée reg_size = gdb_read_register(gdbserver_state.g_cpu, 1124842b42dfSAlex Bennée gdbserver_state.mem_buf, 1125842b42dfSAlex Bennée get_param(params, 0)->val_ull); 1126842b42dfSAlex Bennée if (!reg_size) { 112736e067b2SAlex Bennée gdb_put_packet("E14"); 1128842b42dfSAlex Bennée return; 1129842b42dfSAlex Bennée } else { 1130842b42dfSAlex Bennée g_byte_array_set_size(gdbserver_state.mem_buf, reg_size); 1131842b42dfSAlex Bennée } 1132842b42dfSAlex Bennée 113336e067b2SAlex Bennée gdb_memtohex(gdbserver_state.str_buf, 113436e067b2SAlex Bennée gdbserver_state.mem_buf->data, reg_size); 113536e067b2SAlex Bennée gdb_put_strbuf(); 1136842b42dfSAlex Bennée } 1137842b42dfSAlex Bennée 1138842b42dfSAlex Bennée static void handle_write_mem(GArray *params, void *user_ctx) 1139842b42dfSAlex Bennée { 1140842b42dfSAlex Bennée if (params->len != 3) { 114136e067b2SAlex Bennée gdb_put_packet("E22"); 1142842b42dfSAlex Bennée return; 1143842b42dfSAlex Bennée } 1144842b42dfSAlex Bennée 114536e067b2SAlex Bennée /* gdb_hextomem() reads 2*len bytes */ 1146842b42dfSAlex Bennée if (get_param(params, 1)->val_ull > 1147842b42dfSAlex Bennée strlen(get_param(params, 2)->data) / 2) { 114836e067b2SAlex Bennée gdb_put_packet("E22"); 1149842b42dfSAlex Bennée return; 1150842b42dfSAlex Bennée } 1151842b42dfSAlex Bennée 115236e067b2SAlex Bennée gdb_hextomem(gdbserver_state.mem_buf, get_param(params, 2)->data, 1153842b42dfSAlex Bennée get_param(params, 1)->val_ull); 1154589a5867SAlex Bennée if (gdb_target_memory_rw_debug(gdbserver_state.g_cpu, 1155842b42dfSAlex Bennée get_param(params, 0)->val_ull, 1156842b42dfSAlex Bennée gdbserver_state.mem_buf->data, 1157842b42dfSAlex Bennée gdbserver_state.mem_buf->len, true)) { 115836e067b2SAlex Bennée gdb_put_packet("E14"); 1159842b42dfSAlex Bennée return; 1160842b42dfSAlex Bennée } 1161842b42dfSAlex Bennée 116236e067b2SAlex Bennée gdb_put_packet("OK"); 1163842b42dfSAlex Bennée } 1164842b42dfSAlex Bennée 1165842b42dfSAlex Bennée static void handle_read_mem(GArray *params, void *user_ctx) 1166842b42dfSAlex Bennée { 1167842b42dfSAlex Bennée if (params->len != 2) { 116836e067b2SAlex Bennée gdb_put_packet("E22"); 1169842b42dfSAlex Bennée return; 1170842b42dfSAlex Bennée } 1171842b42dfSAlex Bennée 117236e067b2SAlex Bennée /* gdb_memtohex() doubles the required space */ 1173842b42dfSAlex Bennée if (get_param(params, 1)->val_ull > MAX_PACKET_LENGTH / 2) { 117436e067b2SAlex Bennée gdb_put_packet("E22"); 1175842b42dfSAlex Bennée return; 1176842b42dfSAlex Bennée } 1177842b42dfSAlex Bennée 1178842b42dfSAlex Bennée g_byte_array_set_size(gdbserver_state.mem_buf, 1179842b42dfSAlex Bennée get_param(params, 1)->val_ull); 1180842b42dfSAlex Bennée 1181589a5867SAlex Bennée if (gdb_target_memory_rw_debug(gdbserver_state.g_cpu, 1182842b42dfSAlex Bennée get_param(params, 0)->val_ull, 1183842b42dfSAlex Bennée gdbserver_state.mem_buf->data, 1184842b42dfSAlex Bennée gdbserver_state.mem_buf->len, false)) { 118536e067b2SAlex Bennée gdb_put_packet("E14"); 1186842b42dfSAlex Bennée return; 1187842b42dfSAlex Bennée } 1188842b42dfSAlex Bennée 118936e067b2SAlex Bennée gdb_memtohex(gdbserver_state.str_buf, gdbserver_state.mem_buf->data, 1190842b42dfSAlex Bennée gdbserver_state.mem_buf->len); 119136e067b2SAlex Bennée gdb_put_strbuf(); 1192842b42dfSAlex Bennée } 1193842b42dfSAlex Bennée 1194842b42dfSAlex Bennée static void handle_write_all_regs(GArray *params, void *user_ctx) 1195842b42dfSAlex Bennée { 1196842b42dfSAlex Bennée target_ulong addr, len; 1197842b42dfSAlex Bennée uint8_t *registers; 1198842b42dfSAlex Bennée int reg_size; 1199842b42dfSAlex Bennée 1200842b42dfSAlex Bennée if (!params->len) { 1201842b42dfSAlex Bennée return; 1202842b42dfSAlex Bennée } 1203842b42dfSAlex Bennée 1204842b42dfSAlex Bennée cpu_synchronize_state(gdbserver_state.g_cpu); 1205842b42dfSAlex Bennée len = strlen(get_param(params, 0)->data) / 2; 120636e067b2SAlex Bennée gdb_hextomem(gdbserver_state.mem_buf, get_param(params, 0)->data, len); 1207842b42dfSAlex Bennée registers = gdbserver_state.mem_buf->data; 1208842b42dfSAlex Bennée for (addr = 0; addr < gdbserver_state.g_cpu->gdb_num_g_regs && len > 0; 1209842b42dfSAlex Bennée addr++) { 1210842b42dfSAlex Bennée reg_size = gdb_write_register(gdbserver_state.g_cpu, registers, addr); 1211842b42dfSAlex Bennée len -= reg_size; 1212842b42dfSAlex Bennée registers += reg_size; 1213842b42dfSAlex Bennée } 121436e067b2SAlex Bennée gdb_put_packet("OK"); 1215842b42dfSAlex Bennée } 1216842b42dfSAlex Bennée 1217842b42dfSAlex Bennée static void handle_read_all_regs(GArray *params, void *user_ctx) 1218842b42dfSAlex Bennée { 1219842b42dfSAlex Bennée target_ulong addr, len; 1220842b42dfSAlex Bennée 1221842b42dfSAlex Bennée cpu_synchronize_state(gdbserver_state.g_cpu); 1222842b42dfSAlex Bennée g_byte_array_set_size(gdbserver_state.mem_buf, 0); 1223842b42dfSAlex Bennée len = 0; 1224842b42dfSAlex Bennée for (addr = 0; addr < gdbserver_state.g_cpu->gdb_num_g_regs; addr++) { 1225842b42dfSAlex Bennée len += gdb_read_register(gdbserver_state.g_cpu, 1226842b42dfSAlex Bennée gdbserver_state.mem_buf, 1227842b42dfSAlex Bennée addr); 1228842b42dfSAlex Bennée } 1229842b42dfSAlex Bennée g_assert(len == gdbserver_state.mem_buf->len); 1230842b42dfSAlex Bennée 123136e067b2SAlex Bennée gdb_memtohex(gdbserver_state.str_buf, gdbserver_state.mem_buf->data, len); 123236e067b2SAlex Bennée gdb_put_strbuf(); 1233842b42dfSAlex Bennée } 1234842b42dfSAlex Bennée 1235842b42dfSAlex Bennée static void handle_file_io(GArray *params, void *user_ctx) 1236842b42dfSAlex Bennée { 1237842b42dfSAlex Bennée if (params->len >= 1 && gdbserver_state.current_syscall_cb) { 1238842b42dfSAlex Bennée uint64_t ret; 1239842b42dfSAlex Bennée int err; 1240842b42dfSAlex Bennée 1241842b42dfSAlex Bennée ret = get_param(params, 0)->val_ull; 1242842b42dfSAlex Bennée if (params->len >= 2) { 1243842b42dfSAlex Bennée err = get_param(params, 1)->val_ull; 1244842b42dfSAlex Bennée } else { 1245842b42dfSAlex Bennée err = 0; 1246842b42dfSAlex Bennée } 1247842b42dfSAlex Bennée 1248842b42dfSAlex Bennée /* Convert GDB error numbers back to host error numbers. */ 1249842b42dfSAlex Bennée #define E(X) case GDB_E##X: err = E##X; break 1250842b42dfSAlex Bennée switch (err) { 1251842b42dfSAlex Bennée case 0: 1252842b42dfSAlex Bennée break; 1253842b42dfSAlex Bennée E(PERM); 1254842b42dfSAlex Bennée E(NOENT); 1255842b42dfSAlex Bennée E(INTR); 1256842b42dfSAlex Bennée E(BADF); 1257842b42dfSAlex Bennée E(ACCES); 1258842b42dfSAlex Bennée E(FAULT); 1259842b42dfSAlex Bennée E(BUSY); 1260842b42dfSAlex Bennée E(EXIST); 1261842b42dfSAlex Bennée E(NODEV); 1262842b42dfSAlex Bennée E(NOTDIR); 1263842b42dfSAlex Bennée E(ISDIR); 1264842b42dfSAlex Bennée E(INVAL); 1265842b42dfSAlex Bennée E(NFILE); 1266842b42dfSAlex Bennée E(MFILE); 1267842b42dfSAlex Bennée E(FBIG); 1268842b42dfSAlex Bennée E(NOSPC); 1269842b42dfSAlex Bennée E(SPIPE); 1270842b42dfSAlex Bennée E(ROFS); 1271842b42dfSAlex Bennée E(NAMETOOLONG); 1272842b42dfSAlex Bennée default: 1273842b42dfSAlex Bennée err = EINVAL; 1274842b42dfSAlex Bennée break; 1275842b42dfSAlex Bennée } 1276842b42dfSAlex Bennée #undef E 1277842b42dfSAlex Bennée 1278842b42dfSAlex Bennée gdbserver_state.current_syscall_cb(gdbserver_state.c_cpu, ret, err); 1279842b42dfSAlex Bennée gdbserver_state.current_syscall_cb = NULL; 1280842b42dfSAlex Bennée } 1281842b42dfSAlex Bennée 1282842b42dfSAlex Bennée if (params->len >= 3 && get_param(params, 2)->opcode == (uint8_t)'C') { 128336e067b2SAlex Bennée gdb_put_packet("T02"); 1284842b42dfSAlex Bennée return; 1285842b42dfSAlex Bennée } 1286842b42dfSAlex Bennée 1287842b42dfSAlex Bennée gdb_continue(); 1288842b42dfSAlex Bennée } 1289842b42dfSAlex Bennée 1290842b42dfSAlex Bennée static void handle_step(GArray *params, void *user_ctx) 1291842b42dfSAlex Bennée { 1292842b42dfSAlex Bennée if (params->len) { 1293b428ad12SAlex Bennée gdb_set_cpu_pc(get_param(params, 0)->val_ull); 1294842b42dfSAlex Bennée } 1295842b42dfSAlex Bennée 1296842b42dfSAlex Bennée cpu_single_step(gdbserver_state.c_cpu, gdbserver_state.sstep_flags); 1297842b42dfSAlex Bennée gdb_continue(); 1298842b42dfSAlex Bennée } 1299842b42dfSAlex Bennée 1300842b42dfSAlex Bennée static void handle_backward(GArray *params, void *user_ctx) 1301842b42dfSAlex Bennée { 1302505601d5SAlex Bennée if (!gdb_can_reverse()) { 130336e067b2SAlex Bennée gdb_put_packet("E22"); 1304842b42dfSAlex Bennée } 1305842b42dfSAlex Bennée if (params->len == 1) { 1306842b42dfSAlex Bennée switch (get_param(params, 0)->opcode) { 1307842b42dfSAlex Bennée case 's': 1308842b42dfSAlex Bennée if (replay_reverse_step()) { 1309842b42dfSAlex Bennée gdb_continue(); 1310842b42dfSAlex Bennée } else { 131136e067b2SAlex Bennée gdb_put_packet("E14"); 1312842b42dfSAlex Bennée } 1313842b42dfSAlex Bennée return; 1314842b42dfSAlex Bennée case 'c': 1315842b42dfSAlex Bennée if (replay_reverse_continue()) { 1316842b42dfSAlex Bennée gdb_continue(); 1317842b42dfSAlex Bennée } else { 131836e067b2SAlex Bennée gdb_put_packet("E14"); 1319842b42dfSAlex Bennée } 1320842b42dfSAlex Bennée return; 1321842b42dfSAlex Bennée } 1322842b42dfSAlex Bennée } 1323842b42dfSAlex Bennée 1324842b42dfSAlex Bennée /* Default invalid command */ 132536e067b2SAlex Bennée gdb_put_packet(""); 1326842b42dfSAlex Bennée } 1327842b42dfSAlex Bennée 1328842b42dfSAlex Bennée static void handle_v_cont_query(GArray *params, void *user_ctx) 1329842b42dfSAlex Bennée { 133036e067b2SAlex Bennée gdb_put_packet("vCont;c;C;s;S"); 1331842b42dfSAlex Bennée } 1332842b42dfSAlex Bennée 1333842b42dfSAlex Bennée static void handle_v_cont(GArray *params, void *user_ctx) 1334842b42dfSAlex Bennée { 1335842b42dfSAlex Bennée int res; 1336842b42dfSAlex Bennée 1337842b42dfSAlex Bennée if (!params->len) { 1338842b42dfSAlex Bennée return; 1339842b42dfSAlex Bennée } 1340842b42dfSAlex Bennée 1341842b42dfSAlex Bennée res = gdb_handle_vcont(get_param(params, 0)->data); 1342842b42dfSAlex Bennée if ((res == -EINVAL) || (res == -ERANGE)) { 134336e067b2SAlex Bennée gdb_put_packet("E22"); 1344842b42dfSAlex Bennée } else if (res) { 134536e067b2SAlex Bennée gdb_put_packet(""); 1346842b42dfSAlex Bennée } 1347842b42dfSAlex Bennée } 1348842b42dfSAlex Bennée 1349842b42dfSAlex Bennée static void handle_v_attach(GArray *params, void *user_ctx) 1350842b42dfSAlex Bennée { 1351842b42dfSAlex Bennée GDBProcess *process; 1352842b42dfSAlex Bennée CPUState *cpu; 1353842b42dfSAlex Bennée 1354842b42dfSAlex Bennée g_string_assign(gdbserver_state.str_buf, "E22"); 1355842b42dfSAlex Bennée if (!params->len) { 1356842b42dfSAlex Bennée goto cleanup; 1357842b42dfSAlex Bennée } 1358842b42dfSAlex Bennée 1359842b42dfSAlex Bennée process = gdb_get_process(get_param(params, 0)->val_ul); 1360842b42dfSAlex Bennée if (!process) { 1361842b42dfSAlex Bennée goto cleanup; 1362842b42dfSAlex Bennée } 1363842b42dfSAlex Bennée 1364842b42dfSAlex Bennée cpu = get_first_cpu_in_process(process); 1365842b42dfSAlex Bennée if (!cpu) { 1366842b42dfSAlex Bennée goto cleanup; 1367842b42dfSAlex Bennée } 1368842b42dfSAlex Bennée 1369842b42dfSAlex Bennée process->attached = true; 1370842b42dfSAlex Bennée gdbserver_state.g_cpu = cpu; 1371842b42dfSAlex Bennée gdbserver_state.c_cpu = cpu; 1372842b42dfSAlex Bennée 1373842b42dfSAlex Bennée g_string_printf(gdbserver_state.str_buf, "T%02xthread:", GDB_SIGNAL_TRAP); 1374842b42dfSAlex Bennée gdb_append_thread_id(cpu, gdbserver_state.str_buf); 1375842b42dfSAlex Bennée g_string_append_c(gdbserver_state.str_buf, ';'); 1376842b42dfSAlex Bennée cleanup: 137736e067b2SAlex Bennée gdb_put_strbuf(); 1378842b42dfSAlex Bennée } 1379842b42dfSAlex Bennée 1380842b42dfSAlex Bennée static void handle_v_kill(GArray *params, void *user_ctx) 1381842b42dfSAlex Bennée { 1382842b42dfSAlex Bennée /* Kill the target */ 138336e067b2SAlex Bennée gdb_put_packet("OK"); 1384842b42dfSAlex Bennée error_report("QEMU: Terminated via GDBstub"); 1385842b42dfSAlex Bennée gdb_exit(0); 1386842b42dfSAlex Bennée exit(0); 1387842b42dfSAlex Bennée } 1388842b42dfSAlex Bennée 1389842b42dfSAlex Bennée static const GdbCmdParseEntry gdb_v_commands_table[] = { 1390842b42dfSAlex Bennée /* Order is important if has same prefix */ 1391842b42dfSAlex Bennée { 1392842b42dfSAlex Bennée .handler = handle_v_cont_query, 1393842b42dfSAlex Bennée .cmd = "Cont?", 1394842b42dfSAlex Bennée .cmd_startswith = 1 1395842b42dfSAlex Bennée }, 1396842b42dfSAlex Bennée { 1397842b42dfSAlex Bennée .handler = handle_v_cont, 1398842b42dfSAlex Bennée .cmd = "Cont", 1399842b42dfSAlex Bennée .cmd_startswith = 1, 1400842b42dfSAlex Bennée .schema = "s0" 1401842b42dfSAlex Bennée }, 1402842b42dfSAlex Bennée { 1403842b42dfSAlex Bennée .handler = handle_v_attach, 1404842b42dfSAlex Bennée .cmd = "Attach;", 1405842b42dfSAlex Bennée .cmd_startswith = 1, 1406842b42dfSAlex Bennée .schema = "l0" 1407842b42dfSAlex Bennée }, 1408842b42dfSAlex Bennée { 1409842b42dfSAlex Bennée .handler = handle_v_kill, 1410842b42dfSAlex Bennée .cmd = "Kill;", 1411842b42dfSAlex Bennée .cmd_startswith = 1 1412842b42dfSAlex Bennée }, 1413842b42dfSAlex Bennée }; 1414842b42dfSAlex Bennée 1415842b42dfSAlex Bennée static void handle_v_commands(GArray *params, void *user_ctx) 1416842b42dfSAlex Bennée { 1417842b42dfSAlex Bennée if (!params->len) { 1418842b42dfSAlex Bennée return; 1419842b42dfSAlex Bennée } 1420842b42dfSAlex Bennée 1421842b42dfSAlex Bennée if (process_string_cmd(NULL, get_param(params, 0)->data, 1422842b42dfSAlex Bennée gdb_v_commands_table, 1423842b42dfSAlex Bennée ARRAY_SIZE(gdb_v_commands_table))) { 142436e067b2SAlex Bennée gdb_put_packet(""); 1425842b42dfSAlex Bennée } 1426842b42dfSAlex Bennée } 1427842b42dfSAlex Bennée 1428842b42dfSAlex Bennée static void handle_query_qemu_sstepbits(GArray *params, void *user_ctx) 1429842b42dfSAlex Bennée { 1430842b42dfSAlex Bennée g_string_printf(gdbserver_state.str_buf, "ENABLE=%x", SSTEP_ENABLE); 1431842b42dfSAlex Bennée 1432842b42dfSAlex Bennée if (gdbserver_state.supported_sstep_flags & SSTEP_NOIRQ) { 1433842b42dfSAlex Bennée g_string_append_printf(gdbserver_state.str_buf, ",NOIRQ=%x", 1434842b42dfSAlex Bennée SSTEP_NOIRQ); 1435842b42dfSAlex Bennée } 1436842b42dfSAlex Bennée 1437842b42dfSAlex Bennée if (gdbserver_state.supported_sstep_flags & SSTEP_NOTIMER) { 1438842b42dfSAlex Bennée g_string_append_printf(gdbserver_state.str_buf, ",NOTIMER=%x", 1439842b42dfSAlex Bennée SSTEP_NOTIMER); 1440842b42dfSAlex Bennée } 1441842b42dfSAlex Bennée 144236e067b2SAlex Bennée gdb_put_strbuf(); 1443842b42dfSAlex Bennée } 1444842b42dfSAlex Bennée 1445842b42dfSAlex Bennée static void handle_set_qemu_sstep(GArray *params, void *user_ctx) 1446842b42dfSAlex Bennée { 1447842b42dfSAlex Bennée int new_sstep_flags; 1448842b42dfSAlex Bennée 1449842b42dfSAlex Bennée if (!params->len) { 1450842b42dfSAlex Bennée return; 1451842b42dfSAlex Bennée } 1452842b42dfSAlex Bennée 1453842b42dfSAlex Bennée new_sstep_flags = get_param(params, 0)->val_ul; 1454842b42dfSAlex Bennée 1455842b42dfSAlex Bennée if (new_sstep_flags & ~gdbserver_state.supported_sstep_flags) { 145636e067b2SAlex Bennée gdb_put_packet("E22"); 1457842b42dfSAlex Bennée return; 1458842b42dfSAlex Bennée } 1459842b42dfSAlex Bennée 1460842b42dfSAlex Bennée gdbserver_state.sstep_flags = new_sstep_flags; 146136e067b2SAlex Bennée gdb_put_packet("OK"); 1462842b42dfSAlex Bennée } 1463842b42dfSAlex Bennée 1464842b42dfSAlex Bennée static void handle_query_qemu_sstep(GArray *params, void *user_ctx) 1465842b42dfSAlex Bennée { 1466842b42dfSAlex Bennée g_string_printf(gdbserver_state.str_buf, "0x%x", 1467842b42dfSAlex Bennée gdbserver_state.sstep_flags); 146836e067b2SAlex Bennée gdb_put_strbuf(); 1469842b42dfSAlex Bennée } 1470842b42dfSAlex Bennée 1471842b42dfSAlex Bennée static void handle_query_curr_tid(GArray *params, void *user_ctx) 1472842b42dfSAlex Bennée { 1473842b42dfSAlex Bennée CPUState *cpu; 1474842b42dfSAlex Bennée GDBProcess *process; 1475842b42dfSAlex Bennée 1476842b42dfSAlex Bennée /* 1477842b42dfSAlex Bennée * "Current thread" remains vague in the spec, so always return 1478842b42dfSAlex Bennée * the first thread of the current process (gdb returns the 1479842b42dfSAlex Bennée * first thread). 1480842b42dfSAlex Bennée */ 1481842b42dfSAlex Bennée process = gdb_get_cpu_process(gdbserver_state.g_cpu); 1482842b42dfSAlex Bennée cpu = get_first_cpu_in_process(process); 1483842b42dfSAlex Bennée g_string_assign(gdbserver_state.str_buf, "QC"); 1484842b42dfSAlex Bennée gdb_append_thread_id(cpu, gdbserver_state.str_buf); 148536e067b2SAlex Bennée gdb_put_strbuf(); 1486842b42dfSAlex Bennée } 1487842b42dfSAlex Bennée 1488842b42dfSAlex Bennée static void handle_query_threads(GArray *params, void *user_ctx) 1489842b42dfSAlex Bennée { 1490842b42dfSAlex Bennée if (!gdbserver_state.query_cpu) { 149136e067b2SAlex Bennée gdb_put_packet("l"); 1492842b42dfSAlex Bennée return; 1493842b42dfSAlex Bennée } 1494842b42dfSAlex Bennée 1495842b42dfSAlex Bennée g_string_assign(gdbserver_state.str_buf, "m"); 1496842b42dfSAlex Bennée gdb_append_thread_id(gdbserver_state.query_cpu, gdbserver_state.str_buf); 149736e067b2SAlex Bennée gdb_put_strbuf(); 1498842b42dfSAlex Bennée gdbserver_state.query_cpu = gdb_next_attached_cpu(gdbserver_state.query_cpu); 1499842b42dfSAlex Bennée } 1500842b42dfSAlex Bennée 1501842b42dfSAlex Bennée static void handle_query_first_threads(GArray *params, void *user_ctx) 1502842b42dfSAlex Bennée { 1503842b42dfSAlex Bennée gdbserver_state.query_cpu = gdb_first_attached_cpu(); 1504842b42dfSAlex Bennée handle_query_threads(params, user_ctx); 1505842b42dfSAlex Bennée } 1506842b42dfSAlex Bennée 1507842b42dfSAlex Bennée static void handle_query_thread_extra(GArray *params, void *user_ctx) 1508842b42dfSAlex Bennée { 1509842b42dfSAlex Bennée g_autoptr(GString) rs = g_string_new(NULL); 1510842b42dfSAlex Bennée CPUState *cpu; 1511842b42dfSAlex Bennée 1512842b42dfSAlex Bennée if (!params->len || 1513842b42dfSAlex Bennée get_param(params, 0)->thread_id.kind == GDB_READ_THREAD_ERR) { 151436e067b2SAlex Bennée gdb_put_packet("E22"); 1515842b42dfSAlex Bennée return; 1516842b42dfSAlex Bennée } 1517842b42dfSAlex Bennée 1518842b42dfSAlex Bennée cpu = gdb_get_cpu(get_param(params, 0)->thread_id.pid, 1519842b42dfSAlex Bennée get_param(params, 0)->thread_id.tid); 1520842b42dfSAlex Bennée if (!cpu) { 1521842b42dfSAlex Bennée return; 1522842b42dfSAlex Bennée } 1523842b42dfSAlex Bennée 1524842b42dfSAlex Bennée cpu_synchronize_state(cpu); 1525842b42dfSAlex Bennée 1526842b42dfSAlex Bennée if (gdbserver_state.multiprocess && (gdbserver_state.process_num > 1)) { 1527842b42dfSAlex Bennée /* Print the CPU model and name in multiprocess mode */ 1528842b42dfSAlex Bennée ObjectClass *oc = object_get_class(OBJECT(cpu)); 1529842b42dfSAlex Bennée const char *cpu_model = object_class_get_name(oc); 1530842b42dfSAlex Bennée const char *cpu_name = 1531842b42dfSAlex Bennée object_get_canonical_path_component(OBJECT(cpu)); 1532842b42dfSAlex Bennée g_string_printf(rs, "%s %s [%s]", cpu_model, cpu_name, 1533842b42dfSAlex Bennée cpu->halted ? "halted " : "running"); 1534842b42dfSAlex Bennée } else { 1535842b42dfSAlex Bennée g_string_printf(rs, "CPU#%d [%s]", cpu->cpu_index, 1536842b42dfSAlex Bennée cpu->halted ? "halted " : "running"); 1537842b42dfSAlex Bennée } 1538842b42dfSAlex Bennée trace_gdbstub_op_extra_info(rs->str); 153936e067b2SAlex Bennée gdb_memtohex(gdbserver_state.str_buf, (uint8_t *)rs->str, rs->len); 154036e067b2SAlex Bennée gdb_put_strbuf(); 1541842b42dfSAlex Bennée } 1542842b42dfSAlex Bennée 1543842b42dfSAlex Bennée static void handle_query_supported(GArray *params, void *user_ctx) 1544842b42dfSAlex Bennée { 1545842b42dfSAlex Bennée CPUClass *cc; 1546842b42dfSAlex Bennée 1547842b42dfSAlex Bennée g_string_printf(gdbserver_state.str_buf, "PacketSize=%x", MAX_PACKET_LENGTH); 1548842b42dfSAlex Bennée cc = CPU_GET_CLASS(first_cpu); 1549842b42dfSAlex Bennée if (cc->gdb_core_xml_file) { 1550842b42dfSAlex Bennée g_string_append(gdbserver_state.str_buf, ";qXfer:features:read+"); 1551842b42dfSAlex Bennée } 1552842b42dfSAlex Bennée 1553505601d5SAlex Bennée if (gdb_can_reverse()) { 1554842b42dfSAlex Bennée g_string_append(gdbserver_state.str_buf, 1555842b42dfSAlex Bennée ";ReverseStep+;ReverseContinue+"); 1556842b42dfSAlex Bennée } 1557842b42dfSAlex Bennée 1558842b42dfSAlex Bennée #ifdef CONFIG_USER_ONLY 1559842b42dfSAlex Bennée if (gdbserver_state.c_cpu->opaque) { 1560842b42dfSAlex Bennée g_string_append(gdbserver_state.str_buf, ";qXfer:auxv:read+"); 1561842b42dfSAlex Bennée } 1562842b42dfSAlex Bennée #endif 1563842b42dfSAlex Bennée 1564842b42dfSAlex Bennée if (params->len && 1565842b42dfSAlex Bennée strstr(get_param(params, 0)->data, "multiprocess+")) { 1566842b42dfSAlex Bennée gdbserver_state.multiprocess = true; 1567842b42dfSAlex Bennée } 1568842b42dfSAlex Bennée 1569842b42dfSAlex Bennée g_string_append(gdbserver_state.str_buf, ";vContSupported+;multiprocess+"); 157036e067b2SAlex Bennée gdb_put_strbuf(); 1571842b42dfSAlex Bennée } 1572842b42dfSAlex Bennée 1573842b42dfSAlex Bennée static void handle_query_xfer_features(GArray *params, void *user_ctx) 1574842b42dfSAlex Bennée { 1575842b42dfSAlex Bennée GDBProcess *process; 1576842b42dfSAlex Bennée CPUClass *cc; 1577842b42dfSAlex Bennée unsigned long len, total_len, addr; 1578842b42dfSAlex Bennée const char *xml; 1579842b42dfSAlex Bennée const char *p; 1580842b42dfSAlex Bennée 1581842b42dfSAlex Bennée if (params->len < 3) { 158236e067b2SAlex Bennée gdb_put_packet("E22"); 1583842b42dfSAlex Bennée return; 1584842b42dfSAlex Bennée } 1585842b42dfSAlex Bennée 1586842b42dfSAlex Bennée process = gdb_get_cpu_process(gdbserver_state.g_cpu); 1587842b42dfSAlex Bennée cc = CPU_GET_CLASS(gdbserver_state.g_cpu); 1588842b42dfSAlex Bennée if (!cc->gdb_core_xml_file) { 158936e067b2SAlex Bennée gdb_put_packet(""); 1590842b42dfSAlex Bennée return; 1591842b42dfSAlex Bennée } 1592842b42dfSAlex Bennée 1593842b42dfSAlex Bennée gdb_has_xml = true; 1594842b42dfSAlex Bennée p = get_param(params, 0)->data; 1595842b42dfSAlex Bennée xml = get_feature_xml(p, &p, process); 1596842b42dfSAlex Bennée if (!xml) { 159736e067b2SAlex Bennée gdb_put_packet("E00"); 1598842b42dfSAlex Bennée return; 1599842b42dfSAlex Bennée } 1600842b42dfSAlex Bennée 1601842b42dfSAlex Bennée addr = get_param(params, 1)->val_ul; 1602842b42dfSAlex Bennée len = get_param(params, 2)->val_ul; 1603842b42dfSAlex Bennée total_len = strlen(xml); 1604842b42dfSAlex Bennée if (addr > total_len) { 160536e067b2SAlex Bennée gdb_put_packet("E00"); 1606842b42dfSAlex Bennée return; 1607842b42dfSAlex Bennée } 1608842b42dfSAlex Bennée 1609842b42dfSAlex Bennée if (len > (MAX_PACKET_LENGTH - 5) / 2) { 1610842b42dfSAlex Bennée len = (MAX_PACKET_LENGTH - 5) / 2; 1611842b42dfSAlex Bennée } 1612842b42dfSAlex Bennée 1613842b42dfSAlex Bennée if (len < total_len - addr) { 1614842b42dfSAlex Bennée g_string_assign(gdbserver_state.str_buf, "m"); 161536e067b2SAlex Bennée gdb_memtox(gdbserver_state.str_buf, xml + addr, len); 1616842b42dfSAlex Bennée } else { 1617842b42dfSAlex Bennée g_string_assign(gdbserver_state.str_buf, "l"); 161836e067b2SAlex Bennée gdb_memtox(gdbserver_state.str_buf, xml + addr, total_len - addr); 1619842b42dfSAlex Bennée } 1620842b42dfSAlex Bennée 162136e067b2SAlex Bennée gdb_put_packet_binary(gdbserver_state.str_buf->str, 1622842b42dfSAlex Bennée gdbserver_state.str_buf->len, true); 1623842b42dfSAlex Bennée } 1624842b42dfSAlex Bennée 1625842b42dfSAlex Bennée static void handle_query_qemu_supported(GArray *params, void *user_ctx) 1626842b42dfSAlex Bennée { 1627842b42dfSAlex Bennée g_string_printf(gdbserver_state.str_buf, "sstepbits;sstep"); 1628842b42dfSAlex Bennée #ifndef CONFIG_USER_ONLY 1629842b42dfSAlex Bennée g_string_append(gdbserver_state.str_buf, ";PhyMemMode"); 1630842b42dfSAlex Bennée #endif 163136e067b2SAlex Bennée gdb_put_strbuf(); 1632842b42dfSAlex Bennée } 1633842b42dfSAlex Bennée 1634842b42dfSAlex Bennée static const GdbCmdParseEntry gdb_gen_query_set_common_table[] = { 1635842b42dfSAlex Bennée /* Order is important if has same prefix */ 1636842b42dfSAlex Bennée { 1637842b42dfSAlex Bennée .handler = handle_query_qemu_sstepbits, 1638842b42dfSAlex Bennée .cmd = "qemu.sstepbits", 1639842b42dfSAlex Bennée }, 1640842b42dfSAlex Bennée { 1641842b42dfSAlex Bennée .handler = handle_query_qemu_sstep, 1642842b42dfSAlex Bennée .cmd = "qemu.sstep", 1643842b42dfSAlex Bennée }, 1644842b42dfSAlex Bennée { 1645842b42dfSAlex Bennée .handler = handle_set_qemu_sstep, 1646842b42dfSAlex Bennée .cmd = "qemu.sstep=", 1647842b42dfSAlex Bennée .cmd_startswith = 1, 1648842b42dfSAlex Bennée .schema = "l0" 1649842b42dfSAlex Bennée }, 1650842b42dfSAlex Bennée }; 1651842b42dfSAlex Bennée 1652842b42dfSAlex Bennée static const GdbCmdParseEntry gdb_gen_query_table[] = { 1653842b42dfSAlex Bennée { 1654842b42dfSAlex Bennée .handler = handle_query_curr_tid, 1655842b42dfSAlex Bennée .cmd = "C", 1656842b42dfSAlex Bennée }, 1657842b42dfSAlex Bennée { 1658842b42dfSAlex Bennée .handler = handle_query_threads, 1659842b42dfSAlex Bennée .cmd = "sThreadInfo", 1660842b42dfSAlex Bennée }, 1661842b42dfSAlex Bennée { 1662842b42dfSAlex Bennée .handler = handle_query_first_threads, 1663842b42dfSAlex Bennée .cmd = "fThreadInfo", 1664842b42dfSAlex Bennée }, 1665842b42dfSAlex Bennée { 1666842b42dfSAlex Bennée .handler = handle_query_thread_extra, 1667842b42dfSAlex Bennée .cmd = "ThreadExtraInfo,", 1668842b42dfSAlex Bennée .cmd_startswith = 1, 1669842b42dfSAlex Bennée .schema = "t0" 1670842b42dfSAlex Bennée }, 1671842b42dfSAlex Bennée #ifdef CONFIG_USER_ONLY 1672842b42dfSAlex Bennée { 1673d96bf49bSAlex Bennée .handler = gdb_handle_query_offsets, 1674842b42dfSAlex Bennée .cmd = "Offsets", 1675842b42dfSAlex Bennée }, 1676842b42dfSAlex Bennée #else 1677842b42dfSAlex Bennée { 1678b6fa2ec2SAlex Bennée .handler = gdb_handle_query_rcmd, 1679842b42dfSAlex Bennée .cmd = "Rcmd,", 1680842b42dfSAlex Bennée .cmd_startswith = 1, 1681842b42dfSAlex Bennée .schema = "s0" 1682842b42dfSAlex Bennée }, 1683842b42dfSAlex Bennée #endif 1684842b42dfSAlex Bennée { 1685842b42dfSAlex Bennée .handler = handle_query_supported, 1686842b42dfSAlex Bennée .cmd = "Supported:", 1687842b42dfSAlex Bennée .cmd_startswith = 1, 1688842b42dfSAlex Bennée .schema = "s0" 1689842b42dfSAlex Bennée }, 1690842b42dfSAlex Bennée { 1691842b42dfSAlex Bennée .handler = handle_query_supported, 1692842b42dfSAlex Bennée .cmd = "Supported", 1693842b42dfSAlex Bennée .schema = "s0" 1694842b42dfSAlex Bennée }, 1695842b42dfSAlex Bennée { 1696842b42dfSAlex Bennée .handler = handle_query_xfer_features, 1697842b42dfSAlex Bennée .cmd = "Xfer:features:read:", 1698842b42dfSAlex Bennée .cmd_startswith = 1, 1699842b42dfSAlex Bennée .schema = "s:l,l0" 1700842b42dfSAlex Bennée }, 1701842b42dfSAlex Bennée #if defined(CONFIG_USER_ONLY) && defined(CONFIG_LINUX_USER) 1702842b42dfSAlex Bennée { 1703d96bf49bSAlex Bennée .handler = gdb_handle_query_xfer_auxv, 1704842b42dfSAlex Bennée .cmd = "Xfer:auxv:read::", 1705842b42dfSAlex Bennée .cmd_startswith = 1, 1706842b42dfSAlex Bennée .schema = "l,l0" 1707842b42dfSAlex Bennée }, 1708842b42dfSAlex Bennée #endif 1709842b42dfSAlex Bennée { 17108a2025b3SAlex Bennée .handler = gdb_handle_query_attached, 1711842b42dfSAlex Bennée .cmd = "Attached:", 1712842b42dfSAlex Bennée .cmd_startswith = 1 1713842b42dfSAlex Bennée }, 1714842b42dfSAlex Bennée { 17158a2025b3SAlex Bennée .handler = gdb_handle_query_attached, 1716842b42dfSAlex Bennée .cmd = "Attached", 1717842b42dfSAlex Bennée }, 1718842b42dfSAlex Bennée { 1719842b42dfSAlex Bennée .handler = handle_query_qemu_supported, 1720842b42dfSAlex Bennée .cmd = "qemu.Supported", 1721842b42dfSAlex Bennée }, 1722842b42dfSAlex Bennée #ifndef CONFIG_USER_ONLY 1723842b42dfSAlex Bennée { 1724589a5867SAlex Bennée .handler = gdb_handle_query_qemu_phy_mem_mode, 1725842b42dfSAlex Bennée .cmd = "qemu.PhyMemMode", 1726842b42dfSAlex Bennée }, 1727842b42dfSAlex Bennée #endif 1728842b42dfSAlex Bennée }; 1729842b42dfSAlex Bennée 1730842b42dfSAlex Bennée static const GdbCmdParseEntry gdb_gen_set_table[] = { 1731842b42dfSAlex Bennée /* Order is important if has same prefix */ 1732842b42dfSAlex Bennée { 1733842b42dfSAlex Bennée .handler = handle_set_qemu_sstep, 1734842b42dfSAlex Bennée .cmd = "qemu.sstep:", 1735842b42dfSAlex Bennée .cmd_startswith = 1, 1736842b42dfSAlex Bennée .schema = "l0" 1737842b42dfSAlex Bennée }, 1738842b42dfSAlex Bennée #ifndef CONFIG_USER_ONLY 1739842b42dfSAlex Bennée { 1740589a5867SAlex Bennée .handler = gdb_handle_set_qemu_phy_mem_mode, 1741842b42dfSAlex Bennée .cmd = "qemu.PhyMemMode:", 1742842b42dfSAlex Bennée .cmd_startswith = 1, 1743842b42dfSAlex Bennée .schema = "l0" 1744842b42dfSAlex Bennée }, 1745842b42dfSAlex Bennée #endif 1746842b42dfSAlex Bennée }; 1747842b42dfSAlex Bennée 1748842b42dfSAlex Bennée static void handle_gen_query(GArray *params, void *user_ctx) 1749842b42dfSAlex Bennée { 1750842b42dfSAlex Bennée if (!params->len) { 1751842b42dfSAlex Bennée return; 1752842b42dfSAlex Bennée } 1753842b42dfSAlex Bennée 1754842b42dfSAlex Bennée if (!process_string_cmd(NULL, get_param(params, 0)->data, 1755842b42dfSAlex Bennée gdb_gen_query_set_common_table, 1756842b42dfSAlex Bennée ARRAY_SIZE(gdb_gen_query_set_common_table))) { 1757842b42dfSAlex Bennée return; 1758842b42dfSAlex Bennée } 1759842b42dfSAlex Bennée 1760842b42dfSAlex Bennée if (process_string_cmd(NULL, get_param(params, 0)->data, 1761842b42dfSAlex Bennée gdb_gen_query_table, 1762842b42dfSAlex Bennée ARRAY_SIZE(gdb_gen_query_table))) { 176336e067b2SAlex Bennée gdb_put_packet(""); 1764842b42dfSAlex Bennée } 1765842b42dfSAlex Bennée } 1766842b42dfSAlex Bennée 1767842b42dfSAlex Bennée static void handle_gen_set(GArray *params, void *user_ctx) 1768842b42dfSAlex Bennée { 1769842b42dfSAlex Bennée if (!params->len) { 1770842b42dfSAlex Bennée return; 1771842b42dfSAlex Bennée } 1772842b42dfSAlex Bennée 1773842b42dfSAlex Bennée if (!process_string_cmd(NULL, get_param(params, 0)->data, 1774842b42dfSAlex Bennée gdb_gen_query_set_common_table, 1775842b42dfSAlex Bennée ARRAY_SIZE(gdb_gen_query_set_common_table))) { 1776842b42dfSAlex Bennée return; 1777842b42dfSAlex Bennée } 1778842b42dfSAlex Bennée 1779842b42dfSAlex Bennée if (process_string_cmd(NULL, get_param(params, 0)->data, 1780842b42dfSAlex Bennée gdb_gen_set_table, 1781842b42dfSAlex Bennée ARRAY_SIZE(gdb_gen_set_table))) { 178236e067b2SAlex Bennée gdb_put_packet(""); 1783842b42dfSAlex Bennée } 1784842b42dfSAlex Bennée } 1785842b42dfSAlex Bennée 1786842b42dfSAlex Bennée static void handle_target_halt(GArray *params, void *user_ctx) 1787842b42dfSAlex Bennée { 1788842b42dfSAlex Bennée g_string_printf(gdbserver_state.str_buf, "T%02xthread:", GDB_SIGNAL_TRAP); 1789842b42dfSAlex Bennée gdb_append_thread_id(gdbserver_state.c_cpu, gdbserver_state.str_buf); 1790842b42dfSAlex Bennée g_string_append_c(gdbserver_state.str_buf, ';'); 179136e067b2SAlex Bennée gdb_put_strbuf(); 1792842b42dfSAlex Bennée /* 1793842b42dfSAlex Bennée * Remove all the breakpoints when this query is issued, 1794842b42dfSAlex Bennée * because gdb is doing an initial connect and the state 1795842b42dfSAlex Bennée * should be cleaned up. 1796842b42dfSAlex Bennée */ 1797ae7467b1SAlex Bennée gdb_breakpoint_remove_all(gdbserver_state.c_cpu); 1798842b42dfSAlex Bennée } 1799842b42dfSAlex Bennée 1800842b42dfSAlex Bennée static int gdb_handle_packet(const char *line_buf) 1801842b42dfSAlex Bennée { 1802842b42dfSAlex Bennée const GdbCmdParseEntry *cmd_parser = NULL; 1803842b42dfSAlex Bennée 1804842b42dfSAlex Bennée trace_gdbstub_io_command(line_buf); 1805842b42dfSAlex Bennée 1806842b42dfSAlex Bennée switch (line_buf[0]) { 1807842b42dfSAlex Bennée case '!': 180836e067b2SAlex Bennée gdb_put_packet("OK"); 1809842b42dfSAlex Bennée break; 1810842b42dfSAlex Bennée case '?': 1811842b42dfSAlex Bennée { 1812842b42dfSAlex Bennée static const GdbCmdParseEntry target_halted_cmd_desc = { 1813842b42dfSAlex Bennée .handler = handle_target_halt, 1814842b42dfSAlex Bennée .cmd = "?", 1815842b42dfSAlex Bennée .cmd_startswith = 1 1816842b42dfSAlex Bennée }; 1817842b42dfSAlex Bennée cmd_parser = &target_halted_cmd_desc; 1818842b42dfSAlex Bennée } 1819842b42dfSAlex Bennée break; 1820842b42dfSAlex Bennée case 'c': 1821842b42dfSAlex Bennée { 1822842b42dfSAlex Bennée static const GdbCmdParseEntry continue_cmd_desc = { 1823842b42dfSAlex Bennée .handler = handle_continue, 1824842b42dfSAlex Bennée .cmd = "c", 1825842b42dfSAlex Bennée .cmd_startswith = 1, 1826842b42dfSAlex Bennée .schema = "L0" 1827842b42dfSAlex Bennée }; 1828842b42dfSAlex Bennée cmd_parser = &continue_cmd_desc; 1829842b42dfSAlex Bennée } 1830842b42dfSAlex Bennée break; 1831842b42dfSAlex Bennée case 'C': 1832842b42dfSAlex Bennée { 1833842b42dfSAlex Bennée static const GdbCmdParseEntry cont_with_sig_cmd_desc = { 1834842b42dfSAlex Bennée .handler = handle_cont_with_sig, 1835842b42dfSAlex Bennée .cmd = "C", 1836842b42dfSAlex Bennée .cmd_startswith = 1, 1837842b42dfSAlex Bennée .schema = "l0" 1838842b42dfSAlex Bennée }; 1839842b42dfSAlex Bennée cmd_parser = &cont_with_sig_cmd_desc; 1840842b42dfSAlex Bennée } 1841842b42dfSAlex Bennée break; 1842842b42dfSAlex Bennée case 'v': 1843842b42dfSAlex Bennée { 1844842b42dfSAlex Bennée static const GdbCmdParseEntry v_cmd_desc = { 1845842b42dfSAlex Bennée .handler = handle_v_commands, 1846842b42dfSAlex Bennée .cmd = "v", 1847842b42dfSAlex Bennée .cmd_startswith = 1, 1848842b42dfSAlex Bennée .schema = "s0" 1849842b42dfSAlex Bennée }; 1850842b42dfSAlex Bennée cmd_parser = &v_cmd_desc; 1851842b42dfSAlex Bennée } 1852842b42dfSAlex Bennée break; 1853842b42dfSAlex Bennée case 'k': 1854842b42dfSAlex Bennée /* Kill the target */ 1855842b42dfSAlex Bennée error_report("QEMU: Terminated via GDBstub"); 1856842b42dfSAlex Bennée gdb_exit(0); 1857842b42dfSAlex Bennée exit(0); 1858842b42dfSAlex Bennée case 'D': 1859842b42dfSAlex Bennée { 1860842b42dfSAlex Bennée static const GdbCmdParseEntry detach_cmd_desc = { 1861842b42dfSAlex Bennée .handler = handle_detach, 1862842b42dfSAlex Bennée .cmd = "D", 1863842b42dfSAlex Bennée .cmd_startswith = 1, 1864842b42dfSAlex Bennée .schema = "?.l0" 1865842b42dfSAlex Bennée }; 1866842b42dfSAlex Bennée cmd_parser = &detach_cmd_desc; 1867842b42dfSAlex Bennée } 1868842b42dfSAlex Bennée break; 1869842b42dfSAlex Bennée case 's': 1870842b42dfSAlex Bennée { 1871842b42dfSAlex Bennée static const GdbCmdParseEntry step_cmd_desc = { 1872842b42dfSAlex Bennée .handler = handle_step, 1873842b42dfSAlex Bennée .cmd = "s", 1874842b42dfSAlex Bennée .cmd_startswith = 1, 1875842b42dfSAlex Bennée .schema = "L0" 1876842b42dfSAlex Bennée }; 1877842b42dfSAlex Bennée cmd_parser = &step_cmd_desc; 1878842b42dfSAlex Bennée } 1879842b42dfSAlex Bennée break; 1880842b42dfSAlex Bennée case 'b': 1881842b42dfSAlex Bennée { 1882842b42dfSAlex Bennée static const GdbCmdParseEntry backward_cmd_desc = { 1883842b42dfSAlex Bennée .handler = handle_backward, 1884842b42dfSAlex Bennée .cmd = "b", 1885842b42dfSAlex Bennée .cmd_startswith = 1, 1886842b42dfSAlex Bennée .schema = "o0" 1887842b42dfSAlex Bennée }; 1888842b42dfSAlex Bennée cmd_parser = &backward_cmd_desc; 1889842b42dfSAlex Bennée } 1890842b42dfSAlex Bennée break; 1891842b42dfSAlex Bennée case 'F': 1892842b42dfSAlex Bennée { 1893842b42dfSAlex Bennée static const GdbCmdParseEntry file_io_cmd_desc = { 1894842b42dfSAlex Bennée .handler = handle_file_io, 1895842b42dfSAlex Bennée .cmd = "F", 1896842b42dfSAlex Bennée .cmd_startswith = 1, 1897842b42dfSAlex Bennée .schema = "L,L,o0" 1898842b42dfSAlex Bennée }; 1899842b42dfSAlex Bennée cmd_parser = &file_io_cmd_desc; 1900842b42dfSAlex Bennée } 1901842b42dfSAlex Bennée break; 1902842b42dfSAlex Bennée case 'g': 1903842b42dfSAlex Bennée { 1904842b42dfSAlex Bennée static const GdbCmdParseEntry read_all_regs_cmd_desc = { 1905842b42dfSAlex Bennée .handler = handle_read_all_regs, 1906842b42dfSAlex Bennée .cmd = "g", 1907842b42dfSAlex Bennée .cmd_startswith = 1 1908842b42dfSAlex Bennée }; 1909842b42dfSAlex Bennée cmd_parser = &read_all_regs_cmd_desc; 1910842b42dfSAlex Bennée } 1911842b42dfSAlex Bennée break; 1912842b42dfSAlex Bennée case 'G': 1913842b42dfSAlex Bennée { 1914842b42dfSAlex Bennée static const GdbCmdParseEntry write_all_regs_cmd_desc = { 1915842b42dfSAlex Bennée .handler = handle_write_all_regs, 1916842b42dfSAlex Bennée .cmd = "G", 1917842b42dfSAlex Bennée .cmd_startswith = 1, 1918842b42dfSAlex Bennée .schema = "s0" 1919842b42dfSAlex Bennée }; 1920842b42dfSAlex Bennée cmd_parser = &write_all_regs_cmd_desc; 1921842b42dfSAlex Bennée } 1922842b42dfSAlex Bennée break; 1923842b42dfSAlex Bennée case 'm': 1924842b42dfSAlex Bennée { 1925842b42dfSAlex Bennée static const GdbCmdParseEntry read_mem_cmd_desc = { 1926842b42dfSAlex Bennée .handler = handle_read_mem, 1927842b42dfSAlex Bennée .cmd = "m", 1928842b42dfSAlex Bennée .cmd_startswith = 1, 1929842b42dfSAlex Bennée .schema = "L,L0" 1930842b42dfSAlex Bennée }; 1931842b42dfSAlex Bennée cmd_parser = &read_mem_cmd_desc; 1932842b42dfSAlex Bennée } 1933842b42dfSAlex Bennée break; 1934842b42dfSAlex Bennée case 'M': 1935842b42dfSAlex Bennée { 1936842b42dfSAlex Bennée static const GdbCmdParseEntry write_mem_cmd_desc = { 1937842b42dfSAlex Bennée .handler = handle_write_mem, 1938842b42dfSAlex Bennée .cmd = "M", 1939842b42dfSAlex Bennée .cmd_startswith = 1, 1940842b42dfSAlex Bennée .schema = "L,L:s0" 1941842b42dfSAlex Bennée }; 1942842b42dfSAlex Bennée cmd_parser = &write_mem_cmd_desc; 1943842b42dfSAlex Bennée } 1944842b42dfSAlex Bennée break; 1945842b42dfSAlex Bennée case 'p': 1946842b42dfSAlex Bennée { 1947842b42dfSAlex Bennée static const GdbCmdParseEntry get_reg_cmd_desc = { 1948842b42dfSAlex Bennée .handler = handle_get_reg, 1949842b42dfSAlex Bennée .cmd = "p", 1950842b42dfSAlex Bennée .cmd_startswith = 1, 1951842b42dfSAlex Bennée .schema = "L0" 1952842b42dfSAlex Bennée }; 1953842b42dfSAlex Bennée cmd_parser = &get_reg_cmd_desc; 1954842b42dfSAlex Bennée } 1955842b42dfSAlex Bennée break; 1956842b42dfSAlex Bennée case 'P': 1957842b42dfSAlex Bennée { 1958842b42dfSAlex Bennée static const GdbCmdParseEntry set_reg_cmd_desc = { 1959842b42dfSAlex Bennée .handler = handle_set_reg, 1960842b42dfSAlex Bennée .cmd = "P", 1961842b42dfSAlex Bennée .cmd_startswith = 1, 1962842b42dfSAlex Bennée .schema = "L?s0" 1963842b42dfSAlex Bennée }; 1964842b42dfSAlex Bennée cmd_parser = &set_reg_cmd_desc; 1965842b42dfSAlex Bennée } 1966842b42dfSAlex Bennée break; 1967842b42dfSAlex Bennée case 'Z': 1968842b42dfSAlex Bennée { 1969842b42dfSAlex Bennée static const GdbCmdParseEntry insert_bp_cmd_desc = { 1970842b42dfSAlex Bennée .handler = handle_insert_bp, 1971842b42dfSAlex Bennée .cmd = "Z", 1972842b42dfSAlex Bennée .cmd_startswith = 1, 1973842b42dfSAlex Bennée .schema = "l?L?L0" 1974842b42dfSAlex Bennée }; 1975842b42dfSAlex Bennée cmd_parser = &insert_bp_cmd_desc; 1976842b42dfSAlex Bennée } 1977842b42dfSAlex Bennée break; 1978842b42dfSAlex Bennée case 'z': 1979842b42dfSAlex Bennée { 1980842b42dfSAlex Bennée static const GdbCmdParseEntry remove_bp_cmd_desc = { 1981842b42dfSAlex Bennée .handler = handle_remove_bp, 1982842b42dfSAlex Bennée .cmd = "z", 1983842b42dfSAlex Bennée .cmd_startswith = 1, 1984842b42dfSAlex Bennée .schema = "l?L?L0" 1985842b42dfSAlex Bennée }; 1986842b42dfSAlex Bennée cmd_parser = &remove_bp_cmd_desc; 1987842b42dfSAlex Bennée } 1988842b42dfSAlex Bennée break; 1989842b42dfSAlex Bennée case 'H': 1990842b42dfSAlex Bennée { 1991842b42dfSAlex Bennée static const GdbCmdParseEntry set_thread_cmd_desc = { 1992842b42dfSAlex Bennée .handler = handle_set_thread, 1993842b42dfSAlex Bennée .cmd = "H", 1994842b42dfSAlex Bennée .cmd_startswith = 1, 1995842b42dfSAlex Bennée .schema = "o.t0" 1996842b42dfSAlex Bennée }; 1997842b42dfSAlex Bennée cmd_parser = &set_thread_cmd_desc; 1998842b42dfSAlex Bennée } 1999842b42dfSAlex Bennée break; 2000842b42dfSAlex Bennée case 'T': 2001842b42dfSAlex Bennée { 2002842b42dfSAlex Bennée static const GdbCmdParseEntry thread_alive_cmd_desc = { 2003842b42dfSAlex Bennée .handler = handle_thread_alive, 2004842b42dfSAlex Bennée .cmd = "T", 2005842b42dfSAlex Bennée .cmd_startswith = 1, 2006842b42dfSAlex Bennée .schema = "t0" 2007842b42dfSAlex Bennée }; 2008842b42dfSAlex Bennée cmd_parser = &thread_alive_cmd_desc; 2009842b42dfSAlex Bennée } 2010842b42dfSAlex Bennée break; 2011842b42dfSAlex Bennée case 'q': 2012842b42dfSAlex Bennée { 2013842b42dfSAlex Bennée static const GdbCmdParseEntry gen_query_cmd_desc = { 2014842b42dfSAlex Bennée .handler = handle_gen_query, 2015842b42dfSAlex Bennée .cmd = "q", 2016842b42dfSAlex Bennée .cmd_startswith = 1, 2017842b42dfSAlex Bennée .schema = "s0" 2018842b42dfSAlex Bennée }; 2019842b42dfSAlex Bennée cmd_parser = &gen_query_cmd_desc; 2020842b42dfSAlex Bennée } 2021842b42dfSAlex Bennée break; 2022842b42dfSAlex Bennée case 'Q': 2023842b42dfSAlex Bennée { 2024842b42dfSAlex Bennée static const GdbCmdParseEntry gen_set_cmd_desc = { 2025842b42dfSAlex Bennée .handler = handle_gen_set, 2026842b42dfSAlex Bennée .cmd = "Q", 2027842b42dfSAlex Bennée .cmd_startswith = 1, 2028842b42dfSAlex Bennée .schema = "s0" 2029842b42dfSAlex Bennée }; 2030842b42dfSAlex Bennée cmd_parser = &gen_set_cmd_desc; 2031842b42dfSAlex Bennée } 2032842b42dfSAlex Bennée break; 2033842b42dfSAlex Bennée default: 2034842b42dfSAlex Bennée /* put empty packet */ 203536e067b2SAlex Bennée gdb_put_packet(""); 2036842b42dfSAlex Bennée break; 2037842b42dfSAlex Bennée } 2038842b42dfSAlex Bennée 2039842b42dfSAlex Bennée if (cmd_parser) { 2040842b42dfSAlex Bennée run_cmd_parser(line_buf, cmd_parser); 2041842b42dfSAlex Bennée } 2042842b42dfSAlex Bennée 2043842b42dfSAlex Bennée return RS_IDLE; 2044842b42dfSAlex Bennée } 2045842b42dfSAlex Bennée 2046842b42dfSAlex Bennée void gdb_set_stop_cpu(CPUState *cpu) 2047842b42dfSAlex Bennée { 2048842b42dfSAlex Bennée GDBProcess *p = gdb_get_cpu_process(cpu); 2049842b42dfSAlex Bennée 2050842b42dfSAlex Bennée if (!p->attached) { 2051842b42dfSAlex Bennée /* 2052842b42dfSAlex Bennée * Having a stop CPU corresponding to a process that is not attached 2053842b42dfSAlex Bennée * confuses GDB. So we ignore the request. 2054842b42dfSAlex Bennée */ 2055842b42dfSAlex Bennée return; 2056842b42dfSAlex Bennée } 2057842b42dfSAlex Bennée 2058842b42dfSAlex Bennée gdbserver_state.c_cpu = cpu; 2059842b42dfSAlex Bennée gdbserver_state.g_cpu = cpu; 2060842b42dfSAlex Bennée } 2061842b42dfSAlex Bennée 2062842b42dfSAlex Bennée /* Send a gdb syscall request. 2063842b42dfSAlex Bennée This accepts limited printf-style format specifiers, specifically: 2064842b42dfSAlex Bennée %x - target_ulong argument printed in hex. 2065842b42dfSAlex Bennée %lx - 64-bit argument printed in hex. 2066842b42dfSAlex Bennée %s - string pointer (target_ulong) and length (int) pair. */ 2067842b42dfSAlex Bennée void gdb_do_syscallv(gdb_syscall_complete_cb cb, const char *fmt, va_list va) 2068842b42dfSAlex Bennée { 2069842b42dfSAlex Bennée char *p; 2070842b42dfSAlex Bennée char *p_end; 2071842b42dfSAlex Bennée target_ulong addr; 2072842b42dfSAlex Bennée uint64_t i64; 2073842b42dfSAlex Bennée 2074842b42dfSAlex Bennée if (!gdb_attached()) { 2075842b42dfSAlex Bennée return; 2076842b42dfSAlex Bennée } 2077842b42dfSAlex Bennée 2078842b42dfSAlex Bennée gdbserver_state.current_syscall_cb = cb; 2079842b42dfSAlex Bennée #ifndef CONFIG_USER_ONLY 2080842b42dfSAlex Bennée vm_stop(RUN_STATE_DEBUG); 2081842b42dfSAlex Bennée #endif 2082842b42dfSAlex Bennée p = &gdbserver_state.syscall_buf[0]; 2083842b42dfSAlex Bennée p_end = &gdbserver_state.syscall_buf[sizeof(gdbserver_state.syscall_buf)]; 2084842b42dfSAlex Bennée *(p++) = 'F'; 2085842b42dfSAlex Bennée while (*fmt) { 2086842b42dfSAlex Bennée if (*fmt == '%') { 2087842b42dfSAlex Bennée fmt++; 2088842b42dfSAlex Bennée switch (*fmt++) { 2089842b42dfSAlex Bennée case 'x': 2090842b42dfSAlex Bennée addr = va_arg(va, target_ulong); 2091842b42dfSAlex Bennée p += snprintf(p, p_end - p, TARGET_FMT_lx, addr); 2092842b42dfSAlex Bennée break; 2093842b42dfSAlex Bennée case 'l': 2094842b42dfSAlex Bennée if (*(fmt++) != 'x') 2095842b42dfSAlex Bennée goto bad_format; 2096842b42dfSAlex Bennée i64 = va_arg(va, uint64_t); 2097842b42dfSAlex Bennée p += snprintf(p, p_end - p, "%" PRIx64, i64); 2098842b42dfSAlex Bennée break; 2099842b42dfSAlex Bennée case 's': 2100842b42dfSAlex Bennée addr = va_arg(va, target_ulong); 2101842b42dfSAlex Bennée p += snprintf(p, p_end - p, TARGET_FMT_lx "/%x", 2102842b42dfSAlex Bennée addr, va_arg(va, int)); 2103842b42dfSAlex Bennée break; 2104842b42dfSAlex Bennée default: 2105842b42dfSAlex Bennée bad_format: 2106842b42dfSAlex Bennée error_report("gdbstub: Bad syscall format string '%s'", 2107842b42dfSAlex Bennée fmt - 1); 2108842b42dfSAlex Bennée break; 2109842b42dfSAlex Bennée } 2110842b42dfSAlex Bennée } else { 2111842b42dfSAlex Bennée *(p++) = *(fmt++); 2112842b42dfSAlex Bennée } 2113842b42dfSAlex Bennée } 2114842b42dfSAlex Bennée *p = 0; 2115842b42dfSAlex Bennée #ifdef CONFIG_USER_ONLY 211636e067b2SAlex Bennée gdb_put_packet(gdbserver_state.syscall_buf); 2117842b42dfSAlex Bennée /* Return control to gdb for it to process the syscall request. 2118842b42dfSAlex Bennée * Since the protocol requires that gdb hands control back to us 2119842b42dfSAlex Bennée * using a "here are the results" F packet, we don't need to check 2120842b42dfSAlex Bennée * gdb_handlesig's return value (which is the signal to deliver if 2121842b42dfSAlex Bennée * execution was resumed via a continue packet). 2122842b42dfSAlex Bennée */ 2123842b42dfSAlex Bennée gdb_handlesig(gdbserver_state.c_cpu, 0); 2124842b42dfSAlex Bennée #else 2125842b42dfSAlex Bennée /* In this case wait to send the syscall packet until notification that 2126842b42dfSAlex Bennée the CPU has stopped. This must be done because if the packet is sent 2127842b42dfSAlex Bennée now the reply from the syscall request could be received while the CPU 2128842b42dfSAlex Bennée is still in the running state, which can cause packets to be dropped 2129842b42dfSAlex Bennée and state transition 'T' packets to be sent while the syscall is still 2130842b42dfSAlex Bennée being processed. */ 2131842b42dfSAlex Bennée qemu_cpu_kick(gdbserver_state.c_cpu); 2132842b42dfSAlex Bennée #endif 2133842b42dfSAlex Bennée } 2134842b42dfSAlex Bennée 2135842b42dfSAlex Bennée void gdb_do_syscall(gdb_syscall_complete_cb cb, const char *fmt, ...) 2136842b42dfSAlex Bennée { 2137842b42dfSAlex Bennée va_list va; 2138842b42dfSAlex Bennée 2139842b42dfSAlex Bennée va_start(va, fmt); 2140842b42dfSAlex Bennée gdb_do_syscallv(cb, fmt, va); 2141842b42dfSAlex Bennée va_end(va); 2142842b42dfSAlex Bennée } 2143842b42dfSAlex Bennée 214436e067b2SAlex Bennée void gdb_read_byte(uint8_t ch) 2145842b42dfSAlex Bennée { 2146842b42dfSAlex Bennée uint8_t reply; 2147842b42dfSAlex Bennée 2148842b42dfSAlex Bennée #ifndef CONFIG_USER_ONLY 2149842b42dfSAlex Bennée if (gdbserver_state.last_packet->len) { 2150842b42dfSAlex Bennée /* Waiting for a response to the last packet. If we see the start 2151842b42dfSAlex Bennée of a new command then abandon the previous response. */ 2152842b42dfSAlex Bennée if (ch == '-') { 2153842b42dfSAlex Bennée trace_gdbstub_err_got_nack(); 215436e067b2SAlex Bennée gdb_put_buffer(gdbserver_state.last_packet->data, 2155842b42dfSAlex Bennée gdbserver_state.last_packet->len); 2156842b42dfSAlex Bennée } else if (ch == '+') { 2157842b42dfSAlex Bennée trace_gdbstub_io_got_ack(); 2158842b42dfSAlex Bennée } else { 2159842b42dfSAlex Bennée trace_gdbstub_io_got_unexpected(ch); 2160842b42dfSAlex Bennée } 2161842b42dfSAlex Bennée 2162842b42dfSAlex Bennée if (ch == '+' || ch == '$') { 2163842b42dfSAlex Bennée g_byte_array_set_size(gdbserver_state.last_packet, 0); 2164842b42dfSAlex Bennée } 2165842b42dfSAlex Bennée if (ch != '$') 2166842b42dfSAlex Bennée return; 2167842b42dfSAlex Bennée } 2168842b42dfSAlex Bennée if (runstate_is_running()) { 2169842b42dfSAlex Bennée /* when the CPU is running, we cannot do anything except stop 2170842b42dfSAlex Bennée it when receiving a char */ 2171842b42dfSAlex Bennée vm_stop(RUN_STATE_PAUSED); 2172842b42dfSAlex Bennée } else 2173842b42dfSAlex Bennée #endif 2174842b42dfSAlex Bennée { 2175842b42dfSAlex Bennée switch(gdbserver_state.state) { 2176842b42dfSAlex Bennée case RS_IDLE: 2177842b42dfSAlex Bennée if (ch == '$') { 2178842b42dfSAlex Bennée /* start of command packet */ 2179842b42dfSAlex Bennée gdbserver_state.line_buf_index = 0; 2180842b42dfSAlex Bennée gdbserver_state.line_sum = 0; 2181842b42dfSAlex Bennée gdbserver_state.state = RS_GETLINE; 2182842b42dfSAlex Bennée } else { 2183842b42dfSAlex Bennée trace_gdbstub_err_garbage(ch); 2184842b42dfSAlex Bennée } 2185842b42dfSAlex Bennée break; 2186842b42dfSAlex Bennée case RS_GETLINE: 2187842b42dfSAlex Bennée if (ch == '}') { 2188842b42dfSAlex Bennée /* start escape sequence */ 2189842b42dfSAlex Bennée gdbserver_state.state = RS_GETLINE_ESC; 2190842b42dfSAlex Bennée gdbserver_state.line_sum += ch; 2191842b42dfSAlex Bennée } else if (ch == '*') { 2192842b42dfSAlex Bennée /* start run length encoding sequence */ 2193842b42dfSAlex Bennée gdbserver_state.state = RS_GETLINE_RLE; 2194842b42dfSAlex Bennée gdbserver_state.line_sum += ch; 2195842b42dfSAlex Bennée } else if (ch == '#') { 2196842b42dfSAlex Bennée /* end of command, start of checksum*/ 2197842b42dfSAlex Bennée gdbserver_state.state = RS_CHKSUM1; 2198842b42dfSAlex Bennée } else if (gdbserver_state.line_buf_index >= sizeof(gdbserver_state.line_buf) - 1) { 2199842b42dfSAlex Bennée trace_gdbstub_err_overrun(); 2200842b42dfSAlex Bennée gdbserver_state.state = RS_IDLE; 2201842b42dfSAlex Bennée } else { 2202842b42dfSAlex Bennée /* unescaped command character */ 2203842b42dfSAlex Bennée gdbserver_state.line_buf[gdbserver_state.line_buf_index++] = ch; 2204842b42dfSAlex Bennée gdbserver_state.line_sum += ch; 2205842b42dfSAlex Bennée } 2206842b42dfSAlex Bennée break; 2207842b42dfSAlex Bennée case RS_GETLINE_ESC: 2208842b42dfSAlex Bennée if (ch == '#') { 2209842b42dfSAlex Bennée /* unexpected end of command in escape sequence */ 2210842b42dfSAlex Bennée gdbserver_state.state = RS_CHKSUM1; 2211842b42dfSAlex Bennée } else if (gdbserver_state.line_buf_index >= sizeof(gdbserver_state.line_buf) - 1) { 2212842b42dfSAlex Bennée /* command buffer overrun */ 2213842b42dfSAlex Bennée trace_gdbstub_err_overrun(); 2214842b42dfSAlex Bennée gdbserver_state.state = RS_IDLE; 2215842b42dfSAlex Bennée } else { 2216842b42dfSAlex Bennée /* parse escaped character and leave escape state */ 2217842b42dfSAlex Bennée gdbserver_state.line_buf[gdbserver_state.line_buf_index++] = ch ^ 0x20; 2218842b42dfSAlex Bennée gdbserver_state.line_sum += ch; 2219842b42dfSAlex Bennée gdbserver_state.state = RS_GETLINE; 2220842b42dfSAlex Bennée } 2221842b42dfSAlex Bennée break; 2222842b42dfSAlex Bennée case RS_GETLINE_RLE: 2223842b42dfSAlex Bennée /* 2224842b42dfSAlex Bennée * Run-length encoding is explained in "Debugging with GDB / 2225842b42dfSAlex Bennée * Appendix E GDB Remote Serial Protocol / Overview". 2226842b42dfSAlex Bennée */ 2227842b42dfSAlex Bennée if (ch < ' ' || ch == '#' || ch == '$' || ch > 126) { 2228842b42dfSAlex Bennée /* invalid RLE count encoding */ 2229842b42dfSAlex Bennée trace_gdbstub_err_invalid_repeat(ch); 2230842b42dfSAlex Bennée gdbserver_state.state = RS_GETLINE; 2231842b42dfSAlex Bennée } else { 2232842b42dfSAlex Bennée /* decode repeat length */ 2233842b42dfSAlex Bennée int repeat = ch - ' ' + 3; 2234842b42dfSAlex Bennée if (gdbserver_state.line_buf_index + repeat >= sizeof(gdbserver_state.line_buf) - 1) { 2235842b42dfSAlex Bennée /* that many repeats would overrun the command buffer */ 2236842b42dfSAlex Bennée trace_gdbstub_err_overrun(); 2237842b42dfSAlex Bennée gdbserver_state.state = RS_IDLE; 2238842b42dfSAlex Bennée } else if (gdbserver_state.line_buf_index < 1) { 2239842b42dfSAlex Bennée /* got a repeat but we have nothing to repeat */ 2240842b42dfSAlex Bennée trace_gdbstub_err_invalid_rle(); 2241842b42dfSAlex Bennée gdbserver_state.state = RS_GETLINE; 2242842b42dfSAlex Bennée } else { 2243842b42dfSAlex Bennée /* repeat the last character */ 2244842b42dfSAlex Bennée memset(gdbserver_state.line_buf + gdbserver_state.line_buf_index, 2245842b42dfSAlex Bennée gdbserver_state.line_buf[gdbserver_state.line_buf_index - 1], repeat); 2246842b42dfSAlex Bennée gdbserver_state.line_buf_index += repeat; 2247842b42dfSAlex Bennée gdbserver_state.line_sum += ch; 2248842b42dfSAlex Bennée gdbserver_state.state = RS_GETLINE; 2249842b42dfSAlex Bennée } 2250842b42dfSAlex Bennée } 2251842b42dfSAlex Bennée break; 2252842b42dfSAlex Bennée case RS_CHKSUM1: 2253842b42dfSAlex Bennée /* get high hex digit of checksum */ 2254842b42dfSAlex Bennée if (!isxdigit(ch)) { 2255842b42dfSAlex Bennée trace_gdbstub_err_checksum_invalid(ch); 2256842b42dfSAlex Bennée gdbserver_state.state = RS_GETLINE; 2257842b42dfSAlex Bennée break; 2258842b42dfSAlex Bennée } 2259842b42dfSAlex Bennée gdbserver_state.line_buf[gdbserver_state.line_buf_index] = '\0'; 2260842b42dfSAlex Bennée gdbserver_state.line_csum = fromhex(ch) << 4; 2261842b42dfSAlex Bennée gdbserver_state.state = RS_CHKSUM2; 2262842b42dfSAlex Bennée break; 2263842b42dfSAlex Bennée case RS_CHKSUM2: 2264842b42dfSAlex Bennée /* get low hex digit of checksum */ 2265842b42dfSAlex Bennée if (!isxdigit(ch)) { 2266842b42dfSAlex Bennée trace_gdbstub_err_checksum_invalid(ch); 2267842b42dfSAlex Bennée gdbserver_state.state = RS_GETLINE; 2268842b42dfSAlex Bennée break; 2269842b42dfSAlex Bennée } 2270842b42dfSAlex Bennée gdbserver_state.line_csum |= fromhex(ch); 2271842b42dfSAlex Bennée 2272842b42dfSAlex Bennée if (gdbserver_state.line_csum != (gdbserver_state.line_sum & 0xff)) { 2273842b42dfSAlex Bennée trace_gdbstub_err_checksum_incorrect(gdbserver_state.line_sum, gdbserver_state.line_csum); 2274842b42dfSAlex Bennée /* send NAK reply */ 2275842b42dfSAlex Bennée reply = '-'; 227636e067b2SAlex Bennée gdb_put_buffer(&reply, 1); 2277842b42dfSAlex Bennée gdbserver_state.state = RS_IDLE; 2278842b42dfSAlex Bennée } else { 2279842b42dfSAlex Bennée /* send ACK reply */ 2280842b42dfSAlex Bennée reply = '+'; 228136e067b2SAlex Bennée gdb_put_buffer(&reply, 1); 2282842b42dfSAlex Bennée gdbserver_state.state = gdb_handle_packet(gdbserver_state.line_buf); 2283842b42dfSAlex Bennée } 2284842b42dfSAlex Bennée break; 2285842b42dfSAlex Bennée default: 2286842b42dfSAlex Bennée abort(); 2287842b42dfSAlex Bennée } 2288842b42dfSAlex Bennée } 2289842b42dfSAlex Bennée } 2290842b42dfSAlex Bennée 2291842b42dfSAlex Bennée /* 2292842b42dfSAlex Bennée * Create the process that will contain all the "orphan" CPUs (that are not 2293842b42dfSAlex Bennée * part of a CPU cluster). Note that if this process contains no CPUs, it won't 2294842b42dfSAlex Bennée * be attachable and thus will be invisible to the user. 2295842b42dfSAlex Bennée */ 229636e067b2SAlex Bennée void gdb_create_default_process(GDBState *s) 2297842b42dfSAlex Bennée { 2298842b42dfSAlex Bennée GDBProcess *process; 2299842b42dfSAlex Bennée int max_pid = 0; 2300842b42dfSAlex Bennée 2301842b42dfSAlex Bennée if (gdbserver_state.process_num) { 2302842b42dfSAlex Bennée max_pid = s->processes[s->process_num - 1].pid; 2303842b42dfSAlex Bennée } 2304842b42dfSAlex Bennée 2305842b42dfSAlex Bennée s->processes = g_renew(GDBProcess, s->processes, ++s->process_num); 2306842b42dfSAlex Bennée process = &s->processes[s->process_num - 1]; 2307842b42dfSAlex Bennée 2308842b42dfSAlex Bennée /* We need an available PID slot for this process */ 2309842b42dfSAlex Bennée assert(max_pid < UINT32_MAX); 2310842b42dfSAlex Bennée 2311842b42dfSAlex Bennée process->pid = max_pid + 1; 2312842b42dfSAlex Bennée process->attached = false; 2313842b42dfSAlex Bennée process->target_xml[0] = '\0'; 2314842b42dfSAlex Bennée } 2315842b42dfSAlex Bennée 2316