]>
Commit | Line | Data |
---|---|---|
b4608c04 FB |
1 | /* |
2 | * gdb server stub | |
5fafdf24 | 3 | * |
3475187d | 4 | * Copyright (c) 2003-2005 Fabrice Bellard |
b4608c04 FB |
5 | * |
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 | |
17 | * License along with this library; if not, write to the Free Software | |
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
19 | */ | |
978efd6a | 20 | #include "config.h" |
1fddef4b FB |
21 | #ifdef CONFIG_USER_ONLY |
22 | #include <stdlib.h> | |
23 | #include <stdio.h> | |
24 | #include <stdarg.h> | |
25 | #include <string.h> | |
26 | #include <errno.h> | |
27 | #include <unistd.h> | |
978efd6a | 28 | #include <fcntl.h> |
1fddef4b FB |
29 | |
30 | #include "qemu.h" | |
31 | #else | |
87ecb68b PB |
32 | #include "qemu-common.h" |
33 | #include "qemu-char.h" | |
34 | #include "sysemu.h" | |
35 | #include "gdbstub.h" | |
1fddef4b | 36 | #endif |
67b915a5 | 37 | |
8f447cc7 FB |
38 | #include "qemu_socket.h" |
39 | #ifdef _WIN32 | |
40 | /* XXX: these constants may be independent of the host ones even for Unix */ | |
41 | #ifndef SIGTRAP | |
42 | #define SIGTRAP 5 | |
43 | #endif | |
44 | #ifndef SIGINT | |
45 | #define SIGINT 2 | |
46 | #endif | |
47 | #else | |
b4608c04 | 48 | #include <signal.h> |
8f447cc7 | 49 | #endif |
b4608c04 | 50 | |
4abe615b | 51 | //#define DEBUG_GDB |
b4608c04 | 52 | |
858693c6 FB |
53 | enum RSState { |
54 | RS_IDLE, | |
55 | RS_GETLINE, | |
56 | RS_CHKSUM1, | |
57 | RS_CHKSUM2, | |
a2d1ebaf | 58 | RS_SYSCALL, |
858693c6 | 59 | }; |
858693c6 | 60 | typedef struct GDBState { |
6a00d601 | 61 | CPUState *env; /* current CPU */ |
41625033 | 62 | enum RSState state; /* parsing state */ |
858693c6 FB |
63 | char line_buf[4096]; |
64 | int line_buf_index; | |
65 | int line_csum; | |
4046d913 PB |
66 | char last_packet[4100]; |
67 | int last_packet_len; | |
41625033 | 68 | #ifdef CONFIG_USER_ONLY |
4046d913 | 69 | int fd; |
41625033 | 70 | int running_state; |
4046d913 PB |
71 | #else |
72 | CharDriverState *chr; | |
41625033 | 73 | #endif |
858693c6 | 74 | } GDBState; |
b4608c04 | 75 | |
1fddef4b | 76 | #ifdef CONFIG_USER_ONLY |
4046d913 PB |
77 | /* XXX: This is not thread safe. Do we care? */ |
78 | static int gdbserver_fd = -1; | |
79 | ||
1fddef4b FB |
80 | /* XXX: remove this hack. */ |
81 | static GDBState gdbserver_state; | |
1fddef4b | 82 | |
858693c6 | 83 | static int get_char(GDBState *s) |
b4608c04 FB |
84 | { |
85 | uint8_t ch; | |
86 | int ret; | |
87 | ||
88 | for(;;) { | |
8f447cc7 | 89 | ret = recv(s->fd, &ch, 1, 0); |
b4608c04 FB |
90 | if (ret < 0) { |
91 | if (errno != EINTR && errno != EAGAIN) | |
92 | return -1; | |
93 | } else if (ret == 0) { | |
94 | return -1; | |
95 | } else { | |
96 | break; | |
97 | } | |
98 | } | |
99 | return ch; | |
100 | } | |
4046d913 | 101 | #endif |
b4608c04 | 102 | |
a2d1ebaf PB |
103 | /* GDB stub state for use by semihosting syscalls. */ |
104 | static GDBState *gdb_syscall_state; | |
105 | static gdb_syscall_complete_cb gdb_current_syscall_cb; | |
106 | ||
107 | enum { | |
108 | GDB_SYS_UNKNOWN, | |
109 | GDB_SYS_ENABLED, | |
110 | GDB_SYS_DISABLED, | |
111 | } gdb_syscall_mode; | |
112 | ||
113 | /* If gdb is connected when the first semihosting syscall occurs then use | |
114 | remote gdb syscalls. Otherwise use native file IO. */ | |
115 | int use_gdb_syscalls(void) | |
116 | { | |
117 | if (gdb_syscall_mode == GDB_SYS_UNKNOWN) { | |
118 | gdb_syscall_mode = (gdb_syscall_state ? GDB_SYS_ENABLED | |
119 | : GDB_SYS_DISABLED); | |
120 | } | |
121 | return gdb_syscall_mode == GDB_SYS_ENABLED; | |
122 | } | |
123 | ||
858693c6 | 124 | static void put_buffer(GDBState *s, const uint8_t *buf, int len) |
b4608c04 | 125 | { |
4046d913 | 126 | #ifdef CONFIG_USER_ONLY |
b4608c04 FB |
127 | int ret; |
128 | ||
129 | while (len > 0) { | |
8f447cc7 | 130 | ret = send(s->fd, buf, len, 0); |
b4608c04 FB |
131 | if (ret < 0) { |
132 | if (errno != EINTR && errno != EAGAIN) | |
133 | return; | |
134 | } else { | |
135 | buf += ret; | |
136 | len -= ret; | |
137 | } | |
138 | } | |
4046d913 PB |
139 | #else |
140 | qemu_chr_write(s->chr, buf, len); | |
141 | #endif | |
b4608c04 FB |
142 | } |
143 | ||
144 | static inline int fromhex(int v) | |
145 | { | |
146 | if (v >= '0' && v <= '9') | |
147 | return v - '0'; | |
148 | else if (v >= 'A' && v <= 'F') | |
149 | return v - 'A' + 10; | |
150 | else if (v >= 'a' && v <= 'f') | |
151 | return v - 'a' + 10; | |
152 | else | |
153 | return 0; | |
154 | } | |
155 | ||
156 | static inline int tohex(int v) | |
157 | { | |
158 | if (v < 10) | |
159 | return v + '0'; | |
160 | else | |
161 | return v - 10 + 'a'; | |
162 | } | |
163 | ||
164 | static void memtohex(char *buf, const uint8_t *mem, int len) | |
165 | { | |
166 | int i, c; | |
167 | char *q; | |
168 | q = buf; | |
169 | for(i = 0; i < len; i++) { | |
170 | c = mem[i]; | |
171 | *q++ = tohex(c >> 4); | |
172 | *q++ = tohex(c & 0xf); | |
173 | } | |
174 | *q = '\0'; | |
175 | } | |
176 | ||
177 | static void hextomem(uint8_t *mem, const char *buf, int len) | |
178 | { | |
179 | int i; | |
180 | ||
181 | for(i = 0; i < len; i++) { | |
182 | mem[i] = (fromhex(buf[0]) << 4) | fromhex(buf[1]); | |
183 | buf += 2; | |
184 | } | |
185 | } | |
186 | ||
b4608c04 | 187 | /* return -1 if error, 0 if OK */ |
858693c6 | 188 | static int put_packet(GDBState *s, char *buf) |
b4608c04 | 189 | { |
4046d913 PB |
190 | int len, csum, i; |
191 | char *p; | |
b4608c04 FB |
192 | |
193 | #ifdef DEBUG_GDB | |
194 | printf("reply='%s'\n", buf); | |
195 | #endif | |
196 | ||
197 | for(;;) { | |
4046d913 PB |
198 | p = s->last_packet; |
199 | *(p++) = '$'; | |
b4608c04 | 200 | len = strlen(buf); |
4046d913 PB |
201 | memcpy(p, buf, len); |
202 | p += len; | |
b4608c04 FB |
203 | csum = 0; |
204 | for(i = 0; i < len; i++) { | |
205 | csum += buf[i]; | |
206 | } | |
4046d913 PB |
207 | *(p++) = '#'; |
208 | *(p++) = tohex((csum >> 4) & 0xf); | |
209 | *(p++) = tohex((csum) & 0xf); | |
b4608c04 | 210 | |
4046d913 PB |
211 | s->last_packet_len = p - s->last_packet; |
212 | put_buffer(s, s->last_packet, s->last_packet_len); | |
b4608c04 | 213 | |
4046d913 PB |
214 | #ifdef CONFIG_USER_ONLY |
215 | i = get_char(s); | |
216 | if (i < 0) | |
b4608c04 | 217 | return -1; |
4046d913 | 218 | if (i == '+') |
b4608c04 | 219 | break; |
4046d913 PB |
220 | #else |
221 | break; | |
222 | #endif | |
b4608c04 FB |
223 | } |
224 | return 0; | |
225 | } | |
226 | ||
6da41eaf FB |
227 | #if defined(TARGET_I386) |
228 | ||
6da41eaf FB |
229 | static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf) |
230 | { | |
231 | int i, fpus; | |
5ad265ee AZ |
232 | uint32_t *registers = (uint32_t *)mem_buf; |
233 | ||
234 | #ifdef TARGET_X86_64 | |
235 | /* This corresponds with amd64_register_info[] in gdb/amd64-tdep.c */ | |
236 | uint64_t *registers64 = (uint64_t *)mem_buf; | |
237 | ||
238 | if (env->hflags & HF_CS64_MASK) { | |
239 | registers64[0] = tswap64(env->regs[R_EAX]); | |
240 | registers64[1] = tswap64(env->regs[R_EBX]); | |
241 | registers64[2] = tswap64(env->regs[R_ECX]); | |
242 | registers64[3] = tswap64(env->regs[R_EDX]); | |
243 | registers64[4] = tswap64(env->regs[R_ESI]); | |
244 | registers64[5] = tswap64(env->regs[R_EDI]); | |
245 | registers64[6] = tswap64(env->regs[R_EBP]); | |
246 | registers64[7] = tswap64(env->regs[R_ESP]); | |
247 | for(i = 8; i < 16; i++) { | |
248 | registers64[i] = tswap64(env->regs[i]); | |
249 | } | |
250 | registers64[16] = tswap64(env->eip); | |
251 | ||
252 | registers = (uint32_t *)®isters64[17]; | |
253 | registers[0] = tswap32(env->eflags); | |
254 | registers[1] = tswap32(env->segs[R_CS].selector); | |
255 | registers[2] = tswap32(env->segs[R_SS].selector); | |
256 | registers[3] = tswap32(env->segs[R_DS].selector); | |
257 | registers[4] = tswap32(env->segs[R_ES].selector); | |
258 | registers[5] = tswap32(env->segs[R_FS].selector); | |
259 | registers[6] = tswap32(env->segs[R_GS].selector); | |
260 | /* XXX: convert floats */ | |
261 | for(i = 0; i < 8; i++) { | |
262 | memcpy(mem_buf + 16 * 8 + 7 * 4 + i * 10, &env->fpregs[i], 10); | |
263 | } | |
264 | registers[27] = tswap32(env->fpuc); /* fctrl */ | |
265 | fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11; | |
266 | registers[28] = tswap32(fpus); /* fstat */ | |
267 | registers[29] = 0; /* ftag */ | |
268 | registers[30] = 0; /* fiseg */ | |
269 | registers[31] = 0; /* fioff */ | |
270 | registers[32] = 0; /* foseg */ | |
271 | registers[33] = 0; /* fooff */ | |
272 | registers[34] = 0; /* fop */ | |
273 | for(i = 0; i < 16; i++) { | |
274 | memcpy(mem_buf + 16 * 8 + 35 * 4 + i * 16, &env->xmm_regs[i], 16); | |
275 | } | |
276 | registers[99] = tswap32(env->mxcsr); | |
277 | ||
278 | return 8 * 17 + 4 * 7 + 10 * 8 + 4 * 8 + 16 * 16 + 4; | |
279 | } | |
280 | #endif | |
6da41eaf FB |
281 | |
282 | for(i = 0; i < 8; i++) { | |
e95c8d51 | 283 | registers[i] = env->regs[i]; |
6da41eaf | 284 | } |
e95c8d51 FB |
285 | registers[8] = env->eip; |
286 | registers[9] = env->eflags; | |
287 | registers[10] = env->segs[R_CS].selector; | |
288 | registers[11] = env->segs[R_SS].selector; | |
289 | registers[12] = env->segs[R_DS].selector; | |
290 | registers[13] = env->segs[R_ES].selector; | |
291 | registers[14] = env->segs[R_FS].selector; | |
292 | registers[15] = env->segs[R_GS].selector; | |
6da41eaf FB |
293 | /* XXX: convert floats */ |
294 | for(i = 0; i < 8; i++) { | |
295 | memcpy(mem_buf + 16 * 4 + i * 10, &env->fpregs[i], 10); | |
296 | } | |
e95c8d51 | 297 | registers[36] = env->fpuc; |
6da41eaf | 298 | fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11; |
e95c8d51 FB |
299 | registers[37] = fpus; |
300 | registers[38] = 0; /* XXX: convert tags */ | |
301 | registers[39] = 0; /* fiseg */ | |
302 | registers[40] = 0; /* fioff */ | |
303 | registers[41] = 0; /* foseg */ | |
304 | registers[42] = 0; /* fooff */ | |
305 | registers[43] = 0; /* fop */ | |
3b46e624 | 306 | |
e95c8d51 FB |
307 | for(i = 0; i < 16; i++) |
308 | tswapls(®isters[i]); | |
309 | for(i = 36; i < 44; i++) | |
310 | tswapls(®isters[i]); | |
6da41eaf FB |
311 | return 44 * 4; |
312 | } | |
313 | ||
314 | static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size) | |
315 | { | |
316 | uint32_t *registers = (uint32_t *)mem_buf; | |
317 | int i; | |
318 | ||
319 | for(i = 0; i < 8; i++) { | |
320 | env->regs[i] = tswapl(registers[i]); | |
321 | } | |
e95c8d51 FB |
322 | env->eip = tswapl(registers[8]); |
323 | env->eflags = tswapl(registers[9]); | |
6da41eaf FB |
324 | #if defined(CONFIG_USER_ONLY) |
325 | #define LOAD_SEG(index, sreg)\ | |
326 | if (tswapl(registers[index]) != env->segs[sreg].selector)\ | |
327 | cpu_x86_load_seg(env, sreg, tswapl(registers[index])); | |
328 | LOAD_SEG(10, R_CS); | |
329 | LOAD_SEG(11, R_SS); | |
330 | LOAD_SEG(12, R_DS); | |
331 | LOAD_SEG(13, R_ES); | |
332 | LOAD_SEG(14, R_FS); | |
333 | LOAD_SEG(15, R_GS); | |
334 | #endif | |
335 | } | |
336 | ||
9e62fd7f | 337 | #elif defined (TARGET_PPC) |
9e62fd7f FB |
338 | static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf) |
339 | { | |
a541f297 | 340 | uint32_t *registers = (uint32_t *)mem_buf, tmp; |
9e62fd7f FB |
341 | int i; |
342 | ||
343 | /* fill in gprs */ | |
a541f297 | 344 | for(i = 0; i < 32; i++) { |
e95c8d51 | 345 | registers[i] = tswapl(env->gpr[i]); |
9e62fd7f FB |
346 | } |
347 | /* fill in fprs */ | |
348 | for (i = 0; i < 32; i++) { | |
e95c8d51 FB |
349 | registers[(i * 2) + 32] = tswapl(*((uint32_t *)&env->fpr[i])); |
350 | registers[(i * 2) + 33] = tswapl(*((uint32_t *)&env->fpr[i] + 1)); | |
9e62fd7f FB |
351 | } |
352 | /* nip, msr, ccr, lnk, ctr, xer, mq */ | |
e95c8d51 | 353 | registers[96] = tswapl(env->nip); |
0411a972 | 354 | registers[97] = tswapl(env->msr); |
9e62fd7f FB |
355 | tmp = 0; |
356 | for (i = 0; i < 8; i++) | |
a541f297 | 357 | tmp |= env->crf[i] << (32 - ((i + 1) * 4)); |
e95c8d51 FB |
358 | registers[98] = tswapl(tmp); |
359 | registers[99] = tswapl(env->lr); | |
360 | registers[100] = tswapl(env->ctr); | |
76a66253 | 361 | registers[101] = tswapl(ppc_load_xer(env)); |
e95c8d51 | 362 | registers[102] = 0; |
a541f297 FB |
363 | |
364 | return 103 * 4; | |
9e62fd7f FB |
365 | } |
366 | ||
367 | static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size) | |
368 | { | |
369 | uint32_t *registers = (uint32_t *)mem_buf; | |
370 | int i; | |
371 | ||
372 | /* fill in gprs */ | |
373 | for (i = 0; i < 32; i++) { | |
e95c8d51 | 374 | env->gpr[i] = tswapl(registers[i]); |
9e62fd7f FB |
375 | } |
376 | /* fill in fprs */ | |
377 | for (i = 0; i < 32; i++) { | |
e95c8d51 FB |
378 | *((uint32_t *)&env->fpr[i]) = tswapl(registers[(i * 2) + 32]); |
379 | *((uint32_t *)&env->fpr[i] + 1) = tswapl(registers[(i * 2) + 33]); | |
9e62fd7f FB |
380 | } |
381 | /* nip, msr, ccr, lnk, ctr, xer, mq */ | |
e95c8d51 | 382 | env->nip = tswapl(registers[96]); |
0411a972 | 383 | ppc_store_msr(env, tswapl(registers[97])); |
e95c8d51 | 384 | registers[98] = tswapl(registers[98]); |
9e62fd7f | 385 | for (i = 0; i < 8; i++) |
a541f297 | 386 | env->crf[i] = (registers[98] >> (32 - ((i + 1) * 4))) & 0xF; |
e95c8d51 FB |
387 | env->lr = tswapl(registers[99]); |
388 | env->ctr = tswapl(registers[100]); | |
76a66253 | 389 | ppc_store_xer(env, tswapl(registers[101])); |
e95c8d51 FB |
390 | } |
391 | #elif defined (TARGET_SPARC) | |
392 | static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf) | |
393 | { | |
3475187d | 394 | target_ulong *registers = (target_ulong *)mem_buf; |
e95c8d51 FB |
395 | int i; |
396 | ||
397 | /* fill in g0..g7 */ | |
48b2c193 | 398 | for(i = 0; i < 8; i++) { |
e95c8d51 FB |
399 | registers[i] = tswapl(env->gregs[i]); |
400 | } | |
401 | /* fill in register window */ | |
402 | for(i = 0; i < 24; i++) { | |
403 | registers[i + 8] = tswapl(env->regwptr[i]); | |
404 | } | |
9d9754a3 | 405 | #ifndef TARGET_SPARC64 |
e95c8d51 FB |
406 | /* fill in fprs */ |
407 | for (i = 0; i < 32; i++) { | |
408 | registers[i + 32] = tswapl(*((uint32_t *)&env->fpr[i])); | |
409 | } | |
410 | /* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */ | |
411 | registers[64] = tswapl(env->y); | |
3475187d FB |
412 | { |
413 | target_ulong tmp; | |
414 | ||
415 | tmp = GET_PSR(env); | |
416 | registers[65] = tswapl(tmp); | |
417 | } | |
e95c8d51 FB |
418 | registers[66] = tswapl(env->wim); |
419 | registers[67] = tswapl(env->tbr); | |
420 | registers[68] = tswapl(env->pc); | |
421 | registers[69] = tswapl(env->npc); | |
422 | registers[70] = tswapl(env->fsr); | |
423 | registers[71] = 0; /* csr */ | |
424 | registers[72] = 0; | |
3475187d FB |
425 | return 73 * sizeof(target_ulong); |
426 | #else | |
9d9754a3 FB |
427 | /* fill in fprs */ |
428 | for (i = 0; i < 64; i += 2) { | |
429 | uint64_t tmp; | |
430 | ||
8979596d BS |
431 | tmp = ((uint64_t)*(uint32_t *)&env->fpr[i]) << 32; |
432 | tmp |= *(uint32_t *)&env->fpr[i + 1]; | |
433 | registers[i / 2 + 32] = tswap64(tmp); | |
3475187d | 434 | } |
9d9754a3 FB |
435 | registers[64] = tswapl(env->pc); |
436 | registers[65] = tswapl(env->npc); | |
17d996e1 BS |
437 | registers[66] = tswapl(((uint64_t)GET_CCR(env) << 32) | |
438 | ((env->asi & 0xff) << 24) | | |
439 | ((env->pstate & 0xfff) << 8) | | |
440 | GET_CWP64(env)); | |
9d9754a3 FB |
441 | registers[67] = tswapl(env->fsr); |
442 | registers[68] = tswapl(env->fprs); | |
443 | registers[69] = tswapl(env->y); | |
444 | return 70 * sizeof(target_ulong); | |
3475187d | 445 | #endif |
e95c8d51 FB |
446 | } |
447 | ||
448 | static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size) | |
449 | { | |
3475187d | 450 | target_ulong *registers = (target_ulong *)mem_buf; |
e95c8d51 FB |
451 | int i; |
452 | ||
453 | /* fill in g0..g7 */ | |
454 | for(i = 0; i < 7; i++) { | |
455 | env->gregs[i] = tswapl(registers[i]); | |
456 | } | |
457 | /* fill in register window */ | |
458 | for(i = 0; i < 24; i++) { | |
3475187d | 459 | env->regwptr[i] = tswapl(registers[i + 8]); |
e95c8d51 | 460 | } |
9d9754a3 | 461 | #ifndef TARGET_SPARC64 |
e95c8d51 FB |
462 | /* fill in fprs */ |
463 | for (i = 0; i < 32; i++) { | |
464 | *((uint32_t *)&env->fpr[i]) = tswapl(registers[i + 32]); | |
465 | } | |
466 | /* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */ | |
467 | env->y = tswapl(registers[64]); | |
e80cfcfc | 468 | PUT_PSR(env, tswapl(registers[65])); |
e95c8d51 FB |
469 | env->wim = tswapl(registers[66]); |
470 | env->tbr = tswapl(registers[67]); | |
471 | env->pc = tswapl(registers[68]); | |
472 | env->npc = tswapl(registers[69]); | |
473 | env->fsr = tswapl(registers[70]); | |
3475187d | 474 | #else |
9d9754a3 | 475 | for (i = 0; i < 64; i += 2) { |
8979596d BS |
476 | uint64_t tmp; |
477 | ||
478 | tmp = tswap64(registers[i / 2 + 32]); | |
479 | *((uint32_t *)&env->fpr[i]) = tmp >> 32; | |
480 | *((uint32_t *)&env->fpr[i + 1]) = tmp & 0xffffffff; | |
3475187d | 481 | } |
9d9754a3 FB |
482 | env->pc = tswapl(registers[64]); |
483 | env->npc = tswapl(registers[65]); | |
17d996e1 BS |
484 | { |
485 | uint64_t tmp = tswapl(registers[66]); | |
486 | ||
487 | PUT_CCR(env, tmp >> 32); | |
488 | env->asi = (tmp >> 24) & 0xff; | |
489 | env->pstate = (tmp >> 8) & 0xfff; | |
490 | PUT_CWP64(env, tmp & 0xff); | |
491 | } | |
9d9754a3 FB |
492 | env->fsr = tswapl(registers[67]); |
493 | env->fprs = tswapl(registers[68]); | |
494 | env->y = tswapl(registers[69]); | |
3475187d | 495 | #endif |
9e62fd7f | 496 | } |
1fddef4b FB |
497 | #elif defined (TARGET_ARM) |
498 | static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf) | |
499 | { | |
500 | int i; | |
501 | uint8_t *ptr; | |
502 | ||
503 | ptr = mem_buf; | |
504 | /* 16 core integer registers (4 bytes each). */ | |
505 | for (i = 0; i < 16; i++) | |
506 | { | |
507 | *(uint32_t *)ptr = tswapl(env->regs[i]); | |
508 | ptr += 4; | |
509 | } | |
510 | /* 8 FPA registers (12 bytes each), FPS (4 bytes). | |
511 | Not yet implemented. */ | |
512 | memset (ptr, 0, 8 * 12 + 4); | |
513 | ptr += 8 * 12 + 4; | |
514 | /* CPSR (4 bytes). */ | |
b5ff1b31 | 515 | *(uint32_t *)ptr = tswapl (cpsr_read(env)); |
1fddef4b FB |
516 | ptr += 4; |
517 | ||
518 | return ptr - mem_buf; | |
519 | } | |
6da41eaf | 520 | |
1fddef4b FB |
521 | static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size) |
522 | { | |
523 | int i; | |
524 | uint8_t *ptr; | |
525 | ||
526 | ptr = mem_buf; | |
527 | /* Core integer registers. */ | |
528 | for (i = 0; i < 16; i++) | |
529 | { | |
530 | env->regs[i] = tswapl(*(uint32_t *)ptr); | |
531 | ptr += 4; | |
532 | } | |
533 | /* Ignore FPA regs and scr. */ | |
534 | ptr += 8 * 12 + 4; | |
b5ff1b31 | 535 | cpsr_write (env, tswapl(*(uint32_t *)ptr), 0xffffffff); |
1fddef4b | 536 | } |
e6e5906b PB |
537 | #elif defined (TARGET_M68K) |
538 | static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf) | |
539 | { | |
540 | int i; | |
541 | uint8_t *ptr; | |
542 | CPU_DoubleU u; | |
543 | ||
544 | ptr = mem_buf; | |
545 | /* D0-D7 */ | |
546 | for (i = 0; i < 8; i++) { | |
547 | *(uint32_t *)ptr = tswapl(env->dregs[i]); | |
548 | ptr += 4; | |
549 | } | |
550 | /* A0-A7 */ | |
551 | for (i = 0; i < 8; i++) { | |
552 | *(uint32_t *)ptr = tswapl(env->aregs[i]); | |
553 | ptr += 4; | |
554 | } | |
555 | *(uint32_t *)ptr = tswapl(env->sr); | |
556 | ptr += 4; | |
557 | *(uint32_t *)ptr = tswapl(env->pc); | |
558 | ptr += 4; | |
559 | /* F0-F7. The 68881/68040 have 12-bit extended precision registers. | |
560 | ColdFire has 8-bit double precision registers. */ | |
561 | for (i = 0; i < 8; i++) { | |
562 | u.d = env->fregs[i]; | |
563 | *(uint32_t *)ptr = tswap32(u.l.upper); | |
564 | *(uint32_t *)ptr = tswap32(u.l.lower); | |
565 | } | |
566 | /* FP control regs (not implemented). */ | |
567 | memset (ptr, 0, 3 * 4); | |
568 | ptr += 3 * 4; | |
569 | ||
570 | return ptr - mem_buf; | |
571 | } | |
572 | ||
573 | static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size) | |
574 | { | |
575 | int i; | |
576 | uint8_t *ptr; | |
577 | CPU_DoubleU u; | |
578 | ||
579 | ptr = mem_buf; | |
580 | /* D0-D7 */ | |
581 | for (i = 0; i < 8; i++) { | |
582 | env->dregs[i] = tswapl(*(uint32_t *)ptr); | |
583 | ptr += 4; | |
584 | } | |
585 | /* A0-A7 */ | |
586 | for (i = 0; i < 8; i++) { | |
587 | env->aregs[i] = tswapl(*(uint32_t *)ptr); | |
588 | ptr += 4; | |
589 | } | |
590 | env->sr = tswapl(*(uint32_t *)ptr); | |
591 | ptr += 4; | |
592 | env->pc = tswapl(*(uint32_t *)ptr); | |
593 | ptr += 4; | |
594 | /* F0-F7. The 68881/68040 have 12-bit extended precision registers. | |
595 | ColdFire has 8-bit double precision registers. */ | |
596 | for (i = 0; i < 8; i++) { | |
5fafdf24 | 597 | u.l.upper = tswap32(*(uint32_t *)ptr); |
e6e5906b PB |
598 | u.l.lower = tswap32(*(uint32_t *)ptr); |
599 | env->fregs[i] = u.d; | |
600 | } | |
601 | /* FP control regs (not implemented). */ | |
602 | ptr += 3 * 4; | |
603 | } | |
6f970bd9 FB |
604 | #elif defined (TARGET_MIPS) |
605 | static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf) | |
606 | { | |
607 | int i; | |
608 | uint8_t *ptr; | |
609 | ||
610 | ptr = mem_buf; | |
611 | for (i = 0; i < 32; i++) | |
612 | { | |
ead9360e | 613 | *(target_ulong *)ptr = tswapl(env->gpr[i][env->current_tc]); |
2052caa7 | 614 | ptr += sizeof(target_ulong); |
6f970bd9 FB |
615 | } |
616 | ||
7ac256b8 | 617 | *(target_ulong *)ptr = (int32_t)tswap32(env->CP0_Status); |
2052caa7 | 618 | ptr += sizeof(target_ulong); |
6f970bd9 | 619 | |
ead9360e | 620 | *(target_ulong *)ptr = tswapl(env->LO[0][env->current_tc]); |
2052caa7 | 621 | ptr += sizeof(target_ulong); |
6f970bd9 | 622 | |
ead9360e | 623 | *(target_ulong *)ptr = tswapl(env->HI[0][env->current_tc]); |
2052caa7 | 624 | ptr += sizeof(target_ulong); |
6f970bd9 | 625 | |
2052caa7 TS |
626 | *(target_ulong *)ptr = tswapl(env->CP0_BadVAddr); |
627 | ptr += sizeof(target_ulong); | |
6f970bd9 | 628 | |
7ac256b8 | 629 | *(target_ulong *)ptr = (int32_t)tswap32(env->CP0_Cause); |
2052caa7 | 630 | ptr += sizeof(target_ulong); |
6f970bd9 | 631 | |
ead9360e | 632 | *(target_ulong *)ptr = tswapl(env->PC[env->current_tc]); |
2052caa7 | 633 | ptr += sizeof(target_ulong); |
6f970bd9 | 634 | |
36d23958 | 635 | if (env->CP0_Config1 & (1 << CP0C1_FP)) |
8e33c08c | 636 | { |
36d23958 TS |
637 | for (i = 0; i < 32; i++) |
638 | { | |
7ac256b8 TS |
639 | if (env->CP0_Status & (1 << CP0St_FR)) |
640 | *(target_ulong *)ptr = tswapl(env->fpu->fpr[i].d); | |
641 | else | |
642 | *(target_ulong *)ptr = tswap32(env->fpu->fpr[i].w[FP_ENDIAN_IDX]); | |
2052caa7 | 643 | ptr += sizeof(target_ulong); |
36d23958 | 644 | } |
8e33c08c | 645 | |
7ac256b8 | 646 | *(target_ulong *)ptr = (int32_t)tswap32(env->fpu->fcr31); |
2052caa7 | 647 | ptr += sizeof(target_ulong); |
8e33c08c | 648 | |
7ac256b8 | 649 | *(target_ulong *)ptr = (int32_t)tswap32(env->fpu->fcr0); |
2052caa7 | 650 | ptr += sizeof(target_ulong); |
36d23958 | 651 | } |
8e33c08c | 652 | |
7ac256b8 TS |
653 | /* "fp", pseudo frame pointer. Not yet implemented in gdb. */ |
654 | *(target_ulong *)ptr = 0; | |
655 | ptr += sizeof(target_ulong); | |
656 | ||
657 | /* Registers for embedded use, we just pad them. */ | |
658 | for (i = 0; i < 16; i++) | |
659 | { | |
660 | *(target_ulong *)ptr = 0; | |
661 | ptr += sizeof(target_ulong); | |
662 | } | |
663 | ||
664 | /* Processor ID. */ | |
665 | *(target_ulong *)ptr = (int32_t)tswap32(env->CP0_PRid); | |
666 | ptr += sizeof(target_ulong); | |
6f970bd9 FB |
667 | |
668 | return ptr - mem_buf; | |
669 | } | |
670 | ||
8e33c08c TS |
671 | /* convert MIPS rounding mode in FCR31 to IEEE library */ |
672 | static unsigned int ieee_rm[] = | |
673 | { | |
674 | float_round_nearest_even, | |
675 | float_round_to_zero, | |
676 | float_round_up, | |
677 | float_round_down | |
678 | }; | |
679 | #define RESTORE_ROUNDING_MODE \ | |
ead9360e | 680 | set_float_rounding_mode(ieee_rm[env->fpu->fcr31 & 3], &env->fpu->fp_status) |
8e33c08c | 681 | |
6f970bd9 FB |
682 | static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size) |
683 | { | |
684 | int i; | |
685 | uint8_t *ptr; | |
686 | ||
687 | ptr = mem_buf; | |
688 | for (i = 0; i < 32; i++) | |
689 | { | |
ead9360e | 690 | env->gpr[i][env->current_tc] = tswapl(*(target_ulong *)ptr); |
2052caa7 | 691 | ptr += sizeof(target_ulong); |
6f970bd9 FB |
692 | } |
693 | ||
2052caa7 TS |
694 | env->CP0_Status = tswapl(*(target_ulong *)ptr); |
695 | ptr += sizeof(target_ulong); | |
6f970bd9 | 696 | |
ead9360e | 697 | env->LO[0][env->current_tc] = tswapl(*(target_ulong *)ptr); |
2052caa7 | 698 | ptr += sizeof(target_ulong); |
6f970bd9 | 699 | |
ead9360e | 700 | env->HI[0][env->current_tc] = tswapl(*(target_ulong *)ptr); |
2052caa7 | 701 | ptr += sizeof(target_ulong); |
6f970bd9 | 702 | |
2052caa7 TS |
703 | env->CP0_BadVAddr = tswapl(*(target_ulong *)ptr); |
704 | ptr += sizeof(target_ulong); | |
6f970bd9 | 705 | |
2052caa7 TS |
706 | env->CP0_Cause = tswapl(*(target_ulong *)ptr); |
707 | ptr += sizeof(target_ulong); | |
6f970bd9 | 708 | |
ead9360e | 709 | env->PC[env->current_tc] = tswapl(*(target_ulong *)ptr); |
2052caa7 | 710 | ptr += sizeof(target_ulong); |
8e33c08c | 711 | |
36d23958 | 712 | if (env->CP0_Config1 & (1 << CP0C1_FP)) |
8e33c08c | 713 | { |
36d23958 TS |
714 | for (i = 0; i < 32; i++) |
715 | { | |
7ac256b8 TS |
716 | if (env->CP0_Status & (1 << CP0St_FR)) |
717 | env->fpu->fpr[i].d = tswapl(*(target_ulong *)ptr); | |
718 | else | |
719 | env->fpu->fpr[i].w[FP_ENDIAN_IDX] = tswapl(*(target_ulong *)ptr); | |
2052caa7 | 720 | ptr += sizeof(target_ulong); |
36d23958 | 721 | } |
8e33c08c | 722 | |
7ac256b8 | 723 | env->fpu->fcr31 = tswapl(*(target_ulong *)ptr) & 0xFF83FFFF; |
2052caa7 | 724 | ptr += sizeof(target_ulong); |
8e33c08c | 725 | |
7ac256b8 | 726 | /* The remaining registers are assumed to be read-only. */ |
8e33c08c | 727 | |
36d23958 TS |
728 | /* set rounding mode */ |
729 | RESTORE_ROUNDING_MODE; | |
8e33c08c TS |
730 | |
731 | #ifndef CONFIG_SOFTFLOAT | |
36d23958 TS |
732 | /* no floating point exception for native float */ |
733 | SET_FP_ENABLE(env->fcr31, 0); | |
8e33c08c | 734 | #endif |
36d23958 | 735 | } |
6f970bd9 | 736 | } |
fdf9b3e8 | 737 | #elif defined (TARGET_SH4) |
6ef99fc5 TS |
738 | |
739 | /* Hint: Use "set architecture sh4" in GDB to see fpu registers */ | |
740 | ||
fdf9b3e8 FB |
741 | static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf) |
742 | { | |
743 | uint32_t *ptr = (uint32_t *)mem_buf; | |
744 | int i; | |
745 | ||
746 | #define SAVE(x) *ptr++=tswapl(x) | |
9c2a9ea1 PB |
747 | if ((env->sr & (SR_MD | SR_RB)) == (SR_MD | SR_RB)) { |
748 | for (i = 0; i < 8; i++) SAVE(env->gregs[i + 16]); | |
749 | } else { | |
750 | for (i = 0; i < 8; i++) SAVE(env->gregs[i]); | |
751 | } | |
752 | for (i = 8; i < 16; i++) SAVE(env->gregs[i]); | |
fdf9b3e8 FB |
753 | SAVE (env->pc); |
754 | SAVE (env->pr); | |
755 | SAVE (env->gbr); | |
756 | SAVE (env->vbr); | |
757 | SAVE (env->mach); | |
758 | SAVE (env->macl); | |
759 | SAVE (env->sr); | |
6ef99fc5 TS |
760 | SAVE (env->fpul); |
761 | SAVE (env->fpscr); | |
762 | for (i = 0; i < 16; i++) | |
763 | SAVE(env->fregs[i + ((env->fpscr & FPSCR_FR) ? 16 : 0)]); | |
764 | SAVE (env->ssr); | |
765 | SAVE (env->spc); | |
766 | for (i = 0; i < 8; i++) SAVE(env->gregs[i]); | |
767 | for (i = 0; i < 8; i++) SAVE(env->gregs[i + 16]); | |
fdf9b3e8 FB |
768 | return ((uint8_t *)ptr - mem_buf); |
769 | } | |
770 | ||
771 | static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size) | |
772 | { | |
773 | uint32_t *ptr = (uint32_t *)mem_buf; | |
774 | int i; | |
775 | ||
776 | #define LOAD(x) (x)=*ptr++; | |
9c2a9ea1 PB |
777 | if ((env->sr & (SR_MD | SR_RB)) == (SR_MD | SR_RB)) { |
778 | for (i = 0; i < 8; i++) LOAD(env->gregs[i + 16]); | |
779 | } else { | |
780 | for (i = 0; i < 8; i++) LOAD(env->gregs[i]); | |
781 | } | |
782 | for (i = 8; i < 16; i++) LOAD(env->gregs[i]); | |
fdf9b3e8 FB |
783 | LOAD (env->pc); |
784 | LOAD (env->pr); | |
785 | LOAD (env->gbr); | |
786 | LOAD (env->vbr); | |
787 | LOAD (env->mach); | |
788 | LOAD (env->macl); | |
789 | LOAD (env->sr); | |
6ef99fc5 TS |
790 | LOAD (env->fpul); |
791 | LOAD (env->fpscr); | |
792 | for (i = 0; i < 16; i++) | |
793 | LOAD(env->fregs[i + ((env->fpscr & FPSCR_FR) ? 16 : 0)]); | |
794 | LOAD (env->ssr); | |
795 | LOAD (env->spc); | |
796 | for (i = 0; i < 8; i++) LOAD(env->gregs[i]); | |
797 | for (i = 0; i < 8; i++) LOAD(env->gregs[i + 16]); | |
fdf9b3e8 | 798 | } |
f1ccf904 TS |
799 | #elif defined (TARGET_CRIS) |
800 | ||
801 | static int cris_save_32 (unsigned char *d, uint32_t value) | |
802 | { | |
803 | *d++ = (value); | |
804 | *d++ = (value >>= 8); | |
805 | *d++ = (value >>= 8); | |
806 | *d++ = (value >>= 8); | |
807 | return 4; | |
808 | } | |
809 | static int cris_save_16 (unsigned char *d, uint32_t value) | |
810 | { | |
811 | *d++ = (value); | |
812 | *d++ = (value >>= 8); | |
813 | return 2; | |
814 | } | |
815 | static int cris_save_8 (unsigned char *d, uint32_t value) | |
816 | { | |
817 | *d++ = (value); | |
818 | return 1; | |
819 | } | |
820 | ||
821 | /* FIXME: this will bug on archs not supporting unaligned word accesses. */ | |
822 | static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf) | |
823 | { | |
824 | uint8_t *ptr = mem_buf; | |
825 | uint8_t srs; | |
826 | int i; | |
827 | ||
828 | for (i = 0; i < 16; i++) | |
829 | ptr += cris_save_32 (ptr, env->regs[i]); | |
830 | ||
831 | srs = env->pregs[SR_SRS]; | |
832 | ||
833 | ptr += cris_save_8 (ptr, env->pregs[0]); | |
834 | ptr += cris_save_8 (ptr, env->pregs[1]); | |
835 | ptr += cris_save_32 (ptr, env->pregs[2]); | |
836 | ptr += cris_save_8 (ptr, srs); | |
837 | ptr += cris_save_16 (ptr, env->pregs[4]); | |
838 | ||
839 | for (i = 5; i < 16; i++) | |
840 | ptr += cris_save_32 (ptr, env->pregs[i]); | |
841 | ||
842 | ptr += cris_save_32 (ptr, env->pc); | |
843 | ||
844 | for (i = 0; i < 16; i++) | |
845 | ptr += cris_save_32 (ptr, env->sregs[srs][i]); | |
846 | ||
847 | return ((uint8_t *)ptr - mem_buf); | |
848 | } | |
849 | ||
850 | static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size) | |
851 | { | |
852 | uint32_t *ptr = (uint32_t *)mem_buf; | |
853 | int i; | |
854 | ||
855 | #define LOAD(x) (x)=*ptr++; | |
856 | for (i = 0; i < 16; i++) LOAD(env->regs[i]); | |
857 | LOAD (env->pc); | |
858 | } | |
1fddef4b | 859 | #else |
6da41eaf FB |
860 | static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf) |
861 | { | |
862 | return 0; | |
863 | } | |
864 | ||
865 | static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size) | |
866 | { | |
867 | } | |
868 | ||
869 | #endif | |
b4608c04 | 870 | |
1fddef4b | 871 | static int gdb_handle_packet(GDBState *s, CPUState *env, const char *line_buf) |
b4608c04 | 872 | { |
b4608c04 | 873 | const char *p; |
858693c6 | 874 | int ch, reg_size, type; |
b4608c04 | 875 | char buf[4096]; |
f1ccf904 | 876 | uint8_t mem_buf[4096]; |
b4608c04 | 877 | uint32_t *registers; |
9d9754a3 | 878 | target_ulong addr, len; |
3b46e624 | 879 | |
858693c6 FB |
880 | #ifdef DEBUG_GDB |
881 | printf("command='%s'\n", line_buf); | |
882 | #endif | |
883 | p = line_buf; | |
884 | ch = *p++; | |
885 | switch(ch) { | |
886 | case '?': | |
1fddef4b | 887 | /* TODO: Make this return the correct value for user-mode. */ |
858693c6 FB |
888 | snprintf(buf, sizeof(buf), "S%02x", SIGTRAP); |
889 | put_packet(s, buf); | |
890 | break; | |
891 | case 'c': | |
892 | if (*p != '\0') { | |
9d9754a3 | 893 | addr = strtoull(p, (char **)&p, 16); |
4c3a88a2 | 894 | #if defined(TARGET_I386) |
858693c6 | 895 | env->eip = addr; |
5be1a8e0 | 896 | #elif defined (TARGET_PPC) |
858693c6 | 897 | env->nip = addr; |
8d5f07fa FB |
898 | #elif defined (TARGET_SPARC) |
899 | env->pc = addr; | |
900 | env->npc = addr + 4; | |
b5ff1b31 FB |
901 | #elif defined (TARGET_ARM) |
902 | env->regs[15] = addr; | |
fdf9b3e8 | 903 | #elif defined (TARGET_SH4) |
8fac5803 TS |
904 | env->pc = addr; |
905 | #elif defined (TARGET_MIPS) | |
ead9360e | 906 | env->PC[env->current_tc] = addr; |
f1ccf904 TS |
907 | #elif defined (TARGET_CRIS) |
908 | env->pc = addr; | |
4c3a88a2 | 909 | #endif |
858693c6 | 910 | } |
41625033 FB |
911 | #ifdef CONFIG_USER_ONLY |
912 | s->running_state = 1; | |
913 | #else | |
914 | vm_start(); | |
915 | #endif | |
916 | return RS_IDLE; | |
858693c6 FB |
917 | case 's': |
918 | if (*p != '\0') { | |
8fac5803 | 919 | addr = strtoull(p, (char **)&p, 16); |
c33a346e | 920 | #if defined(TARGET_I386) |
858693c6 | 921 | env->eip = addr; |
5be1a8e0 | 922 | #elif defined (TARGET_PPC) |
858693c6 | 923 | env->nip = addr; |
8d5f07fa FB |
924 | #elif defined (TARGET_SPARC) |
925 | env->pc = addr; | |
926 | env->npc = addr + 4; | |
b5ff1b31 FB |
927 | #elif defined (TARGET_ARM) |
928 | env->regs[15] = addr; | |
fdf9b3e8 | 929 | #elif defined (TARGET_SH4) |
8fac5803 TS |
930 | env->pc = addr; |
931 | #elif defined (TARGET_MIPS) | |
ead9360e | 932 | env->PC[env->current_tc] = addr; |
f1ccf904 TS |
933 | #elif defined (TARGET_CRIS) |
934 | env->pc = addr; | |
c33a346e | 935 | #endif |
858693c6 FB |
936 | } |
937 | cpu_single_step(env, 1); | |
41625033 FB |
938 | #ifdef CONFIG_USER_ONLY |
939 | s->running_state = 1; | |
940 | #else | |
941 | vm_start(); | |
942 | #endif | |
943 | return RS_IDLE; | |
a2d1ebaf PB |
944 | case 'F': |
945 | { | |
946 | target_ulong ret; | |
947 | target_ulong err; | |
948 | ||
949 | ret = strtoull(p, (char **)&p, 16); | |
950 | if (*p == ',') { | |
951 | p++; | |
952 | err = strtoull(p, (char **)&p, 16); | |
953 | } else { | |
954 | err = 0; | |
955 | } | |
956 | if (*p == ',') | |
957 | p++; | |
958 | type = *p; | |
959 | if (gdb_current_syscall_cb) | |
960 | gdb_current_syscall_cb(s->env, ret, err); | |
961 | if (type == 'C') { | |
962 | put_packet(s, "T02"); | |
963 | } else { | |
964 | #ifdef CONFIG_USER_ONLY | |
965 | s->running_state = 1; | |
966 | #else | |
967 | vm_start(); | |
968 | #endif | |
969 | } | |
970 | } | |
971 | break; | |
858693c6 FB |
972 | case 'g': |
973 | reg_size = cpu_gdb_read_registers(env, mem_buf); | |
974 | memtohex(buf, mem_buf, reg_size); | |
975 | put_packet(s, buf); | |
976 | break; | |
977 | case 'G': | |
978 | registers = (void *)mem_buf; | |
979 | len = strlen(p) / 2; | |
980 | hextomem((uint8_t *)registers, p, len); | |
981 | cpu_gdb_write_registers(env, mem_buf, len); | |
982 | put_packet(s, "OK"); | |
983 | break; | |
984 | case 'm': | |
9d9754a3 | 985 | addr = strtoull(p, (char **)&p, 16); |
858693c6 FB |
986 | if (*p == ',') |
987 | p++; | |
9d9754a3 | 988 | len = strtoull(p, NULL, 16); |
6f970bd9 FB |
989 | if (cpu_memory_rw_debug(env, addr, mem_buf, len, 0) != 0) { |
990 | put_packet (s, "E14"); | |
991 | } else { | |
992 | memtohex(buf, mem_buf, len); | |
993 | put_packet(s, buf); | |
994 | } | |
858693c6 FB |
995 | break; |
996 | case 'M': | |
9d9754a3 | 997 | addr = strtoull(p, (char **)&p, 16); |
858693c6 FB |
998 | if (*p == ',') |
999 | p++; | |
9d9754a3 | 1000 | len = strtoull(p, (char **)&p, 16); |
b328f873 | 1001 | if (*p == ':') |
858693c6 FB |
1002 | p++; |
1003 | hextomem(mem_buf, p, len); | |
1004 | if (cpu_memory_rw_debug(env, addr, mem_buf, len, 1) != 0) | |
905f20b1 | 1005 | put_packet(s, "E14"); |
858693c6 FB |
1006 | else |
1007 | put_packet(s, "OK"); | |
1008 | break; | |
1009 | case 'Z': | |
1010 | type = strtoul(p, (char **)&p, 16); | |
1011 | if (*p == ',') | |
1012 | p++; | |
9d9754a3 | 1013 | addr = strtoull(p, (char **)&p, 16); |
858693c6 FB |
1014 | if (*p == ',') |
1015 | p++; | |
9d9754a3 | 1016 | len = strtoull(p, (char **)&p, 16); |
858693c6 FB |
1017 | if (type == 0 || type == 1) { |
1018 | if (cpu_breakpoint_insert(env, addr) < 0) | |
1019 | goto breakpoint_error; | |
1020 | put_packet(s, "OK"); | |
6658ffb8 PB |
1021 | #ifndef CONFIG_USER_ONLY |
1022 | } else if (type == 2) { | |
1023 | if (cpu_watchpoint_insert(env, addr) < 0) | |
1024 | goto breakpoint_error; | |
1025 | put_packet(s, "OK"); | |
1026 | #endif | |
858693c6 FB |
1027 | } else { |
1028 | breakpoint_error: | |
905f20b1 | 1029 | put_packet(s, "E22"); |
858693c6 FB |
1030 | } |
1031 | break; | |
1032 | case 'z': | |
1033 | type = strtoul(p, (char **)&p, 16); | |
1034 | if (*p == ',') | |
1035 | p++; | |
9d9754a3 | 1036 | addr = strtoull(p, (char **)&p, 16); |
858693c6 FB |
1037 | if (*p == ',') |
1038 | p++; | |
9d9754a3 | 1039 | len = strtoull(p, (char **)&p, 16); |
858693c6 FB |
1040 | if (type == 0 || type == 1) { |
1041 | cpu_breakpoint_remove(env, addr); | |
1042 | put_packet(s, "OK"); | |
6658ffb8 PB |
1043 | #ifndef CONFIG_USER_ONLY |
1044 | } else if (type == 2) { | |
1045 | cpu_watchpoint_remove(env, addr); | |
1046 | put_packet(s, "OK"); | |
1047 | #endif | |
858693c6 FB |
1048 | } else { |
1049 | goto breakpoint_error; | |
1050 | } | |
1051 | break; | |
831b7825 | 1052 | #ifdef CONFIG_LINUX_USER |
978efd6a PB |
1053 | case 'q': |
1054 | if (strncmp(p, "Offsets", 7) == 0) { | |
1055 | TaskState *ts = env->opaque; | |
1056 | ||
fe834d04 | 1057 | sprintf(buf, |
cd041681 PB |
1058 | "Text=" TARGET_ABI_FMT_lx ";Data=" TARGET_ABI_FMT_lx |
1059 | ";Bss=" TARGET_ABI_FMT_lx, | |
fe834d04 TS |
1060 | ts->info->code_offset, |
1061 | ts->info->data_offset, | |
1062 | ts->info->data_offset); | |
978efd6a PB |
1063 | put_packet(s, buf); |
1064 | break; | |
1065 | } | |
1066 | /* Fall through. */ | |
1067 | #endif | |
858693c6 FB |
1068 | default: |
1069 | // unknown_command: | |
1070 | /* put empty packet */ | |
1071 | buf[0] = '\0'; | |
1072 | put_packet(s, buf); | |
1073 | break; | |
1074 | } | |
1075 | return RS_IDLE; | |
1076 | } | |
1077 | ||
612458f5 FB |
1078 | extern void tb_flush(CPUState *env); |
1079 | ||
1fddef4b | 1080 | #ifndef CONFIG_USER_ONLY |
858693c6 FB |
1081 | static void gdb_vm_stopped(void *opaque, int reason) |
1082 | { | |
1083 | GDBState *s = opaque; | |
1084 | char buf[256]; | |
1085 | int ret; | |
1086 | ||
a2d1ebaf PB |
1087 | if (s->state == RS_SYSCALL) |
1088 | return; | |
1089 | ||
858693c6 | 1090 | /* disable single step if it was enable */ |
6a00d601 | 1091 | cpu_single_step(s->env, 0); |
858693c6 | 1092 | |
e80cfcfc | 1093 | if (reason == EXCP_DEBUG) { |
6658ffb8 | 1094 | if (s->env->watchpoint_hit) { |
aa6290b7 PB |
1095 | snprintf(buf, sizeof(buf), "T%02xwatch:" TARGET_FMT_lx ";", |
1096 | SIGTRAP, | |
6658ffb8 PB |
1097 | s->env->watchpoint[s->env->watchpoint_hit - 1].vaddr); |
1098 | put_packet(s, buf); | |
1099 | s->env->watchpoint_hit = 0; | |
1100 | return; | |
1101 | } | |
6a00d601 | 1102 | tb_flush(s->env); |
858693c6 | 1103 | ret = SIGTRAP; |
bbeb7b5c FB |
1104 | } else if (reason == EXCP_INTERRUPT) { |
1105 | ret = SIGINT; | |
1106 | } else { | |
858693c6 | 1107 | ret = 0; |
bbeb7b5c | 1108 | } |
858693c6 FB |
1109 | snprintf(buf, sizeof(buf), "S%02x", ret); |
1110 | put_packet(s, buf); | |
1111 | } | |
1fddef4b | 1112 | #endif |
858693c6 | 1113 | |
a2d1ebaf PB |
1114 | /* Send a gdb syscall request. |
1115 | This accepts limited printf-style format specifiers, specifically: | |
a87295e8 PB |
1116 | %x - target_ulong argument printed in hex. |
1117 | %lx - 64-bit argument printed in hex. | |
1118 | %s - string pointer (target_ulong) and length (int) pair. */ | |
a2d1ebaf PB |
1119 | void gdb_do_syscall(gdb_syscall_complete_cb cb, char *fmt, ...) |
1120 | { | |
1121 | va_list va; | |
1122 | char buf[256]; | |
1123 | char *p; | |
1124 | target_ulong addr; | |
a87295e8 | 1125 | uint64_t i64; |
a2d1ebaf PB |
1126 | GDBState *s; |
1127 | ||
1128 | s = gdb_syscall_state; | |
1129 | if (!s) | |
1130 | return; | |
1131 | gdb_current_syscall_cb = cb; | |
1132 | s->state = RS_SYSCALL; | |
1133 | #ifndef CONFIG_USER_ONLY | |
1134 | vm_stop(EXCP_DEBUG); | |
1135 | #endif | |
1136 | s->state = RS_IDLE; | |
1137 | va_start(va, fmt); | |
1138 | p = buf; | |
1139 | *(p++) = 'F'; | |
1140 | while (*fmt) { | |
1141 | if (*fmt == '%') { | |
1142 | fmt++; | |
1143 | switch (*fmt++) { | |
1144 | case 'x': | |
1145 | addr = va_arg(va, target_ulong); | |
1146 | p += sprintf(p, TARGET_FMT_lx, addr); | |
1147 | break; | |
a87295e8 PB |
1148 | case 'l': |
1149 | if (*(fmt++) != 'x') | |
1150 | goto bad_format; | |
1151 | i64 = va_arg(va, uint64_t); | |
1152 | p += sprintf(p, "%" PRIx64, i64); | |
1153 | break; | |
a2d1ebaf PB |
1154 | case 's': |
1155 | addr = va_arg(va, target_ulong); | |
1156 | p += sprintf(p, TARGET_FMT_lx "/%x", addr, va_arg(va, int)); | |
1157 | break; | |
1158 | default: | |
a87295e8 | 1159 | bad_format: |
a2d1ebaf PB |
1160 | fprintf(stderr, "gdbstub: Bad syscall format string '%s'\n", |
1161 | fmt - 1); | |
1162 | break; | |
1163 | } | |
1164 | } else { | |
1165 | *(p++) = *(fmt++); | |
1166 | } | |
1167 | } | |
8a93e02a | 1168 | *p = 0; |
a2d1ebaf PB |
1169 | va_end(va); |
1170 | put_packet(s, buf); | |
1171 | #ifdef CONFIG_USER_ONLY | |
1172 | gdb_handlesig(s->env, 0); | |
1173 | #else | |
1174 | cpu_interrupt(s->env, CPU_INTERRUPT_EXIT); | |
1175 | #endif | |
1176 | } | |
1177 | ||
6a00d601 | 1178 | static void gdb_read_byte(GDBState *s, int ch) |
858693c6 | 1179 | { |
6a00d601 | 1180 | CPUState *env = s->env; |
858693c6 FB |
1181 | int i, csum; |
1182 | char reply[1]; | |
1183 | ||
1fddef4b | 1184 | #ifndef CONFIG_USER_ONLY |
4046d913 PB |
1185 | if (s->last_packet_len) { |
1186 | /* Waiting for a response to the last packet. If we see the start | |
1187 | of a new command then abandon the previous response. */ | |
1188 | if (ch == '-') { | |
1189 | #ifdef DEBUG_GDB | |
1190 | printf("Got NACK, retransmitting\n"); | |
1191 | #endif | |
1192 | put_buffer(s, s->last_packet, s->last_packet_len); | |
1193 | } | |
1194 | #ifdef DEBUG_GDB | |
1195 | else if (ch == '+') | |
1196 | printf("Got ACK\n"); | |
1197 | else | |
1198 | printf("Got '%c' when expecting ACK/NACK\n", ch); | |
1199 | #endif | |
1200 | if (ch == '+' || ch == '$') | |
1201 | s->last_packet_len = 0; | |
1202 | if (ch != '$') | |
1203 | return; | |
1204 | } | |
858693c6 FB |
1205 | if (vm_running) { |
1206 | /* when the CPU is running, we cannot do anything except stop | |
1207 | it when receiving a char */ | |
1208 | vm_stop(EXCP_INTERRUPT); | |
5fafdf24 | 1209 | } else |
1fddef4b | 1210 | #endif |
41625033 | 1211 | { |
858693c6 FB |
1212 | switch(s->state) { |
1213 | case RS_IDLE: | |
1214 | if (ch == '$') { | |
1215 | s->line_buf_index = 0; | |
1216 | s->state = RS_GETLINE; | |
c33a346e | 1217 | } |
b4608c04 | 1218 | break; |
858693c6 FB |
1219 | case RS_GETLINE: |
1220 | if (ch == '#') { | |
1221 | s->state = RS_CHKSUM1; | |
1222 | } else if (s->line_buf_index >= sizeof(s->line_buf) - 1) { | |
1223 | s->state = RS_IDLE; | |
4c3a88a2 | 1224 | } else { |
858693c6 | 1225 | s->line_buf[s->line_buf_index++] = ch; |
4c3a88a2 FB |
1226 | } |
1227 | break; | |
858693c6 FB |
1228 | case RS_CHKSUM1: |
1229 | s->line_buf[s->line_buf_index] = '\0'; | |
1230 | s->line_csum = fromhex(ch) << 4; | |
1231 | s->state = RS_CHKSUM2; | |
1232 | break; | |
1233 | case RS_CHKSUM2: | |
1234 | s->line_csum |= fromhex(ch); | |
1235 | csum = 0; | |
1236 | for(i = 0; i < s->line_buf_index; i++) { | |
1237 | csum += s->line_buf[i]; | |
1238 | } | |
1239 | if (s->line_csum != (csum & 0xff)) { | |
1240 | reply[0] = '-'; | |
1241 | put_buffer(s, reply, 1); | |
1242 | s->state = RS_IDLE; | |
4c3a88a2 | 1243 | } else { |
858693c6 FB |
1244 | reply[0] = '+'; |
1245 | put_buffer(s, reply, 1); | |
1fddef4b | 1246 | s->state = gdb_handle_packet(s, env, s->line_buf); |
4c3a88a2 FB |
1247 | } |
1248 | break; | |
a2d1ebaf PB |
1249 | default: |
1250 | abort(); | |
858693c6 FB |
1251 | } |
1252 | } | |
1253 | } | |
1254 | ||
1fddef4b FB |
1255 | #ifdef CONFIG_USER_ONLY |
1256 | int | |
1257 | gdb_handlesig (CPUState *env, int sig) | |
1258 | { | |
1259 | GDBState *s; | |
1260 | char buf[256]; | |
1261 | int n; | |
1262 | ||
1263 | if (gdbserver_fd < 0) | |
1264 | return sig; | |
1265 | ||
1266 | s = &gdbserver_state; | |
1267 | ||
1268 | /* disable single step if it was enabled */ | |
1269 | cpu_single_step(env, 0); | |
1270 | tb_flush(env); | |
1271 | ||
1272 | if (sig != 0) | |
1273 | { | |
1274 | snprintf(buf, sizeof(buf), "S%02x", sig); | |
1275 | put_packet(s, buf); | |
1276 | } | |
1277 | ||
1fddef4b FB |
1278 | sig = 0; |
1279 | s->state = RS_IDLE; | |
41625033 FB |
1280 | s->running_state = 0; |
1281 | while (s->running_state == 0) { | |
1fddef4b FB |
1282 | n = read (s->fd, buf, 256); |
1283 | if (n > 0) | |
1284 | { | |
1285 | int i; | |
1286 | ||
1287 | for (i = 0; i < n; i++) | |
6a00d601 | 1288 | gdb_read_byte (s, buf[i]); |
1fddef4b FB |
1289 | } |
1290 | else if (n == 0 || errno != EAGAIN) | |
1291 | { | |
1292 | /* XXX: Connection closed. Should probably wait for annother | |
1293 | connection before continuing. */ | |
1294 | return sig; | |
1295 | } | |
41625033 | 1296 | } |
1fddef4b FB |
1297 | return sig; |
1298 | } | |
e9009676 FB |
1299 | |
1300 | /* Tell the remote gdb that the process has exited. */ | |
1301 | void gdb_exit(CPUState *env, int code) | |
1302 | { | |
1303 | GDBState *s; | |
1304 | char buf[4]; | |
1305 | ||
1306 | if (gdbserver_fd < 0) | |
1307 | return; | |
1308 | ||
1309 | s = &gdbserver_state; | |
1310 | ||
1311 | snprintf(buf, sizeof(buf), "W%02x", code); | |
1312 | put_packet(s, buf); | |
1313 | } | |
1314 | ||
1fddef4b | 1315 | |
7c9d8e07 | 1316 | static void gdb_accept(void *opaque) |
858693c6 FB |
1317 | { |
1318 | GDBState *s; | |
1319 | struct sockaddr_in sockaddr; | |
1320 | socklen_t len; | |
1321 | int val, fd; | |
1322 | ||
1323 | for(;;) { | |
1324 | len = sizeof(sockaddr); | |
1325 | fd = accept(gdbserver_fd, (struct sockaddr *)&sockaddr, &len); | |
1326 | if (fd < 0 && errno != EINTR) { | |
1327 | perror("accept"); | |
1328 | return; | |
1329 | } else if (fd >= 0) { | |
b4608c04 FB |
1330 | break; |
1331 | } | |
1332 | } | |
858693c6 FB |
1333 | |
1334 | /* set short latency */ | |
1335 | val = 1; | |
8f447cc7 | 1336 | setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *)&val, sizeof(val)); |
3b46e624 | 1337 | |
1fddef4b FB |
1338 | s = &gdbserver_state; |
1339 | memset (s, 0, sizeof (GDBState)); | |
6a00d601 | 1340 | s->env = first_cpu; /* XXX: allow to change CPU */ |
858693c6 FB |
1341 | s->fd = fd; |
1342 | ||
a2d1ebaf PB |
1343 | gdb_syscall_state = s; |
1344 | ||
858693c6 | 1345 | fcntl(fd, F_SETFL, O_NONBLOCK); |
858693c6 FB |
1346 | } |
1347 | ||
1348 | static int gdbserver_open(int port) | |
1349 | { | |
1350 | struct sockaddr_in sockaddr; | |
1351 | int fd, val, ret; | |
1352 | ||
1353 | fd = socket(PF_INET, SOCK_STREAM, 0); | |
1354 | if (fd < 0) { | |
1355 | perror("socket"); | |
1356 | return -1; | |
1357 | } | |
1358 | ||
1359 | /* allow fast reuse */ | |
1360 | val = 1; | |
8f447cc7 | 1361 | setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&val, sizeof(val)); |
858693c6 FB |
1362 | |
1363 | sockaddr.sin_family = AF_INET; | |
1364 | sockaddr.sin_port = htons(port); | |
1365 | sockaddr.sin_addr.s_addr = 0; | |
1366 | ret = bind(fd, (struct sockaddr *)&sockaddr, sizeof(sockaddr)); | |
1367 | if (ret < 0) { | |
1368 | perror("bind"); | |
1369 | return -1; | |
1370 | } | |
1371 | ret = listen(fd, 0); | |
1372 | if (ret < 0) { | |
1373 | perror("listen"); | |
1374 | return -1; | |
1375 | } | |
858693c6 FB |
1376 | return fd; |
1377 | } | |
1378 | ||
1379 | int gdbserver_start(int port) | |
1380 | { | |
1381 | gdbserver_fd = gdbserver_open(port); | |
1382 | if (gdbserver_fd < 0) | |
1383 | return -1; | |
1384 | /* accept connections */ | |
7c9d8e07 | 1385 | gdb_accept (NULL); |
4046d913 PB |
1386 | return 0; |
1387 | } | |
1fddef4b | 1388 | #else |
aa1f17c1 | 1389 | static int gdb_chr_can_receive(void *opaque) |
4046d913 PB |
1390 | { |
1391 | return 1; | |
1392 | } | |
1393 | ||
aa1f17c1 | 1394 | static void gdb_chr_receive(void *opaque, const uint8_t *buf, int size) |
4046d913 PB |
1395 | { |
1396 | GDBState *s = opaque; | |
1397 | int i; | |
1398 | ||
1399 | for (i = 0; i < size; i++) { | |
1400 | gdb_read_byte(s, buf[i]); | |
1401 | } | |
1402 | } | |
1403 | ||
1404 | static void gdb_chr_event(void *opaque, int event) | |
1405 | { | |
1406 | switch (event) { | |
1407 | case CHR_EVENT_RESET: | |
1408 | vm_stop(EXCP_INTERRUPT); | |
a2d1ebaf | 1409 | gdb_syscall_state = opaque; |
4046d913 PB |
1410 | break; |
1411 | default: | |
1412 | break; | |
1413 | } | |
1414 | } | |
1415 | ||
cfc3475a | 1416 | int gdbserver_start(const char *port) |
4046d913 PB |
1417 | { |
1418 | GDBState *s; | |
cfc3475a PB |
1419 | char gdbstub_port_name[128]; |
1420 | int port_num; | |
1421 | char *p; | |
1422 | CharDriverState *chr; | |
1423 | ||
1424 | if (!port || !*port) | |
1425 | return -1; | |
4046d913 | 1426 | |
cfc3475a PB |
1427 | port_num = strtol(port, &p, 10); |
1428 | if (*p == 0) { | |
1429 | /* A numeric value is interpreted as a port number. */ | |
1430 | snprintf(gdbstub_port_name, sizeof(gdbstub_port_name), | |
1431 | "tcp::%d,nowait,nodelay,server", port_num); | |
1432 | port = gdbstub_port_name; | |
1433 | } | |
1434 | ||
1435 | chr = qemu_chr_open(port); | |
4046d913 PB |
1436 | if (!chr) |
1437 | return -1; | |
1438 | ||
1439 | s = qemu_mallocz(sizeof(GDBState)); | |
1440 | if (!s) { | |
1441 | return -1; | |
1442 | } | |
1443 | s->env = first_cpu; /* XXX: allow to change CPU */ | |
1444 | s->chr = chr; | |
aa1f17c1 | 1445 | qemu_chr_add_handlers(chr, gdb_chr_can_receive, gdb_chr_receive, |
4046d913 PB |
1446 | gdb_chr_event, s); |
1447 | qemu_add_vm_stop_handler(gdb_vm_stopped, s); | |
b4608c04 FB |
1448 | return 0; |
1449 | } | |
4046d913 | 1450 | #endif |