* remote.c: Make it work for embedded MIPS. Increase buffer

size, and use throughout.  Round buffer size up if too many regs.
Support baud rate setting and try for an 8-bit path.  If
interrupted while waiting for target, send a ^C down the wire.
Avoid single-byte reads.
* tm-mips.h:  Add more embedded-system registers to REGISTER_NAMES
and NUM_REGS.
* mips-xdep.h:  Avoid the embedded regs when on Unix.
This commit is contained in:
John Gilmore 1992-02-28 03:26:45 +00:00
parent b621d05050
commit b543979cda
4 changed files with 249 additions and 78 deletions

View file

@ -1,5 +1,14 @@
Thu Feb 27 11:48:47 1992 John Gilmore (gnu at cygnus.com)
* remote.c: Make it work for embedded MIPS. Increase buffer
size, and use throughout. Round buffer size up if too many regs.
Support baud rate setting and try for an 8-bit path. If
interrupted while waiting for target, send a ^C down the wire.
Avoid single-byte reads.
* tm-mips.h: Add more embedded-system registers to REGISTER_NAMES
and NUM_REGS.
* mips-xdep.h: Avoid the embedded regs when on Unix.
* mipsread.c: Byte-swap the symbol table structures, using
routines from ecoff.c, to read a symbol table written in any
of the four possible byte orders.

View file

@ -1,5 +1,5 @@
/* Low level MIPS interface to ptrace, for GDB when running under Unix.
Copyright (C) 1988, 1989, 1991 Free Software Foundation, Inc.
Copyright 1988, 1989, 1991, 1992 Free Software Foundation, Inc.
Contributed by Alessandro Forin(af@cs.cmu.edu) at CMU
and by Per Bothner(bothner@cs.wisc.edu) at U.Wisconsin.
@ -144,7 +144,8 @@ store_inferior_registers (regno)
{
if (regno == ZERO_REGNUM || regno == PS_REGNUM
|| regno == BADVADDR_REGNUM || regno == CAUSE_REGNUM
|| regno == FCRIR_REGNUM || regno == FP_REGNUM)
|| regno == FCRIR_REGNUM || regno == FP_REGNUM
|| (regno >= FIRST_EMBED_REGNUM && regno <= LAST_EMBED_REGNUM))
continue;
regaddr = register_addr (regno, 1);
errno = 0;

View file

@ -1,21 +1,21 @@
/* Memory-access and commands for inferior process, for GDB.
Copyright (C) 1988-1991 Free Software Foundation, Inc.
/* Remote target communications for serial-line targets in custom GDB protocol
Copyright 1988, 1991, 1992 Free Software Foundation, Inc.
This file is part of GDB.
GDB is free software; you can redistribute it and/or modify
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
GDB is distributed in the hope that it will be useful,
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GDB; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* Remote communication protocol.
All values are encoded in ascii hex digits.
@ -70,7 +70,6 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <string.h>
#include <fcntl.h>
#include "defs.h"
#include "param.h"
#include "frame.h"
#include "inferior.h"
#include "target.h"
@ -83,9 +82,62 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <signal.h>
extern void add_syms_addr_command ();
extern struct value *call_function_by_hand();
extern void start_remote ();
/* Prototypes for local functions */
static void
remote_write_bytes PARAMS ((CORE_ADDR, char *, int));
static void
remote_read_bytes PARAMS ((CORE_ADDR, char *, int));
static void
remote_files_info PARAMS ((struct target_ops *));
static int
remote_xfer_memory PARAMS ((CORE_ADDR, char *, int, int, struct target_ops *));
static void
remote_prepare_to_store PARAMS ((void));
static void
remote_fetch_registers PARAMS ((int));
static void
remote_resume PARAMS ((int, int));
static void
remote_open PARAMS ((char *, int));
static void
remote_close PARAMS ((int));
static void
remote_store_registers PARAMS ((int));
static void
getpkt PARAMS ((char *));
static void
putpkt PARAMS ((char *));
static void
remote_send PARAMS ((char *));
static int
readchar PARAMS ((void));
static int
remote_wait PARAMS ((WAITTYPE *));
static int
tohex PARAMS ((int));
static int
fromhex PARAMS ((int));
static void
remote_detach PARAMS ((char *, int));
extern struct target_ops remote_ops; /* Forward decl */
@ -101,19 +153,17 @@ int icache;
starts. */
int remote_desc = -1;
#define PBUFSIZ 400
#define PBUFSIZ 1024
/* Maximum number of bytes to read/write at once. The value here
is chosen to fill up a packet (the headers account for the 32). */
#define MAXBUFBYTES ((PBUFSIZ-32)/2)
static void remote_send ();
static void putpkt ();
static void getpkt ();
#if 0
static void dcache_flush ();
/* Round up PBUFSIZ to hold all the registers, at least. */
#if REGISTER_BYTES > MAXBUFBYTES
#undef PBUFSIZ
#define PBUFSIZ (REGISTER_BYTES * 2 + 32)
#endif
/* Called when SIGALRM signal sent due to alarm() timeout. */
#ifndef HAVE_TERMIO
@ -127,17 +177,10 @@ remote_timer ()
}
#endif
/* Initialize remote connection */
void
remote_start()
{
}
/* Clean up connection to a remote debugger. */
/* ARGSUSED */
void
static void
remote_close (quitting)
int quitting;
{
@ -146,15 +189,58 @@ remote_close (quitting)
remote_desc = -1;
}
/* Translate baud rates from integers to damn B_codes. Unix should
have outgrown this crap years ago, but even POSIX wouldn't buck it. */
#ifndef B19200
#define B19200 EXTA
#endif
#ifndef B38400
#define B38400 EXTB
#endif
static struct {int rate, damn_b;} baudtab[] = {
{0, B0},
{50, B50},
{75, B75},
{110, B110},
{134, B134},
{150, B150},
{200, B200},
{300, B300},
{600, B600},
{1200, B1200},
{1800, B1800},
{2400, B2400},
{4800, B4800},
{9600, B9600},
{19200, B19200},
{38400, B38400},
{-1, -1},
};
static int
damn_b (rate)
int rate;
{
int i;
for (i = 0; baudtab[i].rate != -1; i++)
if (rate == baudtab[i].rate) return baudtab[i].damn_b;
return B38400; /* Random */
}
/* Open a connection to a remote debugger.
NAME is the filename used for communication. */
void
static void
remote_open (name, from_tty)
char *name;
int from_tty;
{
TERMINAL sg;
int a_rate, b_rate;
int baudrate_set = 0;
if (name == 0)
error (
@ -173,13 +259,32 @@ device is attached to the remote system (e.g. /dev/ttya).");
if (remote_desc < 0)
perror_with_name (name);
if (baud_rate)
{
if (1 != sscanf (baud_rate, "%d ", &a_rate))
{
b_rate = damn_b (a_rate);
baudrate_set = 1;
}
}
ioctl (remote_desc, TIOCGETP, &sg);
#ifdef HAVE_TERMIO
sg.c_cc[VMIN] = 0; /* read with timeout. */
sg.c_cc[VTIME] = timeout * 10;
sg.c_lflag &= ~(ICANON | ECHO);
sg.c_cflag &= ~PARENB; /* No parity */
sg.c_cflag |= CS8; /* 8-bit path */
if (baudrate_set)
sg.c_cflag = (sb.c_cflag & ~CBAUD) | b_rate;
#else
sg.sg_flags = RAW;
sg.sg_flags |= RAW | ANYP;
sg.sg_flags &= ~ECHO;
if (baudrate_set)
{
sg.sg_ispeed = b_rate;
sg.sg_ospeed = b_rate;
}
#endif
ioctl (remote_desc, TIOCSETP, &sg);
@ -256,7 +361,7 @@ tohex (nib)
/* Tell the remote machine to resume. */
void
static void
remote_resume (step, siggnal)
int step, siggnal;
{
@ -274,19 +379,33 @@ remote_resume (step, siggnal)
putpkt (buf);
}
/* Send ^C to target to halt it. Target will respond, and send us a
packet. */
void remote_interrupt()
{
write (remote_desc, "\003", 1); /* Send a ^C */
}
/* Wait until the remote machine stops, then return,
storing status in STATUS just as `wait' would.
Returns "pid" (though it's not clear what, if anything, that
means in the case of this target). */
int
static int
remote_wait (status)
WAITTYPE *status;
{
unsigned char buf[PBUFSIZ];
void (*ofunc)();
WSETEXIT ((*status), 0);
getpkt (buf);
ofunc = signal (SIGINT, remote_interrupt);
getpkt ((char *) buf);
signal (SIGINT, ofunc);
if (buf[0] == 'E')
error ("Remote failure reply: %s", buf);
if (buf[0] != 'S')
@ -299,7 +418,7 @@ remote_wait (status)
/* Currently we just read all the registers, so we don't use regno. */
/* ARGSUSED */
void
static void
remote_fetch_registers (regno)
int regno;
{
@ -330,7 +449,7 @@ remote_fetch_registers (regno)
/* Prepare to store registers. Since we send them all, we have to
read out the ones we don't want to change first. */
void
static void
remote_prepare_to_store ()
{
remote_fetch_registers (-1);
@ -340,7 +459,7 @@ remote_prepare_to_store ()
FIXME, eventually just store one register if that's all that is needed. */
/* ARGSUSED */
int
static void
remote_store_registers (regno)
int regno;
{
@ -362,7 +481,6 @@ remote_store_registers (regno)
*p = '\0';
remote_send (buf);
return 0;
}
#if 0
@ -405,7 +523,7 @@ remote_store_word (addr, word)
MYADDR is the address of the buffer in our space.
LEN is the number of bytes. */
void
static void
remote_write_bytes (memaddr, myaddr, len)
CORE_ADDR memaddr;
char *myaddr;
@ -420,7 +538,7 @@ remote_write_bytes (memaddr, myaddr, len)
sprintf (buf, "M%x,%x:", memaddr, len);
/* Command describes registers byte by byte,
/* We send target system values byte by byte, in increasing byte addresses,
each byte encoded as two hex characters. */
p = buf + strlen (buf);
@ -440,7 +558,7 @@ remote_write_bytes (memaddr, myaddr, len)
MYADDR is the address of the buffer in our space.
LEN is the number of bytes. */
void
static void
remote_read_bytes (memaddr, myaddr, len)
CORE_ADDR memaddr;
char *myaddr;
@ -456,7 +574,7 @@ remote_read_bytes (memaddr, myaddr, len)
sprintf (buf, "m%x,%x", memaddr, len);
remote_send (buf);
/* Reply describes registers byte by byte,
/* Reply describes memory byte by byte,
each byte encoded as two hex characters. */
p = buf;
@ -473,12 +591,14 @@ remote_read_bytes (memaddr, myaddr, len)
to or from debugger address MYADDR. Write to inferior if SHOULD_WRITE is
nonzero. Returns length of data written or read; 0 for error. */
int
remote_xfer_inferior_memory(memaddr, myaddr, len, should_write)
/* ARGSUSED */
static int
remote_xfer_memory(memaddr, myaddr, len, should_write, target)
CORE_ADDR memaddr;
char *myaddr;
int len;
int should_write;
struct target_ops *target; /* ignored */
{
int origlen = len;
int xfersize;
@ -500,8 +620,9 @@ remote_xfer_inferior_memory(memaddr, myaddr, len, should_write)
return origlen; /* no error possible */
}
void
remote_files_info ()
static void
remote_files_info (target)
struct target_ops *target;
{
printf ("remote files info missing here. FIXME.\n");
}
@ -527,22 +648,35 @@ Receiver responds with:
*/
/* Read a single character from the remote end.
(If supported, we actually read many characters and buffer them up.) */
static int
readchar ()
{
char buf;
static int inbuf_index, inbuf_count;
#define INBUFSIZE PBUFSIZ
static char inbuf[INBUFSIZE];
buf = '\0';
if (inbuf_index >= inbuf_count)
{
/* Time to do another read... */
inbuf_index = 0;
inbuf_count = 0;
inbuf[0] = 0; /* Just in case */
#ifdef HAVE_TERMIO
/* termio does the timeout for us. */
read (remote_desc, &buf, 1);
/* termio does the timeout for us. */
inbuf_count = read (remote_desc, inbuf, INBUFSIZE);
#else
alarm (timeout);
read (remote_desc, &buf, 1);
alarm (0);
alarm (timeout);
inbuf_count = read (remote_desc, inbuf, INBUFSIZE);
alarm (0);
#endif
}
return buf & 0x7f;
/* Just return the next character from the buffer. */
return inbuf[inbuf_index++] & 0x7f;
}
/* Send the command in BUF to the remote machine,
@ -570,7 +704,7 @@ putpkt (buf)
{
int i;
unsigned char csum = 0;
char buf2[500];
char buf2[PBUFSIZ];
int cnt = strlen (buf);
char ch;
char *p;
@ -578,6 +712,9 @@ putpkt (buf)
/* Copy the packet into buffer BUF2, encapsulating it
and giving it a checksum. */
if (cnt > sizeof(buf2) - 5) /* Prosanity check */
abort();
p = buf2;
*p++ = '$';
@ -827,24 +964,45 @@ dcache_init ()
/* Define the target subroutine names */
struct target_ops remote_ops = {
"remote", "Remote serial target in gdb-specific protocol",
"Use a remote computer via a serial line, using a gdb-specific protocol.\n\
Specify the serial device it is connected to (e.g. /dev/ttya).",
remote_open, remote_close,
0, remote_detach, remote_resume, remote_wait, /* attach */
remote_fetch_registers, remote_store_registers,
remote_prepare_to_store, 0, 0, /* conv_from, conv_to */
remote_xfer_inferior_memory, remote_files_info,
0, 0, /* insert_breakpoint, remove_breakpoint, */
0, 0, 0, 0, 0, /* Terminal crud */
0, /* kill */
0, add_syms_addr_command, /* load */
call_function_by_hand,
0, /* lookup_symbol */
0, 0, /* create_inferior FIXME, mourn_inferior FIXME */
process_stratum, 0, /* next */
1, 1, 1, 1, 1, /* all mem, mem, stack, regs, exec */
OPS_MAGIC, /* Always the last thing */
"remote", /* to_shortname */
"Remote serial target in gdb-specific protocol", /* to_longname */
"Use a remote computer via a serial line, using a gdb-specific protocol.\n\
Specify the serial device it is connected to (e.g. /dev/ttya).", /* to_doc */
remote_open, /* to_open */
remote_close, /* to_close */
NULL, /* to_attach */
remote_detach, /* to_detach */
remote_resume, /* to_resume */
remote_wait, /* to_wait */
remote_fetch_registers, /* to_fetch_registers */
remote_store_registers, /* to_store_registers */
remote_prepare_to_store, /* to_prepare_to_store */
NULL, /* to_convert_to_virtual */
NULL, /* to_convert_from_virtual */
remote_xfer_memory, /* to_xfer_memory */
remote_files_info, /* to_files_info */
NULL, /* to_insert_breakpoint */
NULL, /* to_remove_breakpoint */
NULL, /* to_terminal_init */
NULL, /* to_terminal_inferior */
NULL, /* to_terminal_ours_for_output */
NULL, /* to_terminal_ours */
NULL, /* to_terminal_info */
NULL, /* to_kill */
NULL, /* to_load */
NULL, /* to_lookup_symbol */
NULL, /* to_create_inferior */
NULL, /* to_mourn_inferior */
process_stratum, /* to_stratum */
NULL, /* to_next */
1, /* to_has_all_memory */
1, /* to_has_memory */
1, /* to_has_stack */
1, /* to_has_registers */
1, /* to_has_execution */
NULL, /* sections */
NULL, /* sections_end */
OPS_MAGIC /* to_magic */
};
void

View file

@ -95,7 +95,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* Number of machine registers */
#define NUM_REGS 73
#define NUM_REGS 80
/* Initializer for an array of names of registers.
There should be NUM_REGS strings in this initializer. */
@ -107,10 +107,11 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
"t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra", \
"sr", "lo", "hi", "bad", "cause","pc", \
"f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", \
"f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", \
"f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",\
"f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",\
"fsr", "fir", "fp" \
"f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", \
"f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",\
"f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",\
"fsr", "fir", "fp", "inx", "rand", "tlblo","ctxt", "tlbhi",\
"epc", "prid"\
}
/* Register numbers of various important registers.
@ -134,6 +135,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#define FCRCS_REGNUM 70 /* FP control/status */
#define FCRIR_REGNUM 71 /* FP implementation/revision */
#define FP_REGNUM 72 /* Pseudo register that contains true address of executing stack frame */
#define FIRST_EMBED_REGNUM 73 /* First supervisor register for embedded use */
#define LAST_EMBED_REGNUM 79 /* Last one */
/* Define DO_REGISTERS_INFO() to do machine-specific formatting
of register dumps. */