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