aboutsummaryrefslogtreecommitdiff
path: root/gdb/remote-multi.shar
diff options
context:
space:
mode:
authorK. Richard Pixley <rich@cygnus>1991-03-28 16:28:29 +0000
committerK. Richard Pixley <rich@cygnus>1991-03-28 16:28:29 +0000
commitdd3b648e8b12ceb7bfce66e7f179b671403aea9c (patch)
tree91119a0f4943acc9293cd8baba06943621b6e6c7 /gdb/remote-multi.shar
parentbd5635a1e2b38ee8432fcdaa6456079191375277 (diff)
downloadgdb-dd3b648e8b12ceb7bfce66e7f179b671403aea9c.zip
gdb-dd3b648e8b12ceb7bfce66e7f179b671403aea9c.tar.gz
gdb-dd3b648e8b12ceb7bfce66e7f179b671403aea9c.tar.bz2
Johns release
Diffstat (limited to 'gdb/remote-multi.shar')
-rwxr-xr-xgdb/remote-multi.shar1313
1 files changed, 1313 insertions, 0 deletions
diff --git a/gdb/remote-multi.shar b/gdb/remote-multi.shar
new file mode 100755
index 0000000..86c9cf0
--- /dev/null
+++ b/gdb/remote-multi.shar
@@ -0,0 +1,1313 @@
+#!/bin/sh
+# This is a shell archive.
+# Run the file through sh to extract its contents.
+# shar: Shell Archiver
+# Run the following text with /bin/sh to create:
+# Remote_Makefile
+# remote_gutils.c
+# remote_inflow.c
+# remote_server.c
+# remote_utils.c
+# This archive created: Fri Jun 23 17:06:55 1989
+cat << \SHAR_EOF > Remote_Makefile
+# Makefile for the remote server for GDB, the GNU debugger.
+# Copyright (C) 1986, 1989 Free Software Foundation, Inc.
+#
+# This file is part of GDB.
+#
+# GDB 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 1, or (at your option)
+# any later version.
+#
+# GDB 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 GDB; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+CFLAGS = -g
+CC = cc
+
+SERVER = remote_server.o\
+ remote_inflow.o\
+ remote_utils.o\
+ remote_gutils.o
+
+prog : $(SERVER)
+ $(CC) -g -o serve $(SERVER)
+SHAR_EOF
+cat << \SHAR_EOF > remote_gutils.c
+/* General utility routines for the remote server for GDB, the GNU debugger.
+ Copyright (C) 1986, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+#include <sys/ioctl.h>
+#include "defs.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) ();
+ int 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. */
+
+char *
+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. */
+
+char *
+xrealloc (ptr, size)
+ char *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 ()
+{
+ 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. */
+
+void
+error (string, arg1, arg2, arg3)
+ char *string;
+ int arg1, arg2, arg3;
+{
+ fflush (stdout);
+ fprintf (stderr, string, arg1, arg2, arg3);
+ fprintf (stderr, "\n");
+ /************return_to_top_level ();************/
+}
+
+/* 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)
+ char *ptr;
+ int size;
+{
+ register char *p = (char *) xmalloc (size + 1);
+ bcopy (ptr, p, size);
+ p[size] = 0;
+ return p;
+}
+
+char *
+concat (s1, s2, s3)
+ char *s1, *s2, *s3;
+{
+ register int len = strlen (s1) + strlen (s2) + strlen (s3) + 1;
+ register char *val = (char *) xmalloc (len);
+ strcpy (val, s1);
+ strcat (val, s2);
+ strcat (val, s3);
+ return val;
+}
+
+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);
+ }
+}
+SHAR_EOF
+cat << \SHAR_EOF > remote_inflow.c
+/* Low level interface to ptrace, for GDB when running under Unix.
+ Copyright (C) 1986, 1987 Free Software Foundation, Inc.
+*/
+
+#include "defs.h"
+#include "param.h"
+#include "wait.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>
+#include <signal.h>
+#include <sys/ioctl.h>
+#include <sgtty.h>
+#include <fcntl.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*********************/
+
+#ifdef NEW_SUN_PTRACE
+#include <sys/ptrace.h>
+#include <machine/reg.h>
+#endif
+
+extern char **environ;
+extern int errno;
+extern int inferior_pid;
+void error(), quit(), perror_with_name();
+int query();
+void supply_register(), write_register();
+CORE_ADDR read_register();
+
+/* Nonzero if we are debugging an attached outside process
+ rather than an inferior. */
+
+
+/* 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;
+
+ /* exec is said to fail if the executable is open. */
+ /****************close_exec_file ();*****************/
+
+ pid = vfork ();
+ if (pid < 0)
+ perror_with_name ("vfork");
+
+ if (pid == 0)
+ {
+ /* Run inferior in a separate process group. */
+ setpgrp (getpid (), getpid ());
+
+/* Not needed on Sun, at least, and loses there
+ because it clobbers the superior. */
+/*??? signal (SIGQUIT, SIG_DFL);
+ signal (SIGINT, SIG_DFL); */
+
+ errno = 0;
+ ptrace (0);
+
+ execle ("/bin/sh", "sh", "-c", allargs, 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. */
+
+kill_inferior ()
+{
+ if (inferior_pid == 0)
+ return;
+ ptrace (8, inferior_pid, 0, 0);
+ wait (0);
+ /*************inferior_died ();****VK**************/
+}
+
+/* Resume execution of the inferior process.
+ If STEP is nonzero, single-step it.
+ If SIGNAL is nonzero, give it that signal. */
+
+unsigned char
+resume (step, signal,status)
+ int step;
+ int signal;
+ char *status;
+{
+ int pid ;
+ WAITTYPE w;
+
+ errno = 0;
+ ptrace (step ? 9 : 7, inferior_pid, 1, signal);
+ if (errno)
+ perror_with_name ("ptrace");
+ pid = wait(&w);
+ if(pid != inferior_pid)
+ perror_with_name ("wait");
+
+ if(WIFEXITED(w))
+ {
+ printf("\nchild exited with retcode = %x \n",WRETCODE(w));
+ *status = 'E';
+ return((unsigned char) WRETCODE(w));
+ }
+ else if(!WIFSTOPPED(w))
+ {
+ printf("\nchild did terminated with signal = %x \n",WTERMSIG(w));
+ *status = 'T';
+ return((unsigned char) WTERMSIG(w));
+ }
+ else
+ {
+ printf("\nchild stopped with signal = %x \n",WSTOPSIG(w));
+ *status = 'S';
+ return((unsigned char) WSTOPSIG(w));
+ }
+
+}
+
+
+#ifdef NEW_SUN_PTRACE
+
+void
+fetch_inferior_registers ()
+{
+ struct regs inferior_registers;
+ struct fp_status inferior_fp_registers;
+ extern char registers[];
+
+ ptrace (PTRACE_GETREGS, inferior_pid, &inferior_registers);
+ if (errno)
+ perror_with_name ("ptrace");
+ /**********debugging begin **********/
+ print_some_registers(&inferior_registers);
+ /**********debugging end **********/
+ ptrace (PTRACE_GETFPREGS, inferior_pid, &inferior_fp_registers);
+ if (errno)
+ perror_with_name ("ptrace");
+
+ bcopy (&inferior_registers, registers, 16 * 4);
+ bcopy (&inferior_fp_registers, &registers[REGISTER_BYTE (FP0_REGNUM)],
+ sizeof inferior_fp_registers.fps_regs);
+ *(int *)&registers[REGISTER_BYTE (PS_REGNUM)] = inferior_registers.r_ps;
+ *(int *)&registers[REGISTER_BYTE (PC_REGNUM)] = inferior_registers.r_pc;
+ bcopy (&inferior_fp_registers.fps_control,
+ &registers[REGISTER_BYTE (FPC_REGNUM)],
+ sizeof inferior_fp_registers - sizeof inferior_fp_registers.fps_regs);
+}
+
+/* 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). */
+
+store_inferior_registers (regno)
+ int regno;
+{
+ struct regs inferior_registers;
+ struct fp_status inferior_fp_registers;
+ extern char registers[];
+
+ bcopy (registers, &inferior_registers, 16 * 4);
+ bcopy (&registers[REGISTER_BYTE (FP0_REGNUM)], &inferior_fp_registers,
+ sizeof inferior_fp_registers.fps_regs);
+ inferior_registers.r_ps = *(int *)&registers[REGISTER_BYTE (PS_REGNUM)];
+ inferior_registers.r_pc = *(int *)&registers[REGISTER_BYTE (PC_REGNUM)];
+ bcopy (&registers[REGISTER_BYTE (FPC_REGNUM)],
+ &inferior_fp_registers.fps_control,
+ sizeof inferior_fp_registers - sizeof inferior_fp_registers.fps_regs);
+
+ ptrace (PTRACE_SETREGS, inferior_pid, &inferior_registers);
+ if (errno)
+ perror_with_name ("ptrace");
+ ptrace (PTRACE_SETFPREGS, inferior_pid, &inferior_fp_registers);
+ if (errno)
+ perror_with_name ("ptrace");
+}
+
+#endif /* not NEW_SUN_PTRACE */
+
+
+/* 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
+try_writing_regs_command ()
+{
+ register int i;
+ register int value;
+ extern int errno;
+
+ if (inferior_pid == 0)
+ error ("There is no inferior process now.");
+
+ fetch_inferior_registers();
+ for (i = 0;i<18 ; i ++)
+ {
+ QUIT;
+ errno = 0;
+ value = read_register(i);
+ write_register ( i, value);
+ if (errno == 0)
+ {
+ printf (" Succeeded with register %d; value 0x%x (%d).\n",
+ i, value, value);
+ }
+ else
+ printf (" Failed with register %d.\n", i);
+ }
+}
+
+void
+initialize ()
+{
+
+ inferior_pid = 0;
+
+
+}
+
+
+/* Return the contents of register REGNO,
+ regarding it as an integer. */
+
+CORE_ADDR
+read_register (regno)
+ int regno;
+{
+ /* This loses when REGISTER_RAW_SIZE (regno) != sizeof (int) */
+ return *(int *) &registers[REGISTER_BYTE (regno)];
+}
+
+/* Store VALUE in the register number REGNO, regarded as an integer. */
+
+void
+write_register (regno, val)
+ int regno, val;
+{
+ /* This loses when REGISTER_RAW_SIZE (regno) != sizeof (int) */
+ *(int *) &registers[REGISTER_BYTE (regno)] = val;
+
+ if (have_inferior_p ())
+ store_inferior_registers (regno);
+}
+
+
+int
+have_inferior_p ()
+{
+ return inferior_pid != 0;
+}
+
+print_some_registers(regs)
+int regs[];
+{
+ register int i;
+ for (i = 0; i < 18; i++) {
+ printf("reg[%d] = %x\n", i, regs[i]);
+ }
+}
+
+SHAR_EOF
+cat << \SHAR_EOF > remote_server.c
+/* Main code for remote server for GDB, the GNU Debugger.
+ Copyright (C) 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "param.h"
+#include <stdio.h>
+
+void read_inferior_memory(), fetch_inferior_registers();
+unsigned char resume();
+void kill_inferior();
+void initialize(), try_writing_regs_command();
+int create_inferior(), read_register();
+
+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();
+
+
+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;
+
+ initialize();
+ printf("\nwill open serial link\n");
+ remote_open("/dev/ttya",0);
+
+ if(argc < 2)
+ {
+ printf("Enter name of program to be run with command line args\n");
+ gets(own_buf);
+ inferior_pid = create_inferior(own_buf,environ);
+ printf("\nProcess %s created; pid = %d\n",own_buf,inferior_pid);
+ }
+ else
+ {
+ inferior_pid = create_inferior(argv[1],environ);
+ printf("\nProcess %s created; pid = %d\n",argv[1],inferior_pid);
+ }
+
+ do {
+ getpkt(own_buf);
+ printf("\nPacket received is>:%s\n",own_buf);
+ i = 0;
+ ch = own_buf[i++];
+ switch (ch) {
+ case 'h': /**********This is only for tweaking the gdb+ program *******/
+ signal = resume(1,0,&status);
+ prepare_resume_reply(own_buf,status,signal);
+ break;
+ /*************end tweak*************************************/
+
+ case 'g': fetch_inferior_registers();
+ convert_int_to_ascii(registers,own_buf,REGISTER_BYTES);
+ break;
+ case 'G': convert_ascii_to_int(&own_buf[1],registers,REGISTER_BYTES);
+ if(store_inferior_registers(-1)==0)
+ write_ok(own_buf);
+ else
+ write_enn(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': signal = resume(0,0,&status);
+ printf("\nSignal received is >: %0x \n",signal);
+ prepare_resume_reply(own_buf,status,signal);
+ break;
+ case 's': signal = resume(1,0,&status);
+ prepare_resume_reply(own_buf,status,signal);
+ break;
+ case 'k': kill_inferior();
+ sprintf(own_buf,"q");
+ putpkt(own_buf);
+ printf("\nObtained kill request...terminating\n");
+ close(remote_desc);
+ exit(0);
+ case 't': try_writing_regs_command();
+ own_buf[0] = '\0';
+ break;
+ 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**/
+ printf("\nFinished reading data from serial link - Bye!\n");
+ exit(0);
+
+}
+
+SHAR_EOF
+cat << \SHAR_EOF > remote_utils.c
+/* Remote utility routines for the remote server for GDB, the GNU debugger.
+ Copyright (C) 1986, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB 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 1, or (at your option)
+any later version.
+
+GDB 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 GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "param.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)
+ printf("\ncould not open remote device\n");
+
+ ioctl (remote_desc, TIOCGETP, &sg);
+ sg.sg_flags = RAW;
+ ioctl (remote_desc, TIOCSETP, &sg);
+
+ if (from_tty)
+ printf ("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
+ perror ("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')
+ perror ("Remote failure reply: %s", buf);
+}
+
+/* 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[500];
+ char buf3[1];
+ int cnt = strlen (buf);
+ char *p;
+
+ if (kiodebug)
+ fprintf (stderr, "Sending packet: %s\n", buf);
+
+ /* 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;
+
+ printf ("Bad checksum, sentsum=0x%x, csum=0x%x, buf=%s\n",
+ (c1 << 4) + c2, csum, buf);
+ write (remote_desc, "-", 1);
+ }
+
+ write (remote_desc, "+", 1);
+
+ if (kiodebug)
+ fprintf (stderr,"Packet received :%s\n", buf);
+}
+
+
+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);
+ }
+}
+
+void
+prepare_resume_reply(buf,status,signal)
+char *buf ,status;
+unsigned char signal;
+{
+ int nib;
+ char ch;
+
+ *buf++ = 'S';
+ *buf++ = status;
+ nib = ((signal & 0xf0) >> 4) ;
+ *buf++ = tohex(nib);
+ nib = signal & 0x0f;
+ *buf++ = tohex(nib);
+ *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;
+ /************debugging begin************/
+ printf("\nIn decode_m_packet");
+ /************debugging end************/
+
+ while((ch = from[i++]) != ',')
+ {
+ *mem_addr_ptr = *mem_addr_ptr << 4;
+ *mem_addr_ptr |= fromhex(ch) & 0x0f;
+ }
+ /************debugging begin************/
+ printf("\nFinished mem_addr part");
+ /************debugging end************/
+
+ for(j=0; j < 4; j++)
+ {
+ if((ch = from[i++]) == 0)
+ break;
+ *len_ptr = *len_ptr << 4;
+ *len_ptr |= fromhex(ch) & 0x0f;
+ }
+ /************debugging begin************/
+ printf("\nFinished len_ptr part");
+ /************debugging end************/
+}
+
+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;
+ /************debugging begin************/
+ printf("\nIn decode_M_packet");
+ /************debugging end************/
+
+ while((ch = from[i++]) != ',')
+ {
+ *mem_addr_ptr = *mem_addr_ptr << 4;
+ *mem_addr_ptr |= fromhex(ch) & 0x0f;
+ }
+ /************debugging begin************/
+ printf("\nFinished mem_addr part: memaddr = %x",*mem_addr_ptr);
+ /************debugging end************/
+
+ while((ch = from[i++]) != ':')
+ {
+ *len_ptr = *len_ptr << 4;
+ *len_ptr |= fromhex(ch) & 0x0f;
+ }
+ /************debugging begin************/
+ printf("\nFinished len_ptr part: len = %d",*len_ptr);
+ /************debugging end************/
+
+ convert_ascii_to_int(&from[i++],to,*len_ptr);
+
+ /************debugging begin************/
+ printf("\nmembuf : %x",*(int *)to);
+ /************debugging end************/
+}
+
+SHAR_EOF
+# End of shell archive
+exit 0