Move stdarg.h to common-defs.h
[deliverable/binutils-gdb.git] / gdb / gdbserver / gdbreplay.c
CommitLineData
c906108c 1/* Replay a remote debug session logfile for GDB.
ecd75fc8 2 Copyright (C) 1996-2014 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
5c44784c 20#include "config.h"
406b1477 21#include "build-gnulib-gdbserver/config.h"
01208463 22#include "version.h"
406b1477 23
c906108c 24#include <stdio.h>
68070c10 25#if HAVE_SYS_FILE_H
c906108c 26#include <sys/file.h>
68070c10
PA
27#endif
28#if HAVE_SIGNAL_H
c906108c 29#include <signal.h>
68070c10 30#endif
c906108c 31#include <ctype.h>
68070c10 32#if HAVE_FCNTL_H
c906108c 33#include <fcntl.h>
68070c10
PA
34#endif
35#if HAVE_ERRNO_H
5c44784c 36#include <errno.h>
68070c10 37#endif
82e0fd98 38#include <stdlib.h>
0729219d 39#include <string.h>
82e0fd98 40#include <unistd.h>
b80864fb
DJ
41#ifdef HAVE_NETINET_IN_H
42#include <netinet/in.h>
43#endif
44#ifdef HAVE_SYS_SOCKET_H
45#include <sys/socket.h>
46#endif
47#if HAVE_NETDB_H
48#include <netdb.h>
49#endif
50#if HAVE_NETINET_TCP_H
51#include <netinet/tcp.h>
52#endif
a778ab81 53#if HAVE_ALLOCA_H
54#include <alloca.h>
55#endif
68070c10
PA
56#if HAVE_MALLOC_H
57#include <malloc.h>
58#endif
b80864fb 59#if USE_WIN32API
12ea4b69 60#include <winsock2.h>
b80864fb 61#endif
c906108c 62
f450004a
DJ
63#ifndef HAVE_SOCKLEN_T
64typedef int socklen_t;
65#endif
66
c906108c
SS
67/* Sort of a hack... */
68#define EOL (EOF - 1)
69
70static int remote_desc;
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
SS
123/* Print the system error message for errno, and also mention STRING
124 as the file name for which the error was encountered.
125 Then return to command level. */
126
82e0fd98 127static void
54363045 128perror_with_name (const char *string)
c906108c 129{
5c44784c 130#ifndef STDC_HEADERS
c906108c 131 extern int errno;
5c44784c
JM
132#endif
133 const char *err;
c906108c
SS
134 char *combined;
135
43d5792c
DJ
136 err = strerror (errno);
137 if (err == NULL)
138 err = "unknown error";
139
c906108c
SS
140 combined = (char *) alloca (strlen (err) + strlen (string) + 3);
141 strcpy (combined, string);
142 strcat (combined, ": ");
143 strcat (combined, err);
144 fprintf (stderr, "\n%s.\n", combined);
145 fflush (stderr);
146 exit (1);
147}
148
149static void
fba45db2 150sync_error (FILE *fp, char *desc, int expect, int got)
c906108c
SS
151{
152 fprintf (stderr, "\n%s\n", desc);
153 fprintf (stderr, "At logfile offset %ld, expected '0x%x' got '0x%x'\n",
154 ftell (fp), expect, got);
155 fflush (stderr);
156 exit (1);
157}
158
e581f2b4
PA
159static void
160remote_error (const char *desc)
161{
162 fprintf (stderr, "\n%s\n", desc);
163 fflush (stderr);
164 exit (1);
165}
166
82e0fd98 167static void
fba45db2 168remote_close (void)
c906108c 169{
b80864fb
DJ
170#ifdef USE_WIN32API
171 closesocket (remote_desc);
172#else
c906108c 173 close (remote_desc);
b80864fb 174#endif
c906108c
SS
175}
176
177/* Open a connection to a remote debugger.
178 NAME is the filename used for communication. */
179
82e0fd98 180static void
fba45db2 181remote_open (char *name)
c906108c 182{
c906108c
SS
183 if (!strchr (name, ':'))
184 {
185 fprintf (stderr, "%s: Must specify tcp connection as host:addr\n", name);
186 fflush (stderr);
187 exit (1);
188 }
189 else
190 {
b80864fb
DJ
191#ifdef USE_WIN32API
192 static int winsock_initialized;
193#endif
c906108c
SS
194 char *port_str;
195 int port;
196 struct sockaddr_in sockaddr;
f450004a 197 socklen_t tmp;
c906108c
SS
198 int tmp_desc;
199
200 port_str = strchr (name, ':');
201
202 port = atoi (port_str + 1);
203
b80864fb
DJ
204#ifdef USE_WIN32API
205 if (!winsock_initialized)
206 {
207 WSADATA wsad;
208
209 WSAStartup (MAKEWORD (1, 0), &wsad);
210 winsock_initialized = 1;
211 }
212#endif
213
c906108c 214 tmp_desc = socket (PF_INET, SOCK_STREAM, 0);
363a6e9f 215 if (tmp_desc == -1)
c906108c
SS
216 perror_with_name ("Can't open socket");
217
218 /* Allow rapid reuse of this port. */
219 tmp = 1;
c5aa993b
JM
220 setsockopt (tmp_desc, SOL_SOCKET, SO_REUSEADDR, (char *) &tmp,
221 sizeof (tmp));
c906108c
SS
222
223 sockaddr.sin_family = PF_INET;
c5aa993b 224 sockaddr.sin_port = htons (port);
c906108c
SS
225 sockaddr.sin_addr.s_addr = INADDR_ANY;
226
c5aa993b 227 if (bind (tmp_desc, (struct sockaddr *) &sockaddr, sizeof (sockaddr))
c906108c
SS
228 || listen (tmp_desc, 1))
229 perror_with_name ("Can't bind address");
230
231 tmp = sizeof (sockaddr);
c5aa993b 232 remote_desc = accept (tmp_desc, (struct sockaddr *) &sockaddr, &tmp);
c906108c
SS
233 if (remote_desc == -1)
234 perror_with_name ("Accept failed");
235
c906108c
SS
236 /* Enable TCP keep alive process. */
237 tmp = 1;
493e2a69
MS
238 setsockopt (tmp_desc, SOL_SOCKET, SO_KEEPALIVE,
239 (char *) &tmp, sizeof (tmp));
c906108c
SS
240
241 /* Tell TCP not to delay small packets. This greatly speeds up
1b3f6016 242 interactive response. */
c906108c 243 tmp = 1;
373fe97f 244 setsockopt (remote_desc, IPPROTO_TCP, TCP_NODELAY,
c5aa993b 245 (char *) &tmp, sizeof (tmp));
c906108c 246
b80864fb
DJ
247#ifndef USE_WIN32API
248 close (tmp_desc); /* No longer need this */
249
493e2a69
MS
250 signal (SIGPIPE, SIG_IGN); /* If we don't do this, then
251 gdbreplay simply exits when
252 the remote side dies. */
b80864fb
DJ
253#else
254 closesocket (tmp_desc); /* No longer need this */
255#endif
c906108c
SS
256 }
257
b80864fb 258#if defined(F_SETFL) && defined (FASYNC)
c906108c 259 fcntl (remote_desc, F_SETFL, FASYNC);
b80864fb 260#endif
c906108c
SS
261
262 fprintf (stderr, "Replay logfile using %s\n", name);
263 fflush (stderr);
264}
265
c5aa993b 266static int
fba45db2 267tohex (int ch)
c906108c
SS
268{
269 if (ch >= '0' && ch <= '9')
270 {
271 return (ch - '0');
272 }
273 if (ch >= 'A' && ch <= 'F')
274 {
275 return (ch - 'A' + 10);
276 }
277 if (ch >= 'a' && ch <= 'f')
278 {
279 return (ch - 'a' + 10);
280 }
281 fprintf (stderr, "\nInvalid hex digit '%c'\n", ch);
282 fflush (stderr);
283 exit (1);
284}
285
286static int
fba45db2 287logchar (FILE *fp)
c906108c
SS
288{
289 int ch;
290 int ch2;
291
292 ch = fgetc (fp);
293 fputc (ch, stdout);
294 fflush (stdout);
295 switch (ch)
296 {
297 case '\n':
298 ch = EOL;
299 break;
300 case '\\':
301 ch = fgetc (fp);
302 fputc (ch, stdout);
303 fflush (stdout);
304 switch (ch)
305 {
c5aa993b
JM
306 case '\\':
307 break;
308 case 'b':
309 ch = '\b';
310 break;
311 case 'f':
312 ch = '\f';
313 break;
314 case 'n':
315 ch = '\n';
316 break;
317 case 'r':
318 ch = '\r';
319 break;
320 case 't':
321 ch = '\t';
322 break;
323 case 'v':
324 ch = '\v';
325 break;
c906108c
SS
326 case 'x':
327 ch2 = fgetc (fp);
328 fputc (ch2, stdout);
329 fflush (stdout);
330 ch = tohex (ch2) << 4;
331 ch2 = fgetc (fp);
332 fputc (ch2, stdout);
333 fflush (stdout);
334 ch |= tohex (ch2);
335 break;
336 default:
337 /* Treat any other char as just itself */
338 break;
339 }
340 default:
341 break;
342 }
343 return (ch);
344}
345
e581f2b4
PA
346static int
347gdbchar (int desc)
348{
349 unsigned char fromgdb;
350
351 if (read (desc, &fromgdb, 1) != 1)
352 return -1;
353 else
354 return fromgdb;
355}
356
c906108c
SS
357/* Accept input from gdb and match with chars from fp (after skipping one
358 blank) up until a \n is read from fp (which is not matched) */
359
82e0fd98 360static void
fba45db2 361expect (FILE *fp)
c906108c
SS
362{
363 int fromlog;
e581f2b4 364 int fromgdb;
c906108c
SS
365
366 if ((fromlog = logchar (fp)) != ' ')
367 {
368 sync_error (fp, "Sync error during gdb read of leading blank", ' ',
369 fromlog);
370 }
371 do
372 {
373 fromlog = logchar (fp);
374 if (fromlog == EOL)
e581f2b4
PA
375 break;
376 fromgdb = gdbchar (remote_desc);
377 if (fromgdb < 0)
378 remote_error ("Error during read from gdb");
c5aa993b
JM
379 }
380 while (fromlog == fromgdb);
e581f2b4 381
c906108c
SS
382 if (fromlog != EOL)
383 {
e581f2b4 384 sync_error (fp, "Sync error during read of gdb packet from log", fromlog,
c906108c
SS
385 fromgdb);
386 }
387}
388
389/* Play data back to gdb from fp (after skipping leading blank) up until a
390 \n is read from fp (which is discarded and not sent to gdb). */
391
82e0fd98 392static void
fba45db2 393play (FILE *fp)
c906108c
SS
394{
395 int fromlog;
396 char ch;
397
398 if ((fromlog = logchar (fp)) != ' ')
399 {
400 sync_error (fp, "Sync error skipping blank during write to gdb", ' ',
401 fromlog);
402 }
403 while ((fromlog = logchar (fp)) != EOL)
404 {
405 ch = fromlog;
e581f2b4
PA
406 if (write (remote_desc, &ch, 1) != 1)
407 remote_error ("Error during write to gdb");
c906108c
SS
408 }
409}
410
c16158bc
JM
411static void
412gdbreplay_version (void)
413{
414 printf ("GNU gdbreplay %s%s\n"
28498c42 415 "Copyright (C) 2014 Free Software Foundation, Inc.\n"
493e2a69
MS
416 "gdbreplay is free software, covered by "
417 "the GNU General Public License.\n"
90aa6a40 418 "This gdbreplay was configured as \"%s\"\n",
c16158bc
JM
419 PKGVERSION, version, host_name);
420}
421
422static void
423gdbreplay_usage (FILE *stream)
424{
425 fprintf (stream, "Usage:\tgdbreplay <logfile> <host:port>\n");
426 if (REPORT_BUGS_TO[0] && stream == stdout)
427 fprintf (stream, "Report bugs to \"%s\".\n", REPORT_BUGS_TO);
428}
429
c906108c 430int
da85418c 431main (int argc, char *argv[])
c906108c
SS
432{
433 FILE *fp;
434 int ch;
435
c16158bc
JM
436 if (argc >= 2 && strcmp (argv[1], "--version") == 0)
437 {
438 gdbreplay_version ();
439 exit (0);
440 }
441 if (argc >= 2 && strcmp (argv[1], "--help") == 0)
442 {
443 gdbreplay_usage (stdout);
444 exit (0);
445 }
446
c906108c
SS
447 if (argc < 3)
448 {
c16158bc 449 gdbreplay_usage (stderr);
c906108c
SS
450 exit (1);
451 }
452 fp = fopen (argv[1], "r");
453 if (fp == NULL)
454 {
455 perror_with_name (argv[1]);
c5aa993b 456 }
c906108c
SS
457 remote_open (argv[2]);
458 while ((ch = logchar (fp)) != EOF)
459 {
460 switch (ch)
461 {
462 case 'w':
463 /* data sent from gdb to gdbreplay, accept and match it */
464 expect (fp);
465 break;
466 case 'r':
467 /* data sent from gdbreplay to gdb, play it */
468 play (fp);
469 break;
470 case 'c':
471 /* Command executed by gdb */
472 while ((ch = logchar (fp)) != EOL);
473 break;
474 }
475 }
476 remote_close ();
477 exit (0);
478}
This page took 1.05277 seconds and 4 git commands to generate.