OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [gdb-7.1/] [gdb/] [gdbserver/] [gdbreplay.c] - Blame information for rev 855

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 227 jeremybenn
/* Replay a remote debug session logfile for GDB.
2
   Copyright (C) 1996, 1998, 1999, 2000, 2002, 2003, 2005, 2006, 2007, 2008,
3
   2009, 2010 Free Software Foundation, Inc.
4
   Written by Fred Fish (fnf@cygnus.com) from pieces of gdbserver.
5
 
6
   This file is part of GDB.
7
 
8
   This program is free software; you can redistribute it and/or modify
9
   it under the terms of the GNU General Public License as published by
10
   the Free Software Foundation; either version 3 of the License, or
11
   (at your option) any later version.
12
 
13
   This program is distributed in the hope that it will be useful,
14
   but WITHOUT ANY WARRANTY; without even the implied warranty of
15
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
   GNU General Public License for more details.
17
 
18
   You should have received a copy of the GNU General Public License
19
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
20
 
21
#include "config.h"
22
#include <stdio.h>
23
#if HAVE_SYS_FILE_H
24
#include <sys/file.h>
25
#endif
26
#if HAVE_SIGNAL_H
27
#include <signal.h>
28
#endif
29
#include <ctype.h>
30
#if HAVE_FCNTL_H
31
#include <fcntl.h>
32
#endif
33
#if HAVE_ERRNO_H
34
#include <errno.h>
35
#endif
36
#ifdef HAVE_STDLIB_H
37
#include <stdlib.h>
38
#endif
39
#ifdef HAVE_STRING_H
40
#include <string.h>
41
#endif
42
#ifdef HAVE_UNISTD_H
43
#include <unistd.h>
44
#endif
45
#ifdef HAVE_NETINET_IN_H
46
#include <netinet/in.h>
47
#endif
48
#ifdef HAVE_SYS_SOCKET_H
49
#include <sys/socket.h>
50
#endif
51
#if HAVE_NETDB_H
52
#include <netdb.h>
53
#endif
54
#if HAVE_NETINET_TCP_H
55
#include <netinet/tcp.h>
56
#endif
57
#if HAVE_MALLOC_H
58
#include <malloc.h>
59
#endif
60
 
61
#if USE_WIN32API
62
#include <winsock.h>
63
#endif
64
 
65
#ifndef HAVE_SOCKLEN_T
66
typedef int socklen_t;
67
#endif
68
 
69
/* Sort of a hack... */
70
#define EOL (EOF - 1)
71
 
72
/* Version information, from version.c.  */
73
extern const char version[];
74
extern const char host_name[];
75
 
76
static int remote_desc;
77
 
78
#ifdef __MINGW32CE__
79
 
80
#ifndef COUNTOF
81
#define COUNTOF(STR) (sizeof (STR) / sizeof ((STR)[0]))
82
#endif
83
 
84
#define errno (GetLastError ())
85
 
86
char *
87
strerror (DWORD error)
88
{
89
  static char buf[1024];
90
  WCHAR *msgbuf;
91
  DWORD lasterr = GetLastError ();
92
  DWORD chars = FormatMessageW (FORMAT_MESSAGE_FROM_SYSTEM
93
                                | FORMAT_MESSAGE_ALLOCATE_BUFFER,
94
                                NULL,
95
                                error,
96
                                0, /* Default language */
97
                                (LPVOID)&msgbuf,
98
                                0,
99
                                NULL);
100
  if (chars != 0)
101
    {
102
      /* If there is an \r\n appended, zap it.  */
103
      if (chars >= 2
104
          && msgbuf[chars - 2] == '\r'
105
          && msgbuf[chars - 1] == '\n')
106
        {
107
          chars -= 2;
108
          msgbuf[chars] = 0;
109
        }
110
 
111
      if (chars > ((COUNTOF (buf)) - 1))
112
        {
113
          chars = COUNTOF (buf) - 1;
114
          msgbuf [chars] = 0;
115
        }
116
 
117
      wcstombs (buf, msgbuf, chars + 1);
118
      LocalFree (msgbuf);
119
    }
120
  else
121
    sprintf (buf, "unknown win32 error (%ld)", error);
122
 
123
  SetLastError (lasterr);
124
  return buf;
125
}
126
 
127
#endif /* __MINGW32CE__ */
128
 
129
/* Print the system error message for errno, and also mention STRING
130
   as the file name for which the error was encountered.
131
   Then return to command level.  */
132
 
133
static void
134
perror_with_name (const char *string)
135
{
136
#ifndef STDC_HEADERS
137
  extern int errno;
138
#endif
139
  const char *err;
140
  char *combined;
141
 
142
  err = strerror (errno);
143
  if (err == NULL)
144
    err = "unknown error";
145
 
146
  combined = (char *) alloca (strlen (err) + strlen (string) + 3);
147
  strcpy (combined, string);
148
  strcat (combined, ": ");
149
  strcat (combined, err);
150
  fprintf (stderr, "\n%s.\n", combined);
151
  fflush (stderr);
152
  exit (1);
153
}
154
 
155
static void
156
sync_error (FILE *fp, char *desc, int expect, int got)
157
{
158
  fprintf (stderr, "\n%s\n", desc);
159
  fprintf (stderr, "At logfile offset %ld, expected '0x%x' got '0x%x'\n",
160
           ftell (fp), expect, got);
161
  fflush (stderr);
162
  exit (1);
163
}
164
 
165
static void
166
remote_close (void)
167
{
168
#ifdef USE_WIN32API
169
  closesocket (remote_desc);
170
#else
171
  close (remote_desc);
172
#endif
173
}
174
 
175
/* Open a connection to a remote debugger.
176
   NAME is the filename used for communication.  */
177
 
178
static void
179
remote_open (char *name)
180
{
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
    {
189
#ifdef USE_WIN32API
190
      static int winsock_initialized;
191
#endif
192
      char *port_str;
193
      int port;
194
      struct sockaddr_in sockaddr;
195
      socklen_t tmp;
196
      int tmp_desc;
197
 
198
      port_str = strchr (name, ':');
199
 
200
      port = atoi (port_str + 1);
201
 
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
 
212
      tmp_desc = socket (PF_INET, SOCK_STREAM, 0);
213
      if (tmp_desc < 0)
214
        perror_with_name ("Can't open socket");
215
 
216
      /* Allow rapid reuse of this port. */
217
      tmp = 1;
218
      setsockopt (tmp_desc, SOL_SOCKET, SO_REUSEADDR, (char *) &tmp,
219
                  sizeof (tmp));
220
 
221
      sockaddr.sin_family = PF_INET;
222
      sockaddr.sin_port = htons (port);
223
      sockaddr.sin_addr.s_addr = INADDR_ANY;
224
 
225
      if (bind (tmp_desc, (struct sockaddr *) &sockaddr, sizeof (sockaddr))
226
          || listen (tmp_desc, 1))
227
        perror_with_name ("Can't bind address");
228
 
229
      tmp = sizeof (sockaddr);
230
      remote_desc = accept (tmp_desc, (struct sockaddr *) &sockaddr, &tmp);
231
      if (remote_desc == -1)
232
        perror_with_name ("Accept failed");
233
 
234
      /* Enable TCP keep alive process. */
235
      tmp = 1;
236
      setsockopt (tmp_desc, SOL_SOCKET, SO_KEEPALIVE, (char *) &tmp, sizeof (tmp));
237
 
238
      /* Tell TCP not to delay small packets.  This greatly speeds up
239
         interactive response. */
240
      tmp = 1;
241
      setsockopt (remote_desc, IPPROTO_TCP, TCP_NODELAY,
242
                  (char *) &tmp, sizeof (tmp));
243
 
244
#ifndef USE_WIN32API
245
      close (tmp_desc);         /* No longer need this */
246
 
247
      signal (SIGPIPE, SIG_IGN);        /* If we don't do this, then gdbreplay simply
248
                                           exits when the remote side dies.  */
249
#else
250
      closesocket (tmp_desc);   /* No longer need this */
251
#endif
252
    }
253
 
254
#if defined(F_SETFL) && defined (FASYNC)
255
  fcntl (remote_desc, F_SETFL, FASYNC);
256
#endif
257
 
258
  fprintf (stderr, "Replay logfile using %s\n", name);
259
  fflush (stderr);
260
}
261
 
262
static int
263
tohex (int ch)
264
{
265
  if (ch >= '0' && ch <= '9')
266
    {
267
      return (ch - '0');
268
    }
269
  if (ch >= 'A' && ch <= 'F')
270
    {
271
      return (ch - 'A' + 10);
272
    }
273
  if (ch >= 'a' && ch <= 'f')
274
    {
275
      return (ch - 'a' + 10);
276
    }
277
  fprintf (stderr, "\nInvalid hex digit '%c'\n", ch);
278
  fflush (stderr);
279
  exit (1);
280
}
281
 
282
static int
283
logchar (FILE *fp)
284
{
285
  int ch;
286
  int ch2;
287
 
288
  ch = fgetc (fp);
289
  fputc (ch, stdout);
290
  fflush (stdout);
291
  switch (ch)
292
    {
293
    case '\n':
294
      ch = EOL;
295
      break;
296
    case '\\':
297
      ch = fgetc (fp);
298
      fputc (ch, stdout);
299
      fflush (stdout);
300
      switch (ch)
301
        {
302
        case '\\':
303
          break;
304
        case 'b':
305
          ch = '\b';
306
          break;
307
        case 'f':
308
          ch = '\f';
309
          break;
310
        case 'n':
311
          ch = '\n';
312
          break;
313
        case 'r':
314
          ch = '\r';
315
          break;
316
        case 't':
317
          ch = '\t';
318
          break;
319
        case 'v':
320
          ch = '\v';
321
          break;
322
        case 'x':
323
          ch2 = fgetc (fp);
324
          fputc (ch2, stdout);
325
          fflush (stdout);
326
          ch = tohex (ch2) << 4;
327
          ch2 = fgetc (fp);
328
          fputc (ch2, stdout);
329
          fflush (stdout);
330
          ch |= tohex (ch2);
331
          break;
332
        default:
333
          /* Treat any other char as just itself */
334
          break;
335
        }
336
    default:
337
      break;
338
    }
339
  return (ch);
340
}
341
 
342
/* Accept input from gdb and match with chars from fp (after skipping one
343
   blank) up until a \n is read from fp (which is not matched) */
344
 
345
static void
346
expect (FILE *fp)
347
{
348
  int fromlog;
349
  unsigned char fromgdb;
350
 
351
  if ((fromlog = logchar (fp)) != ' ')
352
    {
353
      sync_error (fp, "Sync error during gdb read of leading blank", ' ',
354
                  fromlog);
355
    }
356
  do
357
    {
358
      fromlog = logchar (fp);
359
      if (fromlog == EOL)
360
        {
361
          break;
362
        }
363
      read (remote_desc, &fromgdb, 1);
364
    }
365
  while (fromlog == fromgdb);
366
  if (fromlog != EOL)
367
    {
368
      sync_error (fp, "Sync error during read of gdb packet", fromlog,
369
                  fromgdb);
370
    }
371
}
372
 
373
/* Play data back to gdb from fp (after skipping leading blank) up until a
374
   \n is read from fp (which is discarded and not sent to gdb). */
375
 
376
static void
377
play (FILE *fp)
378
{
379
  int fromlog;
380
  char ch;
381
 
382
  if ((fromlog = logchar (fp)) != ' ')
383
    {
384
      sync_error (fp, "Sync error skipping blank during write to gdb", ' ',
385
                  fromlog);
386
    }
387
  while ((fromlog = logchar (fp)) != EOL)
388
    {
389
      ch = fromlog;
390
      write (remote_desc, &ch, 1);
391
    }
392
}
393
 
394
static void
395
gdbreplay_version (void)
396
{
397
  printf ("GNU gdbreplay %s%s\n"
398
          "Copyright (C) 2010 Free Software Foundation, Inc.\n"
399
          "gdbreplay is free software, covered by the GNU General Public License.\n"
400
          "This gdbreplay was configured as \"%s\"\n",
401
          PKGVERSION, version, host_name);
402
}
403
 
404
static void
405
gdbreplay_usage (FILE *stream)
406
{
407
  fprintf (stream, "Usage:\tgdbreplay <logfile> <host:port>\n");
408
  if (REPORT_BUGS_TO[0] && stream == stdout)
409
    fprintf (stream, "Report bugs to \"%s\".\n", REPORT_BUGS_TO);
410
}
411
 
412
int
413
main (int argc, char *argv[])
414
{
415
  FILE *fp;
416
  int ch;
417
 
418
  if (argc >= 2 && strcmp (argv[1], "--version") == 0)
419
    {
420
      gdbreplay_version ();
421
      exit (0);
422
    }
423
  if (argc >= 2 && strcmp (argv[1], "--help") == 0)
424
    {
425
      gdbreplay_usage (stdout);
426
      exit (0);
427
    }
428
 
429
  if (argc < 3)
430
    {
431
      gdbreplay_usage (stderr);
432
      exit (1);
433
    }
434
  fp = fopen (argv[1], "r");
435
  if (fp == NULL)
436
    {
437
      perror_with_name (argv[1]);
438
    }
439
  remote_open (argv[2]);
440
  while ((ch = logchar (fp)) != EOF)
441
    {
442
      switch (ch)
443
        {
444
        case 'w':
445
          /* data sent from gdb to gdbreplay, accept and match it */
446
          expect (fp);
447
          break;
448
        case 'r':
449
          /* data sent from gdbreplay to gdb, play it */
450
          play (fp);
451
          break;
452
        case 'c':
453
          /* Command executed by gdb */
454
          while ((ch = logchar (fp)) != EOL);
455
          break;
456
        }
457
    }
458
  remote_close ();
459
  exit (0);
460
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.