/* Remote debugging interface for boot monitors, for GDB.
- Copyright 1990, 1991, 1992, 1993, 1995
+ Copyright 1990, 1991, 1992, 1993, 1995, 1996
Free Software Foundation, Inc.
Contributed by Cygnus Support. Written by Rob Savoye for Cygnus.
Resurrected from the ashes by Stu Grossman.
(or possibly TELNET) stream to a terminal multiplexor,
which in turn talks to the target board. */
+/* FIXME 32x64: This code assumes that registers and addresses are at
+ most 32 bits long. If they can be larger, you will need to declare
+ values as LONGEST and use %llx or some such to print values when
+ building commands to send to the monitor. Since we don't know of
+ any actual 64-bit targets with ROM monitors that use this code,
+ it's not an issue right now. -sts 4/18/96 */
+
#include "defs.h"
#include "gdbcore.h"
#include "target.h"
static void monitor_fetch_register PARAMS ((int regno));
static void monitor_store_register PARAMS ((int regno));
-static void monitor_close PARAMS ((int quitting));
static void monitor_detach PARAMS ((char *args, int from_tty));
static void monitor_resume PARAMS ((int pid, int step, enum target_signal sig));
static void monitor_interrupt PARAMS ((int signo));
static void monitor_load PARAMS ((char *file, int from_tty));
static void monitor_mourn_inferior PARAMS ((void));
static void monitor_stop PARAMS ((void));
-static void monitor_debug PARAMS ((char *string));
+static void monitor_debug PARAMS ((char *prefix, char *string, char *suffix));
static int monitor_read_memory PARAMS ((CORE_ADDR addr, char *myaddr,int len));
static int monitor_write_memory PARAMS ((CORE_ADDR addr, char *myaddr,int len));
+static int monitor_expect_regexp PARAMS ((struct re_pattern_buffer *pat,
+ char *buf, int buflen));
static int from_hex PARAMS ((int a));
static unsigned long get_hex_word PARAMS ((void));
characters in printable fashion. */
static void
-monitor_debug (string)
+monitor_debug (prefix, string, suffix)
+ char *prefix;
char *string;
+ char *suffix;
{
int ch;
+ /* print prefix and suffix after each line */
+ static int new_line=1;
+ if (new_line==1) { /* print prefix if last char was a newline */
+ fputs_unfiltered (prefix, gdb_stderr);
+ new_line=0;
+ }
+ if (strchr(string,'\n')) /* save state for next call */
+ new_line=1;
+
while ((ch = *string++) != '\0')
{
switch (ch) {
case '\\': fputs_unfiltered ("\\\\", gdb_stderr); break;
case '\b': fputs_unfiltered ("\\b", gdb_stderr); break;
case '\f': fputs_unfiltered ("\\f", gdb_stderr); break;
- case '\n': fputs_unfiltered ("\\n\n", gdb_stderr); break;
- case '\r': fputs_unfiltered ("\\r\n", gdb_stderr); break;
+ case '\n': fputs_unfiltered ("\\n", gdb_stderr); break;
+ case '\r': fputs_unfiltered ("\\r", gdb_stderr); break;
case '\t': fputs_unfiltered ("\\t", gdb_stderr); break;
case '\v': fputs_unfiltered ("\\v", gdb_stderr); break;
}
}
-}
+ if (new_line==1) { /* print suffix if last char was a newline */
+ fputs_unfiltered (suffix, gdb_stderr);
+ fputs_unfiltered ("\n", gdb_stderr);
+ }
+}
/* monitor_printf_noecho -- Send data to monitor, but don't expect an echo.
Works just like printf. */
vsprintf (sndbuf, pattern, args);
if (remote_debug > 0)
- monitor_debug (sndbuf);
+ monitor_debug ("sent -->", sndbuf, "<--");
len = strlen (sndbuf);
va_list args;
char sndbuf[2000];
int len;
- int i, c;
#ifdef ANSI_PROTOTYPES
va_start (args, pattern);
vsprintf (sndbuf, pattern, args);
if (remote_debug > 0)
- monitor_debug (sndbuf);
+ monitor_debug ("sent -->", sndbuf, "<--");
len = strlen (sndbuf);
if (SERIAL_WRITE(monitor_desc, sndbuf, len))
fprintf_unfiltered (stderr, "SERIAL_WRITE failed: %s\n", safe_strerror (errno));
- for (i = 0; i < len; i++)
- {
- trycr:
- c = readchar (timeout);
-
- if (c != sndbuf[i])
- {
- /* Don't fail if we sent a ^C, they're never echoed */
- if (sndbuf[i] == '\003')
- continue;
-#if 0
- if (sndbuf[i] == '\r'
- && c == '\n')
- goto trycr;
-#endif
- warning ("monitor_printf: Bad echo. Sent: \"%s\", Got: \"%.*s%c\".",
- sndbuf, i, sndbuf, c);
- }
- }
+ /* We used to expect that the next immediate output was the characters we
+ just output, but sometimes some extra junk appeared before the characters
+ we expected, like an extra prompt, or a portmaster sending telnet negotiations.
+ So, just start searching for what we sent, and skip anything unknown. */
+ monitor_expect (sndbuf, (char *)0, 0);
}
/* Read a character from the remote system, doing all the fancy
int timeout;
{
int c;
+ static enum { last_random, last_nl, last_cr, last_crnl } state = last_random;
+ int looping;
- c = SERIAL_READCHAR (monitor_desc, timeout);
+ do
+ {
+ looping = 0;
+ c = SERIAL_READCHAR (monitor_desc, timeout);
- if (remote_debug > 0)
- fputc_unfiltered (c, gdb_stderr);
+ if (c >= 0)
+ {
+ c &= 0x7f;
+ if (remote_debug > 0)
+ {
+ char buf[2];
+ buf[0] = c;
+ buf[1] = '\0';
+ monitor_debug ("read -->", buf, "<--");
+ }
+ }
+
+ /* Canonicialize \n\r combinations into one \r */
+ if ((current_monitor->flags & MO_HANDLE_NL) != 0)
+ {
+ if ((c == '\r' && state == last_nl)
+ || (c == '\n' && state == last_cr))
+ {
+ state = last_crnl;
+ looping = 1;
+ }
+ else if (c == '\r')
+ state = last_cr;
+ else if (c != '\n')
+ state = last_random;
+ else
+ {
+ state = last_nl;
+ c = '\r';
+ }
+ }
+ }
+ while (looping);
if (c >= 0)
- return c & 0x7f;
+ return c;
if (c == SERIAL_TIMEOUT)
#ifdef MAINTENANCE_CMDS
else
c = readchar (timeout);
- if (c == *p++)
+ /* Don't expect any ^C sent to be echoed */
+
+ if (*p == '\003' || c == *p)
{
+ p++;
if (*p == '\0')
{
immediate_quit = 0;
/* Search for a regexp. */
-int
+static int
monitor_expect_regexp (pat, buf, buflen)
struct re_pattern_buffer *pat;
char *buf;
if (current_monitor->stop)
{
monitor_stop ();
- monitor_expect_prompt (NULL, 0);
+ if ((current_monitor->flags & MO_NO_ECHO_ON_OPEN) == 0)
+ {
+ monitor_expect_prompt (NULL, 0);
+ }
}
/* wake up the monitor and see if it's alive */
for (p = mon_ops->init; *p != NULL; p++)
{
- monitor_printf (*p);
+ /* Some of the characters we send may not be echoed,
+ but we hope to get a prompt at the end of it all. */
+
+ if ((current_monitor->flags & MO_NO_ECHO_ON_OPEN) == 0)
+ monitor_printf(*p);
+ else
+ monitor_printf_noecho (*p);
monitor_expect_prompt (NULL, 0);
}
/* Close out all files and local state before this target loses
control. */
-static void
+void
monitor_close (quitting)
int quitting;
{
int regno;
char *valstr;
{
- unsigned LONGEST val;
+ unsigned int val;
unsigned char regbuf[MAX_REGISTER_RAW_SIZE];
char *p;
}
}
-/* Parse the output of a register dump command. A monitor specific regexp is
- used to extract individual register descriptions of the form REG=VAL. Each
- description is split up into a name and a value string which are passed down
- to monitor specific code. */
+/* Parse the output of a register dump command. A monitor specific
+ regexp is used to extract individual register descriptions of the
+ form REG=VAL. Each description is split up into a name and a value
+ string which are passed down to monitor specific code. */
static char *
parse_register_dump (buf, len)
{
int regnamelen, vallen;
char *regname, *val;
-/* Element 0 points to start of register name, and element 1 points to the
- start of the register value. */
+ /* Element 0 points to start of register name, and element 1
+ points to the start of the register value. */
struct re_registers register_strings;
if (re_search (®ister_pattern, buf, len, 0, len,
monitor_printf (current_monitor->getreg.cmd, name);
- /* If RESP_DELIM is specified, we search for that as a leading delimiter for
- the register value. Otherwise, we just start searching from the start of
- the buf. */
+ /* If RESP_DELIM is specified, we search for that as a leading
+ delimiter for the register value. Otherwise, we just start
+ searching from the start of the buf. */
if (current_monitor->getreg.resp_delim)
monitor_expect (current_monitor->getreg.resp_delim, NULL, 0);
regbuf[i] = '\000'; /* terminate the number */
- /* If TERM is present, we wait for that to show up. Also, (if TERM is
- present), we will send TERM_CMD if that is present. In any case, we collect
- all of the output into buf, and then wait for the normal prompt. */
+ /* If TERM is present, we wait for that to show up. Also, (if TERM
+ is present), we will send TERM_CMD if that is present. In any
+ case, we collect all of the output into buf, and then wait for
+ the normal prompt. */
if (current_monitor->getreg.term)
{
{
char buf[200];
int resp_len;
+
monitor_printf (current_monitor->dump_registers);
resp_len = monitor_expect_prompt (buf, sizeof (buf));
parse_register_dump (buf, resp_len);
int regno;
{
char *name;
- unsigned LONGEST val;
+ unsigned int val;
name = REGNAMES (regno);
if (!name)
monitor_printf (current_monitor->setreg.cmd, name, val);
-/* It's possible that there are actually some monitors out there that will
- prompt you when you set a register. In that case, you may need to add some
- code here to deal with TERM and TERM_CMD (see monitor_fetch_register to get
- an idea of what's needed...) */
+/* It's possible that there are actually some monitors out there that
+ will prompt you when you set a register. In that case, you may
+ need to add some code here to deal with TERM and TERM_CMD (see
+ monitor_fetch_register to get an idea of what's needed...) */
monitor_expect_prompt (NULL, 0);
}
char *myaddr;
int len;
{
- unsigned LONGEST val;
+ unsigned int val;
char *cmd;
int i;
char *myaddr;
int len;
{
- unsigned LONGEST val;
- char membuf[sizeof(LONGEST) * 2 + 1];
+ unsigned int val;
+ char membuf[sizeof(int) * 2 + 1];
char *p;
char *cmd;
int i;
the buf. */
if (current_monitor->getmem.resp_delim)
- monitor_expect_regexp (getmem_resp_delim_pattern, NULL, 0);
+ monitor_expect_regexp (&getmem_resp_delim_pattern, NULL, 0);
/* Now, read the appropriate number of hex digits for this loc, skipping
spaces. */
char *myaddr;
int len;
{
- unsigned LONGEST val;
+ unsigned int val;
unsigned char regbuf[MAX_REGISTER_RAW_SIZE];
char buf[512];
char *p, *p1;
static void
monitor_stop ()
{
+ if ((current_monitor->flags & MO_SEND_BREAK_ON_STOP) != 0)
+ SERIAL_SEND_BREAK (monitor_desc);
if (current_monitor->stop)
monitor_printf_noecho (current_monitor->stop);
}