aboutsummaryrefslogtreecommitdiff
path: root/gdb/gdbserver
diff options
context:
space:
mode:
authorStu Grossman <grossman@cygnus>1993-05-26 20:49:21 +0000
committerStu Grossman <grossman@cygnus>1993-05-26 20:49:21 +0000
commite20520b8f9ced9bd3f133ecd2f7a6b840bf371e4 (patch)
treefc9de590fdea1d1f5a4a8545fe18fcd7297bbc94 /gdb/gdbserver
parent185a1705bb2ca43708577aff4703ee6a95321b23 (diff)
downloadfsf-binutils-gdb-e20520b8f9ced9bd3f133ecd2f7a6b840bf371e4.zip
fsf-binutils-gdb-e20520b8f9ced9bd3f133ecd2f7a6b840bf371e4.tar.gz
fsf-binutils-gdb-e20520b8f9ced9bd3f133ecd2f7a6b840bf371e4.tar.bz2
* gdbserver/{remote-gutils.c remote-server.c Makefile.in
configure.in remote-inflow.c remote-utils.c}: New files to support GDB remote server. Currently only works for Lynx.
Diffstat (limited to 'gdb/gdbserver')
-rw-r--r--gdb/gdbserver/configure.in331
-rw-r--r--gdb/gdbserver/remote-gutils.c412
-rw-r--r--gdb/gdbserver/remote-inflow.c366
-rw-r--r--gdb/gdbserver/remote-server.c151
-rw-r--r--gdb/gdbserver/remote-utils.c339
5 files changed, 1599 insertions, 0 deletions
diff --git a/gdb/gdbserver/configure.in b/gdb/gdbserver/configure.in
new file mode 100644
index 0000000..707f8a5
--- /dev/null
+++ b/gdb/gdbserver/configure.in
@@ -0,0 +1,331 @@
+srcname="Remote GDB server"
+srctrigger=remote-server.c
+gdb_serial_driver=../ser-unix.c
+
+# per-host:
+
+# per-target:
+
+# Hack alert! We want this directory to be configured only for the target,
+# which is where it will be running, so we just eliminate the per-host section,
+# and make the per-target stuff setup host & host_cpu according to the target.
+
+host_cpu=$target_cpu
+host=$target
+
+# Map host cpu into the config cpu subdirectory name.
+# The default is $host_cpu.
+
+case "${host_cpu}" in
+
+c[12]) gdb_host_cpu=convex ;;
+hppa*) gdb_host_cpu=pa ;;
+i[34]86) gdb_host_cpu=i386 ;;
+m68*) gdb_host_cpu=m68k ;;
+np1) gdb_host_cpu=gould ;;
+pyramid) gdb_host_cpu=pyr ;;
+*) gdb_host_cpu=$target_cpu ;;
+
+esac
+
+# map host info into gdb names.
+
+case "${host}" in
+
+a29k-*-*) gdb_host=ultra3 ;;
+
+arm-*-*) gdb_host=arm ;;
+
+c[12]-*-*) gdb_host=convex ;;
+
+hppa*-hp-bsd*) gdb_host=hppabsd ;;
+hppa*-hp-hpux*) gdb_host=hppahpux ;;
+
+i[34]86-ncr-*) gdb_host=ncr3000 ;;
+i[34]86-sequent-*) gdb_host=symmetry ;;
+
+i[34]86-*-bsd*) gdb_host=i386bsd ;;
+i[34]86-*-lynx*) gdb_host=i386lynx ;;
+i[34]86-*-go32) gdb_host=go32
+ gdb_serial_driver=ser-go32.c
+ ;;
+i[34]86-*-linux) gdb_host=linux ;;
+i[34]86-*-mach) gdb_host=i386mach ;;
+i[34]86-*-sco3.2v4*) gdb_host=i386sco4 ;;
+i[34]86-*-sco*) gdb_host=i386sco ;;
+i[34]86-*-solaris*) gdb_host=i386sol2 ;;
+i[34]86-*-sunos*) gdb_host=sun386 ;;
+i[34]86-*-sysv3.2) gdb_host=i386v32 ;;
+i[34]86-*-sysv4*) gdb_host=i386v4 ;;
+i[34]86-*-sysv*) gdb_host=i386v ;;
+
+m680[01]0-sun-sunos3*) gdb_host=sun2os3 ;;
+m680[01]0-sun-sunos4*) gdb_host=sun2os4 ;;
+m68030-sony-*) gdb_host=news1000 ;;
+
+m68*-altos-*) gdb_host=altos ;;
+m68*-apollo*-sysv*) gdb_host=apollo68v ;;
+m68*-apollo*-bsd*) gdb_host=apollo68b ;;
+m68*-att-*) gdb_host=3b1 ;;
+m68*-cbm-sysv4*) gdb_host=amix ;;
+m68*-hp-bsd*) gdb_host=hp300bsd ;;
+m68*-hp-hpux*) gdb_host=hp300hpux ;;
+m68*-isi-*) gdb_host=isi ;;
+m68*-sony-*) gdb_host=news ;;
+m68*-sun-sunos3*) gdb_host=sun3os3 ;;
+m68*-sun-sunos4*) gdb_host=sun3os4 ;;
+m68*-sun-*) gdb_host=sun3os4 ;;
+
+m88k-motorola-*) gdb_host=delta88 ;;
+m88k-*-*) gdb_host=m88k ;;
+
+mips-dec-*) gdb_host=decstation ;;
+mips-little-*) gdb_host=littlemips ;;
+mips-sgi-irix3) gdb_host=irix3 ;;
+mips-sgi-irix4*) gdb_host=irix4 ;;
+mips-sony-*) gdb_host=bigmips ;;
+
+none-*-*) gdb_host=none ;;
+
+np1-*-*) gdb_host=np1 ;;
+
+ns32k-umax-*) gdb_host=umax ;;
+ns32k-utek-sysv) gdb_host=merlin ;;
+
+pn-*-*) gdb_host=pn ;;
+
+pyramid-*-*) gdb_host=pyramid ;;
+
+romp-*-*) gdb_host=rtbsd ;;
+
+rs6000-*-*) gdb_host=rs6000 ;;
+
+sparc-*-solaris2*) gdb_host=sun4sol2 ;;
+sparc-*-sunos4*) gdb_host=sun4os4 ;;
+sparc-*-*) gdb_host=sun4os4 ;;
+
+tahoe-*-*) gdb_host=tahoe ;;
+
+vax-*-bsd*) gdb_host=vaxbsd ;;
+vax-*-ultrix2*) gdb_host=vaxult2 ;;
+vax-*-ultrix*) gdb_host=vaxult ;;
+
+esac
+
+if [ ! -f ${srcdir}/../config/${gdb_host_cpu}/${gdb_host}.mh ]; then
+ echo '***' "GDB remote does not support host ${host}" 1>&2
+ exit 1
+fi
+
+# We really shouldn't depend on there being a space after XM_FILE= ...
+hostfile=`awk '$1 == "XM_FILE=" { print $2 }' <${srcdir}/../config/${gdb_host_cpu}/${gdb_host}.mh`
+
+# per-target:
+
+# Map target cpu into the config cpu subdirectory name.
+# The default is $target_cpu.
+
+case "${target_cpu}" in
+
+c[12]) gdb_target_cpu=convex ;;
+hppa*) gdb_target_cpu=pa ;;
+i[34]86) gdb_target_cpu=i386 ;;
+m68*) gdb_target_cpu=m68k ;;
+np1) gdb_target_cpu=gould ;;
+pn) gdb_target_cpu=gould ;;
+pyramid) gdb_target_cpu=pyr ;;
+sparc*) gdb_target_cpu=sparc ;;
+*) gdb_target_cpu=$target_cpu ;;
+
+esac
+
+# map target info into gdb names.
+
+case "${target}" in
+
+a29k-*-aout) gdb_target=a29k ;;
+a29k-*-coff) gdb_target=a29k ;;
+a29k-*-elf) gdb_target=a29k ;;
+a29k-*-ebmon) gdb_target=a29k ;;
+a29k-*-kern) gdb_target=a29k-kern ;;
+a29k-*-none) gdb_target=a29k ;;
+a29k-*-sym1) gdb_target=ultra3 ;;
+a29k-*-udi) gdb_target=a29k-udi ;;
+
+arm-*-*) gdb_target=arm ;;
+
+c1-*-*) gdb_target=convex ;;
+c2-*-*) gdb_target=convex ;;
+
+h8300-*-*) gdb_target=h8300hms ;;
+h8500-*-*) gdb_target=h8500hms ;;
+
+sh-*-*) gdb_target=sh ;;
+
+hppa*-*-bsd*) gdb_target=hppabsd ;;
+hppa*-*-hpux*) gdb_target=hppahpux ;;
+
+i[34]86-sequent-*) gdb_target=symmetry ;;
+i[34]86-ncr-*) gdb_target=ncr3000 ;;
+
+i[34]86-*-aout) gdb_target=i386aout ;;
+i[34]86-*-coff) gdb_target=i386v ;;
+i[34]86-*-elf) gdb_target=i386v ;;
+
+i[34]86-*-bsd*) gdb_target=i386bsd ;;
+i[34]86-*-lynx*) gdb_target=i386lynx ;;
+i[34]86-*-go32) gdb_target=i386aout ;;
+i[34]86-*-solaris*) gdb_target=i386sol2 ;;
+i[34]86-*-sunos*) gdb_target=sun386 ;;
+i[34]86-*-sysv4*) gdb_target=i386v4 ;;
+i[34]86-*-sco*) gdb_target=i386v ;;
+i[34]86-*-sysv*) gdb_target=i386v ;;
+i[34]86-*-linux) gdb_target=linux ;;
+
+i960-*-bout) gdb_target=vxworks960 ;;
+i960-*-coff) gdb_target=nindy960 ;;
+i960-*-elf) gdb_target=nindy960 ;;
+
+i960-*-nindy) gdb_target=nindy960 ;;
+i960-*-vxworks) gdb_target=vxworks960 ;;
+
+m68000-*-aout) gdb_target=m68k-nofp ;;
+m68000-*-coff) gdb_target=m68k-nofp ;;
+m68000-*-elf) gdb_target=m68k-nofp ;;
+m68000-*-sunos3*) gdb_target=sun2os3 ;;
+m68000-*-sunos4*) gdb_target=sun2os4 ;;
+
+m68*-cbm-sysv4*) gdb_target=amix ;;
+m68*-hp-bsd*) gdb_target=hp300bsd ;;
+m68*-hp-hpux*) gdb_target=hp300hpux ;;
+
+m68*-altos-*) gdb_target=altos ;;
+m68*-att-*) gdb_target=3b1 ;;
+m68*-ericsson-*) gdb_target=es1800 ;;
+m68*-isi-*) gdb_target=isi ;;
+m68*-netx-*) gdb_target=vxworks68 ;;
+m68*-sony-*) gdb_target=news ;;
+m68*-tandem-*) gdb_target=st2000 ;;
+
+m68*-*-aout) gdb_target=m68k-fp ;;
+m68*-*-coff) gdb_target=m68k-fp ;;
+m68*-*-elf) gdb_target=m68k-fp ;;
+m68*-*-os68k) gdb_target=os68k ;;
+m68*-*-sunos3*) gdb_target=sun3os3 ;;
+m68*-*-sunos4*) gdb_target=sun3os4 ;;
+m68*-*-vxworks*) gdb_target=vxworks68 ;;
+
+m88k-motorola-*) gdb_target=delta88 ;;
+m88k-*-*) gdb_target=m88k ;;
+
+mips-big-*) gdb_target=bigmips ;;
+mips-dec-*) gdb_target=decstation ;;
+mips-idt-ecoff) gdb_target=idt ;;
+mips-little-*) gdb_target=littlemips ;;
+mips-sgi-*) gdb_target=irix3 ;;
+mips-sony-*) gdb_target=bigmips ;;
+
+none-*-*) gdb_target=none ;;
+
+np1-*-*) gdb_target=np1 ;;
+
+ns32k-utek-sysv) gdb_target=merlin ;;
+ns32k-utek-*) gdb_target=umax ;;
+
+pn-*-*) gdb_target=pn ;;
+
+pyramid-*-*) gdb_target=pyramid ;;
+
+rs6000-*-*) gdb_target=rs6000 ;;
+
+sparc-*-aout) gdb_target=sparc-em ;;
+sparc-*-coff) gdb_target=sparc-em ;;
+sparc-*-elf) gdb_target=sparc-em ;;
+sparc-*-solaris2*) gdb_target=sun4sol2 ;;
+sparc-*-sunos4*) gdb_target=sun4os4 ;;
+sparc-*-vxworks*) gdb_target=sparc-em ;;
+sparc-*-*) gdb_target=sun4os4 ;;
+sparclite*-*-*) gdb_target=sparclite ;;
+
+tahoe-*-*) gdb_target=tahoe ;;
+vax-*-*) gdb_target=vax ;;
+
+z8k-*-sim) gdb_target=z8ksim ;;
+esac
+
+if [ ! -f ${srcdir}/../config/${gdb_target_cpu}/${gdb_target}.mt ]; then
+ echo '***' "GDB remote does not support target ${target}" 1>&2
+ exit 1
+fi
+
+if [ -z "${removing}" ] ; then
+ cat ${srcdir}/../config/${gdb_host_cpu}/${gdb_host}.mh ${srcdir}/../config/${gdb_target_cpu}/${gdb_target}.mt | awk '$1 == "#msg" {
+ print substr($0,6)}'
+fi
+
+# We really shouldn't depend on there being a space after TM_FILE= ...
+targetfile=`awk '$1 == "TM_FILE=" { print $2 }' <${srcdir}/../config/${gdb_target_cpu}/${gdb_target}.mt`
+
+if [ "${target}" = "${host}" ] ; then
+ nativefile=`awk '$1 == "NAT_FILE=" { print $2 }' <${srcdir}/../config/${gdb_host_cpu}/${gdb_host}.mh`
+fi
+
+host_makefile_frag=../config/${gdb_host_cpu}/${gdb_host}.mh
+target_makefile_frag=../config/${gdb_target_cpu}/${gdb_target}.mt
+
+# If hostfile (XM_FILE) and/or targetfile (TM_FILE) and/or nativefile
+# (NAT_FILE) is not set in the ?config/* file, we don't make the
+# corresponding links. But we have to remove the xm.h files and tm.h
+# files anyway, e.g. when switching from "configure host" to
+# "configure none".
+
+files=
+links=
+rm -f xm.h
+rm -f ser-hardwire.c
+if [ "${hostfile}" != "" ]; then
+ if [ -f ${srcdir}/../config/${hostfile} ]; then
+ files="${files} ../config/${hostfile}"
+ else
+ files="${files} ../config/${gdb_host_cpu}/${hostfile}"
+ fi
+ links="${links} xm.h"
+
+# files="${files} ${gdb_serial_driver}"
+# links="${links} ser-hardwire.c"
+fi
+rm -f tm.h
+if [ "${targetfile}" != "" ]; then
+ if [ -f ${srcdir}/../config/${targetfile} ]; then
+ files="${files} ../config/${targetfile}"
+ else
+ files="${files} ../config/${gdb_target_cpu}/${targetfile}"
+ fi
+ links="${links} tm.h"
+fi
+rm -f nm.h
+if [ "${nativefile}" != "" ]; then
+ if [ -f ${srcdir}/../config/${nativefile} ]; then
+ files="${files} ../config/${nativefile}"
+ else
+ files="${files} ../config/${gdb_host_cpu}/${nativefile}"
+ fi
+ links="${links} nm.h"
+# temporary scaffolding until all hosts have the host/target/native
+# split in place.
+else
+ files="${files} ../config/nm-trash.h"
+ links="${links} nm.h"
+fi
+
+if [ ${target_cpu} = "sparclite" ]; then
+ configdirs="${configdirs} sparclite"
+fi
+
+# post-target:
+
+if [ "${nativefile}" = "" ] ; then
+ sed -e '/^NATDEPFILES= /s//# NATDEPFILES= /' \
+ < Makefile > Makefile.tem
+ mv -f Makefile.tem Makefile
+fi
diff --git a/gdb/gdbserver/remote-gutils.c b/gdb/gdbserver/remote-gutils.c
new file mode 100644
index 0000000..9db96415
--- /dev/null
+++ b/gdb/gdbserver/remote-gutils.c
@@ -0,0 +1,412 @@
+/* General utility routines for the remote server for GDB.
+ Copyright (C) 1986, 1989, 1993 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+#include <sys/ioctl.h>
+#include "defs.h"
+#include <setjmp.h>
+
+void error ();
+void fatal ();
+
+/* Chain of cleanup actions established with make_cleanup,
+ to be executed if an error happens. */
+
+static struct cleanup *cleanup_chain;
+
+/* Nonzero means a quit has been requested. */
+
+int quit_flag;
+
+/* Nonzero means quit immediately if Control-C is typed now,
+ rather than waiting until QUIT is executed. */
+
+int immediate_quit;
+
+/* Add a new cleanup to the cleanup_chain,
+ and return the previous chain pointer
+ to be passed later to do_cleanups or discard_cleanups.
+ Args are FUNCTION to clean up with, and ARG to pass to it. */
+
+struct cleanup *
+make_cleanup (function, arg)
+ void (*function) ();
+ PTR arg;
+{
+ register struct cleanup *new
+ = (struct cleanup *) xmalloc (sizeof (struct cleanup));
+ register struct cleanup *old_chain = cleanup_chain;
+
+ new->next = cleanup_chain;
+ new->function = function;
+ new->arg = arg;
+ cleanup_chain = new;
+
+ return old_chain;
+}
+
+/* Discard cleanups and do the actions they describe
+ until we get back to the point OLD_CHAIN in the cleanup_chain. */
+
+void
+do_cleanups (old_chain)
+ register struct cleanup *old_chain;
+{
+ register struct cleanup *ptr;
+ while ((ptr = cleanup_chain) != old_chain)
+ {
+ (*ptr->function) (ptr->arg);
+ cleanup_chain = ptr->next;
+ free (ptr);
+ }
+}
+
+/* Discard cleanups, not doing the actions they describe,
+ until we get back to the point OLD_CHAIN in the cleanup_chain. */
+
+void
+discard_cleanups (old_chain)
+ register struct cleanup *old_chain;
+{
+ register struct cleanup *ptr;
+ while ((ptr = cleanup_chain) != old_chain)
+ {
+ cleanup_chain = ptr->next;
+ free (ptr);
+ }
+}
+
+/* This function is useful for cleanups.
+ Do
+
+ foo = xmalloc (...);
+ old_chain = make_cleanup (free_current_contents, &foo);
+
+ to arrange to free the object thus allocated. */
+
+void
+free_current_contents (location)
+ char **location;
+{
+ free (*location);
+}
+
+/* Generally useful subroutines used throughout the program. */
+
+/* Like malloc but get error if no storage available. */
+
+PTR
+xmalloc (size)
+ long size;
+{
+ register char *val = (char *) malloc (size);
+ if (!val)
+ fatal ("virtual memory exhausted.", 0);
+ return val;
+}
+
+/* Like realloc but get error if no storage available. */
+
+PTR
+xrealloc (ptr, size)
+ PTR ptr;
+ long size;
+{
+ register char *val = (char *) realloc (ptr, size);
+ if (!val)
+ fatal ("virtual memory exhausted.", 0);
+ return val;
+}
+
+/* Print the system error message for errno, and also mention STRING
+ as the file name for which the error was encountered.
+ Then return to command level. */
+
+void
+perror_with_name (string)
+ char *string;
+{
+ extern int sys_nerr;
+ extern char *sys_errlist[];
+ extern int errno;
+ char *err;
+ char *combined;
+
+ if (errno < sys_nerr)
+ err = sys_errlist[errno];
+ else
+ err = "unknown error";
+
+ combined = (char *) alloca (strlen (err) + strlen (string) + 3);
+ strcpy (combined, string);
+ strcat (combined, ": ");
+ strcat (combined, err);
+
+ error ("%s.", combined);
+}
+
+/* Print the system error message for ERRCODE, and also mention STRING
+ as the file name for which the error was encountered. */
+
+void
+print_sys_errmsg (string, errcode)
+ char *string;
+ int errcode;
+{
+ extern int sys_nerr;
+ extern char *sys_errlist[];
+ char *err;
+ char *combined;
+
+ if (errcode < sys_nerr)
+ err = sys_errlist[errcode];
+ else
+ err = "unknown error";
+
+ combined = (char *) alloca (strlen (err) + strlen (string) + 3);
+ strcpy (combined, string);
+ strcat (combined, ": ");
+ strcat (combined, err);
+
+ printf ("%s.\n", combined);
+}
+
+void
+quit ()
+{
+ fflush (stdout);
+ ioctl (fileno (stdout), TIOCFLUSH, 0);
+ error ("Quit");
+}
+
+/* Control C comes here */
+
+void
+request_quit (ignored)
+ int ignored;
+{
+ quit_flag = 1;
+ if (immediate_quit)
+ quit ();
+}
+
+/* Print an error message and return to command level.
+ STRING is the error message, used as a fprintf string,
+ and ARG is passed as an argument to it. */
+
+NORETURN void
+error (string, arg1, arg2, arg3)
+ char *string;
+ int arg1, arg2, arg3;
+{
+ extern jmp_buf toplevel;
+
+ fflush (stdout);
+ fprintf (stderr, string, arg1, arg2, arg3);
+ fprintf (stderr, "\n");
+ longjmp(toplevel, 1);
+}
+
+/* Print an error message and exit reporting failure.
+ This is for a error that we cannot continue from.
+ STRING and ARG are passed to fprintf. */
+
+void
+fatal (string, arg)
+ char *string;
+ int arg;
+{
+ fprintf (stderr, "gdb: ");
+ fprintf (stderr, string, arg);
+ fprintf (stderr, "\n");
+ exit (1);
+}
+
+/* Make a copy of the string at PTR with SIZE characters
+ (and add a null character at the end in the copy).
+ Uses malloc to get the space. Returns the address of the copy. */
+
+char *
+savestring (ptr, size)
+ const char *ptr;
+ int size;
+{
+ register char *p = (char *) xmalloc (size + 1);
+ bcopy (ptr, p, size);
+ p[size] = 0;
+ return p;
+}
+
+void
+print_spaces (n, file)
+ register int n;
+ register FILE *file;
+{
+ while (n-- > 0)
+ fputc (' ', file);
+}
+
+/* Ask user a y-or-n question and return 1 iff answer is yes.
+ Takes three args which are given to printf to print the question.
+ The first, a control string, should end in "? ".
+ It should not say how to answer, because we do that. */
+
+int
+query (ctlstr, arg1, arg2)
+ char *ctlstr;
+{
+ register int answer;
+
+ /* Automatically answer "yes" if input is not from a terminal. */
+ /***********if (!input_from_terminal_p ())
+ return 1; *************************/
+
+ while (1)
+ {
+ printf (ctlstr, arg1, arg2);
+ printf ("(y or n) ");
+ fflush (stdout);
+ answer = fgetc (stdin);
+ clearerr (stdin); /* in case of C-d */
+ if (answer != '\n')
+ while (fgetc (stdin) != '\n')
+ clearerr (stdin);
+ if (answer >= 'a')
+ answer -= 040;
+ if (answer == 'Y')
+ return 1;
+ if (answer == 'N')
+ return 0;
+ printf ("Please answer y or n.\n");
+ }
+}
+
+/* Parse a C escape sequence. STRING_PTR points to a variable
+ containing a pointer to the string to parse. That pointer
+ is updated past the characters we use. The value of the
+ escape sequence is returned.
+
+ A negative value means the sequence \ newline was seen,
+ which is supposed to be equivalent to nothing at all.
+
+ If \ is followed by a null character, we return a negative
+ value and leave the string pointer pointing at the null character.
+
+ If \ is followed by 000, we return 0 and leave the string pointer
+ after the zeros. A value of 0 does not mean end of string. */
+
+int
+parse_escape (string_ptr)
+ char **string_ptr;
+{
+ register int c = *(*string_ptr)++;
+ switch (c)
+ {
+ case 'a':
+ return '\a';
+ case 'b':
+ return '\b';
+ case 'e':
+ return 033;
+ case 'f':
+ return '\f';
+ case 'n':
+ return '\n';
+ case 'r':
+ return '\r';
+ case 't':
+ return '\t';
+ case 'v':
+ return '\v';
+ case '\n':
+ return -2;
+ case 0:
+ (*string_ptr)--;
+ return 0;
+ case '^':
+ c = *(*string_ptr)++;
+ if (c == '\\')
+ c = parse_escape (string_ptr);
+ if (c == '?')
+ return 0177;
+ return (c & 0200) | (c & 037);
+
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ {
+ register int i = c - '0';
+ register int count = 0;
+ while (++count < 3)
+ {
+ if ((c = *(*string_ptr)++) >= '0' && c <= '7')
+ {
+ i *= 8;
+ i += c - '0';
+ }
+ else
+ {
+ (*string_ptr)--;
+ break;
+ }
+ }
+ return i;
+ }
+ default:
+ return c;
+ }
+}
+
+void
+printchar (ch, stream)
+ unsigned char ch;
+ FILE *stream;
+{
+ register int c = ch;
+ if (c < 040 || c >= 0177)
+ {
+ if (c == '\n')
+ fprintf (stream, "\\n");
+ else if (c == '\b')
+ fprintf (stream, "\\b");
+ else if (c == '\t')
+ fprintf (stream, "\\t");
+ else if (c == '\f')
+ fprintf (stream, "\\f");
+ else if (c == '\r')
+ fprintf (stream, "\\r");
+ else if (c == 033)
+ fprintf (stream, "\\e");
+ else if (c == '\a')
+ fprintf (stream, "\\a");
+ else
+ fprintf (stream, "\\%03o", c);
+ }
+ else
+ {
+ if (c == '\\' || c == '"' || c == '\'')
+ fputc ('\\', stream);
+ fputc (c, stream);
+ }
+}
diff --git a/gdb/gdbserver/remote-inflow.c b/gdb/gdbserver/remote-inflow.c
new file mode 100644
index 0000000..f093d83
--- /dev/null
+++ b/gdb/gdbserver/remote-inflow.c
@@ -0,0 +1,366 @@
+/* Low level interface to ptrace, for the remote server for GDB.
+ Copyright (C) 1986, 1987, 1993 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "defs.h"
+#include "frame.h"
+#include "inferior.h"
+/***************************
+#include "initialize.h"
+****************************/
+
+#include <stdio.h>
+#include <sys/param.h>
+#include <sys/dir.h>
+/*#include <sys/user.h>*/
+#define LYNXOS
+#include <sys/mem.h>
+#include <sys/signal.h>
+#include <sys/file.h>
+#include <sys/kernel.h>
+#include <sys/itimer.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/proc.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+#include <sgtty.h>
+#include <fcntl.h>
+#include "/usr/include/wait.h"
+
+/***************Begin MY defs*********************/
+int quit_flag = 0;
+char registers[REGISTER_BYTES];
+
+/* Index within `registers' of the first byte of the space for
+ register N. */
+
+
+char buf2[MAX_REGISTER_RAW_SIZE];
+/***************End MY defs*********************/
+
+#include <sys/ptrace.h>
+/*#include <machine/reg.h>*/
+
+extern char **environ;
+extern int errno;
+extern int inferior_pid;
+void error (), quit (), perror_with_name ();
+int query ();
+
+/* Start an inferior process and returns its pid.
+ ALLARGS is a vector of program-name and args.
+ ENV is the environment vector to pass. */
+
+int
+create_inferior (allargs, env)
+ char **allargs;
+ char **env;
+{
+ int pid;
+ extern int sys_nerr;
+ extern char *sys_errlist[];
+ extern int errno;
+ char status;
+ char execbuf[1024];
+
+ /* exec is said to fail if the executable is open. */
+ /****************close_exec_file ();*****************/
+
+ sprintf (execbuf, "exec %s", allargs);
+
+ pid = fork ();
+ if (pid < 0)
+ perror_with_name ("fork");
+
+ if (pid == 0)
+ {
+ /* Run inferior in a separate process group. */
+ setpgrp (getpid (), getpid ());
+
+ errno = 0;
+ ptrace (PTRACE_TRACEME);
+
+ execle ("/bin/sh", "sh", "-c", execbuf, 0, env);
+
+ fprintf (stderr, "Cannot exec /bin/sh: %s.\n",
+ errno < sys_nerr ? sys_errlist[errno] : "unknown error");
+ fflush (stderr);
+ _exit (0177);
+ }
+
+ return pid;
+}
+
+/* Kill the inferior process. Make us have no inferior. */
+
+void
+kill_inferior ()
+{
+ if (inferior_pid == 0)
+ return;
+ ptrace (8, inferior_pid, 0, 0);
+ wait (0);
+ /*************inferior_died ();****VK**************/
+}
+
+/* Wait for process, returns status */
+
+unsigned char
+mywait (status)
+ char *status;
+{
+ int pid;
+ union wait w;
+
+ pid = wait (&w);
+ if (pid != PIDGET(inferior_pid))
+ perror_with_name ("wait");
+
+ inferior_pid = BUILDPID (inferior_pid, w.w_tid);
+
+ if (WIFEXITED (w))
+ {
+ fprintf (stderr, "\nChild exited with retcode = %x \n", WEXITSTATUS (w));
+ *status = 'E';
+ return ((unsigned char) WEXITSTATUS (w));
+ }
+ else if (!WIFSTOPPED (w))
+ {
+ fprintf (stderr, "\nChild terminated with signal = %x \n", WTERMSIG (w));
+ *status = 'T';
+ return ((unsigned char) WTERMSIG (w));
+ }
+
+ fetch_inferior_registers (0);
+
+ *status = 'S';
+ return ((unsigned char) WSTOPSIG (w));
+}
+
+/* Resume execution of the inferior process.
+ If STEP is nonzero, single-step it.
+ If SIGNAL is nonzero, give it that signal. */
+
+void
+myresume (step, signal)
+ int step;
+ int signal;
+{
+ errno = 0;
+ ptrace (step ? PTRACE_SINGLESTEP : PTRACE_CONT, inferior_pid, 1, signal);
+ if (errno)
+ perror_with_name ("ptrace");
+}
+
+#undef offsetof
+#define offsetof(TYPE, MEMBER) ((unsigned long) &((TYPE *)0)->MEMBER)
+
+static struct econtext *
+lynx_registers_addr()
+{
+ st_t *stblock;
+ int ecpoff = offsetof(st_t, ecp);
+ CORE_ADDR ecp;
+
+ errno = 0;
+ stblock = (st_t *) ptrace (PTRACE_THREADUSER, inferior_pid,
+ (PTRACE_ARG3_TYPE)0, 0);
+ if (errno)
+ perror_with_name ("PTRACE_THREADUSER");
+
+ ecp = (CORE_ADDR) ptrace (PTRACE_PEEKTHREAD, inferior_pid,
+ (PTRACE_ARG3_TYPE)ecpoff, 0);
+ ecp -= (CORE_ADDR)stblock;
+ if (errno)
+ perror_with_name ("lynx_registers_addr(PTRACE_PEEKTHREAD)");
+
+ return (struct econtext *)ecp;
+}
+
+static struct econtext *ecp;
+
+/* Mapping between GDB register #s and offsets into econtext. Must be
+ consistent with REGISTER_NAMES macro in tm-i386v.h. */
+
+#define X(ENTRY)(offsetof(struct econtext, ENTRY) / 4)
+static int regmap[] = {
+ X(eax),
+ X(ecx),
+ X(edx),
+ X(ebx),
+ X(esp),
+ X(ebp),
+ X(esi),
+ X(edi),
+ X(eip),
+ X(flags), /* ps */
+ X(cs),
+ X(ss),
+ X(ds),
+ X(es),
+ X(ecode), /* Lynx doesn't give us either fs or gs, so */
+ X(fault) /* we just substitute these two in the hopes
+ that they are useful. */
+ };
+
+/* Fetch one or more registers from the inferior. REGNO == -1 to get
+ them all. We actually fetch more than requested, when convenient,
+ marking them as valid so we won't fetch them again. */
+
+void
+fetch_inferior_registers (ignored)
+ int ignored;
+{
+ int regno;
+ unsigned long reg;
+ struct econtext *ecp;
+
+ ecp = lynx_registers_addr();
+
+ for (regno = 0; regno < NUM_REGS; regno++)
+ {
+ errno = 0;
+ reg = ptrace (PTRACE_PEEKTHREAD, inferior_pid,
+ (PTRACE_ARG3_TYPE) (&ecp->fault + regmap[regno]), 0);
+ if (errno)
+ perror_with_name ("fetch_inferior_registers(PTRACE_PEEKTHREAD)");
+
+ *(unsigned long *)&registers[REGISTER_BYTE (regno)] = reg;
+ }
+}
+
+/* Store our register values back into the inferior.
+ If REGNO is -1, do this for all registers.
+ Otherwise, REGNO specifies which register (so we can save time). */
+
+void
+store_inferior_registers (ignored)
+ int ignored;
+{
+ int regno;
+ unsigned long reg;
+ struct econtext *ecp;
+
+ ecp = lynx_registers_addr();
+
+ for (regno = 0; regno < NUM_REGS; regno++)
+ {
+ reg = *(unsigned long *)&registers[REGISTER_BYTE (regno)];
+
+ errno = 0;
+ ptrace (PTRACE_POKEUSER, inferior_pid,
+ (PTRACE_ARG3_TYPE) (&ecp->fault + regmap[regno]), reg);
+ if (errno)
+ perror_with_name ("PTRACE_POKEUSER");
+ }
+}
+
+/* NOTE! I tried using PTRACE_READDATA, etc., to read and write memory
+ in the NEW_SUN_PTRACE case.
+ It ought to be straightforward. But it appears that writing did
+ not write the data that I specified. I cannot understand where
+ it got the data that it actually did write. */
+
+/* Copy LEN bytes from inferior's memory starting at MEMADDR
+ to debugger memory starting at MYADDR. */
+
+read_inferior_memory (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ register int i;
+ /* Round starting address down to longword boundary. */
+ register CORE_ADDR addr = memaddr & -sizeof (int);
+ /* Round ending address up; get number of longwords that makes. */
+ register int count
+ = (((memaddr + len) - addr) + sizeof (int) - 1) / sizeof (int);
+ /* Allocate buffer of that many longwords. */
+ register int *buffer = (int *) alloca (count * sizeof (int));
+
+ /* Read all the longwords */
+ for (i = 0; i < count; i++, addr += sizeof (int))
+ {
+ buffer[i] = ptrace (1, inferior_pid, addr, 0);
+ }
+
+ /* Copy appropriate bytes out of the buffer. */
+ bcopy ((char *) buffer + (memaddr & (sizeof (int) - 1)), myaddr, len);
+}
+
+/* Copy LEN bytes of data from debugger memory at MYADDR
+ to inferior's memory at MEMADDR.
+ On failure (cannot write the inferior)
+ returns the value of errno. */
+
+int
+write_inferior_memory (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ register int i;
+ /* Round starting address down to longword boundary. */
+ register CORE_ADDR addr = memaddr & -sizeof (int);
+ /* Round ending address up; get number of longwords that makes. */
+ register int count
+ = (((memaddr + len) - addr) + sizeof (int) - 1) / sizeof (int);
+ /* Allocate buffer of that many longwords. */
+ register int *buffer = (int *) alloca (count * sizeof (int));
+ extern int errno;
+
+ /* Fill start and end extra bytes of buffer with existing memory data. */
+
+ buffer[0] = ptrace (1, inferior_pid, addr, 0);
+
+ if (count > 1)
+ {
+ buffer[count - 1]
+ = ptrace (1, inferior_pid,
+ addr + (count - 1) * sizeof (int), 0);
+ }
+
+ /* Copy data to be written over corresponding part of buffer */
+
+ bcopy (myaddr, (char *) buffer + (memaddr & (sizeof (int) - 1)), len);
+
+ /* Write the entire buffer. */
+
+ for (i = 0; i < count; i++, addr += sizeof (int))
+ {
+ errno = 0;
+ ptrace (4, inferior_pid, addr, buffer[i]);
+ if (errno)
+ return errno;
+ }
+
+ return 0;
+}
+
+void
+initialize ()
+{
+ inferior_pid = 0;
+}
+
+int
+have_inferior_p ()
+{
+ return inferior_pid != 0;
+}
diff --git a/gdb/gdbserver/remote-server.c b/gdb/gdbserver/remote-server.c
new file mode 100644
index 0000000..6a53390
--- /dev/null
+++ b/gdb/gdbserver/remote-server.c
@@ -0,0 +1,151 @@
+/* Main code for remote server for GDB.
+ Copyright (C) 1989, 1993 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "defs.h"
+#include <setjmp.h>
+#include <signal.h>
+
+void read_inferior_memory ();
+unsigned char mywait ();
+void myresume();
+void initialize ();
+int create_inferior ();
+
+extern char registers[];
+int inferior_pid;
+extern char **environ;
+
+/* Descriptor for I/O to remote machine. */
+int remote_desc;
+int kiodebug = 0;
+int remote_debugging;
+
+void remote_send ();
+void putpkt ();
+void getpkt ();
+void remote_open ();
+void write_ok ();
+void write_enn ();
+void convert_ascii_to_int ();
+void convert_int_to_ascii ();
+void prepare_resume_reply ();
+void decode_m_packet ();
+void decode_M_packet ();
+jmp_buf toplevel;
+
+main (argc, argv)
+ int argc;
+ char *argv[];
+{
+ char ch, status, own_buf[2000], mem_buf[2000];
+ int i = 0;
+ unsigned char signal;
+ unsigned int mem_addr, len;
+ char argvec[1024];
+
+ if (setjmp(toplevel))
+ {
+ fprintf(stderr, "Exiting\n");
+ exit(1);
+ }
+
+ if (argc < 3)
+ error("Usage: gdbserver tty prog [args ...]");
+
+ initialize ();
+ remote_open (argv[1], 0);
+
+ argvec[0] = '\000';
+ for (i = 2; i < argc; i++)
+ strcat(argvec, argv[i]);
+
+ inferior_pid = create_inferior (argvec, environ);
+ fprintf (stderr, "Process %s created; pid = %d\n", argv[1], inferior_pid);
+
+ signal = mywait (&status); /* Wait till we are at 1st instr in shell */
+ if (status != 'S' || signal != SIGTRAP)
+ error ("Bad status from shell\n");
+ myresume (0, 0); /* Start up the shell */
+ signal = mywait (&status); /* Wait for program to start */
+
+ /* We are now stopped at the first instruction of the target process */
+
+ setjmp(toplevel);
+ do
+ {
+ getpkt (own_buf);
+ i = 0;
+ ch = own_buf[i++];
+ switch (ch)
+ {
+ case '?':
+ prepare_resume_reply (own_buf, status, signal);
+ break;
+ case 'g':
+ convert_int_to_ascii (registers, own_buf, REGISTER_BYTES);
+ break;
+ case 'G':
+ convert_ascii_to_int (&own_buf[1], registers, REGISTER_BYTES);
+ store_inferior_registers (-1);
+ write_ok (own_buf);
+ break;
+ case 'm':
+ decode_m_packet (&own_buf[1], &mem_addr, &len);
+ read_inferior_memory (mem_addr, mem_buf, len);
+ convert_int_to_ascii (mem_buf, own_buf, len);
+ break;
+ case 'M':
+ decode_M_packet (&own_buf[1], &mem_addr, &len, mem_buf);
+ if (write_inferior_memory (mem_addr, mem_buf, len) == 0)
+ write_ok (own_buf);
+ else
+ write_enn (own_buf);
+ break;
+ case 'c':
+ myresume (0, 0);
+ signal = mywait (&status);
+ prepare_resume_reply (own_buf, status, signal);
+ break;
+ case 's':
+ myresume (1, 0);
+ signal = mywait (&status);
+ prepare_resume_reply (own_buf, status, signal);
+ break;
+ case 'k':
+ kill_inferior ();
+ sprintf (own_buf, "q");
+ putpkt (own_buf);
+ fprintf (stderr, "Obtained kill request...terminating\n");
+ close (remote_desc);
+ exit (0);
+ default:
+ printf ("\nUnknown option chosen by master\n");
+ write_enn (own_buf);
+ break;
+ }
+
+ putpkt (own_buf);
+ }
+ while (1);
+
+ close (remote_desc);
+ /** now get out of here**/
+ fprintf (stderr, "Finished reading data from serial link - Bye!\n");
+ exit (0);
+}
diff --git a/gdb/gdbserver/remote-utils.c b/gdb/gdbserver/remote-utils.c
new file mode 100644
index 0000000..2781ac5
--- /dev/null
+++ b/gdb/gdbserver/remote-utils.c
@@ -0,0 +1,339 @@
+/* Remote utility routines for the remote server for GDB.
+ Copyright (C) 1986, 1989, 1993 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "defs.h"
+#include <stdio.h>
+#include <signal.h>
+#include <sys/wait.h>
+#include <sys/ioctl.h>
+#include <a.out.h>
+#include <sys/file.h>
+#include <sgtty.h>
+
+extern int remote_desc;
+extern int remote_debugging;
+extern int kiodebug;
+
+void remote_open ();
+void remote_send ();
+void putpkt ();
+void getpkt ();
+
+void write_ok ();
+void write_enn ();
+void convert_ascii_to_int ();
+void convert_int_to_ascii ();
+void prepare_resume_reply ();
+
+/* Open a connection to a remote debugger.
+ NAME is the filename used for communication. */
+
+void
+remote_open (name, from_tty)
+ char *name;
+ int from_tty;
+{
+ struct sgttyb sg;
+
+ remote_debugging = 0;
+
+ remote_desc = open (name, O_RDWR);
+ if (remote_desc < 0)
+ perror_with_name ("Could not open remote device");
+
+ ioctl (remote_desc, TIOCGETP, &sg);
+ sg.sg_flags = RAW;
+ ioctl (remote_desc, TIOCSETP, &sg);
+
+ fprintf (stderr, "Remote debugging using %s\n", name);
+ remote_debugging = 1;
+}
+
+/* Convert hex digit A to a number. */
+
+static int
+fromhex (a)
+ int a;
+{
+ if (a >= '0' && a <= '9')
+ return a - '0';
+ else if (a >= 'a' && a <= 'f')
+ return a - 'a' + 10;
+ else
+ error ("Reply contains invalid hex digit");
+}
+
+/* Convert number NIB to a hex digit. */
+
+static int
+tohex (nib)
+ int nib;
+{
+ if (nib < 10)
+ return '0' + nib;
+ else
+ return 'a' + nib - 10;
+}
+
+/* Send the command in BUF to the remote machine,
+ and read the reply into BUF.
+ Report an error if we get an error reply. */
+
+void
+remote_send (buf)
+ char *buf;
+{
+ putpkt (buf);
+ getpkt (buf);
+
+ if (buf[0] == 'E')
+ error ("Remote failure reply: E");
+}
+
+/* Send a packet to the remote machine, with error checking.
+ The data of the packet is in BUF. */
+
+void
+putpkt (buf)
+ char *buf;
+{
+ int i;
+ unsigned char csum = 0;
+ char buf2[2000];
+ char buf3[1];
+ int cnt = strlen (buf);
+ char *p;
+
+ /* Copy the packet into buffer BUF2, encapsulating it
+ and giving it a checksum. */
+
+ p = buf2;
+ *p++ = '$';
+
+ for (i = 0; i < cnt; i++)
+ {
+ csum += buf[i];
+ *p++ = buf[i];
+ }
+ *p++ = '#';
+ *p++ = tohex ((csum >> 4) & 0xf);
+ *p++ = tohex (csum & 0xf);
+
+ /* Send it over and over until we get a positive ack. */
+
+ do
+ {
+ write (remote_desc, buf2, p - buf2);
+ read (remote_desc, buf3, 1);
+ }
+ while (buf3[0] != '+');
+}
+
+static int
+readchar ()
+{
+ char buf[1];
+ while (read (remote_desc, buf, 1) != 1);
+ return buf[0] & 0x7f;
+}
+
+/* Read a packet from the remote machine, with error checking,
+ and store it in BUF. */
+
+void
+getpkt (buf)
+ char *buf;
+{
+ char *bp;
+ unsigned char csum, c, c1, c2;
+ extern kiodebug;
+
+ while (1)
+ {
+ csum = 0;
+ while ((c = readchar ()) != '$');
+
+ bp = buf;
+ while (1)
+ {
+ c = readchar ();
+ if (c == '#')
+ break;
+ *bp++ = c;
+ csum += c;
+ }
+ *bp = 0;
+
+ c1 = fromhex (readchar ());
+ c2 = fromhex (readchar ());
+ if (csum == (c1 << 4) + c2)
+ break;
+
+ fprintf (stderr, "Bad checksum, sentsum=0x%x, csum=0x%x, buf=%s\n",
+ (c1 << 4) + c2, csum, buf);
+ write (remote_desc, "-", 1);
+ }
+
+ write (remote_desc, "+", 1);
+}
+
+void
+write_ok (buf)
+ char *buf;
+{
+ buf[0] = 'O';
+ buf[1] = 'k';
+ buf[2] = '\0';
+}
+
+void
+write_enn (buf)
+ char *buf;
+{
+ buf[0] = 'E';
+ buf[1] = 'N';
+ buf[2] = 'N';
+ buf[3] = '\0';
+}
+
+void
+convert_int_to_ascii (from, to, n)
+ char *from, *to;
+ int n;
+{
+ int nib;
+ char ch;
+ while (n--)
+ {
+ ch = *from++;
+ nib = ((ch & 0xf0) >> 4) & 0x0f;
+ *to++ = tohex (nib);
+ nib = ch & 0x0f;
+ *to++ = tohex (nib);
+ }
+ *to++ = 0;
+}
+
+
+void
+convert_ascii_to_int (from, to, n)
+ char *from, *to;
+ int n;
+{
+ int nib1, nib2;
+ while (n--)
+ {
+ nib1 = fromhex (*from++);
+ nib2 = fromhex (*from++);
+ *to++ = (((nib1 & 0x0f) << 4) & 0xf0) | (nib2 & 0x0f);
+ }
+}
+
+static char *
+outreg(regno, buf)
+ int regno;
+ char *buf;
+{
+ extern char registers[];
+
+ *buf++ = tohex (regno >> 4);
+ *buf++ = tohex (regno & 0xf);
+ *buf++ = ':';
+ convert_int_to_ascii (&registers[REGISTER_BYTE (regno)], buf, 4);
+ buf += 8;
+ *buf++ = ';';
+
+ return buf;
+}
+
+void
+prepare_resume_reply (buf, status, signal)
+ char *buf, status;
+ unsigned char signal;
+{
+ int nib;
+ char ch;
+
+ *buf++ = 'T';
+
+ nib = ((signal & 0xf0) >> 4);
+ *buf++ = tohex (nib);
+ nib = signal & 0x0f;
+ *buf++ = tohex (nib);
+
+ buf = outreg (PC_REGNUM, buf);
+ buf = outreg (FP_REGNUM, buf);
+ buf = outreg (SP_REGNUM, buf);
+#ifdef NPC_REGNUM
+ buf = outreg (NPC_REGNUM, buf);
+#endif
+#ifdef O7_REGNUM
+ buf = outreg (O7_REGNUM, buf);
+#endif
+
+ *buf++ = 0;
+}
+
+void
+decode_m_packet (from, mem_addr_ptr, len_ptr)
+ char *from;
+ unsigned int *mem_addr_ptr, *len_ptr;
+{
+ int i = 0, j = 0;
+ char ch;
+ *mem_addr_ptr = *len_ptr = 0;
+
+ while ((ch = from[i++]) != ',')
+ {
+ *mem_addr_ptr = *mem_addr_ptr << 4;
+ *mem_addr_ptr |= fromhex (ch) & 0x0f;
+ }
+
+ for (j = 0; j < 4; j++)
+ {
+ if ((ch = from[i++]) == 0)
+ break;
+ *len_ptr = *len_ptr << 4;
+ *len_ptr |= fromhex (ch) & 0x0f;
+ }
+}
+
+void
+decode_M_packet (from, mem_addr_ptr, len_ptr, to)
+ char *from, *to;
+ unsigned int *mem_addr_ptr, *len_ptr;
+{
+ int i = 0, j = 0;
+ char ch;
+ *mem_addr_ptr = *len_ptr = 0;
+
+ while ((ch = from[i++]) != ',')
+ {
+ *mem_addr_ptr = *mem_addr_ptr << 4;
+ *mem_addr_ptr |= fromhex (ch) & 0x0f;
+ }
+
+ while ((ch = from[i++]) != ':')
+ {
+ *len_ptr = *len_ptr << 4;
+ *len_ptr |= fromhex (ch) & 0x0f;
+ }
+
+ convert_ascii_to_int (&from[i++], to, *len_ptr);
+}