aboutsummaryrefslogtreecommitdiff
path: root/gdb/gdbserver/remote-utils.c
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/gdbserver/remote-utils.c')
-rw-r--r--gdb/gdbserver/remote-utils.c339
1 files changed, 339 insertions, 0 deletions
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);
+}