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