blob: f1504af44fe65f2a484471ed1d7c9309d84df5c7 [file] [log] [blame]
bellardb4608c02003-06-27 17:34:32 +00001/*
2 * gdb server stub
ths5fafdf22007-09-16 21:08:06 +00003 *
Alex Bennée42a09592019-07-05 13:28:19 +01004 * This implements a subset of the remote protocol as described in:
5 *
6 * https://sourceware.org/gdb/onlinedocs/gdb/Remote-Protocol.html
7 *
bellard34751872005-07-02 14:31:34 +00008 * Copyright (c) 2003-2005 Fabrice Bellard
bellardb4608c02003-06-27 17:34:32 +00009 *
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2 of the License, or (at your option) any later version.
14 *
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
19 *
20 * You should have received a copy of the GNU Lesser General Public
Blue Swirl8167ee82009-07-16 20:47:01 +000021 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
Alex Bennée42a09592019-07-05 13:28:19 +010022 *
23 * SPDX-License-Identifier: LGPL-2.0+
bellardb4608c02003-06-27 17:34:32 +000024 */
Markus Armbruster856dfd82019-05-23 16:35:06 +020025
Peter Maydelld38ea872016-01-29 17:50:05 +000026#include "qemu/osdep.h"
Markus Armbruster856dfd82019-05-23 16:35:06 +020027#include "qemu/ctype.h"
Veronia Bahaaf348b6d2016-03-20 19:16:19 +020028#include "qemu/cutils.h"
Markus Armbruster0b8fa322019-05-23 16:35:07 +020029#include "qemu/module.h"
Alex Bennée842b42d2022-09-29 12:42:22 +010030#include "trace.h"
Peter Maydell85b4fa02021-09-08 16:44:04 +010031#include "exec/gdbstub.h"
Veronia Bahaaf348b6d2016-03-20 19:16:19 +020032#ifdef CONFIG_USER_ONLY
Alex Bennéed96bf492023-03-02 18:57:47 -080033#include "gdbstub/user.h"
bellard1fddef42005-04-17 19:16:13 +000034#else
Luc Michel8f468632019-01-07 15:23:45 +000035#include "hw/cpu/cluster.h"
Like Xu5cc87672019-05-19 04:54:21 +080036#include "hw/boards.h"
bellard1fddef42005-04-17 19:16:13 +000037#endif
bellard67b915a2004-03-31 23:37:16 +000038
Vincent Palatinb3946622017-01-10 11:59:55 +010039#include "sysemu/hw_accel.h"
Markus Armbruster54d31232019-08-12 07:23:59 +020040#include "sysemu/runstate.h"
Philippe Mathieu-Daudé6b5fe132021-03-05 13:54:49 +000041#include "semihosting/semihost.h"
Paolo Bonzini63c91552016-03-15 13:18:37 +010042#include "exec/exec-all.h"
Philippe Mathieu-Daudé5b5968c2022-12-19 18:09:43 +010043#include "exec/replay-core.h"
Alex Bennée548c9602023-03-02 18:57:43 -080044#include "exec/tb-flush.h"
45#include "exec/hwaddr.h"
aurel32ca587a82008-12-18 22:44:13 +000046
Alex Bennéeae7467b2022-09-29 12:42:24 +010047#include "internals.h"
48
pbrook56aebc82008-10-11 17:55:29 +000049typedef struct GDBRegisterState {
50 int base_reg;
51 int num_regs;
Alex Bennéea010bdb2020-03-16 17:21:41 +000052 gdb_get_reg_cb get_reg;
53 gdb_set_reg_cb set_reg;
pbrook56aebc82008-10-11 17:55:29 +000054 const char *xml;
55 struct GDBRegisterState *next;
56} GDBRegisterState;
57
Alex Bennéeb6fa2ec2023-03-02 18:57:46 -080058GDBState gdbserver_state;
Alex Bennée8d98c442020-03-16 17:21:33 +000059
Alex Bennée36e067b2023-03-02 18:57:45 -080060void gdb_init_gdbserver_state(void)
Alex Bennée8d98c442020-03-16 17:21:33 +000061{
62 g_assert(!gdbserver_state.init);
63 memset(&gdbserver_state, 0, sizeof(GDBState));
64 gdbserver_state.init = true;
Alex Bennée308f9e82020-03-16 17:21:35 +000065 gdbserver_state.str_buf = g_string_new(NULL);
Alex Bennée4a25f1b2020-03-16 17:21:36 +000066 gdbserver_state.mem_buf = g_byte_array_sized_new(MAX_PACKET_LENGTH);
Damien Hedded116e812020-03-16 17:21:53 +000067 gdbserver_state.last_packet = g_byte_array_sized_new(MAX_PACKET_LENGTH + 4);
Maxim Levitskyecd39d62021-11-11 12:06:02 +010068
69 /*
Alex Bennée3b7a9382022-09-29 12:42:23 +010070 * What single-step modes are supported is accelerator dependent.
71 * By default try to use no IRQs and no timers while single
72 * stepping so as to make single stepping like a typical ICE HW step.
Maxim Levitskyecd39d62021-11-11 12:06:02 +010073 */
Alex Bennée3b7a9382022-09-29 12:42:23 +010074 gdbserver_state.supported_sstep_flags = accel_supported_gdbstub_sstep_flags();
Maxim Levitsky12bc5b42021-11-11 12:06:03 +010075 gdbserver_state.sstep_flags = SSTEP_ENABLE | SSTEP_NOIRQ | SSTEP_NOTIMER;
76 gdbserver_state.sstep_flags &= gdbserver_state.supported_sstep_flags;
Alex Bennée8d98c442020-03-16 17:21:33 +000077}
78
Andreas Färber5b50e792013-06-29 04:18:45 +020079bool gdb_has_xml;
pbrook56aebc82008-10-11 17:55:29 +000080
Peter Maydellebf1b4c2022-06-10 14:32:36 +010081/*
82 * Return true if there is a GDB currently connected to the stub
83 * and attached to a CPU
84 */
85static bool gdb_attached(void)
86{
87 return gdbserver_state.init && gdbserver_state.c_cpu;
88}
89
blueswir1654efcf2009-04-18 07:29:59 +000090static enum {
pbrooka2d1eba2007-01-28 03:10:55 +000091 GDB_SYS_UNKNOWN,
92 GDB_SYS_ENABLED,
93 GDB_SYS_DISABLED,
94} gdb_syscall_mode;
95
Liviu Ionescua38bb072014-12-11 12:07:48 +000096/* Decide if either remote gdb syscalls or native file IO should be used. */
pbrooka2d1eba2007-01-28 03:10:55 +000097int use_gdb_syscalls(void)
98{
Leon Alraecfe67ce2015-06-19 14:17:45 +010099 SemihostingTarget target = semihosting_get_target();
100 if (target == SEMIHOSTING_TARGET_NATIVE) {
Liviu Ionescua38bb072014-12-11 12:07:48 +0000101 /* -semihosting-config target=native */
102 return false;
Leon Alraecfe67ce2015-06-19 14:17:45 +0100103 } else if (target == SEMIHOSTING_TARGET_GDB) {
Liviu Ionescua38bb072014-12-11 12:07:48 +0000104 /* -semihosting-config target=gdb */
105 return true;
106 }
107
108 /* -semihosting-config target=auto */
109 /* On the first call check if gdb is connected and remember. */
pbrooka2d1eba2007-01-28 03:10:55 +0000110 if (gdb_syscall_mode == GDB_SYS_UNKNOWN) {
Peter Maydellebf1b4c2022-06-10 14:32:36 +0100111 gdb_syscall_mode = gdb_attached() ? GDB_SYS_ENABLED : GDB_SYS_DISABLED;
pbrooka2d1eba2007-01-28 03:10:55 +0000112 }
113 return gdb_syscall_mode == GDB_SYS_ENABLED;
114}
115
Philippe Mathieu-Daudé90057742018-04-08 11:59:33 -0300116/* writes 2*len+1 bytes in buf */
Alex Bennée36e067b2023-03-02 18:57:45 -0800117void gdb_memtohex(GString *buf, const uint8_t *mem, int len)
bellardb4608c02003-06-27 17:34:32 +0000118{
119 int i, c;
bellardb4608c02003-06-27 17:34:32 +0000120 for(i = 0; i < len; i++) {
121 c = mem[i];
Alex Bennée308f9e82020-03-16 17:21:35 +0000122 g_string_append_c(buf, tohex(c >> 4));
123 g_string_append_c(buf, tohex(c & 0xf));
bellardb4608c02003-06-27 17:34:32 +0000124 }
Alex Bennée308f9e82020-03-16 17:21:35 +0000125 g_string_append_c(buf, '\0');
bellardb4608c02003-06-27 17:34:32 +0000126}
127
Alex Bennée36e067b2023-03-02 18:57:45 -0800128void gdb_hextomem(GByteArray *mem, const char *buf, int len)
bellardb4608c02003-06-27 17:34:32 +0000129{
130 int i;
131
132 for(i = 0; i < len; i++) {
Alex Bennée4a25f1b2020-03-16 17:21:36 +0000133 guint8 byte = fromhex(buf[0]) << 4 | fromhex(buf[1]);
134 g_byte_array_append(mem, &byte, 1);
bellardb4608c02003-06-27 17:34:32 +0000135 buf += 2;
136 }
137}
138
Doug Gale5c9522b2017-12-02 20:30:37 -0500139static void hexdump(const char *buf, int len,
140 void (*trace_fn)(size_t ofs, char const *text))
141{
142 char line_buffer[3 * 16 + 4 + 16 + 1];
143
144 size_t i;
145 for (i = 0; i < len || (i & 0xF); ++i) {
146 size_t byte_ofs = i & 15;
147
148 if (byte_ofs == 0) {
149 memset(line_buffer, ' ', 3 * 16 + 4 + 16);
150 line_buffer[3 * 16 + 4 + 16] = 0;
151 }
152
153 size_t col_group = (i >> 2) & 3;
154 size_t hex_col = byte_ofs * 3 + col_group;
155 size_t txt_col = 3 * 16 + 4 + byte_ofs;
156
157 if (i < len) {
158 char value = buf[i];
159
160 line_buffer[hex_col + 0] = tohex((value >> 4) & 0xF);
161 line_buffer[hex_col + 1] = tohex((value >> 0) & 0xF);
162 line_buffer[txt_col + 0] = (value >= ' ' && value < 127)
163 ? value
164 : '.';
165 }
166
167 if (byte_ofs == 0xF)
168 trace_fn(i & -16, line_buffer);
169 }
170}
171
bellardb4608c02003-06-27 17:34:32 +0000172/* return -1 if error, 0 if OK */
Alex Bennée36e067b2023-03-02 18:57:45 -0800173int gdb_put_packet_binary(const char *buf, int len, bool dump)
bellardb4608c02003-06-27 17:34:32 +0000174{
pbrook56aebc82008-10-11 17:55:29 +0000175 int csum, i;
Damien Hedded116e812020-03-16 17:21:53 +0000176 uint8_t footer[3];
bellardb4608c02003-06-27 17:34:32 +0000177
Doug Gale5c9522b2017-12-02 20:30:37 -0500178 if (dump && trace_event_get_state_backends(TRACE_GDBSTUB_IO_BINARYREPLY)) {
179 hexdump(buf, len, trace_gdbstub_io_binaryreply);
180 }
181
bellardb4608c02003-06-27 17:34:32 +0000182 for(;;) {
Damien Hedded116e812020-03-16 17:21:53 +0000183 g_byte_array_set_size(gdbserver_state.last_packet, 0);
184 g_byte_array_append(gdbserver_state.last_packet,
185 (const uint8_t *) "$", 1);
186 g_byte_array_append(gdbserver_state.last_packet,
187 (const uint8_t *) buf, len);
bellardb4608c02003-06-27 17:34:32 +0000188 csum = 0;
189 for(i = 0; i < len; i++) {
190 csum += buf[i];
191 }
Damien Hedded116e812020-03-16 17:21:53 +0000192 footer[0] = '#';
193 footer[1] = tohex((csum >> 4) & 0xf);
194 footer[2] = tohex((csum) & 0xf);
195 g_byte_array_append(gdbserver_state.last_packet, footer, 3);
bellardb4608c02003-06-27 17:34:32 +0000196
Alex Bennée36e067b2023-03-02 18:57:45 -0800197 gdb_put_buffer(gdbserver_state.last_packet->data,
Damien Hedded116e812020-03-16 17:21:53 +0000198 gdbserver_state.last_packet->len);
bellardb4608c02003-06-27 17:34:32 +0000199
Alex Bennéea7e0f9b2023-03-02 18:57:49 -0800200 if (gdb_got_immediate_ack()) {
bellardb4608c02003-06-27 17:34:32 +0000201 break;
Alex Bennéea7e0f9b2023-03-02 18:57:49 -0800202 }
bellardb4608c02003-06-27 17:34:32 +0000203 }
204 return 0;
205}
206
pbrook56aebc82008-10-11 17:55:29 +0000207/* return -1 if error, 0 if OK */
Alex Bennée36e067b2023-03-02 18:57:45 -0800208int gdb_put_packet(const char *buf)
pbrook56aebc82008-10-11 17:55:29 +0000209{
Doug Gale5c9522b2017-12-02 20:30:37 -0500210 trace_gdbstub_io_reply(buf);
pbrook56aebc82008-10-11 17:55:29 +0000211
Alex Bennée36e067b2023-03-02 18:57:45 -0800212 return gdb_put_packet_binary(buf, strlen(buf), false);
pbrook56aebc82008-10-11 17:55:29 +0000213}
214
Alex Bennée36e067b2023-03-02 18:57:45 -0800215void gdb_put_strbuf(void)
pbrook56aebc82008-10-11 17:55:29 +0000216{
Alex Bennée36e067b2023-03-02 18:57:45 -0800217 gdb_put_packet(gdbserver_state.str_buf->str);
Alex Bennée308f9e82020-03-16 17:21:35 +0000218}
219
220/* Encode data using the encoding for 'x' packets. */
Alex Bennée36e067b2023-03-02 18:57:45 -0800221void gdb_memtox(GString *buf, const char *mem, int len)
Alex Bennée308f9e82020-03-16 17:21:35 +0000222{
pbrook56aebc82008-10-11 17:55:29 +0000223 char c;
224
225 while (len--) {
226 c = *(mem++);
227 switch (c) {
228 case '#': case '$': case '*': case '}':
Alex Bennée308f9e82020-03-16 17:21:35 +0000229 g_string_append_c(buf, '}');
230 g_string_append_c(buf, c ^ 0x20);
pbrook56aebc82008-10-11 17:55:29 +0000231 break;
232 default:
Alex Bennée308f9e82020-03-16 17:21:35 +0000233 g_string_append_c(buf, c);
pbrook56aebc82008-10-11 17:55:29 +0000234 break;
235 }
236 }
pbrook56aebc82008-10-11 17:55:29 +0000237}
238
Alex Bennéea346af32020-03-16 17:21:34 +0000239static uint32_t gdb_get_cpu_pid(CPUState *cpu)
Luc Michel1a227332019-01-07 15:23:45 +0000240{
Luc Michel1a227332019-01-07 15:23:45 +0000241 /* TODO: In user mode, we should use the task state PID */
Peter Maydell46f5abc2019-01-29 11:46:06 +0000242 if (cpu->cluster_index == UNASSIGNED_CLUSTER_INDEX) {
243 /* Return the default process' PID */
Alex Bennéea346af32020-03-16 17:21:34 +0000244 int index = gdbserver_state.process_num - 1;
245 return gdbserver_state.processes[index].pid;
Peter Maydell46f5abc2019-01-29 11:46:06 +0000246 }
247 return cpu->cluster_index + 1;
Luc Michel1a227332019-01-07 15:23:45 +0000248}
249
Alex Bennéea346af32020-03-16 17:21:34 +0000250static GDBProcess *gdb_get_process(uint32_t pid)
Luc Michel7d8c87d2019-01-07 15:23:45 +0000251{
252 int i;
253
254 if (!pid) {
255 /* 0 means any process, we take the first one */
Alex Bennéea346af32020-03-16 17:21:34 +0000256 return &gdbserver_state.processes[0];
Luc Michel7d8c87d2019-01-07 15:23:45 +0000257 }
258
Alex Bennéea346af32020-03-16 17:21:34 +0000259 for (i = 0; i < gdbserver_state.process_num; i++) {
260 if (gdbserver_state.processes[i].pid == pid) {
261 return &gdbserver_state.processes[i];
Luc Michel7d8c87d2019-01-07 15:23:45 +0000262 }
263 }
264
265 return NULL;
266}
267
Alex Bennéea346af32020-03-16 17:21:34 +0000268static GDBProcess *gdb_get_cpu_process(CPUState *cpu)
Luc Michel7d8c87d2019-01-07 15:23:45 +0000269{
Alex Bennéea346af32020-03-16 17:21:34 +0000270 return gdb_get_process(gdb_get_cpu_pid(cpu));
Luc Michel7d8c87d2019-01-07 15:23:45 +0000271}
272
273static CPUState *find_cpu(uint32_t thread_id)
274{
275 CPUState *cpu;
276
277 CPU_FOREACH(cpu) {
Alex Bennée36e067b2023-03-02 18:57:45 -0800278 if (gdb_get_cpu_index(cpu) == thread_id) {
Luc Michel7d8c87d2019-01-07 15:23:45 +0000279 return cpu;
280 }
281 }
282
283 return NULL;
284}
285
Alex Bennéea346af32020-03-16 17:21:34 +0000286static CPUState *get_first_cpu_in_process(GDBProcess *process)
Luc Michele40e5202019-01-07 15:23:46 +0000287{
288 CPUState *cpu;
289
290 CPU_FOREACH(cpu) {
Alex Bennéea346af32020-03-16 17:21:34 +0000291 if (gdb_get_cpu_pid(cpu) == process->pid) {
Luc Michele40e5202019-01-07 15:23:46 +0000292 return cpu;
293 }
294 }
295
296 return NULL;
297}
298
Alex Bennéea346af32020-03-16 17:21:34 +0000299static CPUState *gdb_next_cpu_in_process(CPUState *cpu)
Luc Michele40e5202019-01-07 15:23:46 +0000300{
Alex Bennéea346af32020-03-16 17:21:34 +0000301 uint32_t pid = gdb_get_cpu_pid(cpu);
Luc Michele40e5202019-01-07 15:23:46 +0000302 cpu = CPU_NEXT(cpu);
303
304 while (cpu) {
Alex Bennéea346af32020-03-16 17:21:34 +0000305 if (gdb_get_cpu_pid(cpu) == pid) {
Luc Michele40e5202019-01-07 15:23:46 +0000306 break;
307 }
308
309 cpu = CPU_NEXT(cpu);
310 }
311
312 return cpu;
313}
314
Luc Michele40e5202019-01-07 15:23:46 +0000315/* Return the cpu following @cpu, while ignoring unattached processes. */
Alex Bennéea346af32020-03-16 17:21:34 +0000316static CPUState *gdb_next_attached_cpu(CPUState *cpu)
Luc Michele40e5202019-01-07 15:23:46 +0000317{
318 cpu = CPU_NEXT(cpu);
319
320 while (cpu) {
Alex Bennéea346af32020-03-16 17:21:34 +0000321 if (gdb_get_cpu_process(cpu)->attached) {
Luc Michele40e5202019-01-07 15:23:46 +0000322 break;
323 }
324
325 cpu = CPU_NEXT(cpu);
326 }
327
328 return cpu;
329}
330
331/* Return the first attached cpu */
Alex Bennée36e067b2023-03-02 18:57:45 -0800332CPUState *gdb_first_attached_cpu(void)
Luc Michele40e5202019-01-07 15:23:46 +0000333{
334 CPUState *cpu = first_cpu;
Alex Bennéea346af32020-03-16 17:21:34 +0000335 GDBProcess *process = gdb_get_cpu_process(cpu);
Luc Michele40e5202019-01-07 15:23:46 +0000336
337 if (!process->attached) {
Alex Bennéea346af32020-03-16 17:21:34 +0000338 return gdb_next_attached_cpu(cpu);
Luc Michele40e5202019-01-07 15:23:46 +0000339 }
340
341 return cpu;
342}
343
Alex Bennéea346af32020-03-16 17:21:34 +0000344static CPUState *gdb_get_cpu(uint32_t pid, uint32_t tid)
Luc Michelab65eed2019-01-29 11:46:03 +0000345{
346 GDBProcess *process;
347 CPUState *cpu;
348
349 if (!pid && !tid) {
350 /* 0 means any process/thread, we take the first attached one */
Alex Bennéea346af32020-03-16 17:21:34 +0000351 return gdb_first_attached_cpu();
Luc Michelab65eed2019-01-29 11:46:03 +0000352 } else if (pid && !tid) {
353 /* any thread in a specific process */
Alex Bennéea346af32020-03-16 17:21:34 +0000354 process = gdb_get_process(pid);
Luc Michelab65eed2019-01-29 11:46:03 +0000355
356 if (process == NULL) {
357 return NULL;
358 }
359
360 if (!process->attached) {
361 return NULL;
362 }
363
Alex Bennéea346af32020-03-16 17:21:34 +0000364 return get_first_cpu_in_process(process);
Luc Michelab65eed2019-01-29 11:46:03 +0000365 } else {
366 /* a specific thread */
367 cpu = find_cpu(tid);
368
369 if (cpu == NULL) {
370 return NULL;
371 }
372
Alex Bennéea346af32020-03-16 17:21:34 +0000373 process = gdb_get_cpu_process(cpu);
Luc Michelab65eed2019-01-29 11:46:03 +0000374
375 if (pid && process->pid != pid) {
376 return NULL;
377 }
378
379 if (!process->attached) {
380 return NULL;
381 }
382
383 return cpu;
384 }
385}
386
Alex Bennéea346af32020-03-16 17:21:34 +0000387static const char *get_feature_xml(const char *p, const char **newp,
388 GDBProcess *process)
pbrook56aebc82008-10-11 17:55:29 +0000389{
pbrook56aebc82008-10-11 17:55:29 +0000390 size_t len;
391 int i;
392 const char *name;
Alex Bennéea346af32020-03-16 17:21:34 +0000393 CPUState *cpu = get_first_cpu_in_process(process);
Luc Michelc145eea2019-01-07 15:23:46 +0000394 CPUClass *cc = CPU_GET_CLASS(cpu);
pbrook56aebc82008-10-11 17:55:29 +0000395
396 len = 0;
397 while (p[len] && p[len] != ':')
398 len++;
399 *newp = p + len;
400
401 name = NULL;
402 if (strncmp(p, "target.xml", len) == 0) {
Luc Michelc145eea2019-01-07 15:23:46 +0000403 char *buf = process->target_xml;
404 const size_t buf_sz = sizeof(process->target_xml);
pbrook56aebc82008-10-11 17:55:29 +0000405
Luc Michelc145eea2019-01-07 15:23:46 +0000406 /* Generate the XML description for this CPU. */
407 if (!buf[0]) {
408 GDBRegisterState *r;
409
410 pstrcat(buf, buf_sz,
David Hildenbrandb3820e62015-12-03 13:14:41 +0100411 "<?xml version=\"1.0\"?>"
412 "<!DOCTYPE target SYSTEM \"gdb-target.dtd\">"
413 "<target>");
414 if (cc->gdb_arch_name) {
415 gchar *arch = cc->gdb_arch_name(cpu);
Luc Michelc145eea2019-01-07 15:23:46 +0000416 pstrcat(buf, buf_sz, "<architecture>");
417 pstrcat(buf, buf_sz, arch);
418 pstrcat(buf, buf_sz, "</architecture>");
David Hildenbrandb3820e62015-12-03 13:14:41 +0100419 g_free(arch);
420 }
Luc Michelc145eea2019-01-07 15:23:46 +0000421 pstrcat(buf, buf_sz, "<xi:include href=\"");
422 pstrcat(buf, buf_sz, cc->gdb_core_xml_file);
423 pstrcat(buf, buf_sz, "\"/>");
Andreas Färbereac8b352013-06-28 21:11:37 +0200424 for (r = cpu->gdb_regs; r; r = r->next) {
Luc Michelc145eea2019-01-07 15:23:46 +0000425 pstrcat(buf, buf_sz, "<xi:include href=\"");
426 pstrcat(buf, buf_sz, r->xml);
427 pstrcat(buf, buf_sz, "\"/>");
pbrook56aebc82008-10-11 17:55:29 +0000428 }
Luc Michelc145eea2019-01-07 15:23:46 +0000429 pstrcat(buf, buf_sz, "</target>");
pbrook56aebc82008-10-11 17:55:29 +0000430 }
Luc Michelc145eea2019-01-07 15:23:46 +0000431 return buf;
pbrook56aebc82008-10-11 17:55:29 +0000432 }
Abdallah Bouassida200bf5b2018-05-18 17:48:07 +0100433 if (cc->gdb_get_dynamic_xml) {
Abdallah Bouassida200bf5b2018-05-18 17:48:07 +0100434 char *xmlname = g_strndup(p, len);
435 const char *xml = cc->gdb_get_dynamic_xml(cpu, xmlname);
436
437 g_free(xmlname);
438 if (xml) {
439 return xml;
440 }
441 }
pbrook56aebc82008-10-11 17:55:29 +0000442 for (i = 0; ; i++) {
443 name = xml_builtin[i][0];
444 if (!name || (strncmp(name, p, len) == 0 && strlen(name) == len))
445 break;
446 }
447 return name ? xml_builtin[i][1] : NULL;
448}
pbrook56aebc82008-10-11 17:55:29 +0000449
Alex Bennéea010bdb2020-03-16 17:21:41 +0000450static int gdb_read_register(CPUState *cpu, GByteArray *buf, int reg)
pbrook56aebc82008-10-11 17:55:29 +0000451{
Andreas Färbera0e372f2013-06-28 23:18:47 +0200452 CPUClass *cc = CPU_GET_CLASS(cpu);
Andreas Färber385b9f02013-06-27 18:25:36 +0200453 CPUArchState *env = cpu->env_ptr;
pbrook56aebc82008-10-11 17:55:29 +0000454 GDBRegisterState *r;
455
Andreas Färbera0e372f2013-06-28 23:18:47 +0200456 if (reg < cc->gdb_num_core_regs) {
Alex Bennéea010bdb2020-03-16 17:21:41 +0000457 return cc->gdb_read_register(cpu, buf, reg);
Andreas Färbera0e372f2013-06-28 23:18:47 +0200458 }
pbrook56aebc82008-10-11 17:55:29 +0000459
Andreas Färbereac8b352013-06-28 21:11:37 +0200460 for (r = cpu->gdb_regs; r; r = r->next) {
pbrook56aebc82008-10-11 17:55:29 +0000461 if (r->base_reg <= reg && reg < r->base_reg + r->num_regs) {
Alex Bennéea010bdb2020-03-16 17:21:41 +0000462 return r->get_reg(env, buf, reg - r->base_reg);
pbrook56aebc82008-10-11 17:55:29 +0000463 }
464 }
465 return 0;
466}
467
Andreas Färber385b9f02013-06-27 18:25:36 +0200468static int gdb_write_register(CPUState *cpu, uint8_t *mem_buf, int reg)
pbrook56aebc82008-10-11 17:55:29 +0000469{
Andreas Färbera0e372f2013-06-28 23:18:47 +0200470 CPUClass *cc = CPU_GET_CLASS(cpu);
Andreas Färber385b9f02013-06-27 18:25:36 +0200471 CPUArchState *env = cpu->env_ptr;
pbrook56aebc82008-10-11 17:55:29 +0000472 GDBRegisterState *r;
473
Andreas Färbera0e372f2013-06-28 23:18:47 +0200474 if (reg < cc->gdb_num_core_regs) {
Andreas Färber5b50e792013-06-29 04:18:45 +0200475 return cc->gdb_write_register(cpu, mem_buf, reg);
Andreas Färbera0e372f2013-06-28 23:18:47 +0200476 }
pbrook56aebc82008-10-11 17:55:29 +0000477
Andreas Färbereac8b352013-06-28 21:11:37 +0200478 for (r = cpu->gdb_regs; r; r = r->next) {
pbrook56aebc82008-10-11 17:55:29 +0000479 if (r->base_reg <= reg && reg < r->base_reg + r->num_regs) {
480 return r->set_reg(env, mem_buf, reg - r->base_reg);
481 }
482 }
483 return 0;
484}
485
486/* Register a supplemental set of CPU registers. If g_pos is nonzero it
487 specifies the first register number and these registers are included in
488 a standard "g" packet. Direction is relative to gdb, i.e. get_reg is
489 gdb reading a CPU register, and set_reg is gdb modifying a CPU register.
490 */
491
Andreas Färber22169d42013-06-28 21:27:39 +0200492void gdb_register_coprocessor(CPUState *cpu,
Alex Bennéea010bdb2020-03-16 17:21:41 +0000493 gdb_get_reg_cb get_reg, gdb_set_reg_cb set_reg,
Andreas Färber22169d42013-06-28 21:27:39 +0200494 int num_regs, const char *xml, int g_pos)
pbrook56aebc82008-10-11 17:55:29 +0000495{
496 GDBRegisterState *s;
497 GDBRegisterState **p;
pbrook56aebc82008-10-11 17:55:29 +0000498
Andreas Färbereac8b352013-06-28 21:11:37 +0200499 p = &cpu->gdb_regs;
pbrook56aebc82008-10-11 17:55:29 +0000500 while (*p) {
501 /* Check for duplicates. */
502 if (strcmp((*p)->xml, xml) == 0)
503 return;
504 p = &(*p)->next;
505 }
Stefan Weil9643c252011-10-18 22:25:38 +0200506
507 s = g_new0(GDBRegisterState, 1);
Andreas Färbera0e372f2013-06-28 23:18:47 +0200508 s->base_reg = cpu->gdb_num_regs;
Stefan Weil9643c252011-10-18 22:25:38 +0200509 s->num_regs = num_regs;
510 s->get_reg = get_reg;
511 s->set_reg = set_reg;
512 s->xml = xml;
513
pbrook56aebc82008-10-11 17:55:29 +0000514 /* Add to end of list. */
Andreas Färbera0e372f2013-06-28 23:18:47 +0200515 cpu->gdb_num_regs += num_regs;
pbrook56aebc82008-10-11 17:55:29 +0000516 *p = s;
517 if (g_pos) {
518 if (g_pos != s->base_reg) {
Ziyue Yang7ae6c572017-01-18 16:03:29 +0800519 error_report("Error: Bad gdb register numbering for '%s', "
520 "expected %d got %d", xml, g_pos, s->base_reg);
Andreas Färber35143f02013-08-12 18:09:47 +0200521 } else {
522 cpu->gdb_num_g_regs = cpu->gdb_num_regs;
pbrook56aebc82008-10-11 17:55:29 +0000523 }
524 }
525}
526
Alex Bennéea346af32020-03-16 17:21:34 +0000527static void gdb_process_breakpoint_remove_all(GDBProcess *p)
Luc Michel546f3c62019-01-07 15:23:46 +0000528{
Alex Bennéea346af32020-03-16 17:21:34 +0000529 CPUState *cpu = get_first_cpu_in_process(p);
Luc Michel546f3c62019-01-07 15:23:46 +0000530
531 while (cpu) {
Alex Bennéeae7467b2022-09-29 12:42:24 +0100532 gdb_breakpoint_remove_all(cpu);
Alex Bennéea346af32020-03-16 17:21:34 +0000533 cpu = gdb_next_cpu_in_process(cpu);
Luc Michel546f3c62019-01-07 15:23:46 +0000534 }
535}
536
aliguoria1d1bb32008-11-18 20:07:32 +0000537
Alex Bennéeb428ad12023-03-02 18:57:54 -0800538static void gdb_set_cpu_pc(vaddr pc)
aurel32fab9d282009-04-08 21:29:37 +0000539{
Alex Bennéea346af32020-03-16 17:21:34 +0000540 CPUState *cpu = gdbserver_state.c_cpu;
Andreas Färberf45748f2013-06-21 19:09:18 +0200541
542 cpu_synchronize_state(cpu);
Peter Crosthwaite4a2b24e2015-06-23 20:19:21 -0700543 cpu_set_pc(cpu, pc);
aurel32fab9d282009-04-08 21:29:37 +0000544}
545
Alex Bennée36e067b2023-03-02 18:57:45 -0800546void gdb_append_thread_id(CPUState *cpu, GString *buf)
Luc Michel1a227332019-01-07 15:23:45 +0000547{
Alex Bennéea346af32020-03-16 17:21:34 +0000548 if (gdbserver_state.multiprocess) {
Alex Bennée308f9e82020-03-16 17:21:35 +0000549 g_string_append_printf(buf, "p%02x.%02x",
Alex Bennée36e067b2023-03-02 18:57:45 -0800550 gdb_get_cpu_pid(cpu), gdb_get_cpu_index(cpu));
Luc Michel1a227332019-01-07 15:23:45 +0000551 } else {
Alex Bennée36e067b2023-03-02 18:57:45 -0800552 g_string_append_printf(buf, "%02x", gdb_get_cpu_index(cpu));
Luc Michel1a227332019-01-07 15:23:45 +0000553 }
Luc Michel1a227332019-01-07 15:23:45 +0000554}
555
Luc Michel7d8c87d2019-01-07 15:23:45 +0000556static GDBThreadIdKind read_thread_id(const char *buf, const char **end_buf,
557 uint32_t *pid, uint32_t *tid)
558{
559 unsigned long p, t;
560 int ret;
561
562 if (*buf == 'p') {
563 buf++;
564 ret = qemu_strtoul(buf, &buf, 16, &p);
565
566 if (ret) {
567 return GDB_READ_THREAD_ERR;
568 }
569
570 /* Skip '.' */
571 buf++;
572 } else {
573 p = 1;
574 }
575
576 ret = qemu_strtoul(buf, &buf, 16, &t);
577
578 if (ret) {
579 return GDB_READ_THREAD_ERR;
580 }
581
582 *end_buf = buf;
583
584 if (p == -1) {
585 return GDB_ALL_PROCESSES;
586 }
587
588 if (pid) {
589 *pid = p;
590 }
591
592 if (t == -1) {
593 return GDB_ALL_THREADS;
594 }
595
596 if (tid) {
597 *tid = t;
598 }
599
600 return GDB_ONE_THREAD;
601}
602
Claudio Imbrenda544177a2017-02-14 18:07:48 +0100603/**
604 * gdb_handle_vcont - Parses and handles a vCont packet.
605 * returns -ENOTSUP if a command is unsupported, -EINVAL or -ERANGE if there is
606 * a format error, 0 on success.
607 */
Alex Bennéea346af32020-03-16 17:21:34 +0000608static int gdb_handle_vcont(const char *p)
Claudio Imbrenda544177a2017-02-14 18:07:48 +0100609{
Luc Michele40e5202019-01-07 15:23:46 +0000610 int res, signal = 0;
Claudio Imbrenda544177a2017-02-14 18:07:48 +0100611 char cur_action;
612 char *newstates;
613 unsigned long tmp;
Luc Michele40e5202019-01-07 15:23:46 +0000614 uint32_t pid, tid;
615 GDBProcess *process;
Claudio Imbrenda544177a2017-02-14 18:07:48 +0100616 CPUState *cpu;
Luc Michelc99ef792019-03-26 12:53:26 +0000617 GDBThreadIdKind kind;
Alex Bennée7ea0c332023-03-02 18:57:52 -0800618 unsigned int max_cpus = gdb_get_max_cpus();
Claudio Imbrenda544177a2017-02-14 18:07:48 +0100619 /* uninitialised CPUs stay 0 */
620 newstates = g_new0(char, max_cpus);
621
622 /* mark valid CPUs with 1 */
623 CPU_FOREACH(cpu) {
624 newstates[cpu->cpu_index] = 1;
625 }
626
627 /*
628 * res keeps track of what error we are returning, with -ENOTSUP meaning
629 * that the command is unknown or unsupported, thus returning an empty
630 * packet, while -EINVAL and -ERANGE cause an E22 packet, due to invalid,
631 * or incorrect parameters passed.
632 */
633 res = 0;
634 while (*p) {
635 if (*p++ != ';') {
636 res = -ENOTSUP;
637 goto out;
638 }
639
640 cur_action = *p++;
641 if (cur_action == 'C' || cur_action == 'S') {
Peter Maydell95a5bef2017-07-20 17:31:30 +0100642 cur_action = qemu_tolower(cur_action);
Peter Maydell3ddd9032020-11-21 21:03:42 +0000643 res = qemu_strtoul(p, &p, 16, &tmp);
Claudio Imbrenda544177a2017-02-14 18:07:48 +0100644 if (res) {
645 goto out;
646 }
647 signal = gdb_signal_to_target(tmp);
648 } else if (cur_action != 'c' && cur_action != 's') {
649 /* unknown/invalid/unsupported command */
650 res = -ENOTSUP;
651 goto out;
652 }
Luc Michele40e5202019-01-07 15:23:46 +0000653
Luc Michelc99ef792019-03-26 12:53:26 +0000654 if (*p == '\0' || *p == ';') {
655 /*
656 * No thread specifier, action is on "all threads". The
657 * specification is unclear regarding the process to act on. We
658 * choose all processes.
659 */
660 kind = GDB_ALL_PROCESSES;
661 } else if (*p++ == ':') {
662 kind = read_thread_id(p, &p, &pid, &tid);
663 } else {
Luc Michele40e5202019-01-07 15:23:46 +0000664 res = -ENOTSUP;
665 goto out;
666 }
667
Luc Michelc99ef792019-03-26 12:53:26 +0000668 switch (kind) {
Luc Michele40e5202019-01-07 15:23:46 +0000669 case GDB_READ_THREAD_ERR:
670 res = -EINVAL;
671 goto out;
672
673 case GDB_ALL_PROCESSES:
Alex Bennéea346af32020-03-16 17:21:34 +0000674 cpu = gdb_first_attached_cpu();
Luc Michele40e5202019-01-07 15:23:46 +0000675 while (cpu) {
676 if (newstates[cpu->cpu_index] == 1) {
677 newstates[cpu->cpu_index] = cur_action;
Claudio Imbrenda544177a2017-02-14 18:07:48 +0100678 }
Luc Michele40e5202019-01-07 15:23:46 +0000679
Alex Bennéea346af32020-03-16 17:21:34 +0000680 cpu = gdb_next_attached_cpu(cpu);
Claudio Imbrenda544177a2017-02-14 18:07:48 +0100681 }
Luc Michele40e5202019-01-07 15:23:46 +0000682 break;
683
684 case GDB_ALL_THREADS:
Alex Bennéea346af32020-03-16 17:21:34 +0000685 process = gdb_get_process(pid);
Luc Michele40e5202019-01-07 15:23:46 +0000686
687 if (!process->attached) {
688 res = -EINVAL;
Claudio Imbrenda544177a2017-02-14 18:07:48 +0100689 goto out;
690 }
Claudio Imbrenda544177a2017-02-14 18:07:48 +0100691
Alex Bennéea346af32020-03-16 17:21:34 +0000692 cpu = get_first_cpu_in_process(process);
Luc Michele40e5202019-01-07 15:23:46 +0000693 while (cpu) {
694 if (newstates[cpu->cpu_index] == 1) {
695 newstates[cpu->cpu_index] = cur_action;
696 }
697
Alex Bennéea346af32020-03-16 17:21:34 +0000698 cpu = gdb_next_cpu_in_process(cpu);
Luc Michele40e5202019-01-07 15:23:46 +0000699 }
700 break;
701
702 case GDB_ONE_THREAD:
Alex Bennéea346af32020-03-16 17:21:34 +0000703 cpu = gdb_get_cpu(pid, tid);
Alex Bennée5a6a1ad2017-07-12 11:52:16 +0100704
Claudio Imbrenda544177a2017-02-14 18:07:48 +0100705 /* invalid CPU/thread specified */
Alex Bennée5a6a1ad2017-07-12 11:52:16 +0100706 if (!cpu) {
Claudio Imbrenda544177a2017-02-14 18:07:48 +0100707 res = -EINVAL;
708 goto out;
709 }
Alex Bennée5a6a1ad2017-07-12 11:52:16 +0100710
Claudio Imbrenda544177a2017-02-14 18:07:48 +0100711 /* only use if no previous match occourred */
712 if (newstates[cpu->cpu_index] == 1) {
713 newstates[cpu->cpu_index] = cur_action;
714 }
Luc Michele40e5202019-01-07 15:23:46 +0000715 break;
Claudio Imbrenda544177a2017-02-14 18:07:48 +0100716 }
717 }
Alex Bennéea346af32020-03-16 17:21:34 +0000718 gdbserver_state.signal = signal;
719 gdb_continue_partial(newstates);
Claudio Imbrenda544177a2017-02-14 18:07:48 +0100720
721out:
722 g_free(newstates);
723
724 return res;
725}
726
Jon Dorond14055d2019-05-29 09:41:29 +0300727static const char *cmd_next_param(const char *param, const char delimiter)
728{
729 static const char all_delimiters[] = ",;:=";
730 char curr_delimiters[2] = {0};
731 const char *delimiters;
732
733 if (delimiter == '?') {
734 delimiters = all_delimiters;
735 } else if (delimiter == '0') {
736 return strchr(param, '\0');
737 } else if (delimiter == '.' && *param) {
738 return param + 1;
739 } else {
740 curr_delimiters[0] = delimiter;
741 delimiters = curr_delimiters;
742 }
743
744 param += strcspn(param, delimiters);
745 if (*param) {
746 param++;
747 }
748 return param;
749}
750
751static int cmd_parse_params(const char *data, const char *schema,
Alex Bennée26a16182021-05-25 09:24:14 +0100752 GArray *params)
Jon Dorond14055d2019-05-29 09:41:29 +0300753{
Jon Dorond14055d2019-05-29 09:41:29 +0300754 const char *curr_schema, *curr_data;
755
Alex Bennée26a16182021-05-25 09:24:14 +0100756 g_assert(schema);
757 g_assert(params->len == 0);
Jon Dorond14055d2019-05-29 09:41:29 +0300758
759 curr_schema = schema;
Jon Dorond14055d2019-05-29 09:41:29 +0300760 curr_data = data;
761 while (curr_schema[0] && curr_schema[1] && *curr_data) {
Alex Bennée26a16182021-05-25 09:24:14 +0100762 GdbCmdVariant this_param;
763
Jon Dorond14055d2019-05-29 09:41:29 +0300764 switch (curr_schema[0]) {
765 case 'l':
766 if (qemu_strtoul(curr_data, &curr_data, 16,
Alex Bennée26a16182021-05-25 09:24:14 +0100767 &this_param.val_ul)) {
Jon Dorond14055d2019-05-29 09:41:29 +0300768 return -EINVAL;
769 }
Jon Dorond14055d2019-05-29 09:41:29 +0300770 curr_data = cmd_next_param(curr_data, curr_schema[1]);
Alex Bennée26a16182021-05-25 09:24:14 +0100771 g_array_append_val(params, this_param);
Jon Dorond14055d2019-05-29 09:41:29 +0300772 break;
773 case 'L':
774 if (qemu_strtou64(curr_data, &curr_data, 16,
Alex Bennée26a16182021-05-25 09:24:14 +0100775 (uint64_t *)&this_param.val_ull)) {
Jon Dorond14055d2019-05-29 09:41:29 +0300776 return -EINVAL;
777 }
Jon Dorond14055d2019-05-29 09:41:29 +0300778 curr_data = cmd_next_param(curr_data, curr_schema[1]);
Alex Bennée26a16182021-05-25 09:24:14 +0100779 g_array_append_val(params, this_param);
Jon Dorond14055d2019-05-29 09:41:29 +0300780 break;
781 case 's':
Alex Bennée26a16182021-05-25 09:24:14 +0100782 this_param.data = curr_data;
Jon Dorond14055d2019-05-29 09:41:29 +0300783 curr_data = cmd_next_param(curr_data, curr_schema[1]);
Alex Bennée26a16182021-05-25 09:24:14 +0100784 g_array_append_val(params, this_param);
Jon Dorond14055d2019-05-29 09:41:29 +0300785 break;
786 case 'o':
Alex Bennée26a16182021-05-25 09:24:14 +0100787 this_param.opcode = *(uint8_t *)curr_data;
Jon Dorond14055d2019-05-29 09:41:29 +0300788 curr_data = cmd_next_param(curr_data, curr_schema[1]);
Alex Bennée26a16182021-05-25 09:24:14 +0100789 g_array_append_val(params, this_param);
Jon Dorond14055d2019-05-29 09:41:29 +0300790 break;
791 case 't':
Alex Bennée26a16182021-05-25 09:24:14 +0100792 this_param.thread_id.kind =
Jon Dorond14055d2019-05-29 09:41:29 +0300793 read_thread_id(curr_data, &curr_data,
Alex Bennée26a16182021-05-25 09:24:14 +0100794 &this_param.thread_id.pid,
795 &this_param.thread_id.tid);
Jon Dorond14055d2019-05-29 09:41:29 +0300796 curr_data = cmd_next_param(curr_data, curr_schema[1]);
Alex Bennée26a16182021-05-25 09:24:14 +0100797 g_array_append_val(params, this_param);
Jon Dorond14055d2019-05-29 09:41:29 +0300798 break;
799 case '?':
800 curr_data = cmd_next_param(curr_data, curr_schema[1]);
801 break;
802 default:
803 return -EINVAL;
804 }
805 curr_schema += 2;
806 }
807
Jon Dorond14055d2019-05-29 09:41:29 +0300808 return 0;
809}
810
Alex Bennée26a16182021-05-25 09:24:14 +0100811typedef void (*GdbCmdHandler)(GArray *params, void *user_ctx);
Jon Dorond14055d2019-05-29 09:41:29 +0300812
813/*
814 * cmd_startswith -> cmd is compared using startswith
815 *
816 *
817 * schema definitions:
818 * Each schema parameter entry consists of 2 chars,
819 * the first char represents the parameter type handling
820 * the second char represents the delimiter for the next parameter
821 *
822 * Currently supported schema types:
823 * 'l' -> unsigned long (stored in .val_ul)
824 * 'L' -> unsigned long long (stored in .val_ull)
825 * 's' -> string (stored in .data)
826 * 'o' -> single char (stored in .opcode)
827 * 't' -> thread id (stored in .thread_id)
828 * '?' -> skip according to delimiter
829 *
830 * Currently supported delimiters:
831 * '?' -> Stop at any delimiter (",;:=\0")
832 * '0' -> Stop at "\0"
833 * '.' -> Skip 1 char unless reached "\0"
834 * Any other value is treated as the delimiter value itself
835 */
836typedef struct GdbCmdParseEntry {
837 GdbCmdHandler handler;
838 const char *cmd;
839 bool cmd_startswith;
840 const char *schema;
841} GdbCmdParseEntry;
842
843static inline int startswith(const char *string, const char *pattern)
844{
845 return !strncmp(string, pattern, strlen(pattern));
846}
847
Alex Bennéea346af32020-03-16 17:21:34 +0000848static int process_string_cmd(void *user_ctx, const char *data,
Jon Dorond14055d2019-05-29 09:41:29 +0300849 const GdbCmdParseEntry *cmds, int num_cmds)
850{
Alex Bennée26a16182021-05-25 09:24:14 +0100851 int i;
852 g_autoptr(GArray) params = g_array_new(false, true, sizeof(GdbCmdVariant));
Jon Dorond14055d2019-05-29 09:41:29 +0300853
854 if (!cmds) {
855 return -1;
856 }
857
858 for (i = 0; i < num_cmds; i++) {
859 const GdbCmdParseEntry *cmd = &cmds[i];
860 g_assert(cmd->handler && cmd->cmd);
861
862 if ((cmd->cmd_startswith && !startswith(data, cmd->cmd)) ||
863 (!cmd->cmd_startswith && strcmp(cmd->cmd, data))) {
864 continue;
865 }
866
867 if (cmd->schema) {
Alex Bennée26a16182021-05-25 09:24:14 +0100868 if (cmd_parse_params(&data[strlen(cmd->cmd)],
869 cmd->schema, params)) {
870 return -1;
Jon Dorond14055d2019-05-29 09:41:29 +0300871 }
Jon Dorond14055d2019-05-29 09:41:29 +0300872 }
873
Alex Bennée26a16182021-05-25 09:24:14 +0100874 cmd->handler(params, user_ctx);
Jon Dorond14055d2019-05-29 09:41:29 +0300875 return 0;
876 }
877
878 return -1;
879}
880
Alex Bennéea346af32020-03-16 17:21:34 +0000881static void run_cmd_parser(const char *data, const GdbCmdParseEntry *cmd)
Jon Doron3e2c1262019-05-29 09:41:30 +0300882{
883 if (!data) {
884 return;
885 }
886
Alex Bennée308f9e82020-03-16 17:21:35 +0000887 g_string_set_size(gdbserver_state.str_buf, 0);
Alex Bennée4a25f1b2020-03-16 17:21:36 +0000888 g_byte_array_set_size(gdbserver_state.mem_buf, 0);
Alex Bennée308f9e82020-03-16 17:21:35 +0000889
Jon Doron3e2c1262019-05-29 09:41:30 +0300890 /* In case there was an error during the command parsing we must
891 * send a NULL packet to indicate the command is not supported */
Alex Bennéea346af32020-03-16 17:21:34 +0000892 if (process_string_cmd(NULL, data, cmd, 1)) {
Alex Bennée36e067b2023-03-02 18:57:45 -0800893 gdb_put_packet("");
Jon Doron3e2c1262019-05-29 09:41:30 +0300894 }
895}
896
Alex Bennée26a16182021-05-25 09:24:14 +0100897static void handle_detach(GArray *params, void *user_ctx)
Jon Doron3e2c1262019-05-29 09:41:30 +0300898{
899 GDBProcess *process;
Jon Doron3e2c1262019-05-29 09:41:30 +0300900 uint32_t pid = 1;
901
Alex Bennéea346af32020-03-16 17:21:34 +0000902 if (gdbserver_state.multiprocess) {
Alex Bennée26a16182021-05-25 09:24:14 +0100903 if (!params->len) {
Alex Bennée36e067b2023-03-02 18:57:45 -0800904 gdb_put_packet("E22");
Jon Doron3e2c1262019-05-29 09:41:30 +0300905 return;
906 }
907
Alex Bennée26a16182021-05-25 09:24:14 +0100908 pid = get_param(params, 0)->val_ul;
Jon Doron3e2c1262019-05-29 09:41:30 +0300909 }
910
Alex Bennéea346af32020-03-16 17:21:34 +0000911 process = gdb_get_process(pid);
912 gdb_process_breakpoint_remove_all(process);
Jon Doron3e2c1262019-05-29 09:41:30 +0300913 process->attached = false;
914
Alex Bennéea346af32020-03-16 17:21:34 +0000915 if (pid == gdb_get_cpu_pid(gdbserver_state.c_cpu)) {
916 gdbserver_state.c_cpu = gdb_first_attached_cpu();
Jon Doron3e2c1262019-05-29 09:41:30 +0300917 }
918
Alex Bennéea346af32020-03-16 17:21:34 +0000919 if (pid == gdb_get_cpu_pid(gdbserver_state.g_cpu)) {
920 gdbserver_state.g_cpu = gdb_first_attached_cpu();
Jon Doron3e2c1262019-05-29 09:41:30 +0300921 }
922
Alex Bennéea346af32020-03-16 17:21:34 +0000923 if (!gdbserver_state.c_cpu) {
Jon Doron3e2c1262019-05-29 09:41:30 +0300924 /* No more process attached */
925 gdb_syscall_mode = GDB_SYS_DISABLED;
Alex Bennéea346af32020-03-16 17:21:34 +0000926 gdb_continue();
Jon Doron3e2c1262019-05-29 09:41:30 +0300927 }
Alex Bennée36e067b2023-03-02 18:57:45 -0800928 gdb_put_packet("OK");
Jon Doron3e2c1262019-05-29 09:41:30 +0300929}
930
Alex Bennée26a16182021-05-25 09:24:14 +0100931static void handle_thread_alive(GArray *params, void *user_ctx)
Jon Doron44ffded2019-05-29 09:41:31 +0300932{
933 CPUState *cpu;
934
Alex Bennée26a16182021-05-25 09:24:14 +0100935 if (!params->len) {
Alex Bennée36e067b2023-03-02 18:57:45 -0800936 gdb_put_packet("E22");
Jon Doron44ffded2019-05-29 09:41:31 +0300937 return;
938 }
939
Alex Bennée26a16182021-05-25 09:24:14 +0100940 if (get_param(params, 0)->thread_id.kind == GDB_READ_THREAD_ERR) {
Alex Bennée36e067b2023-03-02 18:57:45 -0800941 gdb_put_packet("E22");
Jon Doron44ffded2019-05-29 09:41:31 +0300942 return;
943 }
944
Alex Bennée26a16182021-05-25 09:24:14 +0100945 cpu = gdb_get_cpu(get_param(params, 0)->thread_id.pid,
946 get_param(params, 0)->thread_id.tid);
Jon Doron44ffded2019-05-29 09:41:31 +0300947 if (!cpu) {
Alex Bennée36e067b2023-03-02 18:57:45 -0800948 gdb_put_packet("E22");
Jon Doron44ffded2019-05-29 09:41:31 +0300949 return;
950 }
951
Alex Bennée36e067b2023-03-02 18:57:45 -0800952 gdb_put_packet("OK");
Jon Doron44ffded2019-05-29 09:41:31 +0300953}
954
Alex Bennée26a16182021-05-25 09:24:14 +0100955static void handle_continue(GArray *params, void *user_ctx)
Jon Doron4d6e3fe2019-05-29 09:41:32 +0300956{
Alex Bennée26a16182021-05-25 09:24:14 +0100957 if (params->len) {
958 gdb_set_cpu_pc(get_param(params, 0)->val_ull);
Jon Doron4d6e3fe2019-05-29 09:41:32 +0300959 }
960
Alex Bennéea346af32020-03-16 17:21:34 +0000961 gdbserver_state.signal = 0;
962 gdb_continue();
Jon Doron4d6e3fe2019-05-29 09:41:32 +0300963}
964
Alex Bennée26a16182021-05-25 09:24:14 +0100965static void handle_cont_with_sig(GArray *params, void *user_ctx)
Jon Doronccc47d52019-05-29 09:41:33 +0300966{
967 unsigned long signal = 0;
968
969 /*
970 * Note: C sig;[addr] is currently unsupported and we simply
971 * omit the addr parameter
972 */
Alex Bennée26a16182021-05-25 09:24:14 +0100973 if (params->len) {
974 signal = get_param(params, 0)->val_ul;
Jon Doronccc47d52019-05-29 09:41:33 +0300975 }
976
Alex Bennéea346af32020-03-16 17:21:34 +0000977 gdbserver_state.signal = gdb_signal_to_target(signal);
978 if (gdbserver_state.signal == -1) {
979 gdbserver_state.signal = 0;
Jon Doronccc47d52019-05-29 09:41:33 +0300980 }
Alex Bennéea346af32020-03-16 17:21:34 +0000981 gdb_continue();
Jon Doronccc47d52019-05-29 09:41:33 +0300982}
983
Alex Bennée26a16182021-05-25 09:24:14 +0100984static void handle_set_thread(GArray *params, void *user_ctx)
Jon Doron3a9651d2019-05-29 09:41:34 +0300985{
986 CPUState *cpu;
987
Alex Bennée26a16182021-05-25 09:24:14 +0100988 if (params->len != 2) {
Alex Bennée36e067b2023-03-02 18:57:45 -0800989 gdb_put_packet("E22");
Jon Doron3a9651d2019-05-29 09:41:34 +0300990 return;
991 }
992
Alex Bennée26a16182021-05-25 09:24:14 +0100993 if (get_param(params, 1)->thread_id.kind == GDB_READ_THREAD_ERR) {
Alex Bennée36e067b2023-03-02 18:57:45 -0800994 gdb_put_packet("E22");
Jon Doron3a9651d2019-05-29 09:41:34 +0300995 return;
996 }
997
Alex Bennée26a16182021-05-25 09:24:14 +0100998 if (get_param(params, 1)->thread_id.kind != GDB_ONE_THREAD) {
Alex Bennée36e067b2023-03-02 18:57:45 -0800999 gdb_put_packet("OK");
Jon Doron3a9651d2019-05-29 09:41:34 +03001000 return;
1001 }
1002
Alex Bennée26a16182021-05-25 09:24:14 +01001003 cpu = gdb_get_cpu(get_param(params, 1)->thread_id.pid,
1004 get_param(params, 1)->thread_id.tid);
Jon Doron3a9651d2019-05-29 09:41:34 +03001005 if (!cpu) {
Alex Bennée36e067b2023-03-02 18:57:45 -08001006 gdb_put_packet("E22");
Jon Doron3a9651d2019-05-29 09:41:34 +03001007 return;
1008 }
1009
1010 /*
1011 * Note: This command is deprecated and modern gdb's will be using the
1012 * vCont command instead.
1013 */
Alex Bennée26a16182021-05-25 09:24:14 +01001014 switch (get_param(params, 0)->opcode) {
Jon Doron3a9651d2019-05-29 09:41:34 +03001015 case 'c':
Alex Bennéea346af32020-03-16 17:21:34 +00001016 gdbserver_state.c_cpu = cpu;
Alex Bennée36e067b2023-03-02 18:57:45 -08001017 gdb_put_packet("OK");
Jon Doron3a9651d2019-05-29 09:41:34 +03001018 break;
1019 case 'g':
Alex Bennéea346af32020-03-16 17:21:34 +00001020 gdbserver_state.g_cpu = cpu;
Alex Bennée36e067b2023-03-02 18:57:45 -08001021 gdb_put_packet("OK");
Jon Doron3a9651d2019-05-29 09:41:34 +03001022 break;
1023 default:
Alex Bennée36e067b2023-03-02 18:57:45 -08001024 gdb_put_packet("E22");
Jon Doron3a9651d2019-05-29 09:41:34 +03001025 break;
1026 }
1027}
1028
Alex Bennée26a16182021-05-25 09:24:14 +01001029static void handle_insert_bp(GArray *params, void *user_ctx)
Jon Doron77f6ce52019-05-29 09:41:35 +03001030{
1031 int res;
1032
Alex Bennée26a16182021-05-25 09:24:14 +01001033 if (params->len != 3) {
Alex Bennée36e067b2023-03-02 18:57:45 -08001034 gdb_put_packet("E22");
Jon Doron77f6ce52019-05-29 09:41:35 +03001035 return;
1036 }
1037
Alex Bennéeae7467b2022-09-29 12:42:24 +01001038 res = gdb_breakpoint_insert(gdbserver_state.c_cpu,
1039 get_param(params, 0)->val_ul,
Alex Bennée26a16182021-05-25 09:24:14 +01001040 get_param(params, 1)->val_ull,
1041 get_param(params, 2)->val_ull);
Jon Doron77f6ce52019-05-29 09:41:35 +03001042 if (res >= 0) {
Alex Bennée36e067b2023-03-02 18:57:45 -08001043 gdb_put_packet("OK");
Jon Doron77f6ce52019-05-29 09:41:35 +03001044 return;
1045 } else if (res == -ENOSYS) {
Alex Bennée36e067b2023-03-02 18:57:45 -08001046 gdb_put_packet("");
Jon Doron77f6ce52019-05-29 09:41:35 +03001047 return;
1048 }
1049
Alex Bennée36e067b2023-03-02 18:57:45 -08001050 gdb_put_packet("E22");
Jon Doron77f6ce52019-05-29 09:41:35 +03001051}
1052
Alex Bennée26a16182021-05-25 09:24:14 +01001053static void handle_remove_bp(GArray *params, void *user_ctx)
Jon Doron77f6ce52019-05-29 09:41:35 +03001054{
1055 int res;
1056
Alex Bennée26a16182021-05-25 09:24:14 +01001057 if (params->len != 3) {
Alex Bennée36e067b2023-03-02 18:57:45 -08001058 gdb_put_packet("E22");
Jon Doron77f6ce52019-05-29 09:41:35 +03001059 return;
1060 }
1061
Alex Bennéeae7467b2022-09-29 12:42:24 +01001062 res = gdb_breakpoint_remove(gdbserver_state.c_cpu,
1063 get_param(params, 0)->val_ul,
Alex Bennée26a16182021-05-25 09:24:14 +01001064 get_param(params, 1)->val_ull,
1065 get_param(params, 2)->val_ull);
Jon Doron77f6ce52019-05-29 09:41:35 +03001066 if (res >= 0) {
Alex Bennée36e067b2023-03-02 18:57:45 -08001067 gdb_put_packet("OK");
Jon Doron77f6ce52019-05-29 09:41:35 +03001068 return;
1069 } else if (res == -ENOSYS) {
Alex Bennée36e067b2023-03-02 18:57:45 -08001070 gdb_put_packet("");
Jon Doron77f6ce52019-05-29 09:41:35 +03001071 return;
1072 }
1073
Alex Bennée36e067b2023-03-02 18:57:45 -08001074 gdb_put_packet("E22");
Jon Doron77f6ce52019-05-29 09:41:35 +03001075}
1076
Alex Bennée94b2a622019-07-05 14:23:07 +01001077/*
1078 * handle_set/get_reg
1079 *
1080 * Older gdb are really dumb, and don't use 'G/g' if 'P/p' is available.
1081 * This works, but can be very slow. Anything new enough to understand
1082 * XML also knows how to use this properly. However to use this we
1083 * need to define a local XML file as well as be talking to a
1084 * reasonably modern gdb. Responding with an empty packet will cause
1085 * the remote gdb to fallback to older methods.
1086 */
1087
Alex Bennée26a16182021-05-25 09:24:14 +01001088static void handle_set_reg(GArray *params, void *user_ctx)
Jon Doron62b33202019-05-29 09:41:36 +03001089{
1090 int reg_size;
1091
1092 if (!gdb_has_xml) {
Alex Bennée36e067b2023-03-02 18:57:45 -08001093 gdb_put_packet("");
Jon Doron62b33202019-05-29 09:41:36 +03001094 return;
1095 }
1096
Alex Bennée26a16182021-05-25 09:24:14 +01001097 if (params->len != 2) {
Alex Bennée36e067b2023-03-02 18:57:45 -08001098 gdb_put_packet("E22");
Jon Doron62b33202019-05-29 09:41:36 +03001099 return;
1100 }
1101
Alex Bennée26a16182021-05-25 09:24:14 +01001102 reg_size = strlen(get_param(params, 1)->data) / 2;
Alex Bennée36e067b2023-03-02 18:57:45 -08001103 gdb_hextomem(gdbserver_state.mem_buf, get_param(params, 1)->data, reg_size);
Alex Bennée4a25f1b2020-03-16 17:21:36 +00001104 gdb_write_register(gdbserver_state.g_cpu, gdbserver_state.mem_buf->data,
Alex Bennée26a16182021-05-25 09:24:14 +01001105 get_param(params, 0)->val_ull);
Alex Bennée36e067b2023-03-02 18:57:45 -08001106 gdb_put_packet("OK");
Jon Doron62b33202019-05-29 09:41:36 +03001107}
1108
Alex Bennée26a16182021-05-25 09:24:14 +01001109static void handle_get_reg(GArray *params, void *user_ctx)
Jon Doron5d0e57b2019-05-29 09:41:37 +03001110{
1111 int reg_size;
1112
Jon Doron5d0e57b2019-05-29 09:41:37 +03001113 if (!gdb_has_xml) {
Alex Bennée36e067b2023-03-02 18:57:45 -08001114 gdb_put_packet("");
Jon Doron5d0e57b2019-05-29 09:41:37 +03001115 return;
1116 }
1117
Alex Bennée26a16182021-05-25 09:24:14 +01001118 if (!params->len) {
Alex Bennée36e067b2023-03-02 18:57:45 -08001119 gdb_put_packet("E14");
Jon Doron5d0e57b2019-05-29 09:41:37 +03001120 return;
1121 }
1122
Alex Bennée4a25f1b2020-03-16 17:21:36 +00001123 reg_size = gdb_read_register(gdbserver_state.g_cpu,
Alex Bennéea010bdb2020-03-16 17:21:41 +00001124 gdbserver_state.mem_buf,
Alex Bennée26a16182021-05-25 09:24:14 +01001125 get_param(params, 0)->val_ull);
Jon Doron5d0e57b2019-05-29 09:41:37 +03001126 if (!reg_size) {
Alex Bennée36e067b2023-03-02 18:57:45 -08001127 gdb_put_packet("E14");
Jon Doron5d0e57b2019-05-29 09:41:37 +03001128 return;
Alex Bennée4a25f1b2020-03-16 17:21:36 +00001129 } else {
1130 g_byte_array_set_size(gdbserver_state.mem_buf, reg_size);
Jon Doron5d0e57b2019-05-29 09:41:37 +03001131 }
1132
Alex Bennée36e067b2023-03-02 18:57:45 -08001133 gdb_memtohex(gdbserver_state.str_buf,
1134 gdbserver_state.mem_buf->data, reg_size);
1135 gdb_put_strbuf();
Jon Doron5d0e57b2019-05-29 09:41:37 +03001136}
1137
Alex Bennée26a16182021-05-25 09:24:14 +01001138static void handle_write_mem(GArray *params, void *user_ctx)
Jon Doroncc0ecc72019-05-29 09:41:38 +03001139{
Alex Bennée26a16182021-05-25 09:24:14 +01001140 if (params->len != 3) {
Alex Bennée36e067b2023-03-02 18:57:45 -08001141 gdb_put_packet("E22");
Jon Doroncc0ecc72019-05-29 09:41:38 +03001142 return;
1143 }
1144
Alex Bennée36e067b2023-03-02 18:57:45 -08001145 /* gdb_hextomem() reads 2*len bytes */
Alex Bennée26a16182021-05-25 09:24:14 +01001146 if (get_param(params, 1)->val_ull >
1147 strlen(get_param(params, 2)->data) / 2) {
Alex Bennée36e067b2023-03-02 18:57:45 -08001148 gdb_put_packet("E22");
Jon Doroncc0ecc72019-05-29 09:41:38 +03001149 return;
1150 }
1151
Alex Bennée36e067b2023-03-02 18:57:45 -08001152 gdb_hextomem(gdbserver_state.mem_buf, get_param(params, 2)->data,
Alex Bennée589a5862023-03-02 18:57:51 -08001153 get_param(params, 1)->val_ull);
1154 if (gdb_target_memory_rw_debug(gdbserver_state.g_cpu,
1155 get_param(params, 0)->val_ull,
1156 gdbserver_state.mem_buf->data,
1157 gdbserver_state.mem_buf->len, true)) {
Alex Bennée36e067b2023-03-02 18:57:45 -08001158 gdb_put_packet("E14");
Jon Doroncc0ecc72019-05-29 09:41:38 +03001159 return;
1160 }
1161
Alex Bennée36e067b2023-03-02 18:57:45 -08001162 gdb_put_packet("OK");
Jon Doroncc0ecc72019-05-29 09:41:38 +03001163}
1164
Alex Bennée26a16182021-05-25 09:24:14 +01001165static void handle_read_mem(GArray *params, void *user_ctx)
Jon Doronda92e232019-05-29 09:41:39 +03001166{
Alex Bennée26a16182021-05-25 09:24:14 +01001167 if (params->len != 2) {
Alex Bennée36e067b2023-03-02 18:57:45 -08001168 gdb_put_packet("E22");
Jon Doronda92e232019-05-29 09:41:39 +03001169 return;
1170 }
1171
Alex Bennée36e067b2023-03-02 18:57:45 -08001172 /* gdb_memtohex() doubles the required space */
Alex Bennée26a16182021-05-25 09:24:14 +01001173 if (get_param(params, 1)->val_ull > MAX_PACKET_LENGTH / 2) {
Alex Bennée36e067b2023-03-02 18:57:45 -08001174 gdb_put_packet("E22");
Jon Doronda92e232019-05-29 09:41:39 +03001175 return;
1176 }
1177
Alex Bennée26a16182021-05-25 09:24:14 +01001178 g_byte_array_set_size(gdbserver_state.mem_buf,
1179 get_param(params, 1)->val_ull);
Alex Bennée4a25f1b2020-03-16 17:21:36 +00001180
Alex Bennée589a5862023-03-02 18:57:51 -08001181 if (gdb_target_memory_rw_debug(gdbserver_state.g_cpu,
1182 get_param(params, 0)->val_ull,
1183 gdbserver_state.mem_buf->data,
1184 gdbserver_state.mem_buf->len, false)) {
Alex Bennée36e067b2023-03-02 18:57:45 -08001185 gdb_put_packet("E14");
Jon Doronda92e232019-05-29 09:41:39 +03001186 return;
1187 }
1188
Alex Bennée36e067b2023-03-02 18:57:45 -08001189 gdb_memtohex(gdbserver_state.str_buf, gdbserver_state.mem_buf->data,
Alex Bennée4a25f1b2020-03-16 17:21:36 +00001190 gdbserver_state.mem_buf->len);
Alex Bennée36e067b2023-03-02 18:57:45 -08001191 gdb_put_strbuf();
Jon Doronda92e232019-05-29 09:41:39 +03001192}
1193
Alex Bennée26a16182021-05-25 09:24:14 +01001194static void handle_write_all_regs(GArray *params, void *user_ctx)
Jon Doron287ca122019-05-29 09:41:40 +03001195{
Alex Bennée379b42e2023-03-02 18:57:55 -08001196 int reg_id;
1197 size_t len;
Jon Doron287ca122019-05-29 09:41:40 +03001198 uint8_t *registers;
1199 int reg_size;
1200
Alex Bennée26a16182021-05-25 09:24:14 +01001201 if (!params->len) {
Jon Doron287ca122019-05-29 09:41:40 +03001202 return;
1203 }
1204
Alex Bennéea346af32020-03-16 17:21:34 +00001205 cpu_synchronize_state(gdbserver_state.g_cpu);
Alex Bennée26a16182021-05-25 09:24:14 +01001206 len = strlen(get_param(params, 0)->data) / 2;
Alex Bennée36e067b2023-03-02 18:57:45 -08001207 gdb_hextomem(gdbserver_state.mem_buf, get_param(params, 0)->data, len);
Alex Bennée4a25f1b2020-03-16 17:21:36 +00001208 registers = gdbserver_state.mem_buf->data;
Alex Bennée379b42e2023-03-02 18:57:55 -08001209 for (reg_id = 0;
1210 reg_id < gdbserver_state.g_cpu->gdb_num_g_regs && len > 0;
1211 reg_id++) {
1212 reg_size = gdb_write_register(gdbserver_state.g_cpu, registers, reg_id);
Jon Doron287ca122019-05-29 09:41:40 +03001213 len -= reg_size;
1214 registers += reg_size;
1215 }
Alex Bennée36e067b2023-03-02 18:57:45 -08001216 gdb_put_packet("OK");
Jon Doron287ca122019-05-29 09:41:40 +03001217}
1218
Alex Bennée26a16182021-05-25 09:24:14 +01001219static void handle_read_all_regs(GArray *params, void *user_ctx)
Jon Doron397d1372019-05-29 09:41:41 +03001220{
Alex Bennée379b42e2023-03-02 18:57:55 -08001221 int reg_id;
1222 size_t len;
Jon Doron397d1372019-05-29 09:41:41 +03001223
Alex Bennéea346af32020-03-16 17:21:34 +00001224 cpu_synchronize_state(gdbserver_state.g_cpu);
Alex Bennéea010bdb2020-03-16 17:21:41 +00001225 g_byte_array_set_size(gdbserver_state.mem_buf, 0);
Jon Doron397d1372019-05-29 09:41:41 +03001226 len = 0;
Alex Bennée379b42e2023-03-02 18:57:55 -08001227 for (reg_id = 0; reg_id < gdbserver_state.g_cpu->gdb_num_g_regs; reg_id++) {
Alex Bennée4a25f1b2020-03-16 17:21:36 +00001228 len += gdb_read_register(gdbserver_state.g_cpu,
Alex Bennéea010bdb2020-03-16 17:21:41 +00001229 gdbserver_state.mem_buf,
Alex Bennée379b42e2023-03-02 18:57:55 -08001230 reg_id);
Jon Doron397d1372019-05-29 09:41:41 +03001231 }
Alex Bennéea010bdb2020-03-16 17:21:41 +00001232 g_assert(len == gdbserver_state.mem_buf->len);
Jon Doron397d1372019-05-29 09:41:41 +03001233
Alex Bennée36e067b2023-03-02 18:57:45 -08001234 gdb_memtohex(gdbserver_state.str_buf, gdbserver_state.mem_buf->data, len);
1235 gdb_put_strbuf();
Jon Doron397d1372019-05-29 09:41:41 +03001236}
1237
Alex Bennée26a16182021-05-25 09:24:14 +01001238static void handle_file_io(GArray *params, void *user_ctx)
Jon Doron4b20fab2019-05-29 09:41:42 +03001239{
Alex Bennée26a16182021-05-25 09:24:14 +01001240 if (params->len >= 1 && gdbserver_state.current_syscall_cb) {
Richard Henderson64c8c6a2022-04-29 16:21:43 -07001241 uint64_t ret;
1242 int err;
Jon Doron4b20fab2019-05-29 09:41:42 +03001243
Richard Henderson64c8c6a2022-04-29 16:21:43 -07001244 ret = get_param(params, 0)->val_ull;
Alex Bennée26a16182021-05-25 09:24:14 +01001245 if (params->len >= 2) {
Richard Henderson64c8c6a2022-04-29 16:21:43 -07001246 err = get_param(params, 1)->val_ull;
Sandra Loosemorec6ee9522019-08-27 16:33:17 -06001247 } else {
1248 err = 0;
1249 }
Richard Hendersonc805e112022-06-07 12:38:26 -07001250
1251 /* Convert GDB error numbers back to host error numbers. */
1252#define E(X) case GDB_E##X: err = E##X; break
1253 switch (err) {
1254 case 0:
1255 break;
1256 E(PERM);
1257 E(NOENT);
1258 E(INTR);
1259 E(BADF);
1260 E(ACCES);
1261 E(FAULT);
1262 E(BUSY);
1263 E(EXIST);
1264 E(NODEV);
1265 E(NOTDIR);
1266 E(ISDIR);
1267 E(INVAL);
1268 E(NFILE);
1269 E(MFILE);
1270 E(FBIG);
1271 E(NOSPC);
1272 E(SPIPE);
1273 E(ROFS);
1274 E(NAMETOOLONG);
1275 default:
1276 err = EINVAL;
1277 break;
1278 }
1279#undef E
1280
Alex Bennéea346af32020-03-16 17:21:34 +00001281 gdbserver_state.current_syscall_cb(gdbserver_state.c_cpu, ret, err);
1282 gdbserver_state.current_syscall_cb = NULL;
Jon Doron4b20fab2019-05-29 09:41:42 +03001283 }
1284
Alex Bennée26a16182021-05-25 09:24:14 +01001285 if (params->len >= 3 && get_param(params, 2)->opcode == (uint8_t)'C') {
Alex Bennée36e067b2023-03-02 18:57:45 -08001286 gdb_put_packet("T02");
Jon Doron4b20fab2019-05-29 09:41:42 +03001287 return;
1288 }
1289
Alex Bennéea346af32020-03-16 17:21:34 +00001290 gdb_continue();
Jon Doron4b20fab2019-05-29 09:41:42 +03001291}
1292
Alex Bennée26a16182021-05-25 09:24:14 +01001293static void handle_step(GArray *params, void *user_ctx)
Jon Doron933f80d2019-05-29 09:41:43 +03001294{
Alex Bennée26a16182021-05-25 09:24:14 +01001295 if (params->len) {
Alex Bennéeb428ad12023-03-02 18:57:54 -08001296 gdb_set_cpu_pc(get_param(params, 0)->val_ull);
Jon Doron933f80d2019-05-29 09:41:43 +03001297 }
1298
Maxim Levitskyecd39d62021-11-11 12:06:02 +01001299 cpu_single_step(gdbserver_state.c_cpu, gdbserver_state.sstep_flags);
Alex Bennéea346af32020-03-16 17:21:34 +00001300 gdb_continue();
Jon Doron933f80d2019-05-29 09:41:43 +03001301}
1302
Alex Bennée26a16182021-05-25 09:24:14 +01001303static void handle_backward(GArray *params, void *user_ctx)
Pavel Dovgalyukfda84582020-10-03 20:13:43 +03001304{
Alex Bennée505601d2023-03-02 18:57:53 -08001305 if (!gdb_can_reverse()) {
Alex Bennée36e067b2023-03-02 18:57:45 -08001306 gdb_put_packet("E22");
Pavel Dovgalyukfda84582020-10-03 20:13:43 +03001307 }
Alex Bennée26a16182021-05-25 09:24:14 +01001308 if (params->len == 1) {
1309 switch (get_param(params, 0)->opcode) {
Pavel Dovgalyukfda84582020-10-03 20:13:43 +03001310 case 's':
1311 if (replay_reverse_step()) {
1312 gdb_continue();
1313 } else {
Alex Bennée36e067b2023-03-02 18:57:45 -08001314 gdb_put_packet("E14");
Pavel Dovgalyukfda84582020-10-03 20:13:43 +03001315 }
1316 return;
Pavel Dovgalyukcda38252020-10-03 20:13:49 +03001317 case 'c':
1318 if (replay_reverse_continue()) {
1319 gdb_continue();
1320 } else {
Alex Bennée36e067b2023-03-02 18:57:45 -08001321 gdb_put_packet("E14");
Pavel Dovgalyukcda38252020-10-03 20:13:49 +03001322 }
1323 return;
Pavel Dovgalyukfda84582020-10-03 20:13:43 +03001324 }
1325 }
1326
1327 /* Default invalid command */
Alex Bennée36e067b2023-03-02 18:57:45 -08001328 gdb_put_packet("");
Pavel Dovgalyukfda84582020-10-03 20:13:43 +03001329}
1330
Alex Bennée26a16182021-05-25 09:24:14 +01001331static void handle_v_cont_query(GArray *params, void *user_ctx)
Jon Doron8536ec02019-05-29 09:41:44 +03001332{
Alex Bennée36e067b2023-03-02 18:57:45 -08001333 gdb_put_packet("vCont;c;C;s;S");
Jon Doron8536ec02019-05-29 09:41:44 +03001334}
1335
Alex Bennée26a16182021-05-25 09:24:14 +01001336static void handle_v_cont(GArray *params, void *user_ctx)
Jon Doron8536ec02019-05-29 09:41:44 +03001337{
1338 int res;
1339
Alex Bennée26a16182021-05-25 09:24:14 +01001340 if (!params->len) {
Jon Doron8536ec02019-05-29 09:41:44 +03001341 return;
1342 }
1343
Alex Bennée26a16182021-05-25 09:24:14 +01001344 res = gdb_handle_vcont(get_param(params, 0)->data);
Jon Doron8536ec02019-05-29 09:41:44 +03001345 if ((res == -EINVAL) || (res == -ERANGE)) {
Alex Bennée36e067b2023-03-02 18:57:45 -08001346 gdb_put_packet("E22");
Jon Doron8536ec02019-05-29 09:41:44 +03001347 } else if (res) {
Alex Bennée36e067b2023-03-02 18:57:45 -08001348 gdb_put_packet("");
Jon Doron8536ec02019-05-29 09:41:44 +03001349 }
1350}
1351
Alex Bennée26a16182021-05-25 09:24:14 +01001352static void handle_v_attach(GArray *params, void *user_ctx)
Jon Doron8536ec02019-05-29 09:41:44 +03001353{
1354 GDBProcess *process;
1355 CPUState *cpu;
Jon Doron8536ec02019-05-29 09:41:44 +03001356
Alex Bennée308f9e82020-03-16 17:21:35 +00001357 g_string_assign(gdbserver_state.str_buf, "E22");
Alex Bennée26a16182021-05-25 09:24:14 +01001358 if (!params->len) {
Jon Doron8536ec02019-05-29 09:41:44 +03001359 goto cleanup;
1360 }
1361
Alex Bennée26a16182021-05-25 09:24:14 +01001362 process = gdb_get_process(get_param(params, 0)->val_ul);
Jon Doron8536ec02019-05-29 09:41:44 +03001363 if (!process) {
1364 goto cleanup;
1365 }
1366
Alex Bennéea346af32020-03-16 17:21:34 +00001367 cpu = get_first_cpu_in_process(process);
Jon Doron8536ec02019-05-29 09:41:44 +03001368 if (!cpu) {
1369 goto cleanup;
1370 }
1371
1372 process->attached = true;
Alex Bennéea346af32020-03-16 17:21:34 +00001373 gdbserver_state.g_cpu = cpu;
1374 gdbserver_state.c_cpu = cpu;
Jon Doron8536ec02019-05-29 09:41:44 +03001375
Alex Bennée308f9e82020-03-16 17:21:35 +00001376 g_string_printf(gdbserver_state.str_buf, "T%02xthread:", GDB_SIGNAL_TRAP);
1377 gdb_append_thread_id(cpu, gdbserver_state.str_buf);
1378 g_string_append_c(gdbserver_state.str_buf, ';');
Jon Doron8536ec02019-05-29 09:41:44 +03001379cleanup:
Alex Bennée36e067b2023-03-02 18:57:45 -08001380 gdb_put_strbuf();
Jon Doron8536ec02019-05-29 09:41:44 +03001381}
1382
Alex Bennée26a16182021-05-25 09:24:14 +01001383static void handle_v_kill(GArray *params, void *user_ctx)
Jon Doron8536ec02019-05-29 09:41:44 +03001384{
1385 /* Kill the target */
Alex Bennée36e067b2023-03-02 18:57:45 -08001386 gdb_put_packet("OK");
Jon Doron8536ec02019-05-29 09:41:44 +03001387 error_report("QEMU: Terminated via GDBstub");
Alex Bennéeb9e10c62021-01-08 22:42:45 +00001388 gdb_exit(0);
Jon Doron8536ec02019-05-29 09:41:44 +03001389 exit(0);
1390}
1391
Philippe Mathieu-Daudé305bea02021-05-20 18:42:59 +01001392static const GdbCmdParseEntry gdb_v_commands_table[] = {
Jon Doron8536ec02019-05-29 09:41:44 +03001393 /* Order is important if has same prefix */
1394 {
1395 .handler = handle_v_cont_query,
1396 .cmd = "Cont?",
1397 .cmd_startswith = 1
1398 },
1399 {
1400 .handler = handle_v_cont,
1401 .cmd = "Cont",
1402 .cmd_startswith = 1,
1403 .schema = "s0"
1404 },
1405 {
1406 .handler = handle_v_attach,
1407 .cmd = "Attach;",
1408 .cmd_startswith = 1,
1409 .schema = "l0"
1410 },
1411 {
1412 .handler = handle_v_kill,
1413 .cmd = "Kill;",
1414 .cmd_startswith = 1
1415 },
1416};
1417
Alex Bennée26a16182021-05-25 09:24:14 +01001418static void handle_v_commands(GArray *params, void *user_ctx)
Jon Doron8536ec02019-05-29 09:41:44 +03001419{
Alex Bennée26a16182021-05-25 09:24:14 +01001420 if (!params->len) {
Jon Doron8536ec02019-05-29 09:41:44 +03001421 return;
1422 }
1423
Alex Bennée26a16182021-05-25 09:24:14 +01001424 if (process_string_cmd(NULL, get_param(params, 0)->data,
Jon Doron8536ec02019-05-29 09:41:44 +03001425 gdb_v_commands_table,
1426 ARRAY_SIZE(gdb_v_commands_table))) {
Alex Bennée36e067b2023-03-02 18:57:45 -08001427 gdb_put_packet("");
Jon Doron8536ec02019-05-29 09:41:44 +03001428 }
1429}
1430
Alex Bennée26a16182021-05-25 09:24:14 +01001431static void handle_query_qemu_sstepbits(GArray *params, void *user_ctx)
Jon Doron2704efa2019-05-29 09:41:45 +03001432{
Maxim Levitskyecd39d62021-11-11 12:06:02 +01001433 g_string_printf(gdbserver_state.str_buf, "ENABLE=%x", SSTEP_ENABLE);
1434
1435 if (gdbserver_state.supported_sstep_flags & SSTEP_NOIRQ) {
1436 g_string_append_printf(gdbserver_state.str_buf, ",NOIRQ=%x",
1437 SSTEP_NOIRQ);
1438 }
1439
1440 if (gdbserver_state.supported_sstep_flags & SSTEP_NOTIMER) {
1441 g_string_append_printf(gdbserver_state.str_buf, ",NOTIMER=%x",
1442 SSTEP_NOTIMER);
1443 }
1444
Alex Bennée36e067b2023-03-02 18:57:45 -08001445 gdb_put_strbuf();
Jon Doron2704efa2019-05-29 09:41:45 +03001446}
1447
Alex Bennée26a16182021-05-25 09:24:14 +01001448static void handle_set_qemu_sstep(GArray *params, void *user_ctx)
Jon Doron2704efa2019-05-29 09:41:45 +03001449{
Maxim Levitskyecd39d62021-11-11 12:06:02 +01001450 int new_sstep_flags;
1451
Alex Bennée26a16182021-05-25 09:24:14 +01001452 if (!params->len) {
Jon Doron2704efa2019-05-29 09:41:45 +03001453 return;
1454 }
1455
Maxim Levitskyecd39d62021-11-11 12:06:02 +01001456 new_sstep_flags = get_param(params, 0)->val_ul;
1457
1458 if (new_sstep_flags & ~gdbserver_state.supported_sstep_flags) {
Alex Bennée36e067b2023-03-02 18:57:45 -08001459 gdb_put_packet("E22");
Maxim Levitskyecd39d62021-11-11 12:06:02 +01001460 return;
1461 }
1462
1463 gdbserver_state.sstep_flags = new_sstep_flags;
Alex Bennée36e067b2023-03-02 18:57:45 -08001464 gdb_put_packet("OK");
Jon Doron2704efa2019-05-29 09:41:45 +03001465}
1466
Alex Bennée26a16182021-05-25 09:24:14 +01001467static void handle_query_qemu_sstep(GArray *params, void *user_ctx)
Jon Doron2704efa2019-05-29 09:41:45 +03001468{
Maxim Levitskyecd39d62021-11-11 12:06:02 +01001469 g_string_printf(gdbserver_state.str_buf, "0x%x",
1470 gdbserver_state.sstep_flags);
Alex Bennée36e067b2023-03-02 18:57:45 -08001471 gdb_put_strbuf();
Jon Doron2704efa2019-05-29 09:41:45 +03001472}
1473
Alex Bennée26a16182021-05-25 09:24:14 +01001474static void handle_query_curr_tid(GArray *params, void *user_ctx)
bellardb4608c02003-06-27 17:34:32 +00001475{
Andreas Färber2e0f2cf2013-06-27 19:19:39 +02001476 CPUState *cpu;
Luc Michelc145eea2019-01-07 15:23:46 +00001477 GDBProcess *process;
Jon Doron2704efa2019-05-29 09:41:45 +03001478
1479 /*
1480 * "Current thread" remains vague in the spec, so always return
1481 * the first thread of the current process (gdb returns the
1482 * first thread).
1483 */
Alex Bennéea346af32020-03-16 17:21:34 +00001484 process = gdb_get_cpu_process(gdbserver_state.g_cpu);
1485 cpu = get_first_cpu_in_process(process);
Alex Bennée308f9e82020-03-16 17:21:35 +00001486 g_string_assign(gdbserver_state.str_buf, "QC");
1487 gdb_append_thread_id(cpu, gdbserver_state.str_buf);
Alex Bennée36e067b2023-03-02 18:57:45 -08001488 gdb_put_strbuf();
Jon Doron2704efa2019-05-29 09:41:45 +03001489}
1490
Alex Bennée26a16182021-05-25 09:24:14 +01001491static void handle_query_threads(GArray *params, void *user_ctx)
Jon Doron2704efa2019-05-29 09:41:45 +03001492{
Alex Bennéea346af32020-03-16 17:21:34 +00001493 if (!gdbserver_state.query_cpu) {
Alex Bennée36e067b2023-03-02 18:57:45 -08001494 gdb_put_packet("l");
Jon Doron2704efa2019-05-29 09:41:45 +03001495 return;
1496 }
1497
Alex Bennée308f9e82020-03-16 17:21:35 +00001498 g_string_assign(gdbserver_state.str_buf, "m");
1499 gdb_append_thread_id(gdbserver_state.query_cpu, gdbserver_state.str_buf);
Alex Bennée36e067b2023-03-02 18:57:45 -08001500 gdb_put_strbuf();
Alex Bennéea346af32020-03-16 17:21:34 +00001501 gdbserver_state.query_cpu = gdb_next_attached_cpu(gdbserver_state.query_cpu);
Jon Doron2704efa2019-05-29 09:41:45 +03001502}
1503
Alex Bennée26a16182021-05-25 09:24:14 +01001504static void handle_query_first_threads(GArray *params, void *user_ctx)
Jon Doron2704efa2019-05-29 09:41:45 +03001505{
Alex Bennéea346af32020-03-16 17:21:34 +00001506 gdbserver_state.query_cpu = gdb_first_attached_cpu();
Alex Bennée26a16182021-05-25 09:24:14 +01001507 handle_query_threads(params, user_ctx);
Jon Doron2704efa2019-05-29 09:41:45 +03001508}
1509
Alex Bennée26a16182021-05-25 09:24:14 +01001510static void handle_query_thread_extra(GArray *params, void *user_ctx)
Jon Doron2704efa2019-05-29 09:41:45 +03001511{
Alex Bennée308f9e82020-03-16 17:21:35 +00001512 g_autoptr(GString) rs = g_string_new(NULL);
Jon Doron2704efa2019-05-29 09:41:45 +03001513 CPUState *cpu;
Jon Doron2704efa2019-05-29 09:41:45 +03001514
Alex Bennée26a16182021-05-25 09:24:14 +01001515 if (!params->len ||
1516 get_param(params, 0)->thread_id.kind == GDB_READ_THREAD_ERR) {
Alex Bennée36e067b2023-03-02 18:57:45 -08001517 gdb_put_packet("E22");
Jon Doron2704efa2019-05-29 09:41:45 +03001518 return;
1519 }
1520
Alex Bennée26a16182021-05-25 09:24:14 +01001521 cpu = gdb_get_cpu(get_param(params, 0)->thread_id.pid,
1522 get_param(params, 0)->thread_id.tid);
Jon Doron2704efa2019-05-29 09:41:45 +03001523 if (!cpu) {
1524 return;
1525 }
1526
1527 cpu_synchronize_state(cpu);
1528
Alex Bennéea346af32020-03-16 17:21:34 +00001529 if (gdbserver_state.multiprocess && (gdbserver_state.process_num > 1)) {
Jon Doron2704efa2019-05-29 09:41:45 +03001530 /* Print the CPU model and name in multiprocess mode */
1531 ObjectClass *oc = object_get_class(OBJECT(cpu));
1532 const char *cpu_model = object_class_get_name(oc);
Markus Armbruster7a309cc2020-07-14 18:02:00 +02001533 const char *cpu_name =
Denis Plotnikov076b2fa2020-04-03 20:11:44 +01001534 object_get_canonical_path_component(OBJECT(cpu));
Alex Bennée308f9e82020-03-16 17:21:35 +00001535 g_string_printf(rs, "%s %s [%s]", cpu_model, cpu_name,
1536 cpu->halted ? "halted " : "running");
Jon Doron2704efa2019-05-29 09:41:45 +03001537 } else {
Alex Bennée308f9e82020-03-16 17:21:35 +00001538 g_string_printf(rs, "CPU#%d [%s]", cpu->cpu_index,
Jon Doron2704efa2019-05-29 09:41:45 +03001539 cpu->halted ? "halted " : "running");
1540 }
Alex Bennée308f9e82020-03-16 17:21:35 +00001541 trace_gdbstub_op_extra_info(rs->str);
Alex Bennée36e067b2023-03-02 18:57:45 -08001542 gdb_memtohex(gdbserver_state.str_buf, (uint8_t *)rs->str, rs->len);
1543 gdb_put_strbuf();
Jon Doron2704efa2019-05-29 09:41:45 +03001544}
1545
Alex Bennée26a16182021-05-25 09:24:14 +01001546static void handle_query_supported(GArray *params, void *user_ctx)
Jon Doron2704efa2019-05-29 09:41:45 +03001547{
Andreas Färber5b24c642013-07-07 15:08:22 +02001548 CPUClass *cc;
Jon Doron2704efa2019-05-29 09:41:45 +03001549
Alex Bennée308f9e82020-03-16 17:21:35 +00001550 g_string_printf(gdbserver_state.str_buf, "PacketSize=%x", MAX_PACKET_LENGTH);
Jon Doron2704efa2019-05-29 09:41:45 +03001551 cc = CPU_GET_CLASS(first_cpu);
1552 if (cc->gdb_core_xml_file) {
Alex Bennée308f9e82020-03-16 17:21:35 +00001553 g_string_append(gdbserver_state.str_buf, ";qXfer:features:read+");
Jon Doron2704efa2019-05-29 09:41:45 +03001554 }
1555
Alex Bennée505601d2023-03-02 18:57:53 -08001556 if (gdb_can_reverse()) {
Pavel Dovgalyukcda38252020-10-03 20:13:49 +03001557 g_string_append(gdbserver_state.str_buf,
1558 ";ReverseStep+;ReverseContinue+");
Pavel Dovgalyukfda84582020-10-03 20:13:43 +03001559 }
1560
Lirong Yuan51c623b2021-01-08 22:42:42 +00001561#ifdef CONFIG_USER_ONLY
1562 if (gdbserver_state.c_cpu->opaque) {
1563 g_string_append(gdbserver_state.str_buf, ";qXfer:auxv:read+");
1564 }
1565#endif
1566
Alex Bennée26a16182021-05-25 09:24:14 +01001567 if (params->len &&
1568 strstr(get_param(params, 0)->data, "multiprocess+")) {
Alex Bennéea346af32020-03-16 17:21:34 +00001569 gdbserver_state.multiprocess = true;
Jon Doron2704efa2019-05-29 09:41:45 +03001570 }
1571
Changbin Du3bc26092020-03-16 17:21:55 +00001572 g_string_append(gdbserver_state.str_buf, ";vContSupported+;multiprocess+");
Alex Bennée36e067b2023-03-02 18:57:45 -08001573 gdb_put_strbuf();
Jon Doron2704efa2019-05-29 09:41:45 +03001574}
1575
Alex Bennée26a16182021-05-25 09:24:14 +01001576static void handle_query_xfer_features(GArray *params, void *user_ctx)
Jon Doron2704efa2019-05-29 09:41:45 +03001577{
1578 GDBProcess *process;
1579 CPUClass *cc;
1580 unsigned long len, total_len, addr;
1581 const char *xml;
bellardb4608c02003-06-27 17:34:32 +00001582 const char *p;
Jon Doron2704efa2019-05-29 09:41:45 +03001583
Alex Bennée26a16182021-05-25 09:24:14 +01001584 if (params->len < 3) {
Alex Bennée36e067b2023-03-02 18:57:45 -08001585 gdb_put_packet("E22");
Jon Doron2704efa2019-05-29 09:41:45 +03001586 return;
1587 }
1588
Alex Bennéea346af32020-03-16 17:21:34 +00001589 process = gdb_get_cpu_process(gdbserver_state.g_cpu);
1590 cc = CPU_GET_CLASS(gdbserver_state.g_cpu);
Jon Doron2704efa2019-05-29 09:41:45 +03001591 if (!cc->gdb_core_xml_file) {
Alex Bennée36e067b2023-03-02 18:57:45 -08001592 gdb_put_packet("");
Jon Doron2704efa2019-05-29 09:41:45 +03001593 return;
1594 }
1595
1596 gdb_has_xml = true;
Alex Bennée26a16182021-05-25 09:24:14 +01001597 p = get_param(params, 0)->data;
Alex Bennéea346af32020-03-16 17:21:34 +00001598 xml = get_feature_xml(p, &p, process);
Jon Doron2704efa2019-05-29 09:41:45 +03001599 if (!xml) {
Alex Bennée36e067b2023-03-02 18:57:45 -08001600 gdb_put_packet("E00");
Jon Doron2704efa2019-05-29 09:41:45 +03001601 return;
1602 }
1603
Alex Bennée26a16182021-05-25 09:24:14 +01001604 addr = get_param(params, 1)->val_ul;
1605 len = get_param(params, 2)->val_ul;
Jon Doron2704efa2019-05-29 09:41:45 +03001606 total_len = strlen(xml);
1607 if (addr > total_len) {
Alex Bennée36e067b2023-03-02 18:57:45 -08001608 gdb_put_packet("E00");
Jon Doron2704efa2019-05-29 09:41:45 +03001609 return;
1610 }
1611
1612 if (len > (MAX_PACKET_LENGTH - 5) / 2) {
1613 len = (MAX_PACKET_LENGTH - 5) / 2;
1614 }
1615
1616 if (len < total_len - addr) {
Alex Bennée308f9e82020-03-16 17:21:35 +00001617 g_string_assign(gdbserver_state.str_buf, "m");
Alex Bennée36e067b2023-03-02 18:57:45 -08001618 gdb_memtox(gdbserver_state.str_buf, xml + addr, len);
Jon Doron2704efa2019-05-29 09:41:45 +03001619 } else {
Alex Bennée308f9e82020-03-16 17:21:35 +00001620 g_string_assign(gdbserver_state.str_buf, "l");
Alex Bennée36e067b2023-03-02 18:57:45 -08001621 gdb_memtox(gdbserver_state.str_buf, xml + addr, total_len - addr);
Jon Doron2704efa2019-05-29 09:41:45 +03001622 }
1623
Alex Bennée36e067b2023-03-02 18:57:45 -08001624 gdb_put_packet_binary(gdbserver_state.str_buf->str,
Alex Bennée308f9e82020-03-16 17:21:35 +00001625 gdbserver_state.str_buf->len, true);
Jon Doron2704efa2019-05-29 09:41:45 +03001626}
1627
Alex Bennée26a16182021-05-25 09:24:14 +01001628static void handle_query_qemu_supported(GArray *params, void *user_ctx)
Jon Doron2704efa2019-05-29 09:41:45 +03001629{
Alex Bennée308f9e82020-03-16 17:21:35 +00001630 g_string_printf(gdbserver_state.str_buf, "sstepbits;sstep");
Jon Doronab4752e2019-05-29 09:41:48 +03001631#ifndef CONFIG_USER_ONLY
Alex Bennée308f9e82020-03-16 17:21:35 +00001632 g_string_append(gdbserver_state.str_buf, ";PhyMemMode");
Jon Doronab4752e2019-05-29 09:41:48 +03001633#endif
Alex Bennée36e067b2023-03-02 18:57:45 -08001634 gdb_put_strbuf();
Jon Doron2704efa2019-05-29 09:41:45 +03001635}
1636
Philippe Mathieu-Daudé305bea02021-05-20 18:42:59 +01001637static const GdbCmdParseEntry gdb_gen_query_set_common_table[] = {
Jon Doron2704efa2019-05-29 09:41:45 +03001638 /* Order is important if has same prefix */
1639 {
1640 .handler = handle_query_qemu_sstepbits,
1641 .cmd = "qemu.sstepbits",
1642 },
1643 {
1644 .handler = handle_query_qemu_sstep,
1645 .cmd = "qemu.sstep",
1646 },
1647 {
1648 .handler = handle_set_qemu_sstep,
1649 .cmd = "qemu.sstep=",
1650 .cmd_startswith = 1,
1651 .schema = "l0"
1652 },
1653};
1654
Philippe Mathieu-Daudé305bea02021-05-20 18:42:59 +01001655static const GdbCmdParseEntry gdb_gen_query_table[] = {
Jon Doron2704efa2019-05-29 09:41:45 +03001656 {
1657 .handler = handle_query_curr_tid,
1658 .cmd = "C",
1659 },
1660 {
1661 .handler = handle_query_threads,
1662 .cmd = "sThreadInfo",
1663 },
1664 {
1665 .handler = handle_query_first_threads,
1666 .cmd = "fThreadInfo",
1667 },
1668 {
1669 .handler = handle_query_thread_extra,
1670 .cmd = "ThreadExtraInfo,",
1671 .cmd_startswith = 1,
1672 .schema = "t0"
1673 },
1674#ifdef CONFIG_USER_ONLY
1675 {
Alex Bennéed96bf492023-03-02 18:57:47 -08001676 .handler = gdb_handle_query_offsets,
Jon Doron2704efa2019-05-29 09:41:45 +03001677 .cmd = "Offsets",
1678 },
1679#else
1680 {
Alex Bennéeb6fa2ec2023-03-02 18:57:46 -08001681 .handler = gdb_handle_query_rcmd,
Jon Doron2704efa2019-05-29 09:41:45 +03001682 .cmd = "Rcmd,",
1683 .cmd_startswith = 1,
1684 .schema = "s0"
1685 },
1686#endif
1687 {
1688 .handler = handle_query_supported,
1689 .cmd = "Supported:",
1690 .cmd_startswith = 1,
1691 .schema = "s0"
1692 },
1693 {
1694 .handler = handle_query_supported,
1695 .cmd = "Supported",
1696 .schema = "s0"
1697 },
1698 {
1699 .handler = handle_query_xfer_features,
1700 .cmd = "Xfer:features:read:",
1701 .cmd_startswith = 1,
1702 .schema = "s:l,l0"
1703 },
Lirong Yuan51c623b2021-01-08 22:42:42 +00001704#if defined(CONFIG_USER_ONLY) && defined(CONFIG_LINUX_USER)
1705 {
Alex Bennéed96bf492023-03-02 18:57:47 -08001706 .handler = gdb_handle_query_xfer_auxv,
Lirong Yuan51c623b2021-01-08 22:42:42 +00001707 .cmd = "Xfer:auxv:read::",
1708 .cmd_startswith = 1,
1709 .schema = "l,l0"
1710 },
1711#endif
Jon Doron2704efa2019-05-29 09:41:45 +03001712 {
Alex Bennée8a2025b2023-03-02 18:57:50 -08001713 .handler = gdb_handle_query_attached,
Jon Doron2704efa2019-05-29 09:41:45 +03001714 .cmd = "Attached:",
1715 .cmd_startswith = 1
1716 },
1717 {
Alex Bennée8a2025b2023-03-02 18:57:50 -08001718 .handler = gdb_handle_query_attached,
Jon Doron2704efa2019-05-29 09:41:45 +03001719 .cmd = "Attached",
1720 },
1721 {
1722 .handler = handle_query_qemu_supported,
1723 .cmd = "qemu.Supported",
1724 },
Jon Doronab4752e2019-05-29 09:41:48 +03001725#ifndef CONFIG_USER_ONLY
1726 {
Alex Bennée589a5862023-03-02 18:57:51 -08001727 .handler = gdb_handle_query_qemu_phy_mem_mode,
Jon Doronab4752e2019-05-29 09:41:48 +03001728 .cmd = "qemu.PhyMemMode",
1729 },
1730#endif
Jon Doron2704efa2019-05-29 09:41:45 +03001731};
1732
Philippe Mathieu-Daudé305bea02021-05-20 18:42:59 +01001733static const GdbCmdParseEntry gdb_gen_set_table[] = {
Jon Doron2704efa2019-05-29 09:41:45 +03001734 /* Order is important if has same prefix */
1735 {
1736 .handler = handle_set_qemu_sstep,
1737 .cmd = "qemu.sstep:",
1738 .cmd_startswith = 1,
1739 .schema = "l0"
1740 },
Jon Doronab4752e2019-05-29 09:41:48 +03001741#ifndef CONFIG_USER_ONLY
1742 {
Alex Bennée589a5862023-03-02 18:57:51 -08001743 .handler = gdb_handle_set_qemu_phy_mem_mode,
Jon Doronab4752e2019-05-29 09:41:48 +03001744 .cmd = "qemu.PhyMemMode:",
1745 .cmd_startswith = 1,
1746 .schema = "l0"
1747 },
1748#endif
Jon Doron2704efa2019-05-29 09:41:45 +03001749};
1750
Alex Bennée26a16182021-05-25 09:24:14 +01001751static void handle_gen_query(GArray *params, void *user_ctx)
Jon Doron2704efa2019-05-29 09:41:45 +03001752{
Alex Bennée26a16182021-05-25 09:24:14 +01001753 if (!params->len) {
Jon Doron2704efa2019-05-29 09:41:45 +03001754 return;
1755 }
1756
Alex Bennée26a16182021-05-25 09:24:14 +01001757 if (!process_string_cmd(NULL, get_param(params, 0)->data,
Jon Doron2704efa2019-05-29 09:41:45 +03001758 gdb_gen_query_set_common_table,
1759 ARRAY_SIZE(gdb_gen_query_set_common_table))) {
1760 return;
1761 }
1762
Alex Bennée26a16182021-05-25 09:24:14 +01001763 if (process_string_cmd(NULL, get_param(params, 0)->data,
Jon Doron2704efa2019-05-29 09:41:45 +03001764 gdb_gen_query_table,
1765 ARRAY_SIZE(gdb_gen_query_table))) {
Alex Bennée36e067b2023-03-02 18:57:45 -08001766 gdb_put_packet("");
Jon Doron2704efa2019-05-29 09:41:45 +03001767 }
1768}
1769
Alex Bennée26a16182021-05-25 09:24:14 +01001770static void handle_gen_set(GArray *params, void *user_ctx)
Jon Doron2704efa2019-05-29 09:41:45 +03001771{
Alex Bennée26a16182021-05-25 09:24:14 +01001772 if (!params->len) {
Jon Doron2704efa2019-05-29 09:41:45 +03001773 return;
1774 }
1775
Alex Bennée26a16182021-05-25 09:24:14 +01001776 if (!process_string_cmd(NULL, get_param(params, 0)->data,
Jon Doron2704efa2019-05-29 09:41:45 +03001777 gdb_gen_query_set_common_table,
1778 ARRAY_SIZE(gdb_gen_query_set_common_table))) {
1779 return;
1780 }
1781
Alex Bennée26a16182021-05-25 09:24:14 +01001782 if (process_string_cmd(NULL, get_param(params, 0)->data,
Jon Doron2704efa2019-05-29 09:41:45 +03001783 gdb_gen_set_table,
1784 ARRAY_SIZE(gdb_gen_set_table))) {
Alex Bennée36e067b2023-03-02 18:57:45 -08001785 gdb_put_packet("");
Jon Doron2704efa2019-05-29 09:41:45 +03001786 }
1787}
1788
Alex Bennée26a16182021-05-25 09:24:14 +01001789static void handle_target_halt(GArray *params, void *user_ctx)
Jon Doron7009d572019-05-29 09:41:46 +03001790{
Alex Bennée308f9e82020-03-16 17:21:35 +00001791 g_string_printf(gdbserver_state.str_buf, "T%02xthread:", GDB_SIGNAL_TRAP);
1792 gdb_append_thread_id(gdbserver_state.c_cpu, gdbserver_state.str_buf);
1793 g_string_append_c(gdbserver_state.str_buf, ';');
Alex Bennée36e067b2023-03-02 18:57:45 -08001794 gdb_put_strbuf();
Jon Doron7009d572019-05-29 09:41:46 +03001795 /*
1796 * Remove all the breakpoints when this query is issued,
1797 * because gdb is doing an initial connect and the state
1798 * should be cleaned up.
1799 */
Alex Bennéeae7467b2022-09-29 12:42:24 +01001800 gdb_breakpoint_remove_all(gdbserver_state.c_cpu);
Jon Doron7009d572019-05-29 09:41:46 +03001801}
1802
Alex Bennéea346af32020-03-16 17:21:34 +00001803static int gdb_handle_packet(const char *line_buf)
Jon Doron2704efa2019-05-29 09:41:45 +03001804{
Jon Doron3e2c1262019-05-29 09:41:30 +03001805 const GdbCmdParseEntry *cmd_parser = NULL;
ths3b46e622007-09-17 08:09:54 +00001806
Doug Gale5c9522b2017-12-02 20:30:37 -05001807 trace_gdbstub_io_command(line_buf);
Alex Bennée118e2262017-07-12 11:52:13 +01001808
Jon Doron3f1cbac2019-05-29 09:41:47 +03001809 switch (line_buf[0]) {
Luc Michel53fd6552019-01-07 15:23:46 +00001810 case '!':
Alex Bennée36e067b2023-03-02 18:57:45 -08001811 gdb_put_packet("OK");
Luc Michel53fd6552019-01-07 15:23:46 +00001812 break;
bellard858693c2004-03-31 18:52:07 +00001813 case '?':
Jon Doron7009d572019-05-29 09:41:46 +03001814 {
1815 static const GdbCmdParseEntry target_halted_cmd_desc = {
1816 .handler = handle_target_halt,
1817 .cmd = "?",
1818 .cmd_startswith = 1
1819 };
1820 cmd_parser = &target_halted_cmd_desc;
1821 }
bellard858693c2004-03-31 18:52:07 +00001822 break;
1823 case 'c':
Jon Doron4d6e3fe2019-05-29 09:41:32 +03001824 {
1825 static const GdbCmdParseEntry continue_cmd_desc = {
1826 .handler = handle_continue,
1827 .cmd = "c",
1828 .cmd_startswith = 1,
1829 .schema = "L0"
1830 };
1831 cmd_parser = &continue_cmd_desc;
bellard858693c2004-03-31 18:52:07 +00001832 }
Jon Doron4d6e3fe2019-05-29 09:41:32 +03001833 break;
edgar_igl1f487ee2008-05-17 22:20:53 +00001834 case 'C':
Jon Doronccc47d52019-05-29 09:41:33 +03001835 {
1836 static const GdbCmdParseEntry cont_with_sig_cmd_desc = {
1837 .handler = handle_cont_with_sig,
1838 .cmd = "C",
1839 .cmd_startswith = 1,
1840 .schema = "l0"
1841 };
1842 cmd_parser = &cont_with_sig_cmd_desc;
1843 }
1844 break;
Jan Kiszkadd32aa12009-06-27 09:53:51 +02001845 case 'v':
Jon Doron8536ec02019-05-29 09:41:44 +03001846 {
1847 static const GdbCmdParseEntry v_cmd_desc = {
1848 .handler = handle_v_commands,
1849 .cmd = "v",
1850 .cmd_startswith = 1,
1851 .schema = "s0"
1852 };
1853 cmd_parser = &v_cmd_desc;
Jan Kiszkadd32aa12009-06-27 09:53:51 +02001854 }
Jon Doron8536ec02019-05-29 09:41:44 +03001855 break;
edgar_igl7d03f822008-05-17 18:58:29 +00001856 case 'k':
1857 /* Kill the target */
Ziyue Yang7ae6c572017-01-18 16:03:29 +08001858 error_report("QEMU: Terminated via GDBstub");
Alex Bennéeb9e10c62021-01-08 22:42:45 +00001859 gdb_exit(0);
edgar_igl7d03f822008-05-17 18:58:29 +00001860 exit(0);
1861 case 'D':
Jon Doron3e2c1262019-05-29 09:41:30 +03001862 {
1863 static const GdbCmdParseEntry detach_cmd_desc = {
1864 .handler = handle_detach,
1865 .cmd = "D",
1866 .cmd_startswith = 1,
1867 .schema = "?.l0"
1868 };
1869 cmd_parser = &detach_cmd_desc;
Luc Michel546f3c62019-01-07 15:23:46 +00001870 }
edgar_igl7d03f822008-05-17 18:58:29 +00001871 break;
bellard858693c2004-03-31 18:52:07 +00001872 case 's':
Jon Doron933f80d2019-05-29 09:41:43 +03001873 {
1874 static const GdbCmdParseEntry step_cmd_desc = {
1875 .handler = handle_step,
1876 .cmd = "s",
1877 .cmd_startswith = 1,
1878 .schema = "L0"
1879 };
1880 cmd_parser = &step_cmd_desc;
bellard858693c2004-03-31 18:52:07 +00001881 }
Jon Doron933f80d2019-05-29 09:41:43 +03001882 break;
Pavel Dovgalyukfda84582020-10-03 20:13:43 +03001883 case 'b':
1884 {
1885 static const GdbCmdParseEntry backward_cmd_desc = {
1886 .handler = handle_backward,
1887 .cmd = "b",
1888 .cmd_startswith = 1,
1889 .schema = "o0"
1890 };
1891 cmd_parser = &backward_cmd_desc;
1892 }
1893 break;
pbrooka2d1eba2007-01-28 03:10:55 +00001894 case 'F':
1895 {
Jon Doron4b20fab2019-05-29 09:41:42 +03001896 static const GdbCmdParseEntry file_io_cmd_desc = {
1897 .handler = handle_file_io,
1898 .cmd = "F",
1899 .cmd_startswith = 1,
1900 .schema = "L,L,o0"
1901 };
1902 cmd_parser = &file_io_cmd_desc;
pbrooka2d1eba2007-01-28 03:10:55 +00001903 }
1904 break;
bellard858693c2004-03-31 18:52:07 +00001905 case 'g':
Jon Doron397d1372019-05-29 09:41:41 +03001906 {
1907 static const GdbCmdParseEntry read_all_regs_cmd_desc = {
1908 .handler = handle_read_all_regs,
1909 .cmd = "g",
1910 .cmd_startswith = 1
1911 };
1912 cmd_parser = &read_all_regs_cmd_desc;
pbrook56aebc82008-10-11 17:55:29 +00001913 }
bellard858693c2004-03-31 18:52:07 +00001914 break;
1915 case 'G':
Jon Doron287ca122019-05-29 09:41:40 +03001916 {
1917 static const GdbCmdParseEntry write_all_regs_cmd_desc = {
1918 .handler = handle_write_all_regs,
1919 .cmd = "G",
1920 .cmd_startswith = 1,
1921 .schema = "s0"
1922 };
1923 cmd_parser = &write_all_regs_cmd_desc;
pbrook56aebc82008-10-11 17:55:29 +00001924 }
bellard858693c2004-03-31 18:52:07 +00001925 break;
1926 case 'm':
Jon Doronda92e232019-05-29 09:41:39 +03001927 {
1928 static const GdbCmdParseEntry read_mem_cmd_desc = {
1929 .handler = handle_read_mem,
1930 .cmd = "m",
1931 .cmd_startswith = 1,
1932 .schema = "L,L0"
1933 };
1934 cmd_parser = &read_mem_cmd_desc;
bellard6f970bd2005-12-05 19:55:19 +00001935 }
bellard858693c2004-03-31 18:52:07 +00001936 break;
1937 case 'M':
Jon Doroncc0ecc72019-05-29 09:41:38 +03001938 {
1939 static const GdbCmdParseEntry write_mem_cmd_desc = {
1940 .handler = handle_write_mem,
1941 .cmd = "M",
1942 .cmd_startswith = 1,
1943 .schema = "L,L:s0"
1944 };
1945 cmd_parser = &write_mem_cmd_desc;
Fabien Chouteau44520db2011-09-08 12:48:16 +02001946 }
bellard858693c2004-03-31 18:52:07 +00001947 break;
pbrook56aebc82008-10-11 17:55:29 +00001948 case 'p':
Jon Doron5d0e57b2019-05-29 09:41:37 +03001949 {
1950 static const GdbCmdParseEntry get_reg_cmd_desc = {
1951 .handler = handle_get_reg,
1952 .cmd = "p",
1953 .cmd_startswith = 1,
1954 .schema = "L0"
1955 };
1956 cmd_parser = &get_reg_cmd_desc;
pbrook56aebc82008-10-11 17:55:29 +00001957 }
1958 break;
1959 case 'P':
Jon Doron62b33202019-05-29 09:41:36 +03001960 {
1961 static const GdbCmdParseEntry set_reg_cmd_desc = {
1962 .handler = handle_set_reg,
1963 .cmd = "P",
1964 .cmd_startswith = 1,
1965 .schema = "L?s0"
1966 };
1967 cmd_parser = &set_reg_cmd_desc;
1968 }
pbrook56aebc82008-10-11 17:55:29 +00001969 break;
bellard858693c2004-03-31 18:52:07 +00001970 case 'Z':
Jon Doron77f6ce52019-05-29 09:41:35 +03001971 {
1972 static const GdbCmdParseEntry insert_bp_cmd_desc = {
1973 .handler = handle_insert_bp,
1974 .cmd = "Z",
1975 .cmd_startswith = 1,
1976 .schema = "l?L?L0"
1977 };
1978 cmd_parser = &insert_bp_cmd_desc;
1979 }
1980 break;
bellard858693c2004-03-31 18:52:07 +00001981 case 'z':
Jon Doron77f6ce52019-05-29 09:41:35 +03001982 {
1983 static const GdbCmdParseEntry remove_bp_cmd_desc = {
1984 .handler = handle_remove_bp,
1985 .cmd = "z",
1986 .cmd_startswith = 1,
1987 .schema = "l?L?L0"
1988 };
1989 cmd_parser = &remove_bp_cmd_desc;
1990 }
bellard858693c2004-03-31 18:52:07 +00001991 break;
aliguori880a7572008-11-18 20:30:24 +00001992 case 'H':
Jon Doron3a9651d2019-05-29 09:41:34 +03001993 {
1994 static const GdbCmdParseEntry set_thread_cmd_desc = {
1995 .handler = handle_set_thread,
1996 .cmd = "H",
1997 .cmd_startswith = 1,
1998 .schema = "o.t0"
1999 };
2000 cmd_parser = &set_thread_cmd_desc;
aliguori880a7572008-11-18 20:30:24 +00002001 }
2002 break;
2003 case 'T':
Jon Doron44ffded2019-05-29 09:41:31 +03002004 {
2005 static const GdbCmdParseEntry thread_alive_cmd_desc = {
2006 .handler = handle_thread_alive,
2007 .cmd = "T",
2008 .cmd_startswith = 1,
2009 .schema = "t0"
2010 };
2011 cmd_parser = &thread_alive_cmd_desc;
Nathan Froyd1e9fa732009-06-03 11:33:08 -07002012 }
aliguori880a7572008-11-18 20:30:24 +00002013 break;
pbrook978efd62006-06-17 18:30:42 +00002014 case 'q':
Jon Doron2704efa2019-05-29 09:41:45 +03002015 {
2016 static const GdbCmdParseEntry gen_query_cmd_desc = {
2017 .handler = handle_gen_query,
2018 .cmd = "q",
2019 .cmd_startswith = 1,
2020 .schema = "s0"
2021 };
2022 cmd_parser = &gen_query_cmd_desc;
2023 }
2024 break;
edgar_igl60897d32008-05-09 08:25:14 +00002025 case 'Q':
Jon Doron2704efa2019-05-29 09:41:45 +03002026 {
2027 static const GdbCmdParseEntry gen_set_cmd_desc = {
2028 .handler = handle_gen_set,
2029 .cmd = "Q",
2030 .cmd_startswith = 1,
2031 .schema = "s0"
2032 };
2033 cmd_parser = &gen_set_cmd_desc;
edgar_igl60897d32008-05-09 08:25:14 +00002034 }
Jon Doron2704efa2019-05-29 09:41:45 +03002035 break;
bellard858693c2004-03-31 18:52:07 +00002036 default:
bellard858693c2004-03-31 18:52:07 +00002037 /* put empty packet */
Alex Bennée36e067b2023-03-02 18:57:45 -08002038 gdb_put_packet("");
bellard858693c2004-03-31 18:52:07 +00002039 break;
2040 }
Jon Doron3e2c1262019-05-29 09:41:30 +03002041
Ramiro Polla2bdec392019-08-05 21:09:01 +02002042 if (cmd_parser) {
Alex Bennéea346af32020-03-16 17:21:34 +00002043 run_cmd_parser(line_buf, cmd_parser);
Ramiro Polla2bdec392019-08-05 21:09:01 +02002044 }
Jon Doron3e2c1262019-05-29 09:41:30 +03002045
bellard858693c2004-03-31 18:52:07 +00002046 return RS_IDLE;
2047}
2048
Andreas Färber64f6b342013-05-27 02:06:09 +02002049void gdb_set_stop_cpu(CPUState *cpu)
aliguori880a7572008-11-18 20:30:24 +00002050{
Alex Bennéea346af32020-03-16 17:21:34 +00002051 GDBProcess *p = gdb_get_cpu_process(cpu);
Luc Michel160d8582019-01-07 15:23:46 +00002052
2053 if (!p->attached) {
2054 /*
2055 * Having a stop CPU corresponding to a process that is not attached
2056 * confuses GDB. So we ignore the request.
2057 */
2058 return;
2059 }
2060
Alex Bennée8d98c442020-03-16 17:21:33 +00002061 gdbserver_state.c_cpu = cpu;
2062 gdbserver_state.g_cpu = cpu;
aliguori880a7572008-11-18 20:30:24 +00002063}
2064
pbrooka2d1eba2007-01-28 03:10:55 +00002065/* Send a gdb syscall request.
2066 This accepts limited printf-style format specifiers, specifically:
pbrooka87295e2007-05-26 15:09:38 +00002067 %x - target_ulong argument printed in hex.
2068 %lx - 64-bit argument printed in hex.
2069 %s - string pointer (target_ulong) and length (int) pair. */
Peter Maydell19239b32015-09-07 10:39:27 +01002070void gdb_do_syscallv(gdb_syscall_complete_cb cb, const char *fmt, va_list va)
pbrooka2d1eba2007-01-28 03:10:55 +00002071{
pbrooka2d1eba2007-01-28 03:10:55 +00002072 char *p;
Meador Ingecdb432b2012-03-15 17:49:45 +00002073 char *p_end;
pbrooka2d1eba2007-01-28 03:10:55 +00002074 target_ulong addr;
pbrooka87295e2007-05-26 15:09:38 +00002075 uint64_t i64;
pbrooka2d1eba2007-01-28 03:10:55 +00002076
Peter Maydellebf1b4c2022-06-10 14:32:36 +01002077 if (!gdb_attached()) {
pbrooka2d1eba2007-01-28 03:10:55 +00002078 return;
Alex Bennéea346af32020-03-16 17:21:34 +00002079 }
Alex Bennée8d98c442020-03-16 17:21:33 +00002080
2081 gdbserver_state.current_syscall_cb = cb;
pbrooka2d1eba2007-01-28 03:10:55 +00002082#ifndef CONFIG_USER_ONLY
Luiz Capitulino0461d5a2011-09-30 14:45:27 -03002083 vm_stop(RUN_STATE_DEBUG);
pbrooka2d1eba2007-01-28 03:10:55 +00002084#endif
Alex Bennée8d98c442020-03-16 17:21:33 +00002085 p = &gdbserver_state.syscall_buf[0];
2086 p_end = &gdbserver_state.syscall_buf[sizeof(gdbserver_state.syscall_buf)];
pbrooka2d1eba2007-01-28 03:10:55 +00002087 *(p++) = 'F';
2088 while (*fmt) {
2089 if (*fmt == '%') {
2090 fmt++;
2091 switch (*fmt++) {
2092 case 'x':
2093 addr = va_arg(va, target_ulong);
Meador Ingecdb432b2012-03-15 17:49:45 +00002094 p += snprintf(p, p_end - p, TARGET_FMT_lx, addr);
pbrooka2d1eba2007-01-28 03:10:55 +00002095 break;
pbrooka87295e2007-05-26 15:09:38 +00002096 case 'l':
2097 if (*(fmt++) != 'x')
2098 goto bad_format;
2099 i64 = va_arg(va, uint64_t);
Meador Ingecdb432b2012-03-15 17:49:45 +00002100 p += snprintf(p, p_end - p, "%" PRIx64, i64);
pbrooka87295e2007-05-26 15:09:38 +00002101 break;
pbrooka2d1eba2007-01-28 03:10:55 +00002102 case 's':
2103 addr = va_arg(va, target_ulong);
Meador Ingecdb432b2012-03-15 17:49:45 +00002104 p += snprintf(p, p_end - p, TARGET_FMT_lx "/%x",
blueswir1363a37d2008-08-21 17:58:08 +00002105 addr, va_arg(va, int));
pbrooka2d1eba2007-01-28 03:10:55 +00002106 break;
2107 default:
pbrooka87295e2007-05-26 15:09:38 +00002108 bad_format:
Ziyue Yang7ae6c572017-01-18 16:03:29 +08002109 error_report("gdbstub: Bad syscall format string '%s'",
2110 fmt - 1);
pbrooka2d1eba2007-01-28 03:10:55 +00002111 break;
2112 }
2113 } else {
2114 *(p++) = *(fmt++);
2115 }
2116 }
pbrook8a93e022007-08-06 13:19:15 +00002117 *p = 0;
pbrooka2d1eba2007-01-28 03:10:55 +00002118#ifdef CONFIG_USER_ONLY
Alex Bennée36e067b2023-03-02 18:57:45 -08002119 gdb_put_packet(gdbserver_state.syscall_buf);
Peter Maydell4f710862018-05-15 19:19:58 +01002120 /* Return control to gdb for it to process the syscall request.
2121 * Since the protocol requires that gdb hands control back to us
2122 * using a "here are the results" F packet, we don't need to check
2123 * gdb_handlesig's return value (which is the signal to deliver if
2124 * execution was resumed via a continue packet).
2125 */
Alex Bennée8d98c442020-03-16 17:21:33 +00002126 gdb_handlesig(gdbserver_state.c_cpu, 0);
pbrooka2d1eba2007-01-28 03:10:55 +00002127#else
Meador Ingecdb432b2012-03-15 17:49:45 +00002128 /* In this case wait to send the syscall packet until notification that
2129 the CPU has stopped. This must be done because if the packet is sent
2130 now the reply from the syscall request could be received while the CPU
2131 is still in the running state, which can cause packets to be dropped
2132 and state transition 'T' packets to be sent while the syscall is still
2133 being processed. */
Alex Bennée8d98c442020-03-16 17:21:33 +00002134 qemu_cpu_kick(gdbserver_state.c_cpu);
pbrooka2d1eba2007-01-28 03:10:55 +00002135#endif
2136}
2137
Peter Maydell19239b32015-09-07 10:39:27 +01002138void gdb_do_syscall(gdb_syscall_complete_cb cb, const char *fmt, ...)
2139{
2140 va_list va;
2141
2142 va_start(va, fmt);
2143 gdb_do_syscallv(cb, fmt, va);
2144 va_end(va);
2145}
2146
Alex Bennée36e067b2023-03-02 18:57:45 -08002147void gdb_read_byte(uint8_t ch)
bellard858693c2004-03-31 18:52:07 +00002148{
ths60fe76f2007-12-16 03:02:09 +00002149 uint8_t reply;
bellard858693c2004-03-31 18:52:07 +00002150
bellard1fddef42005-04-17 19:16:13 +00002151#ifndef CONFIG_USER_ONLY
Damien Hedded116e812020-03-16 17:21:53 +00002152 if (gdbserver_state.last_packet->len) {
pbrook4046d912007-01-28 01:53:16 +00002153 /* Waiting for a response to the last packet. If we see the start
2154 of a new command then abandon the previous response. */
2155 if (ch == '-') {
Doug Gale5c9522b2017-12-02 20:30:37 -05002156 trace_gdbstub_err_got_nack();
Alex Bennée36e067b2023-03-02 18:57:45 -08002157 gdb_put_buffer(gdbserver_state.last_packet->data,
Damien Hedded116e812020-03-16 17:21:53 +00002158 gdbserver_state.last_packet->len);
Alex Bennée118e2262017-07-12 11:52:13 +01002159 } else if (ch == '+') {
Doug Gale5c9522b2017-12-02 20:30:37 -05002160 trace_gdbstub_io_got_ack();
Alex Bennée118e2262017-07-12 11:52:13 +01002161 } else {
Markus Armbruster33c846e2019-05-14 20:03:09 +02002162 trace_gdbstub_io_got_unexpected(ch);
pbrook4046d912007-01-28 01:53:16 +00002163 }
Alex Bennée118e2262017-07-12 11:52:13 +01002164
Damien Hedded116e812020-03-16 17:21:53 +00002165 if (ch == '+' || ch == '$') {
2166 g_byte_array_set_size(gdbserver_state.last_packet, 0);
2167 }
pbrook4046d912007-01-28 01:53:16 +00002168 if (ch != '$')
2169 return;
2170 }
Luiz Capitulino13548692011-07-29 15:36:43 -03002171 if (runstate_is_running()) {
bellard858693c2004-03-31 18:52:07 +00002172 /* when the CPU is running, we cannot do anything except stop
2173 it when receiving a char */
Luiz Capitulino0461d5a2011-09-30 14:45:27 -03002174 vm_stop(RUN_STATE_PAUSED);
ths5fafdf22007-09-16 21:08:06 +00002175 } else
bellard1fddef42005-04-17 19:16:13 +00002176#endif
bellard41625032005-04-24 10:07:11 +00002177 {
Alex Bennéea346af32020-03-16 17:21:34 +00002178 switch(gdbserver_state.state) {
bellard858693c2004-03-31 18:52:07 +00002179 case RS_IDLE:
2180 if (ch == '$') {
Doug Gale4bf43122017-05-01 12:22:10 -04002181 /* start of command packet */
Alex Bennéea346af32020-03-16 17:21:34 +00002182 gdbserver_state.line_buf_index = 0;
2183 gdbserver_state.line_sum = 0;
2184 gdbserver_state.state = RS_GETLINE;
Doug Gale4bf43122017-05-01 12:22:10 -04002185 } else {
Markus Armbruster33c846e2019-05-14 20:03:09 +02002186 trace_gdbstub_err_garbage(ch);
bellard4c3a88a2003-07-26 12:06:08 +00002187 }
2188 break;
bellard858693c2004-03-31 18:52:07 +00002189 case RS_GETLINE:
Doug Gale4bf43122017-05-01 12:22:10 -04002190 if (ch == '}') {
2191 /* start escape sequence */
Alex Bennéea346af32020-03-16 17:21:34 +00002192 gdbserver_state.state = RS_GETLINE_ESC;
2193 gdbserver_state.line_sum += ch;
Doug Gale4bf43122017-05-01 12:22:10 -04002194 } else if (ch == '*') {
2195 /* start run length encoding sequence */
Alex Bennéea346af32020-03-16 17:21:34 +00002196 gdbserver_state.state = RS_GETLINE_RLE;
2197 gdbserver_state.line_sum += ch;
Doug Gale4bf43122017-05-01 12:22:10 -04002198 } else if (ch == '#') {
2199 /* end of command, start of checksum*/
Alex Bennéea346af32020-03-16 17:21:34 +00002200 gdbserver_state.state = RS_CHKSUM1;
2201 } else if (gdbserver_state.line_buf_index >= sizeof(gdbserver_state.line_buf) - 1) {
Doug Gale5c9522b2017-12-02 20:30:37 -05002202 trace_gdbstub_err_overrun();
Alex Bennéea346af32020-03-16 17:21:34 +00002203 gdbserver_state.state = RS_IDLE;
bellard858693c2004-03-31 18:52:07 +00002204 } else {
Doug Gale4bf43122017-05-01 12:22:10 -04002205 /* unescaped command character */
Alex Bennéea346af32020-03-16 17:21:34 +00002206 gdbserver_state.line_buf[gdbserver_state.line_buf_index++] = ch;
2207 gdbserver_state.line_sum += ch;
Doug Gale4bf43122017-05-01 12:22:10 -04002208 }
2209 break;
2210 case RS_GETLINE_ESC:
2211 if (ch == '#') {
2212 /* unexpected end of command in escape sequence */
Alex Bennéea346af32020-03-16 17:21:34 +00002213 gdbserver_state.state = RS_CHKSUM1;
2214 } else if (gdbserver_state.line_buf_index >= sizeof(gdbserver_state.line_buf) - 1) {
Doug Gale4bf43122017-05-01 12:22:10 -04002215 /* command buffer overrun */
Doug Gale5c9522b2017-12-02 20:30:37 -05002216 trace_gdbstub_err_overrun();
Alex Bennéea346af32020-03-16 17:21:34 +00002217 gdbserver_state.state = RS_IDLE;
Doug Gale4bf43122017-05-01 12:22:10 -04002218 } else {
2219 /* parse escaped character and leave escape state */
Alex Bennéea346af32020-03-16 17:21:34 +00002220 gdbserver_state.line_buf[gdbserver_state.line_buf_index++] = ch ^ 0x20;
2221 gdbserver_state.line_sum += ch;
2222 gdbserver_state.state = RS_GETLINE;
Doug Gale4bf43122017-05-01 12:22:10 -04002223 }
2224 break;
2225 case RS_GETLINE_RLE:
Markus Armbruster046aba12019-05-14 20:03:08 +02002226 /*
2227 * Run-length encoding is explained in "Debugging with GDB /
2228 * Appendix E GDB Remote Serial Protocol / Overview".
2229 */
2230 if (ch < ' ' || ch == '#' || ch == '$' || ch > 126) {
Doug Gale4bf43122017-05-01 12:22:10 -04002231 /* invalid RLE count encoding */
Markus Armbruster33c846e2019-05-14 20:03:09 +02002232 trace_gdbstub_err_invalid_repeat(ch);
Alex Bennéea346af32020-03-16 17:21:34 +00002233 gdbserver_state.state = RS_GETLINE;
Doug Gale4bf43122017-05-01 12:22:10 -04002234 } else {
2235 /* decode repeat length */
Markus Armbruster33c846e2019-05-14 20:03:09 +02002236 int repeat = ch - ' ' + 3;
Alex Bennéea346af32020-03-16 17:21:34 +00002237 if (gdbserver_state.line_buf_index + repeat >= sizeof(gdbserver_state.line_buf) - 1) {
Doug Gale4bf43122017-05-01 12:22:10 -04002238 /* that many repeats would overrun the command buffer */
Doug Gale5c9522b2017-12-02 20:30:37 -05002239 trace_gdbstub_err_overrun();
Alex Bennéea346af32020-03-16 17:21:34 +00002240 gdbserver_state.state = RS_IDLE;
2241 } else if (gdbserver_state.line_buf_index < 1) {
Doug Gale4bf43122017-05-01 12:22:10 -04002242 /* got a repeat but we have nothing to repeat */
Doug Gale5c9522b2017-12-02 20:30:37 -05002243 trace_gdbstub_err_invalid_rle();
Alex Bennéea346af32020-03-16 17:21:34 +00002244 gdbserver_state.state = RS_GETLINE;
Doug Gale4bf43122017-05-01 12:22:10 -04002245 } else {
2246 /* repeat the last character */
Alex Bennéea346af32020-03-16 17:21:34 +00002247 memset(gdbserver_state.line_buf + gdbserver_state.line_buf_index,
2248 gdbserver_state.line_buf[gdbserver_state.line_buf_index - 1], repeat);
2249 gdbserver_state.line_buf_index += repeat;
2250 gdbserver_state.line_sum += ch;
2251 gdbserver_state.state = RS_GETLINE;
Doug Gale4bf43122017-05-01 12:22:10 -04002252 }
bellard858693c2004-03-31 18:52:07 +00002253 }
2254 break;
2255 case RS_CHKSUM1:
Doug Gale4bf43122017-05-01 12:22:10 -04002256 /* get high hex digit of checksum */
2257 if (!isxdigit(ch)) {
Markus Armbruster33c846e2019-05-14 20:03:09 +02002258 trace_gdbstub_err_checksum_invalid(ch);
Alex Bennéea346af32020-03-16 17:21:34 +00002259 gdbserver_state.state = RS_GETLINE;
Doug Gale4bf43122017-05-01 12:22:10 -04002260 break;
2261 }
Alex Bennéea346af32020-03-16 17:21:34 +00002262 gdbserver_state.line_buf[gdbserver_state.line_buf_index] = '\0';
2263 gdbserver_state.line_csum = fromhex(ch) << 4;
2264 gdbserver_state.state = RS_CHKSUM2;
bellard858693c2004-03-31 18:52:07 +00002265 break;
2266 case RS_CHKSUM2:
Doug Gale4bf43122017-05-01 12:22:10 -04002267 /* get low hex digit of checksum */
2268 if (!isxdigit(ch)) {
Markus Armbruster33c846e2019-05-14 20:03:09 +02002269 trace_gdbstub_err_checksum_invalid(ch);
Alex Bennéea346af32020-03-16 17:21:34 +00002270 gdbserver_state.state = RS_GETLINE;
Doug Gale4bf43122017-05-01 12:22:10 -04002271 break;
bellard858693c2004-03-31 18:52:07 +00002272 }
Alex Bennéea346af32020-03-16 17:21:34 +00002273 gdbserver_state.line_csum |= fromhex(ch);
Doug Gale4bf43122017-05-01 12:22:10 -04002274
Alex Bennéea346af32020-03-16 17:21:34 +00002275 if (gdbserver_state.line_csum != (gdbserver_state.line_sum & 0xff)) {
2276 trace_gdbstub_err_checksum_incorrect(gdbserver_state.line_sum, gdbserver_state.line_csum);
Doug Gale4bf43122017-05-01 12:22:10 -04002277 /* send NAK reply */
ths60fe76f2007-12-16 03:02:09 +00002278 reply = '-';
Alex Bennée36e067b2023-03-02 18:57:45 -08002279 gdb_put_buffer(&reply, 1);
Alex Bennéea346af32020-03-16 17:21:34 +00002280 gdbserver_state.state = RS_IDLE;
bellard858693c2004-03-31 18:52:07 +00002281 } else {
Doug Gale4bf43122017-05-01 12:22:10 -04002282 /* send ACK reply */
ths60fe76f2007-12-16 03:02:09 +00002283 reply = '+';
Alex Bennée36e067b2023-03-02 18:57:45 -08002284 gdb_put_buffer(&reply, 1);
Alex Bennéea346af32020-03-16 17:21:34 +00002285 gdbserver_state.state = gdb_handle_packet(gdbserver_state.line_buf);
bellard858693c2004-03-31 18:52:07 +00002286 }
bellardb4608c02003-06-27 17:34:32 +00002287 break;
pbrooka2d1eba2007-01-28 03:10:55 +00002288 default:
2289 abort();
bellardb4608c02003-06-27 17:34:32 +00002290 }
2291 }
bellard858693c2004-03-31 18:52:07 +00002292}
2293
Luc Michel8f468632019-01-07 15:23:45 +00002294/*
2295 * Create the process that will contain all the "orphan" CPUs (that are not
2296 * part of a CPU cluster). Note that if this process contains no CPUs, it won't
2297 * be attachable and thus will be invisible to the user.
2298 */
Alex Bennée36e067b2023-03-02 18:57:45 -08002299void gdb_create_default_process(GDBState *s)
Luc Michel8f468632019-01-07 15:23:45 +00002300{
2301 GDBProcess *process;
2302 int max_pid = 0;
2303
Alex Bennéea346af32020-03-16 17:21:34 +00002304 if (gdbserver_state.process_num) {
Luc Michel8f468632019-01-07 15:23:45 +00002305 max_pid = s->processes[s->process_num - 1].pid;
2306 }
2307
2308 s->processes = g_renew(GDBProcess, s->processes, ++s->process_num);
2309 process = &s->processes[s->process_num - 1];
2310
2311 /* We need an available PID slot for this process */
2312 assert(max_pid < UINT32_MAX);
2313
2314 process->pid = max_pid + 1;
2315 process->attached = false;
Luc Michelc145eea2019-01-07 15:23:46 +00002316 process->target_xml[0] = '\0';
Luc Michel8f468632019-01-07 15:23:45 +00002317}
2318