* gdbserver/Makefile.in: Add dependancies on server.h.

* gdbserver/remote-gutils.c:  Remove lots of unused functions and
	variables.
	* gdbserver/remote-inflow.c:  Remove lots of unused variables and
	#includes.  Also, use PTRACE_* symbols instead of constants.
	(mywait):  Surround calls to wait() with enable/disable_async_io()
	so that we can be interrupted from GDB while waiting for the
	child.  Also, handle child exit more gracefully.
	* gdbserver/remote-server.c:  Remove lots of unused variables.
	Move all extern defs into server.h.  Redo main loop so that
	failure from getpkt() causes communications to be re-established.
	Fix 'k' command so that it restarts the child.
	* gdbserver/remote-utils.c:  Remove lots of unloved vars and
	subrs.  Move many extern decls into server.h.  (remote_open):  For
	tcp, seperate usage of proto fd from connected fd.  Close proto
	fd after getting connection.  (putpkt/getpkt):  Pay attention to
	errors when reading/writing.  Report these to the caller.  New
	routines input_interrupt/enable_async_io/disable_async_io to make
	it possible to get an I/O interrupt when data arrives from the
	comm link.
	* serial.h:  New file to contain common defs for all remote files.
This commit is contained in:
Stu Grossman 1993-06-26 00:41:00 +00:00
parent a037b21e75
commit 41e170e271
3 changed files with 81 additions and 463 deletions

View File

@ -17,123 +17,11 @@ 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. */
#include "server.h"
#include <stdio.h>
#include <sys/ioctl.h>
#include "defs.h"
#include <setjmp.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) ();
PTR 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. */
PTR
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. */
PTR
xrealloc (ptr, size)
PTR 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. */
@ -161,51 +49,6 @@ perror_with_name (string)
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 (ignored)
int ignored;
{
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. */
@ -237,176 +80,3 @@ fatal (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)
const 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);
}
}

View File

@ -17,17 +17,13 @@ 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. */
#include "defs.h"
#include "server.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>*/
#define LYNXOS
#include <sys/mem.h>
#include <sys/signal.h>
@ -43,25 +39,9 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <fcntl.h>
#include "/usr/include/wait.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*********************/
#include <sys/ptrace.h>
/*#include <machine/reg.h>*/
extern char **environ;
extern int errno;
extern int inferior_pid;
void error (), quit (), perror_with_name ();
int query ();
/* Start an inferior process and returns its pid.
ALLARGS is a vector of program-name and args.
@ -100,9 +80,10 @@ kill_inferior ()
{
if (inferior_pid == 0)
return;
ptrace (8, inferior_pid, 0, 0);
ptrace (PTRACE_KILL, inferior_pid, 0, 0);
wait (0);
/*************inferior_died ();****VK**************/
inferior_pid = 0;
}
/* Wait for process, returns status */
@ -114,7 +95,12 @@ mywait (status)
int pid;
union wait w;
enable_async_io();
pid = wait (&w);
disable_async_io();
if (pid != PIDGET(inferior_pid))
perror_with_name ("wait");
@ -122,9 +108,9 @@ mywait (status)
if (WIFEXITED (w))
{
fprintf (stderr, "\nChild exited with retcode = %x \n", WEXITSTATUS (w));
*status = 'E';
return ((unsigned char) WEXITSTATUS (w));
fprintf (stderr, "\nChild exited with status %d\n", WEXITSTATUS (w));
fprintf (stderr, "GDBserver exiting\n");
exit (0);
}
else if (!WIFSTOPPED (w))
{
@ -266,6 +252,7 @@ store_inferior_registers (ignored)
/* Copy LEN bytes from inferior's memory starting at MEMADDR
to debugger memory starting at MYADDR. */
void
read_inferior_memory (memaddr, myaddr, len)
CORE_ADDR memaddr;
char *myaddr;
@ -283,7 +270,7 @@ read_inferior_memory (memaddr, myaddr, len)
/* Read all the longwords */
for (i = 0; i < count; i++, addr += sizeof (int))
{
buffer[i] = ptrace (1, inferior_pid, addr, 0);
buffer[i] = ptrace (PTRACE_PEEKTEXT, inferior_pid, addr, 0);
}
/* Copy appropriate bytes out of the buffer. */
@ -313,12 +300,12 @@ write_inferior_memory (memaddr, myaddr, len)
/* Fill start and end extra bytes of buffer with existing memory data. */
buffer[0] = ptrace (1, inferior_pid, addr, 0);
buffer[0] = ptrace (PTRACE_PEEKTEXT, inferior_pid, addr, 0);
if (count > 1)
{
buffer[count - 1]
= ptrace (1, inferior_pid,
= ptrace (PTRACE_PEEKTEXT, inferior_pid,
addr + (count - 1) * sizeof (int), 0);
}
@ -331,22 +318,10 @@ write_inferior_memory (memaddr, myaddr, len)
for (i = 0; i < count; i++, addr += sizeof (int))
{
errno = 0;
ptrace (4, inferior_pid, addr, buffer[i]);
ptrace (PTRACE_POKETEXT, inferior_pid, addr, buffer[i]);
if (errno)
return errno;
}
return 0;
}
void
initialize ()
{
inferior_pid = 0;
}
int
have_inferior_p ()
{
return inferior_pid != 0;
}

View File

@ -17,37 +17,7 @@ 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. */
#include "defs.h"
#include <setjmp.h>
#include <signal.h>
void read_inferior_memory ();
unsigned char mywait ();
void myresume();
void initialize ();
int create_inferior ();
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 ();
jmp_buf toplevel;
#include "server.h"
main (argc, argv)
int argc;
@ -67,9 +37,6 @@ main (argc, argv)
if (argc < 3)
error("Usage: gdbserver tty prog [args ...]");
initialize ();
remote_open (argv[1], 0);
inferior_pid = create_inferior (argv[2], &argv[2]);
fprintf (stderr, "Process %s created; pid = %d\n", argv[2], inferior_pid);
@ -77,66 +44,72 @@ main (argc, argv)
/* We are now stopped at the first instruction of the target process */
setjmp(toplevel);
do
while (1)
{
getpkt (own_buf);
i = 0;
ch = own_buf[i++];
switch (ch)
remote_open (argv[1]);
setjmp(toplevel);
while (getpkt (own_buf) > 0)
{
case '?':
prepare_resume_reply (own_buf, status, signal);
break;
case 'g':
convert_int_to_ascii (registers, own_buf, REGISTER_BYTES);
break;
case 'G':
convert_ascii_to_int (&own_buf[1], registers, REGISTER_BYTES);
store_inferior_registers (-1);
write_ok (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':
myresume (0, 0);
signal = mywait (&status);
prepare_resume_reply (own_buf, status, signal);
break;
case 's':
myresume (1, 0);
signal = mywait (&status);
prepare_resume_reply (own_buf, status, signal);
break;
case 'k':
kill_inferior ();
sprintf (own_buf, "q");
i = 0;
ch = own_buf[i++];
switch (ch)
{
case '?':
prepare_resume_reply (own_buf, status, signal);
break;
case 'g':
convert_int_to_ascii (registers, own_buf, REGISTER_BYTES);
break;
case 'G':
convert_ascii_to_int (&own_buf[1], registers, REGISTER_BYTES);
store_inferior_registers (-1);
write_ok (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':
myresume (0, 0);
signal = mywait (&status);
prepare_resume_reply (own_buf, status, signal);
break;
case 's':
myresume (1, 0);
signal = mywait (&status);
prepare_resume_reply (own_buf, status, signal);
break;
case 'k':
fprintf (stderr, "Killing inferior\n");
kill_inferior ();
inferior_pid = create_inferior (argv[2], &argv[2]);
fprintf (stderr, "Process %s created; pid = %d\n", argv[2],
inferior_pid);
signal = mywait (&status); /* Wait till we are at 1st instr in prog */
break;
default:
printf ("\nUnknown option chosen by master\n");
write_enn (own_buf);
break;
}
putpkt (own_buf);
fprintf (stderr, "Obtained kill request...terminating\n");
close (remote_desc);
exit (0);
default:
printf ("\nUnknown option chosen by master\n");
write_enn (own_buf);
break;
}
putpkt (own_buf);
}
while (1);
/* We come here when getpkt fails. Close the connection, and re-open it
at the top of the loop. */
close (remote_desc);
/** now get out of here**/
fprintf (stderr, "Finished reading data from serial link - Bye!\n");
exit (0);
fprintf (stderr, "Remote side has terminated connection. GDBserver will reopen the connection.\n");
remote_close ();
}
}