binutils-gdb/gdb/remote-multi.shar

1314 lines
30 KiB
Plaintext
Raw Normal View History

1991-03-28 17:28:29 +01:00
#!/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