1991-04-05 11:01:15 +02: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.
|
|
|
|
|
#
|
1991-06-04 09:31:55 +02:00
|
|
|
|
# This program is free software; you can redistribute it and/or modify
|
1991-04-05 11:01:15 +02:00
|
|
|
|
# it under the terms of the GNU General Public License as published by
|
1991-06-04 09:31:55 +02:00
|
|
|
|
# the Free Software Foundation; either version 2 of the License, or
|
|
|
|
|
# (at your option) any later version.
|
1991-04-05 11:01:15 +02:00
|
|
|
|
#
|
1991-06-04 09:31:55 +02:00
|
|
|
|
# This program is distributed in the hope that it will be useful,
|
1991-04-05 11:01:15 +02: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
|
1991-06-04 09:31:55 +02:00
|
|
|
|
# along with this program; if not, write to the Free Software
|
|
|
|
|
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
1991-04-05 11:01:15 +02: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.
|
|
|
|
|
|
1991-06-04 09:31:55 +02:00
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
1991-04-05 11:01:15 +02:00
|
|
|
|
it under the terms of the GNU General Public License as published by
|
1991-06-04 09:31:55 +02:00
|
|
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
|
|
|
(at your option) any later version.
|
1991-04-05 11:01:15 +02:00
|
|
|
|
|
1991-06-04 09:31:55 +02:00
|
|
|
|
This program is distributed in the hope that it will be useful,
|
1991-04-05 11:01:15 +02: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
|
1991-06-04 09:31:55 +02:00
|
|
|
|
along with this program; if not, write to the Free Software
|
|
|
|
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
1991-04-05 11:01:15 +02: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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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.
|
|
|
|
|
|
1991-06-04 09:31:55 +02:00
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
1991-04-05 11:01:15 +02:00
|
|
|
|
it under the terms of the GNU General Public License as published by
|
1991-06-04 09:31:55 +02:00
|
|
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
|
|
|
(at your option) any later version.
|
1991-04-05 11:01:15 +02:00
|
|
|
|
|
1991-06-04 09:31:55 +02:00
|
|
|
|
This program is distributed in the hope that it will be useful,
|
1991-04-05 11:01:15 +02: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
|
1991-06-04 09:31:55 +02:00
|
|
|
|
along with this program; if not, write to the Free Software
|
|
|
|
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
1991-04-05 11:01:15 +02: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.
|
|
|
|
|
|
1991-06-04 09:31:55 +02:00
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
1991-04-05 11:01:15 +02:00
|
|
|
|
it under the terms of the GNU General Public License as published by
|
1991-06-04 09:31:55 +02:00
|
|
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
|
|
|
(at your option) any later version.
|
1991-04-05 11:01:15 +02:00
|
|
|
|
|
1991-06-04 09:31:55 +02:00
|
|
|
|
This program is distributed in the hope that it will be useful,
|
1991-04-05 11:01:15 +02: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
|
1991-06-04 09:31:55 +02:00
|
|
|
|
along with this program; if not, write to the Free Software
|
|
|
|
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
1991-04-05 11:01:15 +02: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
|