X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Fgdbserver%2Fgdbreplay.c;h=6ce00b3e2242580c1a307e296b479bb40e006809;hb=505106cdc7c816a44bbfee11daf500f4e5e14072;hp=4fabf1d90e42d6b8057a18bd3d9d651ca369665c;hpb=fba45db2faf619e71856ee38ec63949c0ef6903e;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/gdbserver/gdbreplay.c b/gdb/gdbserver/gdbreplay.c index 4fabf1d90e..6ce00b3e22 100644 --- a/gdb/gdbserver/gdbreplay.c +++ b/gdb/gdbserver/gdbreplay.c @@ -1,12 +1,13 @@ /* Replay a remote debug session logfile for GDB. - Copyright (C) 1996 Free Software Foundation, Inc. + Copyright (C) 1996, 1998, 1999, 2000, 2002, 2003, 2005, 2006, 2007, 2008, + 2009, 2010 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,43 +16,133 @@ 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 +#if HAVE_SYS_FILE_H #include -#include -#include -#include -#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 +#ifdef HAVE_STRING_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif +#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 +#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) +/* Version information, from version.c. */ +extern const char version[]; +extern const char host_name[]; + 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 (char *string) +static void +perror_with_name (const char *string) { #ifndef STDC_HEADERS - extern int sys_nerr; - extern char *sys_errlist[]; extern int errno; #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, ": "); @@ -71,20 +162,22 @@ sync_error (FILE *fp, char *desc, int expect, int got) exit (1); } -void +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 +static void remote_open (char *name) { - extern char *strchr (); - if (!strchr (name, ':')) { fprintf (stderr, "%s: Must specify tcp connection as host:addr\n", name); @@ -93,17 +186,29 @@ remote_open (char *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) perror_with_name ("Can't open socket"); @@ -126,27 +231,29 @@ remote_open (char *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)); /* 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. */ +#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); @@ -235,7 +342,7 @@ logchar (FILE *fp) /* 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 +static void expect (FILE *fp) { int fromlog; @@ -266,7 +373,7 @@ expect (FILE *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 +static void play (FILE *fp) { int fromlog; @@ -284,18 +391,44 @@ play (FILE *fp) } } +static void +gdbreplay_version (void) +{ + printf ("GNU gdbreplay %s%s\n" + "Copyright (C) 2010 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");