#!/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 #include #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 #include #include #include #include #include #include #include /***************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 #include #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 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 #include #include #include #include #include #include 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