* NEWS: Mention native Windows support.

* Makefile.in (gdb_select_h, ser_tcp_h): New.
	(ALLDEPFILES): Add ser-mingw.c.
	(event-loop.o, inflow.o, mingw-hdep.o, posix-hdep.o, ser-base.o)
	(ser-tcp.o, ser-unix.o): Update.
	(ser-mingw.o): New rule.
	* configure: Regenerated.
	* configure.ac: Add ser-mingw.o for mingw32.
	* ser-mingw.c: New file.
	* event-loop.c: Include "gdb_select.h".
	(gdb_select): Remove, moved to mingw-hdep.c and posix-hdep.c.
	* ser-base.c: Include "gdb_select.h".
	(ser_base_wait_for): Use gdb_select.
	* serial.c (serial_for_fd): New function.
	(serial_fdopen): Try "terminal" before "hardwire".  Initialize
	the allocated struct serial.
	(serial_wait_handle): New function.
	* serial.h (serial_for_fd, serial_wait_handle): New prototypes.
	(struct serial_ops) [USE_WIN32API]: Add wait_handle.
	* gdb_select.h: New file.
	* ser-tcp.c: Include "ser-tcp.h".  Remove unused "ser-unix.h" include.
	(net_close, net_read_prim, net_write_prim): Make global.
	(net_open): Likewise.  Pass an exception set to select.  Whitespace fix.
	Document why we can not use gdb_select.
	(_initialize_ser_tcp) [USE_WIN32API]: Do not register TCP support here.
	* ser-tcp.h: New file.
	* inflow.c (gdb_has_a_terminal): Don't initialize stdin_serial here.
	(handle_sigio): Use gdb_select.
	(initialize_stdin_serial): New function.
	* terminal.h (initialize_stdin_serial): New prototype.
	* top.c (gdb_init): Call initialize_stdin_serial.
	* mingw-hdep.c (gdb_select): New function, moved from gdb_select in
	event-loop.c.  Add exception condition support.  Use serial_for_fd
	and serial_wait_handle.  Fix timeout handling.
	* posix-hdep.c: Include "gdb_select.h".
	(gdb_select): New function.
	* remote-st.c (connect_command): Use gdb_select.
	* ser-unix.c: Include "gdb_select.h".
	(hardwire_send_break, wait_for): Use gdb_select.
This commit is contained in:
Daniel Jacobowitz 2006-02-10 22:01:43 +00:00
parent 121ce6e53d
commit 0ea3f30e21
20 changed files with 1181 additions and 138 deletions

View File

@ -1,3 +1,45 @@
2006-02-10 Daniel Jacobowitz <dan@codesourcery.com>
* NEWS: Mention native Windows support.
* Makefile.in (gdb_select_h, ser_tcp_h): New.
(ALLDEPFILES): Add ser-mingw.c.
(event-loop.o, inflow.o, mingw-hdep.o, posix-hdep.o, ser-base.o)
(ser-tcp.o, ser-unix.o): Update.
(ser-mingw.o): New rule.
* configure: Regenerated.
* configure.ac: Add ser-mingw.o for mingw32.
* ser-mingw.c: New file.
* event-loop.c: Include "gdb_select.h".
(gdb_select): Remove, moved to mingw-hdep.c and posix-hdep.c.
* ser-base.c: Include "gdb_select.h".
(ser_base_wait_for): Use gdb_select.
* serial.c (serial_for_fd): New function.
(serial_fdopen): Try "terminal" before "hardwire". Initialize
the allocated struct serial.
(serial_wait_handle): New function.
* serial.h (serial_for_fd, serial_wait_handle): New prototypes.
(struct serial_ops) [USE_WIN32API]: Add wait_handle.
* gdb_select.h: New file.
* ser-tcp.c: Include "ser-tcp.h". Remove unused "ser-unix.h" include.
(net_close, net_read_prim, net_write_prim): Make global.
(net_open): Likewise. Pass an exception set to select. Whitespace fix.
Document why we can not use gdb_select.
(_initialize_ser_tcp) [USE_WIN32API]: Do not register TCP support here.
* ser-tcp.h: New file.
* inflow.c (gdb_has_a_terminal): Don't initialize stdin_serial here.
(handle_sigio): Use gdb_select.
(initialize_stdin_serial): New function.
* terminal.h (initialize_stdin_serial): New prototype.
* top.c (gdb_init): Call initialize_stdin_serial.
* mingw-hdep.c (gdb_select): New function, moved from gdb_select in
event-loop.c. Add exception condition support. Use serial_for_fd
and serial_wait_handle. Fix timeout handling.
* posix-hdep.c: Include "gdb_select.h".
(gdb_select): New function.
* remote-st.c (connect_command): Use gdb_select.
* ser-unix.c: Include "gdb_select.h".
(hardwire_send_break, wait_for): Use gdb_select.
2006-02-10 Daniel Jacobowitz <dan@codesourcery.com>
* Makefile.in (mingw-hdep.o, posix-hdep.o): New dependencies.

View File

@ -694,6 +694,7 @@ gdb_obstack_h = gdb_obstack.h $(obstack_h)
gdb_proc_service_h = gdb_proc_service.h $(gregset_h)
gdb_ptrace_h = gdb_ptrace.h
gdb_regex_h = gdb_regex.h $(xregex_h)
gdb_select_h = gdb_select.h
gdb_stabs_h = gdb-stabs.h
gdb_stat_h = gdb_stat.h
gdb_string_h = gdb_string.h
@ -767,6 +768,7 @@ scm_tags_h = scm-tags.h
sentinel_frame_h = sentinel-frame.h
serial_h = serial.h
ser_base_h = ser-base.h
ser_tcp_h = ser-tcp.h
ser_unix_h = ser-unix.h
shnbsd_tdep_h = shnbsd-tdep.h
sh_tdep_h = sh-tdep.h
@ -1445,7 +1447,7 @@ ALLDEPFILES = \
remote-st.c remote-utils.c dcache.c \
rs6000-nat.c rs6000-tdep.c \
s390-tdep.c s390-nat.c \
ser-go32.c ser-pipe.c ser-tcp.c \
ser-go32.c ser-pipe.c ser-tcp.c ser-mingw.c \
sh-tdep.c sh64-tdep.c shnbsd-tdep.c shnbsd-nat.c \
sol2-tdep.c \
solib-irix.c solib-svr4.c solib-sunos.c \
@ -1922,7 +1924,7 @@ eval.o: eval.c $(defs_h) $(gdb_string_h) $(symtab_h) $(gdbtypes_h) \
$(f_lang_h) $(cp_abi_h) $(infcall_h) $(objc_lang_h) $(block_h) \
$(parser_defs_h) $(cp_support_h)
event-loop.o: event-loop.c $(defs_h) $(event_loop_h) $(event_top_h) \
$(gdb_string_h) $(exceptions_h) $(gdb_assert_h)
$(gdb_string_h) $(exceptions_h) $(gdb_assert_h) $(gdb_select_h)
event-top.o: event-top.c $(defs_h) $(top_h) $(inferior_h) $(target_h) \
$(terminal_h) $(event_loop_h) $(event_top_h) $(interps_h) \
$(exceptions_h) $(gdbcmd_h) $(readline_h) $(readline_history_h)
@ -2129,7 +2131,7 @@ inf-loop.o: inf-loop.c $(defs_h) $(inferior_h) $(target_h) $(event_loop_h) \
$(event_top_h) $(inf_loop_h) $(remote_h) $(exceptions_h)
inflow.o: inflow.c $(defs_h) $(frame_h) $(inferior_h) $(command_h) \
$(serial_h) $(terminal_h) $(target_h) $(gdbthread_h) $(gdb_string_h) \
$(inflow_h)
$(inflow_h) $(gdb_select_h)
inf-ptrace.o: inf-ptrace.c $(defs_h) $(command_h) $(inferior_h) $(inflow_h) \
$(gdbcore_h) $(regcache_h) $(gdb_assert_h) \
$(gdb_string_h) $(gdb_ptrace_h) $(gdb_wait_h) $(inf_child_h)
@ -2282,7 +2284,8 @@ memattr.o: memattr.c $(defs_h) $(command_h) $(gdbcmd_h) $(memattr_h) \
$(target_h) $(value_h) $(language_h) $(gdb_string_h)
mem-break.o: mem-break.c $(defs_h) $(symtab_h) $(breakpoint_h) $(inferior_h) \
$(target_h)
mingw-hdep.o: mingw-hdep.c $(defs_h) $(gdb_string_h)
mingw-hdep.o: mingw-hdep.c $(defs_h) $(serial_h) $(gdb_assert_h) \
$(gdb_select_h) $(gdb_string_h)
minsyms.o: minsyms.c $(defs_h) $(gdb_string_h) $(symtab_h) $(bfd_h) \
$(symfile_h) $(objfiles_h) $(demangle_h) $(value_h) $(cp_abi_h)
mips64obsd-nat.o: mips64obsd-nat.c $(defs_h) $(inferior_h) $(regcache_h) \
@ -2378,7 +2381,7 @@ p-exp.o: p-exp.c $(defs_h) $(gdb_string_h) $(expression_h) $(value_h) \
p-lang.o: p-lang.c $(defs_h) $(gdb_string_h) $(symtab_h) $(gdbtypes_h) \
$(expression_h) $(parser_defs_h) $(language_h) $(p_lang_h) \
$(valprint_h) $(value_h)
posix-hdep.o: posix-hdep.c $(defs_h) $(gdb_string_h)
posix-hdep.o: posix-hdep.c $(defs_h) $(gdb_string_h) $(gdb_select_h)
ppc-bdm.o: ppc-bdm.c $(defs_h) $(gdbcore_h) $(gdb_string_h) $(frame_h) \
$(inferior_h) $(bfd_h) $(symfile_h) $(target_h) $(gdbcmd_h) \
$(objfiles_h) $(gdb_stabs_h) $(serial_h) $(ocd_h) $(ppc_tdep_h) \
@ -2517,13 +2520,15 @@ ser-e7kpc.o: ser-e7kpc.c $(defs_h) $(serial_h) $(gdb_string_h)
ser-go32.o: ser-go32.c $(defs_h) $(gdbcmd_h) $(serial_h) $(gdb_string_h)
serial.o: serial.c $(defs_h) $(serial_h) $(gdb_string_h) $(gdbcmd_h)
ser-base.o: ser-base.c $(defs_h) $(serial_h) $(ser_base_h) $(event_loop_h) \
$(gdb_string_h)
$(gdb_select_h) $(gdb_string_h)
ser-pipe.o: ser-pipe.c $(defs_h) $(serial_h) $(ser_base_h) $(ser_unix_h) \
$(gdb_vfork_h) $(gdb_string_h)
ser-tcp.o: ser-tcp.c $(defs_h) $(serial_h) $(ser_base_h) $(ser_unix_h) \
ser-tcp.o: ser-tcp.c $(defs_h) $(serial_h) $(ser_base_h) $(ser_tcp_h) \
$(gdb_string_h)
ser-unix.o: ser-unix.c $(defs_h) $(serial_h) $(ser_base_h) $(ser_unix_h) \
$(terminal_h) $(gdb_string_h)
$(terminal_h) $(gdb_select_h) $(gdb_string_h)
ser-mingw.o: ser-mingw.c $(defs_h) $(serial_h) $(ser_base_h) \
$(ser_tcp_h) $(gdb_assert_h) $(gdb_string_h)
sh3-rom.o: sh3-rom.c $(defs_h) $(gdbcore_h) $(target_h) $(monitor_h) \
$(serial_h) $(srec_h) $(arch_utils_h) $(regcache_h) $(gdb_string_h) \
$(sh_tdep_h)

View File

@ -41,6 +41,12 @@ detach-fork <n> Delete a fork from the list of forks
Morpho Technologies ms2 ms1-elf
* Improved Windows host support
GDB now builds as a cross debugger hosted on i686-mingw32, including
native console support, and remote communications using either
network sockets or serial ports.
* REMOVED features
The ARM rdi-share module.

2
gdb/configure vendored
View File

@ -20097,7 +20097,7 @@ SER_HARDWIRE="ser-base.o ser-unix.o ser-pipe.o ser-tcp.o"
case ${host} in
*go32* ) SER_HARDWIRE=ser-go32.o ;;
*djgpp* ) SER_HARDWIRE=ser-go32.o ;;
*mingw32*) SER_HARDWIRE="ser-base.o ser-tcp.o" ;;
*mingw32*) SER_HARDWIRE="ser-base.o ser-tcp.o ser-mingw.o" ;;
esac

View File

@ -1,5 +1,6 @@
dnl Autoconf configure script for GDB, the GNU debugger.
dnl Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
dnl Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
dnl 2005, 2006
dnl Free Software Foundation, Inc.
dnl
dnl This file is part of GDB.
@ -1202,7 +1203,7 @@ SER_HARDWIRE="ser-base.o ser-unix.o ser-pipe.o ser-tcp.o"
case ${host} in
*go32* ) SER_HARDWIRE=ser-go32.o ;;
*djgpp* ) SER_HARDWIRE=ser-go32.o ;;
*mingw32*) SER_HARDWIRE="ser-base.o ser-tcp.o" ;;
*mingw32*) SER_HARDWIRE="ser-base.o ser-tcp.o ser-mingw.o" ;;
esac
AC_SUBST(SER_HARDWIRE)

View File

@ -1,5 +1,6 @@
/* Event loop machinery for GDB, the GNU debugger.
Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
Copyright (C) 1999, 2000, 2001, 2002, 2005, 2006
Free Software Foundation, Inc.
Written by Elena Zannoni <ezannoni@cygnus.com> of Cygnus Solutions.
This file is part of GDB.
@ -37,6 +38,7 @@
#include <sys/time.h>
#include "exceptions.h"
#include "gdb_assert.h"
#include "gdb_select.h"
typedef struct gdb_event gdb_event;
typedef void (event_handler_func) (int);
@ -731,97 +733,6 @@ handle_file_event (int event_file_desc)
}
}
/* Wrapper for select. This function is not yet exported from this
file because it is not sufficiently general. For example,
ser-base.c uses select to check for socket activity, and this
function does not support sockets under Windows, so we do not want
to use gdb_select in ser-base.c. */
static int
gdb_select (int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
struct timeval *timeout)
{
#ifdef USE_WIN32API
HANDLE handles[MAXIMUM_WAIT_OBJECTS];
HANDLE h;
DWORD event;
DWORD num_handles;
int fd;
int num_ready;
num_ready = 0;
num_handles = 0;
for (fd = 0; fd < n; ++fd)
{
/* There is no support yet for WRITEFDS. At present, this isn't
used by GDB -- but we do not want to silently ignore WRITEFDS
if something starts using it. */
gdb_assert (!FD_ISSET (fd, writefds));
if (!FD_ISSET (fd, readfds)
&& !FD_ISSET (fd, exceptfds))
continue;
h = (HANDLE) _get_osfhandle (fd);
if (h == INVALID_HANDLE_VALUE)
{
/* If the underlying handle is INVALID_HANDLE_VALUE, then
this descriptor is no more. */
if (FD_ISSET (fd, exceptfds))
++num_ready;
continue;
}
/* The only exceptional condition we recognize is a closed file
descriptor. Since we have already checked for that
condition, clear the exceptional bit for this descriptor. */
FD_CLR (fd, exceptfds);
if (FD_ISSET (fd, readfds))
{
gdb_assert (num_handles < MAXIMUM_WAIT_OBJECTS);
handles[num_handles++] = h;
}
}
/* If we don't need to wait for any handles, we are done. */
if (!num_handles)
return num_ready;
event = WaitForMultipleObjects (num_handles,
handles,
FALSE,
timeout
? (timeout->tv_sec * 1000 + timeout->tv_usec)
: INFINITE);
/* EVENT can only be a value in the WAIT_ABANDONED_0 range if the
HANDLES included an abandoned mutex. Since GDB doesn't use
mutexes, that should never occur. */
gdb_assert (!(WAIT_ABANDONED_0 <= event
&& event < WAIT_ABANDONED_0 + num_handles));
if (event == WAIT_FAILED)
return -1;
if (event == WAIT_TIMEOUT)
return num_ready;
/* Run through the READFDS, clearing bits corresponding to descriptors
for which input is unavailable. */
num_ready += num_handles;
h = handles[event - WAIT_OBJECT_0];
for (fd = 0; fd < n; ++fd)
{
HANDLE fd_h;
if (!FD_ISSET (fd, readfds))
continue;
fd_h = (HANDLE) _get_osfhandle (fd);
/* This handle might be ready, even though it wasn't the handle
returned by WaitForMultipleObjects. */
if (fd_h != h && WaitForSingleObject (fd_h, 0) != WAIT_OBJECT_0)
{
FD_CLR (fd, readfds);
--num_ready;
}
}
return num_ready;
#else
return select (n, readfds, writefds, exceptfds, timeout);
#endif
}
/* Called by gdb_do_one_event to wait for new events on the
monitored file descriptors. Queue file events as they are
detected by the poll.

37
gdb/gdb_select.h Normal file
View File

@ -0,0 +1,37 @@
/* Slightly more portable version of <sys/select.h>.
Copyright (C) 2006
Free Software Foundation, Inc.
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
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
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., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA. */
#if !defined(GDB_SELECT_H)
#define GDB_SELECT_H
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
#ifdef USE_WIN32API
#include <winsock2.h>
#endif
extern int gdb_select (int n, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, struct timeval *timeout);
#endif /* !defined(GDB_SELECT_H) */

View File

@ -1,6 +1,6 @@
/* Low level interface to ptrace, for GDB when running under Unix.
Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995,
1996, 1998, 1999, 2000, 2001, 2002, 2003, 2004
1996, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
Free Software Foundation, Inc.
This file is part of GDB.
@ -32,9 +32,7 @@
#include "gdb_string.h"
#include <signal.h>
#include <fcntl.h>
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
#include "gdb_select.h"
#include "inflow.h"
@ -129,7 +127,6 @@ gdb_has_a_terminal (void)
#endif
gdb_has_a_terminal_flag = no;
stdin_serial = serial_fdopen (0);
if (stdin_serial != NULL)
{
our_ttystate = serial_get_tty_state (stdin_serial);
@ -643,7 +640,7 @@ handle_sigio (int signo)
FD_ZERO (&readfds);
FD_SET (target_activity_fd, &readfds);
numfds = select (target_activity_fd + 1, &readfds, NULL, NULL, NULL);
numfds = gdb_select (target_activity_fd + 1, &readfds, NULL, NULL, NULL);
if (numfds >= 0 && FD_ISSET (target_activity_fd, &readfds))
{
#ifndef _WIN32
@ -730,6 +727,18 @@ gdb_setpgid (void)
return retval;
}
/* Get all the current tty settings (including whether we have a
tty at all!). We can't do this in _initialize_inflow because
serial_fdopen() won't work until the serial_ops_list is
initialized, but we don't want to do it lazily either, so
that we can guarantee stdin_serial is opened if there is
a terminal. */
void
initialize_stdin_serial (void)
{
stdin_serial = serial_fdopen (0);
}
void
_initialize_inflow (void)
{

View File

@ -21,7 +21,10 @@
Boston, MA 02110-1301, USA. */
#include "defs.h"
#include "serial.h"
#include "gdb_assert.h"
#include "gdb_select.h"
#include "gdb_string.h"
#include <windows.h>
@ -69,3 +72,124 @@ safe_strerror (int errnum)
return buffer;
}
/* Wrapper for select. On Windows systems, where the select interface
only works for sockets, this uses the GDB serial abstraction to
handle sockets, consoles, pipes, and serial ports.
The arguments to this function are the same as the traditional
arguments to select on POSIX platforms. */
int
gdb_select (int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
struct timeval *timeout)
{
static HANDLE never_handle;
HANDLE handles[MAXIMUM_WAIT_OBJECTS];
HANDLE h;
DWORD event;
DWORD num_handles;
int fd;
int num_ready;
int indx;
num_ready = 0;
num_handles = 0;
for (fd = 0; fd < n; ++fd)
{
HANDLE read = NULL, except = NULL;
struct serial *scb;
/* There is no support yet for WRITEFDS. At present, this isn't
used by GDB -- but we do not want to silently ignore WRITEFDS
if something starts using it. */
gdb_assert (!writefds || !FD_ISSET (fd, writefds));
if (!FD_ISSET (fd, readfds)
&& !FD_ISSET (fd, exceptfds))
continue;
h = (HANDLE) _get_osfhandle (fd);
scb = serial_for_fd (fd);
if (scb)
serial_wait_handle (scb, &read, &except);
if (read == NULL)
read = h;
if (except == NULL)
{
if (!never_handle)
never_handle = CreateEvent (0, FALSE, FALSE, 0);
except = never_handle;
}
if (FD_ISSET (fd, readfds))
{
gdb_assert (num_handles < MAXIMUM_WAIT_OBJECTS);
handles[num_handles++] = read;
}
if (FD_ISSET (fd, exceptfds))
{
gdb_assert (num_handles < MAXIMUM_WAIT_OBJECTS);
handles[num_handles++] = except;
}
}
/* If we don't need to wait for any handles, we are done. */
if (!num_handles)
{
if (timeout)
Sleep (timeout->tv_sec * 1000 + timeout->tv_usec / 1000);
return 0;
}
event = WaitForMultipleObjects (num_handles,
handles,
FALSE,
timeout
? (timeout->tv_sec * 1000
+ timeout->tv_usec / 1000)
: INFINITE);
/* EVENT can only be a value in the WAIT_ABANDONED_0 range if the
HANDLES included an abandoned mutex. Since GDB doesn't use
mutexes, that should never occur. */
gdb_assert (!(WAIT_ABANDONED_0 <= event
&& event < WAIT_ABANDONED_0 + num_handles));
if (event == WAIT_FAILED)
return -1;
if (event == WAIT_TIMEOUT)
return 0;
/* Run through the READFDS, clearing bits corresponding to descriptors
for which input is unavailable. */
h = handles[event - WAIT_OBJECT_0];
for (fd = 0, indx = 0; fd < n; ++fd)
{
HANDLE fd_h;
if (FD_ISSET (fd, readfds))
{
fd_h = handles[indx++];
/* This handle might be ready, even though it wasn't the handle
returned by WaitForMultipleObjects. */
if (fd_h != h && WaitForSingleObject (fd_h, 0) != WAIT_OBJECT_0)
FD_CLR (fd, readfds);
else
num_ready++;
}
if (FD_ISSET (fd, exceptfds))
{
fd_h = handles[indx++];
/* This handle might be ready, even though it wasn't the handle
returned by WaitForMultipleObjects. */
if (fd_h != h && WaitForSingleObject (fd_h, 0) != WAIT_OBJECT_0)
FD_CLR (fd, exceptfds);
else
num_ready++;
}
}
return num_ready;
}

View File

@ -24,6 +24,8 @@
#include "gdb_string.h"
#include "gdb_select.h"
/* The strerror() function can return NULL for errno values that are
out of range. Provide a "safe" version that always returns a
printable string. */
@ -43,3 +45,11 @@ safe_strerror (int errnum)
return (msg);
}
/* Wrapper for select. Nothing special needed on POSIX platforms. */
int
gdb_select (int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
struct timeval *timeout)
{
return select (n, readfds, writefds, exceptfds, timeout);
}

View File

@ -704,7 +704,7 @@ connect_command (char *args, int fromtty)
{
FD_SET (0, &readfds);
FD_SET (deprecated_serial_fd (st2000_desc), &readfds);
numfds = select (sizeof (readfds) * 8, &readfds, 0, 0, 0);
numfds = gdb_select (sizeof (readfds) * 8, &readfds, 0, 0, 0);
}
while (numfds == 0);

View File

@ -1,7 +1,7 @@
/* Generic serial interface functions.
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
2003, 2004, 2005 Free Software Foundation, Inc.
2003, 2004, 2005, 2006 Free Software Foundation, Inc.
This file is part of GDB.
@ -25,6 +25,7 @@
#include "ser-base.h"
#include "event-loop.h"
#include "gdb_select.h"
#include "gdb_string.h"
#include <sys/time.h>
#ifdef USE_WIN32API
@ -202,9 +203,9 @@ ser_base_wait_for (struct serial *scb, int timeout)
FD_SET (scb->fd, &exceptfds);
if (timeout >= 0)
numfds = select (scb->fd + 1, &readfds, 0, &exceptfds, &tv);
numfds = gdb_select (scb->fd + 1, &readfds, 0, &exceptfds, &tv);
else
numfds = select (scb->fd + 1, &readfds, 0, &exceptfds, 0);
numfds = gdb_select (scb->fd + 1, &readfds, 0, &exceptfds, 0);
if (numfds <= 0)
{

796
gdb/ser-mingw.c Normal file
View File

@ -0,0 +1,796 @@
/* Serial interface for local (hardwired) serial ports on Windows systems
Copyright (C) 2006
Free Software Foundation, Inc.
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
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
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., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA. */
#include "defs.h"
#include "serial.h"
#include "ser-base.h"
#include "ser-tcp.h"
#include <windows.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include "gdb_assert.h"
#include "gdb_string.h"
void _initialize_ser_windows (void);
struct ser_windows_state
{
int in_progress;
OVERLAPPED ov;
DWORD lastCommMask;
HANDLE except_event;
};
/* Open up a real live device for serial I/O. */
static int
ser_windows_open (struct serial *scb, const char *name)
{
HANDLE h;
struct ser_windows_state *state;
COMMTIMEOUTS timeouts;
/* Only allow COM ports. */
if (strncmp (name, "COM", 3) != 0)
{
errno = ENOENT;
return -1;
}
h = CreateFile (name, GENERIC_READ | GENERIC_WRITE, 0, NULL,
OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
if (h == INVALID_HANDLE_VALUE)
{
errno = ENOENT;
return -1;
}
scb->fd = _open_osfhandle ((long) h, O_RDWR);
if (scb->fd < 0)
{
errno = ENOENT;
return -1;
}
if (!SetCommMask (h, EV_RXCHAR))
{
errno = EINVAL;
return -1;
}
timeouts.ReadIntervalTimeout = MAXDWORD;
timeouts.ReadTotalTimeoutConstant = 0;
timeouts.ReadTotalTimeoutMultiplier = 0;
timeouts.WriteTotalTimeoutConstant = 0;
timeouts.WriteTotalTimeoutMultiplier = 0;
if (!SetCommTimeouts (h, &timeouts))
{
errno = EINVAL;
return -1;
}
state = xmalloc (sizeof (struct ser_windows_state));
memset (state, 0, sizeof (struct ser_windows_state));
scb->state = state;
/* Create a manual reset event to watch the input buffer. */
state->ov.hEvent = CreateEvent (0, TRUE, FALSE, 0);
/* Create a (currently unused) handle to record exceptions. */
state->except_event = CreateEvent (0, TRUE, FALSE, 0);
return 0;
}
/* Wait for the output to drain away, as opposed to flushing (discarding)
it. */
static int
ser_windows_drain_output (struct serial *scb)
{
HANDLE h = (HANDLE) _get_osfhandle (scb->fd);
return (FlushFileBuffers (h) != 0) ? 0 : -1;
}
static int
ser_windows_flush_output (struct serial *scb)
{
HANDLE h = (HANDLE) _get_osfhandle (scb->fd);
return (PurgeComm (h, PURGE_TXCLEAR) != 0) ? 0 : -1;
}
static int
ser_windows_flush_input (struct serial *scb)
{
HANDLE h = (HANDLE) _get_osfhandle (scb->fd);
return (PurgeComm (h, PURGE_RXCLEAR) != 0) ? 0 : -1;
}
static int
ser_windows_send_break (struct serial *scb)
{
HANDLE h = (HANDLE) _get_osfhandle (scb->fd);
if (SetCommBreak (h) == 0)
return -1;
/* Delay for 250 milliseconds. */
Sleep (250);
if (ClearCommBreak (h))
return -1;
return 0;
}
static void
ser_windows_raw (struct serial *scb)
{
HANDLE h = (HANDLE) _get_osfhandle (scb->fd);
DCB state;
if (GetCommState (h, &state) == 0)
return;
state.fParity = FALSE;
state.fOutxCtsFlow = FALSE;
state.fOutxDsrFlow = FALSE;
state.fDtrControl = DTR_CONTROL_ENABLE;
state.fDsrSensitivity = FALSE;
state.fOutX = FALSE;
state.fInX = FALSE;
state.fNull = FALSE;
state.fAbortOnError = FALSE;
state.ByteSize = 8;
state.Parity = NOPARITY;
scb->current_timeout = 0;
if (SetCommState (h, &state) == 0)
warning (_("SetCommState failed\n"));
}
static int
ser_windows_setstopbits (struct serial *scb, int num)
{
HANDLE h = (HANDLE) _get_osfhandle (scb->fd);
DCB state;
if (GetCommState (h, &state) == 0)
return -1;
switch (num)
{
case SERIAL_1_STOPBITS:
state.StopBits = ONESTOPBIT;
break;
case SERIAL_1_AND_A_HALF_STOPBITS:
state.StopBits = ONE5STOPBITS;
break;
case SERIAL_2_STOPBITS:
state.StopBits = TWOSTOPBITS;
break;
default:
return 1;
}
return (SetCommState (h, &state) != 0) ? 0 : -1;
}
static int
ser_windows_setbaudrate (struct serial *scb, int rate)
{
HANDLE h = (HANDLE) _get_osfhandle (scb->fd);
DCB state;
if (GetCommState (h, &state) == 0)
return -1;
state.BaudRate = rate;
return (SetCommState (h, &state) != 0) ? 0 : -1;
}
static void
ser_windows_close (struct serial *scb)
{
struct ser_windows_state *state;
/* Stop any pending selects. */
CancelIo ((HANDLE) _get_osfhandle (scb->fd));
state = scb->state;
CloseHandle (state->ov.hEvent);
CloseHandle (state->except_event);
if (scb->fd < 0)
return;
close (scb->fd);
scb->fd = -1;
xfree (scb->state);
}
static void
ser_windows_wait_handle (struct serial *scb, HANDLE *read, HANDLE *except)
{
struct ser_windows_state *state;
COMSTAT status;
DWORD errors;
HANDLE h = (HANDLE) _get_osfhandle (scb->fd);
state = scb->state;
*except = state->except_event;
*read = state->ov.hEvent;
if (state->in_progress)
return;
/* Reset the mask - we are only interested in any characters which
arrive after this point, not characters which might have arrived
and already been read. */
/* This really, really shouldn't be necessary - just the second one.
But otherwise an internal flag for EV_RXCHAR does not get
cleared, and we get a duplicated event, if the last batch
of characters included at least two arriving close together. */
if (!SetCommMask (h, 0))
warning (_("ser_windows_wait_handle: reseting mask failed"));
if (!SetCommMask (h, EV_RXCHAR))
warning (_("ser_windows_wait_handle: reseting mask failed (2)"));
/* There's a potential race condition here; we must check cbInQue
and not wait if that's nonzero. */
ClearCommError (h, &errors, &status);
if (status.cbInQue > 0)
{
SetEvent (state->ov.hEvent);
return;
}
state->in_progress = 1;
ResetEvent (state->ov.hEvent);
state->lastCommMask = -2;
if (WaitCommEvent (h, &state->lastCommMask, &state->ov))
{
gdb_assert (state->lastCommMask & EV_RXCHAR);
SetEvent (state->ov.hEvent);
}
else
gdb_assert (GetLastError () == ERROR_IO_PENDING);
}
static int
ser_windows_read_prim (struct serial *scb, size_t count)
{
struct ser_windows_state *state;
OVERLAPPED ov;
DWORD bytes_read, bytes_read_tmp;
HANDLE h;
gdb_byte *p;
state = scb->state;
if (state->in_progress)
{
WaitForSingleObject (state->ov.hEvent, INFINITE);
state->in_progress = 0;
ResetEvent (state->ov.hEvent);
}
memset (&ov, 0, sizeof (OVERLAPPED));
ov.hEvent = CreateEvent (0, FALSE, FALSE, 0);
h = (HANDLE) _get_osfhandle (scb->fd);
if (!ReadFile (h, scb->buf, /* count */ 1, &bytes_read, &ov))
{
if (GetLastError () != ERROR_IO_PENDING
|| !GetOverlappedResult (h, &ov, &bytes_read, TRUE))
bytes_read = -1;
}
CloseHandle (ov.hEvent);
return bytes_read;
}
static int
ser_windows_write_prim (struct serial *scb, const void *buf, size_t len)
{
struct ser_windows_state *state;
OVERLAPPED ov;
DWORD bytes_written;
HANDLE h;
memset (&ov, 0, sizeof (OVERLAPPED));
ov.hEvent = CreateEvent (0, FALSE, FALSE, 0);
h = (HANDLE) _get_osfhandle (scb->fd);
if (!WriteFile (h, buf, len, &bytes_written, &ov))
{
if (GetLastError () != ERROR_IO_PENDING
|| !GetOverlappedResult (h, &ov, &bytes_written, TRUE))
bytes_written = -1;
}
CloseHandle (ov.hEvent);
return bytes_written;
}
struct ser_console_state
{
HANDLE read_event;
HANDLE except_event;
HANDLE start_select;
HANDLE stop_select;
};
static DWORD WINAPI
console_select_thread (void *arg)
{
struct serial *scb = arg;
struct ser_console_state *state, state_copy;
int event_index, fd;
HANDLE h;
/* Copy useful information out of the control block, to make sure
that we do not race with freeing it. */
state_copy = *(struct ser_console_state *) scb->state;
state = &state_copy;
fd = scb->fd;
h = (HANDLE) _get_osfhandle (fd);
while (1)
{
HANDLE wait_events[2];
INPUT_RECORD record;
DWORD n_records;
wait_events[0] = state->start_select;
wait_events[1] = state->stop_select;
if (WaitForMultipleObjects (2, wait_events, FALSE, INFINITE) != WAIT_OBJECT_0)
{
CloseHandle (state->stop_select);
return 0;
}
retry:
wait_events[0] = state->stop_select;
wait_events[1] = h;
event_index = WaitForMultipleObjects (2, wait_events, FALSE, INFINITE);
if (event_index == WAIT_OBJECT_0
|| WaitForSingleObject (state->stop_select, 0) == WAIT_OBJECT_0)
{
CloseHandle (state->stop_select);
return 0;
}
if (event_index != WAIT_OBJECT_0 + 1)
{
/* Wait must have failed; assume an error has occured, e.g.
the handle has been closed. */
SetEvent (state->except_event);
continue;
}
/* We've got a pending event on the console. See if it's
of interest. */
if (!PeekConsoleInput (h, &record, 1, &n_records) || n_records != 1)
{
/* Something went wrong. Maybe the console is gone. */
SetEvent (state->except_event);
continue;
}
if (record.EventType == KEY_EVENT && record.Event.KeyEvent.bKeyDown)
{
/* This is really a keypress. */
SetEvent (state->read_event);
continue;
}
/* Otherwise discard it and wait again. */
ReadConsoleInput (h, &record, 1, &n_records);
goto retry;
}
}
static int
fd_is_pipe (int fd)
{
if (PeekNamedPipe ((HANDLE) _get_osfhandle (fd), NULL, 0, NULL, NULL, NULL))
return 1;
else
return 0;
}
static DWORD WINAPI
pipe_select_thread (void *arg)
{
struct serial *scb = arg;
struct ser_console_state *state, state_copy;
int event_index, fd;
HANDLE h;
/* Copy useful information out of the control block, to make sure
that we do not race with freeing it. */
state_copy = *(struct ser_console_state *) scb->state;
state = &state_copy;
fd = scb->fd;
h = (HANDLE) _get_osfhandle (fd);
while (1)
{
HANDLE wait_events[2];
DWORD n_avail;
wait_events[0] = state->start_select;
wait_events[1] = state->stop_select;
if (WaitForMultipleObjects (2, wait_events, FALSE, INFINITE) != WAIT_OBJECT_0)
{
CloseHandle (state->stop_select);
return 0;
}
retry:
if (!PeekNamedPipe (h, NULL, 0, NULL, &n_avail, NULL))
{
SetEvent (state->except_event);
continue;
}
if (n_avail > 0)
{
SetEvent (state->read_event);
continue;
}
if (WaitForSingleObject (state->stop_select, 0) == WAIT_OBJECT_0)
{
CloseHandle (state->stop_select);
return 0;
}
Sleep (10);
goto retry;
}
}
static void
ser_console_wait_handle (struct serial *scb, HANDLE *read, HANDLE *except)
{
struct ser_console_state *state = scb->state;
if (state == NULL)
{
DWORD threadId;
int is_tty;
is_tty = isatty (scb->fd);
if (!is_tty && !fd_is_pipe (scb->fd))
{
*read = NULL;
*except = NULL;
return;
}
state = xmalloc (sizeof (struct ser_console_state));
memset (state, 0, sizeof (struct ser_console_state));
scb->state = state;
/* Create auto reset events to wake and terminate the select thread. */
state->start_select = CreateEvent (0, FALSE, FALSE, 0);
state->stop_select = CreateEvent (0, FALSE, FALSE, 0);
/* Create our own events to report read and exceptions separately.
The exception event is currently never used. */
state->read_event = CreateEvent (0, FALSE, FALSE, 0);
state->except_event = CreateEvent (0, FALSE, FALSE, 0);
/* And finally start the select thread. */
if (is_tty)
CreateThread (NULL, 0, console_select_thread, scb, 0, &threadId);
else
CreateThread (NULL, 0, pipe_select_thread, scb, 0, &threadId);
}
ResetEvent (state->read_event);
ResetEvent (state->except_event);
SetEvent (state->start_select);
*read = state->read_event;
*except = state->except_event;
}
static void
ser_console_close (struct serial *scb)
{
struct ser_console_state *state = scb->state;
if (scb->state)
{
SetEvent (state->stop_select);
CloseHandle (state->read_event);
CloseHandle (state->except_event);
xfree (scb->state);
}
}
struct ser_console_ttystate
{
int is_a_tty;
};
static serial_ttystate
ser_console_get_tty_state (struct serial *scb)
{
if (isatty (scb->fd))
{
struct ser_console_ttystate *state;
state = (struct ser_console_ttystate *) xmalloc (sizeof *state);
state->is_a_tty = 1;
return state;
}
else
return NULL;
}
struct net_windows_state
{
HANDLE read_event;
HANDLE except_event;
HANDLE start_select;
HANDLE stop_select;
HANDLE sock_event;
};
static DWORD WINAPI
net_windows_select_thread (void *arg)
{
struct serial *scb = arg;
struct net_windows_state *state, state_copy;
int event_index, fd;
/* Copy useful information out of the control block, to make sure
that we do not race with freeing it. */
state_copy = *(struct net_windows_state *) scb->state;
state = &state_copy;
fd = scb->fd;
while (1)
{
HANDLE wait_events[2];
WSANETWORKEVENTS events;
wait_events[0] = state->start_select;
wait_events[1] = state->stop_select;
if (WaitForMultipleObjects (2, wait_events, FALSE, INFINITE) != WAIT_OBJECT_0)
{
CloseHandle (state->stop_select);
return 0;
}
wait_events[0] = state->stop_select;
wait_events[1] = state->sock_event;
event_index = WaitForMultipleObjects (2, wait_events, FALSE, INFINITE);
if (event_index == WAIT_OBJECT_0
|| WaitForSingleObject (state->stop_select, 0) == WAIT_OBJECT_0)
{
CloseHandle (state->stop_select);
return 0;
}
if (event_index != WAIT_OBJECT_0 + 1)
{
/* Some error has occured. Assume that this is an error
condition. */
SetEvent (state->except_event);
continue;
}
/* Enumerate the internal network events, and reset the object that
signalled us to catch the next event. */
WSAEnumNetworkEvents (fd, state->sock_event, &events);
if (events.lNetworkEvents & FD_READ)
SetEvent (state->read_event);
if (events.lNetworkEvents & FD_CLOSE)
SetEvent (state->except_event);
}
}
static void
net_windows_wait_handle (struct serial *scb, HANDLE *read, HANDLE *except)
{
struct net_windows_state *state = scb->state;
ResetEvent (state->read_event);
ResetEvent (state->except_event);
SetEvent (state->start_select);
*read = state->read_event;
*except = state->except_event;
}
static int
net_windows_open (struct serial *scb, const char *name)
{
struct net_windows_state *state;
int ret;
DWORD threadId;
ret = net_open (scb, name);
if (ret != 0)
return ret;
state = xmalloc (sizeof (struct net_windows_state));
memset (state, 0, sizeof (struct net_windows_state));
scb->state = state;
/* Create auto reset events to wake and terminate the select thread. */
state->start_select = CreateEvent (0, FALSE, FALSE, 0);
state->stop_select = CreateEvent (0, FALSE, FALSE, 0);
/* Associate an event with the socket. */
state->sock_event = CreateEvent (0, TRUE, FALSE, 0);
WSAEventSelect (scb->fd, state->sock_event, FD_READ | FD_CLOSE);
/* Create our own events to report read and close separately. */
state->read_event = CreateEvent (0, FALSE, FALSE, 0);
state->except_event = CreateEvent (0, FALSE, FALSE, 0);
/* And finally start the select thread. */
CreateThread (NULL, 0, net_windows_select_thread, scb, 0, &threadId);
return 0;
}
static void
net_windows_close (struct serial *scb)
{
struct net_windows_state *state = scb->state;
SetEvent (state->stop_select);
CloseHandle (state->read_event);
CloseHandle (state->except_event);
CloseHandle (state->start_select);
CloseHandle (state->sock_event);
xfree (scb->state);
net_close (scb);
}
void
_initialize_ser_windows (void)
{
WSADATA wsa_data;
struct serial_ops *ops;
/* First register the serial port driver. */
ops = XMALLOC (struct serial_ops);
memset (ops, 0, sizeof (struct serial_ops));
ops->name = "hardwire";
ops->next = 0;
ops->open = ser_windows_open;
ops->close = ser_windows_close;
ops->flush_output = ser_windows_flush_output;
ops->flush_input = ser_windows_flush_input;
ops->send_break = ser_windows_send_break;
/* These are only used for stdin; we do not need them for serial
ports, so supply the standard dummies. */
ops->get_tty_state = ser_base_get_tty_state;
ops->set_tty_state = ser_base_set_tty_state;
ops->print_tty_state = ser_base_print_tty_state;
ops->noflush_set_tty_state = ser_base_noflush_set_tty_state;
ops->go_raw = ser_windows_raw;
ops->setbaudrate = ser_windows_setbaudrate;
ops->setstopbits = ser_windows_setstopbits;
ops->drain_output = ser_windows_drain_output;
ops->readchar = ser_base_readchar;
ops->write = ser_base_write;
ops->async = ser_base_async;
ops->read_prim = ser_windows_read_prim;
ops->write_prim = ser_windows_write_prim;
ops->wait_handle = ser_windows_wait_handle;
serial_add_interface (ops);
/* Next create the dummy serial driver used for terminals. We only
provide the TTY-related methods. */
ops = XMALLOC (struct serial_ops);
memset (ops, 0, sizeof (struct serial_ops));
ops->name = "terminal";
ops->next = 0;
ops->close = ser_console_close;
ops->get_tty_state = ser_console_get_tty_state;
ops->set_tty_state = ser_base_set_tty_state;
ops->print_tty_state = ser_base_print_tty_state;
ops->noflush_set_tty_state = ser_base_noflush_set_tty_state;
ops->drain_output = ser_base_drain_output;
ops->wait_handle = ser_console_wait_handle;
serial_add_interface (ops);
/* If WinSock works, register the TCP/UDP socket driver. */
if (WSAStartup (MAKEWORD (1, 0), &wsa_data) != 0)
/* WinSock is unavailable. */
return;
ops = XMALLOC (struct serial_ops);
memset (ops, 0, sizeof (struct serial_ops));
ops->name = "tcp";
ops->next = 0;
ops->open = net_windows_open;
ops->close = net_windows_close;
ops->readchar = ser_base_readchar;
ops->write = ser_base_write;
ops->flush_output = ser_base_flush_output;
ops->flush_input = ser_base_flush_input;
ops->send_break = ser_base_send_break;
ops->go_raw = ser_base_raw;
ops->get_tty_state = ser_base_get_tty_state;
ops->set_tty_state = ser_base_set_tty_state;
ops->print_tty_state = ser_base_print_tty_state;
ops->noflush_set_tty_state = ser_base_noflush_set_tty_state;
ops->setbaudrate = ser_base_setbaudrate;
ops->setstopbits = ser_base_setstopbits;
ops->drain_output = ser_base_drain_output;
ops->async = ser_base_async;
ops->read_prim = net_read_prim;
ops->write_prim = net_write_prim;
ops->wait_handle = net_windows_wait_handle;
serial_add_interface (ops);
}

View File

@ -1,6 +1,6 @@
/* Serial interface for raw TCP connections on Un*x like systems.
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2001, 2005
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2001, 2005, 2006
Free Software Foundation, Inc.
This file is part of GDB.
@ -23,7 +23,7 @@
#include "defs.h"
#include "serial.h"
#include "ser-base.h"
#include "ser-unix.h"
#include "ser-tcp.h"
#include <sys/types.h>
@ -56,8 +56,6 @@
typedef int socklen_t;
#endif
static int net_open (struct serial *scb, const char *name);
static void net_close (struct serial *scb);
void _initialize_ser_tcp (void);
/* seconds to wait for connect */
@ -67,7 +65,7 @@ void _initialize_ser_tcp (void);
/* Open a tcp socket */
static int
int
net_open (struct serial *scb, const char *name)
{
char *port_str, hostname[100];
@ -153,7 +151,7 @@ net_open (struct serial *scb, const char *name)
{
/* looks like we need to wait for the connect */
struct timeval t;
fd_set rset, wset;
fd_set rset, wset, eset;
int polls = 0;
FD_ZERO (&rset);
@ -174,10 +172,19 @@ net_open (struct serial *scb, const char *name)
FD_SET (scb->fd, &rset);
wset = rset;
eset = rset;
t.tv_sec = 0;
t.tv_usec = 1000000 / POLL_INTERVAL;
n = select (scb->fd + 1, &rset, &wset, NULL, &t);
/* POSIX systems return connection success or failure by signalling
wset. Windows systems return success in wset and failure in
eset.
We must call select here, rather than gdb_select, because
the serial structure has not yet been initialized - the
MinGW select wrapper will not know that this FD refers
to a socket. */
n = select (scb->fd + 1, &rset, &wset, &eset, &t);
polls++;
}
while (n == 0 && polls <= TIMEOUT * POLL_INTERVAL);
@ -194,7 +201,7 @@ net_open (struct serial *scb, const char *name)
{
int res, err;
socklen_t len;
len = sizeof(err);
len = sizeof (err);
/* On Windows, the fourth parameter to getsockopt is a "char *";
on UNIX systems it is generally "void *". The cast to "void *"
is OK everywhere, since in C "void *" can be implicitly
@ -230,7 +237,7 @@ net_open (struct serial *scb, const char *name)
return 0;
}
static void
void
net_close (struct serial *scb)
{
if (scb->fd < 0)
@ -240,13 +247,13 @@ net_close (struct serial *scb)
scb->fd = -1;
}
static int
int
net_read_prim (struct serial *scb, size_t count)
{
return recv (scb->fd, scb->buf, count, 0);
}
static int
int
net_write_prim (struct serial *scb, const void *buf, size_t count)
{
return send (scb->fd, buf, count, 0);
@ -255,13 +262,12 @@ net_write_prim (struct serial *scb, const void *buf, size_t count)
void
_initialize_ser_tcp (void)
{
struct serial_ops *ops;
#ifdef USE_WIN32API
WSADATA wsa_data;
if (WSAStartup (MAKEWORD (1, 0), &wsa_data) != 0)
/* WinSock is unavailable. */
return;
#endif
/* Do nothing; the TCP serial operations will be initialized in
ser-mingw.c. */
return;
#else
struct serial_ops *ops;
ops = XMALLOC (struct serial_ops);
memset (ops, 0, sizeof (struct serial_ops));
ops->name = "tcp";
@ -285,4 +291,5 @@ _initialize_ser_tcp (void)
ops->read_prim = net_read_prim;
ops->write_prim = net_write_prim;
serial_add_interface (ops);
#endif /* USE_WIN32API */
}

32
gdb/ser-tcp.h Normal file
View File

@ -0,0 +1,32 @@
/* Serial interface for raw TCP connections on Un*x like systems.
Copyright (C) 2006 Free Software Foundation, Inc.
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
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
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., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA. */
#ifndef SER_TCP_H
#define SER_TCP_H
struct serial;
extern int net_open (struct serial *scb, const char *name);
extern void net_close (struct serial *scb);
extern int net_read_prim (struct serial *scb, size_t count);
extern int net_write_prim (struct serial *scb, const void *buf, size_t count);
#endif

View File

@ -31,6 +31,7 @@
#include <sys/socket.h>
#include <sys/time.h>
#include "gdb_select.h"
#include "gdb_string.h"
#ifdef HAVE_TERMIOS
@ -365,7 +366,7 @@ hardwire_send_break (struct serial *scb)
the full length of time. I think that is OK. */
timeout.tv_sec = 0;
timeout.tv_usec = 250000;
select (0, 0, 0, 0, &timeout);
gdb_select (0, 0, 0, 0, &timeout);
status = ioctl (scb->fd, TIOCCBRK, 0);
return status;
}
@ -448,9 +449,9 @@ wait_for (struct serial *scb, int timeout)
FD_SET (scb->fd, &readfds);
if (timeout >= 0)
numfds = select (scb->fd + 1, &readfds, 0, 0, &tv);
numfds = gdb_select (scb->fd + 1, &readfds, 0, 0, &tv);
else
numfds = select (scb->fd + 1, &readfds, 0, 0, 0);
numfds = gdb_select (scb->fd + 1, &readfds, 0, 0, 0);
if (numfds <= 0)
if (numfds == 0)

View File

@ -1,7 +1,7 @@
/* Generic serial interface routines
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
2001, 2002 Free Software Foundation, Inc.
2001, 2002, 2004, 2005, 2006 Free Software Foundation, Inc.
This file is part of GDB.
@ -233,6 +233,22 @@ serial_open (const char *name)
return scb;
}
/* Return the open serial device for FD, if found, or NULL if FD
is not already opened. */
struct serial *
serial_for_fd (int fd)
{
struct serial *scb;
struct serial_ops *ops;
for (scb = scb_base; scb; scb = scb->next)
if (scb->fd == fd)
return scb;
return NULL;
}
struct serial *
serial_fdopen (const int fd)
{
@ -246,12 +262,14 @@ serial_fdopen (const int fd)
return scb;
}
ops = serial_interface_lookup ("hardwire");
ops = serial_interface_lookup ("terminal");
if (!ops)
ops = serial_interface_lookup ("hardwire");
if (!ops)
return NULL;
scb = XMALLOC (struct serial);
scb = XCALLOC (1, struct serial);
scb->ops = ops;
@ -524,6 +542,19 @@ serial_debug_p (struct serial *scb)
return scb->debug_p || global_serial_debug_p;
}
#ifdef USE_WIN32API
void
serial_wait_handle (struct serial *scb, HANDLE *read, HANDLE *except)
{
if (scb->ops->wait_handle)
scb->ops->wait_handle (scb, read, except);
else
{
*read = (HANDLE) _get_osfhandle (scb->fd);
*except = NULL;
}
}
#endif
#if 0
/* The connect command is #if 0 because I hadn't thought of an elegant

View File

@ -1,5 +1,6 @@
/* Remote serial support interface definitions for GDB, the GNU Debugger.
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
2004, 2005, 2006
Free Software Foundation, Inc.
This file is part of GDB.
@ -22,6 +23,10 @@
#ifndef SERIAL_H
#define SERIAL_H
#ifdef USE_WIN32API
#include <windows.h>
#endif
struct ui_file;
/* For most routines, if a failure is indicated, then errno should be
@ -41,6 +46,10 @@ struct serial;
extern struct serial *serial_open (const char *name);
/* Find an already opened serial stream using a file handle. */
extern struct serial *serial_for_fd (int fd);
/* Open a new serial stream using a file handle. */
extern struct serial *serial_fdopen (const int fd);
@ -238,6 +247,13 @@ struct serial_ops
/* Perform a low-level write operation, writing (at most) COUNT
bytes from BUF. */
int (*write_prim)(struct serial *scb, const void *buf, size_t count);
#ifdef USE_WIN32API
/* Return a handle to wait on, indicating available data from SCB
when signaled, in *READ. Return a handle indicating errors
in *EXCEPT. */
void (*wait_handle) (struct serial *scb, HANDLE *read, HANDLE *except);
#endif /* USE_WIN32API */
};
/* Add a new serial interface to the interface list */
@ -248,4 +264,12 @@ extern void serial_add_interface (struct serial_ops * optable);
extern void serial_log_command (const char *);
#ifdef USE_WIN32API
/* Windows-only: find or create handles that we can wait on for this
serial device. */
extern void serial_wait_handle (struct serial *, HANDLE *, HANDLE *);
#endif /* USE_WIN32API */
#endif /* SERIAL_H */

View File

@ -1,5 +1,6 @@
/* Terminal interface definitions for GDB, the GNU Debugger.
Copyright (C) 1986, 1989, 1990, 1991, 1992, 1993, 1995, 1996, 1999, 2000
Copyright (C) 1986, 1989, 1990, 1991, 1992, 1993, 1995, 1996, 1999, 2000,
2006
Free Software Foundation, Inc.
This file is part of GDB.
@ -88,4 +89,7 @@ extern int job_control;
we lack job control. */
extern int gdb_setpgid (void);
/* Set up a serial structure describing standard input. In inflow.c. */
extern void initialize_stdin_serial (void);
#endif /* !defined (TERMINAL_H) */

View File

@ -1550,6 +1550,8 @@ gdb_init (char *argv0)
init_cli_cmds();
init_main (); /* But that omits this file! Do it now */
initialize_stdin_serial ();
async_init_signals ();
/* We need a default language for parsing expressions, so simple things like