/* Remote debugging interface for boot monitors, for GDB.
- Copyright 1990-1993, 1995-1997, 1999-2000 Free Software Foundation, Inc.
+ Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+ 2000, 2001 Free Software Foundation, Inc.
Contributed by Cygnus Support. Written by Rob Savoye for Cygnus.
Resurrected from the ashes by Stu Grossman.
/* This file was derived from various remote-* modules. It is a collection
of generic support functions so GDB can talk directly to a ROM based
monitor. This saves use from having to hack an exception based handler
- into existance, and makes for quick porting.
+ into existence, and makes for quick porting.
This module talks to a debug monitor called 'MONITOR', which
We communicate with MONITOR via either a direct serial line, or a TCP
#include "defs.h"
#include "gdbcore.h"
#include "target.h"
-#include "gdb_wait.h"
#include <signal.h>
#include <ctype.h>
#include "gdb_string.h"
#include "gdbcmd.h"
#include "inferior.h"
#include "gdb_regex.h"
-#include "dcache.h"
#include "srec.h"
+#include "regcache.h"
static char *dev_name;
static struct target_ops *targ_ops;
static void monitor_printable_string (char *newstr, char *oldstr, int len);
static void monitor_error (char *function, char *message, CORE_ADDR memaddr, int len, char *string, int final_char);
static void monitor_detach (char *args, int from_tty);
-static void monitor_resume (int pid, int step, enum target_signal sig);
+static void monitor_resume (ptid_t ptid, int step, enum target_signal sig);
static void monitor_interrupt (int signo);
static void monitor_interrupt_twice (int signo);
static void monitor_interrupt_query (void);
static void monitor_wait_cleanup (void *old_timeout);
-static int monitor_wait (int pid, struct target_waitstatus *status);
+static ptid_t monitor_wait (ptid_t ptid, struct target_waitstatus *status);
static void monitor_fetch_registers (int regno);
static void monitor_store_registers (int regno);
static void monitor_prepare_to_store (void);
static int monitor_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len,
- int write, struct target_ops *target);
+ int write,
+ struct mem_attrib *attrib,
+ struct target_ops *target);
static void monitor_files_info (struct target_ops *ops);
static int monitor_insert_breakpoint (CORE_ADDR addr, char *shadow);
static int monitor_remove_breakpoint (CORE_ADDR addr, char *shadow);
that monitor_open knows that we don't have a file open when the
program starts. */
-static serial_t monitor_desc = NULL;
+static struct serial *monitor_desc = NULL;
/* Pointer to regexp pattern matching data */
static struct re_pattern_buffer getmem_resp_delim_pattern;
static char getmem_resp_delim_fastmap[256];
+static struct re_pattern_buffer setmem_resp_delim_pattern;
+static char setmem_resp_delim_fastmap[256];
+
+static struct re_pattern_buffer setreg_resp_delim_pattern;
+static char setreg_resp_delim_fastmap[256];
+
static int dump_reg_flag; /* Non-zero means do a dump_registers cmd when
monitor_wait wakes up. */
-static DCACHE *remote_dcache;
static int first_time = 0; /* is this the first time we're executing after
gaving created the child proccess? */
len = strlen (sndbuf);
if (len + 1 > sizeof sndbuf)
- abort ();
+ internal_error (__FILE__, __LINE__, "failed internal consistency check");
if (monitor_debug_p)
{
len = strlen (sndbuf);
if (len + 1 > sizeof sndbuf)
- abort ();
+ internal_error (__FILE__, __LINE__, "failed internal consistency check");
if (monitor_debug_p)
{
compile_pattern (mon_ops->getmem.resp_delim, &getmem_resp_delim_pattern,
getmem_resp_delim_fastmap);
+ if (mon_ops->setmem.resp_delim)
+ compile_pattern (mon_ops->setmem.resp_delim, &setmem_resp_delim_pattern,
+ setmem_resp_delim_fastmap);
+
+ if (mon_ops->setreg.resp_delim)
+ compile_pattern (mon_ops->setreg.resp_delim, &setreg_resp_delim_pattern,
+ setreg_resp_delim_fastmap);
+
unpush_target (targ_ops);
if (dev_name)
- free (dev_name);
- dev_name = strsave (args);
+ xfree (dev_name);
+ dev_name = xstrdup (args);
monitor_desc = SERIAL_OPEN (dev_name);
push_target (targ_ops);
- inferior_pid = 42000; /* Make run command think we are busy... */
+ inferior_ptid = pid_to_ptid (42000); /* Make run command think we are busy... */
/* Give monitor_wait something to read */
monitor_printf (current_monitor->line_term);
- if (remote_dcache)
- dcache_free (remote_dcache);
-
- if (current_monitor->flags & MO_HAS_BLOCKWRITES)
- remote_dcache = dcache_init (monitor_read_memory,
- monitor_write_memory_block);
- else
- remote_dcache = dcache_init (monitor_read_memory, monitor_write_memory);
-
start_remote ();
}
/* Free breakpoint memory */
if (breakaddr != NULL)
{
- free (breakaddr);
+ xfree (breakaddr);
breakaddr = NULL;
}
}
monitor_debug ("Supplying Register %d %s\n", regno, valstr);
- if (*p != '\0')
+ if (val == 0 && valstr == p)
error ("monitor_supply_register (%d): bad value from monitor: %s.",
regno, valstr);
/* Tell the remote machine to resume. */
-void
-flush_monitor_dcache (void)
-{
- dcache_invd (remote_dcache);
-}
-
static void
-monitor_resume (int pid, int step, enum target_signal sig)
+monitor_resume (ptid_t ptid, int step, enum target_signal sig)
{
/* Some monitors require a different command when starting a program */
monitor_debug ("MON resume\n");
dump_reg_flag = 1;
return;
}
- dcache_invd (remote_dcache);
if (step)
monitor_printf (current_monitor->step);
else
/* Wait until the remote machine stops, then return, storing status in
status just as `wait' would. */
-static int
-monitor_wait (int pid, struct target_waitstatus *status)
+static ptid_t
+monitor_wait (ptid_t ptid, struct target_waitstatus *status)
{
int old_timeout = timeout;
char buf[TARGET_BUF_SIZE];
in_monitor_wait = 0;
- return inferior_pid;
+ return inferior_ptid;
}
/* Fetch register REGNO, or all registers if REGNO is -1. Returns
parse_register_dump (buf, resp_len);
}
else
- abort (); /* Need some way to read registers */
+ internal_error (__FILE__, __LINE__, "failed internal consistency check"); /* Need some way to read registers */
}
static void
else
monitor_printf (current_monitor->setreg.cmd, name, val);
+ if (current_monitor->setreg.resp_delim)
+ {
+ monitor_debug ("EXP setreg.resp_delim\n");
+ monitor_expect_regexp (&setreg_resp_delim_pattern, NULL, 0);
+ if (current_monitor->flags & MO_SETREG_INTERACTIVE)
+ monitor_printf ("%s\r", paddr_nz (val));
+ }
if (current_monitor->setreg.term)
{
monitor_debug ("EXP setreg.term\n");
monitor_printf_noecho (cmd, memaddr);
+ if (current_monitor->setmem.resp_delim)
+ {
+ monitor_debug ("EXP setmem.resp_delim");
+ monitor_expect_regexp (&setmem_resp_delim_pattern, NULL, 0);
+ monitor_printf ("%x\r", val);
+ }
if (current_monitor->setmem.term)
{
monitor_debug ("EXP setmem.term");
char membuf[sizeof (int) * 2 + 1];
char *p;
char *cmd;
- int i;
monitor_debug ("MON read single\n");
#if 0
else
monitor_error ("monitor_read_memory_single",
"bad response from monitor",
- memaddr, i, membuf, c);
+ memaddr, 0, NULL, 0);
}
- for (i = 0; i < len * 2; i++)
- {
- int c;
- while (1)
- {
- c = readchar (timeout);
- if (isxdigit (c))
- break;
- if (c == ' ')
- continue;
-
- monitor_error ("monitor_read_memory_single",
- "bad response from monitor",
- memaddr, i, membuf, c);
- }
+ {
+ int i;
+ for (i = 0; i < len * 2; i++)
+ {
+ int c;
+ while (1)
+ {
+ c = readchar (timeout);
+ if (isxdigit (c))
+ break;
+ if (c == ' ')
+ continue;
+
+ monitor_error ("monitor_read_memory_single",
+ "bad response from monitor",
+ memaddr, i, membuf, 0);
+ }
membuf[i] = c;
}
-
- membuf[i] = '\000'; /* terminate the number */
+ membuf[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
return len;
}
+/* Transfer LEN bytes between target address MEMADDR and GDB address
+ MYADDR. Returns 0 for success, errno code for failure. TARGET is
+ unused. */
+
static int
-monitor_xfer_memory (memaddr, myaddr, len, write, target)
- CORE_ADDR memaddr;
- char *myaddr;
- int len;
- int write;
- struct target_ops *target; /* ignored */
+monitor_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int write,
+ struct mem_attrib *attrib ATTRIBUTE_UNUSED,
+ struct target_ops *target ATTRIBUTE_UNUSED)
{
- return dcache_xfer_memory (remote_dcache, memaddr, myaddr, len, write);
+ int res;
+
+ if (write)
+ {
+ if (current_monitor->flags & MO_HAS_BLOCKWRITES)
+ res = monitor_write_memory_block(memaddr, myaddr, len);
+ else
+ res = monitor_write_memory(memaddr, myaddr, len);
+ }
+ else
+ {
+ res = monitor_read_memory(memaddr, myaddr, len);
+ }
+
+ return res;
}
static void
static void
monitor_load (char *file, int from_tty)
{
- dcache_invd (remote_dcache);
monitor_debug ("MON load\n");
if (current_monitor->load_routine)
if (exec_bfd)
write_pc (bfd_get_start_address (exec_bfd));
- inferior_pid = 0; /* No process now */
+ inferior_ptid = null_ptid ; /* No process now */
/* This is necessary because many things were based on the PC at the time that
we attached to the monitor, which is no longer valid now that we have loaded
monitor_ops.to_stop = monitor_stop;
monitor_ops.to_rcmd = monitor_rcmd;
monitor_ops.to_pid_to_exec_file = NULL;
- monitor_ops.to_core_file_to_sym_file = NULL;
monitor_ops.to_stratum = process_stratum;
monitor_ops.DONT_USE = 0;
monitor_ops.to_has_all_memory = 1;