From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1Lu1VB-0002eS-HK for qemu-devel@nongnu.org; Wed, 15 Apr 2009 05:33:53 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1Lu1V5-0002eG-SE for qemu-devel@nongnu.org; Wed, 15 Apr 2009 05:33:51 -0400 Received: from [199.232.76.173] (port=43427 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1Lu1V5-0002eD-Cv for qemu-devel@nongnu.org; Wed, 15 Apr 2009 05:33:47 -0400 Received: from imag.imag.fr ([129.88.30.1]:38063) by monty-python.gnu.org with esmtps (TLS-1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.60) (envelope-from ) id 1Lu1V2-0004i4-Qu for qemu-devel@nongnu.org; Wed, 15 Apr 2009 05:33:47 -0400 Date: Wed, 15 Apr 2009 11:25:42 +0200 From: Philippe Waille Message-ID: <20090415092542.GA31193@otto.imag.fr> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="VS++wcV0S1rZb1Fb" Content-Disposition: inline Subject: [Qemu-devel] [PATCH] Gdbstub user mode -gdb dev option : add unix sockets Reply-To: qemu-devel@nongnu.org List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org --VS++wcV0S1rZb1Fb Content-Type: text/plain; charset=iso-8859-1 Content-Disposition: inline Content-Transfer-Encoding: quoted-printable X-MIME-Autoconverted: from 8bit to quoted-printable by imag.imag.fr id n3F9SpUd006851 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 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- linux-user/main.c (r=E9vision 7105) +++ linux-user/main.c (copie de travail) @@ -2202,40 +2202,37 @@ =20 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=3D= %s)\n" - "-s size set the stack size in bytes (default=3D%ld= )\n" - "-cpu model select CPU (-cpu ? for list)\n" - "-drop-ld-preload drop LD_PRELOAD for target process\n" - "-E var=3Dvalue sets/modifies targets environment variab= le(s)\n" - "-U var unsets targets environment variable(s)\n" - "\n" - "Debug options:\n" - "-d options activate log (logfile=3D%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 t= o the\n" - " 'strace' program. Enable by setting to an= y value.\n" - "You can use -E and -U options to set/unset environment varia= bles\n" - "for target process. It is possible to provide several varia= bles\n" - "by repeating the option. For example:\n" - " -E var1=3Dval2 -E var2=3Dval2 -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=3D= %s)\n", + interp_prefix); + printf("-s size set the stack size in bytes (default=3D%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=3Dvalue sets/modifies targets environment variab= le(s)\n"); + printf("-U var unsets targets environment variable(s)\n")= ; + printf("\n"); + printf("Debug options:\n"); + printf("-d options activate log (logfile=3D%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 t= o the\n"); + printf(" 'strace' program. Enable by setting to an= y value.\n"); + printf("You can use -E and -U options to set/unset environment varia= bles\n"); + printf("for target process. It is possible to provide several varia= bles\n"); + printf("by repeating the option. For example:\n"); + printf(" -E var1=3Dval2 -E var2=3Dval2 -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"); exit(1); } =20 @@ -2264,7 +2261,6 @@ CPUState *env; int optind; const char *r; - int gdbstub_port =3D 0; char **target_environ, **wrk; envlist_t *envlist =3D NULL; =20 @@ -2345,10 +2341,15 @@ fprintf(stderr, "page size must be a power of two\n"); exit(1); } - } else if (!strcmp(r, "g")) { - if (optind >=3D argc) + } else if (!strcmp(r, "gdb")) { + if (optind >=3D argc) { break; - gdbstub_port =3D atoi(argv[optind++]); + } + if (gdbserver_start(argv[optind++]) < 0) { + /* stop command line analysis */ + optind =3D argc; + break; + } } else if (!strcmp(r, "r")) { qemu_uname_release =3D argv[optind++]; } else if (!strcmp(r, "cpu")) { @@ -2706,8 +2707,10 @@ ts->heap_limit =3D 0; #endif =20 - if (gdbstub_port) { - gdbserver_start (gdbstub_port); + if (gdbstub_accept !=3D NULL) { + if ((*gdbstub_accept)() < 0) { + return -1; + } gdb_handlesig(env, 0); } cpu_loop(env); Index: gdbstub.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- gdbstub.c (r=E9vision 7105) +++ gdbstub.c (copie de travail) @@ -19,23 +19,19 @@ */ #include "config.h" #include "qemu-common.h" + #ifdef CONFIG_USER_ONLY -#include -#include -#include -#include -#include -#include -#include +#include "qemu.h" +#include "gdbstub.h" =20 -#include "qemu.h" -#else +#else /* CONFIG_USER_ONLY */ #include "monitor.h" #include "qemu-char.h" #include "sysemu.h" #include "gdbstub.h" -#endif +#endif /* CONFIG_USER_ONLY */ =20 + #define MAX_PACKET_LENGTH 4096 =20 #include "qemu_socket.h" @@ -215,7 +211,7 @@ -1 #endif }; -#else +#else /* CONFIG_USER_ONLY */ /* In system mode we only need SIGINT and SIGTRAP; other signals are not yet supported. */ =20 @@ -232,7 +228,7 @@ -1, TARGET_SIGTRAP }; -#endif +#endif /* CONFIG_USER_ONLY */ =20 #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 */ =20 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 =3D -1; +gdbstub_func gdbstub_accept =3D NULL; =20 -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 */ =20 - for(;;) { - ret =3D recv(s->fd, &ch, 1, 0); - if (ret < 0) { - if (errno =3D=3D ECONNRESET) - s->fd =3D -1; - if (errno !=3D EINTR && errno !=3D EAGAIN) - return -1; - } else if (ret =3D=3D 0) { - close(s->fd); - s->fd =3D -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; =20 enum { @@ -361,26 +339,6 @@ #endif } =20 -static void put_buffer(GDBState *s, const uint8_t *buf, int len) -{ -#ifdef CONFIG_USER_ONLY - int ret; - - while (len > 0) { - ret =3D send(s->fd, buf, len, 0); - if (ret < 0) { - if (errno !=3D EINTR && errno !=3D EAGAIN) - return; - } else { - buf +=3D ret; - len -=3D ret; - } - } -#else - qemu_chr_write(s->chr, buf, len); -#endif -} - static inline int fromhex(int v) { if (v >=3D '0' && v <=3D '9') @@ -1280,7 +1238,7 @@ return 0; } =20 -#endif +#endif /* TARGET */ =20 static int num_g_regs =3D NUM_CORE_REGS; =20 @@ -2091,8 +2049,7 @@ } =20 #ifdef CONFIG_USER_ONLY -int -gdb_queuesig (void) +int gdb_queuesig (void) { GDBState *s; =20 @@ -2104,16 +2061,41 @@ return 1; } =20 -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 =3D 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 =3D 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; =20 s =3D gdbserver_state; - if (gdbserver_fd < 0 || s->fd < 0) - return sig; + if (gdb_disconnected (s)) return sig; =20 /* 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=20 connection. */ - if (s->fd < 0) - return sig; =20 + if (gdb_disconnected (s)) return sig; + sig =3D 0; s->state =3D RS_IDLE; s->running_state =3D 0; @@ -2138,10 +2120,11 @@ { int i; =20 - for (i =3D 0; i < n; i++) + for (i =3D 0; i < n; i++) { gdb_read_byte (s, buf[i]); + } } - else if (n =3D=3D 0 || errno !=3D EAGAIN) + else if (n =3D=3D 0 || errno !=3D EAGAIN)=20 { /* XXX: Connection closed. Should probably wait for annother connection before continuing. */ @@ -2153,108 +2136,294 @@ return sig; } =20 -/* 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; =20 - s =3D gdbserver_state; - if (gdbserver_fd < 0 || s->fd < 0) - return; + for(;;) { + ret =3D recv(s->fd, &ch, 1, 0); + if (ret < 0) { + if (errno =3D=3D ECONNRESET) + s->fd =3D -1; + if (errno !=3D EINTR && errno !=3D EAGAIN) + return -1; + } else if (ret =3D=3D 0) { + close(s->fd); + s->fd =3D -1; + return -1; + } else { + break; + } + } + return ch; +} =20 - 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 =3D send(s->fd, buf, len, 0); + if (ret < 0) { + if (errno !=3D EINTR && errno !=3D EAGAIN) + return; + } else { + buf +=3D ret; + len -=3D ret; + } + } } =20 -/* 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)=20 { - GDBState *s; - char buf[4]; + return (gdbserver_fd < 0) || (s->fd < 0); +} =20 - s =3D gdbserver_state; - if (gdbserver_fd < 0 || s->fd < 0) - return; +static GDBState *gdbserver_create_gdbstate (void) +{ + GDBState *s; =20 - snprintf(buf, sizeof(buf), "X%02x", target_signal_to_gdb (sig)); - put_packet(s, buf); + s =3D qemu_mallocz(sizeof(GDBState)); + s->c_cpu =3D first_cpu; + s->g_cpu =3D first_cpu; + gdb_has_xml =3D 0; + gdbserver_state =3D s; + return s; } =20 -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; =20 - for(;;) { - len =3D sizeof(sockaddr); - fd =3D accept(gdbserver_fd, (struct sockaddr *)&sockaddr, &len); - if (fd < 0 && errno !=3D EINTR) { - perror("accept"); - return; - } else if (fd >=3D 0) { - break; + for (;;) { + fd =3D accept (gdbserver_fd,=20 + (struct sockaddr *) NULL, (socklen_t *) NULL); + if (fd < 0) { + if (errno !=3D EINTR) { + perror("accept"); + return -1; + } + } else { + break; } } - /* set short latency */ - val =3D 1; - setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *)&val, sizeof(val)); + res =3D 1; + res =3D setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *)&res, sizeo= f (res)); + if (res < 0) { + fprintf (stderr, "gdbserver ERROR : set nodelay\n"); + return -1; + }=20 + res =3D fcntl(fd, F_SETFL, O_NONBLOCK); + if (res < 0) { + fprintf (stderr, "gdbserver ERROR : set nonblock\n"); + return -1; + } + s =3D gdbserver_create_gdbstate (); + s -> fd =3D fd; + return 0; +} =20 - s =3D qemu_mallocz(sizeof(GDBState)); - s->c_cpu =3D first_cpu; - s->g_cpu =3D first_cpu; - s->fd =3D fd; - gdb_has_xml =3D 0; =20 - gdbserver_state =3D 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; =20 - fcntl(fd, F_SETFL, O_NONBLOCK); + memset (&info_in, 0, sizeof(struct addrinfo)); + info_in.ai_flags=3DAI_PASSIVE; /* force INADDR_ANY if host =3D=3D N= ULL */ + info_in.ai_family=3D AF_INET; + info_in.ai_socktype=3DSOCK_STREAM; + info_in.ai_protocol=3DIPPROTO_TCP; + + if (getaddrinfo(host, port, &info_in, &info_out) < 0) { + perror ("hostname/portname name conversion error"); + return -1; + } + addr =3D (struct sockaddr_in *) info_out -> ai_addr; + gdbserver_fd =3D 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 */=20 + res =3D 1; + res =3D setsockopt(gdbserver_fd, SOL_SOCKET, SO_REUSEADDR, + (char *) &res, sizeof(res)); + if (res <0) { + perror("gdb socket : set fast reuse\n"); + return -1; + } + res =3D bind (gdbserver_fd, (struct sockaddr *) addr, sizeof (addrin= )); + if (res <0) { + perror("gdb socket bind\n"); + return -1; + } + res =3D listen (gdbserver_fd,0); + if (res <0) { + perror("listen\n"); + return -1; + } + gdbstub_accept =3D faccept; + return 0; +}=20 + +#ifndef _WIN32 +static int gdbserver_unix_unlink (void) +{ + struct sockaddr_un sock; + socklen_t len; + int res; + + len =3D sizeof (sock.sun_path); + res =3D getsockname (gdbserver_fd, &sock, &len); + if (res < 0 ) { + fprintf (stderr,"gdb accept/unlink : cannot get socket name\n"); + return -1; + } + res =3D unlink (sock.sun_path); + if (res < 0) { + fprintf (stderr,"gdb accept/unlink : cannot unlink %s\n",sock.sun= _path); + return -1; + }=20 + return 0; } =20 -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 =3D accept (gdbserver_fd,=20 + (struct sockaddr *) NULL, ( socklen_t *) NULL); + if (fd < 0) { + if (errno !=3D EINTR) { + perror("accept"); + return -1; + } + } else { + break; + } + } =20 - fd =3D socket(PF_INET, SOCK_STREAM, 0); - if (fd < 0) { - perror("socket"); - return -1; + res =3D fcntl(fd, F_SETFL, O_NONBLOCK); + if (res < 0) { + fprintf (stderr, "gdbserver ERROR : set nonblock\n"); + return -1; } + s =3D gdbserver_create_gdbstate (); + s -> fd =3D fd; + return 0; +} =20 - /* allow fast reuse */ - val =3D 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 ()); +} =20 - sockaddr.sin_family =3D AF_INET; - sockaddr.sin_port =3D htons(port); - sockaddr.sin_addr.s_addr =3D 0; - ret =3D bind(fd, (struct sockaddr *)&sockaddr, sizeof(sockaddr)); - if (ret < 0) { - perror("bind"); +static int gdbserver_unix_start (const char *filename,=20 + gdbstub_func faccept) +{ + struct sockaddr_un addr; + int res; + + if (strlen(filename) =3D=3D 0) { + fprintf (stderr, "gdbserver ERROR : missing unix socket name\n"); + return -1; + } + + memset (&addr, 0, sizeof(struct sockaddr_un)); + addr.sun_family =3D AF_UNIX; + strcpy (addr.sun_path, filename); + + gdbserver_fd =3D socket (AF_UNIX,SOCK_STREAM,0); + if (gdbserver_fd < 0) { + perror ("gsbserver socket"); return -1; } - ret =3D listen(fd, 0); - if (ret < 0) { - perror("listen"); + res =3D bind (gdbserver_fd, (struct sockaddr *) &addr,=20 + sizeof(struct sockaddr_un)); + if (res < 0) { + perror ("gdbserver bind\n"); return -1; } - return fd; -} + res =3D listen (gdbserver_fd,0); + if (res <0) { + perror("listen\n"); + return -1; + } + gdbstub_accept =3D faccept; + return 0; +}=20 =20 -int gdbserver_start(int port) +#endif /* _WIN32 */ =20 + +void gdbstub_usage (void)=20 { - gdbserver_fd =3D 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 */ +} =20 + +int gdbserver_start (const char *device) +{ + const char *p; + char *name, *devicename,*opt; + + name =3D malloc (strlen(device)+1); + /* Light memory leak : will never be freed */ + + if (strstart (device, "tcp:",&p)) { + if ((p =3D=3D NULL) || (strlen(p) =3D=3D 0)) { + perror ("tcp socket syntax error"); + return -1; + } + strcpy (name,p); + devicename =3D strrchr (name,':'); + if (devicename =3D=3D NULL) { + return -1; + } + *devicename++ =3D 0; + if (*devicename =3D=3D 0) { + return -1; + } + if (*name =3D=3D 0) { + name =3D NULL; + } + return gdbserver_tcp_start (name,devicename, + gdbserver_tcp_accept); +#ifndef _WIN32 + } else if (strstart (device, "unix:",&p)) { + strcpy (name,p); + opt =3D strrchr(name,','); + if (opt =3D=3D NULL) { + return gdbserver_unix_start(name,gdbserver_unix_accept); + } else { + *opt++ =3D 0; + if (!strcmp(opt,"unlink")) { + return gdbserver_unix_start(name, + gdbserver_unix_accept_unlink); + } else { + fprintf (stderr,"gdb unix socket : unknown %s option\n",op= t); + return -1; + } + }=20 +#endif /* _WIN32 */ + } else { + return -1; + } return 0; } =20 +/* Tell the remote gdb that the process has exited due to SIG. */ /* Disable gdb stub for child processes. */ void gdbserver_fork(CPUState *env) { @@ -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 */ =20 int gdbserver_start(const char *device) { @@ -2356,7 +2532,7 @@ act.sa_handler =3D gdb_sigterm_handler; sigaction(SIGINT, &act, NULL); } -#endif +#endif /* _WIN32 */ chr =3D qemu_chr_open("gdb", device, NULL); if (!chr) return -1; @@ -2390,4 +2566,4 @@ =20 return 0; } -#endif +#endif /* CONFIG_USER_ONLY */ Index: gdbstub.h =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- gdbstub.h (r=E9vision 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); =20 -#endif +#endif /* GDBSTUB_H */ --VS++wcV0S1rZb1Fb Content-Type: application/x-tar Content-Disposition: attachment; filename="patch.tar" Content-Transfer-Encoding: quoted-printable gdbstub.c=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=000000644=000054742= =000054730=0000000202076=0011171146655=00012416=00 0=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00ustar =00waille=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= equipar=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00/*=0A * gdb server stub=0A *=0A * Copyrigh= t (c) 2003-2005 Fabrice Bellard=0A *=0A * This library is free software; yo= u can redistribute it and/or=0A * modify it under the terms of the GNU Less= er General Public=0A * License as published by the Free Software Foundation= ; either=0A * version 2 of the License, or (at your option) any later versi= on.=0A *=0A * This library is distributed in the hope that it will be usefu= l,=0A * but WITHOUT ANY WARRANTY; without even the implied warranty of=0A *= MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU=0A * Les= ser General Public License for more details.=0A *=0A * You should have rece= ived a copy of the GNU Lesser General Public=0A * License along with this l= ibrary; if not, write to the Free Software=0A * Foundation, Inc., 51 Frankl= in Street, Fifth Floor, Boston MA 02110-1301 USA=0A */=0A#include "config.= h"=0A#include "qemu-common.h"=0A=0A#ifdef CONFIG_USER_ONLY=0A#include "qemu= =2Eh"=0A#include "gdbstub.h"=0A=0A#else /* CONFIG_USER_ONLY */=0A#include "= monitor.h"=0A#include "qemu-char.h"=0A#include "sysemu.h"=0A#include "gdbst= ub.h"=0A#endif /* CONFIG_USER_ONLY */=0A=0A=0A#define MAX_PACKET_LENGTH 409= 6=0A=0A#include "qemu_socket.h"=0A#include "kvm.h"=0A=0A=0Aenum {=0A GDB= _SIGNAL_0 =3D 0,=0A GDB_SIGNAL_INT =3D 2,=0A GDB_SIGNAL_TRAP =3D 5,= =0A GDB_SIGNAL_UNKNOWN =3D 143=0A};=0A=0A#ifdef CONFIG_USER_ONLY=0A=0A/*= Map target signal numbers to GDB protocol signal numbers and vice=0A * ver= sa. For user emulation's currently supported systems, we can=0A * assume m= ost signals are defined.=0A */=0A=0Astatic int gdb_signal_table[] =3D {=0A = 0,=0A TARGET_SIGHUP,=0A TARGET_SIGINT,=0A TARGET_SIGQUIT,=0A = TARGET_SIGILL,=0A TARGET_SIGTRAP,=0A TARGET_SIGABRT,=0A -1, /* SI= GEMT */=0A TARGET_SIGFPE,=0A TARGET_SIGKILL,=0A TARGET_SIGBUS,=0A = TARGET_SIGSEGV,=0A TARGET_SIGSYS,=0A TARGET_SIGPIPE,=0A TARGET_= SIGALRM,=0A TARGET_SIGTERM,=0A TARGET_SIGURG,=0A TARGET_SIGSTOP,= =0A TARGET_SIGTSTP,=0A TARGET_SIGCONT,=0A TARGET_SIGCHLD,=0A TA= RGET_SIGTTIN,=0A TARGET_SIGTTOU,=0A TARGET_SIGIO,=0A TARGET_SIGXCP= U,=0A TARGET_SIGXFSZ,=0A TARGET_SIGVTALRM,=0A TARGET_SIGPROF,=0A = TARGET_SIGWINCH,=0A -1, /* SIGLOST */=0A TARGET_SIGUSR1,=0A TARG= ET_SIGUSR2,=0A#ifdef TARGET_SIGPWR=0A TARGET_SIGPWR,=0A#else=0A -1,= =0A#endif=0A -1, /* SIGPOLL */=0A -1,=0A -1,=0A -1,=0A -1,= =0A -1,=0A -1,=0A -1,=0A -1,=0A -1,=0A -1,=0A -1,=0A#i= fdef __SIGRTMIN=0A __SIGRTMIN + 1,=0A __SIGRTMIN + 2,=0A __SIGRTMI= N + 3,=0A __SIGRTMIN + 4,=0A __SIGRTMIN + 5,=0A __SIGRTMIN + 6,=0A= __SIGRTMIN + 7,=0A __SIGRTMIN + 8,=0A __SIGRTMIN + 9,=0A __SIG= RTMIN + 10,=0A __SIGRTMIN + 11,=0A __SIGRTMIN + 12,=0A __SIGRTMIN = + 13,=0A __SIGRTMIN + 14,=0A __SIGRTMIN + 15,=0A __SIGRTMIN + 16,= =0A __SIGRTMIN + 17,=0A __SIGRTMIN + 18,=0A __SIGRTMIN + 19,=0A = __SIGRTMIN + 20,=0A __SIGRTMIN + 21,=0A __SIGRTMIN + 22,=0A __SIG= RTMIN + 23,=0A __SIGRTMIN + 24,=0A __SIGRTMIN + 25,=0A __SIGRTMIN = + 26,=0A __SIGRTMIN + 27,=0A __SIGRTMIN + 28,=0A __SIGRTMIN + 29,= =0A __SIGRTMIN + 30,=0A __SIGRTMIN + 31,=0A -1, /* SIGCANCEL */=0A= __SIGRTMIN,=0A __SIGRTMIN + 32,=0A __SIGRTMIN + 33,=0A __SIGRT= MIN + 34,=0A __SIGRTMIN + 35,=0A __SIGRTMIN + 36,=0A __SIGRTMIN + = 37,=0A __SIGRTMIN + 38,=0A __SIGRTMIN + 39,=0A __SIGRTMIN + 40,=0A= __SIGRTMIN + 41,=0A __SIGRTMIN + 42,=0A __SIGRTMIN + 43,=0A __= SIGRTMIN + 44,=0A __SIGRTMIN + 45,=0A __SIGRTMIN + 46,=0A __SIGRTM= IN + 47,=0A __SIGRTMIN + 48,=0A __SIGRTMIN + 49,=0A __SIGRTMIN + 5= 0,=0A __SIGRTMIN + 51,=0A __SIGRTMIN + 52,=0A __SIGRTMIN + 53,=0A = __SIGRTMIN + 54,=0A __SIGRTMIN + 55,=0A __SIGRTMIN + 56,=0A __S= IGRTMIN + 57,=0A __SIGRTMIN + 58,=0A __SIGRTMIN + 59,=0A __SIGRTMI= N + 60,=0A __SIGRTMIN + 61,=0A __SIGRTMIN + 62,=0A __SIGRTMIN + 63= ,=0A __SIGRTMIN + 64,=0A __SIGRTMIN + 65,=0A __SIGRTMIN + 66,=0A = __SIGRTMIN + 67,=0A __SIGRTMIN + 68,=0A __SIGRTMIN + 69,=0A __SI= GRTMIN + 70,=0A __SIGRTMIN + 71,=0A __SIGRTMIN + 72,=0A __SIGRTMIN= + 73,=0A __SIGRTMIN + 74,=0A __SIGRTMIN + 75,=0A __SIGRTMIN + 76,= =0A __SIGRTMIN + 77,=0A __SIGRTMIN + 78,=0A __SIGRTMIN + 79,=0A = __SIGRTMIN + 80,=0A __SIGRTMIN + 81,=0A __SIGRTMIN + 82,=0A __SIG= RTMIN + 83,=0A __SIGRTMIN + 84,=0A __SIGRTMIN + 85,=0A __SIGRTMIN = + 86,=0A __SIGRTMIN + 87,=0A __SIGRTMIN + 88,=0A __SIGRTMIN + 89,= =0A __SIGRTMIN + 90,=0A __SIGRTMIN + 91,=0A __SIGRTMIN + 92,=0A = __SIGRTMIN + 93,=0A __SIGRTMIN + 94,=0A __SIGRTMIN + 95,=0A -1, /= * SIGINFO */=0A -1, /* UNKNOWN */=0A -1, /* DEFAULT */=0A -1,=0A = -1,=0A -1,=0A -1,=0A -1,=0A -1=0A#endif=0A};=0A#else /* CONF= IG_USER_ONLY */=0A/* In system mode we only need SIGINT and SIGTRAP; other = signals=0A are not yet supported. */=0A=0Aenum {=0A TARGET_SIGINT =3D= 2,=0A TARGET_SIGTRAP =3D 5=0A};=0A=0Astatic int gdb_signal_table[] =3D = {=0A -1,=0A -1,=0A TARGET_SIGINT,=0A -1,=0A -1,=0A TARGET= _SIGTRAP=0A};=0A#endif /* CONFIG_USER_ONLY */=0A=0A#ifdef CONFIG_USER_ONLY= =0Astatic int target_signal_to_gdb (int sig)=0A{=0A int i;=0A for (i = =3D 0; i < ARRAY_SIZE (gdb_signal_table); i++)=0A if (gdb_signal_tab= le[i] =3D=3D sig)=0A return i;=0A return GDB_SIGNAL_UNKNOWN;= =0A}=0A#endif /* CONFIG_USER_ONLY */=0A=0Astatic int gdb_signal_to_target = (int sig)=0A{=0A if (sig < ARRAY_SIZE (gdb_signal_table))=0A retu= rn gdb_signal_table[sig];=0A else=0A return -1;=0A}=0A=0A//#defin= e DEBUG_GDB=0A=0Atypedef struct GDBRegisterState {=0A int base_reg;=0A = int num_regs;=0A gdb_reg_cb get_reg;=0A gdb_reg_cb set_reg;=0A c= onst char *xml;=0A struct GDBRegisterState *next;=0A} GDBRegisterState;= =0A=0Aenum RSState {=0A RS_INACTIVE,=0A RS_IDLE,=0A RS_GETLINE,=0A= RS_CHKSUM1,=0A RS_CHKSUM2,=0A RS_SYSCALL,=0A};=0Atypedef struct G= DBState {=0A CPUState *c_cpu; /* current CPU for step/continue ops */=0A= CPUState *g_cpu; /* current CPU for other ops */=0A CPUState *query_= cpu; /* for q{f|s}ThreadInfo */=0A enum RSState state; /* parsing state = */=0A char line_buf[MAX_PACKET_LENGTH];=0A int line_buf_index;=0A = int line_csum;=0A uint8_t last_packet[MAX_PACKET_LENGTH + 4];=0A int = last_packet_len;=0A int signal;=0A#ifdef CONFIG_USER_ONLY=0A int fd;= =0A int running_state;=0A#else=0A CharDriverState *chr;=0A CharDri= verState *mon_chr;=0A#endif=0A} GDBState;=0A=0A/* By default use no IRQs an= d no timers while single stepping so as to=0A * make single stepping like a= n ICE HW step.=0A */=0Astatic int sstep_flags =3D SSTEP_ENABLE|SSTEP_NOIRQ|= SSTEP_NOTIMER;=0A=0Astatic GDBState *gdbserver_state;=0A=0A/* This is an ug= ly hack to cope with both new and old gdb.=0A If gdb sends qXfer:features= :read then assume we're talking to a newish=0A gdb that understands targe= t descriptions. */=0Astatic int gdb_has_xml;=0A=0A#ifdef CONFIG_USER_ONLY= =0A/* XXX: This is not thread safe. Do we care? */=0Astatic int gdbserver= _fd =3D -1;=0Agdbstub_func gdbstub_accept =3D NULL;=0A=0Astatic int gdb_dis= connected (GDBState *);=0Astatic int get_char(GDBState *s);=0A#endif /* CON= FIG_USER_ONLY */=0A=0Astatic void put_buffer(GDBState *s, const uint8_t *bu= f, int len);=0Astatic gdb_syscall_complete_cb gdb_current_syscall_cb;=0A=0A= enum {=0A GDB_SYS_UNKNOWN,=0A GDB_SYS_ENABLED,=0A GDB_SYS_DISABLED= ,=0A} gdb_syscall_mode;=0A=0A/* If gdb is connected when the first semihost= ing syscall occurs then use=0A remote gdb syscalls. Otherwise use native= file IO. */=0Aint use_gdb_syscalls(void)=0A{=0A if (gdb_syscall_mode = =3D=3D GDB_SYS_UNKNOWN) {=0A gdb_syscall_mode =3D (gdbserver_state ?= GDB_SYS_ENABLED=0A : GDB_SYS_DI= SABLED);=0A }=0A return gdb_syscall_mode =3D=3D GDB_SYS_ENABLED;=0A}= =0A=0A/* Resume execution. */=0Astatic inline void gdb_continue(GDBState *= s)=0A{=0A#ifdef CONFIG_USER_ONLY=0A s->running_state =3D 1;=0A#else=0A = vm_start();=0A#endif=0A}=0A=0Astatic inline int fromhex(int v)=0A{=0A = if (v >=3D '0' && v <=3D '9')=0A return v - '0';=0A else if (v >= =3D 'A' && v <=3D 'F')=0A return v - 'A' + 10;=0A else if (v >=3D= 'a' && v <=3D 'f')=0A return v - 'a' + 10;=0A else=0A ret= urn 0;=0A}=0A=0Astatic inline int tohex(int v)=0A{=0A if (v < 10)=0A = return v + '0';=0A else=0A return v - 10 + 'a';=0A}=0A=0Astat= ic void memtohex(char *buf, const uint8_t *mem, int len)=0A{=0A int i, c= ;=0A char *q;=0A q =3D buf;=0A for(i =3D 0; i < len; i++) {=0A = c =3D mem[i];=0A *q++ =3D tohex(c >> 4);=0A *q++ =3D tohe= x(c & 0xf);=0A }=0A *q =3D '\0';=0A}=0A=0Astatic void hextomem(uint8_= t *mem, const char *buf, int len)=0A{=0A int i;=0A=0A for(i =3D 0; i = < len; i++) {=0A mem[i] =3D (fromhex(buf[0]) << 4) | fromhex(buf[1])= ;=0A buf +=3D 2;=0A }=0A}=0A=0A/* return -1 if error, 0 if OK */= =0Astatic int put_packet_binary(GDBState *s, const char *buf, int len)=0A{= =0A int csum, i;=0A uint8_t *p;=0A=0A for(;;) {=0A p =3D s-= >last_packet;=0A *(p++) =3D '$';=0A memcpy(p, buf, len);=0A = p +=3D len;=0A csum =3D 0;=0A for(i =3D 0; i < len; i++= ) {=0A csum +=3D buf[i];=0A }=0A *(p++) =3D '#';= =0A *(p++) =3D tohex((csum >> 4) & 0xf);=0A *(p++) =3D tohex(= (csum) & 0xf);=0A=0A s->last_packet_len =3D p - s->last_packet;=0A = put_buffer(s, (uint8_t *)s->last_packet, s->last_packet_len);=0A=0A#i= fdef CONFIG_USER_ONLY=0A i =3D get_char(s);=0A if (i < 0)=0A = return -1;=0A if (i =3D=3D '+')=0A break;=0A#e= lse=0A break;=0A#endif=0A }=0A return 0;=0A}=0A=0A/* return -1= if error, 0 if OK */=0Astatic int put_packet(GDBState *s, const char *buf)= =0A{=0A#ifdef DEBUG_GDB=0A printf("reply=3D'%s'\n", buf);=0A#endif=0A=0A= return put_packet_binary(s, buf, strlen(buf));=0A}=0A=0A/* The GDB remo= te protocol transfers values in target byte order. This means=0A we can = use the raw memory access routines to access the value buffer.=0A Conveni= ently, these also handle the case where the buffer is mis-aligned.=0A */=0A= #define GET_REG8(val) do { \=0A stb_p(mem_buf, val); \=0A return 1; \= =0A } while(0)=0A#define GET_REG16(val) do { \=0A stw_p(mem_buf, val)= ; \=0A return 2; \=0A } while(0)=0A#define GET_REG32(val) do { \=0A = stl_p(mem_buf, val); \=0A return 4; \=0A } while(0)=0A#define GET_R= EG64(val) do { \=0A stq_p(mem_buf, val); \=0A return 8; \=0A } whi= le(0)=0A=0A#if TARGET_LONG_BITS =3D=3D 64=0A#define GET_REGL(val) GET_REG64= (val)=0A#define ldtul_p(addr) ldq_p(addr)=0A#else=0A#define GET_REGL(val) G= ET_REG32(val)=0A#define ldtul_p(addr) ldl_p(addr)=0A#endif=0A=0A#if defined= (TARGET_I386)=0A=0A#ifdef TARGET_X86_64=0Astatic const int gpr_map[16] =3D = {=0A R_EAX, R_EBX, R_ECX, R_EDX, R_ESI, R_EDI, R_EBP, R_ESP,=0A 8, 9,= 10, 11, 12, 13, 14, 15=0A};=0A#else=0Astatic const int gpr_map[8] =3D {0, = 1, 2, 3, 4, 5, 6, 7};=0A#endif=0A=0A#define NUM_CORE_REGS (CPU_NB_REGS * 2 = + 25)=0A=0Astatic int cpu_gdb_read_register(CPUState *env, uint8_t *mem_buf= , int n)=0A{=0A if (n < CPU_NB_REGS) {=0A GET_REGL(env->regs[gpr_= map[n]]);=0A } else if (n >=3D CPU_NB_REGS + 8 && n < CPU_NB_REGS + 16) = {=0A /* FIXME: byteswap float values. */=0A#ifdef USE_X86LDOUBLE=0A= memcpy(mem_buf, &env->fpregs[n - (CPU_NB_REGS + 8)], 10);=0A#else= =0A memset(mem_buf, 0, 10);=0A#endif=0A return 10;=0A } el= se if (n >=3D CPU_NB_REGS + 24) {=0A n -=3D CPU_NB_REGS + 24;=0A = if (n < CPU_NB_REGS) {=0A stq_p(mem_buf, env->xmm_regs[n].XM= M_Q(0));=0A stq_p(mem_buf + 8, env->xmm_regs[n].XMM_Q(1));=0A = return 16;=0A } else if (n =3D=3D CPU_NB_REGS) {=0A = GET_REG32(env->mxcsr);=0A } =0A } else {=0A n -=3D CPU= _NB_REGS;=0A switch (n) {=0A case 0: GET_REGL(env->eip);=0A = case 1: GET_REG32(env->eflags);=0A case 2: GET_REG32(env->segs= [R_CS].selector);=0A case 3: GET_REG32(env->segs[R_SS].selector);=0A= case 4: GET_REG32(env->segs[R_DS].selector);=0A case 5: GET_= REG32(env->segs[R_ES].selector);=0A case 6: GET_REG32(env->segs[R_FS= ].selector);=0A case 7: GET_REG32(env->segs[R_GS].selector);=0A = /* 8...15 x87 regs. */=0A case 16: GET_REG32(env->fpuc);=0A = case 17: GET_REG32((env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11);=0A= case 18: GET_REG32(0); /* ftag */=0A case 19: GET_REG32(0); = /* fiseg */=0A case 20: GET_REG32(0); /* fioff */=0A case 21:= GET_REG32(0); /* foseg */=0A case 22: GET_REG32(0); /* fooff */=0A = case 23: GET_REG32(0); /* fop */=0A /* 24+ xmm regs. */=0A = }=0A }=0A return 0;=0A}=0A=0Astatic int cpu_gdb_write_register(= CPUState *env, uint8_t *mem_buf, int i)=0A{=0A uint32_t tmp;=0A=0A if= (i < CPU_NB_REGS) {=0A env->regs[gpr_map[i]] =3D ldtul_p(mem_buf);= =0A return sizeof(target_ulong);=0A } else if (i >=3D CPU_NB_REGS= + 8 && i < CPU_NB_REGS + 16) {=0A i -=3D CPU_NB_REGS + 8;=0A#ifdef = USE_X86LDOUBLE=0A memcpy(&env->fpregs[i], mem_buf, 10);=0A#endif=0A = return 10;=0A } else if (i >=3D CPU_NB_REGS + 24) {=0A i -= =3D CPU_NB_REGS + 24;=0A if (i < CPU_NB_REGS) {=0A env->x= mm_regs[i].XMM_Q(0) =3D ldq_p(mem_buf);=0A env->xmm_regs[i].XMM_= Q(1) =3D ldq_p(mem_buf + 8);=0A return 16;=0A } else if (= i =3D=3D CPU_NB_REGS) {=0A env->mxcsr =3D ldl_p(mem_buf);=0A = return 4;=0A }=0A } else {=0A i -=3D CPU_NB_REGS;= =0A switch (i) {=0A case 0: env->eip =3D ldtul_p(mem_buf); re= turn sizeof(target_ulong);=0A case 1: env->eflags =3D ldl_p(mem_buf)= ; return 4;=0A#if defined(CONFIG_USER_ONLY)=0A#define LOAD_SEG(index, sreg)= \=0A tmp =3D ldl_p(mem_buf);\=0A if (tmp !=3D env->se= gs[sreg].selector)\=0A cpu_x86_load_seg(env, sreg, tmp);=0A#= else=0A/* FIXME: Honor segment registers. Needs to avoid raising an except= ion=0A when the selector is invalid. */=0A#define LOAD_SEG(index, sreg) = do {} while(0)=0A#endif=0A case 2: LOAD_SEG(10, R_CS); return 4;=0A = case 3: LOAD_SEG(11, R_SS); return 4;=0A case 4: LOAD_SEG(12,= R_DS); return 4;=0A case 5: LOAD_SEG(13, R_ES); return 4;=0A = case 6: LOAD_SEG(14, R_FS); return 4;=0A case 7: LOAD_SEG(15, R_GS)= ; return 4;=0A /* 8...15 x87 regs. */=0A case 16: env->fpuc = =3D ldl_p(mem_buf); return 4;=0A case 17:=0A tmp =3D= ldl_p(mem_buf);=0A env->fpstt =3D (tmp >> 11) & 7;=0A = env->fpus =3D tmp & ~0x3800;=0A return 4;=0A = case 18: /* ftag */ return 4;=0A case 19: /* fiseg */ return 4;= =0A case 20: /* fioff */ return 4;=0A case 21: /* foseg */ re= turn 4;=0A case 22: /* fooff */ return 4;=0A case 23: /* fop = */ return 4;=0A /* 24+ xmm regs. */=0A }=0A }=0A /* Un= recognised register. */=0A return 0;=0A}=0A=0A#elif defined (TARGET_PPC= )=0A=0A/* Old gdb always expects FP registers. Newer (xml-aware) gdb only= =0A expects whatever the target description contains. Due to a=0A hist= orical mishap the FP registers appear in between core integer=0A regs and= PC, MSR, CR, and so forth. We hack round this by giving the=0A FP regs = zero size when talking to a newer gdb. */=0A#define NUM_CORE_REGS 71=0A#if= defined (TARGET_PPC64)=0A#define GDB_CORE_XML "power64-core.xml"=0A#else= =0A#define GDB_CORE_XML "power-core.xml"=0A#endif=0A=0Astatic int cpu_gdb_r= ead_register(CPUState *env, uint8_t *mem_buf, int n)=0A{=0A if (n < 32) = {=0A /* gprs */=0A GET_REGL(env->gpr[n]);=0A } else if (n = < 64) {=0A /* fprs */=0A if (gdb_has_xml)=0A retur= n 0;=0A stfq_p(mem_buf, env->fpr[n-32]);=0A return 8;=0A }= else {=0A switch (n) {=0A case 64: GET_REGL(env->nip);=0A = case 65: GET_REGL(env->msr);=0A case 66:=0A {=0A = uint32_t cr =3D 0;=0A int i;=0A f= or (i =3D 0; i < 8; i++)=0A cr |=3D env->crf[i] << (32 -= ((i + 1) * 4));=0A GET_REG32(cr);=0A }=0A = case 67: GET_REGL(env->lr);=0A case 68: GET_REGL(env->ctr);=0A = case 69: GET_REGL(env->xer);=0A case 70:=0A {=0A = if (gdb_has_xml)=0A return 0;=0A = GET_REG32(0); /* fpscr */=0A }=0A }=0A }=0A retur= n 0;=0A}=0A=0Astatic int cpu_gdb_write_register(CPUState *env, uint8_t *mem= _buf, int n)=0A{=0A if (n < 32) {=0A /* gprs */=0A env->gp= r[n] =3D ldtul_p(mem_buf);=0A return sizeof(target_ulong);=0A } e= lse if (n < 64) {=0A /* fprs */=0A if (gdb_has_xml)=0A = return 0;=0A env->fpr[n-32] =3D ldfq_p(mem_buf);=0A retu= rn 8;=0A } else {=0A switch (n) {=0A case 64:=0A = env->nip =3D ldtul_p(mem_buf);=0A return sizeof(target_ulong);= =0A case 65:=0A ppc_store_msr(env, ldtul_p(mem_buf));=0A = return sizeof(target_ulong);=0A case 66:=0A {= =0A uint32_t cr =3D ldl_p(mem_buf);=0A int i;= =0A for (i =3D 0; i < 8; i++)=0A env->crf= [i] =3D (cr >> (32 - ((i + 1) * 4))) & 0xF;=0A return 4;=0A = }=0A case 67:=0A env->lr =3D ldtul_p(mem_buf);= =0A return sizeof(target_ulong);=0A case 68:=0A = env->ctr =3D ldtul_p(mem_buf);=0A return sizeof(target_ulong);= =0A case 69:=0A env->xer =3D ldtul_p(mem_buf);=0A = return sizeof(target_ulong);=0A case 70:=0A /* fpscr = */=0A if (gdb_has_xml)=0A return 0;=0A = return 4;=0A }=0A }=0A return 0;=0A}=0A=0A#elif defined (TARG= ET_SPARC)=0A=0A#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)=0A#def= ine NUM_CORE_REGS 86=0A#else=0A#define NUM_CORE_REGS 72=0A#endif=0A=0A#ifde= f TARGET_ABI32=0A#define GET_REGA(val) GET_REG32(val)=0A#else=0A#define GET= _REGA(val) GET_REGL(val)=0A#endif=0A=0Astatic int cpu_gdb_read_register(CPU= State *env, uint8_t *mem_buf, int n)=0A{=0A if (n < 8) {=0A /* g0= =2E.g7 */=0A GET_REGA(env->gregs[n]);=0A }=0A if (n < 32) {=0A= /* register window */=0A GET_REGA(env->regwptr[n - 8]);=0A = }=0A#if defined(TARGET_ABI32) || !defined(TARGET_SPARC64)=0A if (n < 6= 4) {=0A /* fprs */=0A GET_REG32(*((uint32_t *)&env->fpr[n - 3= 2]));=0A }=0A /* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */=0A switc= h (n) {=0A case 64: GET_REGA(env->y);=0A case 65: GET_REGA(GET_PSR(en= v));=0A case 66: GET_REGA(env->wim);=0A case 67: GET_REGA(env->tbr);= =0A case 68: GET_REGA(env->pc);=0A case 69: GET_REGA(env->npc);=0A = case 70: GET_REGA(env->fsr);=0A case 71: GET_REGA(0); /* csr */=0A d= efault: GET_REGA(0);=0A }=0A#else=0A if (n < 64) {=0A /* f0-f3= 1 */=0A GET_REG32(*((uint32_t *)&env->fpr[n - 32]));=0A }=0A i= f (n < 80) {=0A /* f32-f62 (double width, even numbers only) */=0A = uint64_t val;=0A=0A val =3D (uint64_t)*((uint32_t *)&env->fpr[= (n - 64) * 2 + 32]) << 32;=0A val |=3D *((uint32_t *)&env->fpr[(n - = 64) * 2 + 33]);=0A GET_REG64(val);=0A }=0A switch (n) {=0A = case 80: GET_REGL(env->pc);=0A case 81: GET_REGL(env->npc);=0A case 8= 2: GET_REGL(((uint64_t)GET_CCR(env) << 32) |=0A (= (env->asi & 0xff) << 24) |=0A ((env->pstate & 0xf= ff) << 8) |=0A GET_CWP64(env));=0A case 83: GE= T_REGL(env->fsr);=0A case 84: GET_REGL(env->fprs);=0A case 85: GET_RE= GL(env->y);=0A }=0A#endif=0A return 0;=0A}=0A=0Astatic int cpu_gdb_wr= ite_register(CPUState *env, uint8_t *mem_buf, int n)=0A{=0A#if defined(TARG= ET_ABI32)=0A abi_ulong tmp;=0A=0A tmp =3D ldl_p(mem_buf);=0A#else=0A = target_ulong tmp;=0A=0A tmp =3D ldtul_p(mem_buf);=0A#endif=0A=0A i= f (n < 8) {=0A /* g0..g7 */=0A env->gregs[n] =3D tmp;=0A }= else if (n < 32) {=0A /* register window */=0A env->regwptr[= n - 8] =3D tmp;=0A }=0A#if defined(TARGET_ABI32) || !defined(TARGET_SPAR= C64)=0A else if (n < 64) {=0A /* fprs */=0A *((uint32_t *)= &env->fpr[n - 32]) =3D tmp;=0A } else {=0A /* Y, PSR, WIM, TBR, P= C, NPC, FPSR, CPSR */=0A switch (n) {=0A case 64: env->y =3D = tmp; break;=0A case 65: PUT_PSR(env, tmp); break;=0A case 66:= env->wim =3D tmp; break;=0A case 67: env->tbr =3D tmp; break;=0A = case 68: env->pc =3D tmp; break;=0A case 69: env->npc =3D tmp; = break;=0A case 70: env->fsr =3D tmp; break;=0A default: retur= n 0;=0A }=0A }=0A return 4;=0A#else=0A else if (n < 64) {= =0A /* f0-f31 */=0A env->fpr[n] =3D ldfl_p(mem_buf);=0A = return 4;=0A } else if (n < 80) {=0A /* f32-f62 (double width, = even numbers only) */=0A *((uint32_t *)&env->fpr[(n - 64) * 2 + 32])= =3D tmp >> 32;=0A *((uint32_t *)&env->fpr[(n - 64) * 2 + 33]) =3D t= mp;=0A } else {=0A switch (n) {=0A case 80: env->pc =3D tm= p; break;=0A case 81: env->npc =3D tmp; break;=0A case 82:=0A= PUT_CCR(env, tmp >> 32);=0A env->asi =3D (tmp >> 24) & 0xff;=0A = env->pstate =3D (tmp >> 8) & 0xfff;=0A PUT_CWP64(env, tmp & 0xff);=0A= break;=0A case 83: env->fsr =3D tmp; break;=0A case 84: = env->fprs =3D tmp; break;=0A case 85: env->y =3D tmp; break;=0A = default: return 0;=0A }=0A }=0A return 8;=0A#endif=0A}=0A#e= lif defined (TARGET_ARM)=0A=0A/* Old gdb always expect FPA registers. Newe= r (xml-aware) gdb only expect=0A whatever the target description contains= =2E Due to a historical mishap=0A the FPA registers appear in between co= re integer regs and the CPSR.=0A We hack round this by giving the FPA reg= s zero size when talking to a=0A newer gdb. */=0A#define NUM_CORE_REGS 2= 6=0A#define GDB_CORE_XML "arm-core.xml"=0A=0Astatic int cpu_gdb_read_regist= er(CPUState *env, uint8_t *mem_buf, int n)=0A{=0A if (n < 16) {=0A = /* Core integer register. */=0A GET_REG32(env->regs[n]);=0A }= =0A if (n < 24) {=0A /* FPA registers. */=0A if (gdb_has_= xml)=0A return 0;=0A memset(mem_buf, 0, 12);=0A re= turn 12;=0A }=0A switch (n) {=0A case 24:=0A /* FPA status = register. */=0A if (gdb_has_xml)=0A return 0;=0A = GET_REG32(0);=0A case 25:=0A /* CPSR */=0A GET_REG32(cpsr_= read(env));=0A }=0A /* Unknown register. */=0A return 0;=0A}=0A= =0Astatic int cpu_gdb_write_register(CPUState *env, uint8_t *mem_buf, int n= )=0A{=0A uint32_t tmp;=0A=0A tmp =3D ldl_p(mem_buf);=0A=0A /* Mask= out low bit of PC to workaround gdb bugs. This will probably=0A cau= se problems if we ever implement the Jazelle DBX extensions. */=0A if (= n =3D=3D 15)=0A tmp &=3D ~1;=0A=0A if (n < 16) {=0A /* Cor= e integer register. */=0A env->regs[n] =3D tmp;=0A return 4;= =0A }=0A if (n < 24) { /* 16-23 */=0A /* FPA registers (ignore= d). */=0A if (gdb_has_xml)=0A return 0;=0A return= 12;=0A }=0A switch (n) {=0A case 24:=0A /* FPA status regi= ster (ignored). */=0A if (gdb_has_xml)=0A return 0;=0A = return 4;=0A case 25:=0A /* CPSR */=0A cpsr_write (e= nv, tmp, 0xffffffff);=0A return 4;=0A }=0A /* Unknown register= =2E */=0A return 0;=0A}=0A=0A#elif defined (TARGET_M68K)=0A=0A#define N= UM_CORE_REGS 18=0A=0A#define GDB_CORE_XML "cf-core.xml"=0A=0Astatic int cpu= _gdb_read_register(CPUState *env, uint8_t *mem_buf, int n)=0A{=0A if (n = < 8) {=0A /* D0-D7 */=0A GET_REG32(env->dregs[n]);=0A } el= se if (n < 16) {=0A /* A0-A7 */=0A GET_REG32(env->aregs[n - 8= ]);=0A } else {=0A switch (n) {=0A case 16: GET_REG32(env->sr);= =0A case 17: GET_REG32(env->pc);=0A }=0A }=0A /* FP reg= isters not included here because they vary between=0A ColdFire and m6= 8k. Use XML bits for these. */=0A return 0;=0A}=0A=0Astatic int cpu_gd= b_write_register(CPUState *env, uint8_t *mem_buf, int n)=0A{=0A uint32_t= tmp;=0A=0A tmp =3D ldl_p(mem_buf);=0A=0A if (n < 8) {=0A /* D= 0-D7 */=0A env->dregs[n] =3D tmp;=0A } else if (n < 8) {=0A = /* A0-A7 */=0A env->aregs[n - 8] =3D tmp;=0A } else {=0A = switch (n) {=0A case 16: env->sr =3D tmp; break;=0A case 17:= env->pc =3D tmp; break;=0A default: return 0;=0A }=0A }= =0A return 4;=0A}=0A#elif defined (TARGET_MIPS)=0A=0A#define NUM_CORE_RE= GS 73=0A=0Astatic int cpu_gdb_read_register(CPUState *env, uint8_t *mem_buf= , int n)=0A{=0A if (n < 32) {=0A GET_REGL(env->active_tc.gpr[n]);= =0A }=0A if (env->CP0_Config1 & (1 << CP0C1_FP)) {=0A if (n >= =3D 38 && n < 70) {=0A if (env->CP0_Status & (1 << CP0St_FR))=0A= GET_REGL(env->active_fpu.fpr[n - 38].d);=0A else=0A GET_REGL(= env->active_fpu.fpr[n - 38].w[FP_ENDIAN_IDX]);=0A }=0A switch= (n) {=0A case 70: GET_REGL((int32_t)env->active_fpu.fcr31);=0A = case 71: GET_REGL((int32_t)env->active_fpu.fcr0);=0A }=0A }=0A= switch (n) {=0A case 32: GET_REGL((int32_t)env->CP0_Status);=0A c= ase 33: GET_REGL(env->active_tc.LO[0]);=0A case 34: GET_REGL(env->active= _tc.HI[0]);=0A case 35: GET_REGL(env->CP0_BadVAddr);=0A case 36: GET_= REGL((int32_t)env->CP0_Cause);=0A case 37: GET_REGL(env->active_tc.PC);= =0A case 72: GET_REGL(0); /* fp */=0A case 89: GET_REGL((int32_t)env-= >CP0_PRid);=0A }=0A if (n >=3D 73 && n <=3D 88) {=0A /* 16 embedded r= egs. */=0A GET_REGL(0);=0A }=0A=0A return 0;=0A}=0A=0A/* convert MIP= S rounding mode in FCR31 to IEEE library */=0Astatic unsigned int ieee_rm[]= =3D=0A {=0A float_round_nearest_even,=0A float_round_to_zero,=0A = float_round_up,=0A float_round_down=0A };=0A#define RESTORE_ROUNDING_M= ODE \=0A set_float_rounding_mode(ieee_rm[env->active_fpu.fcr31 & 3], &en= v->active_fpu.fp_status)=0A=0Astatic int cpu_gdb_write_register(CPUState *e= nv, uint8_t *mem_buf, int n)=0A{=0A target_ulong tmp;=0A=0A tmp =3D l= dtul_p(mem_buf);=0A=0A if (n < 32) {=0A env->active_tc.gpr[n] =3D= tmp;=0A return sizeof(target_ulong);=0A }=0A if (env->CP0_Con= fig1 & (1 << CP0C1_FP)=0A && n >=3D 38 && n < 73) {=0A if= (n < 70) {=0A if (env->CP0_Status & (1 << CP0St_FR))=0A = env->active_fpu.fpr[n - 38].d =3D tmp;=0A else=0A = env->active_fpu.fpr[n - 38].w[FP_ENDIAN_IDX] =3D tmp;=0A }=0A = switch (n) {=0A case 70:=0A env->active_fpu.fcr31 = =3D tmp & 0xFF83FFFF;=0A /* set rounding mode */=0A R= ESTORE_ROUNDING_MODE;=0A#ifndef CONFIG_SOFTFLOAT=0A /* no floati= ng point exception for native float */=0A SET_FP_ENABLE(env->act= ive_fpu.fcr31, 0);=0A#endif=0A break;=0A case 71: env->ac= tive_fpu.fcr0 =3D tmp; break;=0A }=0A return sizeof(target_ul= ong);=0A }=0A switch (n) {=0A case 32: env->CP0_Status =3D tmp; br= eak;=0A case 33: env->active_tc.LO[0] =3D tmp; break;=0A case 34: env= ->active_tc.HI[0] =3D tmp; break;=0A case 35: env->CP0_BadVAddr =3D tmp;= break;=0A case 36: env->CP0_Cause =3D tmp; break;=0A case 37: env->a= ctive_tc.PC =3D tmp; break;=0A case 72: /* fp, ignored */ break;=0A d= efault: =0A if (n > 89)=0A return 0;=0A /* Other registers are readonly= =2E Ignore writes. */=0A break;=0A }=0A=0A return sizeof(target_ulo= ng);=0A}=0A#elif defined (TARGET_SH4)=0A=0A/* Hint: Use "set architecture s= h4" in GDB to see fpu registers */=0A/* FIXME: We should use XML for this. = */=0A=0A#define NUM_CORE_REGS 59=0A=0Astatic int cpu_gdb_read_register(CPU= State *env, uint8_t *mem_buf, int n)=0A{=0A if (n < 8) {=0A if ((= env->sr & (SR_MD | SR_RB)) =3D=3D (SR_MD | SR_RB)) {=0A GET_REGL= (env->gregs[n + 16]);=0A } else {=0A GET_REGL(env->gregs[= n]);=0A }=0A } else if (n < 16) {=0A GET_REGL(env->gregs[n= - 8]);=0A } else if (n >=3D 25 && n < 41) {=0A GET_REGL(env->fregs[(n -= 25) + ((env->fpscr & FPSCR_FR) ? 16 : 0)]);=0A } else if (n >=3D 43 && = n < 51) {=0A GET_REGL(env->gregs[n - 43]);=0A } else if (n >=3D 51 && n = < 59) {=0A GET_REGL(env->gregs[n - (51 - 16)]);=0A }=0A switch (n) {= =0A case 16: GET_REGL(env->pc);=0A case 17: GET_REGL(env->pr);=0A = case 18: GET_REGL(env->gbr);=0A case 19: GET_REGL(env->vbr);=0A case = 20: GET_REGL(env->mach);=0A case 21: GET_REGL(env->macl);=0A case 22:= GET_REGL(env->sr);=0A case 23: GET_REGL(env->fpul);=0A case 24: GET_= REGL(env->fpscr);=0A case 41: GET_REGL(env->ssr);=0A case 42: GET_REG= L(env->spc);=0A }=0A=0A return 0;=0A}=0A=0Astatic int cpu_gdb_write_r= egister(CPUState *env, uint8_t *mem_buf, int n)=0A{=0A uint32_t tmp;=0A= =0A tmp =3D ldl_p(mem_buf);=0A=0A if (n < 8) {=0A if ((env->sr= & (SR_MD | SR_RB)) =3D=3D (SR_MD | SR_RB)) {=0A env->gregs[n + = 16] =3D tmp;=0A } else {=0A env->gregs[n] =3D tmp;=0A = }=0A return 4;=0A } else if (n < 16) {=0A env->gregs[n - 8] = =3D tmp;=0A return 4;=0A } else if (n >=3D 25 && n < 41) {=0A env->fregs= [(n - 25) + ((env->fpscr & FPSCR_FR) ? 16 : 0)] =3D tmp;=0A } else if (n= >=3D 43 && n < 51) {=0A env->gregs[n - 43] =3D tmp;=0A return 4;=0A } e= lse if (n >=3D 51 && n < 59) {=0A env->gregs[n - (51 - 16)] =3D tmp;=0A ret= urn 4;=0A }=0A switch (n) {=0A case 16: env->pc =3D tmp;=0A cas= e 17: env->pr =3D tmp;=0A case 18: env->gbr =3D tmp;=0A case 19: env-= >vbr =3D tmp;=0A case 20: env->mach =3D tmp;=0A case 21: env->macl = =3D tmp;=0A case 22: env->sr =3D tmp;=0A case 23: env->fpul =3D tmp;= =0A case 24: env->fpscr =3D tmp;=0A case 41: env->ssr =3D tmp;=0A = case 42: env->spc =3D tmp;=0A default: return 0;=0A }=0A=0A return= 4;=0A}=0A#elif defined (TARGET_CRIS)=0A=0A#define NUM_CORE_REGS 49=0A=0Ast= atic int cpu_gdb_read_register(CPUState *env, uint8_t *mem_buf, int n)=0A{= =0A uint8_t srs;=0A=0A srs =3D env->pregs[PR_SRS];=0A if (n < 16) = {=0A GET_REG32(env->regs[n]);=0A }=0A=0A if (n >=3D 21 && n < 32) {= =0A GET_REG32(env->pregs[n - 16]);=0A }=0A if (n >=3D 33 && n < 49) {= =0A GET_REG32(env->sregs[srs][n - 33]);=0A }=0A switch (n) {=0A ca= se 16: GET_REG8(env->pregs[0]);=0A case 17: GET_REG8(env->pregs[1]);=0A = case 18: GET_REG32(env->pregs[2]);=0A case 19: GET_REG8(srs);=0A c= ase 20: GET_REG16(env->pregs[4]);=0A case 32: GET_REG32(env->pc);=0A = }=0A=0A return 0;=0A}=0A=0Astatic int cpu_gdb_write_register(CPUState *e= nv, uint8_t *mem_buf, int n)=0A{=0A uint32_t tmp;=0A=0A if (n > 49)= =0A return 0;=0A=0A tmp =3D ldl_p(mem_buf);=0A=0A if (n < 16) {=0A en= v->regs[n] =3D tmp;=0A }=0A=0A if (n >=3D 21 && n < 32) {=0A env->pre= gs[n - 16] =3D tmp;=0A }=0A=0A /* FIXME: Should support function regs= be writable? */=0A switch (n) {=0A case 16: return 1;=0A case 17= : return 1;=0A case 18: env->pregs[PR_PID] =3D tmp; break;=0A case 19= : return 1;=0A case 20: return 2;=0A case 32: env->pc =3D tmp; break;= =0A }=0A=0A return 4;=0A}=0A#elif defined (TARGET_ALPHA)=0A=0A#define= NUM_CORE_REGS 65=0A=0Astatic int cpu_gdb_read_register(CPUState *env, uint= 8_t *mem_buf, int n)=0A{=0A if (n < 31) {=0A GET_REGL(env->ir[n]);= =0A }=0A else if (n =3D=3D 31) {=0A GET_REGL(0);=0A }=0A = else if (n<63) {=0A uint64_t val;=0A=0A val=3D*((uint64_t *)&en= v->fir[n-32]);=0A GET_REGL(val);=0A }=0A else if (n=3D=3D63) {= =0A GET_REGL(env->fpcr);=0A }=0A else if (n=3D=3D64) {=0A = GET_REGL(env->pc);=0A }=0A else {=0A GET_REGL(0);=0A }=0A= =0A return 0;=0A}=0A=0Astatic int cpu_gdb_write_register(CPUState *env, = uint8_t *mem_buf, int n)=0A{=0A target_ulong tmp;=0A tmp =3D ldtul_p(= mem_buf);=0A=0A if (n < 31) {=0A env->ir[n] =3D tmp;=0A }=0A= =0A if (n > 31 && n < 63) {=0A env->fir[n - 32] =3D ldfl_p(mem_bu= f);=0A }=0A=0A if (n =3D=3D 64 ) {=0A env->pc=3Dtmp;=0A }=0A= =0A return 8;=0A}=0A#else=0A=0A#define NUM_CORE_REGS 0=0A=0Astatic int c= pu_gdb_read_register(CPUState *env, uint8_t *mem_buf, int n)=0A{=0A retu= rn 0;=0A}=0A=0Astatic int cpu_gdb_write_register(CPUState *env, uint8_t *me= m_buf, int n)=0A{=0A return 0;=0A}=0A=0A#endif /* TARGET */=0A=0Astatic = int num_g_regs =3D NUM_CORE_REGS;=0A=0A#ifdef GDB_CORE_XML=0A/* Encode data= using the encoding for 'x' packets. */=0Astatic int memtox(char *buf, con= st char *mem, int len)=0A{=0A char *p =3D buf;=0A char c;=0A=0A wh= ile (len--) {=0A c =3D *(mem++);=0A switch (c) {=0A ca= se '#': case '$': case '*': case '}':=0A *(p++) =3D '}';=0A = *(p++) =3D c ^ 0x20;=0A break;=0A default:=0A = *(p++) =3D c;=0A break;=0A }=0A }=0A return = p - buf;=0A}=0A=0Astatic const char *get_feature_xml(const char *p, const c= har **newp)=0A{=0A extern const char *const xml_builtin[][2];=0A size= _t len;=0A int i;=0A const char *name;=0A static char target_xml[1= 024];=0A=0A len =3D 0;=0A while (p[len] && p[len] !=3D ':')=0A = len++;=0A *newp =3D p + len;=0A=0A name =3D NULL;=0A if (strncmp(= p, "target.xml", len) =3D=3D 0) {=0A /* Generate the XML description= for this CPU. */=0A if (!target_xml[0]) {=0A GDBRegiste= rState *r;=0A=0A snprintf(target_xml, sizeof(target_xml),=0A = ""=0A ""=0A ""=0A= "",=0A = GDB_CORE_XML);=0A=0A for (r =3D first_cpu->gdb_regs; r; r =3D r-= >next) {=0A pstrcat(target_xml, sizeof(target_xml), "xml);=0A pstrcat(target_xml, sizeof(target_xml), "\"/>")= ;=0A }=0A pstrcat(target_xml, sizeof(target_xml), "");=0A }=0A return target_xml;=0A }=0A for (i = =3D 0; ; i++) {=0A name =3D xml_builtin[i][0];=0A if (!name |= | (strncmp(name, p, len) =3D=3D 0 && strlen(name) =3D=3D len))=0A = break;=0A }=0A return name ? xml_builtin[i][1] : NULL;=0A}=0A#endif= =0A=0Astatic int gdb_read_register(CPUState *env, uint8_t *mem_buf, int reg= )=0A{=0A GDBRegisterState *r;=0A=0A if (reg < NUM_CORE_REGS)=0A = return cpu_gdb_read_register(env, mem_buf, reg);=0A=0A for (r =3D env-= >gdb_regs; r; r =3D r->next) {=0A if (r->base_reg <=3D reg && reg < = r->base_reg + r->num_regs) {=0A return r->get_reg(env, mem_buf, = reg - r->base_reg);=0A }=0A }=0A return 0;=0A}=0A=0Astatic int= gdb_write_register(CPUState *env, uint8_t *mem_buf, int reg)=0A{=0A GDB= RegisterState *r;=0A=0A if (reg < NUM_CORE_REGS)=0A return cpu_gd= b_write_register(env, mem_buf, reg);=0A=0A for (r =3D env->gdb_regs; r; = r =3D r->next) {=0A if (r->base_reg <=3D reg && reg < r->base_reg + = r->num_regs) {=0A return r->set_reg(env, mem_buf, reg - r->base_= reg);=0A }=0A }=0A return 0;=0A}=0A=0A/* Register a supplement= al set of CPU registers. If g_pos is nonzero it=0A specifies the first r= egister number and these registers are included in=0A a standard "g" pack= et. Direction is relative to gdb, i.e. get_reg is=0A gdb reading a CPU r= egister, and set_reg is gdb modifying a CPU register.=0A */=0A=0Avoid gdb_r= egister_coprocessor(CPUState * env,=0A gdb_reg_= cb get_reg, gdb_reg_cb set_reg,=0A int num_regs= , const char *xml, int g_pos)=0A{=0A GDBRegisterState *s;=0A GDBRegis= terState **p;=0A static int last_reg =3D NUM_CORE_REGS;=0A=0A s =3D (= GDBRegisterState *)qemu_mallocz(sizeof(GDBRegisterState));=0A s->base_re= g =3D last_reg;=0A s->num_regs =3D num_regs;=0A s->get_reg =3D get_re= g;=0A s->set_reg =3D set_reg;=0A s->xml =3D xml;=0A p =3D &env->gd= b_regs;=0A while (*p) {=0A /* Check for duplicates. */=0A = if (strcmp((*p)->xml, xml) =3D=3D 0)=0A return;=0A p =3D= &(*p)->next;=0A }=0A /* Add to end of list. */=0A last_reg +=3D = num_regs;=0A *p =3D s;=0A if (g_pos) {=0A if (g_pos !=3D s->ba= se_reg) {=0A fprintf(stderr, "Error: Bad gdb register numbering = for '%s'\n"=0A "Expected %d got %d\n", xml, g_pos, s->ba= se_reg);=0A } else {=0A num_g_regs =3D last_reg;=0A = }=0A }=0A}=0A=0A#ifndef CONFIG_USER_ONLY=0Astatic const int xlat_gdb_t= ype[] =3D {=0A [GDB_WATCHPOINT_WRITE] =3D BP_GDB | BP_MEM_WRITE,=0A = [GDB_WATCHPOINT_READ] =3D BP_GDB | BP_MEM_READ,=0A [GDB_WATCHPOINT_ACC= ESS] =3D BP_GDB | BP_MEM_ACCESS,=0A};=0A#endif=0A=0Astatic int gdb_breakpoi= nt_insert(target_ulong addr, target_ulong len, int type)=0A{=0A CPUState= *env;=0A int err =3D 0;=0A=0A if (kvm_enabled())=0A return kv= m_insert_breakpoint(gdbserver_state->c_cpu, addr, len, type);=0A=0A swit= ch (type) {=0A case GDB_BREAKPOINT_SW:=0A case GDB_BREAKPOINT_HW:=0A = for (env =3D first_cpu; env !=3D NULL; env =3D env->next_cpu) {=0A = err =3D cpu_breakpoint_insert(env, addr, BP_GDB, NULL);=0A = if (err)=0A break;=0A }=0A return err;=0A= #ifndef CONFIG_USER_ONLY=0A case GDB_WATCHPOINT_WRITE:=0A case GDB_WA= TCHPOINT_READ:=0A case GDB_WATCHPOINT_ACCESS:=0A for (env =3D fir= st_cpu; env !=3D NULL; env =3D env->next_cpu) {=0A err =3D cpu_w= atchpoint_insert(env, addr, len, xlat_gdb_type[type],=0A = NULL);=0A if (err)=0A break;= =0A }=0A return err;=0A#endif=0A default:=0A return= -ENOSYS;=0A }=0A}=0A=0Astatic int gdb_breakpoint_remove(target_ulong ad= dr, target_ulong len, int type)=0A{=0A CPUState *env;=0A int err =3D = 0;=0A=0A if (kvm_enabled())=0A return kvm_remove_breakpoint(gdbse= rver_state->c_cpu, addr, len, type);=0A=0A switch (type) {=0A case GD= B_BREAKPOINT_SW:=0A case GDB_BREAKPOINT_HW:=0A for (env =3D first= _cpu; env !=3D NULL; env =3D env->next_cpu) {=0A err =3D cpu_bre= akpoint_remove(env, addr, BP_GDB);=0A if (err)=0A = break;=0A }=0A return err;=0A#ifndef CONFIG_USER_ONLY=0A = case GDB_WATCHPOINT_WRITE:=0A case GDB_WATCHPOINT_READ:=0A case GDB_W= ATCHPOINT_ACCESS:=0A for (env =3D first_cpu; env !=3D NULL; env =3D = env->next_cpu) {=0A err =3D cpu_watchpoint_remove(env, addr, len= , xlat_gdb_type[type]);=0A if (err)=0A break;=0A = }=0A return err;=0A#endif=0A default:=0A return -EN= OSYS;=0A }=0A}=0A=0Astatic void gdb_breakpoint_remove_all(void)=0A{=0A = CPUState *env;=0A=0A if (kvm_enabled()) {=0A kvm_remove_all_bre= akpoints(gdbserver_state->c_cpu);=0A return;=0A }=0A=0A for (e= nv =3D first_cpu; env !=3D NULL; env =3D env->next_cpu) {=0A cpu_bre= akpoint_remove_all(env, BP_GDB);=0A#ifndef CONFIG_USER_ONLY=0A cpu_w= atchpoint_remove_all(env, BP_GDB);=0A#endif=0A }=0A}=0A=0Astatic void gd= b_set_cpu_pc(GDBState *s, target_ulong pc)=0A{=0A#if defined(TARGET_I386)= =0A s->c_cpu->eip =3D pc;=0A cpu_synchronize_state(s->c_cpu, 1);=0A#e= lif defined (TARGET_PPC)=0A s->c_cpu->nip =3D pc;=0A#elif defined (TARGE= T_SPARC)=0A s->c_cpu->pc =3D pc;=0A s->c_cpu->npc =3D pc + 4;=0A#elif= defined (TARGET_ARM)=0A s->c_cpu->regs[15] =3D pc;=0A#elif defined (TAR= GET_SH4)=0A s->c_cpu->pc =3D pc;=0A#elif defined (TARGET_MIPS)=0A s->= c_cpu->active_tc.PC =3D pc;=0A#elif defined (TARGET_CRIS)=0A s->c_cpu->p= c =3D pc;=0A#elif defined (TARGET_ALPHA)=0A s->c_cpu->pc =3D pc;=0A#endi= f=0A}=0A=0Astatic int gdb_handle_packet(GDBState *s, const char *line_buf)= =0A{=0A CPUState *env;=0A const char *p;=0A int ch, reg_size, type= , res, thread;=0A char buf[MAX_PACKET_LENGTH];=0A uint8_t mem_buf[MAX= _PACKET_LENGTH];=0A uint8_t *registers;=0A target_ulong addr, len;=0A= =0A#ifdef DEBUG_GDB=0A printf("command=3D'%s'\n", line_buf);=0A#endif=0A= p =3D line_buf;=0A ch =3D *p++;=0A switch(ch) {=0A case '?':= =0A /* TODO: Make this return the correct value for user-mode. */= =0A snprintf(buf, sizeof(buf), "T%02xthread:%02x;", GDB_SIGNAL_TRAP,= =0A s->c_cpu->cpu_index+1);=0A put_packet(s, buf);= =0A /* Remove all the breakpoints when this query is issued,=0A = * because gdb is doing and initial connect and the state=0A * s= hould be cleaned up.=0A */=0A gdb_breakpoint_remove_all();= =0A break;=0A case 'c':=0A if (*p !=3D '\0') {=0A = addr =3D strtoull(p, (char **)&p, 16);=0A gdb_set_cpu_pc(s, a= ddr);=0A }=0A s->signal =3D 0;=0A gdb_continue(s);=0A = return RS_IDLE;=0A case 'C':=0A s->signal =3D gdb_signal_to_targe= t (strtoul(p, (char **)&p, 16));=0A if (s->signal =3D=3D -1)=0A = s->signal =3D 0;=0A gdb_continue(s);=0A return RS_IDLE= ;=0A case 'k':=0A /* Kill the target */=0A fprintf(stderr,= "\nQEMU: Terminated via GDBstub\n");=0A exit(0);=0A case 'D':=0A= /* Detach packet */=0A gdb_breakpoint_remove_all();=0A = gdb_continue(s);=0A put_packet(s, "OK");=0A break;=0A ca= se 's':=0A if (*p !=3D '\0') {=0A addr =3D strtoull(p, (c= har **)&p, 16);=0A gdb_set_cpu_pc(s, addr);=0A }=0A = cpu_single_step(s->c_cpu, sstep_flags);=0A gdb_continue(s);=0A ret= urn RS_IDLE;=0A case 'F':=0A {=0A target_ulong ret;=0A= target_ulong err;=0A=0A ret =3D strtoull(p, (char **= )&p, 16);=0A if (*p =3D=3D ',') {=0A p++;=0A = err =3D strtoull(p, (char **)&p, 16);=0A } else {=0A = err =3D 0;=0A }=0A if (*p =3D=3D ',')= =0A p++;=0A type =3D *p;=0A if (gdb_cu= rrent_syscall_cb)=0A gdb_current_syscall_cb(s->c_cpu, ret, e= rr);=0A if (type =3D=3D 'C') {=0A put_packet(s, "= T02");=0A } else {=0A gdb_continue(s);=0A = }=0A }=0A break;=0A case 'g':=0A cpu_synchroniz= e_state(s->g_cpu, 0);=0A len =3D 0;=0A for (addr =3D 0; addr = < num_g_regs; addr++) {=0A reg_size =3D gdb_read_register(s->g_c= pu, mem_buf + len, addr);=0A len +=3D reg_size;=0A }=0A = memtohex(buf, mem_buf, len);=0A put_packet(s, buf);=0A = break;=0A case 'G':=0A registers =3D mem_buf;=0A len =3D s= trlen(p) / 2;=0A hextomem((uint8_t *)registers, p, len);=0A f= or (addr =3D 0; addr < num_g_regs && len > 0; addr++) {=0A reg_s= ize =3D gdb_write_register(s->g_cpu, registers, addr);=0A len -= =3D reg_size;=0A registers +=3D reg_size;=0A }=0A = cpu_synchronize_state(s->g_cpu, 1);=0A put_packet(s, "OK");=0A = break;=0A case 'm':=0A addr =3D strtoull(p, (char **)&p, 16);= =0A if (*p =3D=3D ',')=0A p++;=0A len =3D strtoull= (p, NULL, 16);=0A if (cpu_memory_rw_debug(s->g_cpu, addr, mem_buf, l= en, 0) !=3D 0) {=0A put_packet (s, "E14");=0A } else {=0A= memtohex(buf, mem_buf, len);=0A put_packet(s, buf);= =0A }=0A break;=0A case 'M':=0A addr =3D strtoull(p= , (char **)&p, 16);=0A if (*p =3D=3D ',')=0A p++;=0A = len =3D strtoull(p, (char **)&p, 16);=0A if (*p =3D=3D ':')=0A = p++;=0A hextomem(mem_buf, p, len);=0A if (cpu_memory= _rw_debug(s->g_cpu, addr, mem_buf, len, 1) !=3D 0)=0A put_packet= (s, "E14");=0A else=0A put_packet(s, "OK");=0A bre= ak;=0A case 'p':=0A /* Older gdb are really dumb, and don't use '= g' if 'p' is avaialable.=0A This works, but can be very slow. An= ything new enough to=0A understand XML also knows how to use this= properly. */=0A if (!gdb_has_xml)=0A goto unknown_comma= nd;=0A addr =3D strtoull(p, (char **)&p, 16);=0A reg_size =3D= gdb_read_register(s->g_cpu, mem_buf, addr);=0A if (reg_size) {=0A = memtohex(buf, mem_buf, reg_size);=0A put_packet(s, buf= );=0A } else {=0A put_packet(s, "E14");=0A }=0A = break;=0A case 'P':=0A if (!gdb_has_xml)=0A goto = unknown_command;=0A addr =3D strtoull(p, (char **)&p, 16);=0A = if (*p =3D=3D '=3D')=0A p++;=0A reg_size =3D strlen(p) /= 2;=0A hextomem(mem_buf, p, reg_size);=0A gdb_write_register(= s->g_cpu, mem_buf, addr);=0A put_packet(s, "OK");=0A break;= =0A case 'Z':=0A case 'z':=0A type =3D strtoul(p, (char **)&p,= 16);=0A if (*p =3D=3D ',')=0A p++;=0A addr =3D st= rtoull(p, (char **)&p, 16);=0A if (*p =3D=3D ',')=0A p++;= =0A len =3D strtoull(p, (char **)&p, 16);=0A if (ch =3D=3D 'Z= ')=0A res =3D gdb_breakpoint_insert(addr, len, type);=0A = else=0A res =3D gdb_breakpoint_remove(addr, len, type);=0A = if (res >=3D 0)=0A put_packet(s, "OK");=0A else if (re= s =3D=3D -ENOSYS)=0A put_packet(s, "");=0A else=0A = put_packet(s, "E22");=0A break;=0A case 'H':=0A type = =3D *p++;=0A thread =3D strtoull(p, (char **)&p, 16);=0A if (= thread =3D=3D -1 || thread =3D=3D 0) {=0A put_packet(s, "OK");= =0A break;=0A }=0A for (env =3D first_cpu; env != =3D NULL; env =3D env->next_cpu)=0A if (env->cpu_index + 1 =3D= =3D thread)=0A break;=0A if (env =3D=3D NULL) {=0A = put_packet(s, "E22");=0A break;=0A }=0A s= witch (type) {=0A case 'c':=0A s->c_cpu =3D env;=0A = put_packet(s, "OK");=0A break;=0A case 'g':=0A = s->g_cpu =3D env;=0A put_packet(s, "OK");=0A b= reak;=0A default:=0A put_packet(s, "E22");=0A = break;=0A }=0A break;=0A case 'T':=0A thread =3D = strtoull(p, (char **)&p, 16);=0A#ifndef CONFIG_USER_ONLY=0A if (thre= ad > 0 && thread < smp_cpus + 1)=0A#else=0A if (thread =3D=3D 1)=0A#= endif=0A put_packet(s, "OK");=0A else=0A put_= packet(s, "E22");=0A break;=0A case 'q':=0A case 'Q':=0A = /* parse any 'q' packets here */=0A if (!strcmp(p,"qemu.sstepbits"= )) {=0A /* Query Breakpoint bit definitions */=0A snp= rintf(buf, sizeof(buf), "ENABLE=3D%x,NOIRQ=3D%x,NOTIMER=3D%x",=0A = SSTEP_ENABLE,=0A SSTEP_NOIRQ,=0A = SSTEP_NOTIMER);=0A put_packet(s, buf);=0A br= eak;=0A } else if (strncmp(p,"qemu.sstep",10) =3D=3D 0) {=0A = /* Display or change the sstep_flags */=0A p +=3D 10;=0A = if (*p !=3D '=3D') {=0A /* Display current setting *= /=0A snprintf(buf, sizeof(buf), "0x%x", sstep_flags);=0A = put_packet(s, buf);=0A break;=0A }=0A= p++;=0A type =3D strtoul(p, (char **)&p, 16);=0A = sstep_flags =3D type;=0A put_packet(s, "OK");=0A = break;=0A } else if (strcmp(p,"C") =3D=3D 0) {=0A /* = "Current thread" remains vague in the spec, so always return=0A = * the first CPU (gdb returns the first thread). */=0A put_pack= et(s, "QC1");=0A break;=0A } else if (strcmp(p,"fThreadIn= fo") =3D=3D 0) {=0A s->query_cpu =3D first_cpu;=0A go= to report_cpuinfo;=0A } else if (strcmp(p,"sThreadInfo") =3D=3D 0) {= =0A report_cpuinfo:=0A if (s->query_cpu) {=0A = snprintf(buf, sizeof(buf), "m%x", s->query_cpu->cpu_index+1);=0A = put_packet(s, buf);=0A s->query_cpu =3D s->query_cp= u->next_cpu;=0A } else=0A put_packet(s, "l");=0A = break;=0A } else if (strncmp(p,"ThreadExtraInfo,", 16) = =3D=3D 0) {=0A thread =3D strtoull(p+16, (char **)&p, 16);=0A = for (env =3D first_cpu; env !=3D NULL; env =3D env->next_cpu)=0A = if (env->cpu_index + 1 =3D=3D thread) {=0A = cpu_synchronize_state(env, 0);=0A len =3D snprintf((cha= r *)mem_buf, sizeof(mem_buf),=0A "CPU#%d = [%s]", env->cpu_index,=0A env->halted ? "= halted " : "running");=0A memtohex(buf, mem_buf, len);= =0A put_packet(s, buf);=0A break;=0A = }=0A break;=0A }=0A#ifdef CONFIG_USER_ONLY= =0A else if (strncmp(p, "Offsets", 7) =3D=3D 0) {=0A Task= State *ts =3D s->c_cpu->opaque;=0A=0A snprintf(buf, sizeof(buf),= =0A "Text=3D" TARGET_ABI_FMT_lx ";Data=3D" TARGET_ABI_F= MT_lx=0A ";Bss=3D" TARGET_ABI_FMT_lx,=0A = ts->info->code_offset,=0A ts->info->data_offset,= =0A ts->info->data_offset);=0A put_packet(s,= buf);=0A break;=0A }=0A#else /* !CONFIG_USER_ONLY */=0A = else if (strncmp(p, "Rcmd,", 5) =3D=3D 0) {=0A int len = =3D strlen(p + 5);=0A=0A if ((len % 2) !=3D 0) {=0A = put_packet(s, "E01");=0A break;=0A }=0A = hextomem(mem_buf, p + 5, len);=0A len =3D len / 2;=0A = mem_buf[len++] =3D 0;=0A qemu_chr_read(s->mon_chr, mem_buf= , len);=0A put_packet(s, "OK");=0A break;=0A }= =0A#endif /* !CONFIG_USER_ONLY */=0A if (strncmp(p, "Supported", 9) = =3D=3D 0) {=0A snprintf(buf, sizeof(buf), "PacketSize=3D%x", MAX= _PACKET_LENGTH);=0A#ifdef GDB_CORE_XML=0A pstrcat(buf, sizeof(bu= f), ";qXfer:features:read+");=0A#endif=0A put_packet(s, buf);=0A= break;=0A }=0A#ifdef GDB_CORE_XML=0A if (strncmp(= p, "Xfer:features:read:", 19) =3D=3D 0) {=0A const char *xml;=0A= target_ulong total_len;=0A=0A gdb_has_xml =3D 1;=0A = p +=3D 19;=0A xml =3D get_feature_xml(p, &p);=0A = if (!xml) {=0A snprintf(buf, sizeof(buf), "E00");=0A = put_packet(s, buf);=0A break;=0A }= =0A=0A if (*p =3D=3D ':')=0A p++;=0A a= ddr =3D strtoul(p, (char **)&p, 16);=0A if (*p =3D=3D ',')=0A = p++;=0A len =3D strtoul(p, (char **)&p, 16);=0A=0A = total_len =3D strlen(xml);=0A if (addr > total_len) {= =0A snprintf(buf, sizeof(buf), "E00");=0A put= _packet(s, buf);=0A break;=0A }=0A if = (len > (MAX_PACKET_LENGTH - 5) / 2)=0A len =3D (MAX_PACKET_L= ENGTH - 5) / 2;=0A if (len < total_len - addr) {=0A = buf[0] =3D 'm';=0A len =3D memtox(buf + 1, xml + addr, le= n);=0A } else {=0A buf[0] =3D 'l';=0A = len =3D memtox(buf + 1, xml + addr, total_len - addr);=0A }= =0A put_packet_binary(s, buf, len + 1);=0A break;=0A = }=0A#endif=0A /* Unrecognised 'q' command. */=0A goto= unknown_command;=0A=0A default:=0A unknown_command:=0A /* put= empty packet */=0A buf[0] =3D '\0';=0A put_packet(s, buf);= =0A break;=0A }=0A return RS_IDLE;=0A}=0A=0Avoid gdb_set_stop_= cpu(CPUState *env)=0A{=0A gdbserver_state->c_cpu =3D env;=0A gdbserve= r_state->g_cpu =3D env;=0A}=0A=0A#ifndef CONFIG_USER_ONLY=0Astatic void gdb= _vm_state_change(void *opaque, int running, int reason)=0A{=0A GDBState = *s =3D gdbserver_state;=0A CPUState *env =3D s->c_cpu;=0A char buf[25= 6];=0A const char *type;=0A int ret;=0A=0A if (running || (reason = !=3D EXCP_DEBUG && reason !=3D EXCP_INTERRUPT) ||=0A s->state =3D=3D= RS_INACTIVE || s->state =3D=3D RS_SYSCALL)=0A return;=0A=0A /* d= isable single step if it was enable */=0A cpu_single_step(env, 0);=0A=0A= if (reason =3D=3D EXCP_DEBUG) {=0A if (env->watchpoint_hit) {=0A= switch (env->watchpoint_hit->flags & BP_MEM_ACCESS) {=0A = case BP_MEM_READ:=0A type =3D "r";=0A br= eak;=0A case BP_MEM_ACCESS:=0A type =3D "a";=0A = break;=0A default:=0A type =3D "";= =0A break;=0A }=0A snprintf(buf, sizeo= f(buf),=0A "T%02xthread:%02x;%swatch:" TARGET_FMT_lx ";= ",=0A GDB_SIGNAL_TRAP, env->cpu_index+1, type,=0A = env->watchpoint_hit->vaddr);=0A put_packet(s, buf= );=0A env->watchpoint_hit =3D NULL;=0A return;=0A = }=0A tb_flush(env);=0A ret =3D GDB_SIGNAL_TRAP;=0A } else {= =0A ret =3D GDB_SIGNAL_INT;=0A }=0A snprintf(buf, sizeof(buf),= "T%02xthread:%02x;", ret, env->cpu_index+1);=0A put_packet(s, buf);=0A}= =0A#endif=0A=0A/* Send a gdb syscall request.=0A This accepts limited pri= ntf-style format specifiers, specifically:=0A %x - target_ulong argumen= t printed in hex.=0A %lx - 64-bit argument printed in hex.=0A %s - s= tring pointer (target_ulong) and length (int) pair. */=0Avoid gdb_do_sysca= ll(gdb_syscall_complete_cb cb, const char *fmt, ...)=0A{=0A va_list va;= =0A char buf[256];=0A char *p;=0A target_ulong addr;=0A uint64_= t i64;=0A GDBState *s;=0A=0A s =3D gdbserver_state;=0A if (!s)=0A = return;=0A gdb_current_syscall_cb =3D cb;=0A s->state =3D RS_S= YSCALL;=0A#ifndef CONFIG_USER_ONLY=0A vm_stop(EXCP_DEBUG);=0A#endif=0A = s->state =3D RS_IDLE;=0A va_start(va, fmt);=0A p =3D buf;=0A *(p= ++) =3D 'F';=0A while (*fmt) {=0A if (*fmt =3D=3D '%') {=0A = fmt++;=0A switch (*fmt++) {=0A case 'x':=0A = addr =3D va_arg(va, target_ulong);=0A p +=3D snp= rintf(p, &buf[sizeof(buf)] - p, TARGET_FMT_lx, addr);=0A bre= ak;=0A case 'l':=0A if (*(fmt++) !=3D 'x')=0A = goto bad_format;=0A i64 =3D va_arg(va, uint6= 4_t);=0A p +=3D snprintf(p, &buf[sizeof(buf)] - p, "%" PRIx6= 4, i64);=0A break;=0A case 's':=0A = addr =3D va_arg(va, target_ulong);=0A p +=3D snprintf(p, &b= uf[sizeof(buf)] - p, TARGET_FMT_lx "/%x",=0A a= ddr, va_arg(va, int));=0A break;=0A default:=0A = bad_format:=0A fprintf(stderr, "gdbstub: Bad sysca= ll format string '%s'\n",=0A fmt - 1);=0A = break;=0A }=0A } else {=0A *(p++) =3D *(f= mt++);=0A }=0A }=0A *p =3D 0;=0A va_end(va);=0A put_pack= et(s, buf);=0A#ifdef CONFIG_USER_ONLY=0A gdb_handlesig(s->c_cpu, 0);=0A#= else=0A cpu_exit(s->c_cpu);=0A#endif=0A}=0A=0Astatic void gdb_read_byte(= GDBState *s, int ch)=0A{=0A int i, csum;=0A uint8_t reply;=0A=0A#ifnd= ef CONFIG_USER_ONLY=0A if (s->last_packet_len) {=0A /* Waiting fo= r a response to the last packet. If we see the start=0A of a new= command then abandon the previous response. */=0A if (ch =3D=3D '-= ') {=0A#ifdef DEBUG_GDB=0A printf("Got NACK, retransmitting\n");= =0A#endif=0A put_buffer(s, (uint8_t *)s->last_packet, s->last_pa= cket_len);=0A }=0A#ifdef DEBUG_GDB=0A else if (ch =3D=3D '+')= =0A printf("Got ACK\n");=0A else=0A printf("Go= t '%c' when expecting ACK/NACK\n", ch);=0A#endif=0A if (ch =3D=3D '+= ' || ch =3D=3D '$')=0A s->last_packet_len =3D 0;=0A if (c= h !=3D '$')=0A return;=0A }=0A if (vm_running) {=0A = /* when the CPU is running, we cannot do anything except stop=0A = it when receiving a char */=0A vm_stop(EXCP_INTERRUPT);=0A } els= e=0A#endif=0A {=0A switch(s->state) {=0A case RS_IDLE:=0A = if (ch =3D=3D '$') {=0A s->line_buf_index =3D 0;= =0A s->state =3D RS_GETLINE;=0A }=0A b= reak;=0A case RS_GETLINE:=0A if (ch =3D=3D '#') {=0A = s->state =3D RS_CHKSUM1;=0A } else if (s->line_buf_index = >=3D sizeof(s->line_buf) - 1) {=0A s->state =3D RS_IDLE;=0A = } else {=0A s->line_buf[s->line_buf_index++] =3D ch;= =0A }=0A break;=0A case RS_CHKSUM1:=0A = s->line_buf[s->line_buf_index] =3D '\0';=0A s->line_csum =3D= fromhex(ch) << 4;=0A s->state =3D RS_CHKSUM2;=0A bre= ak;=0A case RS_CHKSUM2:=0A s->line_csum |=3D fromhex(ch);= =0A csum =3D 0;=0A for(i =3D 0; i < s->line_buf_index= ; i++) {=0A csum +=3D s->line_buf[i];=0A }=0A = if (s->line_csum !=3D (csum & 0xff)) {=0A reply =3D = '-';=0A put_buffer(s, &reply, 1);=0A s->state= =3D RS_IDLE;=0A } else {=0A reply =3D '+';=0A = put_buffer(s, &reply, 1);=0A s->state =3D gdb_h= andle_packet(s, s->line_buf);=0A }=0A break;=0A = default:=0A abort();=0A }=0A }=0A}=0A=0A#ifdef CONFI= G_USER_ONLY=0Aint gdb_queuesig (void)=0A{=0A GDBState *s;=0A=0A s =3D= gdbserver_state;=0A=0A if (gdbserver_fd < 0 || s->fd < 0)=0A ret= urn 0;=0A else=0A return 1;=0A}=0A=0A/* Tell the remote gdb that = the process has exited. */=0Avoid gdb_exit(CPUState *env, int code)=0A{=0A= GDBState *s;=0A char buf[4];=0A=0A s =3D gdbserver_state;=0A if (gdbse= rver_fd < 0 || s->fd < 0)=0A return;=0A=0A snprintf(buf, sizeof(buf), "= W%02x", code);=0A put_packet(s, buf);=0A}=0A=0Avoid gdb_signalled(CPUState= *env, int sig)=0A{=0A GDBState *s;=0A char buf[4];=0A=0A s =3D gdbserve= r_state;=0A if (gdbserver_fd < 0 || s->fd < 0)=0A return;=0A=0A snprin= tf(buf, sizeof(buf), "X%02x", target_signal_to_gdb (sig));=0A put_packet(s= , buf);=0A}=0A=0Aint gdb_handlesig (CPUState *env, int sig)=0A{=0A GDBStat= e *s;=0A char buf[256];=0A int n;=0A=0A s =3D gdbserver_state;=0A if (g= db_disconnected (s)) return sig;=0A=0A /* disable single step if it was en= abled */=0A cpu_single_step(env, 0);=0A tb_flush(env);=0A=0A if (sig != =3D 0)=0A {=0A snprintf(buf, sizeof(buf), "S%02x", target_signal_to= _gdb (sig));=0A put_packet(s, buf);=0A }=0A /* put_packet() might = have detected that the peer terminated the =0A connection. */=0A=0A i= f (gdb_disconnected (s)) return sig;=0A=0A sig =3D 0;=0A s->state =3D RS_= IDLE;=0A s->running_state =3D 0;=0A while (s->running_state =3D=3D 0) {= =0A n =3D read (s->fd, buf, 256);=0A if (n > 0)=0A {=0A = int i;=0A=0A for (i =3D 0; i < n; i++) {=0A gdb_= read_byte (s, buf[i]);=0A }=0A }=0A else if (n =3D=3D = 0 || errno !=3D EAGAIN) =0A {=0A /* XXX: Connection closed.= Should probably wait for annother=0A connection before contin= uing. */=0A return sig;=0A }=0A }=0A sig =3D s->signal;= =0A s->signal =3D 0;=0A return sig;=0A}=0A=0Astatic int get_char(GDBState= *s)=0A{=0A uint8_t ch;=0A int ret;=0A=0A for(;;) {=0A ret = =3D recv(s->fd, &ch, 1, 0);=0A if (ret < 0) {=0A if (errn= o =3D=3D ECONNRESET)=0A s->fd =3D -1;=0A if (errn= o !=3D EINTR && errno !=3D EAGAIN)=0A return -1;=0A }= else if (ret =3D=3D 0) {=0A close(s->fd);=0A s->fd = =3D -1;=0A return -1;=0A } else {=0A break;=0A= }=0A }=0A return ch;=0A}=0A=0A=0Astatic void put_buffer(GDBSt= ate *s, const uint8_t *buf, int len)=0A{=0A int ret;=0A while (len > = 0) {=0A ret =3D send(s->fd, buf, len, 0);=0A if (ret < 0) {= =0A if (errno !=3D EINTR && errno !=3D EAGAIN)=0A = return;=0A } else {=0A buf +=3D ret;=0A len -= =3D ret;=0A }=0A }=0A}=0A=0Astatic int gdb_disconnected (GDBState= *s) =0A{=0A return (gdbserver_fd < 0) || (s->fd < 0);=0A}=0A=0Astatic = GDBState *gdbserver_create_gdbstate (void)=0A{=0A GDBState *s;=0A=0A = s =3D qemu_mallocz(sizeof(GDBState));=0A s->c_cpu =3D first_cpu;=0A s= ->g_cpu =3D first_cpu;=0A gdb_has_xml =3D 0;=0A gdbserver_state =3D s= ;=0A return s;=0A}=0A=0Astatic int gdbserver_tcp_accept (void)=0A{=0A = int fd,res;=0A GDBState *s;=0A=0A for (;;) {=0A fd =3D accept= (gdbserver_fd, =0A (struct sockaddr *) NULL, (socklen_= t *) NULL);=0A if (fd < 0) {=0A if (errno !=3D EINTR) {=0A= perror("accept");=0A return -1;=0A }= =0A } else {=0A break;=0A }=0A }=0A /* set sh= ort latency */=0A res =3D 1;=0A res =3D setsockopt(fd, IPPROTO_TCP, T= CP_NODELAY, (char *)&res, sizeof (res));=0A if (res < 0) {=0A fpri= ntf (stderr, "gdbserver ERROR : set nodelay\n");=0A return -1;=0A = } =0A res =3D fcntl(fd, F_SETFL, O_NONBLOCK);=0A if (res < 0) {=0A = fprintf (stderr, "gdbserver ERROR : set nonblock\n");=0A return -= 1;=0A }=0A s =3D gdbserver_create_gdbstate ();=0A s -> fd =3D fd;= =0A return 0;=0A}=0A=0A=0Astatic int gdbserver_tcp_start (const char *ho= st, const char *port,=0A gdbstub_func faccep= t)=0A{=0A struct addrinfo info_in, *info_out;=0A struct sockaddr_in a= ddrin, *addr;=0A int res;=0A=0A memset (&info_in, 0, sizeof(struct ad= drinfo));=0A info_in.ai_flags=3DAI_PASSIVE; /* force INADDR_ANY if host= =3D=3D NULL */=0A info_in.ai_family=3D AF_INET;=0A info_in.ai_sockty= pe=3DSOCK_STREAM;=0A info_in.ai_protocol=3DIPPROTO_TCP;=0A=0A if (get= addrinfo(host, port, &info_in, &info_out) < 0) {=0A perror ("hostnam= e/portname name conversion error");=0A return -1;=0A }=0A addr= =3D (struct sockaddr_in *) info_out -> ai_addr;=0A gdbserver_fd =3D soc= ket (info_in.ai_family, info_in.ai_socktype,=0A i= nfo_in.ai_protocol);=0A if (info_in.ai_protocol < 0) {=0A perror = ("gdb socket");=0A return -1;=0A }=0A /* allow fast reuse */ = =0A res =3D 1;=0A res =3D setsockopt(gdbserver_fd, SOL_SOCKET, SO_REU= SEADDR,=0A (char *) &res, sizeof(res));=0A if (res <= 0) {=0A perror("gdb socket : set fast reuse\n");=0A return -= 1;=0A }=0A res =3D bind (gdbserver_fd, (struct sockaddr *) addr, size= of (addrin));=0A if (res <0) {=0A perror("gdb socket bind\n");=0A= return -1;=0A }=0A res =3D listen (gdbserver_fd,0);=0A if = (res <0) {=0A perror("listen\n");=0A return -1;=0A }=0A = gdbstub_accept =3D faccept;=0A return 0;=0A} =0A=0A#ifndef _WIN32= =0Astatic int gdbserver_unix_unlink (void)=0A{=0A struct sockaddr_un soc= k;=0A socklen_t len;=0A int res;=0A=0A len =3D sizeof (sock.sun_pa= th);=0A res =3D getsockname (gdbserver_fd, &sock, &len);=0A if (res <= 0 ) {=0A fprintf (stderr,"gdb accept/unlink : cannot get socket name= \n");=0A return -1;=0A }=0A res =3D unlink (sock.sun_path);=0A = if (res < 0) {=0A fprintf (stderr,"gdb accept/unlink : cannot unli= nk %s\n",sock.sun_path);=0A return -1;=0A } =0A return 0;=0A}= =0A=0Astatic int gdbserver_unix_accept (void)=0A{=0A int fd,res;=0A G= DBState *s;=0A for (;;) {=0A fd =3D accept (gdbserver_fd, =0A = (struct sockaddr *) NULL, ( socklen_t *) NULL);=0A = if (fd < 0) {=0A if (errno !=3D EINTR) {=0A perror("= accept");=0A return -1;=0A }=0A } else {=0A = break;=0A }=0A }=0A=0A res =3D fcntl(fd, F_SETFL, O_N= ONBLOCK);=0A if (res < 0) {=0A fprintf (stderr, "gdbserver ERROR := set nonblock\n");=0A return -1;=0A }=0A s =3D gdbserver_create= _gdbstate ();=0A s -> fd =3D fd;=0A return 0;=0A}=0A=0Astatic int gdb= server_unix_accept_unlink (void)=0A{=0A return (gdbserver_unix_accept ()= + gdbserver_unix_unlink ());=0A}=0A=0Astatic int gdbserver_unix_start (con= st char *filename, =0A gdbstub_func faccept= )=0A{=0A struct sockaddr_un addr;=0A int res;=0A=0A if (strlen(fil= ename) =3D=3D 0) {=0A fprintf (stderr, "gdbserver ERROR : missing uni= x socket name\n");=0A return -1;=0A }=0A=0A memset (&addr, 0, s= izeof(struct sockaddr_un));=0A addr.sun_family =3D AF_UNIX;=0A strcpy= (addr.sun_path, filename);=0A=0A gdbserver_fd =3D socket (AF_UNIX,SOCK_= STREAM,0);=0A if (gdbserver_fd < 0) {=0A perror ("gsbserver socke= t");=0A return -1;=0A }=0A res =3D bind (gdbserver_fd, (struct= sockaddr *) &addr, =0A sizeof(struct sockaddr_un));=0A i= f (res < 0) {=0A perror ("gdbserver bind\n");=0A return -1;= =0A }=0A res =3D listen (gdbserver_fd,0);=0A if (res <0) {=0A = perror("listen\n");=0A return -1;=0A }=0A gdbstub_accept = =3D faccept;=0A return 0;=0A} =0A=0A#endif /* _WIN32 */ =0A=0Avo= id gdbstub_usage (void) =0A{=0A printf("-gdb device /* use gdb> t= arget command */\n");=0A printf(" tcp:host:port target remote ho= st:port \n");=0A#ifndef _WIN32=0A printf(" unix:name target= remote | socat stdio unix:name\n");=0A printf(" unix:name,unlink := unlink remove name from filesystem after connection\n");=0A#endif /* _WIN3= 2 */=0A} =0A=0Aint gdbserver_start (const char *device)=0A{=0A const= char *p;=0A char *name, *devicename,*opt;=0A=0A name =3D malloc (str= len(device)+1);=0A /* Light memory leak : will never be freed */=0A=0A = if (strstart (device, "tcp:",&p)) {=0A if ((p =3D=3D NULL) || (str= len(p) =3D=3D 0)) {=0A perror ("tcp socket syntax error");=0A = return -1;=0A }=0A strcpy (name,p);=0A device= name =3D strrchr (name,':');=0A if (devicename =3D=3D NULL) {=0A = return -1;=0A }=0A *devicename++ =3D 0;=0A if = (*devicename =3D=3D 0) {=0A return -1;=0A }=0A if = (*name =3D=3D 0) {=0A name =3D NULL;=0A }=0A retur= n gdbserver_tcp_start (name,devicename,=0A = gdbserver_tcp_accept);=0A#ifndef _WIN32=0A } else if (strstart (devic= e, "unix:",&p)) {=0A strcpy (name,p);=0A opt =3D strrchr(name= ,',');=0A if (opt =3D=3D NULL) {=0A return gdbserver_unix_= start(name,gdbserver_unix_accept);=0A } else {=0A *opt++ = =3D 0;=0A if (!strcmp(opt,"unlink")) {=0A return gdb= server_unix_start(name,=0A gdbserv= er_unix_accept_unlink);=0A } else {=0A fprintf (stde= rr,"gdb unix socket : unknown %s option\n",opt);=0A return -1;= =0A }=0A } =0A#endif /* _WIN32 */=0A } else {=0A = return -1;=0A }=0A return 0;=0A}=0A=0A/* Tell the remote gdb that the= process has exited due to SIG. */=0A/* Disable gdb stub for child process= es. */=0Avoid gdbserver_fork(CPUState *env)=0A{=0A GDBState *s =3D gdbs= erver_state;=0A if (gdbserver_fd < 0 || s->fd < 0)=0A return;=0A = close(s->fd);=0A s->fd =3D -1;=0A cpu_breakpoint_remove_all(env, BP_= GDB);=0A cpu_watchpoint_remove_all(env, BP_GDB);=0A}=0A=0A#else /* CONFI= G_USER_ONLY */=0A=0Astatic void put_buffer(GDBState *s, const uint8_t *buf,= int len)=0A{=0A qemu_chr_write(s->chr, buf, len);=0A}=0A=0Astatic int g= db_chr_can_receive(void *opaque)=0A{=0A /* We can handle an arbitrarily la= rge amount of data.=0A Pick the maximum packet size, which is as good as = anything. */=0A return MAX_PACKET_LENGTH;=0A}=0A=0Astatic void gdb_chr_re= ceive(void *opaque, const uint8_t *buf, int size)=0A{=0A int i;=0A=0A = for (i =3D 0; i < size; i++) {=0A gdb_read_byte(gdbserver_state, bu= f[i]);=0A }=0A}=0A=0Astatic void gdb_chr_event(void *opaque, int event)= =0A{=0A switch (event) {=0A case CHR_EVENT_RESET:=0A vm_stop(E= XCP_INTERRUPT);=0A gdb_has_xml =3D 0;=0A break;=0A default= :=0A break;=0A }=0A}=0A=0Astatic void gdb_monitor_output(GDBState= *s, const char *msg, int len)=0A{=0A char buf[MAX_PACKET_LENGTH];=0A=0A= buf[0] =3D 'O';=0A if (len > (MAX_PACKET_LENGTH/2) - 1)=0A le= n =3D (MAX_PACKET_LENGTH/2) - 1;=0A memtohex(buf + 1, (uint8_t *)msg, le= n);=0A put_packet(s, buf);=0A}=0A=0Astatic int gdb_monitor_write(CharDri= verState *chr, const uint8_t *buf, int len)=0A{=0A const char *p =3D (co= nst char *)buf;=0A int max_sz;=0A=0A max_sz =3D (sizeof(gdbserver_sta= te->last_packet) - 2) / 2;=0A for (;;) {=0A if (len <=3D max_sz) = {=0A gdb_monitor_output(gdbserver_state, p, len);=0A = break;=0A }=0A gdb_monitor_output(gdbserver_state, p, max_sz)= ;=0A p +=3D max_sz;=0A len -=3D max_sz;=0A }=0A return = len;=0A}=0A=0A#ifndef _WIN32=0Astatic void gdb_sigterm_handler(int signal)= =0A{=0A if (vm_running)=0A vm_stop(EXCP_INTERRUPT);=0A}=0A#endif = /* _WIN32 */=0A=0Aint gdbserver_start(const char *device)=0A{=0A GDBStat= e *s;=0A char gdbstub_device_name[128];=0A CharDriverState *chr =3D N= ULL;=0A CharDriverState *mon_chr;=0A=0A if (!device)=0A return= -1;=0A if (strcmp(device, "none") !=3D 0) {=0A if (strstart(devi= ce, "tcp:", NULL)) {=0A /* enforce required TCP attributes */=0A= snprintf(gdbstub_device_name, sizeof(gdbstub_device_name),=0A = "%s,nowait,nodelay,server", device);=0A devic= e =3D gdbstub_device_name;=0A }=0A#ifndef _WIN32=0A else if (= strcmp(device, "stdio") =3D=3D 0) {=0A struct sigaction act;=0A= =0A memset(&act, 0, sizeof(act));=0A act.sa_handler = =3D gdb_sigterm_handler;=0A sigaction(SIGINT, &act, NULL);=0A = }=0A#endif /* _WIN32 */=0A chr =3D qemu_chr_open("gdb", device,= NULL);=0A if (!chr)=0A return -1;=0A=0A qemu_chr_= add_handlers(chr, gdb_chr_can_receive, gdb_chr_receive,=0A = gdb_chr_event, NULL);=0A }=0A=0A s =3D gdbserver_state;= =0A if (!s) {=0A s =3D qemu_mallocz(sizeof(GDBState));=0A = gdbserver_state =3D s;=0A=0A qemu_add_vm_change_state_handler(gdb_vm= _state_change, NULL);=0A=0A /* Initialize a monitor terminal for gdb= */=0A mon_chr =3D qemu_mallocz(sizeof(*mon_chr));=0A mon_chr= ->chr_write =3D gdb_monitor_write;=0A monitor_init(mon_chr, 0);=0A = } else {=0A if (s->chr)=0A qemu_chr_close(s->chr);=0A = mon_chr =3D s->mon_chr;=0A memset(s, 0, sizeof(GDBState));=0A = }=0A s->c_cpu =3D first_cpu;=0A s->g_cpu =3D first_cpu;=0A s->c= hr =3D chr;=0A s->state =3D chr ? RS_IDLE : RS_INACTIVE;=0A s->mon_ch= r =3D mon_chr;=0A=0A return 0;=0A}=0A#endif /* CONFIG_USER_ONLY */=0A=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00gdb= stub.h=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=000000644=000054742=000= 054730=0000000002356=0011171150436=00012412=00 0=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00ustar =00waille=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00equipa= r=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00#ifndef GDBSTUB_H=0A#define GDBSTUB_H=0A=0A#defi= ne DEFAULT_GDBSTUB_PORT "1234"=0A=0A/* GDB breakpoint/watchpoint types */= =0A#define GDB_BREAKPOINT_SW 0=0A#define GDB_BREAKPOINT_HW 1= =0A#define GDB_WATCHPOINT_WRITE 2=0A#define GDB_WATCHPOINT_READ 3= =0A#define GDB_WATCHPOINT_ACCESS 4=0A=0Atypedef void (*gdb_syscall_compl= ete_cb)(CPUState *env,=0A target_ulo= ng ret, target_ulong err);=0A=0Avoid gdb_do_syscall(gdb_syscall_complete_cb= cb, const char *fmt, ...);=0Aint use_gdb_syscalls(void);=0Avoid gdb_set_st= op_cpu(CPUState *env);=0A=0A#ifdef CONFIG_USER_ONLY=0Atypedef int (*gdbstub= _func) (void);=0Aextern gdbstub_func gdbstub_accept;=0A=0Aint gdb_queuesig = (void);=0Aint gdb_handlesig (CPUState *, int);=0Avoid gdb_exit(CPUState *, = int);=0Avoid gdb_signalled(CPUState *, int);=0Avoid gdbserver_fork(CPUState= *);=0Avoid gdbstub_usage (void);=0A#endif /* CONFIG_USER_ONLY */=0A=0Aint = gdbserver_start(const char *device);=0A=0A/* Get or set a register. Return= s the size of the register. */=0Atypedef int (*gdb_reg_cb)(CPUState *env, = uint8_t *buf, int reg);=0Avoid gdb_register_coprocessor(CPUState *env,=0A = gdb_reg_cb get_reg, gdb_reg_cb set_reg,=0A = int num_regs, const char *xml, int g_pos);=0A=0A#e= ndif /* GDBSTUB_H */=0A=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00linux-user/main.c=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=000000644=0000= 54742=000054730=0000000253756=0011171150541=00014023=00 0=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00ustar =00waille= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00equipar=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00/*=0A * qemu user main=0A *=0A * Copy= right (c) 2003-2008 Fabrice Bellard=0A *=0A * This program is free softwar= e; you can redistribute it and/or modify=0A * it under the terms of the GN= U General Public License as published by=0A * the Free Software Foundation= ; either version 2 of the License, or=0A * (at your option) any later vers= ion.=0A *=0A * This program is distributed in the hope that it will be use= ful,=0A * but WITHOUT ANY WARRANTY; without even the implied warranty of= =0A * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the=0A * = GNU General Public License for more details.=0A *=0A * You should have rec= eived a copy of the GNU General Public License=0A * along with this progra= m; if not, write to the Free Software=0A * Foundation, Inc., 51 Franklin S= treet - Fifth Floor, Boston,=0A * MA 02110-1301, USA.=0A */=0A#include =0A#include =0A#include =0A#include =0A= #include =0A#include =0A#include =0A=0A#incl= ude "qemu.h"=0A#include "qemu-common.h"=0A#include "cache-utils.h"=0A/* For= tb_lock */=0A#include "exec-all.h"=0A=0A=0A#include "envlist.h"=0A=0A#defi= ne DEBUG_LOGFILE "/tmp/qemu.log"=0A=0Achar *exec_path;=0A=0Aint singlestep;= =0A=0Astatic const char *interp_prefix =3D CONFIG_QEMU_PREFIX;=0Aconst char= *qemu_uname_release =3D CONFIG_UNAME_RELEASE;=0A=0A#if defined(__i386__) &= & !defined(CONFIG_STATIC)=0A/* Force usage of an ELF interpreter even if it= is an ELF shared=0A object ! */=0Aconst char interp[] __attribute__((sec= tion(".interp"))) =3D "/lib/ld-linux.so.2";=0A#endif=0A=0A/* for recent lib= c, we add these dummy symbols which are not declared=0A when generating a= linked object (bug in ld ?) */=0A#if (__GLIBC__ > 2 || (__GLIBC__ =3D=3D 2= && __GLIBC_MINOR__ >=3D 3)) && !defined(CONFIG_STATIC)=0Aasm(".globl __pre= init_array_start\n"=0A ".globl __preinit_array_end\n"=0A ".globl __in= it_array_start\n"=0A ".globl __init_array_end\n"=0A ".globl __fini_ar= ray_start\n"=0A ".globl __fini_array_end\n"=0A ".section \".rodata\"\= n"=0A "__preinit_array_start:\n"=0A "__preinit_array_end:\n"=0A "_= _init_array_start:\n"=0A "__init_array_end:\n"=0A "__fini_array_start= :\n"=0A "__fini_array_end:\n"=0A ".long 0\n"=0A ".previous\n");=0A= #endif=0A=0A/* XXX: on x86 MAP_GROWSDOWN only works if ESP <=3D address + 3= 2, so=0A we allocate a bigger stack. Need a better solution, for example= =0A by remapping the process stack directly at the right place */=0Aunsig= ned long x86_stack_size =3D 512 * 1024;=0A=0Avoid gemu_log(const char *fmt,= ...)=0A{=0A va_list ap;=0A=0A va_start(ap, fmt);=0A vfprintf(stde= rr, fmt, ap);=0A va_end(ap);=0A}=0A=0Avoid cpu_outb(CPUState *env, int a= ddr, int val)=0A{=0A fprintf(stderr, "outb: port=3D0x%04x, data=3D%02x\n= ", addr, val);=0A}=0A=0Avoid cpu_outw(CPUState *env, int addr, int val)=0A{= =0A fprintf(stderr, "outw: port=3D0x%04x, data=3D%04x\n", addr, val);=0A= }=0A=0Avoid cpu_outl(CPUState *env, int addr, int val)=0A{=0A fprintf(st= derr, "outl: port=3D0x%04x, data=3D%08x\n", addr, val);=0A}=0A=0Aint cpu_in= b(CPUState *env, int addr)=0A{=0A fprintf(stderr, "inb: port=3D0x%04x\n"= , addr);=0A return 0;=0A}=0A=0Aint cpu_inw(CPUState *env, int addr)=0A{= =0A fprintf(stderr, "inw: port=3D0x%04x\n", addr);=0A return 0;=0A}= =0A=0Aint cpu_inl(CPUState *env, int addr)=0A{=0A fprintf(stderr, "inl: = port=3D0x%04x\n", addr);=0A return 0;=0A}=0A=0A#if defined(TARGET_I386)= =0Aint cpu_get_pic_interrupt(CPUState *env)=0A{=0A return -1;=0A}=0A#end= if=0A=0A/* timers for rdtsc */=0A=0A#if 0=0A=0Astatic uint64_t emu_time;=0A= =0Aint64_t cpu_get_real_ticks(void)=0A{=0A return emu_time++;=0A}=0A=0A#= endif=0A=0A#if defined(USE_NPTL)=0A/***************************************= ********************/=0A/* Helper routines for implementing atomic operatio= ns. */=0A=0A/* To implement exclusive operations we force all cpus to sync= ronise.=0A We don't require a full sync, only that no cpus are executing = guest code.=0A The alternative is to map target atomic ops onto host equi= valents,=0A which requires quite a lot of per host/target work. */=0Asta= tic pthread_mutex_t cpu_list_mutex =3D PTHREAD_MUTEX_INITIALIZER;=0Astatic = pthread_mutex_t exclusive_lock =3D PTHREAD_MUTEX_INITIALIZER;=0Astatic pthr= ead_cond_t exclusive_cond =3D PTHREAD_COND_INITIALIZER;=0Astatic pthread_co= nd_t exclusive_resume =3D PTHREAD_COND_INITIALIZER;=0Astatic int pending_cp= us;=0A=0A/* Make sure everything is in a consistent state for calling fork(= ). */=0Avoid fork_start(void)=0A{=0A mmap_fork_start();=0A pthread_m= utex_lock(&tb_lock);=0A pthread_mutex_lock(&exclusive_lock);=0A}=0A=0Avo= id fork_end(int child)=0A{=0A if (child) {=0A /* Child processes = created by fork() only have a single thread.=0A Discard informati= on about the parent threads. */=0A first_cpu =3D thread_env;=0A = thread_env->next_cpu =3D NULL;=0A pending_cpus =3D 0;=0A = pthread_mutex_init(&exclusive_lock, NULL);=0A pthread_mutex_init(&cp= u_list_mutex, NULL);=0A pthread_cond_init(&exclusive_cond, NULL);=0A= pthread_cond_init(&exclusive_resume, NULL);=0A pthread_mutex= _init(&tb_lock, NULL);=0A gdbserver_fork(thread_env);=0A } else {= =0A pthread_mutex_unlock(&exclusive_lock);=0A pthread_mutex_u= nlock(&tb_lock);=0A }=0A mmap_fork_end(child);=0A}=0A=0A/* Wait for p= ending exclusive operations to complete. The exclusive lock=0A must be h= eld. */=0Astatic inline void exclusive_idle(void)=0A{=0A while (pending= _cpus) {=0A pthread_cond_wait(&exclusive_resume, &exclusive_lock);= =0A }=0A}=0A=0A/* Start an exclusive operation.=0A Must only be called= from outside cpu_arm_exec. */=0Astatic inline void start_exclusive(void)= =0A{=0A CPUState *other;=0A pthread_mutex_lock(&exclusive_lock);=0A = exclusive_idle();=0A=0A pending_cpus =3D 1;=0A /* Make all other cp= us stop executing. */=0A for (other =3D first_cpu; other; other =3D oth= er->next_cpu) {=0A if (other->running) {=0A pending_cpus+= +;=0A cpu_exit(other);=0A }=0A }=0A if (pending_cpu= s > 1) {=0A pthread_cond_wait(&exclusive_cond, &exclusive_lock);=0A = }=0A}=0A=0A/* Finish an exclusive operation. */=0Astatic inline void en= d_exclusive(void)=0A{=0A pending_cpus =3D 0;=0A pthread_cond_broadcas= t(&exclusive_resume);=0A pthread_mutex_unlock(&exclusive_lock);=0A}=0A= =0A/* Wait for exclusive ops to finish, and begin cpu execution. */=0Astat= ic inline void cpu_exec_start(CPUState *env)=0A{=0A pthread_mutex_lock(&= exclusive_lock);=0A exclusive_idle();=0A env->running =3D 1;=0A pt= hread_mutex_unlock(&exclusive_lock);=0A}=0A=0A/* Mark cpu as not executing,= and release pending exclusive ops. */=0Astatic inline void cpu_exec_end(C= PUState *env)=0A{=0A pthread_mutex_lock(&exclusive_lock);=0A env->run= ning =3D 0;=0A if (pending_cpus > 1) {=0A pending_cpus--;=0A = if (pending_cpus =3D=3D 1) {=0A pthread_cond_signal(&exclusiv= e_cond);=0A }=0A }=0A exclusive_idle();=0A pthread_mutex_un= lock(&exclusive_lock);=0A}=0A=0Avoid cpu_list_lock(void)=0A{=0A pthread_= mutex_lock(&cpu_list_mutex);=0A}=0A=0Avoid cpu_list_unlock(void)=0A{=0A = pthread_mutex_unlock(&cpu_list_mutex);=0A}=0A#else /* if !USE_NPTL */=0A/* = These are no-ops because we are not threadsafe. */=0Astatic inline void cp= u_exec_start(CPUState *env)=0A{=0A}=0A=0Astatic inline void cpu_exec_end(CP= UState *env)=0A{=0A}=0A=0Astatic inline void start_exclusive(void)=0A{=0A}= =0A=0Astatic inline void end_exclusive(void)=0A{=0A}=0A=0Avoid fork_start(v= oid)=0A{=0A}=0A=0Avoid fork_end(int child)=0A{=0A if (child) {=0A = gdbserver_fork(thread_env);=0A }=0A}=0A=0Avoid cpu_list_lock(void)=0A{= =0A}=0A=0Avoid cpu_list_unlock(void)=0A{=0A}=0A#endif=0A=0A=0A#ifdef TARGET= _I386=0A/***********************************************************/=0A/* = CPUX86 core interface */=0A=0Avoid cpu_smm_update(CPUState *env)=0A{=0A}=0A= =0Auint64_t cpu_get_tsc(CPUX86State *env)=0A{=0A return cpu_get_real_tic= ks();=0A}=0A=0Astatic void write_dt(void *ptr, unsigned long addr, unsigned= long limit,=0A int flags)=0A{=0A unsigned int e1, e= 2;=0A uint32_t *p;=0A e1 =3D (addr << 16) | (limit & 0xffff);=0A e= 2 =3D ((addr >> 16) & 0xff) | (addr & 0xff000000) | (limit & 0x000f0000);= =0A e2 |=3D flags;=0A p =3D ptr;=0A p[0] =3D tswap32(e1);=0A p[= 1] =3D tswap32(e2);=0A}=0A=0Astatic uint64_t *idt_table;=0A#ifdef TARGET_X8= 6_64=0Astatic void set_gate64(void *ptr, unsigned int type, unsigned int dp= l,=0A uint64_t addr, unsigned int sel)=0A{=0A uint= 32_t *p, e1, e2;=0A e1 =3D (addr & 0xffff) | (sel << 16);=0A e2 =3D (= addr & 0xffff0000) | 0x8000 | (dpl << 13) | (type << 8);=0A p =3D ptr;= =0A p[0] =3D tswap32(e1);=0A p[1] =3D tswap32(e2);=0A p[2] =3D tsw= ap32(addr >> 32);=0A p[3] =3D 0;=0A}=0A/* only dpl matters as we do only= user space emulation */=0Astatic void set_idt(int n, unsigned int dpl)=0A{= =0A set_gate64(idt_table + n * 2, 0, dpl, 0, 0);=0A}=0A#else=0Astatic vo= id set_gate(void *ptr, unsigned int type, unsigned int dpl,=0A = uint32_t addr, unsigned int sel)=0A{=0A uint32_t *p, e1, e2;=0A = e1 =3D (addr & 0xffff) | (sel << 16);=0A e2 =3D (addr & 0xffff0000) |= 0x8000 | (dpl << 13) | (type << 8);=0A p =3D ptr;=0A p[0] =3D tswap3= 2(e1);=0A p[1] =3D tswap32(e2);=0A}=0A=0A/* only dpl matters as we do on= ly user space emulation */=0Astatic void set_idt(int n, unsigned int dpl)= =0A{=0A set_gate(idt_table + n, 0, dpl, 0, 0);=0A}=0A#endif=0A=0Avoid cp= u_loop(CPUX86State *env)=0A{=0A int trapnr;=0A abi_ulong pc;=0A ta= rget_siginfo_t info;=0A=0A for(;;) {=0A trapnr =3D cpu_x86_exec(e= nv);=0A switch(trapnr) {=0A case 0x80:=0A /* linux= syscall from int $0x80 */=0A env->regs[R_EAX] =3D do_syscall(en= v,=0A env->regs[R_EAX],=0A = env->regs[R_EBX],=0A = env->regs[R_ECX],=0A = env->regs[R_EDX],=0A env->= regs[R_ESI],=0A env->regs[R_EDI],= =0A env->regs[R_EBP]);=0A = break;=0A#ifndef TARGET_ABI32=0A case EXCP_SYSCALL:=0A = /* linux syscall from syscall intruction */=0A env->regs[R_EAX]= =3D do_syscall(env,=0A env->regs[= R_EAX],=0A env->regs[R_EDI],=0A = env->regs[R_ESI],=0A = env->regs[R_EDX],=0A = env->regs[10],=0A env= ->regs[8],=0A env->regs[9]);=0A = env->eip =3D env->exception_next_eip;=0A break;=0A#endi= f=0A case EXCP0B_NOSEG:=0A case EXCP0C_STACK:=0A i= nfo.si_signo =3D SIGBUS;=0A info.si_errno =3D 0;=0A i= nfo.si_code =3D TARGET_SI_KERNEL;=0A info._sifields._sigfault._a= ddr =3D 0;=0A queue_signal(env, info.si_signo, &info);=0A = break;=0A case EXCP0D_GPF:=0A /* XXX: potential prob= lem if ABI32 */=0A#ifndef TARGET_X86_64=0A if (env->eflags & VM_= MASK) {=0A handle_vm86_fault(env);=0A } else=0A#e= ndif=0A {=0A info.si_signo =3D SIGSEGV;=0A = info.si_errno =3D 0;=0A info.si_code =3D TARGET_SI_= KERNEL;=0A info._sifields._sigfault._addr =3D 0;=0A = queue_signal(env, info.si_signo, &info);=0A }=0A = break;=0A case EXCP0E_PAGE:=0A info.si_signo =3D SIGSE= GV;=0A info.si_errno =3D 0;=0A if (!(env->error_code = & 1))=0A info.si_code =3D TARGET_SEGV_MAPERR;=0A = else=0A info.si_code =3D TARGET_SEGV_ACCERR;=0A i= nfo._sifields._sigfault._addr =3D env->cr[2];=0A queue_signal(en= v, info.si_signo, &info);=0A break;=0A case EXCP00_DIVZ:= =0A#ifndef TARGET_X86_64=0A if (env->eflags & VM_MASK) {=0A = handle_vm86_trap(env, trapnr);=0A } else=0A#endif=0A = {=0A /* division by zero */=0A inf= o.si_signo =3D SIGFPE;=0A info.si_errno =3D 0;=0A = info.si_code =3D TARGET_FPE_INTDIV;=0A info._sifields._= sigfault._addr =3D env->eip;=0A queue_signal(env, info.si_si= gno, &info);=0A }=0A break;=0A case EXCP01_DB:= =0A case EXCP03_INT3:=0A#ifndef TARGET_X86_64=0A if (env-= >eflags & VM_MASK) {=0A handle_vm86_trap(env, trapnr);=0A = } else=0A#endif=0A {=0A info.si_signo = =3D SIGTRAP;=0A info.si_errno =3D 0;=0A if (t= rapnr =3D=3D EXCP01_DB) {=0A info.si_code =3D TARGET_TRA= P_BRKPT;=0A info._sifields._sigfault._addr =3D env->eip;= =0A } else {=0A info.si_code =3D TARGET_S= I_KERNEL;=0A info._sifields._sigfault._addr =3D 0;=0A = }=0A queue_signal(env, info.si_signo, &info);= =0A }=0A break;=0A case EXCP04_INTO:=0A = case EXCP05_BOUND:=0A#ifndef TARGET_X86_64=0A if (env->eflags &= VM_MASK) {=0A handle_vm86_trap(env, trapnr);=0A = } else=0A#endif=0A {=0A info.si_signo =3D SIGSEGV= ;=0A info.si_errno =3D 0;=0A info.si_code =3D= TARGET_SI_KERNEL;=0A info._sifields._sigfault._addr =3D 0;= =0A queue_signal(env, info.si_signo, &info);=0A }= =0A break;=0A case EXCP06_ILLOP:=0A info.si_si= gno =3D SIGILL;=0A info.si_errno =3D 0;=0A info.si_co= de =3D TARGET_ILL_ILLOPN;=0A info._sifields._sigfault._addr =3D = env->eip;=0A queue_signal(env, info.si_signo, &info);=0A = break;=0A case EXCP_INTERRUPT:=0A /* just indicate th= at signals should be handled asap */=0A break;=0A case EX= CP_DEBUG:=0A {=0A int sig;=0A=0A s= ig =3D gdb_handlesig (env, TARGET_SIGTRAP);=0A if (sig)=0A = {=0A info.si_signo =3D sig;=0A = info.si_errno =3D 0;=0A info.si_code =3D TARGE= T_TRAP_BRKPT;=0A queue_signal(env, info.si_signo, &info)= ;=0A }=0A }=0A break;=0A defa= ult:=0A pc =3D env->segs[R_CS].base + env->eip;=0A fp= rintf(stderr, "qemu: 0x%08lx: unhandled CPU exception 0x%x - aborting\n",= =0A (long)pc, trapnr);=0A abort();=0A = }=0A process_pending_signals(env);=0A }=0A}=0A#endif=0A=0A#ifdef = TARGET_ARM=0A=0Astatic void arm_cache_flush(abi_ulong start, abi_ulong last= )=0A{=0A abi_ulong addr, last1;=0A=0A if (last < start)=0A ret= urn;=0A addr =3D start;=0A for(;;) {=0A last1 =3D ((addr + TAR= GET_PAGE_SIZE) & TARGET_PAGE_MASK) - 1;=0A if (last1 > last)=0A = last1 =3D last;=0A tb_invalidate_page_range(addr, last1 + 1);= =0A if (last1 =3D=3D last)=0A break;=0A addr =3D l= ast1 + 1;=0A }=0A}=0A=0A/* Handle a jump to the kernel code page. */=0A= static int=0Ado_kernel_trap(CPUARMState *env)=0A{=0A uint32_t addr;=0A = uint32_t cpsr;=0A uint32_t val;=0A=0A switch (env->regs[15]) {=0A = case 0xffff0fa0: /* __kernel_memory_barrier */=0A /* ??? No-op. Wi= ll need to do better for SMP. */=0A break;=0A case 0xffff0fc0: /= * __kernel_cmpxchg */=0A /* XXX: This only works between threads, n= ot between processes.=0A It's probably possible to implement thi= s with native host=0A operations. However things like ldrex/stre= x are much harder so=0A there's not much point trying. */=0A = start_exclusive();=0A cpsr =3D cpsr_read(env);=0A addr = =3D env->regs[2];=0A /* FIXME: This should SEGV if the access fails.= */=0A if (get_user_u32(val, addr))=0A val =3D ~env->reg= s[0];=0A if (val =3D=3D env->regs[0]) {=0A val =3D env->r= egs[1];=0A /* FIXME: Check for segfaults. */=0A put_= user_u32(val, addr);=0A env->regs[0] =3D 0;=0A cpsr |= =3D CPSR_C;=0A } else {=0A env->regs[0] =3D -1;=0A = cpsr &=3D ~CPSR_C;=0A }=0A cpsr_write(env, cpsr, CPSR_C)= ;=0A end_exclusive();=0A break;=0A case 0xffff0fe0: /* __k= ernel_get_tls */=0A env->regs[0] =3D env->cp15.c13_tls2;=0A b= reak;=0A default:=0A return 1;=0A }=0A /* Jump back to the = caller. */=0A addr =3D env->regs[14];=0A if (addr & 1) {=0A e= nv->thumb =3D 1;=0A addr &=3D ~1;=0A }=0A env->regs[15] =3D ad= dr;=0A=0A return 0;=0A}=0A=0Avoid cpu_loop(CPUARMState *env)=0A{=0A i= nt trapnr;=0A unsigned int n, insn;=0A target_siginfo_t info;=0A u= int32_t addr;=0A=0A for(;;) {=0A cpu_exec_start(env);=0A t= rapnr =3D cpu_arm_exec(env);=0A cpu_exec_end(env);=0A switch(= trapnr) {=0A case EXCP_UDEF:=0A {=0A TaskS= tate *ts =3D env->opaque;=0A uint32_t opcode;=0A = int rc;=0A=0A /* we handle the FPU emulation here, as Li= nux */=0A /* we get the opcode */=0A /* FIXME= - what to do if get_user() fails? */=0A get_user_u32(opcode= , env->regs[15]);=0A=0A rc =3D EmulateAll(opcode, &ts->fpa, = env);=0A if (rc =3D=3D 0) { /* illegal instruction */=0A = info.si_signo =3D SIGILL;=0A info.si_err= no =3D 0;=0A info.si_code =3D TARGET_ILL_ILLOPN;=0A = info._sifields._sigfault._addr =3D env->regs[15];=0A = queue_signal(env, info.si_signo, &info);=0A } el= se if (rc < 0) { /* FP exception */=0A int arm_fpe=3D0;= =0A=0A /* translate softfloat flags to FPSR flags */=0A = if (-rc & float_flag_invalid)=0A ar= m_fpe |=3D BIT_IOC;=0A if (-rc & float_flag_divbyzero)= =0A arm_fpe |=3D BIT_DZC;=0A if (-r= c & float_flag_overflow)=0A arm_fpe |=3D BIT_OFC;=0A = if (-rc & float_flag_underflow)=0A a= rm_fpe |=3D BIT_UFC;=0A if (-rc & float_flag_inexact)=0A= arm_fpe |=3D BIT_IXC;=0A=0A FPSR f= psr =3D ts->fpa.fpsr;=0A //printf("fpsr 0x%x, arm_fpe 0x= %x\n",fpsr,arm_fpe);=0A=0A if (fpsr & (arm_fpe << 16)) {= /* exception enabled? */=0A info.si_signo =3D SIGFPE;= =0A info.si_errno =3D 0;=0A=0A /*= ordered by priority, least first */=0A if (arm_fpe & = BIT_IXC) info.si_code =3D TARGET_FPE_FLTRES;=0A if (ar= m_fpe & BIT_UFC) info.si_code =3D TARGET_FPE_FLTUND;=0A = if (arm_fpe & BIT_OFC) info.si_code =3D TARGET_FPE_FLTOVF;=0A = if (arm_fpe & BIT_DZC) info.si_code =3D TARGET_FPE_FLTDIV;=0A = if (arm_fpe & BIT_IOC) info.si_code =3D TARGET_FPE_FLTINV= ;=0A=0A info._sifields._sigfault._addr =3D env->regs[1= 5];=0A queue_signal(env, info.si_signo, &info);=0A = } else {=0A env->regs[15] +=3D 4;=0A = }=0A=0A /* accumulate unenabled except= ions */=0A if ((!(fpsr & BIT_IXE)) && (arm_fpe & BIT_IXC= ))=0A fpsr |=3D BIT_IXC;=0A if ((!(= fpsr & BIT_UFE)) && (arm_fpe & BIT_UFC))=0A fpsr |=3D = BIT_UFC;=0A if ((!(fpsr & BIT_OFE)) && (arm_fpe & BIT_OF= C))=0A fpsr |=3D BIT_OFC;=0A if ((!= (fpsr & BIT_DZE)) && (arm_fpe & BIT_DZC))=0A fpsr |=3D= BIT_DZC;=0A if ((!(fpsr & BIT_IOE)) && (arm_fpe & BIT_I= OC))=0A fpsr |=3D BIT_IOC;=0A ts->f= pa.fpsr=3Dfpsr;=0A } else { /* everything OK */=0A = /* increment PC */=0A env->regs[15] +=3D 4;=0A= }=0A }=0A break;=0A case EXCP_= SWI:=0A case EXCP_BKPT:=0A {=0A env->eabi = =3D 1;=0A /* system call */=0A if (trapnr =3D= =3D EXCP_BKPT) {=0A if (env->thumb) {=0A = /* FIXME - what to do if get_user() fails? */=0A = get_user_u16(insn, env->regs[15]);=0A n =3D ins= n & 0xff;=0A env->regs[15] +=3D 2;=0A = } else {=0A /* FIXME - what to do if get_user()= fails? */=0A get_user_u32(insn, env->regs[15]);=0A = n =3D (insn & 0xf) | ((insn >> 4) & 0xff0);=0A = env->regs[15] +=3D 4;=0A }=0A = } else {=0A if (env->thumb) {=0A = /* FIXME - what to do if get_user() fails? */=0A = get_user_u16(insn, env->regs[15] - 2);=0A n =3D = insn & 0xff;=0A } else {=0A /* FI= XME - what to do if get_user() fails? */=0A get_user= _u32(insn, env->regs[15] - 4);=0A n =3D insn & 0xfff= fff;=0A }=0A }=0A=0A if (n= =3D=3D ARM_NR_cacheflush) {=0A arm_cache_flush(env->reg= s[0], env->regs[1]);=0A } else if (n =3D=3D ARM_NR_semihosti= ng=0A || n =3D=3D ARM_NR_thumb_semihosting) {=0A = env->regs[0] =3D do_arm_semihosting (env);=0A = } else if (n =3D=3D 0 || n >=3D ARM_SYSCALL_BASE=0A = || (env->thumb && n =3D=3D ARM_THUMB_SYSCALL)) {=0A = /* linux syscall */=0A if (env->thumb || n =3D=3D 0)= {=0A n =3D env->regs[7];=0A } el= se {=0A n -=3D ARM_SYSCALL_BASE;=0A = env->eabi =3D 0;=0A }=0A if ( = n > ARM_NR_BASE) {=0A switch (n) {=0A = case ARM_NR_cacheflush:=0A arm_cache_fl= ush(env->regs[0], env->regs[1]);=0A break;=0A = case ARM_NR_set_tls:=0A cpu= _set_tls(env, env->regs[0]);=0A env->regs[0] =3D= 0;=0A break;=0A default:= =0A gemu_log("qemu: Unsupported ARM syscall: 0x%= x\n",=0A n);=0A = env->regs[0] =3D -TARGET_ENOSYS;=0A break;= =0A }=0A } else {=0A = env->regs[0] =3D do_syscall(env,=0A = n,=0A = env->regs[0],=0A env->reg= s[1],=0A env->regs[2],=0A = env->regs[3],=0A = env->regs[4],=0A = env->regs[5]);=0A }=0A = } else {=0A goto error;=0A }= =0A }=0A break;=0A case EXCP_INTERRUPT:=0A = /* just indicate that signals should be handled asap */=0A = break;=0A case EXCP_PREFETCH_ABORT:=0A addr =3D env->c= p15.c6_insn;=0A goto do_segv;=0A case EXCP_DATA_ABORT:=0A= addr =3D env->cp15.c6_data;=0A goto do_segv;=0A = do_segv:=0A {=0A info.si_signo =3D SIGSEGV;=0A= info.si_errno =3D 0;=0A /* XXX: check env->e= rror_code */=0A info.si_code =3D TARGET_SEGV_MAPERR;=0A = info._sifields._sigfault._addr =3D addr;=0A queue= _signal(env, info.si_signo, &info);=0A }=0A break;=0A= case EXCP_DEBUG:=0A {=0A int sig;=0A=0A = sig =3D gdb_handlesig (env, TARGET_SIGTRAP);=0A = if (sig)=0A {=0A info.si_signo =3D si= g;=0A info.si_errno =3D 0;=0A info.si= _code =3D TARGET_TRAP_BRKPT;=0A queue_signal(env, info.s= i_signo, &info);=0A }=0A }=0A break;= =0A case EXCP_KERNEL_TRAP:=0A if (do_kernel_trap(env))=0A= goto error;=0A break;=0A default:=0A = error:=0A fprintf(stderr, "qemu: unhandled CPU exception 0x%x -= aborting\n",=0A trapnr);=0A cpu_dump_state(e= nv, stderr, fprintf, 0);=0A abort();=0A }=0A proce= ss_pending_signals(env);=0A }=0A}=0A=0A#endif=0A=0A#ifdef TARGET_SPARC= =0A#define SPARC64_STACK_BIAS 2047=0A=0A//#define DEBUG_WIN=0A=0A/* WARNING= : dealing with register windows _is_ complicated. More info=0A can be fou= nd at http://www.sics.se/~psm/sparcstack.html */=0Astatic inline int get_re= g_index(CPUSPARCState *env, int cwp, int index)=0A{=0A index =3D (index = + cwp * 16) % (16 * env->nwindows);=0A /* wrap handling : if cwp is on t= he last window, then we use the=0A registers 'after' the end */=0A = if (index < 8 && env->cwp =3D=3D env->nwindows - 1)=0A index +=3D 1= 6 * env->nwindows;=0A return index;=0A}=0A=0A/* save the register window= 'cwp1' */=0Astatic inline void save_window_offset(CPUSPARCState *env, int = cwp1)=0A{=0A unsigned int i;=0A abi_ulong sp_ptr;=0A=0A sp_ptr =3D= env->regbase[get_reg_index(env, cwp1, 6)];=0A#ifdef TARGET_SPARC64=0A i= f (sp_ptr & 3)=0A sp_ptr +=3D SPARC64_STACK_BIAS;=0A#endif=0A#if def= ined(DEBUG_WIN)=0A printf("win_overflow: sp_ptr=3D0x" TARGET_ABI_FMT_lx = " save_cwp=3D%d\n",=0A sp_ptr, cwp1);=0A#endif=0A for(i =3D 0;= i < 16; i++) {=0A /* FIXME - what to do if put_user() fails? */=0A = put_user_ual(env->regbase[get_reg_index(env, cwp1, 8 + i)], sp_ptr);= =0A sp_ptr +=3D sizeof(abi_ulong);=0A }=0A}=0A=0Astatic void save= _window(CPUSPARCState *env)=0A{=0A#ifndef TARGET_SPARC64=0A unsigned int= new_wim;=0A new_wim =3D ((env->wim >> 1) | (env->wim << (env->nwindows = - 1))) &=0A ((1LL << env->nwindows) - 1);=0A save_window_offset(e= nv, cpu_cwp_dec(env, env->cwp - 2));=0A env->wim =3D new_wim;=0A#else=0A= save_window_offset(env, cpu_cwp_dec(env, env->cwp - 2));=0A env->can= save++;=0A env->canrestore--;=0A#endif=0A}=0A=0Astatic void restore_wind= ow(CPUSPARCState *env)=0A{=0A#ifndef TARGET_SPARC64=0A unsigned int new_= wim;=0A#endif=0A unsigned int i, cwp1;=0A abi_ulong sp_ptr;=0A=0A#ifn= def TARGET_SPARC64=0A new_wim =3D ((env->wim << 1) | (env->wim >> (env->= nwindows - 1))) &=0A ((1LL << env->nwindows) - 1);=0A#endif=0A=0A = /* restore the invalid window */=0A cwp1 =3D cpu_cwp_inc(env, env->cwp = + 1);=0A sp_ptr =3D env->regbase[get_reg_index(env, cwp1, 6)];=0A#ifdef = TARGET_SPARC64=0A if (sp_ptr & 3)=0A sp_ptr +=3D SPARC64_STACK_BI= AS;=0A#endif=0A#if defined(DEBUG_WIN)=0A printf("win_underflow: sp_ptr= =3D0x" TARGET_ABI_FMT_lx " load_cwp=3D%d\n",=0A sp_ptr, cwp1);=0A= #endif=0A for(i =3D 0; i < 16; i++) {=0A /* FIXME - what to do if= get_user() fails? */=0A get_user_ual(env->regbase[get_reg_index(env= , cwp1, 8 + i)], sp_ptr);=0A sp_ptr +=3D sizeof(abi_ulong);=0A }= =0A#ifdef TARGET_SPARC64=0A env->canrestore++;=0A if (env->cleanwin <= env->nwindows - 1)=0A env->cleanwin++;=0A env->cansave--;=0A#els= e=0A env->wim =3D new_wim;=0A#endif=0A}=0A=0Astatic void flush_windows(C= PUSPARCState *env)=0A{=0A int offset, cwp1;=0A=0A offset =3D 1;=0A = for(;;) {=0A /* if restore would invoke restore_window(), then we c= an stop */=0A cwp1 =3D cpu_cwp_inc(env, env->cwp + offset);=0A#ifnde= f TARGET_SPARC64=0A if (env->wim & (1 << cwp1))=0A break;= =0A#else=0A if (env->canrestore =3D=3D 0)=0A break;=0A = env->cansave++;=0A env->canrestore--;=0A#endif=0A save_w= indow_offset(env, cwp1);=0A offset++;=0A }=0A cwp1 =3D cpu_cwp= _inc(env, env->cwp + 1);=0A#ifndef TARGET_SPARC64=0A /* set wim so that = restore will reload the registers */=0A env->wim =3D 1 << cwp1;=0A#endif= =0A#if defined(DEBUG_WIN)=0A printf("flush_windows: nb=3D%d\n", offset -= 1);=0A#endif=0A}=0A=0Avoid cpu_loop (CPUSPARCState *env)=0A{=0A int tra= pnr, ret;=0A target_siginfo_t info;=0A=0A while (1) {=0A trapn= r =3D cpu_sparc_exec (env);=0A=0A switch (trapnr) {=0A#ifndef TARGET= _SPARC64=0A case 0x88:=0A case 0x90:=0A#else=0A case 0= x110:=0A case 0x16d:=0A#endif=0A ret =3D do_syscall (env,= env->gregs[1],=0A env->regwptr[0], env->regwp= tr[1],=0A env->regwptr[2], env->regwptr[3],=0A= env->regwptr[4], env->regwptr[5]);=0A = if ((unsigned int)ret >=3D (unsigned int)(-515)) {=0A#if defined(TARGET= _SPARC64) && !defined(TARGET_ABI32)=0A env->xcc |=3D PSR_CAR= RY;=0A#else=0A env->psr |=3D PSR_CARRY;=0A#endif=0A = ret =3D -ret;=0A } else {=0A#if defined(TARGET_SPARC64) &= & !defined(TARGET_ABI32)=0A env->xcc &=3D ~PSR_CARRY;=0A#els= e=0A env->psr &=3D ~PSR_CARRY;=0A#endif=0A }=0A = env->regwptr[0] =3D ret;=0A /* next instruction */=0A = env->pc =3D env->npc;=0A env->npc =3D env->npc + 4;= =0A break;=0A case 0x83: /* flush windows */=0A#ifdef TAR= GET_ABI32=0A case 0x103:=0A#endif=0A flush_windows(env);= =0A /* next instruction */=0A env->pc =3D env->npc;= =0A env->npc =3D env->npc + 4;=0A break;=0A#ifndef TA= RGET_SPARC64=0A case TT_WIN_OVF: /* window overflow */=0A = save_window(env);=0A break;=0A case TT_WIN_UNF: /* windo= w underflow */=0A restore_window(env);=0A break;=0A = case TT_TFAULT:=0A case TT_DFAULT:=0A {=0A = info.si_signo =3D SIGSEGV;=0A info.si_errno =3D 0;=0A= /* XXX: check env->error_code */=0A info.si_= code =3D TARGET_SEGV_MAPERR;=0A info._sifields._sigfault._ad= dr =3D env->mmuregs[4];=0A queue_signal(env, info.si_signo, = &info);=0A }=0A break;=0A#else=0A case TT_SPIL= L: /* window overflow */=0A save_window(env);=0A brea= k;=0A case TT_FILL: /* window underflow */=0A restore_win= dow(env);=0A break;=0A case TT_TFAULT:=0A case TT_= DFAULT:=0A {=0A info.si_signo =3D SIGSEGV;=0A = info.si_errno =3D 0;=0A /* XXX: check env->error= _code */=0A info.si_code =3D TARGET_SEGV_MAPERR;=0A = if (trapnr =3D=3D TT_DFAULT)=0A info._sifields._s= igfault._addr =3D env->dmmuregs[4];=0A else=0A = info._sifields._sigfault._addr =3D env->tsptr->tpc;=0A = queue_signal(env, info.si_signo, &info);=0A }=0A bre= ak;=0A#ifndef TARGET_ABI32=0A case 0x16e:=0A flush_window= s(env);=0A sparc64_get_context(env);=0A break;=0A = case 0x16f:=0A flush_windows(env);=0A sparc64_set= _context(env);=0A break;=0A#endif=0A#endif=0A case EXCP_I= NTERRUPT:=0A /* just indicate that signals should be handled asa= p */=0A break;=0A case EXCP_DEBUG:=0A {=0A = int sig;=0A=0A sig =3D gdb_handlesig (env, TARGE= T_SIGTRAP);=0A if (sig)=0A {=0A = info.si_signo =3D sig;=0A info.si_errno =3D 0;= =0A info.si_code =3D TARGET_TRAP_BRKPT;=0A = queue_signal(env, info.si_signo, &info);=0A }=0A = }=0A break;=0A default:=0A printf ("Un= handled trap: 0x%x\n", trapnr);=0A cpu_dump_state(env, stderr, f= printf, 0);=0A exit (1);=0A }=0A process_pending_s= ignals (env);=0A }=0A}=0A=0A#endif=0A=0A#ifdef TARGET_PPC=0Astatic inlin= e uint64_t cpu_ppc_get_tb (CPUState *env)=0A{=0A /* TO FIX */=0A retu= rn 0;=0A}=0A=0Auint32_t cpu_ppc_load_tbl (CPUState *env)=0A{=0A return c= pu_ppc_get_tb(env) & 0xFFFFFFFF;=0A}=0A=0Auint32_t cpu_ppc_load_tbu (CPUSta= te *env)=0A{=0A return cpu_ppc_get_tb(env) >> 32;=0A}=0A=0Auint32_t cpu_= ppc_load_atbl (CPUState *env)=0A{=0A return cpu_ppc_get_tb(env) & 0xFFFF= FFFF;=0A}=0A=0Auint32_t cpu_ppc_load_atbu (CPUState *env)=0A{=0A return = cpu_ppc_get_tb(env) >> 32;=0A}=0A=0Auint32_t cpu_ppc601_load_rtcu (CPUState= *env)=0A__attribute__ (( alias ("cpu_ppc_load_tbu") ));=0A=0Auint32_t cpu_= ppc601_load_rtcl (CPUState *env)=0A{=0A return cpu_ppc_load_tbl(env) & 0= x3FFFFF80;=0A}=0A=0A/* XXX: to be fixed */=0Aint ppc_dcr_read (ppc_dcr_t *d= cr_env, int dcrn, target_ulong *valp)=0A{=0A return -1;=0A}=0A=0Aint ppc= _dcr_write (ppc_dcr_t *dcr_env, int dcrn, target_ulong val)=0A{=0A retur= n -1;=0A}=0A=0A#define EXCP_DUMP(env, fmt, args...) = \=0Ado { = \=0A fprintf(stderr, fmt , ##args); = \=0A cpu_dump_state(env, stderr, fprintf,= 0); \=0A qemu_log(fmt, ##args); = \=0A log_cpu_state(env, 0); = \=0A} while (0)=0A=0Av= oid cpu_loop(CPUPPCState *env)=0A{=0A target_siginfo_t info;=0A int t= rapnr;=0A uint32_t ret;=0A=0A for(;;) {=0A trapnr =3D cpu_ppc_= exec(env);=0A switch(trapnr) {=0A case POWERPC_EXCP_NONE:=0A = /* Just go on */=0A break;=0A case POWERPC_EXC= P_CRITICAL: /* Critical input */=0A cpu_a= bort(env, "Critical interrupt while in user mode. "=0A = "Aborting\n");=0A break;=0A case POWERPC_EXCP_MCHECK: = /* Machine check exception */=0A cpu_abort(env, "M= achine check exception while in user mode. "=0A "Abort= ing\n");=0A break;=0A case POWERPC_EXCP_DSI: /* Data= storage exception */=0A EXCP_DUMP(env, "Invalid = data memory access: 0x" ADDRX "\n",=0A env->spr[SPR_DA= R]);=0A /* XXX: check this. Seems bugged */=0A switch= (env->error_code & 0xFF000000) {=0A case 0x40000000:=0A = info.si_signo =3D TARGET_SIGSEGV;=0A info.si_errno = =3D 0;=0A info.si_code =3D TARGET_SEGV_MAPERR;=0A = break;=0A case 0x04000000:=0A info.si_signo = =3D TARGET_SIGILL;=0A info.si_errno =3D 0;=0A = info.si_code =3D TARGET_ILL_ILLADR;=0A break;=0A = case 0x08000000:=0A info.si_signo =3D TARGET_SIGSEGV;=0A = info.si_errno =3D 0;=0A info.si_code =3D TARGET= _SEGV_ACCERR;=0A break;=0A default:=0A = /* Let's send a regular segfault... */=0A EXCP_DUMP(env= , "Invalid segfault errno (%02x)\n",=0A env->error= _code);=0A info.si_signo =3D TARGET_SIGSEGV;=0A = info.si_errno =3D 0;=0A info.si_code =3D TARGET_SEGV_MAPE= RR;=0A break;=0A }=0A info._sifields._= sigfault._addr =3D env->nip;=0A queue_signal(env, info.si_signo,= &info);=0A break;=0A case POWERPC_EXCP_ISI: /* Inst= ruction storage exception */=0A EXCP_DUMP(env, "Invalid = instruction fetch: 0x\n" ADDRX "\n",=0A env->spr[SPR_S= RR0]);=0A /* XXX: check this */=0A switch (env->error= _code & 0xFF000000) {=0A case 0x40000000:=0A info= =2Esi_signo =3D TARGET_SIGSEGV;=0A info.si_errno =3D 0;=0A = info.si_code =3D TARGET_SEGV_MAPERR;=0A break;=0A = case 0x10000000:=0A case 0x08000000:=0A = info.si_signo =3D TARGET_SIGSEGV;=0A info.si_errno =3D 0;= =0A info.si_code =3D TARGET_SEGV_ACCERR;=0A b= reak;=0A default:=0A /* Let's send a regular segf= ault... */=0A EXCP_DUMP(env, "Invalid segfault errno (%02x)\= n",=0A env->error_code);=0A info.si= _signo =3D TARGET_SIGSEGV;=0A info.si_errno =3D 0;=0A = info.si_code =3D TARGET_SEGV_MAPERR;=0A break;=0A = }=0A info._sifields._sigfault._addr =3D env->nip - 4;= =0A queue_signal(env, info.si_signo, &info);=0A break= ;=0A case POWERPC_EXCP_EXTERNAL: /* External input = */=0A cpu_abort(env, "External interrupt while in user mod= e. "=0A "Aborting\n");=0A break;=0A = case POWERPC_EXCP_ALIGN: /* Alignment exception */=0A = EXCP_DUMP(env, "Unaligned memory access\n");=0A /* XX= X: check this */=0A info.si_signo =3D TARGET_SIGBUS;=0A = info.si_errno =3D 0;=0A info.si_code =3D TARGET_BUS_ADRALN;= =0A info._sifields._sigfault._addr =3D env->nip - 4;=0A = queue_signal(env, info.si_signo, &info);=0A break;=0A = case POWERPC_EXCP_PROGRAM: /* Program exception */=0A = /* XXX: check this */=0A switch (env->error_code & ~0= xF) {=0A case POWERPC_EXCP_FP:=0A EXCP_DUMP(env, = "Floating point program exception\n");=0A info.si_signo =3D = TARGET_SIGFPE;=0A info.si_errno =3D 0;=0A swi= tch (env->error_code & 0xF) {=0A case POWERPC_EXCP_FP_OX:=0A= info.si_code =3D TARGET_FPE_FLTOVF;=0A = break;=0A case POWERPC_EXCP_FP_UX:=0A = info.si_code =3D TARGET_FPE_FLTUND;=0A break;=0A = case POWERPC_EXCP_FP_ZX:=0A case POWERPC_EXCP_FP_VXZ= DZ:=0A info.si_code =3D TARGET_FPE_FLTDIV;=0A = break;=0A case POWERPC_EXCP_FP_XX:=0A = info.si_code =3D TARGET_FPE_FLTRES;=0A break;=0A = case POWERPC_EXCP_FP_VXSOFT:=0A info.si_co= de =3D TARGET_FPE_FLTINV;=0A break;=0A ca= se POWERPC_EXCP_FP_VXSNAN:=0A case POWERPC_EXCP_FP_VXISI:=0A= case POWERPC_EXCP_FP_VXIDI:=0A case POWERPC_= EXCP_FP_VXIMZ:=0A case POWERPC_EXCP_FP_VXVC:=0A = case POWERPC_EXCP_FP_VXSQRT:=0A case POWERPC_EXCP_FP_VXCV= I:=0A info.si_code =3D TARGET_FPE_FLTSUB;=0A = break;=0A default:=0A EXCP_DUMP(e= nv, "Unknown floating point exception (%02x)\n",=0A = env->error_code);=0A break;=0A }=0A= break;=0A case POWERPC_EXCP_INVAL:=0A = EXCP_DUMP(env, "Invalid instruction\n");=0A info.si_sig= no =3D TARGET_SIGILL;=0A info.si_errno =3D 0;=0A = switch (env->error_code & 0xF) {=0A case POWERPC_EXCP_IN= VAL_INVAL:=0A info.si_code =3D TARGET_ILL_ILLOPC;=0A = break;=0A case POWERPC_EXCP_INVAL_LSWX:=0A = info.si_code =3D TARGET_ILL_ILLOPN;=0A = break;=0A case POWERPC_EXCP_INVAL_SPR:=0A = info.si_code =3D TARGET_ILL_PRVREG;=0A break;=0A = case POWERPC_EXCP_INVAL_FP:=0A info.si_code = =3D TARGET_ILL_COPROC;=0A break;=0A defau= lt:=0A EXCP_DUMP(env, "Unknown invalid operation (%02x)\= n",=0A env->error_code & 0xF);=0A = info.si_code =3D TARGET_ILL_ILLADR;=0A break;=0A = }=0A break;=0A case POWERPC_EXCP_P= RIV:=0A EXCP_DUMP(env, "Privilege violation\n");=0A = info.si_signo =3D TARGET_SIGILL;=0A info.si_errno =3D= 0;=0A switch (env->error_code & 0xF) {=0A ca= se POWERPC_EXCP_PRIV_OPC:=0A info.si_code =3D TARGET_ILL= _PRVOPC;=0A break;=0A case POWERPC_EXCP_P= RIV_REG:=0A info.si_code =3D TARGET_ILL_PRVREG;=0A = break;=0A default:=0A EXCP_= DUMP(env, "Unknown privilege violation (%02x)\n",=0A = env->error_code & 0xF);=0A info.si_code =3D TARGE= T_ILL_PRVOPC;=0A break;=0A }=0A = break;=0A case POWERPC_EXCP_TRAP:=0A cpu_ab= ort(env, "Tried to call a TRAP\n");=0A break;=0A = default:=0A /* Should not happen ! */=0A cpu_= abort(env, "Unknown program exception (%02x)\n",=0A = env->error_code);=0A break;=0A }=0A = info._sifields._sigfault._addr =3D env->nip - 4;=0A queue_signal= (env, info.si_signo, &info);=0A break;=0A case POWERPC_EX= CP_FPU: /* Floating-point unavailable exception */=0A EXCP= _DUMP(env, "No floating point allowed\n");=0A info.si_signo =3D = TARGET_SIGILL;=0A info.si_errno =3D 0;=0A info.si_cod= e =3D TARGET_ILL_COPROC;=0A info._sifields._sigfault._addr =3D e= nv->nip - 4;=0A queue_signal(env, info.si_signo, &info);=0A = break;=0A case POWERPC_EXCP_SYSCALL: /* System call exceptio= n */=0A cpu_abort(env, "Syscall exception while = in user mode. "=0A "Aborting\n");=0A break;= =0A case POWERPC_EXCP_APU: /* Auxiliary processor unavailable = */=0A EXCP_DUMP(env, "No APU instruction allowed\n");=0A = info.si_signo =3D TARGET_SIGILL;=0A info.si_errno =3D 0= ;=0A info.si_code =3D TARGET_ILL_COPROC;=0A info._sif= ields._sigfault._addr =3D env->nip - 4;=0A queue_signal(env, inf= o.si_signo, &info);=0A break;=0A case POWERPC_EXCP_DECR: = /* Decrementer exception */=0A cpu_abort(env= , "Decrementer interrupt while in user mode. "=0A "Abo= rting\n");=0A break;=0A case POWERPC_EXCP_FIT: /* Fi= xed-interval timer interrupt */=0A cpu_abort(env, "Fix in= terval timer interrupt while in user mode. "=0A "Abort= ing\n");=0A break;=0A case POWERPC_EXCP_WDT: /* Watc= hdog timer interrupt */=0A cpu_abort(env, "Watchdog= timer interrupt while in user mode. "=0A "Aborting\n"= );=0A break;=0A case POWERPC_EXCP_DTLB: /* Data TLB e= rror */=0A cpu_abort(env, "Data TLB excep= tion while in user mode. "=0A "Aborting\n");=0A = break;=0A case POWERPC_EXCP_ITLB: /* Instruction TLB error = */=0A cpu_abort(env, "Instruction TLB exception = while in user mode. "=0A "Aborting\n");=0A = break;=0A case POWERPC_EXCP_SPEU: /* SPE/embedded floating-point= unavail. */=0A EXCP_DUMP(env, "No SPE/floating-point instructi= on allowed\n");=0A info.si_signo =3D TARGET_SIGILL;=0A = info.si_errno =3D 0;=0A info.si_code =3D TARGET_ILL_COPROC;=0A= info._sifields._sigfault._addr =3D env->nip - 4;=0A = queue_signal(env, info.si_signo, &info);=0A break;=0A cas= e POWERPC_EXCP_EFPDI: /* Embedded floating-point data IRQ */=0A = cpu_abort(env, "Embedded floating-point data IRQ not handled\n");= =0A break;=0A case POWERPC_EXCP_EFPRI: /* Embedded flo= ating-point round IRQ */=0A cpu_abort(env, "Embedded floatin= g-point round IRQ not handled\n");=0A break;=0A case POWE= RPC_EXCP_EPERFM: /* Embedded performance monitor IRQ */=0A = cpu_abort(env, "Performance monitor exception not handled\n");=0A = break;=0A case POWERPC_EXCP_DOORI: /* Embedded doorbell inter= rupt */=0A cpu_abort(env, "Doorbell interrupt while in= user mode. "=0A "Aborting\n");=0A break;= =0A case POWERPC_EXCP_DOORCI: /* Embedded doorbell critical interr= upt */=0A cpu_abort(env, "Doorbell critical interrupt while in = user mode. "=0A "Aborting\n");=0A break;=0A= case POWERPC_EXCP_RESET: /* System reset exception = */=0A cpu_abort(env, "Reset interrupt while in user mode. "=0A= "Aborting\n");=0A break;=0A case PO= WERPC_EXCP_DSEG: /* Data segment exception */=0A = cpu_abort(env, "Data segment exception while in user mode. "=0A = "Aborting\n");=0A break;=0A case POWERPC_EX= CP_ISEG: /* Instruction segment exception */=0A cpu_= abort(env, "Instruction segment exception "=0A "while = in user mode. Aborting\n");=0A break;=0A /* PowerPC 64 wi= th hypervisor mode support */=0A case POWERPC_EXCP_HDECR: /* Hype= rvisor decrementer exception */=0A cpu_abort(env, "Hypervis= or decrementer interrupt "=0A "while in user mode. Abo= rting\n");=0A break;=0A case POWERPC_EXCP_TRACE: /* Tr= ace exception */=0A /* Nothing to do:=0A = * we use this exception to emulate step-by-step execution mode.= =0A */=0A break;=0A /* PowerPC 64 with hyperv= isor mode support */=0A case POWERPC_EXCP_HDSI: /* Hypervisor da= ta storage exception */=0A cpu_abort(env, "Hypervisor data s= torage exception "=0A "while in user mode. Aborting\n"= );=0A break;=0A case POWERPC_EXCP_HISI: /* Hypervisor= instruction storage excp */=0A cpu_abort(env, "Hypervisor ins= truction storage exception "=0A "while in user mode. A= borting\n");=0A break;=0A case POWERPC_EXCP_HDSEG: /* = Hypervisor data segment exception */=0A cpu_abort(env, "Hype= rvisor data segment exception "=0A "while in user mode= =2E Aborting\n");=0A break;=0A case POWERPC_EXCP_HISEG: = /* Hypervisor instruction segment excp */=0A cpu_abort(env, = "Hypervisor instruction segment exception "=0A "while = in user mode. Aborting\n");=0A break;=0A case POWERPC_EXC= P_VPU: /* Vector unavailable exception */=0A EXCP_= DUMP(env, "No Altivec instructions allowed\n");=0A info.si_signo= =3D TARGET_SIGILL;=0A info.si_errno =3D 0;=0A info.s= i_code =3D TARGET_ILL_COPROC;=0A info._sifields._sigfault._addr = =3D env->nip - 4;=0A queue_signal(env, info.si_signo, &info);=0A= break;=0A case POWERPC_EXCP_PIT: /* Programmable in= terval timer IRQ */=0A cpu_abort(env, "Programable interva= l timer interrupt "=0A "while in user mode. Aborting\n= ");=0A break;=0A case POWERPC_EXCP_IO: /* IO error = exception */=0A cpu_abort(env, "IO error exce= ption while in user mode. "=0A "Aborting\n");=0A = break;=0A case POWERPC_EXCP_RUNM: /* Run mode exception = */=0A cpu_abort(env, "Run mode exception while = in user mode. "=0A "Aborting\n");=0A break;= =0A case POWERPC_EXCP_EMUL: /* Emulation trap exception = */=0A cpu_abort(env, "Emulation trap exception not handled\= n");=0A break;=0A case POWERPC_EXCP_IFTLB: /* Instruct= ion fetch TLB error */=0A cpu_abort(env, "Instruction = fetch TLB exception "=0A "while in user-mode. Aborting= ");=0A break;=0A case POWERPC_EXCP_DLTLB: /* Data load= TLB miss */=0A cpu_abort(env, "Data load TLB= exception while in user-mode. "=0A "Aborting");=0A = break;=0A case POWERPC_EXCP_DSTLB: /* Data store TLB mis= s */=0A cpu_abort(env, "Data store TLB excepti= on while in user-mode. "=0A "Aborting");=0A = break;=0A case POWERPC_EXCP_FPA: /* Floating-point assist exce= ption */=0A cpu_abort(env, "Floating-point assist exceptio= n not handled\n");=0A break;=0A case POWERPC_EXCP_IABR: = /* Instruction address breakpoint */=0A cpu_abort(env,= "Instruction address breakpoint exception "=0A "not h= andled\n");=0A break;=0A case POWERPC_EXCP_SMI: /* S= ystem management interrupt */=0A cpu_abort(env, "Syste= m management interrupt while in user mode. "=0A "Abort= ing\n");=0A break;=0A case POWERPC_EXCP_THERM: /* Ther= mal interrupt */=0A cpu_abort(env, "Thermal = interrupt interrupt while in user mode. "=0A "Aborting= \n");=0A break;=0A case POWERPC_EXCP_PERFM: /* Embedded= performance monitor IRQ */=0A cpu_abort(env, "Performance = monitor exception not handled\n");=0A break;=0A case POWE= RPC_EXCP_VPUA: /* Vector assist exception */=0A = cpu_abort(env, "Vector assist exception not handled\n");=0A br= eak;=0A case POWERPC_EXCP_SOFTP: /* Soft patch exception = */=0A cpu_abort(env, "Soft patch exception not handled\= n");=0A break;=0A case POWERPC_EXCP_MAINT: /* Maintena= nce exception */=0A cpu_abort(env, "Maintenance = exception while in user mode. "=0A "Aborting\n");=0A = break;=0A case POWERPC_EXCP_STOP: /* stop translation = */=0A /* We did invalidate the instruction = cache. Go on */=0A break;=0A case POWERPC_EXCP_BRANCH: = /* branch instruction: */=0A /* We just stoppe= d because of a branch. Go on */=0A break;=0A case POWERPC= _EXCP_SYSCALL_USER:=0A /* system call in user-mode emulation */= =0A /* WARNING:=0A * PPC ABI uses overflow flag in c= r0 to signal an error=0A * in syscalls.=0A */=0A#if= 0=0A printf("syscall %d 0x%08x 0x%08x 0x%08x 0x%08x\n", env->gp= r[0],=0A env->gpr[3], env->gpr[4], env->gpr[5], env->gpr[= 6]);=0A#endif=0A env->crf[0] &=3D ~0x1;=0A ret =3D do= _syscall(env, env->gpr[0], env->gpr[3], env->gpr[4],=0A = env->gpr[5], env->gpr[6], env->gpr[7],=0A = env->gpr[8]);=0A if (ret > (uint32_t)(-515)) {=0A = env->crf[0] |=3D 0x1;=0A ret =3D -ret;=0A }= =0A env->gpr[3] =3D ret;=0A#if 0=0A printf("syscall r= eturned 0x%08x (%d)\n", ret, ret);=0A#endif=0A break;=0A = case EXCP_DEBUG:=0A {=0A int sig;=0A=0A = sig =3D gdb_handlesig(env, TARGET_SIGTRAP);=0A if (sig= ) {=0A info.si_signo =3D sig;=0A info= =2Esi_errno =3D 0;=0A info.si_code =3D TARGET_TRAP_BRKPT= ;=0A queue_signal(env, info.si_signo, &info);=0A = }=0A }=0A break;=0A case EXCP_INTERR= UPT:=0A /* just indicate that signals should be handled asap */= =0A break;=0A default:=0A cpu_abort(env, "Unkn= own exception 0x%d. Aborting\n", trapnr);=0A break;=0A }= =0A process_pending_signals(env);=0A }=0A}=0A#endif=0A=0A#ifdef T= ARGET_MIPS=0A=0A#define MIPS_SYS(name, args) args,=0A=0Astatic const uint8_= t mips_syscall_args[] =3D {=0A MIPS_SYS(sys_syscall , 0) /* 4000 */=0A MIPS= _SYS(sys_exit , 1)=0A MIPS_SYS(sys_fork , 0)=0A MIPS_SYS(sys_read , 3)=0A M= IPS_SYS(sys_write , 3)=0A MIPS_SYS(sys_open , 3) /* 4005 */=0A MIPS_SYS(sys= _close , 1)=0A MIPS_SYS(sys_waitpid , 3)=0A MIPS_SYS(sys_creat , 2)=0A MIPS= _SYS(sys_link , 2)=0A MIPS_SYS(sys_unlink , 1) /* 4010 */=0A MIPS_SYS(sys_e= xecve , 0)=0A MIPS_SYS(sys_chdir , 1)=0A MIPS_SYS(sys_time , 1)=0A MIPS_SYS= (sys_mknod , 3)=0A MIPS_SYS(sys_chmod , 2) /* 4015 */=0A MIPS_SYS(sys_lchow= n , 3)=0A MIPS_SYS(sys_ni_syscall , 0)=0A MIPS_SYS(sys_ni_syscall , 0) /* w= as sys_stat */=0A MIPS_SYS(sys_lseek , 3)=0A MIPS_SYS(sys_getpid , 0) /* 40= 20 */=0A MIPS_SYS(sys_mount , 5)=0A MIPS_SYS(sys_oldumount , 1)=0A MIPS_SYS= (sys_setuid , 1)=0A MIPS_SYS(sys_getuid , 0)=0A MIPS_SYS(sys_stime , 1) /* = 4025 */=0A MIPS_SYS(sys_ptrace , 4)=0A MIPS_SYS(sys_alarm , 1)=0A MIPS_SYS(= sys_ni_syscall , 0) /* was sys_fstat */=0A MIPS_SYS(sys_pause , 0)=0A MIPS_= SYS(sys_utime , 2) /* 4030 */=0A MIPS_SYS(sys_ni_syscall , 0)=0A MIPS_SYS(s= ys_ni_syscall , 0)=0A MIPS_SYS(sys_access , 2)=0A MIPS_SYS(sys_nice , 1)=0A= MIPS_SYS(sys_ni_syscall , 0) /* 4035 */=0A MIPS_SYS(sys_sync , 0)=0A MIPS_= SYS(sys_kill , 2)=0A MIPS_SYS(sys_rename , 2)=0A MIPS_SYS(sys_mkdir , 2)=0A= MIPS_SYS(sys_rmdir , 1) /* 4040 */=0A MIPS_SYS(sys_dup , 1)=0A MIPS_SYS(s= ys_pipe , 0)=0A MIPS_SYS(sys_times , 1)=0A MIPS_SYS(sys_ni_syscall , 0)=0A = MIPS_SYS(sys_brk , 1) /* 4045 */=0A MIPS_SYS(sys_setgid , 1)=0A MIPS_SYS(s= ys_getgid , 0)=0A MIPS_SYS(sys_ni_syscall , 0) /* was signal(2) */=0A MIPS_= SYS(sys_geteuid , 0)=0A MIPS_SYS(sys_getegid , 0) /* 4050 */=0A MIPS_SYS(sy= s_acct , 0)=0A MIPS_SYS(sys_umount , 2)=0A MIPS_SYS(sys_ni_syscall , 0)=0A = MIPS_SYS(sys_ioctl , 3)=0A MIPS_SYS(sys_fcntl , 3) /* 4055 */=0A MIPS_SYS(s= ys_ni_syscall , 2)=0A MIPS_SYS(sys_setpgid , 2)=0A MIPS_SYS(sys_ni_syscall = , 0)=0A MIPS_SYS(sys_olduname , 1)=0A MIPS_SYS(sys_umask , 1) /* 4060 */=0A= MIPS_SYS(sys_chroot , 1)=0A MIPS_SYS(sys_ustat , 2)=0A MIPS_SYS(sys_dup2 ,= 2)=0A MIPS_SYS(sys_getppid , 0)=0A MIPS_SYS(sys_getpgrp , 0) /* 4065 */=0A= MIPS_SYS(sys_setsid , 0)=0A MIPS_SYS(sys_sigaction , 3)=0A MIPS_SYS(sys_sg= etmask , 0)=0A MIPS_SYS(sys_ssetmask , 1)=0A MIPS_SYS(sys_setreuid , 2) /* = 4070 */=0A MIPS_SYS(sys_setregid , 2)=0A MIPS_SYS(sys_sigsuspend , 0)=0A MI= PS_SYS(sys_sigpending , 1)=0A MIPS_SYS(sys_sethostname , 2)=0A MIPS_SYS(sys= _setrlimit , 2) /* 4075 */=0A MIPS_SYS(sys_getrlimit , 2)=0A MIPS_SYS(sys_g= etrusage , 2)=0A MIPS_SYS(sys_gettimeofday, 2)=0A MIPS_SYS(sys_settimeofday= , 2)=0A MIPS_SYS(sys_getgroups , 2) /* 4080 */=0A MIPS_SYS(sys_setgroups , = 2)=0A MIPS_SYS(sys_ni_syscall , 0) /* old_select */=0A MIPS_SYS(sys_symlink= , 2)=0A MIPS_SYS(sys_ni_syscall , 0) /* was sys_lstat */=0A MIPS_SYS(sys_r= eadlink , 3) /* 4085 */=0A MIPS_SYS(sys_uselib , 1)=0A MIPS_SYS(sys_swapon = , 2)=0A MIPS_SYS(sys_reboot , 3)=0A MIPS_SYS(old_readdir , 3)=0A MIPS_SYS(o= ld_mmap , 6) /* 4090 */=0A MIPS_SYS(sys_munmap , 2)=0A MIPS_SYS(sys_truncat= e , 2)=0A MIPS_SYS(sys_ftruncate , 2)=0A MIPS_SYS(sys_fchmod , 2)=0A MIPS_S= YS(sys_fchown , 3) /* 4095 */=0A MIPS_SYS(sys_getpriority , 2)=0A MIPS_SYS(= sys_setpriority , 3)=0A MIPS_SYS(sys_ni_syscall , 0)=0A MIPS_SYS(sys_statfs= , 2)=0A MIPS_SYS(sys_fstatfs , 2) /* 4100 */=0A MIPS_SYS(sys_ni_syscall , = 0) /* was ioperm(2) */=0A MIPS_SYS(sys_socketcall , 2)=0A MIPS_SYS(sys_sysl= og , 3)=0A MIPS_SYS(sys_setitimer , 3)=0A MIPS_SYS(sys_getitimer , 2) /* 41= 05 */=0A MIPS_SYS(sys_newstat , 2)=0A MIPS_SYS(sys_newlstat , 2)=0A MIPS_SY= S(sys_newfstat , 2)=0A MIPS_SYS(sys_uname , 1)=0A MIPS_SYS(sys_ni_syscall ,= 0) /* 4110 was iopl(2) */=0A MIPS_SYS(sys_vhangup , 0)=0A MIPS_SYS(sys_ni_= syscall , 0) /* was sys_idle() */=0A MIPS_SYS(sys_ni_syscall , 0) /* was sy= s_vm86 */=0A MIPS_SYS(sys_wait4 , 4)=0A MIPS_SYS(sys_swapoff , 1) /* 4115 *= /=0A MIPS_SYS(sys_sysinfo , 1)=0A MIPS_SYS(sys_ipc , 6)=0A MIPS_SYS(sys_fs= ync , 1)=0A MIPS_SYS(sys_sigreturn , 0)=0A MIPS_SYS(sys_clone , 0) /* 4120 = */=0A MIPS_SYS(sys_setdomainname, 2)=0A MIPS_SYS(sys_newuname , 1)=0A MIPS_= SYS(sys_ni_syscall , 0) /* sys_modify_ldt */=0A MIPS_SYS(sys_adjtimex , 1)= =0A MIPS_SYS(sys_mprotect , 3) /* 4125 */=0A MIPS_SYS(sys_sigprocmask , 3)= =0A MIPS_SYS(sys_ni_syscall , 0) /* was create_module */=0A MIPS_SYS(sys_in= it_module , 5)=0A MIPS_SYS(sys_delete_module, 1)=0A MIPS_SYS(sys_ni_syscall= , 0) /* 4130 was get_kernel_syms */=0A MIPS_SYS(sys_quotactl , 0)=0A MIPS_= SYS(sys_getpgid , 1)=0A MIPS_SYS(sys_fchdir , 1)=0A MIPS_SYS(sys_bdflush , = 2)=0A MIPS_SYS(sys_sysfs , 3) /* 4135 */=0A MIPS_SYS(sys_personality , 1)= =0A MIPS_SYS(sys_ni_syscall , 0) /* for afs_syscall */=0A MIPS_SYS(sys_setf= suid , 1)=0A MIPS_SYS(sys_setfsgid , 1)=0A MIPS_SYS(sys_llseek , 5) /* 4140= */=0A MIPS_SYS(sys_getdents , 3)=0A MIPS_SYS(sys_select , 5)=0A MIPS_SYS(s= ys_flock , 2)=0A MIPS_SYS(sys_msync , 3)=0A MIPS_SYS(sys_readv , 3) /* 4145= */=0A MIPS_SYS(sys_writev , 3)=0A MIPS_SYS(sys_cacheflush , 3)=0A MIPS_SYS= (sys_cachectl , 3)=0A MIPS_SYS(sys_sysmips , 4)=0A MIPS_SYS(sys_ni_syscall = , 0) /* 4150 */=0A MIPS_SYS(sys_getsid , 1)=0A MIPS_SYS(sys_fdatasync , 0)= =0A MIPS_SYS(sys_sysctl , 1)=0A MIPS_SYS(sys_mlock , 2)=0A MIPS_SYS(sys_mun= lock , 2) /* 4155 */=0A MIPS_SYS(sys_mlockall , 1)=0A MIPS_SYS(sys_munlocka= ll , 0)=0A MIPS_SYS(sys_sched_setparam, 2)=0A MIPS_SYS(sys_sched_getparam, = 2)=0A MIPS_SYS(sys_sched_setscheduler, 3) /* 4160 */=0A MIPS_SYS(sys_sched_= getscheduler, 1)=0A MIPS_SYS(sys_sched_yield , 0)=0A MIPS_SYS(sys_sched_get= _priority_max, 1)=0A MIPS_SYS(sys_sched_get_priority_min, 1)=0A MIPS_SYS(sy= s_sched_rr_get_interval, 2) /* 4165 */=0A MIPS_SYS(sys_nanosleep, 2)=0A MIP= S_SYS(sys_mremap , 4)=0A MIPS_SYS(sys_accept , 3)=0A MIPS_SYS(sys_bind , 3)= =0A MIPS_SYS(sys_connect , 3) /* 4170 */=0A MIPS_SYS(sys_getpeername , 3)= =0A MIPS_SYS(sys_getsockname , 3)=0A MIPS_SYS(sys_getsockopt , 5)=0A MIPS_S= YS(sys_listen , 2)=0A MIPS_SYS(sys_recv , 4) /* 4175 */=0A MIPS_SYS(sys_rec= vfrom , 6)=0A MIPS_SYS(sys_recvmsg , 3)=0A MIPS_SYS(sys_send , 4)=0A MIPS_S= YS(sys_sendmsg , 3)=0A MIPS_SYS(sys_sendto , 6) /* 4180 */=0A MIPS_SYS(sys_= setsockopt , 5)=0A MIPS_SYS(sys_shutdown , 2)=0A MIPS_SYS(sys_socket , 3)= =0A MIPS_SYS(sys_socketpair , 4)=0A MIPS_SYS(sys_setresuid , 3) /* 4185 */= =0A MIPS_SYS(sys_getresuid , 3)=0A MIPS_SYS(sys_ni_syscall , 0) /* was sys_= query_module */=0A MIPS_SYS(sys_poll , 3)=0A MIPS_SYS(sys_nfsservctl , 3)= =0A MIPS_SYS(sys_setresgid , 3) /* 4190 */=0A MIPS_SYS(sys_getresgid , 3)= =0A MIPS_SYS(sys_prctl , 5)=0A MIPS_SYS(sys_rt_sigreturn, 0)=0A MIPS_SYS(sy= s_rt_sigaction, 4)=0A MIPS_SYS(sys_rt_sigprocmask, 4) /* 4195 */=0A MIPS_SY= S(sys_rt_sigpending, 2)=0A MIPS_SYS(sys_rt_sigtimedwait, 4)=0A MIPS_SYS(sys= _rt_sigqueueinfo, 3)=0A MIPS_SYS(sys_rt_sigsuspend, 0)=0A MIPS_SYS(sys_prea= d64 , 6) /* 4200 */=0A MIPS_SYS(sys_pwrite64 , 6)=0A MIPS_SYS(sys_chown , 3= )=0A MIPS_SYS(sys_getcwd , 2)=0A MIPS_SYS(sys_capget , 2)=0A MIPS_SYS(sys_c= apset , 2) /* 4205 */=0A MIPS_SYS(sys_sigaltstack , 0)=0A MIPS_SYS(sys_send= file , 4)=0A MIPS_SYS(sys_ni_syscall , 0)=0A MIPS_SYS(sys_ni_syscall , 0)= =0A MIPS_SYS(sys_mmap2 , 6) /* 4210 */=0A MIPS_SYS(sys_truncate64 , 4)=0A M= IPS_SYS(sys_ftruncate64 , 4)=0A MIPS_SYS(sys_stat64 , 2)=0A MIPS_SYS(sys_ls= tat64 , 2)=0A MIPS_SYS(sys_fstat64 , 2) /* 4215 */=0A MIPS_SYS(sys_pivot_ro= ot , 2)=0A MIPS_SYS(sys_mincore , 3)=0A MIPS_SYS(sys_madvise , 3)=0A MIPS_S= YS(sys_getdents64 , 3)=0A MIPS_SYS(sys_fcntl64 , 3) /* 4220 */=0A MIPS_SYS(= sys_ni_syscall , 0)=0A MIPS_SYS(sys_gettid , 0)=0A MIPS_SYS(sys_readahead ,= 5)=0A MIPS_SYS(sys_setxattr , 5)=0A MIPS_SYS(sys_lsetxattr , 5) /* 4225 */= =0A MIPS_SYS(sys_fsetxattr , 5)=0A MIPS_SYS(sys_getxattr , 4)=0A MIPS_SYS(s= ys_lgetxattr , 4)=0A MIPS_SYS(sys_fgetxattr , 4)=0A MIPS_SYS(sys_listxattr = , 3) /* 4230 */=0A MIPS_SYS(sys_llistxattr , 3)=0A MIPS_SYS(sys_flistxattr = , 3)=0A MIPS_SYS(sys_removexattr , 2)=0A MIPS_SYS(sys_lremovexattr, 2)=0A M= IPS_SYS(sys_fremovexattr, 2) /* 4235 */=0A MIPS_SYS(sys_tkill , 2)=0A MIPS_= SYS(sys_sendfile64 , 5)=0A MIPS_SYS(sys_futex , 2)=0A MIPS_SYS(sys_sched_se= taffinity, 3)=0A MIPS_SYS(sys_sched_getaffinity, 3) /* 4240 */=0A MIPS_SYS(= sys_io_setup , 2)=0A MIPS_SYS(sys_io_destroy , 1)=0A MIPS_SYS(sys_io_geteve= nts, 5)=0A MIPS_SYS(sys_io_submit , 3)=0A MIPS_SYS(sys_io_cancel , 3) /* 42= 45 */=0A MIPS_SYS(sys_exit_group , 1)=0A MIPS_SYS(sys_lookup_dcookie, 3)=0A= MIPS_SYS(sys_epoll_create, 1)=0A MIPS_SYS(sys_epoll_ctl , 4)=0A MIPS_SYS(s= ys_epoll_wait , 3) /* 4250 */=0A MIPS_SYS(sys_remap_file_pages, 5)=0A MIPS_= SYS(sys_set_tid_address, 1)=0A MIPS_SYS(sys_restart_syscall, 0)=0A MIPS_SYS= (sys_fadvise64_64, 7)=0A MIPS_SYS(sys_statfs64 , 3) /* 4255 */=0A MIPS_SYS(= sys_fstatfs64 , 2)=0A MIPS_SYS(sys_timer_create, 3)=0A MIPS_SYS(sys_timer_s= ettime, 4)=0A MIPS_SYS(sys_timer_gettime, 2)=0A MIPS_SYS(sys_timer_getoverr= un, 1) /* 4260 */=0A MIPS_SYS(sys_timer_delete, 1)=0A MIPS_SYS(sys_clock_se= ttime, 2)=0A MIPS_SYS(sys_clock_gettime, 2)=0A MIPS_SYS(sys_clock_getres, 2= )=0A MIPS_SYS(sys_clock_nanosleep, 4) /* 4265 */=0A MIPS_SYS(sys_tgkill , 3= )=0A MIPS_SYS(sys_utimes , 2)=0A MIPS_SYS(sys_mbind , 4)=0A MIPS_SYS(sys_ni= _syscall , 0) /* sys_get_mempolicy */=0A MIPS_SYS(sys_ni_syscall , 0) /* 42= 70 sys_set_mempolicy */=0A MIPS_SYS(sys_mq_open , 4)=0A MIPS_SYS(sys_mq_unl= ink , 1)=0A MIPS_SYS(sys_mq_timedsend, 5)=0A MIPS_SYS(sys_mq_timedreceive, = 5)=0A MIPS_SYS(sys_mq_notify , 2) /* 4275 */=0A MIPS_SYS(sys_mq_getsetattr,= 3)=0A MIPS_SYS(sys_ni_syscall , 0) /* sys_vserver */=0A MIPS_SYS(sys_waiti= d , 4)=0A MIPS_SYS(sys_ni_syscall , 0) /* available, was setaltroot */=0A M= IPS_SYS(sys_add_key , 5)=0A MIPS_SYS(sys_request_key, 4)=0A MIPS_SYS(sys_ke= yctl , 5)=0A MIPS_SYS(sys_set_thread_area, 1)=0A MIPS_SYS(sys_inotify_init,= 0)=0A MIPS_SYS(sys_inotify_add_watch, 3) /* 4285 */=0A MIPS_SYS(sys_inotif= y_rm_watch, 2)=0A MIPS_SYS(sys_migrate_pages, 4)=0A MIPS_SYS(sys_openat, 4)= =0A MIPS_SYS(sys_mkdirat, 3)=0A MIPS_SYS(sys_mknodat, 4) /* 4290 */=0A MIPS= _SYS(sys_fchownat, 5)=0A MIPS_SYS(sys_futimesat, 3)=0A MIPS_SYS(sys_fstatat= 64, 4)=0A MIPS_SYS(sys_unlinkat, 3)=0A MIPS_SYS(sys_renameat, 4) /* 4295 */= =0A MIPS_SYS(sys_linkat, 5)=0A MIPS_SYS(sys_symlinkat, 3)=0A MIPS_SYS(sys_r= eadlinkat, 4)=0A MIPS_SYS(sys_fchmodat, 3)=0A MIPS_SYS(sys_faccessat, 3) /*= 4300 */=0A MIPS_SYS(sys_pselect6, 6)=0A MIPS_SYS(sys_ppoll, 5)=0A MIPS_SYS= (sys_unshare, 1)=0A MIPS_SYS(sys_splice, 4)=0A MIPS_SYS(sys_sync_file_range= , 7) /* 4305 */=0A MIPS_SYS(sys_tee, 4)=0A MIPS_SYS(sys_vmsplice, 4)=0A MIP= S_SYS(sys_move_pages, 6)=0A MIPS_SYS(sys_set_robust_list, 2)=0A MIPS_SYS(sy= s_get_robust_list, 3) /* 4310 */=0A MIPS_SYS(sys_kexec_load, 4)=0A MIPS_SYS= (sys_getcpu, 3)=0A MIPS_SYS(sys_epoll_pwait, 6)=0A MIPS_SYS(sys_ioprio_set,= 3)=0A MIPS_SYS(sys_ioprio_get, 2)=0A};=0A=0A#undef MIPS_SYS=0A=0Avoid cpu_= loop(CPUMIPSState *env)=0A{=0A target_siginfo_t info;=0A int trapnr, = ret;=0A unsigned int syscall_num;=0A=0A for(;;) {=0A trapnr = =3D cpu_mips_exec(env);=0A switch(trapnr) {=0A case EXCP_SYSC= ALL:=0A syscall_num =3D env->active_tc.gpr[2] - 4000;=0A = env->active_tc.PC +=3D 4;=0A if (syscall_num >=3D sizeof(mip= s_syscall_args)) {=0A ret =3D -ENOSYS;=0A } else = {=0A int nb_args;=0A abi_ulong sp_reg;=0A = abi_ulong arg5 =3D 0, arg6 =3D 0, arg7 =3D 0, arg8 =3D 0;=0A=0A= nb_args =3D mips_syscall_args[syscall_num];=0A = sp_reg =3D env->active_tc.gpr[29];=0A switch (nb_args) {= =0A /* these arguments are taken from the stack */=0A = /* FIXME - what to do if get_user() fails? */=0A ca= se 8: get_user_ual(arg8, sp_reg + 28);=0A case 7: get_user_u= al(arg7, sp_reg + 24);=0A case 6: get_user_ual(arg6, sp_reg = + 20);=0A case 5: get_user_ual(arg5, sp_reg + 16);=0A = default:=0A break;=0A }=0A = ret =3D do_syscall(env, env->active_tc.gpr[2],=0A = env->active_tc.gpr[4],=0A = env->active_tc.gpr[5],=0A env->active_tc.gp= r[6],=0A env->active_tc.gpr[7],=0A = arg5, arg6/*, arg7, arg8*/);=0A }=0A = if ((unsigned int)ret >=3D (unsigned int)(-1133)) {=0A = env->active_tc.gpr[7] =3D 1; /* error flag */=0A ret =3D = -ret;=0A } else {=0A env->active_tc.gpr[7] =3D 0;= /* error flag */=0A }=0A env->active_tc.gpr[2] =3D r= et;=0A break;=0A case EXCP_TLBL:=0A case EXCP_TLBS= :=0A case EXCP_CpU:=0A case EXCP_RI:=0A info.si_si= gno =3D TARGET_SIGILL;=0A info.si_errno =3D 0;=0A inf= o.si_code =3D 0;=0A queue_signal(env, info.si_signo, &info);=0A = break;=0A case EXCP_INTERRUPT:=0A /* just indi= cate that signals should be handled asap */=0A break;=0A = case EXCP_DEBUG:=0A {=0A int sig;=0A=0A = sig =3D gdb_handlesig (env, TARGET_SIGTRAP);=0A if (si= g)=0A {=0A info.si_signo =3D sig;=0A = info.si_errno =3D 0;=0A info.si_code = =3D TARGET_TRAP_BRKPT;=0A queue_signal(env, info.si_sign= o, &info);=0A }=0A }=0A break;=0A = default:=0A // error:=0A fprintf(stderr, = "qemu: unhandled CPU exception 0x%x - aborting\n",=0A tr= apnr);=0A cpu_dump_state(env, stderr, fprintf, 0);=0A = abort();=0A }=0A process_pending_signals(env);=0A }=0A}= =0A#endif=0A=0A#ifdef TARGET_SH4=0Avoid cpu_loop (CPUState *env)=0A{=0A = int trapnr, ret;=0A target_siginfo_t info;=0A=0A while (1) {=0A = trapnr =3D cpu_sh4_exec (env);=0A=0A switch (trapnr) {=0A c= ase 0x160:=0A env->pc +=3D 2;=0A ret =3D do_syscall(e= nv,=0A env->gregs[3],=0A = env->gregs[4],=0A env->gregs[5],=0A = env->gregs[6],=0A env->g= regs[7],=0A env->gregs[0],=0A = env->gregs[1]);=0A env->gregs[0] =3D ret;=0A = break;=0A case EXCP_INTERRUPT:=0A /* just indicate tha= t signals should be handled asap */=0A break;=0A case EXC= P_DEBUG:=0A {=0A int sig;=0A=0A si= g =3D gdb_handlesig (env, TARGET_SIGTRAP);=0A if (sig)=0A = {=0A info.si_signo =3D sig;=0A = info.si_errno =3D 0;=0A info.si_code =3D TARGET= _TRAP_BRKPT;=0A queue_signal(env, info.si_signo, &info);= =0A }=0A }=0A break;=0A case 0xa0:= =0A case 0xc0:=0A info.si_signo =3D SIGSEGV;=0A info.= si_errno =3D 0;=0A info.si_code =3D TARGET_SEGV_MAPERR;=0A = info._sifields._sigfault._addr =3D env->tea;=0A queue_sign= al(env, info.si_signo, &info);=0A break;=0A=0A default:=0A = printf ("Unhandled trap: 0x%x\n", trapnr);=0A cpu_dump_sta= te(env, stderr, fprintf, 0);=0A exit (1);=0A }=0A = process_pending_signals (env);=0A }=0A}=0A#endif=0A=0A#ifdef TARGET_CRIS= =0Avoid cpu_loop (CPUState *env)=0A{=0A int trapnr, ret;=0A target_si= ginfo_t info;=0A =0A while (1) {=0A trapnr =3D cpu_cris_exec (= env);=0A switch (trapnr) {=0A case 0xaa:=0A {=0A = info.si_signo =3D SIGSEGV;=0A info.si_errno = =3D 0;=0A /* XXX: check env->error_code */=0A = info.si_code =3D TARGET_SEGV_MAPERR;=0A info._sifields._sig= fault._addr =3D env->pregs[PR_EDA];=0A queue_signal(env, inf= o.si_signo, &info);=0A }=0A break;=0A case EXCP_INTER= RUPT:=0A /* just indicate that signals should be handled asap */=0A bre= ak;=0A case EXCP_BREAK:=0A ret =3D do_syscall(env, =0A = env->regs[9], =0A env= ->regs[10], =0A env->regs[11], =0A = env->regs[12], =0A env->regs[13= ], =0A env->pregs[7], =0A = env->pregs[11]);=0A env->regs[10] =3D ret;=0A = break;=0A case EXCP_DEBUG:=0A {=0A int sig= ;=0A=0A sig =3D gdb_handlesig (env, TARGET_SIGTRAP);=0A = if (sig)=0A {=0A info.si_sig= no =3D sig;=0A info.si_errno =3D 0;=0A = info.si_code =3D TARGET_TRAP_BRKPT;=0A queue_signal(en= v, info.si_signo, &info);=0A }=0A }=0A = break;=0A default:=0A printf ("Unhandled trap: 0x%x\n"= , trapnr);=0A cpu_dump_state(env, stderr, fprintf, 0);=0A = exit (1);=0A }=0A process_pending_signals (env);=0A }= =0A}=0A#endif=0A=0A#ifdef TARGET_M68K=0A=0Avoid cpu_loop(CPUM68KState *env)= =0A{=0A int trapnr;=0A unsigned int n;=0A target_siginfo_t info;= =0A TaskState *ts =3D env->opaque;=0A=0A for(;;) {=0A trapnr = =3D cpu_m68k_exec(env);=0A switch(trapnr) {=0A case EXCP_ILLE= GAL:=0A {=0A if (ts->sim_syscalls) {=0A = uint16_t nr;=0A nr =3D lduw(env->pc + 2);=0A = env->pc +=3D 4;=0A do_m68k_simcall(env= , nr);=0A } else {=0A goto do_sigill;=0A = }=0A }=0A break;=0A case EXCP_H= ALT_INSN:=0A /* Semihosing syscall. */=0A env->pc += =3D 4;=0A do_m68k_semihosting(env, env->dregs[0]);=0A = break;=0A case EXCP_LINEA:=0A case EXCP_LINEF:=0A cas= e EXCP_UNSUPPORTED:=0A do_sigill:=0A info.si_signo =3D SI= GILL;=0A info.si_errno =3D 0;=0A info.si_code =3D TAR= GET_ILL_ILLOPN;=0A info._sifields._sigfault._addr =3D env->pc;= =0A queue_signal(env, info.si_signo, &info);=0A break= ;=0A case EXCP_TRAP0:=0A {=0A ts->sim_sysc= alls =3D 0;=0A n =3D env->dregs[0];=0A env->p= c +=3D 2;=0A env->dregs[0] =3D do_syscall(env,=0A = n,=0A = env->dregs[1],=0A env->dregs[2]= ,=0A env->dregs[3],=0A = env->dregs[4],=0A = env->dregs[5],=0A en= v->aregs[0]);=0A }=0A break;=0A case EXCP_INTE= RRUPT:=0A /* just indicate that signals should be handled asap *= /=0A break;=0A case EXCP_ACCESS:=0A {=0A = info.si_signo =3D SIGSEGV;=0A info.si_errno =3D 0;= =0A /* XXX: check env->error_code */=0A info.= si_code =3D TARGET_SEGV_MAPERR;=0A info._sifields._sigfault.= _addr =3D env->mmu.ar;=0A queue_signal(env, info.si_signo, &= info);=0A }=0A break;=0A case EXCP_DEBUG:=0A = {=0A int sig;=0A=0A sig =3D gdb_han= dlesig (env, TARGET_SIGTRAP);=0A if (sig)=0A = {=0A info.si_signo =3D sig;=0A info= =2Esi_errno =3D 0;=0A info.si_code =3D TARGET_TRAP_BRKPT= ;=0A queue_signal(env, info.si_signo, &info);=0A = }=0A }=0A break;=0A default:=0A = fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",= =0A trapnr);=0A cpu_dump_state(env, stderr, f= printf, 0);=0A abort();=0A }=0A process_pending_si= gnals(env);=0A }=0A}=0A#endif /* TARGET_M68K */=0A=0A#ifdef TARGET_ALPHA= =0Avoid cpu_loop (CPUState *env)=0A{=0A int trapnr;=0A target_siginfo= _t info;=0A=0A while (1) {=0A trapnr =3D cpu_alpha_exec (env);=0A= =0A switch (trapnr) {=0A case EXCP_RESET:=0A fprin= tf(stderr, "Reset requested. Exit\n");=0A exit(1);=0A = break;=0A case EXCP_MCHK:=0A fprintf(stderr, "Machine ch= eck exception. Exit\n");=0A exit(1);=0A break;=0A = case EXCP_ARITH:=0A fprintf(stderr, "Arithmetic trap.\n");= =0A exit(1);=0A break;=0A case EXCP_HW_INTERRU= PT:=0A fprintf(stderr, "External interrupt. Exit\n");=0A = exit(1);=0A break;=0A case EXCP_DFAULT:=0A = fprintf(stderr, "MMU data fault\n");=0A exit(1);=0A = break;=0A case EXCP_DTB_MISS_PAL:=0A fprintf(stderr, "MMU= data TLB miss in PALcode\n");=0A exit(1);=0A break;= =0A case EXCP_ITB_MISS:=0A fprintf(stderr, "MMU instructi= on TLB miss\n");=0A exit(1);=0A break;=0A case= EXCP_ITB_ACV:=0A fprintf(stderr, "MMU instruction access violat= ion\n");=0A exit(1);=0A break;=0A case EXCP_DT= B_MISS_NATIVE:=0A fprintf(stderr, "MMU data TLB miss\n");=0A = exit(1);=0A break;=0A case EXCP_UNALIGN:=0A = fprintf(stderr, "Unaligned access\n");=0A exit(1);=0A = break;=0A case EXCP_OPCDEC:=0A fprintf(stderr, "In= valid instruction\n");=0A exit(1);=0A break;=0A = case EXCP_FEN:=0A fprintf(stderr, "Floating-point not allowed\= n");=0A exit(1);=0A break;=0A case EXCP_CALL_P= AL ... (EXCP_CALL_PALP - 1):=0A call_pal(env, (trapnr >> 6) | 0x= 80);=0A break;=0A case EXCP_CALL_PALP ... (EXCP_CALL_PALE= - 1):=0A fprintf(stderr, "Privileged call to PALcode\n");=0A = exit(1);=0A break;=0A case EXCP_DEBUG:=0A = {=0A int sig;=0A=0A sig =3D gdb_handlesi= g (env, TARGET_SIGTRAP);=0A if (sig)=0A {= =0A info.si_signo =3D sig;=0A info.si= _errno =3D 0;=0A info.si_code =3D TARGET_TRAP_BRKPT;=0A = queue_signal(env, info.si_signo, &info);=0A = }=0A }=0A break;=0A default:=0A = printf ("Unhandled trap: 0x%x\n", trapnr);=0A cpu_dump_state(e= nv, stderr, fprintf, 0);=0A exit (1);=0A }=0A proc= ess_pending_signals (env);=0A }=0A}=0A#endif /* TARGET_ALPHA */=0A=0Asta= tic void usage(void)=0A{=0A printf("qemu-" TARGET_ARCH " version " QEMU_= VERSION ", Copyright (c) 2003-2008 Fabrice Bellard\n");=0A printf("usage= : qemu-" TARGET_ARCH " [options] program [arguments...]\n");=0A printf("= Linux CPU emulator (compiled for %s emulation)\n",=0A TARGET_ARCH= );=0A printf("\n");=0A printf("Standard options:\n");=0A printf("-= h print this help\n");=0A gdbstub_usage();=0A printf("= -L path set the elf interpreter prefix (default=3D%s)\n",=0A = interp_prefix);=0A printf("-s size set the stack size in= bytes (default=3D%ld)\n",=0A x86_stack_size);=0A printf("-cpu= model select CPU (-cpu ? for list)\n");=0A printf("-drop-ld-prel= oad drop LD_PRELOAD for target process\n");=0A printf("-E var=3Dvalue = sets/modifies targets environment variable(s)\n");=0A printf("-U var= unsets targets environment variable(s)\n");=0A printf("\n");= =0A printf("Debug options:\n");=0A printf("-d options activate log = (logfile=3D%s)\n", DEBUG_LOGFILE);=0A printf("-p pagesize set the host = page size to 'pagesize'\n");=0A printf("-strace log system calls\n"= );=0A printf("\n");=0A printf("Environment variables:\n");=0A prin= tf("QEMU_STRACE Print system calls and arguments similar to the\n");= =0A printf(" 'strace' program. Enable by setting to an= y value.\n");=0A printf("You can use -E and -U options to set/unset envi= ronment variables\n");=0A printf("for target process. It is possible to= provide several variables\n");=0A printf("by repeating the option. For= example:\n");=0A printf(" -E var1=3Dval2 -E var2=3Dval2 -U LD_PRELOA= D -U LD_DEBUG\n");=0A printf("Note that if you provide several changes t= o single variable\n");=0A printf("last change will stay in effect.\n");= =0A exit(1);=0A}=0A=0ATHREAD CPUState *thread_env;=0A=0A/* Assumes conte= nts are already zeroed. */=0Avoid init_task_state(TaskState *ts)=0A{=0A = int i;=0A =0A ts->used =3D 1;=0A ts->first_free =3D ts->sigqueue_tab= le;=0A for (i =3D 0; i < MAX_SIGQUEUE_SIZE - 1; i++) {=0A ts->sig= queue_table[i].next =3D &ts->sigqueue_table[i + 1];=0A }=0A ts->sigqu= eue_table[i].next =3D NULL;=0A}=0A =0Aint main(int argc, char **argv, char = **envp)=0A{=0A const char *filename;=0A const char *cpu_model;=0A = struct target_pt_regs regs1, *regs =3D ®s1;=0A struct image_info info= 1, *info =3D &info1;=0A TaskState ts1, *ts =3D &ts1;=0A CPUState *env= ;=0A int optind;=0A const char *r;=0A char **target_environ, **wrk= ;=0A envlist_t *envlist =3D NULL;=0A=0A if (argc <=3D 1)=0A us= age();=0A=0A qemu_cache_utils_init(envp);=0A=0A /* init debug */=0A = cpu_set_log_filename(DEBUG_LOGFILE);=0A=0A if ((envlist =3D envlist_cr= eate()) =3D=3D NULL) {=0A (void) fprintf(stderr, "Unable to allocate= envlist\n");=0A exit(1);=0A }=0A=0A /* add current environmen= t into the list */=0A for (wrk =3D environ; *wrk !=3D NULL; wrk++) {=0A = (void) envlist_setenv(envlist, *wrk);=0A }=0A=0A cpu_model =3D= NULL;=0A optind =3D 1;=0A for(;;) {=0A if (optind >=3D argc)= =0A break;=0A r =3D argv[optind];=0A if (r[0] !=3D= '-')=0A break;=0A optind++;=0A r++;=0A if = (!strcmp(r, "-")) {=0A break;=0A } else if (!strcmp(r, "d= ")) {=0A int mask;=0A const CPULogItem *item;=0A=0A = if (optind >=3D argc)=0A break;=0A=0A r =3D argv[optind++];=0A = mask =3D cpu_str_to_log_mask(r);=0A if (!mask) {=0A = printf("Log items (comma separated):\n");=0A for(i= tem =3D cpu_log_items; item->mask !=3D 0; item++) {=0A p= rintf("%-10s %s\n", item->name, item->help);=0A }=0A = exit(1);=0A }=0A cpu_set_log(mask);=0A = } else if (!strcmp(r, "E")) {=0A r =3D argv[optind++];=0A = if (envlist_setenv(envlist, r) !=3D 0)=0A usage();=0A = } else if (!strcmp(r, "U")) {=0A r =3D argv[optind++];=0A= if (envlist_unsetenv(envlist, r) !=3D 0)=0A usag= e();=0A } else if (!strcmp(r, "s")) {=0A if (optind >=3D = argc)=0A break;=0A r =3D argv[optind++];=0A = x86_stack_size =3D strtol(r, (char **)&r, 0);=0A if (x86_s= tack_size <=3D 0)=0A usage();=0A if (*r =3D=3D 'M= ')=0A x86_stack_size *=3D 1024 * 1024;=0A else if= (*r =3D=3D 'k' || *r =3D=3D 'K')=0A x86_stack_size *=3D 102= 4;=0A } else if (!strcmp(r, "L")) {=0A interp_prefix =3D = argv[optind++];=0A } else if (!strcmp(r, "p")) {=0A if (o= ptind >=3D argc)=0A break;=0A qemu_host_page_size= =3D atoi(argv[optind++]);=0A if (qemu_host_page_size =3D=3D 0 |= |=0A (qemu_host_page_size & (qemu_host_page_size - 1)) !=3D = 0) {=0A fprintf(stderr, "page size must be a power of two\n"= );=0A exit(1);=0A }=0A } else if (!strcmp(= r, "gdb")) {=0A if (optind >=3D argc) {=0A break;= =0A }=0A if (gdbserver_start(argv[optind++]) < 0) {= =0A /* stop command line analysis */=0A optin= d =3D argc;=0A break;=0A }=0A } else if (!strcmp(= r, "r")) {=0A qemu_uname_release =3D argv[optind++];=0A } else i= f (!strcmp(r, "cpu")) {=0A cpu_model =3D argv[optind++];=0A = if (cpu_model =3D=3D NULL || strcmp(cpu_model, "?") =3D=3D 0) {=0A/*= XXX: implement xxx_cpu_list for targets that still miss it */=0A#if define= d(cpu_list)=0A cpu_list(stdout, &fprintf);=0A#endif=0A = exit(1);=0A }=0A } else if (!strcmp(r, "dro= p-ld-preload")) {=0A (void) envlist_unsetenv(envlist, "LD_PRELOA= D");=0A } else if (!strcmp(r, "singlestep")) {=0A singles= tep =3D 1;=0A } else if (!strcmp(r, "strace")) {=0A do_st= race =3D 1;=0A } else=0A {=0A usage();=0A }= =0A }=0A if (optind >=3D argc)=0A usage();=0A filename =3D = argv[optind];=0A exec_path =3D argv[optind];=0A=0A /* Zero out regs *= /=0A memset(regs, 0, sizeof(struct target_pt_regs));=0A=0A /* Zero ou= t image_info */=0A memset(info, 0, sizeof(struct image_info));=0A=0A = /* Scan interp_prefix dir for replacement files. */=0A init_paths(interp= _prefix);=0A=0A if (cpu_model =3D=3D NULL) {=0A#if defined(TARGET_I386)= =0A#ifdef TARGET_X86_64=0A cpu_model =3D "qemu64";=0A#else=0A = cpu_model =3D "qemu32";=0A#endif=0A#elif defined(TARGET_ARM)=0A cpu= _model =3D "any";=0A#elif defined(TARGET_M68K)=0A cpu_model =3D "any= ";=0A#elif defined(TARGET_SPARC)=0A#ifdef TARGET_SPARC64=0A cpu_mode= l =3D "TI UltraSparc II";=0A#else=0A cpu_model =3D "Fujitsu MB86904"= ;=0A#endif=0A#elif defined(TARGET_MIPS)=0A#if defined(TARGET_ABI_MIPSN32) |= | defined(TARGET_ABI_MIPSN64)=0A cpu_model =3D "20Kc";=0A#else=0A = cpu_model =3D "24Kf";=0A#endif=0A#elif defined(TARGET_PPC)=0A#ifdef TA= RGET_PPC64=0A cpu_model =3D "970";=0A#else=0A cpu_model =3D "= 750";=0A#endif=0A#else=0A cpu_model =3D "any";=0A#endif=0A }=0A = cpu_exec_init_all(0);=0A /* NOTE: we need to init the CPU at this stag= e to get=0A qemu_host_page_size */=0A env =3D cpu_init(cpu_model);= =0A if (!env) {=0A fprintf(stderr, "Unable to find CPU definition= \n");=0A exit(1);=0A }=0A thread_env =3D env;=0A=0A if (get= env("QEMU_STRACE")) {=0A do_strace =3D 1;=0A }=0A=0A target_en= viron =3D envlist_to_environ(envlist, NULL);=0A envlist_free(envlist);= =0A=0A if (loader_exec(filename, argv+optind, target_environ, regs, info= ) !=3D 0) {=0A printf("Error loading %s\n", filename);=0A _ex= it(1);=0A }=0A=0A for (wrk =3D target_environ; *wrk; wrk++) {=0A = free(*wrk);=0A }=0A=0A free(target_environ);=0A=0A if (qemu_log= _enabled()) {=0A log_page_dump();=0A=0A qemu_log("start_brk = 0x" TARGET_ABI_FMT_lx "\n", info->start_brk);=0A qemu_log("end_code= 0x" TARGET_ABI_FMT_lx "\n", info->end_code);=0A qemu_log("start_= code 0x" TARGET_ABI_FMT_lx "\n",=0A info->start_code);=0A = qemu_log("start_data 0x" TARGET_ABI_FMT_lx "\n",=0A = info->start_data);=0A qemu_log("end_data 0x" TARGET_ABI_FMT_lx "= \n", info->end_data);=0A qemu_log("start_stack 0x" TARGET_ABI_FMT_lx= "\n",=0A info->start_stack);=0A qemu_log("brk = 0x" TARGET_ABI_FMT_lx "\n", info->brk);=0A qemu_log("entry = 0x" TARGET_ABI_FMT_lx "\n", info->entry);=0A }=0A=0A target_set_brk(i= nfo->brk);=0A syscall_init();=0A signal_init();=0A=0A /* build Tas= k State */=0A memset(ts, 0, sizeof(TaskState));=0A init_task_state(ts= );=0A ts->info =3D info;=0A env->opaque =3D ts;=0A=0A#if defined(TARG= ET_I386)=0A cpu_x86_set_cpl(env, 3);=0A=0A env->cr[0] =3D CR0_PG_MASK= | CR0_WP_MASK | CR0_PE_MASK;=0A env->hflags |=3D HF_PE_MASK;=0A if (= env->cpuid_features & CPUID_SSE) {=0A env->cr[4] |=3D CR4_OSFXSR_MAS= K;=0A env->hflags |=3D HF_OSFXSR_MASK;=0A }=0A#ifndef TARGET_ABI3= 2=0A /* enable 64 bit mode if possible */=0A if (!(env->cpuid_ext2_fe= atures & CPUID_EXT2_LM)) {=0A fprintf(stderr, "The selected x86 CPU = does not support 64 bit mode\n");=0A exit(1);=0A }=0A env->cr[= 4] |=3D CR4_PAE_MASK;=0A env->efer |=3D MSR_EFER_LMA | MSR_EFER_LME;=0A = env->hflags |=3D HF_LMA_MASK;=0A#endif=0A=0A /* flags setup : we acti= vate the IRQs by default as in user mode */=0A env->eflags |=3D IF_MASK;= =0A=0A /* linux register setup */=0A#ifndef TARGET_ABI32=0A env->regs= [R_EAX] =3D regs->rax;=0A env->regs[R_EBX] =3D regs->rbx;=0A env->reg= s[R_ECX] =3D regs->rcx;=0A env->regs[R_EDX] =3D regs->rdx;=0A env->re= gs[R_ESI] =3D regs->rsi;=0A env->regs[R_EDI] =3D regs->rdi;=0A env->r= egs[R_EBP] =3D regs->rbp;=0A env->regs[R_ESP] =3D regs->rsp;=0A env->= eip =3D regs->rip;=0A#else=0A env->regs[R_EAX] =3D regs->eax;=0A env-= >regs[R_EBX] =3D regs->ebx;=0A env->regs[R_ECX] =3D regs->ecx;=0A env= ->regs[R_EDX] =3D regs->edx;=0A env->regs[R_ESI] =3D regs->esi;=0A en= v->regs[R_EDI] =3D regs->edi;=0A env->regs[R_EBP] =3D regs->ebp;=0A e= nv->regs[R_ESP] =3D regs->esp;=0A env->eip =3D regs->eip;=0A#endif=0A=0A= /* linux interrupt setup */=0A#ifndef TARGET_ABI32=0A env->idt.limit= =3D 511;=0A#else=0A env->idt.limit =3D 255;=0A#endif=0A env->idt.bas= e =3D target_mmap(0, sizeof(uint64_t) * (env->idt.limit + 1),=0A = PROT_READ|PROT_WRITE,=0A = MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);=0A idt_table =3D g2h(env->idt.base)= ;=0A set_idt(0, 0);=0A set_idt(1, 0);=0A set_idt(2, 0);=0A set_= idt(3, 3);=0A set_idt(4, 3);=0A set_idt(5, 0);=0A set_idt(6, 0);= =0A set_idt(7, 0);=0A set_idt(8, 0);=0A set_idt(9, 0);=0A set_i= dt(10, 0);=0A set_idt(11, 0);=0A set_idt(12, 0);=0A set_idt(13, 0)= ;=0A set_idt(14, 0);=0A set_idt(15, 0);=0A set_idt(16, 0);=0A s= et_idt(17, 0);=0A set_idt(18, 0);=0A set_idt(19, 0);=0A set_idt(0x= 80, 3);=0A=0A /* linux segment setup */=0A {=0A uint64_t *gdt_= table;=0A env->gdt.base =3D target_mmap(0, sizeof(uint64_t) * TARGET= _GDT_ENTRIES,=0A PROT_READ|PROT_WRITE,= =0A MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);= =0A env->gdt.limit =3D sizeof(uint64_t) * TARGET_GDT_ENTRIES - 1;=0A= gdt_table =3D g2h(env->gdt.base);=0A#ifdef TARGET_ABI32=0A w= rite_dt(&gdt_table[__USER_CS >> 3], 0, 0xfffff,=0A DESC_G_M= ASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |=0A (3 << DE= SC_DPL_SHIFT) | (0xa << DESC_TYPE_SHIFT));=0A#else=0A /* 64 bit code= segment */=0A write_dt(&gdt_table[__USER_CS >> 3], 0, 0xfffff,=0A = DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |=0A = DESC_L_MASK |=0A (3 << DESC_DPL_SHIFT) | (0x= a << DESC_TYPE_SHIFT));=0A#endif=0A write_dt(&gdt_table[__USER_DS >>= 3], 0, 0xfffff,=0A DESC_G_MASK | DESC_B_MASK | DESC_P_MASK= | DESC_S_MASK |=0A (3 << DESC_DPL_SHIFT) | (0x2 << DESC_TY= PE_SHIFT));=0A }=0A cpu_x86_load_seg(env, R_CS, __USER_CS);=0A cpu= _x86_load_seg(env, R_SS, __USER_DS);=0A#ifdef TARGET_ABI32=0A cpu_x86_lo= ad_seg(env, R_DS, __USER_DS);=0A cpu_x86_load_seg(env, R_ES, __USER_DS);= =0A cpu_x86_load_seg(env, R_FS, __USER_DS);=0A cpu_x86_load_seg(env, = R_GS, __USER_DS);=0A /* This hack makes Wine work... */=0A env->segs[= R_FS].selector =3D 0;=0A#else=0A cpu_x86_load_seg(env, R_DS, 0);=0A c= pu_x86_load_seg(env, R_ES, 0);=0A cpu_x86_load_seg(env, R_FS, 0);=0A = cpu_x86_load_seg(env, R_GS, 0);=0A#endif=0A#elif defined(TARGET_ARM)=0A = {=0A int i;=0A cpsr_write(env, regs->uregs[16], 0xffffffff);= =0A for(i =3D 0; i < 16; i++) {=0A env->regs[i] =3D regs-= >uregs[i];=0A }=0A }=0A#elif defined(TARGET_SPARC)=0A {=0A = int i;=0A env->pc =3D regs->pc;=0A env->npc =3D regs->npc;=0A en= v->y =3D regs->y;=0A for(i =3D 0; i < 8; i++)=0A env->gre= gs[i] =3D regs->u_regs[i];=0A for(i =3D 0; i < 8; i++)=0A = env->regwptr[i] =3D regs->u_regs[i + 8];=0A }=0A#elif defined(TARGET_PP= C)=0A {=0A int i;=0A=0A#if defined(TARGET_PPC64)=0A#if defined(TA= RGET_ABI32)=0A env->msr &=3D ~((target_ulong)1 << MSR_SF);=0A#else= =0A env->msr |=3D (target_ulong)1 << MSR_SF;=0A#endif=0A#endif=0A = env->nip =3D regs->nip;=0A for(i =3D 0; i < 32; i++) {=0A = env->gpr[i] =3D regs->gpr[i];=0A }=0A }=0A#elif defined(TAR= GET_M68K)=0A {=0A env->pc =3D regs->pc;=0A env->dregs[0] = =3D regs->d0;=0A env->dregs[1] =3D regs->d1;=0A env->dregs[2]= =3D regs->d2;=0A env->dregs[3] =3D regs->d3;=0A env->dregs[4= ] =3D regs->d4;=0A env->dregs[5] =3D regs->d5;=0A env->dregs[= 6] =3D regs->d6;=0A env->dregs[7] =3D regs->d7;=0A env->aregs= [0] =3D regs->a0;=0A env->aregs[1] =3D regs->a1;=0A env->areg= s[2] =3D regs->a2;=0A env->aregs[3] =3D regs->a3;=0A env->are= gs[4] =3D regs->a4;=0A env->aregs[5] =3D regs->a5;=0A env->ar= egs[6] =3D regs->a6;=0A env->aregs[7] =3D regs->usp;=0A env->= sr =3D regs->sr;=0A ts->sim_syscalls =3D 1;=0A }=0A#elif defined(= TARGET_MIPS)=0A {=0A int i;=0A=0A for(i =3D 0; i < 32; i++= ) {=0A env->active_tc.gpr[i] =3D regs->regs[i];=0A }=0A = env->active_tc.PC =3D regs->cp0_epc;=0A }=0A#elif defined(TARGET_S= H4)=0A {=0A int i;=0A=0A for(i =3D 0; i < 16; i++) {=0A = env->gregs[i] =3D regs->regs[i];=0A }=0A env->pc =3D= regs->pc;=0A }=0A#elif defined(TARGET_ALPHA)=0A {=0A int i;= =0A=0A for(i =3D 0; i < 28; i++) {=0A env->ir[i] =3D ((ab= i_ulong *)regs)[i];=0A }=0A env->ipr[IPR_USP] =3D regs->usp;= =0A env->ir[30] =3D regs->usp;=0A env->pc =3D regs->pc;=0A = env->unique =3D regs->unique;=0A }=0A#elif defined(TARGET_CRIS)=0A = {=0A env->regs[0] =3D regs->r0;=0A env->regs[1] =3D regs->r1;=0A= env->regs[2] =3D regs->r2;=0A env->regs[3] =3D regs->r3;=0A en= v->regs[4] =3D regs->r4;=0A env->regs[5] =3D regs->r5;=0A env->regs= [6] =3D regs->r6;=0A env->regs[7] =3D regs->r7;=0A env->regs[8] =3D= regs->r8;=0A env->regs[9] =3D regs->r9;=0A env->regs[10] =3D regs-= >r10;=0A env->regs[11] =3D regs->r11;=0A env->regs[12] =3D regs->r1= 2;=0A env->regs[13] =3D regs->r13;=0A env->regs[14] =3D info->start= _stack;=0A env->regs[15] =3D regs->acr; =0A env->pc =3D regs->e= rp;=0A }=0A#else=0A#error unsupported target CPU=0A#endif=0A=0A#if defin= ed(TARGET_ARM) || defined(TARGET_M68K)=0A ts->stack_base =3D info->start= _stack;=0A ts->heap_base =3D info->brk;=0A /* This will be filled in = on the first SYS_HEAPINFO call. */=0A ts->heap_limit =3D 0;=0A#endif=0A= =0A if (gdbstub_accept !=3D NULL) {=0A if ((*gdbstub_accept)() < = 0) {=0A return -1;=0A }=0A gdb_handlesig(env, 0);= =0A }=0A cpu_loop(env);=0A /* never exits */=0A return 0;=0A}= =0A=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00=00= =00 --VS++wcV0S1rZb1Fb--