binutils-gdb/gdb/rem-multi.shar

1314 lines
30 KiB
Plaintext
Raw Normal View History

1991-04-05 17:01:15 +08: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.
#
# This program is free software; you can redistribute it and/or modify
1991-04-05 17:01:15 +08:00
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
1991-04-05 17:01:15 +08:00
#
# This program is distributed in the hope that it will be useful,
1991-04-05 17:01:15 +08:00
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
1991-04-05 17:01:15 +08:00
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.
This program is free software; you can redistribute it and/or modify
1991-04-05 17:01:15 +08:00
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
1991-04-05 17:01:15 +08:00
This program is distributed in the hope that it will be useful,
1991-04-05 17:01:15 +08:00
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
1991-04-05 17:01:15 +08:00
#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.
This program is free software; you can redistribute it and/or modify
1991-04-05 17:01:15 +08:00
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
1991-04-05 17:01:15 +08:00
This program is distributed in the hope that it will be useful,
1991-04-05 17:01:15 +08:00
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
1991-04-05 17:01:15 +08:00
#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.
This program is free software; you can redistribute it and/or modify
1991-04-05 17:01:15 +08:00
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
1991-04-05 17:01:15 +08:00
This program is distributed in the hope that it will be useful,
1991-04-05 17:01:15 +08:00
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
1991-04-05 17:01:15 +08:00
#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