ubsan: bpf: left shift cannot be represented in type 'DI' (aka 'long')
[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
268a13a5
TT
20#include "gdbsupport/common-defs.h"
21#include "gdbsupport/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
268a13a5
TT
51#include "gdbsupport/netstuff.h"
52#include "gdbsupport/rsp-low.h"
c7ab0aef 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
c906108c 292static int
fba45db2 293logchar (FILE *fp)
c906108c
SS
294{
295 int ch;
296 int ch2;
297
298 ch = fgetc (fp);
43ac54fc
TT
299 if (ch != '\r')
300 {
301 fputc (ch, stdout);
302 fflush (stdout);
303 }
c906108c
SS
304 switch (ch)
305 {
43ac54fc
TT
306 /* Treat \r\n as a newline. */
307 case '\r':
308 ch = fgetc (fp);
309 if (ch == '\n')
310 ch = EOL;
311 else
312 {
313 ungetc (ch, fp);
314 ch = '\r';
315 }
316 fputc (ch == EOL ? '\n' : '\r', stdout);
317 fflush (stdout);
318 break;
c906108c
SS
319 case '\n':
320 ch = EOL;
321 break;
322 case '\\':
323 ch = fgetc (fp);
324 fputc (ch, stdout);
325 fflush (stdout);
326 switch (ch)
327 {
c5aa993b
JM
328 case '\\':
329 break;
330 case 'b':
331 ch = '\b';
332 break;
333 case 'f':
334 ch = '\f';
335 break;
336 case 'n':
337 ch = '\n';
338 break;
339 case 'r':
340 ch = '\r';
341 break;
342 case 't':
343 ch = '\t';
344 break;
345 case 'v':
346 ch = '\v';
347 break;
c906108c
SS
348 case 'x':
349 ch2 = fgetc (fp);
350 fputc (ch2, stdout);
351 fflush (stdout);
909c2cda 352 ch = fromhex (ch2) << 4;
c906108c
SS
353 ch2 = fgetc (fp);
354 fputc (ch2, stdout);
355 fflush (stdout);
909c2cda 356 ch |= fromhex (ch2);
c906108c
SS
357 break;
358 default:
359 /* Treat any other char as just itself */
360 break;
361 }
362 default:
363 break;
364 }
365 return (ch);
366}
367
e581f2b4
PA
368static int
369gdbchar (int desc)
370{
371 unsigned char fromgdb;
372
373 if (read (desc, &fromgdb, 1) != 1)
374 return -1;
375 else
376 return fromgdb;
377}
378
c906108c
SS
379/* Accept input from gdb and match with chars from fp (after skipping one
380 blank) up until a \n is read from fp (which is not matched) */
381
82e0fd98 382static void
fba45db2 383expect (FILE *fp)
c906108c
SS
384{
385 int fromlog;
e581f2b4 386 int fromgdb;
c906108c
SS
387
388 if ((fromlog = logchar (fp)) != ' ')
389 {
390 sync_error (fp, "Sync error during gdb read of leading blank", ' ',
391 fromlog);
392 }
393 do
394 {
395 fromlog = logchar (fp);
396 if (fromlog == EOL)
e581f2b4
PA
397 break;
398 fromgdb = gdbchar (remote_desc);
399 if (fromgdb < 0)
400 remote_error ("Error during read from gdb");
c5aa993b
JM
401 }
402 while (fromlog == fromgdb);
e581f2b4 403
c906108c
SS
404 if (fromlog != EOL)
405 {
e581f2b4 406 sync_error (fp, "Sync error during read of gdb packet from log", fromlog,
c906108c
SS
407 fromgdb);
408 }
409}
410
411/* Play data back to gdb from fp (after skipping leading blank) up until a
412 \n is read from fp (which is discarded and not sent to gdb). */
413
82e0fd98 414static void
fba45db2 415play (FILE *fp)
c906108c
SS
416{
417 int fromlog;
418 char ch;
419
420 if ((fromlog = logchar (fp)) != ' ')
421 {
422 sync_error (fp, "Sync error skipping blank during write to gdb", ' ',
423 fromlog);
424 }
425 while ((fromlog = logchar (fp)) != EOL)
426 {
427 ch = fromlog;
e581f2b4
PA
428 if (write (remote_desc, &ch, 1) != 1)
429 remote_error ("Error during write to gdb");
c906108c
SS
430 }
431}
432
c16158bc
JM
433static void
434gdbreplay_version (void)
435{
436 printf ("GNU gdbreplay %s%s\n"
66d91b39 437 "Copyright (C) 2019 Free Software Foundation, Inc.\n"
493e2a69
MS
438 "gdbreplay is free software, covered by "
439 "the GNU General Public License.\n"
90aa6a40 440 "This gdbreplay was configured as \"%s\"\n",
c16158bc
JM
441 PKGVERSION, version, host_name);
442}
443
444static void
445gdbreplay_usage (FILE *stream)
446{
752312ba 447 fprintf (stream, "Usage:\tgdbreplay LOGFILE HOST:PORT\n");
c16158bc
JM
448 if (REPORT_BUGS_TO[0] && stream == stdout)
449 fprintf (stream, "Report bugs to \"%s\".\n", REPORT_BUGS_TO);
450}
451
03349c93
PA
452/* Main function. This is called by the real "main" function,
453 wrapped in a TRY_CATCH that handles any uncaught exceptions. */
454
455static void ATTRIBUTE_NORETURN
456captured_main (int argc, char *argv[])
c906108c
SS
457{
458 FILE *fp;
459 int ch;
460
c16158bc
JM
461 if (argc >= 2 && strcmp (argv[1], "--version") == 0)
462 {
463 gdbreplay_version ();
464 exit (0);
465 }
466 if (argc >= 2 && strcmp (argv[1], "--help") == 0)
467 {
468 gdbreplay_usage (stdout);
469 exit (0);
470 }
471
c906108c
SS
472 if (argc < 3)
473 {
c16158bc 474 gdbreplay_usage (stderr);
c906108c
SS
475 exit (1);
476 }
477 fp = fopen (argv[1], "r");
478 if (fp == NULL)
479 {
480 perror_with_name (argv[1]);
c5aa993b 481 }
c906108c
SS
482 remote_open (argv[2]);
483 while ((ch = logchar (fp)) != EOF)
484 {
485 switch (ch)
486 {
487 case 'w':
488 /* data sent from gdb to gdbreplay, accept and match it */
489 expect (fp);
490 break;
491 case 'r':
492 /* data sent from gdbreplay to gdb, play it */
493 play (fp);
494 break;
495 case 'c':
496 /* Command executed by gdb */
497 while ((ch = logchar (fp)) != EOL);
498 break;
499 }
500 }
501 remote_close ();
502 exit (0);
503}
03349c93
PA
504
505int
506main (int argc, char *argv[])
507{
a70b8144 508 try
03349c93
PA
509 {
510 captured_main (argc, argv);
511 }
230d2906 512 catch (const gdb_exception &exception)
03349c93
PA
513 {
514 if (exception.reason == RETURN_ERROR)
515 {
516 fflush (stdout);
3d6e9d23 517 fprintf (stderr, "%s\n", exception.what ());
03349c93
PA
518 }
519
520 exit (1);
521 }
03349c93
PA
522
523 gdb_assert_not_reached ("captured_main should never return");
524}
This page took 1.481631 seconds and 4 git commands to generate.