1 /////////////////////////////////////////////////////////////////////////
2 // $Id: gdbstub.cc,v 1.35 2008/12/05 22:34:42 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
)
187 for (int i
= 0; i
<count
; i
++)
189 ch
= hex(*buf
++) << 4;
190 ch
= ch
+ hex(*buf
++);
195 char* mem2hex(char* mem
, char* buf
, int count
)
199 for (int i
= 0; i
<count
; i
++)
202 *buf
++ = hexchars
[ch
>> 4];
203 *buf
++ = hexchars
[ch
% 16];
219 Bit64u
read_little_endian_hex(char *&buf
)
224 while (isxdigit(*buf
)) {
225 byte
= hexdigit(*buf
++);
227 byte
= (byte
<< 4) | hexdigit(*buf
++);
228 ret
|= (unsigned long long)byte
<< (n
*8);
234 static int continue_thread
= -1;
235 static int other_thread
= 0;
237 #if !BX_SUPPORT_X86_64
239 #define NUMREGSBYTES (NUMREGS * 4)
240 static int registers
[NUMREGS
];
243 #define MAX_BREAKPOINTS (255)
244 static unsigned int breakpoints
[MAX_BREAKPOINTS
] = {0,};
245 static unsigned int nr_breakpoints
= 0;
247 static int stub_trace_flag
= 0;
248 static int instr_count
= 0;
249 static int saved_eip
= 0;
250 static int bx_enter_gdbstub
= 0;
252 void bx_gdbstub_break(void)
254 bx_enter_gdbstub
= 1;
257 int bx_gdbstub_check(unsigned int eip
)
263 #if defined(__CYGWIN__) || defined(__MINGW32__)
265 struct timeval tv
= {0, 0};
268 if (bx_enter_gdbstub
)
270 bx_enter_gdbstub
= 0;
271 last_stop_reason
= GDBSTUB_EXECUTION_BREAKPOINT
;
272 return GDBSTUB_EXECUTION_BREAKPOINT
;
277 if ((instr_count
% 500) == 0)
279 #if !defined(__CYGWIN__) && !defined(__MINGW32__)
280 arg
= fcntl(socket_fd
, F_GETFL
);
281 fcntl(socket_fd
, F_SETFL
, arg
| O_NONBLOCK
);
282 r
= recv(socket_fd
, &ch
, 1, 0);
283 fcntl(socket_fd
, F_SETFL
, arg
);
286 FD_SET(socket_fd
, &fds
);
287 r
= select(socket_fd
+ 1, &fds
, NULL
, NULL
, &tv
);
290 r
= recv(socket_fd
, (char *)&ch
, 1, 0);
295 BX_INFO(("Got byte %x", (unsigned int)ch
));
296 last_stop_reason
= GDBSTUB_USER_BREAK
;
297 return GDBSTUB_USER_BREAK
;
301 for (i
= 0; i
< nr_breakpoints
; i
++)
303 if (eip
== breakpoints
[i
])
305 BX_INFO(("found breakpoint at %x", eip
));
306 last_stop_reason
= GDBSTUB_EXECUTION_BREAKPOINT
;
307 return GDBSTUB_EXECUTION_BREAKPOINT
;
311 if (stub_trace_flag
== 1)
313 last_stop_reason
= GDBSTUB_TRACE
;
314 return GDBSTUB_TRACE
;
316 last_stop_reason
= GDBSTUB_STOP_NO_REASON
;
317 return GDBSTUB_STOP_NO_REASON
;
320 static int remove_breakpoint(unsigned int addr
, int len
)
329 for (i
= 0; i
< MAX_BREAKPOINTS
; i
++)
331 if (breakpoints
[i
] == addr
)
333 BX_INFO(("Removing breakpoint at %x", addr
));
341 static void insert_breakpoint(unsigned int addr
)
345 BX_INFO(("setting breakpoint at %x", addr
));
347 for (i
= 0; i
< (unsigned)MAX_BREAKPOINTS
; i
++)
349 if (breakpoints
[i
] == 0)
351 breakpoints
[i
] = addr
;
352 if (i
>= nr_breakpoints
)
354 nr_breakpoints
= i
+ 1;
359 BX_INFO(("No slot for breakpoint"));
362 static void do_pc_breakpoint(int insert
, unsigned long long addr
, int len
)
364 for (int i
= 0; i
< len
; ++i
)
366 insert_breakpoint(addr
+i
);
368 remove_breakpoint(addr
+i
, 1);
371 static void do_breakpoint(int insert
, char* buffer
)
374 unsigned long type
= strtoul(buffer
, &ebuf
, 16);
375 unsigned long long addr
= strtoull(ebuf
+1, &ebuf
, 16);
376 unsigned long len
= strtoul(ebuf
+1, &ebuf
, 16);
380 do_pc_breakpoint(insert
, addr
, len
);
389 static void write_signal(char* buf
, int signal
)
391 buf
[0] = hexchars
[signal
>> 4];
392 buf
[1] = hexchars
[signal
% 16];
396 static int access_linear(Bit64u laddress
,
404 if (((laddress
& 0xfff) + len
) > 4096)
406 valid
= access_linear(laddress
,
407 4096 - (laddress
& 0xfff),
410 if (!valid
) return(0);
412 valid
= access_linear(laddress
,
413 len
+ (laddress
& 0xfff) - 4096,
415 (Bit8u
*)((unsigned long)data
+
416 4096 - (laddress
& 0xfff)));
420 valid
= BX_CPU(0)->dbg_xlate_linear2phy(laddress
, (bx_phy_address
*)&phys
);
421 if (!valid
) return(0);
424 valid
= BX_MEM(0)->dbg_set_mem(phys
, len
, data
);
426 valid
= BX_MEM(0)->dbg_fetch_mem(BX_CPU(0), phys
, len
, data
);
432 static void debug_loop(void)
437 unsigned char mem
[255];
442 BX_DEBUG(("get_buffer '%s'", buffer
));
453 new_eip
= (Bit32u
) atoi(buffer
+ 1);
455 BX_INFO(("continuing at %x", new_eip
));
457 for (int i
=0; i
<BX_SMP_PROCESSORS
; i
++) {
458 BX_CPU(i
)->invalidate_prefetch_q();
462 BX_CPU_THIS_PTR gen_reg
[BX_32BIT_REG_EIP
].dword
.erx
= new_eip
;
472 bx_cpu
.invalidate_prefetch_q();
473 BX_CPU_THIS_PTR gen_reg
[BX_32BIT_REG_EIP
].dword
.erx
= saved_eip
;
476 BX_INFO(("stopped with %x", last_stop_reason
));
478 if (last_stop_reason
== GDBSTUB_EXECUTION_BREAKPOINT
||
479 last_stop_reason
== GDBSTUB_TRACE
)
481 write_signal(&buf
[1], SIGTRAP
);
485 write_signal(&buf
[1], 0);
495 BX_INFO(("stepping"));
500 BX_INFO(("stopped with %x", last_stop_reason
));
502 if (last_stop_reason
== GDBSTUB_EXECUTION_BREAKPOINT
||
503 last_stop_reason
== GDBSTUB_TRACE
)
505 write_signal(&buf
[1], SIGTRAP
);
509 write_signal(&buf
[1], SIGTRAP
);
519 unsigned char mem
[255];
522 addr
= strtoull(&buffer
[1], &ebuf
, 16);
523 len
= strtoul(ebuf
+ 1, &ebuf
, 16);
524 hex2mem(ebuf
+ 1, mem
, len
);
526 if (len
== 1 && mem
[0] == 0xcc)
528 insert_breakpoint(addr
);
531 else if (remove_breakpoint(addr
, len
))
537 if (access_linear(addr
, len
, BX_WRITE
, mem
))
555 addr
= strtoull(&buffer
[1], &ebuf
, 16);
556 len
= strtoul(ebuf
+ 1, NULL
, 16);
557 BX_INFO(("addr %Lx len %x", addr
, len
));
559 access_linear(addr
, len
, BX_READ
, mem
);
560 mem2hex((char *)mem
, obuf
, len
);
568 unsigned long long value
;
571 reg
= strtoul(&buffer
[1], &ebuf
, 16);
573 value
= read_little_endian_hex(ebuf
);
575 BX_INFO(("reg %d set to %Lx", reg
, value
));
576 #if BX_SUPPORT_X86_64 == 0
613 BX_CPU_THIS_PTR
invalidate_prefetch_q();
688 BX_CPU_THIS_PTR
invalidate_prefetch_q();
701 #if BX_SUPPORT_X86_64 == 0
710 if (last_stop_reason
== GDBSTUB_EXECUTION_BREAKPOINT
)
712 registers
[8] = EIP
+ 1;
718 registers
[9] = BX_CPU_THIS_PTR
read_eflags();
720 BX_CPU_THIS_PTR sregs
[BX_SEG_REG_CS
].selector
.value
;
722 BX_CPU_THIS_PTR sregs
[BX_SEG_REG_SS
].selector
.value
;
724 BX_CPU_THIS_PTR sregs
[BX_SEG_REG_DS
].selector
.value
;
726 BX_CPU_THIS_PTR sregs
[BX_SEG_REG_ES
].selector
.value
;
728 BX_CPU_THIS_PTR sregs
[BX_SEG_REG_FS
].selector
.value
;
730 BX_CPU_THIS_PTR sregs
[BX_SEG_REG_GS
].selector
.value
;
731 mem2hex((char *)registers
, obuf
, NUMREGSBYTES
);
733 #define PUTREG(buf, val, len) do { \
735 (buf) = mem2hex((char*)&u, (buf), (len)); \
757 if (last_stop_reason
== GDBSTUB_EXECUTION_BREAKPOINT
)
762 PUTREG(buf
, BX_CPU_THIS_PTR
read_eflags(), 4);
763 PUTREG(buf
, BX_CPU_THIS_PTR sregs
[BX_SEG_REG_CS
].selector
.value
, 4);
764 PUTREG(buf
, BX_CPU_THIS_PTR sregs
[BX_SEG_REG_SS
].selector
.value
, 4);
765 PUTREG(buf
, BX_CPU_THIS_PTR sregs
[BX_SEG_REG_DS
].selector
.value
, 4);
766 PUTREG(buf
, BX_CPU_THIS_PTR sregs
[BX_SEG_REG_ES
].selector
.value
, 4);
767 PUTREG(buf
, BX_CPU_THIS_PTR sregs
[BX_SEG_REG_FS
].selector
.value
, 4);
768 PUTREG(buf
, BX_CPU_THIS_PTR sregs
[BX_SEG_REG_GS
].selector
.value
, 4);
774 sprintf(obuf
, "S%02x", SIGTRAP
);
779 if (buffer
[1] == 'c')
781 continue_thread
= strtol(&buffer
[2], NULL
, 16);
784 else if (buffer
[1] == 'g')
786 other_thread
= strtol(&buffer
[2], NULL
, 16);
796 if (buffer
[1] == 'C')
798 sprintf(obuf
,"%Lx", (Bit64u
)1);
801 else if (strncmp(&buffer
[1], "Offsets", strlen("Offsets")) == 0)
803 sprintf(obuf
, "Text=%x;Data=%x;Bss=%x",
804 SIM
->get_param_num("text_base", gdbstub_list
)->get(),
805 SIM
->get_param_num("data_base", gdbstub_list
)->get(),
806 SIM
->get_param_num("bss_base", gdbstub_list
)->get());
809 else if (strncmp(&buffer
[1], "Supported", strlen("Supported")) == 0)
820 do_breakpoint(1, buffer
+1);
823 do_breakpoint(0, buffer
+1);
826 BX_PANIC(("Debugger asked us to quit"));
836 static void wait_for_connect(int portn
)
838 struct sockaddr_in sockaddr
;
839 socklen_t sockaddr_len
;
840 struct protoent
*protoent
;
844 listen_socket_fd
= socket(PF_INET
, SOCK_STREAM
, 0);
845 if (listen_socket_fd
== -1)
847 BX_PANIC(("Failed to create socket"));
851 /* Allow rapid reuse of this port */
854 r
= setsockopt(listen_socket_fd
, SOL_SOCKET
, SO_REUSEADDR
, (const char *)&opt
, sizeof(opt
));
856 r
= setsockopt(listen_socket_fd
, SOL_SOCKET
, SO_REUSEADDR
, &opt
, sizeof(opt
));
860 BX_INFO(("setsockopt(SO_REUSEADDR) failed"));
863 memset (&sockaddr
, '\000', sizeof sockaddr
);
864 #if BX_HAVE_SOCKADDR_IN_SIN_LEN
865 // if you don't have sin_len change that to #if 0. This is the subject of
866 // bug [ 626840 ] no 'sin_len' in 'struct sockaddr_in'.
867 sockaddr
.sin_len
= sizeof sockaddr
;
869 sockaddr
.sin_family
= AF_INET
;
870 sockaddr
.sin_port
= htons(portn
);
871 sockaddr
.sin_addr
.s_addr
= htonl(INADDR_ANY
);
873 r
= bind(listen_socket_fd
, (struct sockaddr
*)&sockaddr
, sizeof(sockaddr
));
876 BX_PANIC(("Failed to bind socket"));
879 r
= listen(listen_socket_fd
, 0);
882 BX_PANIC(("Failed to listen on socket"));
885 sockaddr_len
= sizeof sockaddr
;
886 socket_fd
= accept(listen_socket_fd
, (struct sockaddr
*)&sockaddr
, &sockaddr_len
);
889 BX_PANIC(("Failed to accept on socket"));
891 close(listen_socket_fd
);
893 protoent
= getprotobyname ("tcp");
896 BX_INFO(("getprotobyname (\"tcp\") failed"));
900 /* Disable Nagle - allow small packets to be sent without delay. */
903 r
= setsockopt (socket_fd
, protoent
->p_proto
, TCP_NODELAY
, (const char *)&opt
, sizeof(opt
));
905 r
= setsockopt (socket_fd
, protoent
->p_proto
, TCP_NODELAY
, &opt
, sizeof(opt
));
909 BX_INFO(("setsockopt(TCP_NODELAY) failed"));
911 Bit32u ip
= sockaddr
.sin_addr
.s_addr
;
912 printf("Connected to %d.%d.%d.%d\n", ip
& 0xff, (ip
>> 8) & 0xff, (ip
>> 16) & 0xff, (ip
>> 24) & 0xff);
915 void bx_gdbstub_init(void)
917 gdbstublog
= new logfunctions();
918 gdbstublog
->put("GDBST");
919 gdbstublog
->setonoff(LOGLEV_PANIC
, ACT_FATAL
);
921 gdbstub_list
= (bx_list_c
*) SIM
->get_param(BXPN_GDBSTUB
);
922 int portn
= SIM
->get_param_num("port", gdbstub_list
)->get();
926 WSAStartup(2, &wsaData
);
929 /* Wait for connect */
930 printf("Waiting for gdb connection on port %d\n", portn
);
931 wait_for_connect(portn
);
933 /* Do debugger command loop */