- add gdb pipe support to native win32 (--pipe option)
authorntfreak <ntfreak@b42882b7-edfa-0310-969c-e2dbd0fdcd60>
Thu, 1 Jan 2009 16:06:46 +0000 (16:06 +0000)
committerntfreak <ntfreak@b42882b7-edfa-0310-969c-e2dbd0fdcd60>
Thu, 1 Jan 2009 16:06:46 +0000 (16:06 +0000)
git-svn-id: svn://svn.berlios.de/openocd/trunk@1294 b42882b7-edfa-0310-969c-e2dbd0fdcd60

doc/openocd.texi
src/helper/options.c
src/helper/replacements.c
src/helper/replacements.h
src/server/gdb_server.c
src/server/server.c

index 39a56303198d28b8ce0120508087357df1d146f7..63ab6fedf62a0e0d271a65ee57da583a9b9589ea 100644 (file)
@@ -557,7 +557,6 @@ the @option{-s <search>} switch. The current directory and the OpenOCD
 target library is in the search path by default.
 
 For details on the @option{-p} option. @xref{Connecting to GDB}.
-Option @option{-p} is not currently supported under native win32.
 
 Note! OpenOCD will launch the GDB & telnet server even if it can not
 establish a connection with the target. In general, it is possible for
index 203791bd66024fd68c9c70615db2f672e37840c8..dd9f71387a79733b2c39275e8f5b716264d4c672 100644 (file)
@@ -148,14 +148,8 @@ int parse_cmdline_args(struct command_context_s *cmd_ctx, int argc, char *argv[]
 #if BUILD_ECOSBOARD == 1
                                /* pipes unsupported on hosted platforms */
                                LOG_WARNING("pipes not supported on this platform");
-#else
-#ifdef IS_MINGW
-                               /* pipes currently unsupported on win32 */
-                               LOG_WARNING("pipes currently unsupported on win32");
-                               exit(1);
 #else
                                server_use_pipes = 1;
-#endif
 #endif
                                break;
                }
index b6ddfd7c562082c9db9cd3a98b23e3ba1ace9bef..39a736c7c4336e2d26c3684f3c81ad223a058999 100644 (file)
@@ -68,6 +68,10 @@ void *fill_malloc(size_t size)
 
 #include <stdio.h>
 
+#ifdef _WIN32
+#include <io.h>
+#endif
+
 /* replacements for gettimeofday */
 #ifndef HAVE_GETTIMEOFDAY
 
@@ -137,3 +141,151 @@ char* strndup(const char *s, size_t n)
        return (char *) memcpy (new, s, len);
 }
 #endif
+
+#ifdef _WIN32
+int win_select(int max_fd, fd_set *rfds, fd_set *wfds, fd_set *efds, struct timeval *tv)
+{
+       DWORD ms_total, limit;
+       HANDLE handles[MAXIMUM_WAIT_OBJECTS];
+       int handle_slot_to_fd[MAXIMUM_WAIT_OBJECTS];
+       int n_handles = 0, i;
+       fd_set sock_read, sock_write, sock_except;
+       fd_set aread, awrite, aexcept;
+       int sock_max_fd = -1;
+       struct timeval tvslice;
+       int retcode;
+
+#define SAFE_FD_ISSET(fd, set) (set != NULL && FD_ISSET(fd, set))
+
+       /* calculate how long we need to wait in milliseconds */
+       if (tv == NULL) {
+               ms_total = INFINITE;
+       } else {
+               ms_total = tv->tv_sec * 1000;
+               ms_total += tv->tv_usec / 1000;
+       }
+
+       FD_ZERO(&sock_read);
+       FD_ZERO(&sock_write);
+       FD_ZERO(&sock_except);
+
+       /* build an array of handles for non-sockets */
+       for (i = 0; i < max_fd; i++) {
+               if (SAFE_FD_ISSET(i, rfds) || SAFE_FD_ISSET(i, wfds) || SAFE_FD_ISSET(i, efds)) {
+                       handles[n_handles] = (HANDLE)_get_osfhandle(i);
+                       if (handles[n_handles] == INVALID_HANDLE_VALUE) {
+                               /* socket */
+                               if (SAFE_FD_ISSET(i, rfds)) {
+                                       FD_SET(i, &sock_read);
+                               }
+                               if (SAFE_FD_ISSET(i, wfds)) {
+                                       FD_SET(i, &sock_write);
+                               }
+                               if (SAFE_FD_ISSET(i, efds)) {
+                                       FD_SET(i, &sock_except);
+                               }
+                               if (i > sock_max_fd) {
+                                       sock_max_fd = i;
+                               }
+                       } else {
+                               handle_slot_to_fd[n_handles] = i;
+                               n_handles++;
+                       }
+               }
+       }
+
+       if (n_handles == 0) {
+               /* plain sockets only - let winsock handle the whole thing */
+               return select(max_fd, rfds, wfds, efds, tv);
+       }
+
+       /* mixture of handles and sockets; lets multiplex between
+        * winsock and waiting on the handles */
+
+       FD_ZERO(&aread);
+       FD_ZERO(&awrite);
+       FD_ZERO(&aexcept);
+       
+       limit = GetTickCount() + ms_total;
+       do {
+               retcode = 0;
+       
+               if (sock_max_fd >= 0) {
+                       /* overwrite the zero'd sets here; the select call
+                        * will clear those that are not active */
+                       aread = sock_read;
+                       awrite = sock_write;
+                       aexcept = sock_except;
+
+                       tvslice.tv_sec = 0;
+                       tvslice.tv_usec = 100000;
+
+                       retcode = select(sock_max_fd+1, &aread, &awrite, &aexcept, &tvslice);
+               }
+               if (n_handles > 0) {
+                       /* check handles */
+                       DWORD wret;
+
+                       wret = MsgWaitForMultipleObjects(n_handles, handles, FALSE, retcode > 0 ? 0 : 100, QS_ALLEVENTS);
+
+                       if (wret == WAIT_TIMEOUT) {
+                               /* set retcode to 0; this is the default.
+                                * select() may have set it to something else,
+                                * in which case we leave it alone, so this branch
+                                * does nothing */
+                               ;
+                       } else if (wret == WAIT_FAILED) {
+                               if (retcode == 0) {
+                                       retcode = -1;
+                               }
+                       } else {
+                               if (retcode < 0) {
+                                       retcode = 0;
+                               }
+                               for (i = 0; i < n_handles; i++) {
+                                       if (WAIT_OBJECT_0 == WaitForSingleObject(handles[i], 0)) {
+                                               if (SAFE_FD_ISSET(handle_slot_to_fd[i], rfds)) {
+                                                       DWORD dwBytes;
+                                                       
+                                                       if (PeekNamedPipe((HANDLE)_get_osfhandle(handle_slot_to_fd[i]), NULL, 0, NULL, &dwBytes, NULL))
+                                                       {
+                                                               /* check to see if gdb pipe has data available */
+                                                               if (dwBytes)
+                                                               {
+                                                                       FD_SET(handle_slot_to_fd[i], &aread);
+                                                                       retcode++;
+                                                               }
+                                                       }
+                                                       else
+                                                       {
+                                                               FD_SET(handle_slot_to_fd[i], &aread);
+                                                               retcode++;
+                                                       }
+                                               }
+                                               if (SAFE_FD_ISSET(handle_slot_to_fd[i], wfds)) {
+                                                       FD_SET(handle_slot_to_fd[i], &awrite);
+                                                       retcode++;
+                                               }
+                                               if (SAFE_FD_ISSET(handle_slot_to_fd[i], efds)) {
+                                                       FD_SET(handle_slot_to_fd[i], &aexcept);
+                                                       retcode++;
+                                               }
+                                       }
+                               }
+                       }
+               }
+       } while (retcode == 0 && (ms_total == INFINITE || GetTickCount() < limit));
+
+       if (rfds) {
+               *rfds = aread;
+       }
+       if (wfds) {
+               *wfds = awrite;
+       }
+       if (efds) {
+               *efds = aexcept;
+       }
+
+       return retcode;
+}
+#endif
index b6165085a889ac2304913d18812fac14e3c2cb2a..c3a2bf77d94e5bc3dbc3d8bfe607457e08b1dc0f 100644 (file)
@@ -180,6 +180,9 @@ static __inline void outb(unsigned char value, unsigned short int port)
 }
 
 #endif /* IS_MINGW */
+
+int win_select(int max_fd, fd_set *rfds, fd_set *wfds, fd_set *efds, struct timeval *tv);
+
 #endif  /* _WIN32 */
 
 /* generic socket functions for Windows and Posix */
@@ -221,6 +224,15 @@ static __inline void socket_nonblock(int fd)
 #endif
 }
 
+static __inline int socket_select(int max_fd, fd_set *rfds, fd_set *wfds, fd_set *efds, struct timeval *tv)
+{
+#ifdef _WIN32
+       return win_select(max_fd, rfds, wfds, efds, tv);
+#else
+       return select(max_fd, rfds, wfds, efds, tv);
+#endif
+}
+
 #ifndef HAVE_ELF_H
 
 typedef struct
index 3f9e1e71a7dd0cbb50030acbc43b67eda735565f..eb612c7a9b88a2f0a074ad853541c3467dbc2341 100644 (file)
@@ -126,7 +126,7 @@ int check_pending(connection_t *connection, int timeout_s, int *got_data)
 
        tv.tv_sec = timeout_s;
        tv.tv_usec = 0;
-       if (select(connection->fd + 1, &read_fds, NULL, NULL, &tv) == 0)
+       if (socket_select(connection->fd + 1, &read_fds, NULL, NULL, &tv) == 0)
        {
                /* This can typically be because a "monitor" command took too long
                 * before printing any progress messages
index b5b9a205db137564f96583b4160f4b481e2d9ef1..e97dac9ac77061b8c82aa82dbfaed9566460fe6a 100644 (file)
@@ -97,12 +97,11 @@ int add_connection(service_t *service, command_context_t *cmd_ctx)
        }
        else if (service->type == CONNECTION_PIPE)
        {
-#ifndef _WIN32
                c->fd = service->fd;
                
                /* do not check for new connections again on stdin */
                service->fd = -1;
-#endif
+               
                LOG_INFO("accepting '%s' connection from pipe", service->name);
                if ((retval = service->new_connection(c)) != ERROR_OK)
                {
@@ -223,6 +222,8 @@ int add_service(char *name, enum connection_type type, unsigned short port, int
                        LOG_WARNING("cannot change stdout mode to binary");
                if (_setmode(_fileno(stdin), _O_BINARY) < 0)
                        LOG_WARNING("cannot change stdin mode to binary");
+               if (_setmode(_fileno(stderr), _O_BINARY) < 0)
+                       LOG_WARNING("cannot change stderr mode to binary");
 #else
                socket_nonblock(c->fd);
 #endif
@@ -365,7 +366,7 @@ int server_loop(command_context_t *command_context)
                kept_alive();
                
                /* Only while we're sleeping we'll let others run */
-               retval = select(fd_max + 1, &read_fds, NULL, NULL, &tv);
+               retval = socket_select(fd_max + 1, &read_fds, NULL, NULL, &tv);
                openocd_sleep_postlude();
 
                if (retval == -1)
@@ -503,7 +504,7 @@ int server_init(void)
        WORD wVersionRequested;
        WSADATA wsaData;
 
-       wVersionRequested = MAKEWORD( 2, 2 );
+       wVersionRequested = MAKEWORD(2, 2);
 
        if (WSAStartup(wVersionRequested, &wsaData) != 0)
        {
@@ -511,7 +512,16 @@ int server_init(void)
                exit(-1);
        }
 
-       SetConsoleCtrlHandler( ControlHandler, TRUE );
+       if (server_use_pipes == 0)
+       {
+               /* register ctrl-c handler */
+               SetConsoleCtrlHandler(ControlHandler, TRUE);
+       }
+       else
+       {
+               /* we are using pipes so ignore ctrl-c */
+               SetConsoleCtrlHandler(NULL, TRUE);
+       }
 
        signal(SIGINT, sig_handler);
        signal(SIGTERM, sig_handler);