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