added CPU callbacks
[qemu] / gdbstub.c
1 /*
2  * gdb server stub
3  * 
4  * Copyright (c) 2003 Fabrice Bellard
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  */
20 #include <stdlib.h>
21 #include <stdio.h>
22 #include <string.h>
23 #include <unistd.h>
24 #include <errno.h>
25 #include <sys/socket.h>
26 #include <netinet/in.h>
27 #include <netinet/tcp.h>
28 #include <signal.h>
29
30 #include "config.h"
31 #include "cpu.h"
32 #include "thunk.h"
33 #include "exec-all.h"
34
35 //#define DEBUG_GDB
36
37 int gdbstub_fd = -1;
38
39 /* return 0 if OK */
40 static int gdbstub_open(int port)
41 {
42     struct sockaddr_in sockaddr;
43     socklen_t len;
44     int fd, val, ret;
45
46     fd = socket(PF_INET, SOCK_STREAM, 0);
47     if (fd < 0) {
48         perror("socket");
49         return -1;
50     }
51
52     /* allow fast reuse */
53     val = 1;
54     setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
55
56     sockaddr.sin_family = AF_INET;
57     sockaddr.sin_port = htons(port);
58     sockaddr.sin_addr.s_addr = 0;
59     ret = bind(fd, (struct sockaddr *)&sockaddr, sizeof(sockaddr));
60     if (ret < 0) {
61         perror("bind");
62         return -1;
63     }
64     ret = listen(fd, 0);
65     if (ret < 0) {
66         perror("listen");
67         return -1;
68     }
69     
70     /* now wait for one connection */
71     for(;;) {
72         len = sizeof(sockaddr);
73         gdbstub_fd = accept(fd, (struct sockaddr *)&sockaddr, &len);
74         if (gdbstub_fd < 0 && errno != EINTR) {
75             perror("accept");
76             return -1;
77         } else if (gdbstub_fd >= 0) {
78             break;
79         }
80     }
81     
82     /* set short latency */
83     val = 1;
84     setsockopt(gdbstub_fd, SOL_TCP, TCP_NODELAY, &val, sizeof(val));
85     return 0;
86 }
87
88 static int get_char(void)
89 {
90     uint8_t ch;
91     int ret;
92
93     for(;;) {
94         ret = read(gdbstub_fd, &ch, 1);
95         if (ret < 0) {
96             if (errno != EINTR && errno != EAGAIN)
97                 return -1;
98         } else if (ret == 0) {
99             return -1;
100         } else {
101             break;
102         }
103     }
104     return ch;
105 }
106
107 static void put_buffer(const uint8_t *buf, int len)
108 {
109     int ret;
110
111     while (len > 0) {
112         ret = write(gdbstub_fd, buf, len);
113         if (ret < 0) {
114             if (errno != EINTR && errno != EAGAIN)
115                 return;
116         } else {
117             buf += ret;
118             len -= ret;
119         }
120     }
121 }
122
123 static inline int fromhex(int v)
124 {
125     if (v >= '0' && v <= '9')
126         return v - '0';
127     else if (v >= 'A' && v <= 'F')
128         return v - 'A' + 10;
129     else if (v >= 'a' && v <= 'f')
130         return v - 'a' + 10;
131     else
132         return 0;
133 }
134
135 static inline int tohex(int v)
136 {
137     if (v < 10)
138         return v + '0';
139     else
140         return v - 10 + 'a';
141 }
142
143 static void memtohex(char *buf, const uint8_t *mem, int len)
144 {
145     int i, c;
146     char *q;
147     q = buf;
148     for(i = 0; i < len; i++) {
149         c = mem[i];
150         *q++ = tohex(c >> 4);
151         *q++ = tohex(c & 0xf);
152     }
153     *q = '\0';
154 }
155
156 static void hextomem(uint8_t *mem, const char *buf, int len)
157 {
158     int i;
159
160     for(i = 0; i < len; i++) {
161         mem[i] = (fromhex(buf[0]) << 4) | fromhex(buf[1]);
162         buf += 2;
163     }
164 }
165
166 /* return -1 if error or EOF */
167 static int get_packet(char *buf, int buf_size)
168 {
169     int ch, len, csum, csum1;
170     char reply[1];
171     
172     for(;;) {
173         for(;;) {
174             ch = get_char();
175             if (ch < 0)
176                 return -1;
177             if (ch == '$')
178                 break;
179         }
180         len = 0;
181         csum = 0;
182         for(;;) {
183             ch = get_char();
184             if (ch < 0)
185                 return -1;
186             if (ch == '#')
187                 break;
188             if (len > buf_size - 1)
189                 return -1;
190             buf[len++] = ch;
191             csum += ch;
192         }
193         buf[len] = '\0';
194         ch = get_char();
195         if (ch < 0)
196             return -1;
197         csum1 = fromhex(ch) << 4;
198         ch = get_char();
199         if (ch < 0)
200             return -1;
201         csum1 |= fromhex(ch);
202         if ((csum & 0xff) != csum1) {
203             reply[0] = '-';
204             put_buffer(reply, 1);
205         } else {
206             reply[0] = '+';
207             put_buffer(reply, 1);
208             break;
209         }
210     }
211 #ifdef DEBUG_GDB
212     printf("command='%s'\n", buf);
213 #endif
214     return len;
215 }
216
217 /* return -1 if error, 0 if OK */
218 static int put_packet(char *buf)
219 {
220     char buf1[3];
221     int len, csum, ch, i;
222
223 #ifdef DEBUG_GDB
224     printf("reply='%s'\n", buf);
225 #endif
226
227     for(;;) {
228         buf1[0] = '$';
229         put_buffer(buf1, 1);
230         len = strlen(buf);
231         put_buffer(buf, len);
232         csum = 0;
233         for(i = 0; i < len; i++) {
234             csum += buf[i];
235         }
236         buf1[0] = '#';
237         buf1[1] = tohex((csum >> 4) & 0xf);
238         buf1[2] = tohex((csum) & 0xf);
239
240         put_buffer(buf1, 3);
241
242         ch = get_char();
243         if (ch < 0)
244             return -1;
245         if (ch == '+')
246             break;
247     }
248     return 0;
249 }
250
251     /* better than nothing for SOFTMMU : we use physical addresses */
252 #ifdef CONFIG_SOFTMMU
253 static int memory_rw(uint8_t *buf, uint32_t addr, int len, int is_write)
254 {
255     uint8_t *ptr;
256
257     if (addr >= phys_ram_size ||
258         ((int64_t)addr + len > phys_ram_size))
259         return -1;
260     ptr = phys_ram_base + addr;
261     if (is_write)
262         memcpy(ptr, buf, len);
263     else
264         memcpy(buf, ptr, len);
265     return 0;
266 }
267 #else
268 static int memory_rw(uint8_t *buf, uint32_t addr, int len, int is_write)
269 {
270     int l, flags;
271     uint32_t page;
272
273     while (len > 0) {
274         page = addr & TARGET_PAGE_MASK;
275         l = (page + TARGET_PAGE_SIZE) - addr;
276         if (l > len)
277             l = len;
278         flags = page_get_flags(page);
279         if (!(flags & PAGE_VALID))
280             return -1;
281         if (is_write) {
282             if (!(flags & PAGE_WRITE))
283                 return -1;
284             memcpy((uint8_t *)addr, buf, l);
285         } else {
286             if (!(flags & PAGE_READ))
287                 return -1;
288             memcpy(buf, (uint8_t *)addr, l);
289         }
290         len -= l;
291         buf += l;
292         addr += l;
293     }
294     return 0;
295 }
296 #endif
297
298 #if defined(TARGET_I386)
299
300 static void to_le32(uint8_t *p, int v)
301 {
302     p[0] = v;
303     p[1] = v >> 8;
304     p[2] = v >> 16;
305     p[3] = v >> 24;
306 }
307
308 static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf)
309 {
310     int i, fpus;
311
312     for(i = 0; i < 8; i++) {
313         to_le32(mem_buf + i * 4, env->regs[i]);
314     }
315     to_le32(mem_buf + 8 * 4, env->eip);
316     to_le32(mem_buf + 9 * 4, env->eflags);
317     to_le32(mem_buf + 10 * 4, env->segs[R_CS].selector);
318     to_le32(mem_buf + 11 * 4, env->segs[R_SS].selector);
319     to_le32(mem_buf + 12 * 4, env->segs[R_DS].selector);
320     to_le32(mem_buf + 13 * 4, env->segs[R_ES].selector);
321     to_le32(mem_buf + 14 * 4, env->segs[R_FS].selector);
322     to_le32(mem_buf + 15 * 4, env->segs[R_GS].selector);
323     /* XXX: convert floats */
324     for(i = 0; i < 8; i++) {
325         memcpy(mem_buf + 16 * 4 + i * 10, &env->fpregs[i], 10);
326     }
327     to_le32(mem_buf + 36 * 4, env->fpuc);
328     fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
329     to_le32(mem_buf + 37 * 4, fpus);
330     to_le32(mem_buf + 38 * 4, 0); /* XXX: convert tags */
331     to_le32(mem_buf + 39 * 4, 0); /* fiseg */
332     to_le32(mem_buf + 40 * 4, 0); /* fioff */
333     to_le32(mem_buf + 41 * 4, 0); /* foseg */
334     to_le32(mem_buf + 42 * 4, 0); /* fooff */
335     to_le32(mem_buf + 43 * 4, 0); /* fop */
336     return 44 * 4;
337 }
338
339 static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size)
340 {
341     uint32_t *registers = (uint32_t *)mem_buf;
342     int i;
343
344     for(i = 0; i < 8; i++) {
345         env->regs[i] = tswapl(registers[i]);
346     }
347     env->eip = registers[8];
348     env->eflags = registers[9];
349 #if defined(CONFIG_USER_ONLY)
350 #define LOAD_SEG(index, sreg)\
351             if (tswapl(registers[index]) != env->segs[sreg].selector)\
352                 cpu_x86_load_seg(env, sreg, tswapl(registers[index]));
353             LOAD_SEG(10, R_CS);
354             LOAD_SEG(11, R_SS);
355             LOAD_SEG(12, R_DS);
356             LOAD_SEG(13, R_ES);
357             LOAD_SEG(14, R_FS);
358             LOAD_SEG(15, R_GS);
359 #endif
360 }
361
362 #else
363
364 static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf)
365 {
366     return 0;
367 }
368
369 static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size)
370 {
371 }
372
373 #endif
374
375 /* port = 0 means default port */
376 int cpu_gdbstub(void *opaque, int (*main_loop)(void *opaque), int port)
377 {
378     CPUState *env;
379     const char *p;
380     int ret, ch, reg_size, type;
381     char buf[4096];
382     uint8_t mem_buf[2000];
383     uint32_t *registers;
384     uint32_t addr, len;
385     
386     printf("Waiting gdb connection on port %d\n", port);
387     if (gdbstub_open(port) < 0)
388         return -1;
389     printf("Connected\n");
390     for(;;) {
391         ret = get_packet(buf, sizeof(buf));
392         if (ret < 0)
393             break;
394         p = buf;
395         ch = *p++;
396         switch(ch) {
397         case '?':
398             snprintf(buf, sizeof(buf), "S%02x", SIGTRAP);
399             put_packet(buf);
400             break;
401         case 'c':
402             if (*p != '\0') {
403                 addr = strtoul(p, (char **)&p, 16);
404                 env = cpu_gdbstub_get_env(opaque);
405 #if defined(TARGET_I386)
406                 env->eip = addr;
407 #endif
408             }
409             ret = main_loop(opaque);
410             if (ret == EXCP_DEBUG)
411                 ret = SIGTRAP;
412             else
413                 ret = 0;
414             snprintf(buf, sizeof(buf), "S%02x", ret);
415             put_packet(buf);
416             break;
417         case 's':
418             env = cpu_gdbstub_get_env(opaque);
419             if (*p != '\0') {
420                 addr = strtoul(p, (char **)&p, 16);
421 #if defined(TARGET_I386)
422                 env->eip = addr;
423 #endif
424             }
425             cpu_single_step(env, 1);
426             ret = main_loop(opaque);
427             cpu_single_step(env, 0);
428             if (ret == EXCP_DEBUG)
429                 ret = SIGTRAP;
430             else
431                 ret = 0;
432             snprintf(buf, sizeof(buf), "S%02x", ret);
433             put_packet(buf);
434             break;
435         case 'g':
436             env = cpu_gdbstub_get_env(opaque);
437             reg_size = cpu_gdb_read_registers(env, mem_buf);
438             memtohex(buf, mem_buf, reg_size);
439             put_packet(buf);
440             break;
441         case 'G':
442             env = cpu_gdbstub_get_env(opaque);
443             registers = (void *)mem_buf;
444             len = strlen(p) / 2;
445             hextomem((uint8_t *)registers, p, len);
446             cpu_gdb_write_registers(env, mem_buf, len);
447             put_packet("OK");
448             break;
449         case 'm':
450             addr = strtoul(p, (char **)&p, 16);
451             if (*p == ',')
452                 p++;
453             len = strtoul(p, NULL, 16);
454             if (memory_rw(mem_buf, addr, len, 0) != 0)
455                 memset(mem_buf, 0, len);
456             memtohex(buf, mem_buf, len);
457             put_packet(buf);
458             break;
459         case 'M':
460             addr = strtoul(p, (char **)&p, 16);
461             if (*p == ',')
462                 p++;
463             len = strtoul(p, (char **)&p, 16);
464             if (*p == ',')
465                 p++;
466             hextomem(mem_buf, p, len);
467             if (memory_rw(mem_buf, addr, len, 1) != 0)
468                 put_packet("ENN");
469             else
470                 put_packet("OK");
471             break;
472         case 'Z':
473             type = strtoul(p, (char **)&p, 16);
474             if (*p == ',')
475                 p++;
476             addr = strtoul(p, (char **)&p, 16);
477             if (*p == ',')
478                 p++;
479             len = strtoul(p, (char **)&p, 16);
480             if (type == 0 || type == 1) {
481                 env = cpu_gdbstub_get_env(opaque);
482                 if (cpu_breakpoint_insert(env, addr) < 0)
483                     goto breakpoint_error;
484                 put_packet("OK");
485             } else {
486             breakpoint_error:
487                 put_packet("ENN");
488             }
489             break;
490         case 'z':
491             type = strtoul(p, (char **)&p, 16);
492             if (*p == ',')
493                 p++;
494             addr = strtoul(p, (char **)&p, 16);
495             if (*p == ',')
496                 p++;
497             len = strtoul(p, (char **)&p, 16);
498             if (type == 0 || type == 1) {
499                 env = cpu_gdbstub_get_env(opaque);
500                 cpu_breakpoint_remove(env, addr);
501                 put_packet("OK");
502             } else {
503                 goto breakpoint_error;
504             }
505             break;
506         case 'Q':
507             if (!strncmp(p, "Tinit", 5)) {
508                 /* init traces */
509                 put_packet("OK");
510             } else if (!strncmp(p, "TStart", 6)) {
511                 /* start log (gdb 'tstart' command) */
512                 env = cpu_gdbstub_get_env(opaque);
513                 tb_flush(env);
514                 cpu_set_log(CPU_LOG_ALL);
515                 put_packet("OK");
516             } else if (!strncmp(p, "TStop", 5)) {
517                 /* stop log (gdb 'tstop' command) */
518                 cpu_set_log(0);
519                 put_packet("OK");
520             } else {
521                 goto unknown_command;
522             }
523             break;
524         default:
525         unknown_command:
526             /* put empty packet */
527             buf[0] = '\0';
528             put_packet(buf);
529             break;
530         }
531     }
532     return 0;
533 }