Commit | Line | Data |
---|---|---|
e20520b8 SG |
1 | /* Remote utility routines for the remote server for GDB. |
2 | Copyright (C) 1986, 1989, 1993 Free Software Foundation, Inc. | |
3 | ||
4 | This file is part of GDB. | |
5 | ||
6 | This program is free software; you can redistribute it and/or modify | |
7 | it under the terms of the GNU General Public License as published by | |
8 | the Free Software Foundation; either version 2 of the License, or | |
9 | (at your option) any later version. | |
10 | ||
11 | This program 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 | |
14 | GNU General Public License for more details. | |
15 | ||
16 | You should have received a copy of the GNU General Public License | |
17 | along with this program; if not, write to the Free Software | |
d1732185 | 18 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ |
e20520b8 | 19 | |
d1732185 MS |
20 | #include "server.h" |
21 | #include "terminal.h" | |
e20520b8 | 22 | #include <stdio.h> |
d1732185 | 23 | #include <string.h> |
e20520b8 | 24 | #include <sys/ioctl.h> |
e20520b8 | 25 | #include <sys/file.h> |
38dc5e12 | 26 | #include <netinet/in.h> |
38dc5e12 | 27 | #include <sys/socket.h> |
d1732185 | 28 | #include <netdb.h> |
38dc5e12 | 29 | #include <netinet/tcp.h> |
d1732185 MS |
30 | #include <sys/ioctl.h> |
31 | #include <signal.h> | |
32 | #include <fcntl.h> | |
e20520b8 | 33 | |
d1732185 | 34 | int remote_debug = 1; |
e20520b8 | 35 | |
d1732185 | 36 | static int remote_desc; |
e20520b8 SG |
37 | |
38 | /* Open a connection to a remote debugger. | |
39 | NAME is the filename used for communication. */ | |
40 | ||
41 | void | |
d1732185 | 42 | remote_open (name) |
e20520b8 | 43 | char *name; |
e20520b8 | 44 | { |
d1732185 | 45 | int save_fcntl_flags; |
e20520b8 | 46 | |
38dc5e12 SG |
47 | if (!strchr (name, ':')) |
48 | { | |
49 | remote_desc = open (name, O_RDWR); | |
50 | if (remote_desc < 0) | |
51 | perror_with_name ("Could not open remote device"); | |
52 | ||
d1732185 MS |
53 | #ifdef HAVE_TERMIOS |
54 | { | |
55 | struct termios termios; | |
56 | tcgetattr(remote_desc, &termios); | |
57 | ||
58 | termios.c_iflag = 0; | |
59 | termios.c_oflag = 0; | |
60 | termios.c_lflag = 0; | |
61 | termios.c_cflag &= ~(CSIZE|PARENB); | |
62 | termios.c_cflag |= CLOCAL | CS8; | |
63 | termios.c_cc[VMIN] = 0; | |
64 | termios.c_cc[VTIME] = 0; | |
65 | ||
66 | tcsetattr(remote_desc, TCSANOW, &termios); | |
67 | } | |
68 | #endif | |
69 | ||
70 | #ifdef HAVE_TERMIO | |
71 | { | |
72 | struct termio termio; | |
73 | ioctl (remote_desc, TCGETA, &termio); | |
74 | ||
75 | termio.c_iflag = 0; | |
76 | termio.c_oflag = 0; | |
77 | termio.c_lflag = 0; | |
78 | termio.c_cflag &= ~(CSIZE|PARENB); | |
79 | termio.c_cflag |= CLOCAL | CS8; | |
80 | termio.c_cc[VMIN] = 0; | |
81 | termio.c_cc[VTIME] = 0; | |
82 | ||
83 | ioctl (remote_desc, TCSETA, &termio); | |
84 | } | |
85 | #endif | |
86 | ||
87 | #ifdef HAVE_SGTTY | |
88 | { | |
89 | struct sgttyb sg; | |
90 | ||
91 | ioctl (remote_desc, TIOCGETP, &sg); | |
92 | sg.sg_flags = RAW; | |
93 | ioctl (remote_desc, TIOCSETP, &sg); | |
94 | } | |
95 | #endif | |
96 | ||
97 | ||
38dc5e12 SG |
98 | } |
99 | else | |
100 | { | |
101 | char *port_str; | |
102 | int port; | |
103 | struct sockaddr_in sockaddr; | |
104 | int tmp; | |
d1732185 MS |
105 | struct protoent *protoent; |
106 | int tmp_desc; | |
38dc5e12 SG |
107 | |
108 | port_str = strchr (name, ':'); | |
109 | ||
110 | port = atoi (port_str + 1); | |
111 | ||
d1732185 MS |
112 | tmp_desc = socket (PF_INET, SOCK_STREAM, 0); |
113 | if (tmp_desc < 0) | |
38dc5e12 SG |
114 | perror_with_name ("Can't open socket"); |
115 | ||
116 | /* Allow rapid reuse of this port. */ | |
117 | tmp = 1; | |
d1732185 | 118 | setsockopt (tmp_desc, SOL_SOCKET, SO_REUSEADDR, (char *)&tmp, |
38dc5e12 SG |
119 | sizeof(tmp)); |
120 | ||
38dc5e12 SG |
121 | sockaddr.sin_family = PF_INET; |
122 | sockaddr.sin_port = htons(port); | |
123 | sockaddr.sin_addr.s_addr = INADDR_ANY; | |
e20520b8 | 124 | |
d1732185 MS |
125 | if (bind (tmp_desc, (struct sockaddr *)&sockaddr, sizeof (sockaddr)) |
126 | || listen (tmp_desc, 1)) | |
38dc5e12 SG |
127 | perror_with_name ("Can't bind address"); |
128 | ||
129 | tmp = sizeof (sockaddr); | |
d1732185 | 130 | remote_desc = accept (tmp_desc, (struct sockaddr *)&sockaddr, &tmp); |
38dc5e12 SG |
131 | if (remote_desc == -1) |
132 | perror_with_name ("Accept failed"); | |
133 | ||
d1732185 MS |
134 | protoent = getprotobyname ("tcp"); |
135 | if (!protoent) | |
136 | perror_with_name ("getprotobyname"); | |
137 | ||
138 | /* Enable TCP keep alive process. */ | |
38dc5e12 | 139 | tmp = 1; |
d1732185 MS |
140 | setsockopt (tmp_desc, SOL_SOCKET, SO_KEEPALIVE, (char *)&tmp, sizeof(tmp)); |
141 | ||
142 | /* Tell TCP not to delay small packets. This greatly speeds up | |
143 | interactive response. */ | |
144 | tmp = 1; | |
145 | setsockopt (remote_desc, protoent->p_proto, TCP_NODELAY, | |
146 | (char *)&tmp, sizeof(tmp)); | |
147 | ||
148 | close (tmp_desc); /* No longer need this */ | |
149 | ||
150 | signal (SIGPIPE, SIG_IGN); /* If we don't do this, then gdbserver simply | |
151 | exits when the remote side dies. */ | |
38dc5e12 | 152 | } |
e20520b8 | 153 | |
d1732185 MS |
154 | #if defined(F_SETFL) && defined (FASYNC) |
155 | save_fcntl_flags = fcntl (remote_desc, F_GETFL, 0); | |
156 | fcntl (remote_desc, F_SETFL, save_fcntl_flags | FASYNC); | |
157 | disable_async_io (); | |
158 | #endif /* FASYNC */ | |
e20520b8 | 159 | fprintf (stderr, "Remote debugging using %s\n", name); |
d1732185 MS |
160 | } |
161 | ||
162 | void | |
163 | remote_close() | |
164 | { | |
165 | close (remote_desc); | |
e20520b8 SG |
166 | } |
167 | ||
168 | /* Convert hex digit A to a number. */ | |
169 | ||
170 | static int | |
171 | fromhex (a) | |
172 | int a; | |
173 | { | |
174 | if (a >= '0' && a <= '9') | |
175 | return a - '0'; | |
176 | else if (a >= 'a' && a <= 'f') | |
177 | return a - 'a' + 10; | |
178 | else | |
179 | error ("Reply contains invalid hex digit"); | |
180 | } | |
181 | ||
182 | /* Convert number NIB to a hex digit. */ | |
183 | ||
184 | static int | |
185 | tohex (nib) | |
186 | int nib; | |
187 | { | |
188 | if (nib < 10) | |
189 | return '0' + nib; | |
190 | else | |
191 | return 'a' + nib - 10; | |
192 | } | |
193 | ||
e20520b8 | 194 | /* Send a packet to the remote machine, with error checking. |
d1732185 | 195 | The data of the packet is in BUF. Returns >= 0 on success, -1 otherwise. */ |
e20520b8 | 196 | |
d1732185 | 197 | int |
e20520b8 SG |
198 | putpkt (buf) |
199 | char *buf; | |
200 | { | |
201 | int i; | |
202 | unsigned char csum = 0; | |
203 | char buf2[2000]; | |
204 | char buf3[1]; | |
205 | int cnt = strlen (buf); | |
206 | char *p; | |
207 | ||
208 | /* Copy the packet into buffer BUF2, encapsulating it | |
209 | and giving it a checksum. */ | |
210 | ||
211 | p = buf2; | |
212 | *p++ = '$'; | |
213 | ||
214 | for (i = 0; i < cnt; i++) | |
215 | { | |
216 | csum += buf[i]; | |
217 | *p++ = buf[i]; | |
218 | } | |
219 | *p++ = '#'; | |
220 | *p++ = tohex ((csum >> 4) & 0xf); | |
221 | *p++ = tohex (csum & 0xf); | |
222 | ||
d1732185 MS |
223 | *p = '\0'; |
224 | ||
e20520b8 SG |
225 | /* Send it over and over until we get a positive ack. */ |
226 | ||
227 | do | |
228 | { | |
d1732185 MS |
229 | int cc; |
230 | ||
231 | if (write (remote_desc, buf2, p - buf2) != p - buf2) | |
232 | { | |
233 | perror ("putpkt(write)"); | |
234 | return -1; | |
235 | } | |
236 | ||
237 | if (remote_debug) | |
238 | printf ("putpkt (\"%s\"); [looking for ack]\n", buf2); | |
239 | cc = read (remote_desc, buf3, 1); | |
240 | if (remote_debug) | |
241 | printf ("[received '%c' (0x%x)]\n", buf3[0], buf3[0]); | |
242 | if (cc <= 0) | |
243 | { | |
244 | if (cc == 0) | |
245 | fprintf (stderr, "putpkt(read): Got EOF\n"); | |
246 | else | |
247 | perror ("putpkt(read)"); | |
248 | ||
249 | return -1; | |
250 | } | |
e20520b8 SG |
251 | } |
252 | while (buf3[0] != '+'); | |
d1732185 MS |
253 | |
254 | return 1; /* Success! */ | |
255 | } | |
256 | ||
257 | /* Come here when we get an input interrupt from the remote side. This | |
258 | interrupt should only be active while we are waiting for the child to do | |
259 | something. About the only thing that should come through is a ^C, which | |
260 | will cause us to send a SIGINT to the child. */ | |
261 | ||
262 | static void | |
263 | input_interrupt() | |
264 | { | |
265 | int cc; | |
266 | char c; | |
267 | ||
268 | cc = read (remote_desc, &c, 1); | |
269 | ||
270 | if (cc != 1 || c != '\003') | |
271 | { | |
272 | fprintf(stderr, "input_interrupt, cc = %d c = %d\n", cc, c); | |
273 | return; | |
274 | } | |
275 | ||
276 | kill (inferior_pid, SIGINT); | |
277 | } | |
278 | ||
279 | void | |
280 | enable_async_io() | |
281 | { | |
282 | signal (SIGIO, input_interrupt); | |
e20520b8 SG |
283 | } |
284 | ||
d1732185 MS |
285 | void |
286 | disable_async_io() | |
287 | { | |
288 | signal (SIGIO, SIG_IGN); | |
289 | } | |
290 | ||
291 | /* Returns next char from remote GDB. -1 if error. */ | |
292 | ||
e20520b8 SG |
293 | static int |
294 | readchar () | |
295 | { | |
38dc5e12 SG |
296 | static char buf[BUFSIZ]; |
297 | static int bufcnt = 0; | |
298 | static char *bufp; | |
299 | ||
300 | if (bufcnt-- > 0) | |
301 | return *bufp++ & 0x7f; | |
302 | ||
303 | bufcnt = read (remote_desc, buf, sizeof (buf)); | |
304 | ||
305 | if (bufcnt <= 0) | |
306 | { | |
d1732185 MS |
307 | if (bufcnt == 0) |
308 | fprintf (stderr, "readchar: Got EOF\n"); | |
309 | else | |
310 | perror ("readchar"); | |
311 | ||
312 | return -1; | |
38dc5e12 SG |
313 | } |
314 | ||
315 | bufp = buf; | |
316 | bufcnt--; | |
317 | return *bufp++ & 0x7f; | |
e20520b8 SG |
318 | } |
319 | ||
320 | /* Read a packet from the remote machine, with error checking, | |
d1732185 | 321 | and store it in BUF. Returns length of packet, or negative if error. */ |
e20520b8 | 322 | |
d1732185 | 323 | int |
e20520b8 SG |
324 | getpkt (buf) |
325 | char *buf; | |
326 | { | |
327 | char *bp; | |
38dc5e12 SG |
328 | unsigned char csum, c1, c2; |
329 | int c; | |
e20520b8 SG |
330 | |
331 | while (1) | |
332 | { | |
333 | csum = 0; | |
38dc5e12 | 334 | |
d1732185 MS |
335 | while (1) |
336 | { | |
337 | c = readchar (); | |
338 | if (c == '$') | |
339 | break; | |
340 | if (remote_debug) | |
341 | printf ("[getpkt: discarding char '%c']\n", c); | |
342 | if (c < 0) | |
343 | return -1; | |
344 | } | |
e20520b8 SG |
345 | |
346 | bp = buf; | |
347 | while (1) | |
348 | { | |
349 | c = readchar (); | |
d1732185 MS |
350 | if (c < 0) |
351 | return -1; | |
e20520b8 SG |
352 | if (c == '#') |
353 | break; | |
354 | *bp++ = c; | |
355 | csum += c; | |
356 | } | |
357 | *bp = 0; | |
358 | ||
359 | c1 = fromhex (readchar ()); | |
360 | c2 = fromhex (readchar ()); | |
d1732185 | 361 | |
e20520b8 SG |
362 | if (csum == (c1 << 4) + c2) |
363 | break; | |
364 | ||
365 | fprintf (stderr, "Bad checksum, sentsum=0x%x, csum=0x%x, buf=%s\n", | |
366 | (c1 << 4) + c2, csum, buf); | |
367 | write (remote_desc, "-", 1); | |
368 | } | |
369 | ||
d1732185 MS |
370 | if (remote_debug) |
371 | printf ("getpkt (\"%s\"); [sending ack] \n", buf); | |
372 | ||
e20520b8 | 373 | write (remote_desc, "+", 1); |
d1732185 MS |
374 | |
375 | if (remote_debug) | |
376 | printf ("[sent ack]\n"); | |
377 | return bp - buf; | |
e20520b8 SG |
378 | } |
379 | ||
380 | void | |
381 | write_ok (buf) | |
382 | char *buf; | |
383 | { | |
384 | buf[0] = 'O'; | |
d1732185 | 385 | buf[1] = 'K'; |
e20520b8 SG |
386 | buf[2] = '\0'; |
387 | } | |
388 | ||
389 | void | |
390 | write_enn (buf) | |
391 | char *buf; | |
392 | { | |
393 | buf[0] = 'E'; | |
394 | buf[1] = 'N'; | |
395 | buf[2] = 'N'; | |
396 | buf[3] = '\0'; | |
397 | } | |
398 | ||
399 | void | |
400 | convert_int_to_ascii (from, to, n) | |
401 | char *from, *to; | |
402 | int n; | |
403 | { | |
404 | int nib; | |
405 | char ch; | |
406 | while (n--) | |
407 | { | |
408 | ch = *from++; | |
409 | nib = ((ch & 0xf0) >> 4) & 0x0f; | |
410 | *to++ = tohex (nib); | |
411 | nib = ch & 0x0f; | |
412 | *to++ = tohex (nib); | |
413 | } | |
414 | *to++ = 0; | |
415 | } | |
416 | ||
417 | ||
418 | void | |
419 | convert_ascii_to_int (from, to, n) | |
420 | char *from, *to; | |
421 | int n; | |
422 | { | |
423 | int nib1, nib2; | |
424 | while (n--) | |
425 | { | |
426 | nib1 = fromhex (*from++); | |
427 | nib2 = fromhex (*from++); | |
428 | *to++ = (((nib1 & 0x0f) << 4) & 0xf0) | (nib2 & 0x0f); | |
429 | } | |
430 | } | |
431 | ||
432 | static char * | |
433 | outreg(regno, buf) | |
434 | int regno; | |
435 | char *buf; | |
436 | { | |
437 | extern char registers[]; | |
d1732185 | 438 | int regsize = REGISTER_RAW_SIZE (regno); |
e20520b8 SG |
439 | |
440 | *buf++ = tohex (regno >> 4); | |
441 | *buf++ = tohex (regno & 0xf); | |
442 | *buf++ = ':'; | |
d1732185 MS |
443 | convert_int_to_ascii (®isters[REGISTER_BYTE (regno)], buf, regsize); |
444 | buf += 2 * regsize; | |
e20520b8 SG |
445 | *buf++ = ';'; |
446 | ||
447 | return buf; | |
448 | } | |
449 | ||
450 | void | |
d1732185 MS |
451 | prepare_resume_reply (buf, status, signo) |
452 | char *buf; | |
453 | char status; | |
454 | unsigned char signo; | |
e20520b8 SG |
455 | { |
456 | int nib; | |
e20520b8 | 457 | |
d1732185 | 458 | *buf++ = status; |
e20520b8 | 459 | |
d1732185 MS |
460 | /* FIXME! Should be converting this signal number (numbered |
461 | according to the signal numbering of the system we are running on) | |
462 | to the signal numbers used by the gdb protocol (see enum target_signal | |
463 | in gdb/target.h). */ | |
464 | nib = ((signo & 0xf0) >> 4); | |
e20520b8 | 465 | *buf++ = tohex (nib); |
d1732185 | 466 | nib = signo & 0x0f; |
e20520b8 SG |
467 | *buf++ = tohex (nib); |
468 | ||
d1732185 MS |
469 | if (status == 'T') |
470 | { | |
471 | buf = outreg (PC_REGNUM, buf); | |
472 | buf = outreg (FP_REGNUM, buf); | |
473 | buf = outreg (SP_REGNUM, buf); | |
e20520b8 | 474 | #ifdef NPC_REGNUM |
d1732185 | 475 | buf = outreg (NPC_REGNUM, buf); |
e20520b8 SG |
476 | #endif |
477 | #ifdef O7_REGNUM | |
d1732185 | 478 | buf = outreg (O7_REGNUM, buf); |
e20520b8 SG |
479 | #endif |
480 | ||
d1732185 MS |
481 | /* If the debugger hasn't used any thread features, don't burden it with |
482 | threads. If we didn't check this, GDB 4.13 and older would choke. */ | |
483 | if (cont_thread != 0) | |
484 | { | |
485 | if (old_thread_from_wait != thread_from_wait) | |
486 | { | |
487 | sprintf (buf, "thread:%x;", thread_from_wait); | |
488 | buf += strlen (buf); | |
489 | old_thread_from_wait = thread_from_wait; | |
490 | } | |
491 | } | |
492 | } | |
493 | /* For W and X, we're done. */ | |
e20520b8 SG |
494 | *buf++ = 0; |
495 | } | |
496 | ||
497 | void | |
498 | decode_m_packet (from, mem_addr_ptr, len_ptr) | |
499 | char *from; | |
d1732185 MS |
500 | CORE_ADDR *mem_addr_ptr; |
501 | unsigned int *len_ptr; | |
e20520b8 SG |
502 | { |
503 | int i = 0, j = 0; | |
504 | char ch; | |
505 | *mem_addr_ptr = *len_ptr = 0; | |
506 | ||
507 | while ((ch = from[i++]) != ',') | |
508 | { | |
509 | *mem_addr_ptr = *mem_addr_ptr << 4; | |
510 | *mem_addr_ptr |= fromhex (ch) & 0x0f; | |
511 | } | |
512 | ||
513 | for (j = 0; j < 4; j++) | |
514 | { | |
515 | if ((ch = from[i++]) == 0) | |
516 | break; | |
517 | *len_ptr = *len_ptr << 4; | |
518 | *len_ptr |= fromhex (ch) & 0x0f; | |
519 | } | |
520 | } | |
521 | ||
522 | void | |
523 | decode_M_packet (from, mem_addr_ptr, len_ptr, to) | |
524 | char *from, *to; | |
d1732185 MS |
525 | CORE_ADDR *mem_addr_ptr; |
526 | unsigned int *len_ptr; | |
e20520b8 | 527 | { |
d1732185 | 528 | int i = 0; |
e20520b8 SG |
529 | char ch; |
530 | *mem_addr_ptr = *len_ptr = 0; | |
531 | ||
532 | while ((ch = from[i++]) != ',') | |
533 | { | |
534 | *mem_addr_ptr = *mem_addr_ptr << 4; | |
535 | *mem_addr_ptr |= fromhex (ch) & 0x0f; | |
536 | } | |
537 | ||
538 | while ((ch = from[i++]) != ':') | |
539 | { | |
540 | *len_ptr = *len_ptr << 4; | |
541 | *len_ptr |= fromhex (ch) & 0x0f; | |
542 | } | |
543 | ||
544 | convert_ascii_to_int (&from[i++], to, *len_ptr); | |
545 | } |