Implement IPv6 support for GDB/gdbserver
[deliverable/binutils-gdb.git] / gdb / gdbserver / gdbreplay.c
CommitLineData
c906108c 1/* Replay a remote debug session logfile for GDB.
e2882c85 2 Copyright (C) 1996-2018 Free Software Foundation, Inc.
c906108c
SS
3 Written by Fred Fish (fnf@cygnus.com) from pieces of gdbserver.
4
c5aa993b 5 This file is part of GDB.
c906108c 6
c5aa993b
JM
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
a9762ec7 9 the Free Software Foundation; either version 3 of the License, or
c5aa993b 10 (at your option) any later version.
c906108c 11
c5aa993b
JM
12 This program 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
15 GNU General Public License for more details.
c906108c 16
c5aa993b 17 You should have received a copy of the GNU General Public License
a9762ec7 18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
c906108c 19
03349c93 20#include "common-defs.h"
01208463 21#include "version.h"
406b1477 22
68070c10 23#if HAVE_SYS_FILE_H
c906108c 24#include <sys/file.h>
68070c10
PA
25#endif
26#if HAVE_SIGNAL_H
c906108c 27#include <signal.h>
68070c10 28#endif
c906108c 29#include <ctype.h>
68070c10 30#if HAVE_FCNTL_H
c906108c 31#include <fcntl.h>
68070c10 32#endif
82e0fd98 33#include <unistd.h>
9eb1356e
PA
34#ifdef HAVE_NETINET_IN_H
35#include <netinet/in.h>
36#endif
37#ifdef HAVE_SYS_SOCKET_H
38#include <sys/socket.h>
39#endif
b80864fb
DJ
40#if HAVE_NETDB_H
41#include <netdb.h>
42#endif
43#if HAVE_NETINET_TCP_H
44#include <netinet/tcp.h>
45#endif
9c232dda 46
9eb1356e
PA
47#if USE_WIN32API
48#include <winsock2.h>
c7ab0aef 49#include <wspiapi.h>
9eb1356e 50#endif
c906108c 51
c7ab0aef
SDJ
52#include "netstuff.h"
53
f450004a
DJ
54#ifndef HAVE_SOCKLEN_T
55typedef int socklen_t;
56#endif
57
c906108c
SS
58/* Sort of a hack... */
59#define EOL (EOF - 1)
60
61static int remote_desc;
62
68070c10
PA
63#ifdef __MINGW32CE__
64
65#ifndef COUNTOF
66#define COUNTOF(STR) (sizeof (STR) / sizeof ((STR)[0]))
67#endif
68
69#define errno (GetLastError ())
70
71char *
72strerror (DWORD error)
73{
74 static char buf[1024];
75 WCHAR *msgbuf;
76 DWORD lasterr = GetLastError ();
77 DWORD chars = FormatMessageW (FORMAT_MESSAGE_FROM_SYSTEM
78 | FORMAT_MESSAGE_ALLOCATE_BUFFER,
79 NULL,
80 error,
81 0, /* Default language */
82 (LPVOID)&msgbuf,
83 0,
84 NULL);
85 if (chars != 0)
86 {
87 /* If there is an \r\n appended, zap it. */
88 if (chars >= 2
89 && msgbuf[chars - 2] == '\r'
90 && msgbuf[chars - 1] == '\n')
91 {
92 chars -= 2;
93 msgbuf[chars] = 0;
94 }
95
96 if (chars > ((COUNTOF (buf)) - 1))
97 {
98 chars = COUNTOF (buf) - 1;
99 msgbuf [chars] = 0;
100 }
101
102 wcstombs (buf, msgbuf, chars + 1);
103 LocalFree (msgbuf);
104 }
105 else
106 sprintf (buf, "unknown win32 error (%ld)", error);
107
108 SetLastError (lasterr);
109 return buf;
110}
111
112#endif /* __MINGW32CE__ */
113
c906108c 114static void
a121b7c1 115sync_error (FILE *fp, const char *desc, int expect, int got)
c906108c
SS
116{
117 fprintf (stderr, "\n%s\n", desc);
118 fprintf (stderr, "At logfile offset %ld, expected '0x%x' got '0x%x'\n",
119 ftell (fp), expect, got);
120 fflush (stderr);
121 exit (1);
122}
123
e581f2b4
PA
124static void
125remote_error (const char *desc)
126{
127 fprintf (stderr, "\n%s\n", desc);
128 fflush (stderr);
129 exit (1);
130}
131
82e0fd98 132static void
fba45db2 133remote_close (void)
c906108c 134{
b80864fb
DJ
135#ifdef USE_WIN32API
136 closesocket (remote_desc);
137#else
c906108c 138 close (remote_desc);
b80864fb 139#endif
c906108c
SS
140}
141
142/* Open a connection to a remote debugger.
143 NAME is the filename used for communication. */
144
82e0fd98 145static void
fba45db2 146remote_open (char *name)
c906108c 147{
c7ab0aef
SDJ
148 char *last_colon = strrchr (name, ':');
149
150 if (last_colon == NULL)
c906108c
SS
151 {
152 fprintf (stderr, "%s: Must specify tcp connection as host:addr\n", name);
153 fflush (stderr);
154 exit (1);
155 }
c7ab0aef 156
b80864fb 157#ifdef USE_WIN32API
c7ab0aef 158 static int winsock_initialized;
b80864fb 159#endif
c7ab0aef
SDJ
160 char *port_str;
161 int tmp;
162 int tmp_desc;
163 struct addrinfo hint;
164 struct addrinfo *ainfo;
c906108c 165
c7ab0aef
SDJ
166 memset (&hint, 0, sizeof (hint));
167 /* Assume no prefix will be passed, therefore we should use
168 AF_UNSPEC. */
169 hint.ai_family = AF_UNSPEC;
170 hint.ai_socktype = SOCK_STREAM;
171 hint.ai_protocol = IPPROTO_TCP;
c906108c 172
c7ab0aef
SDJ
173 parsed_connection_spec parsed = parse_connection_spec (name, &hint);
174
175 if (parsed.port_str.empty ())
176 error (_("Missing port on hostname '%s'"), name);
c906108c 177
b80864fb 178#ifdef USE_WIN32API
c7ab0aef
SDJ
179 if (!winsock_initialized)
180 {
181 WSADATA wsad;
b80864fb 182
c7ab0aef
SDJ
183 WSAStartup (MAKEWORD (1, 0), &wsad);
184 winsock_initialized = 1;
185 }
b80864fb
DJ
186#endif
187
c7ab0aef
SDJ
188 int r = getaddrinfo (parsed.host_str.c_str (), parsed.port_str.c_str (),
189 &hint, &ainfo);
c906108c 190
c7ab0aef
SDJ
191 if (r != 0)
192 {
193 fprintf (stderr, "%s:%s: cannot resolve name: %s\n",
194 parsed.host_str.c_str (), parsed.port_str.c_str (),
195 gai_strerror (r));
196 fflush (stderr);
197 exit (1);
198 }
199
200 scoped_free_addrinfo free_ainfo (ainfo);
201
202 struct addrinfo *p;
c906108c 203
c7ab0aef
SDJ
204 for (p = ainfo; p != NULL; p = p->ai_next)
205 {
206 tmp_desc = socket (p->ai_family, p->ai_socktype, p->ai_protocol);
207
208 if (tmp_desc >= 0)
209 break;
210 }
211
212 if (p == NULL)
213 perror_with_name ("Cannot open socket");
214
215 /* Allow rapid reuse of this port. */
216 tmp = 1;
217 setsockopt (tmp_desc, SOL_SOCKET, SO_REUSEADDR, (char *) &tmp,
218 sizeof (tmp));
219
220 switch (p->ai_family)
221 {
222 case AF_INET:
223 ((struct sockaddr_in *) p->ai_addr)->sin_addr.s_addr = INADDR_ANY;
224 break;
225 case AF_INET6:
226 ((struct sockaddr_in6 *) p->ai_addr)->sin6_addr = in6addr_any;
227 break;
228 default:
229 fprintf (stderr, "Invalid 'ai_family' %d\n", p->ai_family);
230 exit (1);
231 }
c906108c 232
c7ab0aef
SDJ
233 if (bind (tmp_desc, p->ai_addr, p->ai_addrlen) != 0)
234 perror_with_name ("Can't bind address");
235
236 if (p->ai_socktype == SOCK_DGRAM)
237 remote_desc = tmp_desc;
238 else
239 {
240 struct sockaddr_storage sockaddr;
241 socklen_t sockaddrsize = sizeof (sockaddr);
242 char orig_host[GDB_NI_MAX_ADDR], orig_port[GDB_NI_MAX_PORT];
243
244 if (listen (tmp_desc, 1) != 0)
245 perror_with_name ("Can't listen on socket");
246
247 remote_desc = accept (tmp_desc, (struct sockaddr *) &sockaddr,
248 &sockaddrsize);
c906108c 249
c906108c
SS
250 if (remote_desc == -1)
251 perror_with_name ("Accept failed");
252
c906108c
SS
253 /* Enable TCP keep alive process. */
254 tmp = 1;
493e2a69
MS
255 setsockopt (tmp_desc, SOL_SOCKET, SO_KEEPALIVE,
256 (char *) &tmp, sizeof (tmp));
c906108c
SS
257
258 /* Tell TCP not to delay small packets. This greatly speeds up
1b3f6016 259 interactive response. */
c906108c 260 tmp = 1;
373fe97f 261 setsockopt (remote_desc, IPPROTO_TCP, TCP_NODELAY,
c5aa993b 262 (char *) &tmp, sizeof (tmp));
c906108c 263
c7ab0aef
SDJ
264 if (getnameinfo ((struct sockaddr *) &sockaddr, sockaddrsize,
265 orig_host, sizeof (orig_host),
266 orig_port, sizeof (orig_port),
267 NI_NUMERICHOST | NI_NUMERICSERV) == 0)
268 {
269 fprintf (stderr, "Remote debugging from host %s, port %s\n",
270 orig_host, orig_port);
271 fflush (stderr);
272 }
273
b80864fb
DJ
274#ifndef USE_WIN32API
275 close (tmp_desc); /* No longer need this */
276
493e2a69
MS
277 signal (SIGPIPE, SIG_IGN); /* If we don't do this, then
278 gdbreplay simply exits when
279 the remote side dies. */
b80864fb
DJ
280#else
281 closesocket (tmp_desc); /* No longer need this */
282#endif
c906108c
SS
283 }
284
b80864fb 285#if defined(F_SETFL) && defined (FASYNC)
c906108c 286 fcntl (remote_desc, F_SETFL, FASYNC);
b80864fb 287#endif
c906108c
SS
288
289 fprintf (stderr, "Replay logfile using %s\n", name);
290 fflush (stderr);
291}
292
c5aa993b 293static int
909c2cda 294fromhex (int ch)
c906108c
SS
295{
296 if (ch >= '0' && ch <= '9')
297 {
298 return (ch - '0');
299 }
300 if (ch >= 'A' && ch <= 'F')
301 {
302 return (ch - 'A' + 10);
303 }
304 if (ch >= 'a' && ch <= 'f')
305 {
306 return (ch - 'a' + 10);
307 }
308 fprintf (stderr, "\nInvalid hex digit '%c'\n", ch);
309 fflush (stderr);
310 exit (1);
311}
312
313static int
fba45db2 314logchar (FILE *fp)
c906108c
SS
315{
316 int ch;
317 int ch2;
318
319 ch = fgetc (fp);
320 fputc (ch, stdout);
321 fflush (stdout);
322 switch (ch)
323 {
324 case '\n':
325 ch = EOL;
326 break;
327 case '\\':
328 ch = fgetc (fp);
329 fputc (ch, stdout);
330 fflush (stdout);
331 switch (ch)
332 {
c5aa993b
JM
333 case '\\':
334 break;
335 case 'b':
336 ch = '\b';
337 break;
338 case 'f':
339 ch = '\f';
340 break;
341 case 'n':
342 ch = '\n';
343 break;
344 case 'r':
345 ch = '\r';
346 break;
347 case 't':
348 ch = '\t';
349 break;
350 case 'v':
351 ch = '\v';
352 break;
c906108c
SS
353 case 'x':
354 ch2 = fgetc (fp);
355 fputc (ch2, stdout);
356 fflush (stdout);
909c2cda 357 ch = fromhex (ch2) << 4;
c906108c
SS
358 ch2 = fgetc (fp);
359 fputc (ch2, stdout);
360 fflush (stdout);
909c2cda 361 ch |= fromhex (ch2);
c906108c
SS
362 break;
363 default:
364 /* Treat any other char as just itself */
365 break;
366 }
367 default:
368 break;
369 }
370 return (ch);
371}
372
e581f2b4
PA
373static int
374gdbchar (int desc)
375{
376 unsigned char fromgdb;
377
378 if (read (desc, &fromgdb, 1) != 1)
379 return -1;
380 else
381 return fromgdb;
382}
383
c906108c
SS
384/* Accept input from gdb and match with chars from fp (after skipping one
385 blank) up until a \n is read from fp (which is not matched) */
386
82e0fd98 387static void
fba45db2 388expect (FILE *fp)
c906108c
SS
389{
390 int fromlog;
e581f2b4 391 int fromgdb;
c906108c
SS
392
393 if ((fromlog = logchar (fp)) != ' ')
394 {
395 sync_error (fp, "Sync error during gdb read of leading blank", ' ',
396 fromlog);
397 }
398 do
399 {
400 fromlog = logchar (fp);
401 if (fromlog == EOL)
e581f2b4
PA
402 break;
403 fromgdb = gdbchar (remote_desc);
404 if (fromgdb < 0)
405 remote_error ("Error during read from gdb");
c5aa993b
JM
406 }
407 while (fromlog == fromgdb);
e581f2b4 408
c906108c
SS
409 if (fromlog != EOL)
410 {
e581f2b4 411 sync_error (fp, "Sync error during read of gdb packet from log", fromlog,
c906108c
SS
412 fromgdb);
413 }
414}
415
416/* Play data back to gdb from fp (after skipping leading blank) up until a
417 \n is read from fp (which is discarded and not sent to gdb). */
418
82e0fd98 419static void
fba45db2 420play (FILE *fp)
c906108c
SS
421{
422 int fromlog;
423 char ch;
424
425 if ((fromlog = logchar (fp)) != ' ')
426 {
427 sync_error (fp, "Sync error skipping blank during write to gdb", ' ',
428 fromlog);
429 }
430 while ((fromlog = logchar (fp)) != EOL)
431 {
432 ch = fromlog;
e581f2b4
PA
433 if (write (remote_desc, &ch, 1) != 1)
434 remote_error ("Error during write to gdb");
c906108c
SS
435 }
436}
437
c16158bc
JM
438static void
439gdbreplay_version (void)
440{
441 printf ("GNU gdbreplay %s%s\n"
82e1e79a 442 "Copyright (C) 2018 Free Software Foundation, Inc.\n"
493e2a69
MS
443 "gdbreplay is free software, covered by "
444 "the GNU General Public License.\n"
90aa6a40 445 "This gdbreplay was configured as \"%s\"\n",
c16158bc
JM
446 PKGVERSION, version, host_name);
447}
448
449static void
450gdbreplay_usage (FILE *stream)
451{
452 fprintf (stream, "Usage:\tgdbreplay <logfile> <host:port>\n");
453 if (REPORT_BUGS_TO[0] && stream == stdout)
454 fprintf (stream, "Report bugs to \"%s\".\n", REPORT_BUGS_TO);
455}
456
03349c93
PA
457/* Main function. This is called by the real "main" function,
458 wrapped in a TRY_CATCH that handles any uncaught exceptions. */
459
460static void ATTRIBUTE_NORETURN
461captured_main (int argc, char *argv[])
c906108c
SS
462{
463 FILE *fp;
464 int ch;
465
c16158bc
JM
466 if (argc >= 2 && strcmp (argv[1], "--version") == 0)
467 {
468 gdbreplay_version ();
469 exit (0);
470 }
471 if (argc >= 2 && strcmp (argv[1], "--help") == 0)
472 {
473 gdbreplay_usage (stdout);
474 exit (0);
475 }
476
c906108c
SS
477 if (argc < 3)
478 {
c16158bc 479 gdbreplay_usage (stderr);
c906108c
SS
480 exit (1);
481 }
482 fp = fopen (argv[1], "r");
483 if (fp == NULL)
484 {
485 perror_with_name (argv[1]);
c5aa993b 486 }
c906108c
SS
487 remote_open (argv[2]);
488 while ((ch = logchar (fp)) != EOF)
489 {
490 switch (ch)
491 {
492 case 'w':
493 /* data sent from gdb to gdbreplay, accept and match it */
494 expect (fp);
495 break;
496 case 'r':
497 /* data sent from gdbreplay to gdb, play it */
498 play (fp);
499 break;
500 case 'c':
501 /* Command executed by gdb */
502 while ((ch = logchar (fp)) != EOL);
503 break;
504 }
505 }
506 remote_close ();
507 exit (0);
508}
03349c93
PA
509
510int
511main (int argc, char *argv[])
512{
513 TRY
514 {
515 captured_main (argc, argv);
516 }
517 CATCH (exception, RETURN_MASK_ALL)
518 {
519 if (exception.reason == RETURN_ERROR)
520 {
521 fflush (stdout);
522 fprintf (stderr, "%s\n", exception.message);
523 }
524
525 exit (1);
526 }
527 END_CATCH
528
529 gdb_assert_not_reached ("captured_main should never return");
530}
This page took 1.326103 seconds and 4 git commands to generate.