OpenCores
URL https://opencores.org/ocsvn/openrisc_2011-10-31/openrisc_2011-10-31/trunk

Subversion Repositories openrisc_2011-10-31

[/] [openrisc/] [tags/] [gnu-src/] [gdb-6.8/] [pre-binutils-2.20.1-sync/] [gdb/] [gdbserver/] [gdbreplay.c] - Diff between revs 157 and 223

Only display areas with differences | Details | Blame | View Log

Rev 157 Rev 223
/* Replay a remote debug session logfile for GDB.
/* Replay a remote debug session logfile for GDB.
   Copyright (C) 1996, 1998, 1999, 2000, 2002, 2003, 2005, 2006, 2007, 2008
   Copyright (C) 1996, 1998, 1999, 2000, 2002, 2003, 2005, 2006, 2007, 2008
   Free Software Foundation, Inc.
   Free Software Foundation, Inc.
   Written by Fred Fish (fnf@cygnus.com) from pieces of gdbserver.
   Written by Fred Fish (fnf@cygnus.com) from pieces of gdbserver.
 
 
   This file is part of GDB.
   This file is part of GDB.
 
 
   This program is free software; you can redistribute it and/or modify
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 3 of the License, or
   the Free Software Foundation; either version 3 of the License, or
   (at your option) any later version.
   (at your option) any later version.
 
 
   This program is distributed in the hope that it will be useful,
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
   GNU General Public License for more details.
 
 
   You should have received a copy of the GNU General Public License
   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 
#include "config.h"
#include "config.h"
#include <stdio.h>
#include <stdio.h>
#if HAVE_SYS_FILE_H
#if HAVE_SYS_FILE_H
#include <sys/file.h>
#include <sys/file.h>
#endif
#endif
#if HAVE_SIGNAL_H
#if HAVE_SIGNAL_H
#include <signal.h>
#include <signal.h>
#endif
#endif
#include <ctype.h>
#include <ctype.h>
#if HAVE_FCNTL_H
#if HAVE_FCNTL_H
#include <fcntl.h>
#include <fcntl.h>
#endif
#endif
#if HAVE_ERRNO_H
#if HAVE_ERRNO_H
#include <errno.h>
#include <errno.h>
#endif
#endif
#ifdef HAVE_STDLIB_H
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#include <stdlib.h>
#endif
#endif
#ifdef HAVE_STRING_H
#ifdef HAVE_STRING_H
#include <string.h>
#include <string.h>
#endif
#endif
#ifdef HAVE_UNISTD_H
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#include <unistd.h>
#endif
#endif
#ifdef HAVE_NETINET_IN_H
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#include <netinet/in.h>
#endif
#endif
#ifdef HAVE_SYS_SOCKET_H
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#include <sys/socket.h>
#endif
#endif
#if HAVE_NETDB_H
#if HAVE_NETDB_H
#include <netdb.h>
#include <netdb.h>
#endif
#endif
#if HAVE_NETINET_TCP_H
#if HAVE_NETINET_TCP_H
#include <netinet/tcp.h>
#include <netinet/tcp.h>
#endif
#endif
#if HAVE_MALLOC_H
#if HAVE_MALLOC_H
#include <malloc.h>
#include <malloc.h>
#endif
#endif
 
 
#if USE_WIN32API
#if USE_WIN32API
#include <winsock.h>
#include <winsock.h>
#endif
#endif
 
 
#ifndef HAVE_SOCKLEN_T
#ifndef HAVE_SOCKLEN_T
typedef int socklen_t;
typedef int socklen_t;
#endif
#endif
 
 
/* Sort of a hack... */
/* Sort of a hack... */
#define EOL (EOF - 1)
#define EOL (EOF - 1)
 
 
static int remote_desc;
static int remote_desc;
 
 
#ifdef __MINGW32CE__
#ifdef __MINGW32CE__
 
 
#ifndef COUNTOF
#ifndef COUNTOF
#define COUNTOF(STR) (sizeof (STR) / sizeof ((STR)[0]))
#define COUNTOF(STR) (sizeof (STR) / sizeof ((STR)[0]))
#endif
#endif
 
 
#define errno (GetLastError ())
#define errno (GetLastError ())
 
 
char *
char *
strerror (DWORD error)
strerror (DWORD error)
{
{
  static char buf[1024];
  static char buf[1024];
  WCHAR *msgbuf;
  WCHAR *msgbuf;
  DWORD lasterr = GetLastError ();
  DWORD lasterr = GetLastError ();
  DWORD chars = FormatMessageW (FORMAT_MESSAGE_FROM_SYSTEM
  DWORD chars = FormatMessageW (FORMAT_MESSAGE_FROM_SYSTEM
                                | FORMAT_MESSAGE_ALLOCATE_BUFFER,
                                | FORMAT_MESSAGE_ALLOCATE_BUFFER,
                                NULL,
                                NULL,
                                error,
                                error,
                                0, /* Default language */
                                0, /* Default language */
                                (LPVOID)&msgbuf,
                                (LPVOID)&msgbuf,
                                0,
                                0,
                                NULL);
                                NULL);
  if (chars != 0)
  if (chars != 0)
    {
    {
      /* If there is an \r\n appended, zap it.  */
      /* If there is an \r\n appended, zap it.  */
      if (chars >= 2
      if (chars >= 2
          && msgbuf[chars - 2] == '\r'
          && msgbuf[chars - 2] == '\r'
          && msgbuf[chars - 1] == '\n')
          && msgbuf[chars - 1] == '\n')
        {
        {
          chars -= 2;
          chars -= 2;
          msgbuf[chars] = 0;
          msgbuf[chars] = 0;
        }
        }
 
 
      if (chars > ((COUNTOF (buf)) - 1))
      if (chars > ((COUNTOF (buf)) - 1))
        {
        {
          chars = COUNTOF (buf) - 1;
          chars = COUNTOF (buf) - 1;
          msgbuf [chars] = 0;
          msgbuf [chars] = 0;
        }
        }
 
 
      wcstombs (buf, msgbuf, chars + 1);
      wcstombs (buf, msgbuf, chars + 1);
      LocalFree (msgbuf);
      LocalFree (msgbuf);
    }
    }
  else
  else
    sprintf (buf, "unknown win32 error (%ld)", error);
    sprintf (buf, "unknown win32 error (%ld)", error);
 
 
  SetLastError (lasterr);
  SetLastError (lasterr);
  return buf;
  return buf;
}
}
 
 
#endif /* __MINGW32CE__ */
#endif /* __MINGW32CE__ */
 
 
/* Print the system error message for errno, and also mention STRING
/* Print the system error message for errno, and also mention STRING
   as the file name for which the error was encountered.
   as the file name for which the error was encountered.
   Then return to command level.  */
   Then return to command level.  */
 
 
static void
static void
perror_with_name (char *string)
perror_with_name (char *string)
{
{
#ifndef STDC_HEADERS
#ifndef STDC_HEADERS
  extern int errno;
  extern int errno;
#endif
#endif
  const char *err;
  const char *err;
  char *combined;
  char *combined;
 
 
  err = strerror (errno);
  err = strerror (errno);
  if (err == NULL)
  if (err == NULL)
    err = "unknown error";
    err = "unknown error";
 
 
  combined = (char *) alloca (strlen (err) + strlen (string) + 3);
  combined = (char *) alloca (strlen (err) + strlen (string) + 3);
  strcpy (combined, string);
  strcpy (combined, string);
  strcat (combined, ": ");
  strcat (combined, ": ");
  strcat (combined, err);
  strcat (combined, err);
  fprintf (stderr, "\n%s.\n", combined);
  fprintf (stderr, "\n%s.\n", combined);
  fflush (stderr);
  fflush (stderr);
  exit (1);
  exit (1);
}
}
 
 
static void
static void
sync_error (FILE *fp, char *desc, int expect, int got)
sync_error (FILE *fp, char *desc, int expect, int got)
{
{
  fprintf (stderr, "\n%s\n", desc);
  fprintf (stderr, "\n%s\n", desc);
  fprintf (stderr, "At logfile offset %ld, expected '0x%x' got '0x%x'\n",
  fprintf (stderr, "At logfile offset %ld, expected '0x%x' got '0x%x'\n",
           ftell (fp), expect, got);
           ftell (fp), expect, got);
  fflush (stderr);
  fflush (stderr);
  exit (1);
  exit (1);
}
}
 
 
static void
static void
remote_close (void)
remote_close (void)
{
{
#ifdef USE_WIN32API
#ifdef USE_WIN32API
  closesocket (remote_desc);
  closesocket (remote_desc);
#else
#else
  close (remote_desc);
  close (remote_desc);
#endif
#endif
}
}
 
 
/* Open a connection to a remote debugger.
/* Open a connection to a remote debugger.
   NAME is the filename used for communication.  */
   NAME is the filename used for communication.  */
 
 
static void
static void
remote_open (char *name)
remote_open (char *name)
{
{
  if (!strchr (name, ':'))
  if (!strchr (name, ':'))
    {
    {
      fprintf (stderr, "%s: Must specify tcp connection as host:addr\n", name);
      fprintf (stderr, "%s: Must specify tcp connection as host:addr\n", name);
      fflush (stderr);
      fflush (stderr);
      exit (1);
      exit (1);
    }
    }
  else
  else
    {
    {
#ifdef USE_WIN32API
#ifdef USE_WIN32API
      static int winsock_initialized;
      static int winsock_initialized;
#endif
#endif
      char *port_str;
      char *port_str;
      int port;
      int port;
      struct sockaddr_in sockaddr;
      struct sockaddr_in sockaddr;
      socklen_t tmp;
      socklen_t tmp;
      int tmp_desc;
      int tmp_desc;
 
 
      port_str = strchr (name, ':');
      port_str = strchr (name, ':');
 
 
      port = atoi (port_str + 1);
      port = atoi (port_str + 1);
 
 
#ifdef USE_WIN32API
#ifdef USE_WIN32API
      if (!winsock_initialized)
      if (!winsock_initialized)
        {
        {
          WSADATA wsad;
          WSADATA wsad;
 
 
          WSAStartup (MAKEWORD (1, 0), &wsad);
          WSAStartup (MAKEWORD (1, 0), &wsad);
          winsock_initialized = 1;
          winsock_initialized = 1;
        }
        }
#endif
#endif
 
 
      tmp_desc = socket (PF_INET, SOCK_STREAM, 0);
      tmp_desc = socket (PF_INET, SOCK_STREAM, 0);
      if (tmp_desc < 0)
      if (tmp_desc < 0)
        perror_with_name ("Can't open socket");
        perror_with_name ("Can't open socket");
 
 
      /* Allow rapid reuse of this port. */
      /* Allow rapid reuse of this port. */
      tmp = 1;
      tmp = 1;
      setsockopt (tmp_desc, SOL_SOCKET, SO_REUSEADDR, (char *) &tmp,
      setsockopt (tmp_desc, SOL_SOCKET, SO_REUSEADDR, (char *) &tmp,
                  sizeof (tmp));
                  sizeof (tmp));
 
 
      sockaddr.sin_family = PF_INET;
      sockaddr.sin_family = PF_INET;
      sockaddr.sin_port = htons (port);
      sockaddr.sin_port = htons (port);
      sockaddr.sin_addr.s_addr = INADDR_ANY;
      sockaddr.sin_addr.s_addr = INADDR_ANY;
 
 
      if (bind (tmp_desc, (struct sockaddr *) &sockaddr, sizeof (sockaddr))
      if (bind (tmp_desc, (struct sockaddr *) &sockaddr, sizeof (sockaddr))
          || listen (tmp_desc, 1))
          || listen (tmp_desc, 1))
        perror_with_name ("Can't bind address");
        perror_with_name ("Can't bind address");
 
 
      tmp = sizeof (sockaddr);
      tmp = sizeof (sockaddr);
      remote_desc = accept (tmp_desc, (struct sockaddr *) &sockaddr, &tmp);
      remote_desc = accept (tmp_desc, (struct sockaddr *) &sockaddr, &tmp);
      if (remote_desc == -1)
      if (remote_desc == -1)
        perror_with_name ("Accept failed");
        perror_with_name ("Accept failed");
 
 
      /* Enable TCP keep alive process. */
      /* Enable TCP keep alive process. */
      tmp = 1;
      tmp = 1;
      setsockopt (tmp_desc, SOL_SOCKET, SO_KEEPALIVE, (char *) &tmp, sizeof (tmp));
      setsockopt (tmp_desc, SOL_SOCKET, SO_KEEPALIVE, (char *) &tmp, sizeof (tmp));
 
 
      /* Tell TCP not to delay small packets.  This greatly speeds up
      /* Tell TCP not to delay small packets.  This greatly speeds up
         interactive response. */
         interactive response. */
      tmp = 1;
      tmp = 1;
      setsockopt (remote_desc, IPPROTO_TCP, TCP_NODELAY,
      setsockopt (remote_desc, IPPROTO_TCP, TCP_NODELAY,
                  (char *) &tmp, sizeof (tmp));
                  (char *) &tmp, sizeof (tmp));
 
 
#ifndef USE_WIN32API
#ifndef USE_WIN32API
      close (tmp_desc);         /* No longer need this */
      close (tmp_desc);         /* No longer need this */
 
 
      signal (SIGPIPE, SIG_IGN);        /* If we don't do this, then gdbreplay simply
      signal (SIGPIPE, SIG_IGN);        /* If we don't do this, then gdbreplay simply
                                           exits when the remote side dies.  */
                                           exits when the remote side dies.  */
#else
#else
      closesocket (tmp_desc);   /* No longer need this */
      closesocket (tmp_desc);   /* No longer need this */
#endif
#endif
    }
    }
 
 
#if defined(F_SETFL) && defined (FASYNC)
#if defined(F_SETFL) && defined (FASYNC)
  fcntl (remote_desc, F_SETFL, FASYNC);
  fcntl (remote_desc, F_SETFL, FASYNC);
#endif
#endif
 
 
  fprintf (stderr, "Replay logfile using %s\n", name);
  fprintf (stderr, "Replay logfile using %s\n", name);
  fflush (stderr);
  fflush (stderr);
}
}
 
 
static int
static int
tohex (int ch)
tohex (int ch)
{
{
  if (ch >= '0' && ch <= '9')
  if (ch >= '0' && ch <= '9')
    {
    {
      return (ch - '0');
      return (ch - '0');
    }
    }
  if (ch >= 'A' && ch <= 'F')
  if (ch >= 'A' && ch <= 'F')
    {
    {
      return (ch - 'A' + 10);
      return (ch - 'A' + 10);
    }
    }
  if (ch >= 'a' && ch <= 'f')
  if (ch >= 'a' && ch <= 'f')
    {
    {
      return (ch - 'a' + 10);
      return (ch - 'a' + 10);
    }
    }
  fprintf (stderr, "\nInvalid hex digit '%c'\n", ch);
  fprintf (stderr, "\nInvalid hex digit '%c'\n", ch);
  fflush (stderr);
  fflush (stderr);
  exit (1);
  exit (1);
}
}
 
 
static int
static int
logchar (FILE *fp)
logchar (FILE *fp)
{
{
  int ch;
  int ch;
  int ch2;
  int ch2;
 
 
  ch = fgetc (fp);
  ch = fgetc (fp);
  fputc (ch, stdout);
  fputc (ch, stdout);
  fflush (stdout);
  fflush (stdout);
  switch (ch)
  switch (ch)
    {
    {
    case '\n':
    case '\n':
      ch = EOL;
      ch = EOL;
      break;
      break;
    case '\\':
    case '\\':
      ch = fgetc (fp);
      ch = fgetc (fp);
      fputc (ch, stdout);
      fputc (ch, stdout);
      fflush (stdout);
      fflush (stdout);
      switch (ch)
      switch (ch)
        {
        {
        case '\\':
        case '\\':
          break;
          break;
        case 'b':
        case 'b':
          ch = '\b';
          ch = '\b';
          break;
          break;
        case 'f':
        case 'f':
          ch = '\f';
          ch = '\f';
          break;
          break;
        case 'n':
        case 'n':
          ch = '\n';
          ch = '\n';
          break;
          break;
        case 'r':
        case 'r':
          ch = '\r';
          ch = '\r';
          break;
          break;
        case 't':
        case 't':
          ch = '\t';
          ch = '\t';
          break;
          break;
        case 'v':
        case 'v':
          ch = '\v';
          ch = '\v';
          break;
          break;
        case 'x':
        case 'x':
          ch2 = fgetc (fp);
          ch2 = fgetc (fp);
          fputc (ch2, stdout);
          fputc (ch2, stdout);
          fflush (stdout);
          fflush (stdout);
          ch = tohex (ch2) << 4;
          ch = tohex (ch2) << 4;
          ch2 = fgetc (fp);
          ch2 = fgetc (fp);
          fputc (ch2, stdout);
          fputc (ch2, stdout);
          fflush (stdout);
          fflush (stdout);
          ch |= tohex (ch2);
          ch |= tohex (ch2);
          break;
          break;
        default:
        default:
          /* Treat any other char as just itself */
          /* Treat any other char as just itself */
          break;
          break;
        }
        }
    default:
    default:
      break;
      break;
    }
    }
  return (ch);
  return (ch);
}
}
 
 
/* Accept input from gdb and match with chars from fp (after skipping one
/* Accept input from gdb and match with chars from fp (after skipping one
   blank) up until a \n is read from fp (which is not matched) */
   blank) up until a \n is read from fp (which is not matched) */
 
 
static void
static void
expect (FILE *fp)
expect (FILE *fp)
{
{
  int fromlog;
  int fromlog;
  unsigned char fromgdb;
  unsigned char fromgdb;
 
 
  if ((fromlog = logchar (fp)) != ' ')
  if ((fromlog = logchar (fp)) != ' ')
    {
    {
      sync_error (fp, "Sync error during gdb read of leading blank", ' ',
      sync_error (fp, "Sync error during gdb read of leading blank", ' ',
                  fromlog);
                  fromlog);
    }
    }
  do
  do
    {
    {
      fromlog = logchar (fp);
      fromlog = logchar (fp);
      if (fromlog == EOL)
      if (fromlog == EOL)
        {
        {
          break;
          break;
        }
        }
      read (remote_desc, &fromgdb, 1);
      read (remote_desc, &fromgdb, 1);
    }
    }
  while (fromlog == fromgdb);
  while (fromlog == fromgdb);
  if (fromlog != EOL)
  if (fromlog != EOL)
    {
    {
      sync_error (fp, "Sync error during read of gdb packet", fromlog,
      sync_error (fp, "Sync error during read of gdb packet", fromlog,
                  fromgdb);
                  fromgdb);
    }
    }
}
}
 
 
/* Play data back to gdb from fp (after skipping leading blank) up until a
/* Play data back to gdb from fp (after skipping leading blank) up until a
   \n is read from fp (which is discarded and not sent to gdb). */
   \n is read from fp (which is discarded and not sent to gdb). */
 
 
static void
static void
play (FILE *fp)
play (FILE *fp)
{
{
  int fromlog;
  int fromlog;
  char ch;
  char ch;
 
 
  if ((fromlog = logchar (fp)) != ' ')
  if ((fromlog = logchar (fp)) != ' ')
    {
    {
      sync_error (fp, "Sync error skipping blank during write to gdb", ' ',
      sync_error (fp, "Sync error skipping blank during write to gdb", ' ',
                  fromlog);
                  fromlog);
    }
    }
  while ((fromlog = logchar (fp)) != EOL)
  while ((fromlog = logchar (fp)) != EOL)
    {
    {
      ch = fromlog;
      ch = fromlog;
      write (remote_desc, &ch, 1);
      write (remote_desc, &ch, 1);
    }
    }
}
}
 
 
int
int
main (int argc, char *argv[])
main (int argc, char *argv[])
{
{
  FILE *fp;
  FILE *fp;
  int ch;
  int ch;
 
 
  if (argc < 3)
  if (argc < 3)
    {
    {
      fprintf (stderr, "Usage: gdbreplay <logfile> <host:port>\n");
      fprintf (stderr, "Usage: gdbreplay <logfile> <host:port>\n");
      fflush (stderr);
      fflush (stderr);
      exit (1);
      exit (1);
    }
    }
  fp = fopen (argv[1], "r");
  fp = fopen (argv[1], "r");
  if (fp == NULL)
  if (fp == NULL)
    {
    {
      perror_with_name (argv[1]);
      perror_with_name (argv[1]);
    }
    }
  remote_open (argv[2]);
  remote_open (argv[2]);
  while ((ch = logchar (fp)) != EOF)
  while ((ch = logchar (fp)) != EOF)
    {
    {
      switch (ch)
      switch (ch)
        {
        {
        case 'w':
        case 'w':
          /* data sent from gdb to gdbreplay, accept and match it */
          /* data sent from gdb to gdbreplay, accept and match it */
          expect (fp);
          expect (fp);
          break;
          break;
        case 'r':
        case 'r':
          /* data sent from gdbreplay to gdb, play it */
          /* data sent from gdbreplay to gdb, play it */
          play (fp);
          play (fp);
          break;
          break;
        case 'c':
        case 'c':
          /* Command executed by gdb */
          /* Command executed by gdb */
          while ((ch = logchar (fp)) != EOL);
          while ((ch = logchar (fp)) != EOL);
          break;
          break;
        }
        }
    }
    }
  remote_close ();
  remote_close ();
  exit (0);
  exit (0);
}
}
 
 

powered by: WebSVN 2.1.0

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