Update create-version.sh to use common/version.h
[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
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 int tmp;
161 int tmp_desc;
162 struct addrinfo hint;
163 struct addrinfo *ainfo;
c906108c 164
c7ab0aef
SDJ
165 memset (&hint, 0, sizeof (hint));
166 /* Assume no prefix will be passed, therefore we should use
167 AF_UNSPEC. */
168 hint.ai_family = AF_UNSPEC;
169 hint.ai_socktype = SOCK_STREAM;
170 hint.ai_protocol = IPPROTO_TCP;
c906108c 171
c7ab0aef
SDJ
172 parsed_connection_spec parsed = parse_connection_spec (name, &hint);
173
174 if (parsed.port_str.empty ())
175 error (_("Missing port on hostname '%s'"), name);
c906108c 176
b80864fb 177#ifdef USE_WIN32API
c7ab0aef
SDJ
178 if (!winsock_initialized)
179 {
180 WSADATA wsad;
b80864fb 181
c7ab0aef
SDJ
182 WSAStartup (MAKEWORD (1, 0), &wsad);
183 winsock_initialized = 1;
184 }
b80864fb
DJ
185#endif
186
c7ab0aef
SDJ
187 int r = getaddrinfo (parsed.host_str.c_str (), parsed.port_str.c_str (),
188 &hint, &ainfo);
c906108c 189
c7ab0aef
SDJ
190 if (r != 0)
191 {
192 fprintf (stderr, "%s:%s: cannot resolve name: %s\n",
193 parsed.host_str.c_str (), parsed.port_str.c_str (),
194 gai_strerror (r));
195 fflush (stderr);
196 exit (1);
197 }
198
199 scoped_free_addrinfo free_ainfo (ainfo);
200
201 struct addrinfo *p;
c906108c 202
c7ab0aef
SDJ
203 for (p = ainfo; p != NULL; p = p->ai_next)
204 {
205 tmp_desc = socket (p->ai_family, p->ai_socktype, p->ai_protocol);
206
207 if (tmp_desc >= 0)
208 break;
209 }
210
211 if (p == NULL)
212 perror_with_name ("Cannot open socket");
213
214 /* Allow rapid reuse of this port. */
215 tmp = 1;
216 setsockopt (tmp_desc, SOL_SOCKET, SO_REUSEADDR, (char *) &tmp,
217 sizeof (tmp));
218
219 switch (p->ai_family)
220 {
221 case AF_INET:
222 ((struct sockaddr_in *) p->ai_addr)->sin_addr.s_addr = INADDR_ANY;
223 break;
224 case AF_INET6:
225 ((struct sockaddr_in6 *) p->ai_addr)->sin6_addr = in6addr_any;
226 break;
227 default:
228 fprintf (stderr, "Invalid 'ai_family' %d\n", p->ai_family);
229 exit (1);
230 }
c906108c 231
c7ab0aef
SDJ
232 if (bind (tmp_desc, p->ai_addr, p->ai_addrlen) != 0)
233 perror_with_name ("Can't bind address");
234
235 if (p->ai_socktype == SOCK_DGRAM)
236 remote_desc = tmp_desc;
237 else
238 {
239 struct sockaddr_storage sockaddr;
240 socklen_t sockaddrsize = sizeof (sockaddr);
241 char orig_host[GDB_NI_MAX_ADDR], orig_port[GDB_NI_MAX_PORT];
242
243 if (listen (tmp_desc, 1) != 0)
244 perror_with_name ("Can't listen on socket");
245
246 remote_desc = accept (tmp_desc, (struct sockaddr *) &sockaddr,
247 &sockaddrsize);
c906108c 248
c906108c
SS
249 if (remote_desc == -1)
250 perror_with_name ("Accept failed");
251
c906108c
SS
252 /* Enable TCP keep alive process. */
253 tmp = 1;
493e2a69
MS
254 setsockopt (tmp_desc, SOL_SOCKET, SO_KEEPALIVE,
255 (char *) &tmp, sizeof (tmp));
c906108c
SS
256
257 /* Tell TCP not to delay small packets. This greatly speeds up
1b3f6016 258 interactive response. */
c906108c 259 tmp = 1;
373fe97f 260 setsockopt (remote_desc, IPPROTO_TCP, TCP_NODELAY,
c5aa993b 261 (char *) &tmp, sizeof (tmp));
c906108c 262
c7ab0aef
SDJ
263 if (getnameinfo ((struct sockaddr *) &sockaddr, sockaddrsize,
264 orig_host, sizeof (orig_host),
265 orig_port, sizeof (orig_port),
266 NI_NUMERICHOST | NI_NUMERICSERV) == 0)
267 {
268 fprintf (stderr, "Remote debugging from host %s, port %s\n",
269 orig_host, orig_port);
270 fflush (stderr);
271 }
272
b80864fb
DJ
273#ifndef USE_WIN32API
274 close (tmp_desc); /* No longer need this */
275
493e2a69
MS
276 signal (SIGPIPE, SIG_IGN); /* If we don't do this, then
277 gdbreplay simply exits when
278 the remote side dies. */
b80864fb
DJ
279#else
280 closesocket (tmp_desc); /* No longer need this */
281#endif
c906108c
SS
282 }
283
b80864fb 284#if defined(F_SETFL) && defined (FASYNC)
c906108c 285 fcntl (remote_desc, F_SETFL, FASYNC);
b80864fb 286#endif
c906108c
SS
287
288 fprintf (stderr, "Replay logfile using %s\n", name);
289 fflush (stderr);
290}
291
c5aa993b 292static int
909c2cda 293fromhex (int ch)
c906108c
SS
294{
295 if (ch >= '0' && ch <= '9')
296 {
297 return (ch - '0');
298 }
299 if (ch >= 'A' && ch <= 'F')
300 {
301 return (ch - 'A' + 10);
302 }
303 if (ch >= 'a' && ch <= 'f')
304 {
305 return (ch - 'a' + 10);
306 }
307 fprintf (stderr, "\nInvalid hex digit '%c'\n", ch);
308 fflush (stderr);
309 exit (1);
310}
311
312static int
fba45db2 313logchar (FILE *fp)
c906108c
SS
314{
315 int ch;
316 int ch2;
317
318 ch = fgetc (fp);
319 fputc (ch, stdout);
320 fflush (stdout);
321 switch (ch)
322 {
323 case '\n':
324 ch = EOL;
325 break;
326 case '\\':
327 ch = fgetc (fp);
328 fputc (ch, stdout);
329 fflush (stdout);
330 switch (ch)
331 {
c5aa993b
JM
332 case '\\':
333 break;
334 case 'b':
335 ch = '\b';
336 break;
337 case 'f':
338 ch = '\f';
339 break;
340 case 'n':
341 ch = '\n';
342 break;
343 case 'r':
344 ch = '\r';
345 break;
346 case 't':
347 ch = '\t';
348 break;
349 case 'v':
350 ch = '\v';
351 break;
c906108c
SS
352 case 'x':
353 ch2 = fgetc (fp);
354 fputc (ch2, stdout);
355 fflush (stdout);
909c2cda 356 ch = fromhex (ch2) << 4;
c906108c
SS
357 ch2 = fgetc (fp);
358 fputc (ch2, stdout);
359 fflush (stdout);
909c2cda 360 ch |= fromhex (ch2);
c906108c
SS
361 break;
362 default:
363 /* Treat any other char as just itself */
364 break;
365 }
366 default:
367 break;
368 }
369 return (ch);
370}
371
e581f2b4
PA
372static int
373gdbchar (int desc)
374{
375 unsigned char fromgdb;
376
377 if (read (desc, &fromgdb, 1) != 1)
378 return -1;
379 else
380 return fromgdb;
381}
382
c906108c
SS
383/* Accept input from gdb and match with chars from fp (after skipping one
384 blank) up until a \n is read from fp (which is not matched) */
385
82e0fd98 386static void
fba45db2 387expect (FILE *fp)
c906108c
SS
388{
389 int fromlog;
e581f2b4 390 int fromgdb;
c906108c
SS
391
392 if ((fromlog = logchar (fp)) != ' ')
393 {
394 sync_error (fp, "Sync error during gdb read of leading blank", ' ',
395 fromlog);
396 }
397 do
398 {
399 fromlog = logchar (fp);
400 if (fromlog == EOL)
e581f2b4
PA
401 break;
402 fromgdb = gdbchar (remote_desc);
403 if (fromgdb < 0)
404 remote_error ("Error during read from gdb");
c5aa993b
JM
405 }
406 while (fromlog == fromgdb);
e581f2b4 407
c906108c
SS
408 if (fromlog != EOL)
409 {
e581f2b4 410 sync_error (fp, "Sync error during read of gdb packet from log", fromlog,
c906108c
SS
411 fromgdb);
412 }
413}
414
415/* Play data back to gdb from fp (after skipping leading blank) up until a
416 \n is read from fp (which is discarded and not sent to gdb). */
417
82e0fd98 418static void
fba45db2 419play (FILE *fp)
c906108c
SS
420{
421 int fromlog;
422 char ch;
423
424 if ((fromlog = logchar (fp)) != ' ')
425 {
426 sync_error (fp, "Sync error skipping blank during write to gdb", ' ',
427 fromlog);
428 }
429 while ((fromlog = logchar (fp)) != EOL)
430 {
431 ch = fromlog;
e581f2b4
PA
432 if (write (remote_desc, &ch, 1) != 1)
433 remote_error ("Error during write to gdb");
c906108c
SS
434 }
435}
436
c16158bc
JM
437static void
438gdbreplay_version (void)
439{
440 printf ("GNU gdbreplay %s%s\n"
66d91b39 441 "Copyright (C) 2019 Free Software Foundation, Inc.\n"
493e2a69
MS
442 "gdbreplay is free software, covered by "
443 "the GNU General Public License.\n"
90aa6a40 444 "This gdbreplay was configured as \"%s\"\n",
c16158bc
JM
445 PKGVERSION, version, host_name);
446}
447
448static void
449gdbreplay_usage (FILE *stream)
450{
752312ba 451 fprintf (stream, "Usage:\tgdbreplay LOGFILE HOST:PORT\n");
c16158bc
JM
452 if (REPORT_BUGS_TO[0] && stream == stdout)
453 fprintf (stream, "Report bugs to \"%s\".\n", REPORT_BUGS_TO);
454}
455
03349c93
PA
456/* Main function. This is called by the real "main" function,
457 wrapped in a TRY_CATCH that handles any uncaught exceptions. */
458
459static void ATTRIBUTE_NORETURN
460captured_main (int argc, char *argv[])
c906108c
SS
461{
462 FILE *fp;
463 int ch;
464
c16158bc
JM
465 if (argc >= 2 && strcmp (argv[1], "--version") == 0)
466 {
467 gdbreplay_version ();
468 exit (0);
469 }
470 if (argc >= 2 && strcmp (argv[1], "--help") == 0)
471 {
472 gdbreplay_usage (stdout);
473 exit (0);
474 }
475
c906108c
SS
476 if (argc < 3)
477 {
c16158bc 478 gdbreplay_usage (stderr);
c906108c
SS
479 exit (1);
480 }
481 fp = fopen (argv[1], "r");
482 if (fp == NULL)
483 {
484 perror_with_name (argv[1]);
c5aa993b 485 }
c906108c
SS
486 remote_open (argv[2]);
487 while ((ch = logchar (fp)) != EOF)
488 {
489 switch (ch)
490 {
491 case 'w':
492 /* data sent from gdb to gdbreplay, accept and match it */
493 expect (fp);
494 break;
495 case 'r':
496 /* data sent from gdbreplay to gdb, play it */
497 play (fp);
498 break;
499 case 'c':
500 /* Command executed by gdb */
501 while ((ch = logchar (fp)) != EOL);
502 break;
503 }
504 }
505 remote_close ();
506 exit (0);
507}
03349c93
PA
508
509int
510main (int argc, char *argv[])
511{
512 TRY
513 {
514 captured_main (argc, argv);
515 }
516 CATCH (exception, RETURN_MASK_ALL)
517 {
518 if (exception.reason == RETURN_ERROR)
519 {
520 fflush (stdout);
521 fprintf (stderr, "%s\n", exception.message);
522 }
523
524 exit (1);
525 }
526 END_CATCH
527
528 gdb_assert_not_reached ("captured_main should never return");
529}
This page took 1.483931 seconds and 4 git commands to generate.