diff options
author | K. Richard Pixley <rich@cygnus> | 1991-03-28 16:28:29 +0000 |
---|---|---|
committer | K. Richard Pixley <rich@cygnus> | 1991-03-28 16:28:29 +0000 |
commit | dd3b648e8b12ceb7bfce66e7f179b671403aea9c (patch) | |
tree | 91119a0f4943acc9293cd8baba06943621b6e6c7 /gdb/remote-multi.shar | |
parent | bd5635a1e2b38ee8432fcdaa6456079191375277 (diff) | |
download | gdb-dd3b648e8b12ceb7bfce66e7f179b671403aea9c.zip gdb-dd3b648e8b12ceb7bfce66e7f179b671403aea9c.tar.gz gdb-dd3b648e8b12ceb7bfce66e7f179b671403aea9c.tar.bz2 |
Johns release
Diffstat (limited to 'gdb/remote-multi.shar')
-rwxr-xr-x | gdb/remote-multi.shar | 1313 |
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, ®isters[REGISTER_BYTE (FP0_REGNUM)], + sizeof inferior_fp_registers.fps_regs); + *(int *)®isters[REGISTER_BYTE (PS_REGNUM)] = inferior_registers.r_ps; + *(int *)®isters[REGISTER_BYTE (PC_REGNUM)] = inferior_registers.r_pc; + bcopy (&inferior_fp_registers.fps_control, + ®isters[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 (®isters[REGISTER_BYTE (FP0_REGNUM)], &inferior_fp_registers, + sizeof inferior_fp_registers.fps_regs); + inferior_registers.r_ps = *(int *)®isters[REGISTER_BYTE (PS_REGNUM)]; + inferior_registers.r_pc = *(int *)®isters[REGISTER_BYTE (PC_REGNUM)]; + bcopy (®isters[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 *) ®isters[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 *) ®isters[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 |