* 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:
parent
a037b21e75
commit
41e170e271
3 changed files with 81 additions and 463 deletions
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 ();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue