GDB: Work around D;PID handling bug in older GDBservers (PR gdb/23377)
[deliverable/binutils-gdb.git] / gdb / gdbserver / gdbreplay.c
CommitLineData
c906108c 1/* Replay a remote debug session logfile for GDB.
e2882c85 2 Copyright (C) 1996-2018 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>
49#endif
c906108c 50
f450004a
DJ
51#ifndef HAVE_SOCKLEN_T
52typedef int socklen_t;
53#endif
54
c906108c
SS
55/* Sort of a hack... */
56#define EOL (EOF - 1)
57
58static int remote_desc;
59
68070c10
PA
60#ifdef __MINGW32CE__
61
62#ifndef COUNTOF
63#define COUNTOF(STR) (sizeof (STR) / sizeof ((STR)[0]))
64#endif
65
66#define errno (GetLastError ())
67
68char *
69strerror (DWORD error)
70{
71 static char buf[1024];
72 WCHAR *msgbuf;
73 DWORD lasterr = GetLastError ();
74 DWORD chars = FormatMessageW (FORMAT_MESSAGE_FROM_SYSTEM
75 | FORMAT_MESSAGE_ALLOCATE_BUFFER,
76 NULL,
77 error,
78 0, /* Default language */
79 (LPVOID)&msgbuf,
80 0,
81 NULL);
82 if (chars != 0)
83 {
84 /* If there is an \r\n appended, zap it. */
85 if (chars >= 2
86 && msgbuf[chars - 2] == '\r'
87 && msgbuf[chars - 1] == '\n')
88 {
89 chars -= 2;
90 msgbuf[chars] = 0;
91 }
92
93 if (chars > ((COUNTOF (buf)) - 1))
94 {
95 chars = COUNTOF (buf) - 1;
96 msgbuf [chars] = 0;
97 }
98
99 wcstombs (buf, msgbuf, chars + 1);
100 LocalFree (msgbuf);
101 }
102 else
103 sprintf (buf, "unknown win32 error (%ld)", error);
104
105 SetLastError (lasterr);
106 return buf;
107}
108
109#endif /* __MINGW32CE__ */
110
c906108c 111static void
a121b7c1 112sync_error (FILE *fp, const char *desc, int expect, int got)
c906108c
SS
113{
114 fprintf (stderr, "\n%s\n", desc);
115 fprintf (stderr, "At logfile offset %ld, expected '0x%x' got '0x%x'\n",
116 ftell (fp), expect, got);
117 fflush (stderr);
118 exit (1);
119}
120
e581f2b4
PA
121static void
122remote_error (const char *desc)
123{
124 fprintf (stderr, "\n%s\n", desc);
125 fflush (stderr);
126 exit (1);
127}
128
82e0fd98 129static void
fba45db2 130remote_close (void)
c906108c 131{
b80864fb
DJ
132#ifdef USE_WIN32API
133 closesocket (remote_desc);
134#else
c906108c 135 close (remote_desc);
b80864fb 136#endif
c906108c
SS
137}
138
139/* Open a connection to a remote debugger.
140 NAME is the filename used for communication. */
141
82e0fd98 142static void
fba45db2 143remote_open (char *name)
c906108c 144{
c906108c
SS
145 if (!strchr (name, ':'))
146 {
147 fprintf (stderr, "%s: Must specify tcp connection as host:addr\n", name);
148 fflush (stderr);
149 exit (1);
150 }
151 else
152 {
b80864fb
DJ
153#ifdef USE_WIN32API
154 static int winsock_initialized;
155#endif
c906108c
SS
156 char *port_str;
157 int port;
9eb1356e 158 struct sockaddr_in sockaddr;
f450004a 159 socklen_t tmp;
c906108c
SS
160 int tmp_desc;
161
162 port_str = strchr (name, ':');
163
164 port = atoi (port_str + 1);
165
b80864fb
DJ
166#ifdef USE_WIN32API
167 if (!winsock_initialized)
168 {
169 WSADATA wsad;
170
171 WSAStartup (MAKEWORD (1, 0), &wsad);
172 winsock_initialized = 1;
173 }
174#endif
175
c906108c 176 tmp_desc = socket (PF_INET, SOCK_STREAM, 0);
363a6e9f 177 if (tmp_desc == -1)
c906108c
SS
178 perror_with_name ("Can't open socket");
179
180 /* Allow rapid reuse of this port. */
181 tmp = 1;
c5aa993b
JM
182 setsockopt (tmp_desc, SOL_SOCKET, SO_REUSEADDR, (char *) &tmp,
183 sizeof (tmp));
c906108c 184
9eb1356e
PA
185 sockaddr.sin_family = PF_INET;
186 sockaddr.sin_port = htons (port);
187 sockaddr.sin_addr.s_addr = INADDR_ANY;
c906108c 188
9eb1356e 189 if (bind (tmp_desc, (struct sockaddr *) &sockaddr, sizeof (sockaddr))
c906108c
SS
190 || listen (tmp_desc, 1))
191 perror_with_name ("Can't bind address");
192
9eb1356e
PA
193 tmp = sizeof (sockaddr);
194 remote_desc = accept (tmp_desc, (struct sockaddr *) &sockaddr, &tmp);
c906108c
SS
195 if (remote_desc == -1)
196 perror_with_name ("Accept failed");
197
c906108c
SS
198 /* Enable TCP keep alive process. */
199 tmp = 1;
493e2a69
MS
200 setsockopt (tmp_desc, SOL_SOCKET, SO_KEEPALIVE,
201 (char *) &tmp, sizeof (tmp));
c906108c
SS
202
203 /* Tell TCP not to delay small packets. This greatly speeds up
1b3f6016 204 interactive response. */
c906108c 205 tmp = 1;
373fe97f 206 setsockopt (remote_desc, IPPROTO_TCP, TCP_NODELAY,
c5aa993b 207 (char *) &tmp, sizeof (tmp));
c906108c 208
b80864fb
DJ
209#ifndef USE_WIN32API
210 close (tmp_desc); /* No longer need this */
211
493e2a69
MS
212 signal (SIGPIPE, SIG_IGN); /* If we don't do this, then
213 gdbreplay simply exits when
214 the remote side dies. */
b80864fb
DJ
215#else
216 closesocket (tmp_desc); /* No longer need this */
217#endif
c906108c
SS
218 }
219
b80864fb 220#if defined(F_SETFL) && defined (FASYNC)
c906108c 221 fcntl (remote_desc, F_SETFL, FASYNC);
b80864fb 222#endif
c906108c
SS
223
224 fprintf (stderr, "Replay logfile using %s\n", name);
225 fflush (stderr);
226}
227
c5aa993b 228static int
909c2cda 229fromhex (int ch)
c906108c
SS
230{
231 if (ch >= '0' && ch <= '9')
232 {
233 return (ch - '0');
234 }
235 if (ch >= 'A' && ch <= 'F')
236 {
237 return (ch - 'A' + 10);
238 }
239 if (ch >= 'a' && ch <= 'f')
240 {
241 return (ch - 'a' + 10);
242 }
243 fprintf (stderr, "\nInvalid hex digit '%c'\n", ch);
244 fflush (stderr);
245 exit (1);
246}
247
248static int
fba45db2 249logchar (FILE *fp)
c906108c
SS
250{
251 int ch;
252 int ch2;
253
254 ch = fgetc (fp);
255 fputc (ch, stdout);
256 fflush (stdout);
257 switch (ch)
258 {
259 case '\n':
260 ch = EOL;
261 break;
262 case '\\':
263 ch = fgetc (fp);
264 fputc (ch, stdout);
265 fflush (stdout);
266 switch (ch)
267 {
c5aa993b
JM
268 case '\\':
269 break;
270 case 'b':
271 ch = '\b';
272 break;
273 case 'f':
274 ch = '\f';
275 break;
276 case 'n':
277 ch = '\n';
278 break;
279 case 'r':
280 ch = '\r';
281 break;
282 case 't':
283 ch = '\t';
284 break;
285 case 'v':
286 ch = '\v';
287 break;
c906108c
SS
288 case 'x':
289 ch2 = fgetc (fp);
290 fputc (ch2, stdout);
291 fflush (stdout);
909c2cda 292 ch = fromhex (ch2) << 4;
c906108c
SS
293 ch2 = fgetc (fp);
294 fputc (ch2, stdout);
295 fflush (stdout);
909c2cda 296 ch |= fromhex (ch2);
c906108c
SS
297 break;
298 default:
299 /* Treat any other char as just itself */
300 break;
301 }
302 default:
303 break;
304 }
305 return (ch);
306}
307
e581f2b4
PA
308static int
309gdbchar (int desc)
310{
311 unsigned char fromgdb;
312
313 if (read (desc, &fromgdb, 1) != 1)
314 return -1;
315 else
316 return fromgdb;
317}
318
c906108c
SS
319/* Accept input from gdb and match with chars from fp (after skipping one
320 blank) up until a \n is read from fp (which is not matched) */
321
82e0fd98 322static void
fba45db2 323expect (FILE *fp)
c906108c
SS
324{
325 int fromlog;
e581f2b4 326 int fromgdb;
c906108c
SS
327
328 if ((fromlog = logchar (fp)) != ' ')
329 {
330 sync_error (fp, "Sync error during gdb read of leading blank", ' ',
331 fromlog);
332 }
333 do
334 {
335 fromlog = logchar (fp);
336 if (fromlog == EOL)
e581f2b4
PA
337 break;
338 fromgdb = gdbchar (remote_desc);
339 if (fromgdb < 0)
340 remote_error ("Error during read from gdb");
c5aa993b
JM
341 }
342 while (fromlog == fromgdb);
e581f2b4 343
c906108c
SS
344 if (fromlog != EOL)
345 {
e581f2b4 346 sync_error (fp, "Sync error during read of gdb packet from log", fromlog,
c906108c
SS
347 fromgdb);
348 }
349}
350
351/* Play data back to gdb from fp (after skipping leading blank) up until a
352 \n is read from fp (which is discarded and not sent to gdb). */
353
82e0fd98 354static void
fba45db2 355play (FILE *fp)
c906108c
SS
356{
357 int fromlog;
358 char ch;
359
360 if ((fromlog = logchar (fp)) != ' ')
361 {
362 sync_error (fp, "Sync error skipping blank during write to gdb", ' ',
363 fromlog);
364 }
365 while ((fromlog = logchar (fp)) != EOL)
366 {
367 ch = fromlog;
e581f2b4
PA
368 if (write (remote_desc, &ch, 1) != 1)
369 remote_error ("Error during write to gdb");
c906108c
SS
370 }
371}
372
c16158bc
JM
373static void
374gdbreplay_version (void)
375{
376 printf ("GNU gdbreplay %s%s\n"
82e1e79a 377 "Copyright (C) 2018 Free Software Foundation, Inc.\n"
493e2a69
MS
378 "gdbreplay is free software, covered by "
379 "the GNU General Public License.\n"
90aa6a40 380 "This gdbreplay was configured as \"%s\"\n",
c16158bc
JM
381 PKGVERSION, version, host_name);
382}
383
384static void
385gdbreplay_usage (FILE *stream)
386{
387 fprintf (stream, "Usage:\tgdbreplay <logfile> <host:port>\n");
388 if (REPORT_BUGS_TO[0] && stream == stdout)
389 fprintf (stream, "Report bugs to \"%s\".\n", REPORT_BUGS_TO);
390}
391
03349c93
PA
392/* Main function. This is called by the real "main" function,
393 wrapped in a TRY_CATCH that handles any uncaught exceptions. */
394
395static void ATTRIBUTE_NORETURN
396captured_main (int argc, char *argv[])
c906108c
SS
397{
398 FILE *fp;
399 int ch;
400
c16158bc
JM
401 if (argc >= 2 && strcmp (argv[1], "--version") == 0)
402 {
403 gdbreplay_version ();
404 exit (0);
405 }
406 if (argc >= 2 && strcmp (argv[1], "--help") == 0)
407 {
408 gdbreplay_usage (stdout);
409 exit (0);
410 }
411
c906108c
SS
412 if (argc < 3)
413 {
c16158bc 414 gdbreplay_usage (stderr);
c906108c
SS
415 exit (1);
416 }
417 fp = fopen (argv[1], "r");
418 if (fp == NULL)
419 {
420 perror_with_name (argv[1]);
c5aa993b 421 }
c906108c
SS
422 remote_open (argv[2]);
423 while ((ch = logchar (fp)) != EOF)
424 {
425 switch (ch)
426 {
427 case 'w':
428 /* data sent from gdb to gdbreplay, accept and match it */
429 expect (fp);
430 break;
431 case 'r':
432 /* data sent from gdbreplay to gdb, play it */
433 play (fp);
434 break;
435 case 'c':
436 /* Command executed by gdb */
437 while ((ch = logchar (fp)) != EOL);
438 break;
439 }
440 }
441 remote_close ();
442 exit (0);
443}
03349c93
PA
444
445int
446main (int argc, char *argv[])
447{
448 TRY
449 {
450 captured_main (argc, argv);
451 }
452 CATCH (exception, RETURN_MASK_ALL)
453 {
454 if (exception.reason == RETURN_ERROR)
455 {
456 fflush (stdout);
457 fprintf (stderr, "%s\n", exception.message);
458 }
459
460 exit (1);
461 }
462 END_CATCH
463
464 gdb_assert_not_reached ("captured_main should never return");
465}
This page took 1.542024 seconds and 4 git commands to generate.