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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [gdb-5.0/] [gdb/] [gdbserver/] [gdbreplay.c] - Diff between revs 107 and 1765

Go to most recent revision | Only display areas with differences | Details | Blame | View Log

Rev 107 Rev 1765
/* Replay a remote debug session logfile for GDB.
/* Replay a remote debug session logfile for GDB.
   Copyright (C) 1996 Free Software Foundation, Inc.
   Copyright (C) 1996 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 2 of the License, or
   the Free Software Foundation; either version 2 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, write to the Free Software
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place - Suite 330,
   Foundation, Inc., 59 Temple Place - Suite 330,
   Boston, MA 02111-1307, USA.  */
   Boston, MA 02111-1307, USA.  */
 
 
#include "config.h"
#include "config.h"
#include <stdio.h>
#include <stdio.h>
#include <sys/file.h>
#include <sys/file.h>
#include <netinet/in.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netdb.h>
#include <netinet/tcp.h>
#include <netinet/tcp.h>
#include <signal.h>
#include <signal.h>
#include <ctype.h>
#include <ctype.h>
#include <fcntl.h>
#include <fcntl.h>
#include <errno.h>
#include <errno.h>
 
 
/* Sort of a hack... */
/* Sort of a hack... */
#define EOL (EOF - 1)
#define EOL (EOF - 1)
 
 
static int remote_desc;
static int remote_desc;
 
 
/* 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.  */
 
 
void
void
perror_with_name (string)
perror_with_name (string)
     char *string;
     char *string;
{
{
#ifndef STDC_HEADERS
#ifndef STDC_HEADERS
  extern int sys_nerr;
  extern int sys_nerr;
  extern char *sys_errlist[];
  extern char *sys_errlist[];
  extern int errno;
  extern int errno;
#endif
#endif
  const char *err;
  const char *err;
  char *combined;
  char *combined;
 
 
  err = (errno < sys_nerr) ? sys_errlist[errno] : "unknown error";
  err = (errno < sys_nerr) ? sys_errlist[errno] : "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 (fp, desc, expect, got)
sync_error (fp, desc, expect, got)
     FILE *fp;
     FILE *fp;
     char *desc;
     char *desc;
     int expect;
     int expect;
     int got;
     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);
}
}
 
 
void
void
remote_close ()
remote_close ()
{
{
  close (remote_desc);
  close (remote_desc);
}
}
 
 
/* 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.  */
 
 
void
void
remote_open (name)
remote_open (name)
     char *name;
     char *name;
{
{
  extern char *strchr ();
  extern char *strchr ();
 
 
  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
    {
    {
      char *port_str;
      char *port_str;
      int port;
      int port;
      struct sockaddr_in sockaddr;
      struct sockaddr_in sockaddr;
      int tmp;
      int tmp;
      struct protoent *protoent;
      struct protoent *protoent;
      int tmp_desc;
      int tmp_desc;
 
 
      port_str = strchr (name, ':');
      port_str = strchr (name, ':');
 
 
      port = atoi (port_str + 1);
      port = atoi (port_str + 1);
 
 
      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");
 
 
      protoent = getprotobyname ("tcp");
      protoent = getprotobyname ("tcp");
      if (!protoent)
      if (!protoent)
        perror_with_name ("getprotobyname");
        perror_with_name ("getprotobyname");
 
 
      /* 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, protoent->p_proto, TCP_NODELAY,
      setsockopt (remote_desc, protoent->p_proto, TCP_NODELAY,
                  (char *) &tmp, sizeof (tmp));
                  (char *) &tmp, sizeof (tmp));
 
 
      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.  */
    }
    }
 
 
  fcntl (remote_desc, F_SETFL, FASYNC);
  fcntl (remote_desc, F_SETFL, FASYNC);
 
 
  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 (ch)
tohex (ch)
     int ch;
     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 (fp)
logchar (fp)
     FILE *fp;
     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) */
 
 
void
void
expect (fp)
expect (fp)
     FILE *fp;
     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). */
 
 
void
void
play (fp)
play (fp)
     FILE *fp;
     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 (argc, argv)
main (argc, argv)
     int argc;
     int argc;
     char *argv[];
     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.