qemu-devel
[Top][All Lists]
Advanced

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

[Qemu-devel] Re: [PATCH] Gdbstub user mode -gdb dev option : add unix so


From: Jan Kiszka
Subject: [Qemu-devel] Re: [PATCH] Gdbstub user mode -gdb dev option : add unix sockets
Date: Wed, 15 Apr 2009 13:04:59 +0200
User-agent: Mozilla/5.0 (X11; U; Linux i686 (x86_64); de; rv:1.8.1.12) Gecko/20080226 SUSE/2.0.0.12-1.1 Thunderbird/2.0.0.12 Mnenhy/0.7.5.666

Philippe Waille wrote:
>   This patch removes the -g portnumber option in user mode.
>   Adds a -gdb device option as in the system mode.
> 
>   -gdb tcp:host:port              or   -gdb tcp::port
>   -gdb unix:socketname[,unlink]
> 
>   Missing tests :
>   + system mode regression test (I don't have a "hello world" example
> for system mode)
>   + _WIN32 mode
> 
> 
> Philippe Waille
> -------------------------------------------------------------------------
> 
> Index: linux-user/main.c
> ===================================================================
> --- linux-user/main.c (révision 7105)
> +++ linux-user/main.c (copie de travail)
> @@ -2202,40 +2202,37 @@
>  
>  static void usage(void)
>  {
> -    printf("qemu-" TARGET_ARCH " version " QEMU_VERSION QEMU_PKGVERSION ", 
> Copyright (c) 2003-2008 Fabrice Bellard\n"
> -           "usage: qemu-" TARGET_ARCH " [options] program [arguments...]\n"
> -           "Linux CPU emulator (compiled for %s emulation)\n"
> -           "\n"
> -           "Standard options:\n"
> -           "-h                print this help\n"
> -           "-g port           wait gdb connection to port\n"
> -           "-L path           set the elf interpreter prefix (default=%s)\n"
> -           "-s size           set the stack size in bytes (default=%ld)\n"
> -           "-cpu model        select CPU (-cpu ? for list)\n"
> -           "-drop-ld-preload  drop LD_PRELOAD for target process\n"
> -           "-E var=value      sets/modifies targets environment 
> variable(s)\n"
> -           "-U var            unsets targets environment variable(s)\n"
> -           "\n"
> -           "Debug options:\n"
> -           "-d options   activate log (logfile=%s)\n"
> -           "-p pagesize  set the host page size to 'pagesize'\n"
> -           "-singlestep  always run in singlestep mode\n"
> -           "-strace      log system calls\n"
> -           "\n"
> -           "Environment variables:\n"
> -           "QEMU_STRACE       Print system calls and arguments similar to 
> the\n"
> -           "                  'strace' program.  Enable by setting to any 
> value.\n"
> -           "You can use -E and -U options to set/unset environment 
> variables\n"
> -           "for target process.  It is possible to provide several 
> variables\n"
> -           "by repeating the option.  For example:\n"
> -           "    -E var1=val2 -E var2=val2 -U LD_PRELOAD -U LD_DEBUG\n"
> -           "Note that if you provide several changes to single variable\n"
> -           "last change will stay in effect.\n"
> -           ,
> -           TARGET_ARCH,
> -           interp_prefix,
> -           x86_stack_size,
> -           DEBUG_LOGFILE);
> +    printf("qemu-" TARGET_ARCH " version " QEMU_VERSION ", Copyright (c) 
> 2003-2008 Fabrice Bellard\n");
> +    printf("usage: qemu-" TARGET_ARCH " [options] program [arguments...]\n");
> +    printf("Linux CPU emulator (compiled for %s emulation)\n",
> +           TARGET_ARCH);
> +    printf("\n");
> +    printf("Standard options:\n");
> +    printf("-h                print this help\n");
> +    gdbstub_usage();
> +    printf("-L path           set the elf interpreter prefix (default=%s)\n",
> +           interp_prefix);
> +    printf("-s size           set the stack size in bytes (default=%ld)\n",
> +           x86_stack_size);
> +    printf("-cpu model        select CPU (-cpu ? for list)\n");
> +    printf("-drop-ld-preload  drop LD_PRELOAD for target process\n");
> +    printf("-E var=value      sets/modifies targets environment 
> variable(s)\n");
> +    printf("-U var            unsets targets environment variable(s)\n");
> +    printf("\n");
> +    printf("Debug options:\n");
> +    printf("-d options   activate log (logfile=%s)\n", DEBUG_LOGFILE);
> +    printf("-p pagesize  set the host page size to 'pagesize'\n");
> +    printf("-strace      log system calls\n");
> +    printf("\n");
> +    printf("Environment variables:\n");
> +    printf("QEMU_STRACE       Print system calls and arguments similar to 
> the\n");
> +    printf("                  'strace' program.  Enable by setting to any 
> value.\n");
> +    printf("You can use -E and -U options to set/unset environment 
> variables\n");
> +    printf("for target process.  It is possible to provide several 
> variables\n");
> +    printf("by repeating the option.  For example:\n");
> +    printf("    -E var1=val2 -E var2=val2 -U LD_PRELOAD -U LD_DEBUG\n");
> +    printf("Note that if you provide several changes to single variable\n");
> +    printf("last change will stay in effect.\n");

Please drop this conversion single -> multiple printf, just change the
string related to this patch. Also, I think factoring out
gdbstub_usage() is a bit overkill.

>      exit(1);
>  }
>  
> @@ -2264,7 +2261,6 @@
>      CPUState *env;
>      int optind;
>      const char *r;
> -    int gdbstub_port = 0;
>      char **target_environ, **wrk;
>      envlist_t *envlist = NULL;
>  
> @@ -2345,10 +2341,15 @@
>                  fprintf(stderr, "page size must be a power of two\n");
>                  exit(1);
>              }
> -        } else if (!strcmp(r, "g")) {
> -            if (optind >= argc)
> +        } else if (!strcmp(r, "gdb")) {
> +            if (optind >= argc) {
>                  break;
> -            gdbstub_port = atoi(argv[optind++]);
> +            }
> +            if (gdbserver_start(argv[optind++]) < 0) {
> +                /* stop command line analysis */
> +                optind = argc;
> +                break;

Shouldn't you rather fail with some error message and exit()?

> +            }
>       } else if (!strcmp(r, "r")) {
>           qemu_uname_release = argv[optind++];
>          } else if (!strcmp(r, "cpu")) {
> @@ -2706,8 +2707,10 @@
>      ts->heap_limit = 0;
>  #endif
>  
> -    if (gdbstub_port) {
> -        gdbserver_start (gdbstub_port);
> +    if (gdbstub_accept != NULL) {
> +        if ((*gdbstub_accept)() < 0) {
> +            return -1;
> +        }

Rather introduce gdbstub_accept() and keep the function point private
(static) to gdbstub.c. gdbstub_accept() could then also check for the
pointer being non-NULL and do the inital handlesig.

>          gdb_handlesig(env, 0);
>      }
>      cpu_loop(env);
> Index: gdbstub.c
> ===================================================================
> --- gdbstub.c (révision 7105)
> +++ gdbstub.c (copie de travail)
> @@ -19,23 +19,19 @@
>   */
>  #include "config.h"
>  #include "qemu-common.h"
> +
>  #ifdef CONFIG_USER_ONLY
> -#include <stdlib.h>
> -#include <stdio.h>
> -#include <stdarg.h>
> -#include <string.h>
> -#include <errno.h>
> -#include <unistd.h>
> -#include <fcntl.h>
> +#include "qemu.h"
> +#include "gdbstub.h"
>  
> -#include "qemu.h"
> -#else
> +#else /* CONFIG_USER_ONLY */

Minor remark: I prefer comment on this with "!CONFIG_USER_ONLY" as the
following code handles the !defined case.

>  #include "monitor.h"
>  #include "qemu-char.h"
>  #include "sysemu.h"
>  #include "gdbstub.h"
> -#endif
> +#endif /* CONFIG_USER_ONLY */

same here

>  
> +
>  #define MAX_PACKET_LENGTH 4096
>  
>  #include "qemu_socket.h"
> @@ -215,7 +211,7 @@
>      -1
>  #endif
>  };
> -#else
> +#else  /* CONFIG_USER_ONLY */

and here

>  /* In system mode we only need SIGINT and SIGTRAP; other signals
>     are not yet supported.  */
>  
> @@ -232,7 +228,7 @@
>      -1,
>      TARGET_SIGTRAP
>  };
> -#endif
> +#endif  /* CONFIG_USER_ONLY */

and here.

>  
>  #ifdef CONFIG_USER_ONLY
>  static int target_signal_to_gdb (int sig)
> @@ -243,7 +239,7 @@
>              return i;
>      return GDB_SIGNAL_UNKNOWN;
>  }
> -#endif
> +#endif  /* CONFIG_USER_ONLY */
>  
>  static int gdb_signal_to_target (int sig)
>  {
> @@ -307,31 +303,13 @@
>  #ifdef CONFIG_USER_ONLY
>  /* XXX: This is not thread safe.  Do we care?  */
>  static int gdbserver_fd = -1;
> +gdbstub_func gdbstub_accept = NULL;
>  
> -static int get_char(GDBState *s)
> -{
> -    uint8_t ch;
> -    int ret;
> +static int gdb_disconnected (GDBState *);
> +static int get_char(GDBState *s);
> +#endif /* CONFIG_USER_ONLY */
>  
> -    for(;;) {
> -        ret = recv(s->fd, &ch, 1, 0);
> -        if (ret < 0) {
> -            if (errno == ECONNRESET)
> -                s->fd = -1;
> -            if (errno != EINTR && errno != EAGAIN)
> -                return -1;
> -        } else if (ret == 0) {
> -            close(s->fd);
> -            s->fd = -1;
> -            return -1;
> -        } else {
> -            break;
> -        }
> -    }
> -    return ch;
> -}
> -#endif
> -
> +static void put_buffer(GDBState *s, const uint8_t *buf, int len);
>  static gdb_syscall_complete_cb gdb_current_syscall_cb;
>  
>  enum {
> @@ -361,26 +339,6 @@
>  #endif
>  }
>  
> -static void put_buffer(GDBState *s, const uint8_t *buf, int len)
> -{
> -#ifdef CONFIG_USER_ONLY
> -    int ret;
> -
> -    while (len > 0) {
> -        ret = send(s->fd, buf, len, 0);
> -        if (ret < 0) {
> -            if (errno != EINTR && errno != EAGAIN)
> -                return;
> -        } else {
> -            buf += ret;
> -            len -= ret;
> -        }
> -    }
> -#else
> -    qemu_chr_write(s->chr, buf, len);
> -#endif
> -}
> -
>  static inline int fromhex(int v)
>  {
>      if (v >= '0' && v <= '9')
> @@ -1280,7 +1238,7 @@
>      return 0;
>  }
>  
> -#endif
> +#endif /* TARGET */

That comment is misleading. Just leave it alone for this patch.

>  
>  static int num_g_regs = NUM_CORE_REGS;
>  
> @@ -2091,8 +2049,7 @@
>  }
>  
>  #ifdef CONFIG_USER_ONLY
> -int
> -gdb_queuesig (void)
> +int gdb_queuesig (void)

If you are at it already: no space between function name and parameter
list. Applies to many other functions in this patch, too. Please adjust.

>  {
>      GDBState *s;
>  
> @@ -2104,16 +2061,41 @@
>          return 1;
>  }
>  
> -int
> -gdb_handlesig (CPUState *env, int sig)
> +/* Tell the remote gdb that the process has exited.  */
> +void gdb_exit(CPUState *env, int code)
>  {
>    GDBState *s;
> +  char buf[4];
> +
> +  s = gdbserver_state;
> +  if (gdbserver_fd < 0 || s->fd < 0)
> +    return;
> +
> +  snprintf(buf, sizeof(buf), "W%02x", code);
> +  put_packet(s, buf);
> +}
> +
> +void gdb_signalled(CPUState *env, int sig)
> +{
> +  GDBState *s;
> +  char buf[4];
> +
> +  s = gdbserver_state;
> +  if (gdbserver_fd < 0 || s->fd < 0)
> +    return;
> +
> +  snprintf(buf, sizeof(buf), "X%02x", target_signal_to_gdb (sig));
> +  put_packet(s, buf);
> +}
> +
> +int gdb_handlesig (CPUState *env, int sig)
> +{
> +  GDBState *s;
>    char buf[256];
>    int n;
>  
>    s = gdbserver_state;
> -  if (gdbserver_fd < 0 || s->fd < 0)
> -    return sig;
> +  if (gdb_disconnected (s)) return sig;

Separate line (with brackets), please.

>  
>    /* disable single step if it was enabled */
>    cpu_single_step(env, 0);
> @@ -2126,9 +2108,9 @@
>      }
>    /* put_packet() might have detected that the peer terminated the 
>       connection.  */
> -  if (s->fd < 0)
> -      return sig;
>  
> +  if (gdb_disconnected (s)) return sig;
> +

Same here.

>    sig = 0;
>    s->state = RS_IDLE;
>    s->running_state = 0;
> @@ -2138,10 +2120,11 @@
>          {
>            int i;
>  
> -          for (i = 0; i < n; i++)
> +          for (i = 0; i < n; i++) {
>              gdb_read_byte (s, buf[i]);
> +          }
>          }
> -      else if (n == 0 || errno != EAGAIN)
> +      else if (n == 0 || errno != EAGAIN) 

Trailing whitespace.

>          {
>            /* XXX: Connection closed.  Should probably wait for annother
>               connection before continuing.  */
> @@ -2153,108 +2136,294 @@
>    return sig;
>  }
>  
> -/* Tell the remote gdb that the process has exited.  */
> -void gdb_exit(CPUState *env, int code)
> +static int get_char(GDBState *s)
>  {
> -  GDBState *s;
> -  char buf[4];
> +    uint8_t ch;
> +    int ret;
>  
> -  s = gdbserver_state;
> -  if (gdbserver_fd < 0 || s->fd < 0)
> -    return;
> +    for(;;) {
> +        ret = recv(s->fd, &ch, 1, 0);
> +        if (ret < 0) {
> +            if (errno == ECONNRESET)
> +                s->fd = -1;
> +            if (errno != EINTR && errno != EAGAIN)
> +                return -1;
> +        } else if (ret == 0) {
> +            close(s->fd);
> +            s->fd = -1;
> +            return -1;
> +        } else {
> +            break;
> +        }
> +    }
> +    return ch;
> +}
>  
> -  snprintf(buf, sizeof(buf), "W%02x", code);
> -  put_packet(s, buf);
> +
> +static void put_buffer(GDBState *s, const uint8_t *buf, int len)
> +{
> +    int ret;
> +    while (len > 0) {
> +        ret = send(s->fd, buf, len, 0);
> +        if (ret < 0) {
> +            if (errno != EINTR && errno != EAGAIN)
> +                return;
> +        } else {
> +            buf += ret;
> +            len -= ret;
> +        }
> +    }
>  }
>  
> -/* Tell the remote gdb that the process has exited due to SIG.  */
> -void gdb_signalled(CPUState *env, int sig)
> +static int gdb_disconnected (GDBState *s) 
>  {
> -  GDBState *s;
> -  char buf[4];
> +    return  (gdbserver_fd < 0) || (s->fd < 0);
> +}
>  
> -  s = gdbserver_state;
> -  if (gdbserver_fd < 0 || s->fd < 0)
> -    return;
> +static GDBState *gdbserver_create_gdbstate (void)
> +{
> +    GDBState *s;
>  
> -  snprintf(buf, sizeof(buf), "X%02x", target_signal_to_gdb (sig));
> -  put_packet(s, buf);
> +    s = qemu_mallocz(sizeof(GDBState));
> +    s->c_cpu = first_cpu;
> +    s->g_cpu = first_cpu;
> +    gdb_has_xml = 0;
> +    gdbserver_state = s;
> +    return s;
>  }
>  
> -static void gdb_accept(void)
> +static int gdbserver_tcp_accept (void)
>  {
> +    int fd,res;
>      GDBState *s;
> -    struct sockaddr_in sockaddr;
> -    socklen_t len;
> -    int val, fd;
>  
> -    for(;;) {
> -        len = sizeof(sockaddr);
> -        fd = accept(gdbserver_fd, (struct sockaddr *)&sockaddr, &len);
> -        if (fd < 0 && errno != EINTR) {
> -            perror("accept");
> -            return;
> -        } else if (fd >= 0) {
> -            break;
> +    for (;;) {
> +        fd = accept (gdbserver_fd, 
> +                     (struct sockaddr *) NULL, (socklen_t *) NULL);
> +        if (fd < 0) {
> +           if (errno != EINTR) {
> +              perror("accept");
> +              return -1;
> +           }
> +        } else {
> +           break;
>          }
>      }
> -
>      /* set short latency */
> -    val = 1;
> -    setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *)&val, sizeof(val));
> +    res = 1;
> +    res = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *)&res, sizeof 
> (res));
> +    if (res < 0) {
> +       fprintf (stderr, "gdbserver ERROR : set nodelay\n");
> +       return -1;
> +    } 
> +    res = fcntl(fd, F_SETFL, O_NONBLOCK);
> +    if (res < 0) {
> +       fprintf (stderr, "gdbserver ERROR : set nonblock\n");
> +       return -1;
> +    }
> +    s = gdbserver_create_gdbstate ();
> +    s -> fd = fd;
> +    return 0;
> +}
>  
> -    s = qemu_mallocz(sizeof(GDBState));
> -    s->c_cpu = first_cpu;
> -    s->g_cpu = first_cpu;
> -    s->fd = fd;
> -    gdb_has_xml = 0;
>  
> -    gdbserver_state = s;
> +static int gdbserver_tcp_start (const char *host, const char *port,
> +                                gdbstub_func faccept)
> +{
> +    struct addrinfo info_in, *info_out;
> +    struct sockaddr_in addrin, *addr;
> +    int res;
>  
> -    fcntl(fd, F_SETFL, O_NONBLOCK);
> +    memset (&info_in, 0, sizeof(struct addrinfo));
> +    info_in.ai_flags=AI_PASSIVE;  /* force INADDR_ANY if host == NULL */
> +    info_in.ai_family= AF_INET;
> +    info_in.ai_socktype=SOCK_STREAM;
> +    info_in.ai_protocol=IPPROTO_TCP;
> +
> +    if (getaddrinfo(host, port, &info_in, &info_out) < 0) {
> +        perror ("hostname/portname name conversion error");
> +        return -1;
> +    }
> +    addr = (struct sockaddr_in *) info_out -> ai_addr;
> +    gdbserver_fd = socket (info_in.ai_family, info_in.ai_socktype,
> +                           info_in.ai_protocol);
> +    if (info_in.ai_protocol < 0) {
> +        perror ("gdb socket");
> +        return -1;
> +    }
> +    /* allow fast reuse */ 
> +    res = 1;
> +    res = setsockopt(gdbserver_fd, SOL_SOCKET, SO_REUSEADDR,
> +                     (char *) &res, sizeof(res));
> +    if (res <0) {
> +        perror("gdb socket : set  fast reuse\n");
> +        return -1;
> +    }
> +    res = bind (gdbserver_fd, (struct sockaddr *) addr, sizeof (addrin));
> +    if (res <0) {
> +        perror("gdb socket bind\n");
> +        return -1;
> +    }
> +    res = listen (gdbserver_fd,0);
> +    if (res <0) {
> +        perror("listen\n");
> +        return -1;
> +    }
> +    gdbstub_accept = faccept;
> +    return 0;
> +} 
> +
> +#ifndef     _WIN32
> +static int gdbserver_unix_unlink (void)
> +{
> +    struct sockaddr_un sock;
> +    socklen_t len;
> +    int res;
> +
> +    len = sizeof (sock.sun_path);
> +    res = getsockname (gdbserver_fd, &sock, &len);
> +    if (res < 0 ) {
> +       fprintf (stderr,"gdb accept/unlink : cannot get socket name\n");
> +       return -1;
> +    }
> +    res = unlink (sock.sun_path);
> +    if (res < 0) {
> +       fprintf (stderr,"gdb accept/unlink : cannot unlink 
> %s\n",sock.sun_path);
> +       return -1;
> +    } 
> +    return 0;
>  }
>  
> -static int gdbserver_open(int port)
> +static int gdbserver_unix_accept (void)
>  {
> -    struct sockaddr_in sockaddr;
> -    int fd, val, ret;
> +    int fd,res;
> +    GDBState *s;
> +    for (;;) {
> +        fd = accept (gdbserver_fd, 
> +                     (struct sockaddr *) NULL, ( socklen_t *) NULL);
> +        if (fd < 0) {
> +           if (errno != EINTR) {
> +              perror("accept");
> +              return -1;
> +           }
> +        } else {
> +           break;
> +        }
> +    }
>  
> -    fd = socket(PF_INET, SOCK_STREAM, 0);
> -    if (fd < 0) {
> -        perror("socket");
> -        return -1;
> +    res = fcntl(fd, F_SETFL, O_NONBLOCK);
> +    if (res < 0) {
> +       fprintf (stderr, "gdbserver ERROR : set nonblock\n");
> +       return -1;
>      }
> +    s = gdbserver_create_gdbstate ();
> +    s -> fd = fd;
> +    return 0;
> +}
>  
> -    /* allow fast reuse */
> -    val = 1;
> -    setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&val, sizeof(val));
> +static int gdbserver_unix_accept_unlink (void)
> +{
> +    return (gdbserver_unix_accept () + gdbserver_unix_unlink ());
> +}
>  
> -    sockaddr.sin_family = AF_INET;
> -    sockaddr.sin_port = htons(port);
> -    sockaddr.sin_addr.s_addr = 0;
> -    ret = bind(fd, (struct sockaddr *)&sockaddr, sizeof(sockaddr));
> -    if (ret < 0) {
> -        perror("bind");
> +static int gdbserver_unix_start (const char *filename, 
> +                                 gdbstub_func faccept)
> +{
> +    struct sockaddr_un addr;
> +    int res;
> +
> +    if (strlen(filename) == 0) {
> +       fprintf (stderr, "gdbserver ERROR : missing unix socket name\n");
> +       return -1;
> +    }
> +
> +    memset (&addr, 0, sizeof(struct sockaddr_un));
> +    addr.sun_family = AF_UNIX;
> +    strcpy (addr.sun_path, filename);
> +
> +    gdbserver_fd = socket (AF_UNIX,SOCK_STREAM,0);
> +    if (gdbserver_fd < 0) {
> +        perror ("gsbserver socket");
>          return -1;
>      }
> -    ret = listen(fd, 0);
> -    if (ret < 0) {
> -        perror("listen");
> +    res = bind (gdbserver_fd, (struct sockaddr *) &addr, 
> +                sizeof(struct sockaddr_un));
> +    if (res < 0) {
> +        perror ("gdbserver bind\n");
>          return -1;
>      }
> -    return fd;
> -}
> +    res = listen (gdbserver_fd,0);
> +    if (res <0) {
> +        perror("listen\n");
> +        return -1;
> +    }
> +    gdbstub_accept = faccept;
> +    return 0;
> +} 
>  
> -int gdbserver_start(int port)
> +#endif      /* _WIN32 */    
> +
> +void gdbstub_usage (void) 
>  {
> -    gdbserver_fd = gdbserver_open(port);
> -    if (gdbserver_fd < 0)
> -        return -1;
> -    /* accept connections */
> -    gdb_accept();
> +     printf("-gdb device       /* use gdb> target command */\n");
> +     printf("     tcp:host:port    target remote host:port  \n");
> +#ifndef _WIN32
> +     printf("     unix:name        target remote | socat stdio unix:name\n");
> +     printf("     unix:name,unlink : unlink remove name from filesystem 
> after connection\n");
> +#endif /* _WIN32 */
> +}     
> +
> +int gdbserver_start (const char *device)
> +{
> +    const char *p;
> +    char *name, *devicename,*opt;
> +
> +    name = malloc (strlen(device)+1);
> +    /* Light memory leak : will never be freed */
> +
> +    if (strstart (device, "tcp:",&p)) {
> +        if ((p == NULL) || (strlen(p) == 0)) {
> +            perror ("tcp socket syntax error");
> +            return -1;
> +        }
> +        strcpy (name,p);
> +        devicename = strrchr (name,':');
> +        if (devicename == NULL) {
> +            return -1;
> +        }
> +        *devicename++ = 0;
> +        if (*devicename == 0) {
> +            return -1;
> +        }
> +        if (*name == 0) {
> +            name = NULL;
> +        }
> +        return gdbserver_tcp_start (name,devicename,
> +                                    gdbserver_tcp_accept);
> +#ifndef _WIN32
> +    } else if (strstart (device, "unix:",&p)) {
> +        strcpy (name,p);
> +        opt = strrchr(name,',');
> +        if (opt == NULL) {
> +           return gdbserver_unix_start(name,gdbserver_unix_accept);
> +        } else {
> +           *opt++ = 0;
> +           if (!strcmp(opt,"unlink")) {
> +              return gdbserver_unix_start(name,
> +                                          gdbserver_unix_accept_unlink);
> +           } else {
> +              fprintf (stderr,"gdb unix socket : unknown %s option\n",opt);
> +              return -1;
> +           }
> +        } 
> +#endif /* _WIN32 */
> +    } else {
> +       return -1;
> +    }
>      return 0;
>  }
>  
> +/* Tell the remote gdb that the process has exited due to SIG.  */
>  /* Disable gdb stub for child processes.  */
>  void gdbserver_fork(CPUState *env)
>  {

Does that new comment really belong here?

> @@ -2266,7 +2435,14 @@
>      cpu_breakpoint_remove_all(env, BP_GDB);
>      cpu_watchpoint_remove_all(env, BP_GDB);
>  }
> -#else
> +
> +#else /* CONFIG_USER_ONLY */
> +
> +static void put_buffer(GDBState *s, const uint8_t *buf, int len)
> +{
> +    qemu_chr_write(s->chr, buf, len);
> +}
> +
>  static int gdb_chr_can_receive(void *opaque)
>  {
>    /* We can handle an arbitrarily large amount of data.
> @@ -2330,7 +2506,7 @@
>      if (vm_running)
>          vm_stop(EXCP_INTERRUPT);
>  }
> -#endif
> +#endif /* _WIN32 */

Skip such not directly related changes.

>  
>  int gdbserver_start(const char *device)
>  {
> @@ -2356,7 +2532,7 @@
>              act.sa_handler = gdb_sigterm_handler;
>              sigaction(SIGINT, &act, NULL);
>          }
> -#endif
> +#endif /* _WIN32 */
>          chr = qemu_chr_open("gdb", device, NULL);
>          if (!chr)
>              return -1;
> @@ -2390,4 +2566,4 @@
>  
>      return 0;
>  }
> -#endif
> +#endif /* CONFIG_USER_ONLY */
> Index: gdbstub.h
> ===================================================================
> --- gdbstub.h (révision 7105)
> +++ gdbstub.h (copie de travail)
> @@ -16,20 +16,25 @@
>  void gdb_do_syscall(gdb_syscall_complete_cb cb, const char *fmt, ...);
>  int use_gdb_syscalls(void);
>  void gdb_set_stop_cpu(CPUState *env);
> +
>  #ifdef CONFIG_USER_ONLY
> +typedef int (*gdbstub_func) (void);
> +extern gdbstub_func gdbstub_accept;
> +
>  int gdb_queuesig (void);
>  int gdb_handlesig (CPUState *, int);
>  void gdb_exit(CPUState *, int);
>  void gdb_signalled(CPUState *, int);
> -int gdbserver_start(int);
>  void gdbserver_fork(CPUState *);
> -#else
> -int gdbserver_start(const char *port);
> -#endif
> +void gdbstub_usage (void);
> +#endif /* CONFIG_USER_ONLY */
> +
> +int gdbserver_start(const char *device);
> +
>  /* Get or set a register.  Returns the size of the register.  */
>  typedef int (*gdb_reg_cb)(CPUState *env, uint8_t *buf, int reg);
>  void gdb_register_coprocessor(CPUState *env,
>                                gdb_reg_cb get_reg, gdb_reg_cb set_reg,
>                                int num_regs, const char *xml, int g_pos);
>  
> -#endif
> +#endif /* GDBSTUB_H */

I still think you are on the right track, just minor issues, some coding
style cleanups and the gdbstub_accept refactoring.

Thanks so far!
Jan

-- 
Siemens AG, Corporate Technology, CT SE 2
Corporate Competence Center Embedded Linux




reply via email to

[Prev in Thread] Current Thread [Next in Thread]