* tracepoint.c (trace_start_command): Set trace_running_p.
[deliverable/binutils-gdb.git] / gdb / monitor.c
index 1b5553a2a34d9eed7cb4fd83e8cff78d74052fa7..03bfa598dc6d5f550d39e4647670b061def527d1 100644 (file)
@@ -1,5 +1,5 @@
 /* Remote debugging interface for boot monitors, for GDB.
-   Copyright 1990, 1991, 1992, 1993, 1995, 1996
+   Copyright 1990, 1991, 1992, 1993, 1995, 1996, 1997
    Free Software Foundation, Inc.
    Contributed by Cygnus Support.  Written by Rob Savoye for Cygnus.
    Resurrected from the ashes by Stu Grossman.
@@ -88,15 +88,17 @@ static void monitor_kill PARAMS ((void));
 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 *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));
+#if 0
 static int from_hex PARAMS ((int a));
 static unsigned long get_hex_word PARAMS ((void));
+#endif
+static void parse_register_dump PARAMS ((char *, int));
 
 static struct monitor_ops *current_monitor;
 
@@ -129,68 +131,18 @@ static DCACHE *remote_dcache;
 static int first_time=0;       /* is this the first time we're executing after 
                                        gaving created the child proccess? */
 
-/* monitor_debug is like fputs_unfiltered, except it prints special
-   characters in printable fashion.  */
+/* Convert hex digit A to a number.  */
 
-static void
-monitor_debug (prefix, string, suffix)
-     char *prefix;
-     char *string;
-     char *suffix;
+static int
+fromhex (a)
+     int a;
 {
-  int ch;
-
-  /* print prefix and suffix after each line */
-  static int new_line=1;
-  static char *prev_prefix = "";
-  static char *prev_suffix = "";
-
-  /* if the prefix is changing, print the previous suffix, a new line,
-     and the new prefix */
-  if (strcmp(prev_prefix, prefix) != 0 && !new_line)
-    {
-      fputs_unfiltered (prev_suffix, gdb_stderr);
-      fputs_unfiltered ("\n", gdb_stderr);
-      fputs_unfiltered (prefix, gdb_stderr);
-    }
-  prev_prefix = prefix;
-  prev_suffix = suffix;
-
-  /* print prefix if last char was a newline*/
-
-  if (new_line == 1) {
-    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) {
-      default:
-       if (isprint (ch))
-         fputc_unfiltered (ch, gdb_stderr);
-
-       else
-         fprintf_unfiltered (gdb_stderr, "\\%03o", ch);
-
-       break;
-
-      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",   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);
-  }
+  if (a >= '0' && a <= '9')
+    return a - '0';
+  else if (a >= 'a' && a <= 'f')
+    return a - 'a' + 10;
+  else 
+    error ("Invalid hex digit %d", a);
 }
 
 /* monitor_printf_noecho -- Send data to monitor, but don't expect an echo.
@@ -219,15 +171,14 @@ monitor_printf_noecho (va_alist)
   vsprintf (sndbuf, pattern, args);
 
   if (remote_debug > 0)
-    monitor_debug ("sent -->", sndbuf, "<--");
+    puts_debug ("sent -->", sndbuf, "<--");
 
   len = strlen (sndbuf);
 
   if (len + 1 > sizeof sndbuf)
     abort ();
 
-  if (SERIAL_WRITE(monitor_desc, sndbuf, len))
-    fprintf_unfiltered (stderr, "SERIAL_WRITE failed: %s\n", safe_strerror (errno));
+  monitor_write (sndbuf, len);
 }
 
 /* monitor_printf -- Send data to monitor and check the echo.  Works just like
@@ -256,15 +207,14 @@ monitor_printf (va_alist)
   vsprintf (sndbuf, pattern, args);
 
   if (remote_debug > 0)
-    monitor_debug ("sent -->", sndbuf, "<--");
+    puts_debug ("sent -->", sndbuf, "<--");
 
   len = strlen (sndbuf);
 
   if (len + 1 > sizeof sndbuf)
     abort ();
 
-  if (SERIAL_WRITE(monitor_desc, sndbuf, len))
-    fprintf_unfiltered (stderr, "SERIAL_WRITE failed: %s\n", safe_strerror (errno));
+  monitor_write (sndbuf, len);
 
   /* We used to expect that the next immediate output was the characters we
      just output, but sometimes some extra junk appeared before the characters
@@ -273,6 +223,49 @@ monitor_printf (va_alist)
   monitor_expect (sndbuf, (char *)0, 0);
 }
 
+
+/* Write characters to the remote system.  */
+
+void
+monitor_write (buf, buflen)
+     char *buf;
+     int buflen;
+{
+  if (SERIAL_WRITE(monitor_desc, buf, buflen))
+    fprintf_unfiltered (stderr, "SERIAL_WRITE failed: %s\n", safe_strerror (errno));
+}
+
+
+/* Read a binary character from the remote system, doing all the fancy
+   timeout stuff, but without interpreting the character in any way,
+   and without printing remote debug information.  */
+
+int
+monitor_readchar ()
+{
+  int c;
+  int looping;
+
+  do
+    {
+      looping = 0;
+      c = SERIAL_READCHAR (monitor_desc, timeout);
+
+      if (c >= 0)
+       c &= 0xff;                      /* don't lose bit 7 */
+    }
+  while (looping);
+
+  if (c >= 0)
+    return c;
+
+  if (c == SERIAL_TIMEOUT)
+      error ("Timeout reading from remote system.");
+
+  perror_with_name ("remote-monitor");
+}
+
+
 /* Read a character from the remote system, doing all the fancy
    timeout stuff.  */
 
@@ -297,7 +290,7 @@ readchar (timeout)
              char buf[2];
              buf[0] = c;
              buf[1] = '\0';
-             monitor_debug ("read -->", buf, "<--");
+             puts_debug ("read -->", buf, "<--");
            }
        }
 
@@ -459,14 +452,13 @@ monitor_expect_regexp (pat, buf, buflen)
    o give your command
    o *then* wait for the prompt.
 
-   Thus the last thing that a procedure does with the serial line
-   will be an monitor_expect_prompt().  Exception:  monitor_resume does not
-   wait for the prompt, because the terminal is being handed over
-   to the inferior.  However, the next thing which happens after that
-   is a monitor_wait which does wait for the prompt.
-   Note that this includes abnormal exit, e.g. error().  This is
-   necessary to prevent getting into states from which we can't
-   recover.  */
+   Thus the last thing that a procedure does with the serial line will
+   be an monitor_expect_prompt().  Exception: monitor_resume does not
+   wait for the prompt, because the terminal is being handed over to
+   the inferior.  However, the next thing which happens after that is
+   a monitor_wait which does wait for the prompt.  Note that this
+   includes abnormal exit, e.g. error().  This is necessary to prevent
+   getting into states from which we can't recover.  */
 
 int
 monitor_expect_prompt (buf, buflen)
@@ -479,6 +471,7 @@ monitor_expect_prompt (buf, buflen)
 /* Get N 32-bit words from remote, each preceded by a space, and put
    them in registers starting at REGNO.  */
 
+#if 0
 static unsigned long
 get_hex_word ()
 {
@@ -502,6 +495,7 @@ get_hex_word ()
 
   return val;
 }
+#endif
 
 static void
 compile_pattern (pattern, compiled_pattern, fastmap)
@@ -537,7 +531,6 @@ monitor_open (args, mon_ops, from_tty)
      int from_tty;
 {
   char *name;
-  int i;
   char **p;
 
   if (mon_ops->magic != MONITOR_OPS_MAGIC)
@@ -726,7 +719,7 @@ monitor_resume (pid, step, sig)
    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 *
+static void
 parse_register_dump (buf, len)
      char *buf;
      int len;
@@ -846,6 +839,16 @@ monitor_wait (pid, status)
     }
   while (resp_len < 0);
 
+  /* Print any output characters that were preceded by ^O.  */
+  if (current_monitor->flags & MO_PRINT_PROGRAM_OUTPUT)
+    {
+      int i;
+
+      for (i = 0; i < resp_len - 1; i++)
+       if (buf[i] == 0x0f)
+         putchar_unfiltered (buf[++i]);
+    }
+
   signal (SIGINT, ofunc);
 
   timeout = old_timeout;
@@ -900,7 +903,13 @@ monitor_fetch_register (regno)
      searching from the start of the buf.  */
 
   if (current_monitor->getreg.resp_delim)
-    monitor_expect (current_monitor->getreg.resp_delim, NULL, 0);
+    {
+      monitor_expect (current_monitor->getreg.resp_delim, NULL, 0);
+      /* Handle case of first 32 registers listed in pairs.  */
+      if (current_monitor->flags & MO_32_REGS_PAIRED
+         && regno & 1 == 1 && regno < 32)
+       monitor_expect (current_monitor->getreg.resp_delim, NULL, 0);
+    }
 
   /* Skip leading spaces and "0x" if MO_HEX_PREFIX flag is set */
   if (current_monitor->flags & MO_HEX_PREFIX) 
@@ -958,7 +967,8 @@ monitor_fetch_register (regno)
 
 /* Read the remote registers into the block regs.  */
 
-static void monitor_dump_regs ()
+static void
+monitor_dump_regs ()
 {
   char buf[1024];
   int resp_len;
@@ -1008,19 +1018,26 @@ monitor_store_register (regno)
 
   val = read_register (regno);
 
- /* send the register deposit command */
 /* send the register deposit command */
 
   if (current_monitor->flags & MO_REGISTER_VALUE_FIRST)
     monitor_printf (current_monitor->setreg.cmd, val, name);
+  else if (current_monitor->flags & MO_SETREG_INTERACTIVE)
+    monitor_printf (current_monitor->setreg.cmd, name);
   else
     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...) */
+  if (current_monitor->setreg.term)
+    {
+      monitor_expect (current_monitor->setreg.term, NULL, 0);
+
+      if (current_monitor->flags & MO_SETREG_INTERACTIVE)
+       monitor_printf ("%x\r", val);
 
-  monitor_expect_prompt (NULL, 0);
+      monitor_expect_prompt (NULL, 0);
+    }
+  else
+    monitor_expect_prompt (NULL, 0);
 }
 
 /* Store the remote registers.  */
@@ -1068,6 +1085,9 @@ monitor_write_memory (memaddr, myaddr, len)
   char *cmd;
   int i;
 
+  if (current_monitor->flags & MO_ADDR_BITS_REMOVE)
+    memaddr = ADDR_BITS_REMOVE (memaddr);
+
   /* Use memory fill command for leading 0 bytes.  */
 
   if (current_monitor->fill)
@@ -1118,6 +1138,19 @@ monitor_write_memory (memaddr, myaddr, len)
 
   if (current_monitor->flags & MO_NO_ECHO_ON_SETMEM)
     monitor_printf_noecho (cmd, memaddr, val);
+  else if (current_monitor->flags & MO_SETMEM_INTERACTIVE)
+    {
+
+      monitor_printf_noecho (cmd, memaddr);
+
+      if (current_monitor->setmem.term)
+       {
+         monitor_expect (current_monitor->setmem.term, NULL, 0);
+
+         monitor_printf ("%x\r", val);
+
+       }
+    }
   else
     monitor_printf (cmd, memaddr, val);
 
@@ -1168,32 +1201,33 @@ monitor_read_memory_single (memaddr, myaddr, len)
       cmd = current_monitor->getmem.cmdb;
     }
 
-/* Send the examine command.  */
+  /* Send the examine command.  */
 
   monitor_printf (cmd, memaddr);
 
-/* 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 memory value.  Otherwise, we just start
+     searching from the start of the buf.  */
 
   if (current_monitor->getmem.resp_delim)
     monitor_expect_regexp (&getmem_resp_delim_pattern, NULL, 0);
 
-/* Now, read the appropriate number of hex digits for this loc, skipping
-   spaces.  */
+  /* Now, read the appropriate number of hex digits for this loc,
+     skipping spaces.  */
 
-  /* Skip leading spaces and "0x" if MO_HEX_PREFIX flag is set */
+  /* Skip leading spaces and "0x" if MO_HEX_PREFIX flag is set. */
   if (current_monitor->flags & MO_HEX_PREFIX) 
     {
       int c;
+
       c = readchar (timeout);
       while (c == ' ')
        c = readchar (timeout);
       if ((c == '0') && ((c = readchar (timeout)) == 'x'))
        ;
       else
-         error ("monitor_read_memory_single (0x%x):  bad response from monitor: %.*s%c.",
-                memaddr, i, membuf, c);
+       error ("monitor_read_memory_single (0x%x):  bad response from monitor: %.*s%c.",
+              memaddr, i, membuf, c);
     }
   for (i = 0; i < len * 2; i++)
     {
@@ -1247,9 +1281,9 @@ monitor_read_memory_single (memaddr, myaddr, len)
   return len;
 }
 
-/* Copy LEN bytes of data from debugger memory at MYADDR to inferior's memory
-   at MEMADDR.  Returns length moved.  Currently, we only do one byte at a
-   time.  */
+/* Copy LEN bytes of data from debugger memory at MYADDR to inferior's
+   memory at MEMADDR.  Returns length moved.  Currently, we do no more
+   than 16 bytes at a time.  */
 
 static int
 monitor_read_memory (memaddr, myaddr, len)
@@ -1258,32 +1292,39 @@ monitor_read_memory (memaddr, myaddr, len)
      int len;
 {
   unsigned int val;
-  unsigned char regbuf[MAX_REGISTER_RAW_SIZE];
   char buf[512];
   char *p, *p1;
-  char *name;
   int resp_len;
   int i;
+  CORE_ADDR dumpaddr;
+
+  if (current_monitor->flags & MO_ADDR_BITS_REMOVE)
+    memaddr = ADDR_BITS_REMOVE (memaddr);
 
   if (current_monitor->flags & MO_GETMEM_READ_SINGLE)
     return monitor_read_memory_single (memaddr, myaddr, len);
 
   len = min (len, 16);
 
-/* See if xfer would cross a 16 byte boundary.  If so, clip it.  */
+  dumpaddr = memaddr & ~0xf;
+
+  /* See if xfer would cross a 16 byte boundary.  If so, clip it.  */
   if (((memaddr ^ (memaddr + len - 1)) & ~0xf) != 0)
     len = ((memaddr + len) & ~0xf) - memaddr;
 
- /* send the memory examine command */
 /* send the memory examine command */
 
   if (current_monitor->flags & MO_GETMEM_NEEDS_RANGE)
     monitor_printf (current_monitor->getmem.cmdb, memaddr, memaddr + len - 1);
+  else if (current_monitor->flags & MO_GETMEM_16_BOUNDARY)
+    monitor_printf (current_monitor->getmem.cmdb, dumpaddr);
   else
     monitor_printf (current_monitor->getmem.cmdb, memaddr, len);
 
-/* 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->getmem.term)
     {
@@ -1305,9 +1346,9 @@ monitor_read_memory (memaddr, myaddr, len)
 
   p = buf;
 
-  /* If RESP_DELIM is specified, we search for that as a leading delimiter for
-     the values.  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 values.  Otherwise, we just start searching
+     from the start of the buf.  */
 
   if (current_monitor->getmem.resp_delim)
     {
@@ -1332,6 +1373,27 @@ monitor_read_memory (memaddr, myaddr, len)
 #endif
     }
 
+  if (current_monitor->flags & MO_GETMEM_16_BOUNDARY)
+    {
+      i = len;
+      while (!(*p == '\000' || *p == '\n' || *p == '\r') && i > 0)
+       {
+         if (isxdigit (*p))
+           {
+             if (dumpaddr >= memaddr && i > 0)
+               {
+                 val = fromhex (*p) * 16 + fromhex (*(p+1));
+                 *myaddr++ = val;
+                 --i;
+               }
+             ++dumpaddr;
+             ++p;
+           }
+         ++p;
+       }
+      return len;
+    }
+
   for (i = len; i > 0; i--)
     {
       /* Skip non-hex chars, but bomb on end of string and newlines */
@@ -1340,6 +1402,7 @@ monitor_read_memory (memaddr, myaddr, len)
        {
          if (isxdigit (*p))
            break;
+
          if (*p == '\000' || *p == '\n' || *p == '\r')
            error ("monitor_read_memory (0x%x):  badly terminated response from monitor: %.*s", memaddr, resp_len, buf);
          p++;
@@ -1420,14 +1483,24 @@ monitor_insert_breakpoint (addr, shadow)
      char *shadow;
 {
   int i;
-  static unsigned char break_insn[] = BREAKPOINT;
+  unsigned char *bp;
+  int bplen;
+
+  if (current_monitor->set_break == NULL)
+    error ("No set_break defined for this monitor");
+
+  if (current_monitor->flags & MO_ADDR_BITS_REMOVE)
+    addr = ADDR_BITS_REMOVE (addr);
+
+  /* Determine appropriate breakpoint size for this address.  */
+  bp = memory_breakpoint_from_pc (&addr, &bplen);
 
   for (i = 0; i < NUM_MONITOR_BREAKPOINTS; i++)
     {
       if (breakaddr[i] == 0)
        {
          breakaddr[i] = addr;
-         monitor_read_memory (addr, shadow, sizeof (break_insn));
+         monitor_read_memory (addr, shadow, bplen);
          monitor_printf (current_monitor->set_break, addr);
          monitor_expect_prompt (NULL, 0);
          return 0;
@@ -1446,14 +1519,22 @@ monitor_remove_breakpoint (addr, shadow)
 {
   int i;
 
+  if (current_monitor->clr_break == NULL)
+    error ("No clr_break defined for this monitor");
+
+  if (current_monitor->flags & MO_ADDR_BITS_REMOVE)
+    addr = ADDR_BITS_REMOVE (addr);
+
   for (i = 0; i < NUM_MONITOR_BREAKPOINTS; i++)
     {
       if (breakaddr[i] == addr)
        {
          breakaddr[i] = 0;
          /* some monitors remove breakpoints based on the address */
-         if (current_monitor->flags & MO_CLR_BREAK_USES_ADDR)   
+         if (current_monitor->flags & MO_CLR_BREAK_USES_ADDR)
            monitor_printf (current_monitor->clr_break, addr);
+         else if (current_monitor->flags & MO_CLR_BREAK_1_BASED)
+           monitor_printf (current_monitor->clr_break, i + 1);
          else
            monitor_printf (current_monitor->clr_break, i);
          monitor_expect_prompt (NULL, 0);
@@ -1470,10 +1551,25 @@ monitor_remove_breakpoint (addr, shadow)
 static int
 monitor_wait_srec_ack ()
 {
-  /* FIXME: eventually we'll want to be able to handle acknowledgements
-     of something other than a '+' character.  Right now this is only
-     going to work for EST visionICE.  */
-  return readchar (timeout) == '+';
+  int i, ch;
+
+  if (current_monitor->flags & MO_SREC_ACK_PLUS)
+    {
+      return (readchar (timeout) == '+');
+    }
+  else if (current_monitor->flags & MO_SREC_ACK_ROTATE)
+    {
+      /* Eat two backspaces, a "rotating" char (|/-\), and a space.  */
+      if ((ch = readchar (1)) < 0)
+       return 0;
+      if ((ch = readchar (1)) < 0)
+       return 0;
+      if ((ch = readchar (1)) < 0)
+       return 0;
+      if ((ch = readchar (1)) < 0)
+       return 0;
+    }
+  return 1;
 }
 
 /* monitor_load -- download a file. */
@@ -1489,12 +1585,23 @@ monitor_load (file, from_tty)
     current_monitor->load_routine (monitor_desc, file, hashmark);
   else
     {                          /* The default is ascii S-records */
+      int n;
+      unsigned long load_offset;
+      char buf[128];
+
+      /* enable user to specify address for downloading as 2nd arg to load */
+      n = sscanf (file, "%s 0x%lx", buf, &load_offset);
+      if (n > 1)
+       file = buf;
+      else
+       load_offset = 0;
+
       monitor_printf (current_monitor->load);
       if (current_monitor->loadresp)
        monitor_expect (current_monitor->loadresp, NULL, 0);
 
-/* FIXME Should add arg here for load_offset (already done for generic_load) */
-      load_srec (monitor_desc, file, 32, SREC_ALL, hashmark,
+      load_srec (monitor_desc, file, (bfd_vma) load_offset,
+                32, SREC_ALL, hashmark,
                 current_monitor->flags & MO_SREC_ACK ?
                   monitor_wait_srec_ack : NULL);
 
@@ -1556,6 +1663,7 @@ monitor_command (args, from_tty)
 
 /* Convert hex digit A to a number.  */
 
+#if 0
 static int
 from_hex (a)
      int a;
@@ -1569,6 +1677,13 @@ from_hex (a)
 
   error ("Reply contains invalid hex digit 0x%x", a);
 }
+#endif
+
+char *
+monitor_get_dev_name ()
+{
+  return dev_name;
+}
 
 static struct target_ops monitor_ops =
 {
This page took 0.030599 seconds and 4 git commands to generate.