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