X-Git-Url: http://drtracing.org/?a=blobdiff_plain;ds=sidebyside;f=gdb%2Fgdbserver%2Fgdbreplay.c;h=1f823e0addc59eee8c621d158d189ea8ddeb9e6c;hb=a3d08894e544f6b9e65581469cbbafbe39a353fe;hp=577396222f7690c9e7b8cbe57d4aa85c7e6d3fee;hpb=dc9e099fc0eced486ae2b49455c9da113c11f4ff;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/gdbserver/gdbreplay.c b/gdb/gdbserver/gdbreplay.c index 577396222f..1f823e0add 100644 --- a/gdb/gdbserver/gdbreplay.c +++ b/gdb/gdbserver/gdbreplay.c @@ -1,12 +1,12 @@ /* Replay a remote debug session logfile for GDB. - Copyright (C) 1996 Free Software Foundation, Inc. + Copyright (C) 1996-2013 Free Software Foundation, Inc. Written by Fred Fish (fnf@cygnus.com) from pieces of gdbserver. This file is part of GDB. 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 - the Free Software Foundation; either version 2 of the License, or + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, @@ -15,40 +15,130 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ + along with this program. If not, see . */ + +#include "config.h" +#include "build-gnulib-gdbserver/config.h" +#include "version.h" #include +#if HAVE_SYS_FILE_H #include +#endif +#if HAVE_SIGNAL_H +#include +#endif +#include +#if HAVE_FCNTL_H +#include +#endif +#if HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +#include +#include +#ifdef HAVE_NETINET_IN_H #include +#endif +#ifdef HAVE_SYS_SOCKET_H #include +#endif +#if HAVE_NETDB_H #include +#endif +#if HAVE_NETINET_TCP_H #include -#include -#include -#include +#endif +#if HAVE_ALLOCA_H +#include +#endif +#if HAVE_MALLOC_H +#include +#endif +#if USE_WIN32API +#include +#endif + +#ifndef HAVE_SOCKLEN_T +typedef int socklen_t; +#endif /* Sort of a hack... */ #define EOL (EOF - 1) static int remote_desc; +#ifdef __MINGW32CE__ + +#ifndef COUNTOF +#define COUNTOF(STR) (sizeof (STR) / sizeof ((STR)[0])) +#endif + +#define errno (GetLastError ()) + +char * +strerror (DWORD error) +{ + static char buf[1024]; + WCHAR *msgbuf; + DWORD lasterr = GetLastError (); + DWORD chars = FormatMessageW (FORMAT_MESSAGE_FROM_SYSTEM + | FORMAT_MESSAGE_ALLOCATE_BUFFER, + NULL, + error, + 0, /* Default language */ + (LPVOID)&msgbuf, + 0, + NULL); + if (chars != 0) + { + /* If there is an \r\n appended, zap it. */ + if (chars >= 2 + && msgbuf[chars - 2] == '\r' + && msgbuf[chars - 1] == '\n') + { + chars -= 2; + msgbuf[chars] = 0; + } + + if (chars > ((COUNTOF (buf)) - 1)) + { + chars = COUNTOF (buf) - 1; + msgbuf [chars] = 0; + } + + wcstombs (buf, msgbuf, chars + 1); + LocalFree (msgbuf); + } + else + sprintf (buf, "unknown win32 error (%ld)", error); + + SetLastError (lasterr); + return buf; +} + +#endif /* __MINGW32CE__ */ + /* Print the system error message for errno, and also mention STRING as the file name for which the error was encountered. Then return to command level. */ -void -perror_with_name (string) - char *string; +static void +perror_with_name (const char *string) { - extern int sys_nerr; - extern char *sys_errlist[]; +#ifndef STDC_HEADERS extern int errno; - char *err; +#endif + const char *err; char *combined; - err = (errno < sys_nerr) ? sys_errlist[errno] : "unknown error"; + err = strerror (errno); + if (err == NULL) + err = "unknown error"; + combined = (char *) alloca (strlen (err) + strlen (string) + 3); strcpy (combined, string); strcat (combined, ": "); @@ -59,11 +149,7 @@ perror_with_name (string) } static void -sync_error (fp, desc, expect, got) - 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, "At logfile offset %ld, expected '0x%x' got '0x%x'\n", @@ -72,21 +158,30 @@ sync_error (fp, desc, expect, got) exit (1); } -void -remote_close () +static void +remote_error (const char *desc) { + fprintf (stderr, "\n%s\n", desc); + fflush (stderr); + exit (1); +} + +static void +remote_close (void) +{ +#ifdef USE_WIN32API + closesocket (remote_desc); +#else close (remote_desc); +#endif } /* Open a connection to a remote debugger. NAME is the filename used for communication. */ -void -remote_open (name) - char *name; +static void +remote_open (char *name) { - extern char *strchr (); - if (!strchr (name, ':')) { fprintf (stderr, "%s: Must specify tcp connection as host:addr\n", name); @@ -95,19 +190,31 @@ remote_open (name) } else { +#ifdef USE_WIN32API + static int winsock_initialized; +#endif char *port_str; int port; struct sockaddr_in sockaddr; - int tmp; - struct protoent *protoent; + socklen_t tmp; int tmp_desc; port_str = strchr (name, ':'); port = atoi (port_str + 1); +#ifdef USE_WIN32API + if (!winsock_initialized) + { + WSADATA wsad; + + WSAStartup (MAKEWORD (1, 0), &wsad); + winsock_initialized = 1; + } +#endif + tmp_desc = socket (PF_INET, SOCK_STREAM, 0); - if (tmp_desc < 0) + if (tmp_desc == -1) perror_with_name ("Can't open socket"); /* Allow rapid reuse of this port. */ @@ -128,35 +235,38 @@ remote_open (name) if (remote_desc == -1) perror_with_name ("Accept failed"); - protoent = getprotobyname ("tcp"); - if (!protoent) - perror_with_name ("getprotobyname"); - /* Enable TCP keep alive process. */ 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 - interactive response. */ + interactive response. */ tmp = 1; - setsockopt (remote_desc, protoent->p_proto, TCP_NODELAY, + setsockopt (remote_desc, IPPROTO_TCP, TCP_NODELAY, (char *) &tmp, sizeof (tmp)); +#ifndef USE_WIN32API close (tmp_desc); /* No longer need this */ - signal (SIGPIPE, SIG_IGN); /* If we don't do this, then gdbreplay simply - exits when the remote side dies. */ + signal (SIGPIPE, SIG_IGN); /* If we don't do this, then + gdbreplay simply exits when + the remote side dies. */ +#else + closesocket (tmp_desc); /* No longer need this */ +#endif } +#if defined(F_SETFL) && defined (FASYNC) fcntl (remote_desc, F_SETFL, FASYNC); +#endif fprintf (stderr, "Replay logfile using %s\n", name); fflush (stderr); } static int -tohex (ch) - int ch; +tohex (int ch) { if (ch >= '0' && ch <= '9') { @@ -176,8 +286,7 @@ tohex (ch) } static int -logchar (fp) - FILE *fp; +logchar (FILE *fp) { int ch; int ch2; @@ -236,15 +345,25 @@ logchar (fp) return (ch); } +static int +gdbchar (int desc) +{ + unsigned char fromgdb; + + if (read (desc, &fromgdb, 1) != 1) + return -1; + else + return fromgdb; +} + /* 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) */ -void -expect (fp) - FILE *fp; +static void +expect (FILE *fp) { int fromlog; - unsigned char fromgdb; + int fromgdb; if ((fromlog = logchar (fp)) != ' ') { @@ -255,15 +374,16 @@ expect (fp) { fromlog = logchar (fp); if (fromlog == EOL) - { - break; - } - read (remote_desc, &fromgdb, 1); + break; + fromgdb = gdbchar (remote_desc); + if (fromgdb < 0) + remote_error ("Error during read from gdb"); } while (fromlog == fromgdb); + if (fromlog != EOL) { - sync_error (fp, "Sync error during read of gdb packet", fromlog, + sync_error (fp, "Sync error during read of gdb packet from log", fromlog, fromgdb); } } @@ -271,9 +391,8 @@ expect (fp) /* 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). */ -void -play (fp) - FILE *fp; +static void +play (FILE *fp) { int fromlog; char ch; @@ -286,22 +405,50 @@ play (fp) while ((fromlog = logchar (fp)) != EOL) { ch = fromlog; - write (remote_desc, &ch, 1); + if (write (remote_desc, &ch, 1) != 1) + remote_error ("Error during write to gdb"); } } +static void +gdbreplay_version (void) +{ + printf ("GNU gdbreplay %s%s\n" + "Copyright (C) 2013 Free Software Foundation, Inc.\n" + "gdbreplay is free software, covered by " + "the GNU General Public License.\n" + "This gdbreplay was configured as \"%s\"\n", + PKGVERSION, version, host_name); +} + +static void +gdbreplay_usage (FILE *stream) +{ + fprintf (stream, "Usage:\tgdbreplay \n"); + if (REPORT_BUGS_TO[0] && stream == stdout) + fprintf (stream, "Report bugs to \"%s\".\n", REPORT_BUGS_TO); +} + int -main (argc, argv) - int argc; - char *argv[]; +main (int argc, char *argv[]) { FILE *fp; int ch; + if (argc >= 2 && strcmp (argv[1], "--version") == 0) + { + gdbreplay_version (); + exit (0); + } + if (argc >= 2 && strcmp (argv[1], "--help") == 0) + { + gdbreplay_usage (stdout); + exit (0); + } + if (argc < 3) { - fprintf (stderr, "Usage: gdbreplay \n"); - fflush (stderr); + gdbreplay_usage (stderr); exit (1); } fp = fopen (argv[1], "r");