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