blob: 5da66f1794173740e5f85071a44d76725e18a89b [file] [log] [blame]
bellardb4608c02003-06-27 17:34:32 +00001/*
2 * gdb server stub
ths5fafdf22007-09-16 21:08:06 +00003 *
bellard34751872005-07-02 14:31:34 +00004 * Copyright (c) 2003-2005 Fabrice Bellard
bellardb4608c02003-06-27 17:34:32 +00005 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
Blue Swirl8167ee82009-07-16 20:47:01 +000017 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
bellardb4608c02003-06-27 17:34:32 +000018 */
Peter Maydelld38ea872016-01-29 17:50:05 +000019#include "qemu/osdep.h"
Markus Armbrusterda34e652016-03-14 09:01:28 +010020#include "qapi/error.h"
Veronia Bahaaf348b6d2016-03-20 19:16:19 +020021#include "qemu/cutils.h"
Paolo Bonzini33c11872016-03-15 16:58:45 +010022#include "cpu.h"
Veronia Bahaaf348b6d2016-03-20 19:16:19 +020023#ifdef CONFIG_USER_ONLY
bellard1fddef42005-04-17 19:16:13 +000024#include "qemu.h"
25#else
Paolo Bonzini83c90892012-12-17 18:19:49 +010026#include "monitor/monitor.h"
Paolo Bonzinidccfcd02013-04-08 16:55:25 +020027#include "sysemu/char.h"
Paolo Bonzini9c17d612012-12-17 18:20:04 +010028#include "sysemu/sysemu.h"
Paolo Bonzini022c62c2012-12-17 18:19:49 +010029#include "exec/gdbstub.h"
bellard1fddef42005-04-17 19:16:13 +000030#endif
bellard67b915a2004-03-31 23:37:16 +000031
pbrook56aebc82008-10-11 17:55:29 +000032#define MAX_PACKET_LENGTH 4096
33
Blue Swirl2b41f102011-06-19 20:38:22 +000034#include "cpu.h"
Paolo Bonzini1de7afc2012-12-17 18:20:00 +010035#include "qemu/sockets.h"
Paolo Bonzini9c17d612012-12-17 18:20:04 +010036#include "sysemu/kvm.h"
Leon Alraecfe67ce2015-06-19 14:17:45 +010037#include "exec/semihost.h"
Paolo Bonzini63c91552016-03-15 13:18:37 +010038#include "exec/exec-all.h"
aurel32ca587a82008-12-18 22:44:13 +000039
Jan Kiszkaa3919382015-02-07 09:38:44 +010040#ifdef CONFIG_USER_ONLY
41#define GDB_ATTACHED "0"
42#else
43#define GDB_ATTACHED "1"
44#endif
45
Andreas Färberf3659ee2013-06-27 19:09:09 +020046static inline int target_memory_rw_debug(CPUState *cpu, target_ulong addr,
47 uint8_t *buf, int len, bool is_write)
Fabien Chouteau44520db2011-09-08 12:48:16 +020048{
Andreas Färberf3659ee2013-06-27 19:09:09 +020049 CPUClass *cc = CPU_GET_CLASS(cpu);
50
51 if (cc->memory_rw_debug) {
52 return cc->memory_rw_debug(cpu, addr, buf, len, is_write);
53 }
54 return cpu_memory_rw_debug(cpu, addr, buf, len, is_write);
Fabien Chouteau44520db2011-09-08 12:48:16 +020055}
aurel32ca587a82008-12-18 22:44:13 +000056
57enum {
58 GDB_SIGNAL_0 = 0,
59 GDB_SIGNAL_INT = 2,
Jan Kiszka425189a2011-03-22 11:02:09 +010060 GDB_SIGNAL_QUIT = 3,
aurel32ca587a82008-12-18 22:44:13 +000061 GDB_SIGNAL_TRAP = 5,
Jan Kiszka425189a2011-03-22 11:02:09 +010062 GDB_SIGNAL_ABRT = 6,
63 GDB_SIGNAL_ALRM = 14,
64 GDB_SIGNAL_IO = 23,
65 GDB_SIGNAL_XCPU = 24,
aurel32ca587a82008-12-18 22:44:13 +000066 GDB_SIGNAL_UNKNOWN = 143
67};
68
69#ifdef CONFIG_USER_ONLY
70
71/* Map target signal numbers to GDB protocol signal numbers and vice
72 * versa. For user emulation's currently supported systems, we can
73 * assume most signals are defined.
74 */
75
76static int gdb_signal_table[] = {
77 0,
78 TARGET_SIGHUP,
79 TARGET_SIGINT,
80 TARGET_SIGQUIT,
81 TARGET_SIGILL,
82 TARGET_SIGTRAP,
83 TARGET_SIGABRT,
84 -1, /* SIGEMT */
85 TARGET_SIGFPE,
86 TARGET_SIGKILL,
87 TARGET_SIGBUS,
88 TARGET_SIGSEGV,
89 TARGET_SIGSYS,
90 TARGET_SIGPIPE,
91 TARGET_SIGALRM,
92 TARGET_SIGTERM,
93 TARGET_SIGURG,
94 TARGET_SIGSTOP,
95 TARGET_SIGTSTP,
96 TARGET_SIGCONT,
97 TARGET_SIGCHLD,
98 TARGET_SIGTTIN,
99 TARGET_SIGTTOU,
100 TARGET_SIGIO,
101 TARGET_SIGXCPU,
102 TARGET_SIGXFSZ,
103 TARGET_SIGVTALRM,
104 TARGET_SIGPROF,
105 TARGET_SIGWINCH,
106 -1, /* SIGLOST */
107 TARGET_SIGUSR1,
108 TARGET_SIGUSR2,
blueswir1c72d5bf2009-01-15 17:27:45 +0000109#ifdef TARGET_SIGPWR
aurel32ca587a82008-12-18 22:44:13 +0000110 TARGET_SIGPWR,
blueswir1c72d5bf2009-01-15 17:27:45 +0000111#else
112 -1,
113#endif
aurel32ca587a82008-12-18 22:44:13 +0000114 -1, /* SIGPOLL */
115 -1,
116 -1,
117 -1,
118 -1,
119 -1,
120 -1,
121 -1,
122 -1,
123 -1,
124 -1,
125 -1,
blueswir1c72d5bf2009-01-15 17:27:45 +0000126#ifdef __SIGRTMIN
aurel32ca587a82008-12-18 22:44:13 +0000127 __SIGRTMIN + 1,
128 __SIGRTMIN + 2,
129 __SIGRTMIN + 3,
130 __SIGRTMIN + 4,
131 __SIGRTMIN + 5,
132 __SIGRTMIN + 6,
133 __SIGRTMIN + 7,
134 __SIGRTMIN + 8,
135 __SIGRTMIN + 9,
136 __SIGRTMIN + 10,
137 __SIGRTMIN + 11,
138 __SIGRTMIN + 12,
139 __SIGRTMIN + 13,
140 __SIGRTMIN + 14,
141 __SIGRTMIN + 15,
142 __SIGRTMIN + 16,
143 __SIGRTMIN + 17,
144 __SIGRTMIN + 18,
145 __SIGRTMIN + 19,
146 __SIGRTMIN + 20,
147 __SIGRTMIN + 21,
148 __SIGRTMIN + 22,
149 __SIGRTMIN + 23,
150 __SIGRTMIN + 24,
151 __SIGRTMIN + 25,
152 __SIGRTMIN + 26,
153 __SIGRTMIN + 27,
154 __SIGRTMIN + 28,
155 __SIGRTMIN + 29,
156 __SIGRTMIN + 30,
157 __SIGRTMIN + 31,
158 -1, /* SIGCANCEL */
159 __SIGRTMIN,
160 __SIGRTMIN + 32,
161 __SIGRTMIN + 33,
162 __SIGRTMIN + 34,
163 __SIGRTMIN + 35,
164 __SIGRTMIN + 36,
165 __SIGRTMIN + 37,
166 __SIGRTMIN + 38,
167 __SIGRTMIN + 39,
168 __SIGRTMIN + 40,
169 __SIGRTMIN + 41,
170 __SIGRTMIN + 42,
171 __SIGRTMIN + 43,
172 __SIGRTMIN + 44,
173 __SIGRTMIN + 45,
174 __SIGRTMIN + 46,
175 __SIGRTMIN + 47,
176 __SIGRTMIN + 48,
177 __SIGRTMIN + 49,
178 __SIGRTMIN + 50,
179 __SIGRTMIN + 51,
180 __SIGRTMIN + 52,
181 __SIGRTMIN + 53,
182 __SIGRTMIN + 54,
183 __SIGRTMIN + 55,
184 __SIGRTMIN + 56,
185 __SIGRTMIN + 57,
186 __SIGRTMIN + 58,
187 __SIGRTMIN + 59,
188 __SIGRTMIN + 60,
189 __SIGRTMIN + 61,
190 __SIGRTMIN + 62,
191 __SIGRTMIN + 63,
192 __SIGRTMIN + 64,
193 __SIGRTMIN + 65,
194 __SIGRTMIN + 66,
195 __SIGRTMIN + 67,
196 __SIGRTMIN + 68,
197 __SIGRTMIN + 69,
198 __SIGRTMIN + 70,
199 __SIGRTMIN + 71,
200 __SIGRTMIN + 72,
201 __SIGRTMIN + 73,
202 __SIGRTMIN + 74,
203 __SIGRTMIN + 75,
204 __SIGRTMIN + 76,
205 __SIGRTMIN + 77,
206 __SIGRTMIN + 78,
207 __SIGRTMIN + 79,
208 __SIGRTMIN + 80,
209 __SIGRTMIN + 81,
210 __SIGRTMIN + 82,
211 __SIGRTMIN + 83,
212 __SIGRTMIN + 84,
213 __SIGRTMIN + 85,
214 __SIGRTMIN + 86,
215 __SIGRTMIN + 87,
216 __SIGRTMIN + 88,
217 __SIGRTMIN + 89,
218 __SIGRTMIN + 90,
219 __SIGRTMIN + 91,
220 __SIGRTMIN + 92,
221 __SIGRTMIN + 93,
222 __SIGRTMIN + 94,
223 __SIGRTMIN + 95,
224 -1, /* SIGINFO */
225 -1, /* UNKNOWN */
226 -1, /* DEFAULT */
227 -1,
228 -1,
229 -1,
230 -1,
231 -1,
232 -1
blueswir1c72d5bf2009-01-15 17:27:45 +0000233#endif
aurel32ca587a82008-12-18 22:44:13 +0000234};
bellard8f447cc2006-06-14 15:21:14 +0000235#else
aurel32ca587a82008-12-18 22:44:13 +0000236/* In system mode we only need SIGINT and SIGTRAP; other signals
237 are not yet supported. */
238
239enum {
240 TARGET_SIGINT = 2,
241 TARGET_SIGTRAP = 5
242};
243
244static int gdb_signal_table[] = {
245 -1,
246 -1,
247 TARGET_SIGINT,
248 -1,
249 -1,
250 TARGET_SIGTRAP
251};
bellard8f447cc2006-06-14 15:21:14 +0000252#endif
bellardb4608c02003-06-27 17:34:32 +0000253
aurel32ca587a82008-12-18 22:44:13 +0000254#ifdef CONFIG_USER_ONLY
255static int target_signal_to_gdb (int sig)
256{
257 int i;
258 for (i = 0; i < ARRAY_SIZE (gdb_signal_table); i++)
259 if (gdb_signal_table[i] == sig)
260 return i;
261 return GDB_SIGNAL_UNKNOWN;
262}
263#endif
264
265static int gdb_signal_to_target (int sig)
266{
267 if (sig < ARRAY_SIZE (gdb_signal_table))
268 return gdb_signal_table[sig];
269 else
270 return -1;
271}
272
bellard4abe6152003-07-26 18:01:58 +0000273//#define DEBUG_GDB
bellardb4608c02003-06-27 17:34:32 +0000274
pbrook56aebc82008-10-11 17:55:29 +0000275typedef struct GDBRegisterState {
276 int base_reg;
277 int num_regs;
278 gdb_reg_cb get_reg;
279 gdb_reg_cb set_reg;
280 const char *xml;
281 struct GDBRegisterState *next;
282} GDBRegisterState;
283
bellard858693c2004-03-31 18:52:07 +0000284enum RSState {
aliguori36556b22009-03-28 18:05:53 +0000285 RS_INACTIVE,
bellard858693c2004-03-31 18:52:07 +0000286 RS_IDLE,
287 RS_GETLINE,
288 RS_CHKSUM1,
289 RS_CHKSUM2,
290};
bellard858693c2004-03-31 18:52:07 +0000291typedef struct GDBState {
Andreas Färber2e0f2cf2013-06-27 19:19:39 +0200292 CPUState *c_cpu; /* current CPU for step/continue ops */
293 CPUState *g_cpu; /* current CPU for other ops */
Andreas Färber52f34622013-06-27 13:44:40 +0200294 CPUState *query_cpu; /* for q{f|s}ThreadInfo */
bellard41625032005-04-24 10:07:11 +0000295 enum RSState state; /* parsing state */
pbrook56aebc82008-10-11 17:55:29 +0000296 char line_buf[MAX_PACKET_LENGTH];
bellard858693c2004-03-31 18:52:07 +0000297 int line_buf_index;
298 int line_csum;
pbrook56aebc82008-10-11 17:55:29 +0000299 uint8_t last_packet[MAX_PACKET_LENGTH + 4];
pbrook4046d912007-01-28 01:53:16 +0000300 int last_packet_len;
edgar_igl1f487ee2008-05-17 22:20:53 +0000301 int signal;
bellard41625032005-04-24 10:07:11 +0000302#ifdef CONFIG_USER_ONLY
pbrook4046d912007-01-28 01:53:16 +0000303 int fd;
bellard41625032005-04-24 10:07:11 +0000304 int running_state;
pbrook4046d912007-01-28 01:53:16 +0000305#else
306 CharDriverState *chr;
aliguori8a34a0f2009-03-05 23:01:55 +0000307 CharDriverState *mon_chr;
bellard41625032005-04-24 10:07:11 +0000308#endif
Meador Ingecdb432b2012-03-15 17:49:45 +0000309 char syscall_buf[256];
310 gdb_syscall_complete_cb current_syscall_cb;
bellard858693c2004-03-31 18:52:07 +0000311} GDBState;
bellardb4608c02003-06-27 17:34:32 +0000312
edgar_igl60897d32008-05-09 08:25:14 +0000313/* By default use no IRQs and no timers while single stepping so as to
314 * make single stepping like an ICE HW step.
315 */
316static int sstep_flags = SSTEP_ENABLE|SSTEP_NOIRQ|SSTEP_NOTIMER;
317
aliguori880a7572008-11-18 20:30:24 +0000318static GDBState *gdbserver_state;
319
Andreas Färber5b50e792013-06-29 04:18:45 +0200320bool gdb_has_xml;
pbrook56aebc82008-10-11 17:55:29 +0000321
bellard1fddef42005-04-17 19:16:13 +0000322#ifdef CONFIG_USER_ONLY
pbrook4046d912007-01-28 01:53:16 +0000323/* XXX: This is not thread safe. Do we care? */
324static int gdbserver_fd = -1;
325
bellard858693c2004-03-31 18:52:07 +0000326static int get_char(GDBState *s)
bellardb4608c02003-06-27 17:34:32 +0000327{
328 uint8_t ch;
329 int ret;
330
331 for(;;) {
Blue Swirl00aa0042011-07-23 20:04:29 +0000332 ret = qemu_recv(s->fd, &ch, 1, 0);
bellardb4608c02003-06-27 17:34:32 +0000333 if (ret < 0) {
edgar_igl1f487ee2008-05-17 22:20:53 +0000334 if (errno == ECONNRESET)
335 s->fd = -1;
Peter Wu5819e3e2016-06-05 16:35:48 +0200336 if (errno != EINTR)
bellardb4608c02003-06-27 17:34:32 +0000337 return -1;
338 } else if (ret == 0) {
edgar_igl1f487ee2008-05-17 22:20:53 +0000339 close(s->fd);
340 s->fd = -1;
bellardb4608c02003-06-27 17:34:32 +0000341 return -1;
342 } else {
343 break;
344 }
345 }
346 return ch;
347}
pbrook4046d912007-01-28 01:53:16 +0000348#endif
bellardb4608c02003-06-27 17:34:32 +0000349
blueswir1654efcf2009-04-18 07:29:59 +0000350static enum {
pbrooka2d1eba2007-01-28 03:10:55 +0000351 GDB_SYS_UNKNOWN,
352 GDB_SYS_ENABLED,
353 GDB_SYS_DISABLED,
354} gdb_syscall_mode;
355
Liviu Ionescua38bb072014-12-11 12:07:48 +0000356/* Decide if either remote gdb syscalls or native file IO should be used. */
pbrooka2d1eba2007-01-28 03:10:55 +0000357int use_gdb_syscalls(void)
358{
Leon Alraecfe67ce2015-06-19 14:17:45 +0100359 SemihostingTarget target = semihosting_get_target();
360 if (target == SEMIHOSTING_TARGET_NATIVE) {
Liviu Ionescua38bb072014-12-11 12:07:48 +0000361 /* -semihosting-config target=native */
362 return false;
Leon Alraecfe67ce2015-06-19 14:17:45 +0100363 } else if (target == SEMIHOSTING_TARGET_GDB) {
Liviu Ionescua38bb072014-12-11 12:07:48 +0000364 /* -semihosting-config target=gdb */
365 return true;
366 }
367
368 /* -semihosting-config target=auto */
369 /* On the first call check if gdb is connected and remember. */
pbrooka2d1eba2007-01-28 03:10:55 +0000370 if (gdb_syscall_mode == GDB_SYS_UNKNOWN) {
aliguori880a7572008-11-18 20:30:24 +0000371 gdb_syscall_mode = (gdbserver_state ? GDB_SYS_ENABLED
372 : GDB_SYS_DISABLED);
pbrooka2d1eba2007-01-28 03:10:55 +0000373 }
374 return gdb_syscall_mode == GDB_SYS_ENABLED;
375}
376
edgar_iglba70a622008-03-14 06:10:42 +0000377/* Resume execution. */
378static inline void gdb_continue(GDBState *s)
379{
380#ifdef CONFIG_USER_ONLY
381 s->running_state = 1;
382#else
Paolo Bonzini26ac7a32013-06-03 17:06:54 +0200383 if (!runstate_needs_reset()) {
Paolo Bonzini87f25c12013-05-30 13:20:40 +0200384 vm_start();
385 }
edgar_iglba70a622008-03-14 06:10:42 +0000386#endif
387}
388
bellard858693c2004-03-31 18:52:07 +0000389static void put_buffer(GDBState *s, const uint8_t *buf, int len)
bellardb4608c02003-06-27 17:34:32 +0000390{
pbrook4046d912007-01-28 01:53:16 +0000391#ifdef CONFIG_USER_ONLY
bellardb4608c02003-06-27 17:34:32 +0000392 int ret;
393
394 while (len > 0) {
bellard8f447cc2006-06-14 15:21:14 +0000395 ret = send(s->fd, buf, len, 0);
bellardb4608c02003-06-27 17:34:32 +0000396 if (ret < 0) {
Peter Wu5819e3e2016-06-05 16:35:48 +0200397 if (errno != EINTR)
bellardb4608c02003-06-27 17:34:32 +0000398 return;
399 } else {
400 buf += ret;
401 len -= ret;
402 }
403 }
pbrook4046d912007-01-28 01:53:16 +0000404#else
Anthony Liguori2cc6e0a2011-08-15 11:17:28 -0500405 qemu_chr_fe_write(s->chr, buf, len);
pbrook4046d912007-01-28 01:53:16 +0000406#endif
bellardb4608c02003-06-27 17:34:32 +0000407}
408
409static inline int fromhex(int v)
410{
411 if (v >= '0' && v <= '9')
412 return v - '0';
413 else if (v >= 'A' && v <= 'F')
414 return v - 'A' + 10;
415 else if (v >= 'a' && v <= 'f')
416 return v - 'a' + 10;
417 else
418 return 0;
419}
420
421static inline int tohex(int v)
422{
423 if (v < 10)
424 return v + '0';
425 else
426 return v - 10 + 'a';
427}
428
429static void memtohex(char *buf, const uint8_t *mem, int len)
430{
431 int i, c;
432 char *q;
433 q = buf;
434 for(i = 0; i < len; i++) {
435 c = mem[i];
436 *q++ = tohex(c >> 4);
437 *q++ = tohex(c & 0xf);
438 }
439 *q = '\0';
440}
441
442static void hextomem(uint8_t *mem, const char *buf, int len)
443{
444 int i;
445
446 for(i = 0; i < len; i++) {
447 mem[i] = (fromhex(buf[0]) << 4) | fromhex(buf[1]);
448 buf += 2;
449 }
450}
451
bellardb4608c02003-06-27 17:34:32 +0000452/* return -1 if error, 0 if OK */
pbrook56aebc82008-10-11 17:55:29 +0000453static int put_packet_binary(GDBState *s, const char *buf, int len)
bellardb4608c02003-06-27 17:34:32 +0000454{
pbrook56aebc82008-10-11 17:55:29 +0000455 int csum, i;
ths60fe76f2007-12-16 03:02:09 +0000456 uint8_t *p;
bellardb4608c02003-06-27 17:34:32 +0000457
bellardb4608c02003-06-27 17:34:32 +0000458 for(;;) {
pbrook4046d912007-01-28 01:53:16 +0000459 p = s->last_packet;
460 *(p++) = '$';
pbrook4046d912007-01-28 01:53:16 +0000461 memcpy(p, buf, len);
462 p += len;
bellardb4608c02003-06-27 17:34:32 +0000463 csum = 0;
464 for(i = 0; i < len; i++) {
465 csum += buf[i];
466 }
pbrook4046d912007-01-28 01:53:16 +0000467 *(p++) = '#';
468 *(p++) = tohex((csum >> 4) & 0xf);
469 *(p++) = tohex((csum) & 0xf);
bellardb4608c02003-06-27 17:34:32 +0000470
pbrook4046d912007-01-28 01:53:16 +0000471 s->last_packet_len = p - s->last_packet;
thsffe8ab82007-12-16 03:16:05 +0000472 put_buffer(s, (uint8_t *)s->last_packet, s->last_packet_len);
bellardb4608c02003-06-27 17:34:32 +0000473
pbrook4046d912007-01-28 01:53:16 +0000474#ifdef CONFIG_USER_ONLY
475 i = get_char(s);
476 if (i < 0)
bellardb4608c02003-06-27 17:34:32 +0000477 return -1;
pbrook4046d912007-01-28 01:53:16 +0000478 if (i == '+')
bellardb4608c02003-06-27 17:34:32 +0000479 break;
pbrook4046d912007-01-28 01:53:16 +0000480#else
481 break;
482#endif
bellardb4608c02003-06-27 17:34:32 +0000483 }
484 return 0;
485}
486
pbrook56aebc82008-10-11 17:55:29 +0000487/* return -1 if error, 0 if OK */
488static int put_packet(GDBState *s, const char *buf)
489{
490#ifdef DEBUG_GDB
491 printf("reply='%s'\n", buf);
492#endif
493
494 return put_packet_binary(s, buf, strlen(buf));
495}
496
pbrook56aebc82008-10-11 17:55:29 +0000497/* Encode data using the encoding for 'x' packets. */
498static int memtox(char *buf, const char *mem, int len)
499{
500 char *p = buf;
501 char c;
502
503 while (len--) {
504 c = *(mem++);
505 switch (c) {
506 case '#': case '$': case '*': case '}':
507 *(p++) = '}';
508 *(p++) = c ^ 0x20;
509 break;
510 default:
511 *(p++) = c;
512 break;
513 }
514 }
515 return p - buf;
516}
517
Andreas Färber5b24c642013-07-07 15:08:22 +0200518static const char *get_feature_xml(const char *p, const char **newp,
519 CPUClass *cc)
pbrook56aebc82008-10-11 17:55:29 +0000520{
pbrook56aebc82008-10-11 17:55:29 +0000521 size_t len;
522 int i;
523 const char *name;
524 static char target_xml[1024];
525
526 len = 0;
527 while (p[len] && p[len] != ':')
528 len++;
529 *newp = p + len;
530
531 name = NULL;
532 if (strncmp(p, "target.xml", len) == 0) {
533 /* Generate the XML description for this CPU. */
534 if (!target_xml[0]) {
535 GDBRegisterState *r;
Andreas Färbereac8b352013-06-28 21:11:37 +0200536 CPUState *cpu = first_cpu;
pbrook56aebc82008-10-11 17:55:29 +0000537
David Hildenbrandb3820e62015-12-03 13:14:41 +0100538 pstrcat(target_xml, sizeof(target_xml),
539 "<?xml version=\"1.0\"?>"
540 "<!DOCTYPE target SYSTEM \"gdb-target.dtd\">"
541 "<target>");
542 if (cc->gdb_arch_name) {
543 gchar *arch = cc->gdb_arch_name(cpu);
544 pstrcat(target_xml, sizeof(target_xml), "<architecture>");
545 pstrcat(target_xml, sizeof(target_xml), arch);
546 pstrcat(target_xml, sizeof(target_xml), "</architecture>");
547 g_free(arch);
548 }
549 pstrcat(target_xml, sizeof(target_xml), "<xi:include href=\"");
550 pstrcat(target_xml, sizeof(target_xml), cc->gdb_core_xml_file);
551 pstrcat(target_xml, sizeof(target_xml), "\"/>");
Andreas Färbereac8b352013-06-28 21:11:37 +0200552 for (r = cpu->gdb_regs; r; r = r->next) {
blueswir12dc766d2009-04-13 16:06:19 +0000553 pstrcat(target_xml, sizeof(target_xml), "<xi:include href=\"");
554 pstrcat(target_xml, sizeof(target_xml), r->xml);
555 pstrcat(target_xml, sizeof(target_xml), "\"/>");
pbrook56aebc82008-10-11 17:55:29 +0000556 }
blueswir12dc766d2009-04-13 16:06:19 +0000557 pstrcat(target_xml, sizeof(target_xml), "</target>");
pbrook56aebc82008-10-11 17:55:29 +0000558 }
559 return target_xml;
560 }
561 for (i = 0; ; i++) {
562 name = xml_builtin[i][0];
563 if (!name || (strncmp(name, p, len) == 0 && strlen(name) == len))
564 break;
565 }
566 return name ? xml_builtin[i][1] : NULL;
567}
pbrook56aebc82008-10-11 17:55:29 +0000568
Andreas Färber385b9f02013-06-27 18:25:36 +0200569static int gdb_read_register(CPUState *cpu, uint8_t *mem_buf, int reg)
pbrook56aebc82008-10-11 17:55:29 +0000570{
Andreas Färbera0e372f2013-06-28 23:18:47 +0200571 CPUClass *cc = CPU_GET_CLASS(cpu);
Andreas Färber385b9f02013-06-27 18:25:36 +0200572 CPUArchState *env = cpu->env_ptr;
pbrook56aebc82008-10-11 17:55:29 +0000573 GDBRegisterState *r;
574
Andreas Färbera0e372f2013-06-28 23:18:47 +0200575 if (reg < cc->gdb_num_core_regs) {
Andreas Färber5b50e792013-06-29 04:18:45 +0200576 return cc->gdb_read_register(cpu, mem_buf, reg);
Andreas Färbera0e372f2013-06-28 23:18:47 +0200577 }
pbrook56aebc82008-10-11 17:55:29 +0000578
Andreas Färbereac8b352013-06-28 21:11:37 +0200579 for (r = cpu->gdb_regs; r; r = r->next) {
pbrook56aebc82008-10-11 17:55:29 +0000580 if (r->base_reg <= reg && reg < r->base_reg + r->num_regs) {
581 return r->get_reg(env, mem_buf, reg - r->base_reg);
582 }
583 }
584 return 0;
585}
586
Andreas Färber385b9f02013-06-27 18:25:36 +0200587static int gdb_write_register(CPUState *cpu, uint8_t *mem_buf, int reg)
pbrook56aebc82008-10-11 17:55:29 +0000588{
Andreas Färbera0e372f2013-06-28 23:18:47 +0200589 CPUClass *cc = CPU_GET_CLASS(cpu);
Andreas Färber385b9f02013-06-27 18:25:36 +0200590 CPUArchState *env = cpu->env_ptr;
pbrook56aebc82008-10-11 17:55:29 +0000591 GDBRegisterState *r;
592
Andreas Färbera0e372f2013-06-28 23:18:47 +0200593 if (reg < cc->gdb_num_core_regs) {
Andreas Färber5b50e792013-06-29 04:18:45 +0200594 return cc->gdb_write_register(cpu, mem_buf, reg);
Andreas Färbera0e372f2013-06-28 23:18:47 +0200595 }
pbrook56aebc82008-10-11 17:55:29 +0000596
Andreas Färbereac8b352013-06-28 21:11:37 +0200597 for (r = cpu->gdb_regs; r; r = r->next) {
pbrook56aebc82008-10-11 17:55:29 +0000598 if (r->base_reg <= reg && reg < r->base_reg + r->num_regs) {
599 return r->set_reg(env, mem_buf, reg - r->base_reg);
600 }
601 }
602 return 0;
603}
604
605/* Register a supplemental set of CPU registers. If g_pos is nonzero it
606 specifies the first register number and these registers are included in
607 a standard "g" packet. Direction is relative to gdb, i.e. get_reg is
608 gdb reading a CPU register, and set_reg is gdb modifying a CPU register.
609 */
610
Andreas Färber22169d42013-06-28 21:27:39 +0200611void gdb_register_coprocessor(CPUState *cpu,
612 gdb_reg_cb get_reg, gdb_reg_cb set_reg,
613 int num_regs, const char *xml, int g_pos)
pbrook56aebc82008-10-11 17:55:29 +0000614{
615 GDBRegisterState *s;
616 GDBRegisterState **p;
pbrook56aebc82008-10-11 17:55:29 +0000617
Andreas Färbereac8b352013-06-28 21:11:37 +0200618 p = &cpu->gdb_regs;
pbrook56aebc82008-10-11 17:55:29 +0000619 while (*p) {
620 /* Check for duplicates. */
621 if (strcmp((*p)->xml, xml) == 0)
622 return;
623 p = &(*p)->next;
624 }
Stefan Weil9643c252011-10-18 22:25:38 +0200625
626 s = g_new0(GDBRegisterState, 1);
Andreas Färbera0e372f2013-06-28 23:18:47 +0200627 s->base_reg = cpu->gdb_num_regs;
Stefan Weil9643c252011-10-18 22:25:38 +0200628 s->num_regs = num_regs;
629 s->get_reg = get_reg;
630 s->set_reg = set_reg;
631 s->xml = xml;
632
pbrook56aebc82008-10-11 17:55:29 +0000633 /* Add to end of list. */
Andreas Färbera0e372f2013-06-28 23:18:47 +0200634 cpu->gdb_num_regs += num_regs;
pbrook56aebc82008-10-11 17:55:29 +0000635 *p = s;
636 if (g_pos) {
637 if (g_pos != s->base_reg) {
638 fprintf(stderr, "Error: Bad gdb register numbering for '%s'\n"
639 "Expected %d got %d\n", xml, g_pos, s->base_reg);
Andreas Färber35143f02013-08-12 18:09:47 +0200640 } else {
641 cpu->gdb_num_g_regs = cpu->gdb_num_regs;
pbrook56aebc82008-10-11 17:55:29 +0000642 }
643 }
644}
645
aliguoria1d1bb32008-11-18 20:07:32 +0000646#ifndef CONFIG_USER_ONLY
Peter Maydell2472b6c2014-09-12 19:04:17 +0100647/* Translate GDB watchpoint type to a flags value for cpu_watchpoint_* */
648static inline int xlat_gdb_type(CPUState *cpu, int gdbtype)
649{
650 static const int xlat[] = {
651 [GDB_WATCHPOINT_WRITE] = BP_GDB | BP_MEM_WRITE,
652 [GDB_WATCHPOINT_READ] = BP_GDB | BP_MEM_READ,
653 [GDB_WATCHPOINT_ACCESS] = BP_GDB | BP_MEM_ACCESS,
654 };
655
656 CPUClass *cc = CPU_GET_CLASS(cpu);
657 int cputype = xlat[gdbtype];
658
659 if (cc->gdb_stop_before_watchpoint) {
660 cputype |= BP_STOP_BEFORE_ACCESS;
661 }
662 return cputype;
663}
aliguoria1d1bb32008-11-18 20:07:32 +0000664#endif
665
aliguori880a7572008-11-18 20:30:24 +0000666static int gdb_breakpoint_insert(target_ulong addr, target_ulong len, int type)
aliguoria1d1bb32008-11-18 20:07:32 +0000667{
Andreas Färber182735e2013-05-29 22:29:20 +0200668 CPUState *cpu;
aliguori880a7572008-11-18 20:30:24 +0000669 int err = 0;
670
Andreas Färber62278812013-06-27 17:12:06 +0200671 if (kvm_enabled()) {
Andreas Färber2e0f2cf2013-06-27 19:19:39 +0200672 return kvm_insert_breakpoint(gdbserver_state->c_cpu, addr, len, type);
Andreas Färber62278812013-06-27 17:12:06 +0200673 }
aliguorie22a25c2009-03-12 20:12:48 +0000674
aliguoria1d1bb32008-11-18 20:07:32 +0000675 switch (type) {
676 case GDB_BREAKPOINT_SW:
677 case GDB_BREAKPOINT_HW:
Andreas Färberbdc44642013-06-24 23:50:24 +0200678 CPU_FOREACH(cpu) {
Andreas Färberb3310ab2013-09-02 17:26:20 +0200679 err = cpu_breakpoint_insert(cpu, addr, BP_GDB, NULL);
680 if (err) {
aliguori880a7572008-11-18 20:30:24 +0000681 break;
Andreas Färberb3310ab2013-09-02 17:26:20 +0200682 }
aliguori880a7572008-11-18 20:30:24 +0000683 }
684 return err;
aliguoria1d1bb32008-11-18 20:07:32 +0000685#ifndef CONFIG_USER_ONLY
686 case GDB_WATCHPOINT_WRITE:
687 case GDB_WATCHPOINT_READ:
688 case GDB_WATCHPOINT_ACCESS:
Andreas Färberbdc44642013-06-24 23:50:24 +0200689 CPU_FOREACH(cpu) {
Peter Maydell2472b6c2014-09-12 19:04:17 +0100690 err = cpu_watchpoint_insert(cpu, addr, len,
691 xlat_gdb_type(cpu, type), NULL);
692 if (err) {
aliguori880a7572008-11-18 20:30:24 +0000693 break;
Peter Maydell2472b6c2014-09-12 19:04:17 +0100694 }
aliguori880a7572008-11-18 20:30:24 +0000695 }
696 return err;
aliguoria1d1bb32008-11-18 20:07:32 +0000697#endif
698 default:
699 return -ENOSYS;
700 }
701}
702
aliguori880a7572008-11-18 20:30:24 +0000703static int gdb_breakpoint_remove(target_ulong addr, target_ulong len, int type)
aliguoria1d1bb32008-11-18 20:07:32 +0000704{
Andreas Färber182735e2013-05-29 22:29:20 +0200705 CPUState *cpu;
aliguori880a7572008-11-18 20:30:24 +0000706 int err = 0;
707
Andreas Färber62278812013-06-27 17:12:06 +0200708 if (kvm_enabled()) {
Andreas Färber2e0f2cf2013-06-27 19:19:39 +0200709 return kvm_remove_breakpoint(gdbserver_state->c_cpu, addr, len, type);
Andreas Färber62278812013-06-27 17:12:06 +0200710 }
aliguorie22a25c2009-03-12 20:12:48 +0000711
aliguoria1d1bb32008-11-18 20:07:32 +0000712 switch (type) {
713 case GDB_BREAKPOINT_SW:
714 case GDB_BREAKPOINT_HW:
Andreas Färberbdc44642013-06-24 23:50:24 +0200715 CPU_FOREACH(cpu) {
Andreas Färberb3310ab2013-09-02 17:26:20 +0200716 err = cpu_breakpoint_remove(cpu, addr, BP_GDB);
717 if (err) {
aliguori880a7572008-11-18 20:30:24 +0000718 break;
Andreas Färberb3310ab2013-09-02 17:26:20 +0200719 }
aliguori880a7572008-11-18 20:30:24 +0000720 }
721 return err;
aliguoria1d1bb32008-11-18 20:07:32 +0000722#ifndef CONFIG_USER_ONLY
723 case GDB_WATCHPOINT_WRITE:
724 case GDB_WATCHPOINT_READ:
725 case GDB_WATCHPOINT_ACCESS:
Andreas Färberbdc44642013-06-24 23:50:24 +0200726 CPU_FOREACH(cpu) {
Peter Maydell2472b6c2014-09-12 19:04:17 +0100727 err = cpu_watchpoint_remove(cpu, addr, len,
728 xlat_gdb_type(cpu, type));
aliguori880a7572008-11-18 20:30:24 +0000729 if (err)
730 break;
731 }
732 return err;
aliguoria1d1bb32008-11-18 20:07:32 +0000733#endif
734 default:
735 return -ENOSYS;
736 }
737}
738
aliguori880a7572008-11-18 20:30:24 +0000739static void gdb_breakpoint_remove_all(void)
aliguoria1d1bb32008-11-18 20:07:32 +0000740{
Andreas Färber182735e2013-05-29 22:29:20 +0200741 CPUState *cpu;
aliguori880a7572008-11-18 20:30:24 +0000742
aliguorie22a25c2009-03-12 20:12:48 +0000743 if (kvm_enabled()) {
Andreas Färber2e0f2cf2013-06-27 19:19:39 +0200744 kvm_remove_all_breakpoints(gdbserver_state->c_cpu);
aliguorie22a25c2009-03-12 20:12:48 +0000745 return;
746 }
747
Andreas Färberbdc44642013-06-24 23:50:24 +0200748 CPU_FOREACH(cpu) {
Andreas Färberb3310ab2013-09-02 17:26:20 +0200749 cpu_breakpoint_remove_all(cpu, BP_GDB);
aliguoria1d1bb32008-11-18 20:07:32 +0000750#ifndef CONFIG_USER_ONLY
Andreas Färber75a34032013-09-02 16:57:02 +0200751 cpu_watchpoint_remove_all(cpu, BP_GDB);
aliguoria1d1bb32008-11-18 20:07:32 +0000752#endif
aliguori880a7572008-11-18 20:30:24 +0000753 }
aliguoria1d1bb32008-11-18 20:07:32 +0000754}
755
aurel32fab9d282009-04-08 21:29:37 +0000756static void gdb_set_cpu_pc(GDBState *s, target_ulong pc)
757{
Andreas Färber2e0f2cf2013-06-27 19:19:39 +0200758 CPUState *cpu = s->c_cpu;
Andreas Färberf45748f2013-06-21 19:09:18 +0200759
760 cpu_synchronize_state(cpu);
Peter Crosthwaite4a2b24e2015-06-23 20:19:21 -0700761 cpu_set_pc(cpu, pc);
aurel32fab9d282009-04-08 21:29:37 +0000762}
763
Andreas Färber2e0f2cf2013-06-27 19:19:39 +0200764static CPUState *find_cpu(uint32_t thread_id)
Nathan Froyd1e9fa732009-06-03 11:33:08 -0700765{
Andreas Färber0d342822012-12-17 07:12:13 +0100766 CPUState *cpu;
Nathan Froyd1e9fa732009-06-03 11:33:08 -0700767
Andreas Färberbdc44642013-06-24 23:50:24 +0200768 CPU_FOREACH(cpu) {
Andreas Färberaa48dd92013-07-09 20:50:52 +0200769 if (cpu_index(cpu) == thread_id) {
Andreas Färber2e0f2cf2013-06-27 19:19:39 +0200770 return cpu;
Andreas Färberaa48dd92013-07-09 20:50:52 +0200771 }
Nathan Froyd1e9fa732009-06-03 11:33:08 -0700772 }
Andreas Färberaa48dd92013-07-09 20:50:52 +0200773
774 return NULL;
Nathan Froyd1e9fa732009-06-03 11:33:08 -0700775}
776
Jan Kiszka4dabe742015-02-07 09:38:43 +0100777static int is_query_packet(const char *p, const char *query, char separator)
778{
779 unsigned int query_len = strlen(query);
780
781 return strncmp(p, query, query_len) == 0 &&
782 (p[query_len] == '\0' || p[query_len] == separator);
783}
784
aliguori880a7572008-11-18 20:30:24 +0000785static int gdb_handle_packet(GDBState *s, const char *line_buf)
bellardb4608c02003-06-27 17:34:32 +0000786{
Andreas Färber2e0f2cf2013-06-27 19:19:39 +0200787 CPUState *cpu;
Andreas Färber5b24c642013-07-07 15:08:22 +0200788 CPUClass *cc;
bellardb4608c02003-06-27 17:34:32 +0000789 const char *p;
Nathan Froyd1e9fa732009-06-03 11:33:08 -0700790 uint32_t thread;
791 int ch, reg_size, type, res;
pbrook56aebc82008-10-11 17:55:29 +0000792 char buf[MAX_PACKET_LENGTH];
793 uint8_t mem_buf[MAX_PACKET_LENGTH];
794 uint8_t *registers;
bellard9d9754a2006-06-25 15:32:37 +0000795 target_ulong addr, len;
ths3b46e622007-09-17 08:09:54 +0000796
bellard858693c2004-03-31 18:52:07 +0000797#ifdef DEBUG_GDB
798 printf("command='%s'\n", line_buf);
bellard4c3a88a2003-07-26 12:06:08 +0000799#endif
bellard858693c2004-03-31 18:52:07 +0000800 p = line_buf;
801 ch = *p++;
802 switch(ch) {
803 case '?':
bellard1fddef42005-04-17 19:16:13 +0000804 /* TODO: Make this return the correct value for user-mode. */
aurel32ca587a82008-12-18 22:44:13 +0000805 snprintf(buf, sizeof(buf), "T%02xthread:%02x;", GDB_SIGNAL_TRAP,
Andreas Färber2e0f2cf2013-06-27 19:19:39 +0200806 cpu_index(s->c_cpu));
bellard858693c2004-03-31 18:52:07 +0000807 put_packet(s, buf);
edgar_igl7d03f822008-05-17 18:58:29 +0000808 /* Remove all the breakpoints when this query is issued,
809 * because gdb is doing and initial connect and the state
810 * should be cleaned up.
811 */
aliguori880a7572008-11-18 20:30:24 +0000812 gdb_breakpoint_remove_all();
bellard858693c2004-03-31 18:52:07 +0000813 break;
814 case 'c':
815 if (*p != '\0') {
bellard9d9754a2006-06-25 15:32:37 +0000816 addr = strtoull(p, (char **)&p, 16);
aurel32fab9d282009-04-08 21:29:37 +0000817 gdb_set_cpu_pc(s, addr);
bellard858693c2004-03-31 18:52:07 +0000818 }
aurel32ca587a82008-12-18 22:44:13 +0000819 s->signal = 0;
edgar_iglba70a622008-03-14 06:10:42 +0000820 gdb_continue(s);
bellard41625032005-04-24 10:07:11 +0000821 return RS_IDLE;
edgar_igl1f487ee2008-05-17 22:20:53 +0000822 case 'C':
aurel32ca587a82008-12-18 22:44:13 +0000823 s->signal = gdb_signal_to_target (strtoul(p, (char **)&p, 16));
824 if (s->signal == -1)
825 s->signal = 0;
edgar_igl1f487ee2008-05-17 22:20:53 +0000826 gdb_continue(s);
827 return RS_IDLE;
Jan Kiszkadd32aa12009-06-27 09:53:51 +0200828 case 'v':
829 if (strncmp(p, "Cont", 4) == 0) {
830 int res_signal, res_thread;
831
832 p += 4;
833 if (*p == '?') {
834 put_packet(s, "vCont;c;C;s;S");
835 break;
836 }
837 res = 0;
838 res_signal = 0;
839 res_thread = 0;
840 while (*p) {
841 int action, signal;
842
843 if (*p++ != ';') {
844 res = 0;
845 break;
846 }
847 action = *p++;
848 signal = 0;
849 if (action == 'C' || action == 'S') {
Martin Simmonsf17b0692014-11-05 14:47:39 +0000850 signal = gdb_signal_to_target(strtoul(p, (char **)&p, 16));
851 if (signal == -1) {
852 signal = 0;
853 }
Jan Kiszkadd32aa12009-06-27 09:53:51 +0200854 } else if (action != 'c' && action != 's') {
855 res = 0;
856 break;
857 }
858 thread = 0;
859 if (*p == ':') {
860 thread = strtoull(p+1, (char **)&p, 16);
861 }
862 action = tolower(action);
863 if (res == 0 || (res == 'c' && action == 's')) {
864 res = action;
865 res_signal = signal;
866 res_thread = thread;
867 }
868 }
869 if (res) {
870 if (res_thread != -1 && res_thread != 0) {
Andreas Färber2e0f2cf2013-06-27 19:19:39 +0200871 cpu = find_cpu(res_thread);
872 if (cpu == NULL) {
Jan Kiszkadd32aa12009-06-27 09:53:51 +0200873 put_packet(s, "E22");
874 break;
875 }
Andreas Färber2e0f2cf2013-06-27 19:19:39 +0200876 s->c_cpu = cpu;
Jan Kiszkadd32aa12009-06-27 09:53:51 +0200877 }
878 if (res == 's') {
Andreas Färber2e0f2cf2013-06-27 19:19:39 +0200879 cpu_single_step(s->c_cpu, sstep_flags);
Jan Kiszkadd32aa12009-06-27 09:53:51 +0200880 }
881 s->signal = res_signal;
882 gdb_continue(s);
883 return RS_IDLE;
884 }
885 break;
886 } else {
887 goto unknown_command;
888 }
edgar_igl7d03f822008-05-17 18:58:29 +0000889 case 'k':
890 /* Kill the target */
891 fprintf(stderr, "\nQEMU: Terminated via GDBstub\n");
892 exit(0);
893 case 'D':
894 /* Detach packet */
aliguori880a7572008-11-18 20:30:24 +0000895 gdb_breakpoint_remove_all();
Daniel Gutson7ea06da2010-02-26 14:13:50 -0300896 gdb_syscall_mode = GDB_SYS_DISABLED;
edgar_igl7d03f822008-05-17 18:58:29 +0000897 gdb_continue(s);
898 put_packet(s, "OK");
899 break;
bellard858693c2004-03-31 18:52:07 +0000900 case 's':
901 if (*p != '\0') {
ths8fac5802007-07-12 10:05:07 +0000902 addr = strtoull(p, (char **)&p, 16);
aurel32fab9d282009-04-08 21:29:37 +0000903 gdb_set_cpu_pc(s, addr);
bellard858693c2004-03-31 18:52:07 +0000904 }
Andreas Färber2e0f2cf2013-06-27 19:19:39 +0200905 cpu_single_step(s->c_cpu, sstep_flags);
edgar_iglba70a622008-03-14 06:10:42 +0000906 gdb_continue(s);
bellard41625032005-04-24 10:07:11 +0000907 return RS_IDLE;
pbrooka2d1eba2007-01-28 03:10:55 +0000908 case 'F':
909 {
910 target_ulong ret;
911 target_ulong err;
912
913 ret = strtoull(p, (char **)&p, 16);
914 if (*p == ',') {
915 p++;
916 err = strtoull(p, (char **)&p, 16);
917 } else {
918 err = 0;
919 }
920 if (*p == ',')
921 p++;
922 type = *p;
Meador Ingecdb432b2012-03-15 17:49:45 +0000923 if (s->current_syscall_cb) {
Andreas Färber2e0f2cf2013-06-27 19:19:39 +0200924 s->current_syscall_cb(s->c_cpu, ret, err);
Meador Ingecdb432b2012-03-15 17:49:45 +0000925 s->current_syscall_cb = NULL;
926 }
pbrooka2d1eba2007-01-28 03:10:55 +0000927 if (type == 'C') {
928 put_packet(s, "T02");
929 } else {
edgar_iglba70a622008-03-14 06:10:42 +0000930 gdb_continue(s);
pbrooka2d1eba2007-01-28 03:10:55 +0000931 }
932 }
933 break;
bellard858693c2004-03-31 18:52:07 +0000934 case 'g':
Andreas Färber2e0f2cf2013-06-27 19:19:39 +0200935 cpu_synchronize_state(s->g_cpu);
pbrook56aebc82008-10-11 17:55:29 +0000936 len = 0;
Andreas Färber35143f02013-08-12 18:09:47 +0200937 for (addr = 0; addr < s->g_cpu->gdb_num_g_regs; addr++) {
Andreas Färber2e0f2cf2013-06-27 19:19:39 +0200938 reg_size = gdb_read_register(s->g_cpu, mem_buf + len, addr);
pbrook56aebc82008-10-11 17:55:29 +0000939 len += reg_size;
940 }
941 memtohex(buf, mem_buf, len);
bellard858693c2004-03-31 18:52:07 +0000942 put_packet(s, buf);
943 break;
944 case 'G':
Andreas Färber2e0f2cf2013-06-27 19:19:39 +0200945 cpu_synchronize_state(s->g_cpu);
pbrook56aebc82008-10-11 17:55:29 +0000946 registers = mem_buf;
bellard858693c2004-03-31 18:52:07 +0000947 len = strlen(p) / 2;
948 hextomem((uint8_t *)registers, p, len);
Andreas Färber35143f02013-08-12 18:09:47 +0200949 for (addr = 0; addr < s->g_cpu->gdb_num_g_regs && len > 0; addr++) {
Andreas Färber2e0f2cf2013-06-27 19:19:39 +0200950 reg_size = gdb_write_register(s->g_cpu, registers, addr);
pbrook56aebc82008-10-11 17:55:29 +0000951 len -= reg_size;
952 registers += reg_size;
953 }
bellard858693c2004-03-31 18:52:07 +0000954 put_packet(s, "OK");
955 break;
956 case 'm':
bellard9d9754a2006-06-25 15:32:37 +0000957 addr = strtoull(p, (char **)&p, 16);
bellard858693c2004-03-31 18:52:07 +0000958 if (*p == ',')
959 p++;
bellard9d9754a2006-06-25 15:32:37 +0000960 len = strtoull(p, NULL, 16);
Kevin Wolf5accecb2015-10-13 09:38:50 +0200961
962 /* memtohex() doubles the required space */
963 if (len > MAX_PACKET_LENGTH / 2) {
964 put_packet (s, "E22");
965 break;
966 }
967
Andreas Färber2e0f2cf2013-06-27 19:19:39 +0200968 if (target_memory_rw_debug(s->g_cpu, addr, mem_buf, len, false) != 0) {
bellard6f970bd2005-12-05 19:55:19 +0000969 put_packet (s, "E14");
970 } else {
971 memtohex(buf, mem_buf, len);
972 put_packet(s, buf);
973 }
bellard858693c2004-03-31 18:52:07 +0000974 break;
975 case 'M':
bellard9d9754a2006-06-25 15:32:37 +0000976 addr = strtoull(p, (char **)&p, 16);
bellard858693c2004-03-31 18:52:07 +0000977 if (*p == ',')
978 p++;
bellard9d9754a2006-06-25 15:32:37 +0000979 len = strtoull(p, (char **)&p, 16);
bellardb328f872005-01-17 22:03:16 +0000980 if (*p == ':')
bellard858693c2004-03-31 18:52:07 +0000981 p++;
Kevin Wolf5accecb2015-10-13 09:38:50 +0200982
983 /* hextomem() reads 2*len bytes */
984 if (len > strlen(p) / 2) {
985 put_packet (s, "E22");
986 break;
987 }
bellard858693c2004-03-31 18:52:07 +0000988 hextomem(mem_buf, p, len);
Andreas Färber2e0f2cf2013-06-27 19:19:39 +0200989 if (target_memory_rw_debug(s->g_cpu, addr, mem_buf, len,
Andreas Färberf3659ee2013-06-27 19:09:09 +0200990 true) != 0) {
bellard905f20b2005-04-26 21:09:55 +0000991 put_packet(s, "E14");
Fabien Chouteau44520db2011-09-08 12:48:16 +0200992 } else {
bellard858693c2004-03-31 18:52:07 +0000993 put_packet(s, "OK");
Fabien Chouteau44520db2011-09-08 12:48:16 +0200994 }
bellard858693c2004-03-31 18:52:07 +0000995 break;
pbrook56aebc82008-10-11 17:55:29 +0000996 case 'p':
997 /* Older gdb are really dumb, and don't use 'g' if 'p' is avaialable.
998 This works, but can be very slow. Anything new enough to
999 understand XML also knows how to use this properly. */
1000 if (!gdb_has_xml)
1001 goto unknown_command;
1002 addr = strtoull(p, (char **)&p, 16);
Andreas Färber2e0f2cf2013-06-27 19:19:39 +02001003 reg_size = gdb_read_register(s->g_cpu, mem_buf, addr);
pbrook56aebc82008-10-11 17:55:29 +00001004 if (reg_size) {
1005 memtohex(buf, mem_buf, reg_size);
1006 put_packet(s, buf);
1007 } else {
1008 put_packet(s, "E14");
1009 }
1010 break;
1011 case 'P':
1012 if (!gdb_has_xml)
1013 goto unknown_command;
1014 addr = strtoull(p, (char **)&p, 16);
1015 if (*p == '=')
1016 p++;
1017 reg_size = strlen(p) / 2;
1018 hextomem(mem_buf, p, reg_size);
Andreas Färber2e0f2cf2013-06-27 19:19:39 +02001019 gdb_write_register(s->g_cpu, mem_buf, addr);
pbrook56aebc82008-10-11 17:55:29 +00001020 put_packet(s, "OK");
1021 break;
bellard858693c2004-03-31 18:52:07 +00001022 case 'Z':
bellard858693c2004-03-31 18:52:07 +00001023 case 'z':
1024 type = strtoul(p, (char **)&p, 16);
1025 if (*p == ',')
1026 p++;
bellard9d9754a2006-06-25 15:32:37 +00001027 addr = strtoull(p, (char **)&p, 16);
bellard858693c2004-03-31 18:52:07 +00001028 if (*p == ',')
1029 p++;
bellard9d9754a2006-06-25 15:32:37 +00001030 len = strtoull(p, (char **)&p, 16);
aliguoria1d1bb32008-11-18 20:07:32 +00001031 if (ch == 'Z')
aliguori880a7572008-11-18 20:30:24 +00001032 res = gdb_breakpoint_insert(addr, len, type);
aliguoria1d1bb32008-11-18 20:07:32 +00001033 else
aliguori880a7572008-11-18 20:30:24 +00001034 res = gdb_breakpoint_remove(addr, len, type);
aliguoria1d1bb32008-11-18 20:07:32 +00001035 if (res >= 0)
1036 put_packet(s, "OK");
1037 else if (res == -ENOSYS)
pbrook0f459d12008-06-09 00:20:13 +00001038 put_packet(s, "");
aliguoria1d1bb32008-11-18 20:07:32 +00001039 else
1040 put_packet(s, "E22");
bellard858693c2004-03-31 18:52:07 +00001041 break;
aliguori880a7572008-11-18 20:30:24 +00001042 case 'H':
1043 type = *p++;
1044 thread = strtoull(p, (char **)&p, 16);
1045 if (thread == -1 || thread == 0) {
1046 put_packet(s, "OK");
1047 break;
1048 }
Andreas Färber2e0f2cf2013-06-27 19:19:39 +02001049 cpu = find_cpu(thread);
1050 if (cpu == NULL) {
aliguori880a7572008-11-18 20:30:24 +00001051 put_packet(s, "E22");
1052 break;
1053 }
1054 switch (type) {
1055 case 'c':
Andreas Färber2e0f2cf2013-06-27 19:19:39 +02001056 s->c_cpu = cpu;
aliguori880a7572008-11-18 20:30:24 +00001057 put_packet(s, "OK");
1058 break;
1059 case 'g':
Andreas Färber2e0f2cf2013-06-27 19:19:39 +02001060 s->g_cpu = cpu;
aliguori880a7572008-11-18 20:30:24 +00001061 put_packet(s, "OK");
1062 break;
1063 default:
1064 put_packet(s, "E22");
1065 break;
1066 }
1067 break;
1068 case 'T':
1069 thread = strtoull(p, (char **)&p, 16);
Andreas Färber2e0f2cf2013-06-27 19:19:39 +02001070 cpu = find_cpu(thread);
Nathan Froyd1e9fa732009-06-03 11:33:08 -07001071
Andreas Färber2e0f2cf2013-06-27 19:19:39 +02001072 if (cpu != NULL) {
Nathan Froyd1e9fa732009-06-03 11:33:08 -07001073 put_packet(s, "OK");
1074 } else {
aliguori880a7572008-11-18 20:30:24 +00001075 put_packet(s, "E22");
Nathan Froyd1e9fa732009-06-03 11:33:08 -07001076 }
aliguori880a7572008-11-18 20:30:24 +00001077 break;
pbrook978efd62006-06-17 18:30:42 +00001078 case 'q':
edgar_igl60897d32008-05-09 08:25:14 +00001079 case 'Q':
1080 /* parse any 'q' packets here */
1081 if (!strcmp(p,"qemu.sstepbits")) {
1082 /* Query Breakpoint bit definitions */
blueswir1363a37d2008-08-21 17:58:08 +00001083 snprintf(buf, sizeof(buf), "ENABLE=%x,NOIRQ=%x,NOTIMER=%x",
1084 SSTEP_ENABLE,
1085 SSTEP_NOIRQ,
1086 SSTEP_NOTIMER);
edgar_igl60897d32008-05-09 08:25:14 +00001087 put_packet(s, buf);
1088 break;
Jan Kiszka4dabe742015-02-07 09:38:43 +01001089 } else if (is_query_packet(p, "qemu.sstep", '=')) {
edgar_igl60897d32008-05-09 08:25:14 +00001090 /* Display or change the sstep_flags */
1091 p += 10;
1092 if (*p != '=') {
1093 /* Display current setting */
blueswir1363a37d2008-08-21 17:58:08 +00001094 snprintf(buf, sizeof(buf), "0x%x", sstep_flags);
edgar_igl60897d32008-05-09 08:25:14 +00001095 put_packet(s, buf);
1096 break;
1097 }
1098 p++;
1099 type = strtoul(p, (char **)&p, 16);
1100 sstep_flags = type;
1101 put_packet(s, "OK");
1102 break;
aliguori880a7572008-11-18 20:30:24 +00001103 } else if (strcmp(p,"C") == 0) {
1104 /* "Current thread" remains vague in the spec, so always return
1105 * the first CPU (gdb returns the first thread). */
1106 put_packet(s, "QC1");
1107 break;
1108 } else if (strcmp(p,"fThreadInfo") == 0) {
Andreas Färber52f34622013-06-27 13:44:40 +02001109 s->query_cpu = first_cpu;
aliguori880a7572008-11-18 20:30:24 +00001110 goto report_cpuinfo;
1111 } else if (strcmp(p,"sThreadInfo") == 0) {
1112 report_cpuinfo:
1113 if (s->query_cpu) {
Andreas Färber52f34622013-06-27 13:44:40 +02001114 snprintf(buf, sizeof(buf), "m%x", cpu_index(s->query_cpu));
aliguori880a7572008-11-18 20:30:24 +00001115 put_packet(s, buf);
Andreas Färberbdc44642013-06-24 23:50:24 +02001116 s->query_cpu = CPU_NEXT(s->query_cpu);
aliguori880a7572008-11-18 20:30:24 +00001117 } else
1118 put_packet(s, "l");
1119 break;
1120 } else if (strncmp(p,"ThreadExtraInfo,", 16) == 0) {
1121 thread = strtoull(p+16, (char **)&p, 16);
Andreas Färber2e0f2cf2013-06-27 19:19:39 +02001122 cpu = find_cpu(thread);
1123 if (cpu != NULL) {
Andreas Färbercb446ec2013-05-01 14:24:52 +02001124 cpu_synchronize_state(cpu);
Kevin Wolf5accecb2015-10-13 09:38:50 +02001125 /* memtohex() doubles the required space */
1126 len = snprintf((char *)mem_buf, sizeof(buf) / 2,
Andreas Färber55e5c282012-12-17 06:18:02 +01001127 "CPU#%d [%s]", cpu->cpu_index,
Andreas Färber259186a2013-01-17 18:51:17 +01001128 cpu->halted ? "halted " : "running");
Nathan Froyd1e9fa732009-06-03 11:33:08 -07001129 memtohex(buf, mem_buf, len);
1130 put_packet(s, buf);
1131 }
aliguori880a7572008-11-18 20:30:24 +00001132 break;
edgar_igl60897d32008-05-09 08:25:14 +00001133 }
blueswir10b8a9882009-03-07 10:51:36 +00001134#ifdef CONFIG_USER_ONLY
Jan Kiszka070949f2015-02-07 09:38:42 +01001135 else if (strcmp(p, "Offsets") == 0) {
Andreas Färber0429a972013-08-26 18:14:44 +02001136 TaskState *ts = s->c_cpu->opaque;
pbrook978efd62006-06-17 18:30:42 +00001137
blueswir1363a37d2008-08-21 17:58:08 +00001138 snprintf(buf, sizeof(buf),
1139 "Text=" TARGET_ABI_FMT_lx ";Data=" TARGET_ABI_FMT_lx
1140 ";Bss=" TARGET_ABI_FMT_lx,
1141 ts->info->code_offset,
1142 ts->info->data_offset,
1143 ts->info->data_offset);
pbrook978efd62006-06-17 18:30:42 +00001144 put_packet(s, buf);
1145 break;
1146 }
blueswir10b8a9882009-03-07 10:51:36 +00001147#else /* !CONFIG_USER_ONLY */
aliguori8a34a0f2009-03-05 23:01:55 +00001148 else if (strncmp(p, "Rcmd,", 5) == 0) {
1149 int len = strlen(p + 5);
1150
1151 if ((len % 2) != 0) {
1152 put_packet(s, "E01");
1153 break;
1154 }
aliguori8a34a0f2009-03-05 23:01:55 +00001155 len = len / 2;
Kevin Wolf5accecb2015-10-13 09:38:50 +02001156 hextomem(mem_buf, p + 5, len);
aliguori8a34a0f2009-03-05 23:01:55 +00001157 mem_buf[len++] = 0;
Anthony Liguorifa5efcc2011-08-15 11:17:30 -05001158 qemu_chr_be_write(s->mon_chr, mem_buf, len);
aliguori8a34a0f2009-03-05 23:01:55 +00001159 put_packet(s, "OK");
1160 break;
1161 }
blueswir10b8a9882009-03-07 10:51:36 +00001162#endif /* !CONFIG_USER_ONLY */
Jan Kiszka4dabe742015-02-07 09:38:43 +01001163 if (is_query_packet(p, "Supported", ':')) {
blueswir15b3715b2008-10-25 11:18:12 +00001164 snprintf(buf, sizeof(buf), "PacketSize=%x", MAX_PACKET_LENGTH);
Andreas Färber5b24c642013-07-07 15:08:22 +02001165 cc = CPU_GET_CLASS(first_cpu);
1166 if (cc->gdb_core_xml_file != NULL) {
1167 pstrcat(buf, sizeof(buf), ";qXfer:features:read+");
1168 }
pbrook56aebc82008-10-11 17:55:29 +00001169 put_packet(s, buf);
1170 break;
1171 }
pbrook56aebc82008-10-11 17:55:29 +00001172 if (strncmp(p, "Xfer:features:read:", 19) == 0) {
1173 const char *xml;
1174 target_ulong total_len;
1175
Andreas Färber5b24c642013-07-07 15:08:22 +02001176 cc = CPU_GET_CLASS(first_cpu);
1177 if (cc->gdb_core_xml_file == NULL) {
1178 goto unknown_command;
1179 }
1180
Andreas Färber5b50e792013-06-29 04:18:45 +02001181 gdb_has_xml = true;
pbrook56aebc82008-10-11 17:55:29 +00001182 p += 19;
Andreas Färber5b24c642013-07-07 15:08:22 +02001183 xml = get_feature_xml(p, &p, cc);
pbrook56aebc82008-10-11 17:55:29 +00001184 if (!xml) {
blueswir15b3715b2008-10-25 11:18:12 +00001185 snprintf(buf, sizeof(buf), "E00");
pbrook56aebc82008-10-11 17:55:29 +00001186 put_packet(s, buf);
1187 break;
1188 }
1189
1190 if (*p == ':')
1191 p++;
1192 addr = strtoul(p, (char **)&p, 16);
1193 if (*p == ',')
1194 p++;
1195 len = strtoul(p, (char **)&p, 16);
1196
1197 total_len = strlen(xml);
1198 if (addr > total_len) {
blueswir15b3715b2008-10-25 11:18:12 +00001199 snprintf(buf, sizeof(buf), "E00");
pbrook56aebc82008-10-11 17:55:29 +00001200 put_packet(s, buf);
1201 break;
1202 }
1203 if (len > (MAX_PACKET_LENGTH - 5) / 2)
1204 len = (MAX_PACKET_LENGTH - 5) / 2;
1205 if (len < total_len - addr) {
1206 buf[0] = 'm';
1207 len = memtox(buf + 1, xml + addr, len);
1208 } else {
1209 buf[0] = 'l';
1210 len = memtox(buf + 1, xml + addr, total_len - addr);
1211 }
1212 put_packet_binary(s, buf, len + 1);
1213 break;
1214 }
Jan Kiszkaa3919382015-02-07 09:38:44 +01001215 if (is_query_packet(p, "Attached", ':')) {
1216 put_packet(s, GDB_ATTACHED);
1217 break;
1218 }
pbrook56aebc82008-10-11 17:55:29 +00001219 /* Unrecognised 'q' command. */
1220 goto unknown_command;
1221
bellard858693c2004-03-31 18:52:07 +00001222 default:
pbrook56aebc82008-10-11 17:55:29 +00001223 unknown_command:
bellard858693c2004-03-31 18:52:07 +00001224 /* put empty packet */
1225 buf[0] = '\0';
1226 put_packet(s, buf);
1227 break;
1228 }
1229 return RS_IDLE;
1230}
1231
Andreas Färber64f6b342013-05-27 02:06:09 +02001232void gdb_set_stop_cpu(CPUState *cpu)
aliguori880a7572008-11-18 20:30:24 +00001233{
Andreas Färber2e0f2cf2013-06-27 19:19:39 +02001234 gdbserver_state->c_cpu = cpu;
1235 gdbserver_state->g_cpu = cpu;
aliguori880a7572008-11-18 20:30:24 +00001236}
1237
bellard1fddef42005-04-17 19:16:13 +00001238#ifndef CONFIG_USER_ONLY
Luiz Capitulino1dfb4dd2011-07-29 14:26:33 -03001239static void gdb_vm_state_change(void *opaque, int running, RunState state)
bellard858693c2004-03-31 18:52:07 +00001240{
aliguori880a7572008-11-18 20:30:24 +00001241 GDBState *s = gdbserver_state;
Andreas Färber2e0f2cf2013-06-27 19:19:39 +02001242 CPUState *cpu = s->c_cpu;
bellard858693c2004-03-31 18:52:07 +00001243 char buf[256];
aliguorid6fc1b32008-11-18 19:55:44 +00001244 const char *type;
bellard858693c2004-03-31 18:52:07 +00001245 int ret;
1246
Meador Ingecdb432b2012-03-15 17:49:45 +00001247 if (running || s->state == RS_INACTIVE) {
1248 return;
1249 }
1250 /* Is there a GDB syscall waiting to be sent? */
1251 if (s->current_syscall_cb) {
1252 put_packet(s, s->syscall_buf);
pbrooka2d1eba2007-01-28 03:10:55 +00001253 return;
Jan Kiszkae07bbac2011-02-09 16:29:40 +01001254 }
Luiz Capitulino1dfb4dd2011-07-29 14:26:33 -03001255 switch (state) {
Luiz Capitulino0461d5a2011-09-30 14:45:27 -03001256 case RUN_STATE_DEBUG:
Andreas Färberff4700b2013-08-26 18:23:18 +02001257 if (cpu->watchpoint_hit) {
1258 switch (cpu->watchpoint_hit->flags & BP_MEM_ACCESS) {
aliguoria1d1bb32008-11-18 20:07:32 +00001259 case BP_MEM_READ:
aliguorid6fc1b32008-11-18 19:55:44 +00001260 type = "r";
1261 break;
aliguoria1d1bb32008-11-18 20:07:32 +00001262 case BP_MEM_ACCESS:
aliguorid6fc1b32008-11-18 19:55:44 +00001263 type = "a";
1264 break;
1265 default:
1266 type = "";
1267 break;
1268 }
aliguori880a7572008-11-18 20:30:24 +00001269 snprintf(buf, sizeof(buf),
1270 "T%02xthread:%02x;%swatch:" TARGET_FMT_lx ";",
Andreas Färber0d342822012-12-17 07:12:13 +01001271 GDB_SIGNAL_TRAP, cpu_index(cpu), type,
Andreas Färberff4700b2013-08-26 18:23:18 +02001272 (target_ulong)cpu->watchpoint_hit->vaddr);
1273 cpu->watchpoint_hit = NULL;
Jan Kiszka425189a2011-03-22 11:02:09 +01001274 goto send_packet;
pbrook6658ffb2007-03-16 23:58:11 +00001275 }
Peter Crosthwaitebbd77c12015-06-23 19:31:15 -07001276 tb_flush(cpu);
aurel32ca587a82008-12-18 22:44:13 +00001277 ret = GDB_SIGNAL_TRAP;
Jan Kiszka425189a2011-03-22 11:02:09 +01001278 break;
Luiz Capitulino0461d5a2011-09-30 14:45:27 -03001279 case RUN_STATE_PAUSED:
aliguori9781e042009-01-22 17:15:29 +00001280 ret = GDB_SIGNAL_INT;
Jan Kiszka425189a2011-03-22 11:02:09 +01001281 break;
Luiz Capitulino0461d5a2011-09-30 14:45:27 -03001282 case RUN_STATE_SHUTDOWN:
Jan Kiszka425189a2011-03-22 11:02:09 +01001283 ret = GDB_SIGNAL_QUIT;
1284 break;
Luiz Capitulino0461d5a2011-09-30 14:45:27 -03001285 case RUN_STATE_IO_ERROR:
Jan Kiszka425189a2011-03-22 11:02:09 +01001286 ret = GDB_SIGNAL_IO;
1287 break;
Luiz Capitulino0461d5a2011-09-30 14:45:27 -03001288 case RUN_STATE_WATCHDOG:
Jan Kiszka425189a2011-03-22 11:02:09 +01001289 ret = GDB_SIGNAL_ALRM;
1290 break;
Luiz Capitulino0461d5a2011-09-30 14:45:27 -03001291 case RUN_STATE_INTERNAL_ERROR:
Jan Kiszka425189a2011-03-22 11:02:09 +01001292 ret = GDB_SIGNAL_ABRT;
1293 break;
Luiz Capitulino0461d5a2011-09-30 14:45:27 -03001294 case RUN_STATE_SAVE_VM:
1295 case RUN_STATE_RESTORE_VM:
Jan Kiszka425189a2011-03-22 11:02:09 +01001296 return;
Luiz Capitulino0461d5a2011-09-30 14:45:27 -03001297 case RUN_STATE_FINISH_MIGRATE:
Jan Kiszka425189a2011-03-22 11:02:09 +01001298 ret = GDB_SIGNAL_XCPU;
1299 break;
1300 default:
1301 ret = GDB_SIGNAL_UNKNOWN;
1302 break;
bellardbbeb7b52006-04-23 18:42:15 +00001303 }
Jan Kiszka226d0072015-07-24 18:52:31 +02001304 gdb_set_stop_cpu(cpu);
Andreas Färber0d342822012-12-17 07:12:13 +01001305 snprintf(buf, sizeof(buf), "T%02xthread:%02x;", ret, cpu_index(cpu));
Jan Kiszka425189a2011-03-22 11:02:09 +01001306
1307send_packet:
bellard858693c2004-03-31 18:52:07 +00001308 put_packet(s, buf);
Jan Kiszka425189a2011-03-22 11:02:09 +01001309
1310 /* disable single step if it was enabled */
Andreas Färber3825b282013-06-24 18:41:06 +02001311 cpu_single_step(cpu, 0);
bellard858693c2004-03-31 18:52:07 +00001312}
bellard1fddef42005-04-17 19:16:13 +00001313#endif
bellard858693c2004-03-31 18:52:07 +00001314
pbrooka2d1eba2007-01-28 03:10:55 +00001315/* Send a gdb syscall request.
1316 This accepts limited printf-style format specifiers, specifically:
pbrooka87295e2007-05-26 15:09:38 +00001317 %x - target_ulong argument printed in hex.
1318 %lx - 64-bit argument printed in hex.
1319 %s - string pointer (target_ulong) and length (int) pair. */
Peter Maydell19239b32015-09-07 10:39:27 +01001320void gdb_do_syscallv(gdb_syscall_complete_cb cb, const char *fmt, va_list va)
pbrooka2d1eba2007-01-28 03:10:55 +00001321{
pbrooka2d1eba2007-01-28 03:10:55 +00001322 char *p;
Meador Ingecdb432b2012-03-15 17:49:45 +00001323 char *p_end;
pbrooka2d1eba2007-01-28 03:10:55 +00001324 target_ulong addr;
pbrooka87295e2007-05-26 15:09:38 +00001325 uint64_t i64;
pbrooka2d1eba2007-01-28 03:10:55 +00001326 GDBState *s;
1327
aliguori880a7572008-11-18 20:30:24 +00001328 s = gdbserver_state;
pbrooka2d1eba2007-01-28 03:10:55 +00001329 if (!s)
1330 return;
Meador Ingecdb432b2012-03-15 17:49:45 +00001331 s->current_syscall_cb = cb;
pbrooka2d1eba2007-01-28 03:10:55 +00001332#ifndef CONFIG_USER_ONLY
Luiz Capitulino0461d5a2011-09-30 14:45:27 -03001333 vm_stop(RUN_STATE_DEBUG);
pbrooka2d1eba2007-01-28 03:10:55 +00001334#endif
Meador Ingecdb432b2012-03-15 17:49:45 +00001335 p = s->syscall_buf;
1336 p_end = &s->syscall_buf[sizeof(s->syscall_buf)];
pbrooka2d1eba2007-01-28 03:10:55 +00001337 *(p++) = 'F';
1338 while (*fmt) {
1339 if (*fmt == '%') {
1340 fmt++;
1341 switch (*fmt++) {
1342 case 'x':
1343 addr = va_arg(va, target_ulong);
Meador Ingecdb432b2012-03-15 17:49:45 +00001344 p += snprintf(p, p_end - p, TARGET_FMT_lx, addr);
pbrooka2d1eba2007-01-28 03:10:55 +00001345 break;
pbrooka87295e2007-05-26 15:09:38 +00001346 case 'l':
1347 if (*(fmt++) != 'x')
1348 goto bad_format;
1349 i64 = va_arg(va, uint64_t);
Meador Ingecdb432b2012-03-15 17:49:45 +00001350 p += snprintf(p, p_end - p, "%" PRIx64, i64);
pbrooka87295e2007-05-26 15:09:38 +00001351 break;
pbrooka2d1eba2007-01-28 03:10:55 +00001352 case 's':
1353 addr = va_arg(va, target_ulong);
Meador Ingecdb432b2012-03-15 17:49:45 +00001354 p += snprintf(p, p_end - p, TARGET_FMT_lx "/%x",
blueswir1363a37d2008-08-21 17:58:08 +00001355 addr, va_arg(va, int));
pbrooka2d1eba2007-01-28 03:10:55 +00001356 break;
1357 default:
pbrooka87295e2007-05-26 15:09:38 +00001358 bad_format:
pbrooka2d1eba2007-01-28 03:10:55 +00001359 fprintf(stderr, "gdbstub: Bad syscall format string '%s'\n",
1360 fmt - 1);
1361 break;
1362 }
1363 } else {
1364 *(p++) = *(fmt++);
1365 }
1366 }
pbrook8a93e022007-08-06 13:19:15 +00001367 *p = 0;
pbrooka2d1eba2007-01-28 03:10:55 +00001368#ifdef CONFIG_USER_ONLY
Meador Ingecdb432b2012-03-15 17:49:45 +00001369 put_packet(s, s->syscall_buf);
Andreas Färber2e0f2cf2013-06-27 19:19:39 +02001370 gdb_handlesig(s->c_cpu, 0);
pbrooka2d1eba2007-01-28 03:10:55 +00001371#else
Meador Ingecdb432b2012-03-15 17:49:45 +00001372 /* In this case wait to send the syscall packet until notification that
1373 the CPU has stopped. This must be done because if the packet is sent
1374 now the reply from the syscall request could be received while the CPU
1375 is still in the running state, which can cause packets to be dropped
1376 and state transition 'T' packets to be sent while the syscall is still
1377 being processed. */
Paolo Bonzini9102ded2015-08-18 06:52:09 -07001378 qemu_cpu_kick(s->c_cpu);
pbrooka2d1eba2007-01-28 03:10:55 +00001379#endif
1380}
1381
Peter Maydell19239b32015-09-07 10:39:27 +01001382void gdb_do_syscall(gdb_syscall_complete_cb cb, const char *fmt, ...)
1383{
1384 va_list va;
1385
1386 va_start(va, fmt);
1387 gdb_do_syscallv(cb, fmt, va);
1388 va_end(va);
1389}
1390
bellard6a00d602005-11-21 23:25:50 +00001391static void gdb_read_byte(GDBState *s, int ch)
bellard858693c2004-03-31 18:52:07 +00001392{
1393 int i, csum;
ths60fe76f2007-12-16 03:02:09 +00001394 uint8_t reply;
bellard858693c2004-03-31 18:52:07 +00001395
bellard1fddef42005-04-17 19:16:13 +00001396#ifndef CONFIG_USER_ONLY
pbrook4046d912007-01-28 01:53:16 +00001397 if (s->last_packet_len) {
1398 /* Waiting for a response to the last packet. If we see the start
1399 of a new command then abandon the previous response. */
1400 if (ch == '-') {
1401#ifdef DEBUG_GDB
1402 printf("Got NACK, retransmitting\n");
1403#endif
thsffe8ab82007-12-16 03:16:05 +00001404 put_buffer(s, (uint8_t *)s->last_packet, s->last_packet_len);
pbrook4046d912007-01-28 01:53:16 +00001405 }
1406#ifdef DEBUG_GDB
1407 else if (ch == '+')
1408 printf("Got ACK\n");
1409 else
1410 printf("Got '%c' when expecting ACK/NACK\n", ch);
1411#endif
1412 if (ch == '+' || ch == '$')
1413 s->last_packet_len = 0;
1414 if (ch != '$')
1415 return;
1416 }
Luiz Capitulino13548692011-07-29 15:36:43 -03001417 if (runstate_is_running()) {
bellard858693c2004-03-31 18:52:07 +00001418 /* when the CPU is running, we cannot do anything except stop
1419 it when receiving a char */
Luiz Capitulino0461d5a2011-09-30 14:45:27 -03001420 vm_stop(RUN_STATE_PAUSED);
ths5fafdf22007-09-16 21:08:06 +00001421 } else
bellard1fddef42005-04-17 19:16:13 +00001422#endif
bellard41625032005-04-24 10:07:11 +00001423 {
bellard858693c2004-03-31 18:52:07 +00001424 switch(s->state) {
1425 case RS_IDLE:
1426 if (ch == '$') {
1427 s->line_buf_index = 0;
1428 s->state = RS_GETLINE;
bellard4c3a88a2003-07-26 12:06:08 +00001429 }
1430 break;
bellard858693c2004-03-31 18:52:07 +00001431 case RS_GETLINE:
1432 if (ch == '#') {
1433 s->state = RS_CHKSUM1;
1434 } else if (s->line_buf_index >= sizeof(s->line_buf) - 1) {
1435 s->state = RS_IDLE;
1436 } else {
1437 s->line_buf[s->line_buf_index++] = ch;
1438 }
1439 break;
1440 case RS_CHKSUM1:
1441 s->line_buf[s->line_buf_index] = '\0';
1442 s->line_csum = fromhex(ch) << 4;
1443 s->state = RS_CHKSUM2;
1444 break;
1445 case RS_CHKSUM2:
1446 s->line_csum |= fromhex(ch);
1447 csum = 0;
1448 for(i = 0; i < s->line_buf_index; i++) {
1449 csum += s->line_buf[i];
1450 }
1451 if (s->line_csum != (csum & 0xff)) {
ths60fe76f2007-12-16 03:02:09 +00001452 reply = '-';
1453 put_buffer(s, &reply, 1);
bellard858693c2004-03-31 18:52:07 +00001454 s->state = RS_IDLE;
1455 } else {
ths60fe76f2007-12-16 03:02:09 +00001456 reply = '+';
1457 put_buffer(s, &reply, 1);
aliguori880a7572008-11-18 20:30:24 +00001458 s->state = gdb_handle_packet(s, s->line_buf);
bellard858693c2004-03-31 18:52:07 +00001459 }
bellardb4608c02003-06-27 17:34:32 +00001460 break;
pbrooka2d1eba2007-01-28 03:10:55 +00001461 default:
1462 abort();
bellardb4608c02003-06-27 17:34:32 +00001463 }
1464 }
bellard858693c2004-03-31 18:52:07 +00001465}
1466
Paul Brook0e1c9c52010-06-16 13:03:51 +01001467/* Tell the remote gdb that the process has exited. */
Andreas Färber9349b4f2012-03-14 01:38:32 +01001468void gdb_exit(CPUArchState *env, int code)
Paul Brook0e1c9c52010-06-16 13:03:51 +01001469{
1470 GDBState *s;
1471 char buf[4];
1472
1473 s = gdbserver_state;
1474 if (!s) {
1475 return;
1476 }
1477#ifdef CONFIG_USER_ONLY
1478 if (gdbserver_fd < 0 || s->fd < 0) {
1479 return;
1480 }
Paolo Bonzini3d0f4412015-03-02 13:26:58 +01001481#else
1482 if (!s->chr) {
1483 return;
1484 }
Paul Brook0e1c9c52010-06-16 13:03:51 +01001485#endif
1486
1487 snprintf(buf, sizeof(buf), "W%02x", (uint8_t)code);
1488 put_packet(s, buf);
Fabien Chouteaue2af15b2011-01-13 12:46:57 +01001489
1490#ifndef CONFIG_USER_ONLY
Paolo Bonzini3d0f4412015-03-02 13:26:58 +01001491 qemu_chr_delete(s->chr);
Fabien Chouteaue2af15b2011-01-13 12:46:57 +01001492#endif
Paul Brook0e1c9c52010-06-16 13:03:51 +01001493}
1494
bellard1fddef42005-04-17 19:16:13 +00001495#ifdef CONFIG_USER_ONLY
1496int
Andreas Färberdb6b81d2013-06-27 19:49:31 +02001497gdb_handlesig(CPUState *cpu, int sig)
bellard1fddef42005-04-17 19:16:13 +00001498{
Andreas Färber5ca666c2013-06-24 19:20:57 +02001499 GDBState *s;
1500 char buf[256];
1501 int n;
bellard1fddef42005-04-17 19:16:13 +00001502
Andreas Färber5ca666c2013-06-24 19:20:57 +02001503 s = gdbserver_state;
1504 if (gdbserver_fd < 0 || s->fd < 0) {
1505 return sig;
bellard1fddef42005-04-17 19:16:13 +00001506 }
1507
Andreas Färber5ca666c2013-06-24 19:20:57 +02001508 /* disable single step if it was enabled */
Andreas Färber3825b282013-06-24 18:41:06 +02001509 cpu_single_step(cpu, 0);
Peter Crosthwaitebbd77c12015-06-23 19:31:15 -07001510 tb_flush(cpu);
bellard1fddef42005-04-17 19:16:13 +00001511
Andreas Färber5ca666c2013-06-24 19:20:57 +02001512 if (sig != 0) {
1513 snprintf(buf, sizeof(buf), "S%02x", target_signal_to_gdb(sig));
1514 put_packet(s, buf);
1515 }
1516 /* put_packet() might have detected that the peer terminated the
1517 connection. */
1518 if (s->fd < 0) {
1519 return sig;
1520 }
1521
1522 sig = 0;
1523 s->state = RS_IDLE;
1524 s->running_state = 0;
1525 while (s->running_state == 0) {
1526 n = read(s->fd, buf, 256);
1527 if (n > 0) {
1528 int i;
1529
1530 for (i = 0; i < n; i++) {
1531 gdb_read_byte(s, buf[i]);
1532 }
Peter Wu5819e3e2016-06-05 16:35:48 +02001533 } else {
Andreas Färber5ca666c2013-06-24 19:20:57 +02001534 /* XXX: Connection closed. Should probably wait for another
1535 connection before continuing. */
Peter Wu5819e3e2016-06-05 16:35:48 +02001536 if (n == 0) {
1537 close(s->fd);
1538 }
1539 s->fd = -1;
Andreas Färber5ca666c2013-06-24 19:20:57 +02001540 return sig;
bellard1fddef42005-04-17 19:16:13 +00001541 }
Andreas Färber5ca666c2013-06-24 19:20:57 +02001542 }
1543 sig = s->signal;
1544 s->signal = 0;
1545 return sig;
bellard1fddef42005-04-17 19:16:13 +00001546}
bellarde9009672005-04-26 20:42:36 +00001547
aurel32ca587a82008-12-18 22:44:13 +00001548/* Tell the remote gdb that the process has exited due to SIG. */
Andreas Färber9349b4f2012-03-14 01:38:32 +01001549void gdb_signalled(CPUArchState *env, int sig)
aurel32ca587a82008-12-18 22:44:13 +00001550{
Andreas Färber5ca666c2013-06-24 19:20:57 +02001551 GDBState *s;
1552 char buf[4];
aurel32ca587a82008-12-18 22:44:13 +00001553
Andreas Färber5ca666c2013-06-24 19:20:57 +02001554 s = gdbserver_state;
1555 if (gdbserver_fd < 0 || s->fd < 0) {
1556 return;
1557 }
aurel32ca587a82008-12-18 22:44:13 +00001558
Andreas Färber5ca666c2013-06-24 19:20:57 +02001559 snprintf(buf, sizeof(buf), "X%02x", target_signal_to_gdb(sig));
1560 put_packet(s, buf);
aurel32ca587a82008-12-18 22:44:13 +00001561}
bellard1fddef42005-04-17 19:16:13 +00001562
aliguori880a7572008-11-18 20:30:24 +00001563static void gdb_accept(void)
bellard858693c2004-03-31 18:52:07 +00001564{
1565 GDBState *s;
1566 struct sockaddr_in sockaddr;
1567 socklen_t len;
MORITA Kazutakabf1c8522013-02-22 12:39:50 +09001568 int fd;
bellard858693c2004-03-31 18:52:07 +00001569
1570 for(;;) {
1571 len = sizeof(sockaddr);
1572 fd = accept(gdbserver_fd, (struct sockaddr *)&sockaddr, &len);
1573 if (fd < 0 && errno != EINTR) {
1574 perror("accept");
1575 return;
1576 } else if (fd >= 0) {
Kevin Wolf40ff6d72009-12-02 12:24:42 +01001577#ifndef _WIN32
1578 fcntl(fd, F_SETFD, FD_CLOEXEC);
1579#endif
bellard858693c2004-03-31 18:52:07 +00001580 break;
1581 }
1582 }
1583
1584 /* set short latency */
MORITA Kazutakabf1c8522013-02-22 12:39:50 +09001585 socket_set_nodelay(fd);
ths3b46e622007-09-17 08:09:54 +00001586
Anthony Liguori7267c092011-08-20 22:09:37 -05001587 s = g_malloc0(sizeof(GDBState));
Andreas Färber2e0f2cf2013-06-27 19:19:39 +02001588 s->c_cpu = first_cpu;
1589 s->g_cpu = first_cpu;
bellard858693c2004-03-31 18:52:07 +00001590 s->fd = fd;
Andreas Färber5b50e792013-06-29 04:18:45 +02001591 gdb_has_xml = false;
bellard858693c2004-03-31 18:52:07 +00001592
aliguori880a7572008-11-18 20:30:24 +00001593 gdbserver_state = s;
bellard858693c2004-03-31 18:52:07 +00001594}
1595
1596static int gdbserver_open(int port)
1597{
1598 struct sockaddr_in sockaddr;
Sebastian Ottlik6669ca12013-10-02 12:23:13 +02001599 int fd, ret;
bellard858693c2004-03-31 18:52:07 +00001600
1601 fd = socket(PF_INET, SOCK_STREAM, 0);
1602 if (fd < 0) {
1603 perror("socket");
1604 return -1;
1605 }
Kevin Wolf40ff6d72009-12-02 12:24:42 +01001606#ifndef _WIN32
1607 fcntl(fd, F_SETFD, FD_CLOEXEC);
1608#endif
bellard858693c2004-03-31 18:52:07 +00001609
Sebastian Ottlik6669ca12013-10-02 12:23:13 +02001610 socket_set_fast_reuse(fd);
bellard858693c2004-03-31 18:52:07 +00001611
1612 sockaddr.sin_family = AF_INET;
1613 sockaddr.sin_port = htons(port);
1614 sockaddr.sin_addr.s_addr = 0;
1615 ret = bind(fd, (struct sockaddr *)&sockaddr, sizeof(sockaddr));
1616 if (ret < 0) {
1617 perror("bind");
Peter Maydellbb161722011-12-24 23:37:24 +00001618 close(fd);
bellard858693c2004-03-31 18:52:07 +00001619 return -1;
1620 }
Peter Wu96165b92016-05-04 11:32:17 +02001621 ret = listen(fd, 1);
bellard858693c2004-03-31 18:52:07 +00001622 if (ret < 0) {
1623 perror("listen");
Peter Maydellbb161722011-12-24 23:37:24 +00001624 close(fd);
bellard858693c2004-03-31 18:52:07 +00001625 return -1;
1626 }
bellard858693c2004-03-31 18:52:07 +00001627 return fd;
1628}
1629
1630int gdbserver_start(int port)
1631{
1632 gdbserver_fd = gdbserver_open(port);
1633 if (gdbserver_fd < 0)
1634 return -1;
1635 /* accept connections */
aliguori880a7572008-11-18 20:30:24 +00001636 gdb_accept();
bellardb4608c02003-06-27 17:34:32 +00001637 return 0;
1638}
aurel322b1319c2008-12-18 22:44:04 +00001639
1640/* Disable gdb stub for child processes. */
Peter Crosthwaitef7ec7f72015-06-23 19:31:16 -07001641void gdbserver_fork(CPUState *cpu)
aurel322b1319c2008-12-18 22:44:04 +00001642{
1643 GDBState *s = gdbserver_state;
Andreas Färber75a34032013-09-02 16:57:02 +02001644
1645 if (gdbserver_fd < 0 || s->fd < 0) {
1646 return;
1647 }
aurel322b1319c2008-12-18 22:44:04 +00001648 close(s->fd);
1649 s->fd = -1;
Andreas Färberb3310ab2013-09-02 17:26:20 +02001650 cpu_breakpoint_remove_all(cpu, BP_GDB);
Andreas Färber75a34032013-09-02 16:57:02 +02001651 cpu_watchpoint_remove_all(cpu, BP_GDB);
aurel322b1319c2008-12-18 22:44:04 +00001652}
pbrook4046d912007-01-28 01:53:16 +00001653#else
thsaa1f17c2007-07-11 22:48:58 +00001654static int gdb_chr_can_receive(void *opaque)
pbrook4046d912007-01-28 01:53:16 +00001655{
pbrook56aebc82008-10-11 17:55:29 +00001656 /* We can handle an arbitrarily large amount of data.
1657 Pick the maximum packet size, which is as good as anything. */
1658 return MAX_PACKET_LENGTH;
pbrook4046d912007-01-28 01:53:16 +00001659}
1660
thsaa1f17c2007-07-11 22:48:58 +00001661static void gdb_chr_receive(void *opaque, const uint8_t *buf, int size)
pbrook4046d912007-01-28 01:53:16 +00001662{
pbrook4046d912007-01-28 01:53:16 +00001663 int i;
1664
1665 for (i = 0; i < size; i++) {
aliguori880a7572008-11-18 20:30:24 +00001666 gdb_read_byte(gdbserver_state, buf[i]);
pbrook4046d912007-01-28 01:53:16 +00001667 }
1668}
1669
1670static void gdb_chr_event(void *opaque, int event)
1671{
1672 switch (event) {
Amit Shahb6b8df52009-10-07 18:31:16 +05301673 case CHR_EVENT_OPENED:
Luiz Capitulino0461d5a2011-09-30 14:45:27 -03001674 vm_stop(RUN_STATE_PAUSED);
Andreas Färber5b50e792013-06-29 04:18:45 +02001675 gdb_has_xml = false;
pbrook4046d912007-01-28 01:53:16 +00001676 break;
1677 default:
1678 break;
1679 }
1680}
1681
aliguori8a34a0f2009-03-05 23:01:55 +00001682static void gdb_monitor_output(GDBState *s, const char *msg, int len)
1683{
1684 char buf[MAX_PACKET_LENGTH];
1685
1686 buf[0] = 'O';
1687 if (len > (MAX_PACKET_LENGTH/2) - 1)
1688 len = (MAX_PACKET_LENGTH/2) - 1;
1689 memtohex(buf + 1, (uint8_t *)msg, len);
1690 put_packet(s, buf);
1691}
1692
1693static int gdb_monitor_write(CharDriverState *chr, const uint8_t *buf, int len)
1694{
1695 const char *p = (const char *)buf;
1696 int max_sz;
1697
1698 max_sz = (sizeof(gdbserver_state->last_packet) - 2) / 2;
1699 for (;;) {
1700 if (len <= max_sz) {
1701 gdb_monitor_output(gdbserver_state, p, len);
1702 break;
1703 }
1704 gdb_monitor_output(gdbserver_state, p, max_sz);
1705 p += max_sz;
1706 len -= max_sz;
1707 }
1708 return len;
1709}
1710
aliguori59030a82009-04-05 18:43:41 +00001711#ifndef _WIN32
1712static void gdb_sigterm_handler(int signal)
1713{
Luiz Capitulino13548692011-07-29 15:36:43 -03001714 if (runstate_is_running()) {
Luiz Capitulino0461d5a2011-09-30 14:45:27 -03001715 vm_stop(RUN_STATE_PAUSED);
Jan Kiszkae07bbac2011-02-09 16:29:40 +01001716 }
aliguori59030a82009-04-05 18:43:41 +00001717}
1718#endif
1719
1720int gdbserver_start(const char *device)
pbrook4046d912007-01-28 01:53:16 +00001721{
1722 GDBState *s;
aliguori59030a82009-04-05 18:43:41 +00001723 char gdbstub_device_name[128];
aliguori36556b22009-03-28 18:05:53 +00001724 CharDriverState *chr = NULL;
1725 CharDriverState *mon_chr;
Daniel P. Berranged0d77082016-01-11 12:44:41 +00001726 ChardevCommon common = { 0 };
pbrook4046d912007-01-28 01:53:16 +00001727
aliguori59030a82009-04-05 18:43:41 +00001728 if (!device)
1729 return -1;
1730 if (strcmp(device, "none") != 0) {
1731 if (strstart(device, "tcp:", NULL)) {
1732 /* enforce required TCP attributes */
1733 snprintf(gdbstub_device_name, sizeof(gdbstub_device_name),
1734 "%s,nowait,nodelay,server", device);
1735 device = gdbstub_device_name;
aliguori36556b22009-03-28 18:05:53 +00001736 }
aliguori59030a82009-04-05 18:43:41 +00001737#ifndef _WIN32
1738 else if (strcmp(device, "stdio") == 0) {
1739 struct sigaction act;
pbrookcfc34752007-02-22 01:48:01 +00001740
aliguori59030a82009-04-05 18:43:41 +00001741 memset(&act, 0, sizeof(act));
1742 act.sa_handler = gdb_sigterm_handler;
1743 sigaction(SIGINT, &act, NULL);
1744 }
1745#endif
Pavel Dovgalyuk33577b42016-03-14 10:44:36 +03001746 chr = qemu_chr_new_noreplay("gdb", device, NULL);
aliguori36556b22009-03-28 18:05:53 +00001747 if (!chr)
1748 return -1;
1749
Hans de Goede456d6062013-03-27 20:29:40 +01001750 qemu_chr_fe_claim_no_fail(chr);
aliguori36556b22009-03-28 18:05:53 +00001751 qemu_chr_add_handlers(chr, gdb_chr_can_receive, gdb_chr_receive,
1752 gdb_chr_event, NULL);
pbrookcfc34752007-02-22 01:48:01 +00001753 }
1754
aliguori36556b22009-03-28 18:05:53 +00001755 s = gdbserver_state;
1756 if (!s) {
Anthony Liguori7267c092011-08-20 22:09:37 -05001757 s = g_malloc0(sizeof(GDBState));
aliguori36556b22009-03-28 18:05:53 +00001758 gdbserver_state = s;
pbrook4046d912007-01-28 01:53:16 +00001759
aliguori36556b22009-03-28 18:05:53 +00001760 qemu_add_vm_change_state_handler(gdb_vm_state_change, NULL);
1761
1762 /* Initialize a monitor terminal for gdb */
Daniel P. Berranged0d77082016-01-11 12:44:41 +00001763 mon_chr = qemu_chr_alloc(&common, &error_abort);
aliguori36556b22009-03-28 18:05:53 +00001764 mon_chr->chr_write = gdb_monitor_write;
1765 monitor_init(mon_chr, 0);
1766 } else {
1767 if (s->chr)
Anthony Liguori70f24fb2011-08-15 11:17:38 -05001768 qemu_chr_delete(s->chr);
aliguori36556b22009-03-28 18:05:53 +00001769 mon_chr = s->mon_chr;
1770 memset(s, 0, sizeof(GDBState));
1771 }
Andreas Färber2e0f2cf2013-06-27 19:19:39 +02001772 s->c_cpu = first_cpu;
1773 s->g_cpu = first_cpu;
pbrook4046d912007-01-28 01:53:16 +00001774 s->chr = chr;
aliguori36556b22009-03-28 18:05:53 +00001775 s->state = chr ? RS_IDLE : RS_INACTIVE;
1776 s->mon_chr = mon_chr;
Meador Ingecdb432b2012-03-15 17:49:45 +00001777 s->current_syscall_cb = NULL;
aliguori8a34a0f2009-03-05 23:01:55 +00001778
pbrook4046d912007-01-28 01:53:16 +00001779 return 0;
1780}
1781#endif