[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] anybody using pdb?


  • To: xen-devel@xxxxxxxxxxxxxxxxxxxxx
  • From: Christian Limpach <chris@xxxxxx>
  • Date: Thu, 11 Mar 2004 01:10:07 +0100
  • Delivery-date: Thu, 11 Mar 2004 00:12:24 +0000
  • List-id: List for Xen developers <xen-devel.lists.sourceforge.net>

Hello!

I'd like to use pdb but it's not quite working as expected.

The 1st issue is that jumping to the debugger by pressing 'D' doesn't work
because this leaves serial interrupts blocked.  Maybe this is only the
case because I'm using lo/hi muxing but my guess is that it's not.  I've
implemented a work around which seems to work:  if pdb is entered by the
keypressed handler it will call a new serial_getc function if there's no
input in the rx ring.  I'm not sure if this is also necessary when
interacting with the debugger on a breakpoint or after a crash...

2nd issue is that the debugger doesn't work when hitting a breakpoint (and
possibly after a crash) which raises my question if anybody is actually
using the pdb code which is in unstable ;-)

Finally, nsplitd seems to be missing the part which connects it to the
serial port (it wants to connect to a host:port, I guess on a terminal
server...).  The 2nd attachment is a program which presents the cleared-bit
connection on stdin/stdout and the set-bit connection on a tcp port (option
-g to set the port).  It should also work from inetd or as a server (option
-p to set the server port) but I haven't really tested those modes (I at
first implemented the inetd/server modes and then decided that I prefer
stdin/stdout...).

===================================================================
RCS file: arch/i386/pdb-stub.c,v
retrieving revision 1.1
diff -up -r1.1 arch/i386/pdb-stub.c
--- arch/i386/pdb-stub.c        2004/03/10 21:14:55     1.1
+++ arch/i386/pdb-stub.c        2004/03/11 00:03:22
@@ -31,6 +31,7 @@ void pdb_put_packet (unsigned char *buff
 
 static int pdb_initialized = 0;
 static int pdb_serhnd      = -1;
+static int pdb_sermaster   = 0;
 
 #define RX_SIZE 32
 #define RX_MASK(_i) ((_i)&(RX_SIZE-1))
@@ -44,8 +45,12 @@ static inline void pdb_put_char(unsigned
 
 static inline unsigned char pdb_get_char(void)
 {
-    while ( rx_cons == rx_prod )
-        barrier();
+    if ( pdb_sermaster && rx_cons == rx_prod ) {
+       return serial_getc(pdb_serhnd);
+    } else {
+       while ( rx_cons == rx_prod )
+           barrier();
+    }
     return rx_ring[RX_MASK(rx_cons++)];
 }
 
@@ -822,7 +827,9 @@ int pdb_handle_exception(int exceptionVe
 
 void pdb_key_pressed(u_char key, void *dev_id, struct pt_regs *regs) 
 {
+    pdb_sermaster = 1;
     pdb_handle_exception(KEYPRESS_EXCEPTION, regs);
+    pdb_sermaster = 0;
     return;
 }
 
===================================================================
RCS file: drivers/char/serial.c,v
retrieving revision 1.2
diff -up -r1.2 drivers/char/serial.c
--- drivers/char/serial.c       2004/03/10 23:16:01     1.2
+++ drivers/char/serial.c       2004/03/10 23:17:57
@@ -137,6 +137,24 @@ static inline void __serial_putc(uart_t 
     outb(c, uart->io_base + THR);
 }
 
+static inline unsigned char __serial_getc(uart_t *uart, int handle)
+{
+    unsigned char c;
+
+    for (;;) {
+       while ( (inb(uart->io_base + LSR) & LSR_DR) == 0 )
+           barrier();
+
+       c = inb(uart->io_base + RBR);
+
+       if ( c & 0x80 && handle & SERHND_HI )
+           break;
+       if ( (c & 0x80) == 0 && handle & SERHND_LO )
+           break;
+    }
+    return c & 0x7f;
+}
+
 #define PARSE_ERR(_f, _a...)                 \
     do {                                     \
         printk( "ERROR: " _f "\n" , ## _a ); \
@@ -396,3 +414,13 @@ void serial_puts(int handle, const unsig
 
     spin_unlock_irqrestore(&uart->lock, flags);
 }
+
+unsigned char serial_getc(int handle)
+{
+    uart_t *uart = &com[handle & SERHND_IDX];
+
+    if ( handle == -1 )
+        return 0;
+
+    return __serial_getc(uart, handle);
+}
===================================================================
RCS file: include/xeno/serial.h,v
retrieving revision 1.1
diff -up -r1.1 include/xeno/serial.h
--- include/xeno/serial.h       2004/03/10 22:50:43     1.1
+++ include/xeno/serial.h       2004/03/10 23:14:15
@@ -36,4 +36,7 @@ void serial_putc(int handle, unsigned ch
 /* Transmit a NULL-terminated string via the specified COM port. */
 void serial_puts(int handle, const unsigned char *s);
 
+/* Receive a single character via the specified COM port. */
+unsigned char serial_getc(int handle);
+
 #endif /* __XEN_SERIAL_H__ */

/*  #define DUMP_HICONN */

#include <stdlib.h>
#include <stdarg.h>
#include <err.h>

#include <termios.h>
#include <unistd.h>

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/poll.h>
#include <signal.h>

#include <getopt.h>

#include <netdb.h>
#include <netinet/in.h>

#ifndef O_BINARY
#define O_BINARY 0
#endif

#ifdef __CYGWIN__
#define COMPORT "/dev/com3"
#else
#define COMPORT "/dev/ttyS0"
#endif

int stdin_needs_reset = 0;
struct termios stdtio;

void
sighandler(int arg)
{
        if (stdin_needs_reset && tcsetattr(STDIN_FILENO, TCSAFLUSH, &stdtio) < 
0)
                err(arg, "tcsetattr failed");
        exit(arg);
}

void
err(int eval, const char *fmt, ...)
{
        va_list va;

        va_start(va, fmt);
        vwarn(fmt, va);
        va_end(va);
        sighandler(eval);
        exit(eval);             /* sigh */
}

int
listenport(int port)
{
        int fd, on;
        struct sockaddr_in sin;

        if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
                err(1, "socket");

        on = 1;
        if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)) < 0)
                err(1, "setsockopt (SO_REUSEADDR)");

        memset(&sin, 0, sizeof(sin));
        sin.sin_family = AF_INET;
        sin.sin_port = htons(port);
        sin.sin_addr.s_addr = INADDR_ANY;
        if (bind(fd, (struct sockaddr *)&sin, sizeof(sin)) < 0)
                err(1, "bind: %d", port);

        if (listen(fd, 1) < 0)
                err(1, "listen");

        return fd;
}

int
main(int argc, char **argv)
{
        int fd, infd[2], outfd[2];
        unsigned char buf[129];
        struct termios tio;
        struct pollfd pfd[3];
        int binmode = 0;
        int doSend = -1;
        int delay = 500;
        char *sendString = NULL;
        int handshake = 0;
        int rate = B57600;
        int port = -1;
        int gdbport = -1;
        struct sockaddr_in peer;
        int peerlen;
        int escape = 0;

        for (;;) {
                int c;
                c = getopt (argc, argv, "g:p:");
                if (c == -1)
                        break;
                switch (c) {
                case 'g':
                        gdbport = atoi(optarg);
                        break;
                case 'p':
                        port = atoi(optarg);
                        break;
                }
        }

        infd[0] = STDIN_FILENO;
        outfd[0] = STDOUT_FILENO;
        if (isatty(STDIN_FILENO)) {
                if (gdbport == -1) {
                        if (port == -1)
                                err(1, "port and gdbport not set with stdin a 
tty");
                        gdbport = port + 1;
                }
                if (port != -1) {
                        infd[0] = listenport(port);
                        outfd[0] = -1;
                }
        } else {
                if (gdbport == -1)
                        gdbport = port + 1;
                peerlen = sizeof(peer);
                if (getpeername(STDIN_FILENO, (struct sockaddr *)&peer, 
&peerlen) < 0)
                        err(1, "getpeername");
                port = ntohs(peer.sin_port);
                infd[0] = STDIN_FILENO;
                outfd[0] = STDOUT_FILENO;
        }
        infd[1] = listenport(gdbport);
        outfd[1] = -1;
        fprintf(stderr, "listen on port %d/%d, fds %d/%d\n", port, gdbport, 
infd[0],
            infd[1]);

        argc -= optind - 1;
        argv += optind - 1;

        fd = open (COMPORT, O_RDWR | O_NOCTTY | O_NONBLOCK | O_BINARY);
        if (fd < 0) {
                fprintf (stderr, "open failed");
                exit (1);
        }

        if (tcgetattr (fd, &tio) < 0)
                err(1, "tcgetattr failed");
        if (cfsetispeed (&tio, rate) < 0)
                err(1, "cfsetispeed failed");
        if (cfsetospeed (&tio, rate) < 0)
                err(1, "cfsetospeed failed");
        tio.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP
            |INLCR|IGNCR|ICRNL|IXON);
        tio.c_oflag &= ~OPOST;
        tio.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
        tio.c_cflag &= ~(CSIZE|PARENB);
        tio.c_cflag |= CS8;
        if (handshake) {
                tio.c_cflag|=CRTSCTS;
                tio.c_cflag|=CSTOPB;
        } else {
                tio.c_cflag&=~CRTSCTS;
                tio.c_cflag&=~CSTOPB;
        }
        if (tcsetattr (fd, TCSAFLUSH, &tio) < 0)
                err(1, "tcsetattr failed");

        if (isatty(infd[0])) {
                stdin_needs_reset = 1;
                signal (SIGINT, sighandler);

                if (tcgetattr (infd[0], &stdtio) < 0)
                        err(1, "tcgetattr failed");
                if (tcgetattr (infd[0], &tio) < 0)
                        err(1, "tcgetattr failed");
                tio.c_oflag &= ~OPOST;
                tio.c_lflag &= ~(ECHO|ECHONL|ICANON|/*ISIG|*/IEXTEN);
                tio.c_cflag &= ~(CSIZE|PARENB);
                tio.c_cflag |= CS8;
                if (tcsetattr (infd[0], TCSAFLUSH, &tio) < 0)
                        err(1, "tcsetattr failed");
        }

        pfd[0].fd = fd;
        pfd[0].events = POLLIN;
        pfd[1].fd = infd[0];
        pfd[1].events = POLLIN;
        pfd[2].fd = infd[1];
        pfd[2].events = POLLIN;
        for (;;) {
                int c;
                while ((c = poll (pfd, 3, 15)) <= 0) {
                        if (c < 0)
                                err(1, "poll failed");
                }
                if ((pfd[0].revents & POLLIN) != 0) {
                        c = read (fd, buf, 1);
                        if (buf[0] & 0x80) {
                                if (outfd[1] >= 0) {
                                        buf[0] &= 0x7f;
                                        write (outfd[1], buf, c);
#if DUMP_HICONN
                                        write (STDERR_FILENO, "[", 1);
                                        write (STDERR_FILENO, buf, c);
                                        write (STDERR_FILENO, "]", 1);
#endif
                        }
                        } else {
                                if (outfd[0] >= 0)
                                        write (outfd[0], buf, c);
                        }
                }
                if ((pfd[1].revents & POLLIN) != 0) {
                        if (outfd[0] >= 0) {
                                c = read (pfd[1].fd, buf, 1);
                                if (c <= 0) {
                                        close(pfd[1].fd);
                                        pfd[1].fd = infd[0];
                                        outfd[0] = -1;
                                } else {
                                        buf[0] &= 0x7f;
                                        if (escape == 0 && buf[0] == '~') {
                                                escape = 1;
                                                continue;
                                        } else if (escape == 1) {
                                                switch(buf[0]) {
                                                case '.':
                                                        write (outfd[0], 
"\r\n", 2);
                                                        sighandler(0);
                                                        /* NOTREACHED */
                                                        break;
                                                case '~':
                                                        break;
                                                default:
                                                        write (fd, "~", 1);
                                                        break;
                                                }
                                        }
                                        if (buf[0] == '\n')
                                                escape = 0;
                                        else
                                                escape = 2;
                                        write (fd, buf, c);
                                }
                        } else {
                                outfd[0] = accept(infd[0], NULL, NULL);
                                pfd[1].fd = outfd[0];
                        }
                }
                if ((pfd[2].revents & POLLIN) != 0) {
                        if (outfd[1] >= 0) {
                                c = read (pfd[2].fd, buf, 1);
                                if (c <= 0) {
                                        close(pfd[2].fd);
                                        pfd[2].fd = infd[1];
                                        outfd[1] = -1;
                                } else {
#ifdef DUMP_HICONN
                                        write (STDERR_FILENO, buf, c);
#endif
                                        buf[0] |= 0x80;
                                        write (fd, buf, c);
                                }
                        } else {
                                outfd[1] = accept(infd[1], NULL, NULL);
                                pfd[2].fd = outfd[1];
                        }
                }
        }

        return 0;
}

-- 
Christian Limpach <chris@xxxxxx>

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.