1 /////////////////////////////////////////////////////////////////////////
2 // $Id: gdbstub.cc,v 1.30 2007/10/18 22:44:38 sshwarts Exp $
3 /////////////////////////////////////////////////////////////////////////
5 // Copyright (C) 2002-2006 The Bochs Project Team
7 // This library is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU Lesser General Public
9 // License as published by the Free Software Foundation; either
10 // version 2 of the License, or (at your option) any later version.
12 // This library is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 // Lesser General Public License for more details.
17 // You should have received a copy of the GNU Lesser General Public
18 // License along with this library; if not, write to the Free Software
19 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 #include <sys/types.h>
28 #include <sys/socket.h>
29 #include <netinet/in.h>
30 #include <netinet/tcp.h>
31 #include <arpa/inet.h>
36 #define NEED_CPU_REG_SHORTCUTS 1
40 #include "iodev/iodev.h"
42 #define LOG_THIS gdbstublog->
45 static int last_stop_reason
= GDBSTUB_STOP_NO_REASON
;
47 #define GDBSTUB_EXECUTION_BREAKPOINT (0xac1)
48 #define GDBSTUB_TRACE (0xac2)
49 #define GDBSTUB_USER_BREAK (0xac3)
51 static bx_list_c
*gdbstub_list
;
52 static int listen_socket_fd
;
54 static logfunctions
*gdbstublog
;
56 static int hex(char ch
)
58 if ((ch
>= 'a') && (ch
<= 'f')) return(ch
- 'a' + 10);
59 if ((ch
>= '0') && (ch
<= '9')) return(ch
- '0');
60 if ((ch
>= 'A') && (ch
<= 'F')) return(ch
- 'A' + 10);
64 static char buf
[4096], *bufptr
= buf
;
66 static void flush_debug_buffer()
70 int n
= send(socket_fd
, p
, bufptr
-p
, 0);
72 BX_ERROR(("error on debug socket: %m"));
80 static void put_debug_char(char ch
)
82 if (bufptr
== buf
+ sizeof buf
)
87 static char get_debug_char(void)
91 recv(socket_fd
, &ch
, 1, 0);
96 static const char hexchars
[]="0123456789abcdef";
98 static void put_reply(char* buffer
)
103 BX_DEBUG (("put_buffer %s", buffer
));
111 while (buffer
[i
] != 0)
113 put_debug_char(buffer
[i
]);
114 csum
= csum
+ buffer
[i
];
119 put_debug_char(hexchars
[csum
>> 4]);
120 put_debug_char(hexchars
[csum
% 16]);
121 flush_debug_buffer();
122 } while (get_debug_char() != '+');
125 static void get_command(char* buffer
)
127 unsigned char checksum
;
128 unsigned char xmitcsum
;
134 while ((ch
= get_debug_char()) != '$');
142 ch
= get_debug_char();
143 if (ch
== '#') break;
144 checksum
= checksum
+ ch
;
152 xmitcsum
= hex(get_debug_char()) << 4;
153 xmitcsum
+= hex(get_debug_char());
154 if (checksum
!= xmitcsum
)
156 BX_INFO(("Bad checksum"));
160 if (checksum
!= xmitcsum
)
163 flush_debug_buffer();
168 if (buffer
[2] == ':')
170 put_debug_char(buffer
[0]);
171 put_debug_char(buffer
[1]);
172 count
= strlen(buffer
);
173 for (i
= 3; i
<= count
; i
++)
175 buffer
[i
- 3] = buffer
[i
];
178 flush_debug_buffer();
180 } while (checksum
!= xmitcsum
);
183 void hex2mem(char* buf
, unsigned char* mem
, int count
)
188 for (i
= 0; i
<count
; i
++)
190 ch
= hex(*buf
++) << 4;
191 ch
= ch
+ hex(*buf
++);
197 char* mem2hex(char* mem
, char* buf
, int count
)
202 for (i
= 0; i
<count
; i
++)
206 *buf
= hexchars
[ch
>> 4];
208 *buf
= hexchars
[ch
% 16];
225 Bit64u
read_little_endian_hex(char *&buf
)
230 while (isxdigit(*buf
)) {
231 byte
= hexdigit(*buf
++);
233 byte
= (byte
<< 4) | hexdigit(*buf
++);
234 ret
|= (unsigned long long)byte
<< (n
*8);
240 static int continue_thread
= -1;
241 static int other_thread
= 0;
243 #if !BX_SUPPORT_X86_64
245 #define NUMREGSBYTES (NUMREGS * 4)
246 static int registers
[NUMREGS
];
249 #define MAX_BREAKPOINTS (255)
250 static unsigned int breakpoints
[MAX_BREAKPOINTS
] = {0,};
251 static unsigned int nr_breakpoints
= 0;
253 static int stub_trace_flag
= 0;
254 static int instr_count
= 0;
255 static int saved_eip
= 0;
256 static int bx_enter_gdbstub
= 0;
258 void bx_gdbstub_break(void)
260 bx_enter_gdbstub
= 1;
263 int bx_gdbstub_check(unsigned int eip
)
269 #if defined(__CYGWIN__) || defined(__MINGW32__)
271 struct timeval tv
= {0, 0};
274 if (bx_enter_gdbstub
)
276 bx_enter_gdbstub
= 0;
277 last_stop_reason
= GDBSTUB_EXECUTION_BREAKPOINT
;
278 return GDBSTUB_EXECUTION_BREAKPOINT
;
283 if ((instr_count
% 500) == 0)
285 #if !defined(__CYGWIN__) && !defined(__MINGW32__)
286 arg
= fcntl(socket_fd
, F_GETFL
);
287 fcntl(socket_fd
, F_SETFL
, arg
| O_NONBLOCK
);
288 r
= recv(socket_fd
, &ch
, 1, 0);
289 fcntl(socket_fd
, F_SETFL
, arg
);
292 FD_SET(socket_fd
, &fds
);
293 r
= select(socket_fd
+ 1, &fds
, NULL
, NULL
, &tv
);
296 r
= recv(socket_fd
, (char *)&ch
, 1, 0);
301 BX_INFO(("Got byte %x", (unsigned int)ch
));
302 last_stop_reason
= GDBSTUB_USER_BREAK
;
303 return GDBSTUB_USER_BREAK
;
307 for (i
= 0; i
< nr_breakpoints
; i
++)
309 if (eip
== breakpoints
[i
])
311 BX_INFO(("found breakpoint at %x", eip
));
312 last_stop_reason
= GDBSTUB_EXECUTION_BREAKPOINT
;
313 return GDBSTUB_EXECUTION_BREAKPOINT
;
317 if (stub_trace_flag
== 1)
319 last_stop_reason
= GDBSTUB_TRACE
;
320 return GDBSTUB_TRACE
;
322 last_stop_reason
= GDBSTUB_STOP_NO_REASON
;
323 return GDBSTUB_STOP_NO_REASON
;
326 static int remove_breakpoint(unsigned int addr
, int len
)
335 for (i
= 0; i
< MAX_BREAKPOINTS
; i
++)
337 if (breakpoints
[i
] == addr
)
339 BX_INFO(("Removing breakpoint at %x", addr
));
347 static void insert_breakpoint(unsigned int addr
)
351 BX_INFO(("setting breakpoint at %x", addr
));
353 for (i
= 0; i
< (unsigned)MAX_BREAKPOINTS
; i
++)
355 if (breakpoints
[i
] == 0)
357 breakpoints
[i
] = addr
;
358 if (i
>= nr_breakpoints
)
360 nr_breakpoints
= i
+ 1;
365 BX_INFO(("No slot for breakpoint"));
368 static void do_pc_breakpoint(int insert
, unsigned long long addr
, int len
)
370 for (int i
= 0; i
< len
; ++i
)
372 insert_breakpoint(addr
+i
);
374 remove_breakpoint(addr
+i
, 1);
377 static void do_breakpoint(int insert
, char* buffer
)
380 unsigned long type
= strtoul(buffer
, &ebuf
, 16);
381 unsigned long long addr
= strtoull(ebuf
+1, &ebuf
, 16);
382 unsigned long len
= strtoul(ebuf
+1, &ebuf
, 16);
386 do_pc_breakpoint(insert
, addr
, len
);
395 static void write_signal(char* buf
, int signal
)
397 buf
[0] = hexchars
[signal
>> 4];
398 buf
[1] = hexchars
[signal
% 16];
402 static int access_linear(Bit64u laddress
,
410 if (((laddress
& 0xfff) + len
) > 4096)
412 valid
= access_linear(laddress
,
413 4096 - (laddress
& 0xfff),
416 if (!valid
) return(0);
418 valid
= access_linear(laddress
,
419 len
+ (laddress
& 0xfff) - 4096,
421 (Bit8u
*)((unsigned long)data
+
422 4096 - (laddress
& 0xfff)));
426 valid
= BX_CPU(0)->dbg_xlate_linear2phy(laddress
, (bx_phy_address
*)&phys
);
427 if (!valid
) return(0);
430 valid
= BX_MEM(0)->dbg_fetch_mem(BX_CPU(0), phys
, len
, data
);
432 valid
= BX_MEM(0)->dbg_set_mem(phys
, len
, data
);
438 static void debug_loop(void)
443 unsigned char mem
[255];
450 BX_DEBUG(("get_buffer %s", buffer
));
461 new_eip
= atoi(buffer
+ 1);
463 BX_INFO(("continuing at %x", new_eip
));
465 for (int i
=0; i
<BX_SMP_PROCESSORS
; i
++) {
466 BX_CPU(i
)->invalidate_prefetch_q();
471 BX_CPU(0)->eip_reg
.dword
.eip
= new_eip
;
481 bx_cpu
.invalidate_prefetch_q();
482 BX_CPU_THIS_PTR eip_reg
.dword
.eip
= saved_eip
;
485 BX_INFO(("stopped with %x", last_stop_reason
));
487 if (last_stop_reason
== GDBSTUB_EXECUTION_BREAKPOINT
||
488 last_stop_reason
== GDBSTUB_TRACE
)
490 write_signal(&buf
[1], SIGTRAP
);
494 write_signal(&buf
[1], 0);
504 BX_INFO(("stepping"));
509 BX_INFO(("stopped with %x", last_stop_reason
));
511 if (last_stop_reason
== GDBSTUB_EXECUTION_BREAKPOINT
||
512 last_stop_reason
== GDBSTUB_TRACE
)
514 write_signal(&buf
[1], SIGTRAP
);
518 write_signal(&buf
[1], SIGTRAP
);
528 unsigned char mem
[255];
531 addr
= strtoull(&buffer
[1], &ebuf
, 16);
532 len
= strtoul(ebuf
+ 1, &ebuf
, 16);
533 hex2mem(ebuf
+ 1, mem
, len
);
535 if (len
== 1 && mem
[0] == 0xcc)
537 insert_breakpoint(addr
);
540 else if (remove_breakpoint(addr
, len
))
546 if (access_linear(addr
, len
, BX_WRITE
, mem
))
564 addr
= strtoull(&buffer
[1], &ebuf
, 16);
565 len
= strtoul(ebuf
+ 1, NULL
, 16);
566 BX_INFO(("addr %Lx len %x", addr
, len
));
568 access_linear(addr
, len
, BX_READ
, mem
);
569 mem2hex((char *)mem
, obuf
, len
);
577 unsigned long long value
;
580 reg
= strtoul(&buffer
[1], &ebuf
, 16);
582 value
= read_little_endian_hex(ebuf
);
584 BX_INFO(("reg %d set to %Lx", reg
, value
));
585 #if !BX_SUPPORT_X86_64
618 BX_CPU_THIS_PTR
invalidate_prefetch_q();
693 BX_CPU_THIS_PTR
invalidate_prefetch_q();
706 #if !BX_SUPPORT_X86_64
715 if (last_stop_reason
== GDBSTUB_EXECUTION_BREAKPOINT
)
717 registers
[8] = EIP
+ 1;
723 registers
[9] = BX_CPU_THIS_PTR
read_eflags();
725 BX_CPU_THIS_PTR sregs
[BX_SEG_REG_CS
].selector
.value
;
727 BX_CPU_THIS_PTR sregs
[BX_SEG_REG_SS
].selector
.value
;
729 BX_CPU_THIS_PTR sregs
[BX_SEG_REG_DS
].selector
.value
;
731 BX_CPU_THIS_PTR sregs
[BX_SEG_REG_ES
].selector
.value
;
733 BX_CPU_THIS_PTR sregs
[BX_SEG_REG_FS
].selector
.value
;
735 BX_CPU_THIS_PTR sregs
[BX_SEG_REG_GS
].selector
.value
;
736 mem2hex((char *)registers
, obuf
, NUMREGSBYTES
);
738 #define PUTREG(buf, val, len) do { \
740 (buf) = mem2hex((char*)&u, (buf), (len)); \
762 if (last_stop_reason
== GDBSTUB_EXECUTION_BREAKPOINT
)
767 PUTREG(buf
, BX_CPU_THIS_PTR
read_eflags(), 4);
768 PUTREG(buf
, BX_CPU_THIS_PTR sregs
[BX_SEG_REG_CS
].selector
.value
, 4);
769 PUTREG(buf
, BX_CPU_THIS_PTR sregs
[BX_SEG_REG_SS
].selector
.value
, 4);
770 PUTREG(buf
, BX_CPU_THIS_PTR sregs
[BX_SEG_REG_DS
].selector
.value
, 4);
771 PUTREG(buf
, BX_CPU_THIS_PTR sregs
[BX_SEG_REG_ES
].selector
.value
, 4);
772 PUTREG(buf
, BX_CPU_THIS_PTR sregs
[BX_SEG_REG_FS
].selector
.value
, 4);
773 PUTREG(buf
, BX_CPU_THIS_PTR sregs
[BX_SEG_REG_GS
].selector
.value
, 4);
779 sprintf(obuf
, "S%02x", SIGTRAP
);
784 if (buffer
[1] == 'c')
786 continue_thread
= strtol(&buffer
[2], NULL
, 16);
789 else if (buffer
[1] == 'g')
791 other_thread
= strtol(&buffer
[2], NULL
, 16);
801 if (buffer
[1] == 'C')
803 sprintf(obuf
,"%Lx", (Bit64u
)1);
806 else if (strncmp(&buffer
[1], "Offsets", strlen("Offsets")) == 0)
808 sprintf(obuf
, "Text=%x;Data=%x;Bss=%x",
809 SIM
->get_param_num("text_base", gdbstub_list
)->get(),
810 SIM
->get_param_num("data_base", gdbstub_list
)->get(),
811 SIM
->get_param_num("bss_base", gdbstub_list
)->get());
821 do_breakpoint(1, buffer
+1);
824 do_breakpoint(0, buffer
+1);
827 BX_PANIC(("Debugger asked us to quit"));
837 static void wait_for_connect(int portn
)
839 struct sockaddr_in sockaddr
;
840 socklen_t sockaddr_len
;
841 struct protoent
*protoent
;
845 listen_socket_fd
= socket(PF_INET
, SOCK_STREAM
, 0);
846 if (listen_socket_fd
== -1)
848 BX_PANIC(("Failed to create socket"));
852 /* Allow rapid reuse of this port */
855 r
= setsockopt(listen_socket_fd
, SOL_SOCKET
, SO_REUSEADDR
, (const char *)&opt
, sizeof(opt
));
857 r
= setsockopt(listen_socket_fd
, SOL_SOCKET
, SO_REUSEADDR
, &opt
, sizeof(opt
));
861 BX_INFO(("setsockopt(SO_REUSEADDR) failed"));
864 memset (&sockaddr
, '\000', sizeof sockaddr
);
865 #if BX_HAVE_SOCKADDR_IN_SIN_LEN
866 // if you don't have sin_len change that to #if 0. This is the subject of
867 // bug [ 626840 ] no 'sin_len' in 'struct sockaddr_in'.
868 sockaddr
.sin_len
= sizeof sockaddr
;
870 sockaddr
.sin_family
= AF_INET
;
871 sockaddr
.sin_port
= htons(portn
);
872 sockaddr
.sin_addr
.s_addr
= htonl(INADDR_ANY
);
874 r
= bind(listen_socket_fd
, (struct sockaddr
*)&sockaddr
, sizeof(sockaddr
));
877 BX_PANIC(("Failed to bind socket"));
880 r
= listen(listen_socket_fd
, 0);
883 BX_PANIC(("Failed to listen on socket"));
886 sockaddr_len
= sizeof sockaddr
;
887 socket_fd
= accept(listen_socket_fd
, (struct sockaddr
*)&sockaddr
, &sockaddr_len
);
890 BX_PANIC(("Failed to accept on socket"));
892 close(listen_socket_fd
);
894 protoent
= getprotobyname ("tcp");
897 BX_INFO(("getprotobyname (\"tcp\") failed"));
901 /* Disable Nagle - allow small packets to be sent without delay. */
904 r
= setsockopt (socket_fd
, protoent
->p_proto
, TCP_NODELAY
, (const char *)&opt
, sizeof(opt
));
906 r
= setsockopt (socket_fd
, protoent
->p_proto
, TCP_NODELAY
, &opt
, sizeof(opt
));
910 BX_INFO(("setsockopt(TCP_NODELAY) failed"));
912 Bit32u ip
= sockaddr
.sin_addr
.s_addr
;
913 printf("Connected to %d.%d.%d.%d\n", ip
& 0xff, (ip
>> 8) & 0xff, (ip
>> 16) & 0xff, (ip
>> 24) & 0xff);
916 void bx_gdbstub_init(void)
918 gdbstublog
= new logfunctions();
919 gdbstublog
->put("GDBST");
920 gdbstublog
->setonoff(LOGLEV_PANIC
, ACT_FATAL
);
922 gdbstub_list
= (bx_list_c
*) SIM
->get_param(BXPN_GDBSTUB
);
923 int portn
= SIM
->get_param_num("port", gdbstub_list
)->get();
927 WSAStartup(2, &wsaData
);
930 /* Wait for connect */
931 printf("Waiting for gdb connection on port %d\n", portn
);
932 wait_for_connect(portn
);
934 /* Do debugger command loop */