* monitor.c (monitor_load_srec monitor_make_srec): Move all
authorStu Grossman <grossman@cygnus>
Tue, 14 Nov 1995 23:24:10 +0000 (23:24 +0000)
committerStu Grossman <grossman@cygnus>
Tue, 14 Nov 1995 23:24:10 +0000 (23:24 +0000)
S-record download code into srec.c.
* srec.c srec.h:  New files.  Contain S-record loading routines
formerly in monitor.c.
* serial.c serial.h:  New routine just like fprintf, but uses
serial_t instead of FILE *.
* sh-tdep.c (frame_find_saved_regs init_extra_frame_info):
Don't add four to saved pc (makes things match manual).  Also, fix
bug where we didn't get pc from stack frame correctly.
* config/sh/tm-sh.h (SAVED_PC_AFTER_CALL):  Don't add four to
saved pc.  Real hardware does this for you.
* sh3-rom.c (sh3_load):  New routine.  Sets up for download then
calls generic S-record loader.
* config/h8300/h8300.mt, config/h8500/h8500.mt,
config/m68k/monitor.mt, config/pa/hppapro.mt, config/sh/sh.mt:
Add srec.o to TDEPFILES.

gdb/.Sanitize
gdb/ChangeLog
gdb/serial.c
gdb/serial.h
gdb/sh-tdep.c
gdb/sh3-rom.c
gdb/srec.c [new file with mode: 0644]
gdb/srec.h [new file with mode: 0644]

index 0373b87a4a7cad296f693671d3e5cad104796de5..e5dfd52347d18af9b5eb6796e4a71992f7310347 100644 (file)
@@ -327,6 +327,8 @@ sparc-stub.c
 sparc-tdep.c
 sparcl-stub.c
 sparcl-tdep.c
+srec.c
+srec.h
 stabsread.c
 stabsread.h
 stack.c
index f36bb55f74d267100fc7ecfad9ab8ffe63ee2d01..c28ff5b1cd18bdc75366d43a13a0c16396b90777 100644 (file)
@@ -1,3 +1,22 @@
+Tue Nov 14 14:51:05 1995  Stu Grossman  (grossman@cygnus.com)
+
+       * monitor.c (monitor_load_srec monitor_make_srec):  Move all
+       S-record download code into srec.c.
+       * srec.c srec.h:  New files.  Contain S-record loading routines
+       formerly in monitor.c.
+       * serial.c serial.h:  New routine just like fprintf, but uses
+       serial_t instead of FILE *.
+       * sh-tdep.c (frame_find_saved_regs init_extra_frame_info):
+       Don't add four to saved pc (makes things match manual).  Also, fix
+       bug where we didn't get pc from stack frame correctly.
+       * config/sh/tm-sh.h (SAVED_PC_AFTER_CALL):  Don't add four to
+       saved pc.  Real hardware does this for you.
+       * sh3-rom.c (sh3_load):  New routine.  Sets up for download then
+       calls generic S-record loader.
+       * config/h8300/h8300.mt, config/h8500/h8500.mt,
+       config/m68k/monitor.mt, config/pa/hppapro.mt, config/sh/sh.mt:
+       Add srec.o to TDEPFILES.
+
 Tue Nov 14 15:57:36 1995  Michael Meissner  <meissner@tiktok.cygnus.com>
 
        * remote-ppcbug.c: New file to support the Motorola PPCBUG monitor
index 8a3a21b50600393f385fb7110ebfff6bfa07b5c3..ea886a6a3c92ec7835c453adff31dbe485ab5ff2 100644 (file)
@@ -307,6 +307,35 @@ connect_command (args, fromtty)
 }
 #endif /* 0 */
 
+/* VARARGS */
+void
+#ifdef ANSI_PROTOTYPES
+serial_printf (serial_t desc, const char *format, ...)
+#else
+serial_printf (va_alist)
+     va_dcl
+#endif
+{
+  va_list args;
+  char *buf;
+#ifdef ANSI_PROTOTYPES
+  va_start (args, format);
+#else
+  serial_t desc;
+  char *format;
+
+  va_start (args);
+  desc = va_arg (args, serial_t);
+  format = va_arg (args, char *);
+#endif
+
+  vasprintf (&buf, format, args);
+  SERIAL_WRITE (desc, buf, strlen (buf));
+
+  free (buf);
+  va_end (args);
+}
+
 void
 _initialize_serial ()
 {
index 60a6da34f7707711f03c4858b465b9c0986bde50..2cf06f36f5b84f56c8e6d7fbccad77233c665bbf 100644 (file)
@@ -167,4 +167,7 @@ void serial_close PARAMS ((serial_t, int));
 
 #define SERIAL_UN_FDOPEN(SERIAL_T) serial_close(SERIAL_T, 0)
 
+extern void serial_printf PARAMS ((serial_t desc, const char *, ...))
+     ATTR_FORMAT(printf, 2, 3);
+
 #endif /* SERIAL_H */
index 95a3f1969c8366fb5add898dd12c6d40bd663def..a56c826e9fb6798c1849262d60413caad9246182 100644 (file)
@@ -213,23 +213,11 @@ frame_find_saved_regs (fi, fsr)
   fi->f_offset = depth - where[FP_REGNUM] - 4;
   /* Work out the return pc - either from the saved pr or the pr
      value */
-  /* Just called, so dig out the real return */
-  if (fi->return_pc == 0)
-    {
-      fi->return_pc = read_register (PR_REGNUM) + 4;
-    }
-  else
-    {
 
-      if (fsr->regs[PR_REGNUM])
-       {
-         fi->return_pc = read_memory_integer (fsr->regs[PR_REGNUM], 4) + 4;
-       }
-      else
-       {
-         fi->return_pc = read_register (PR_REGNUM) + 4;
-       }
-    }
+  if (fsr->regs[PR_REGNUM])
+    fi->return_pc = read_memory_integer (fsr->regs[PR_REGNUM], 4);
+  else
+    fi->return_pc = read_register (PR_REGNUM);
 }
 
 /* initialize the extra info saved in a FRAME */
@@ -241,6 +229,9 @@ init_extra_frame_info (fromleaf, fi)
 {
   struct frame_saved_regs dummy;
 
+  if (fi->next)
+    fi->pc = fi->next->return_pc;
+
   frame_find_saved_regs (fi, &dummy);
 }
 
index b52fa5e6b0dc5fec7d638962ec4436ee4d405f0d..0973bfd620a28fb1ee713509bcb1d5132d67e484 100644 (file)
@@ -22,6 +22,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #include "target.h"
 #include "monitor.h"
 #include "serial.h"
+#include "srec.h"
 
 static void sh3_open PARAMS ((char *args, int from_tty));
 
@@ -102,6 +103,24 @@ sh3_supply_register (regname, regnamelen, val, vallen)
       val = monitor_supply_register (regno++, val);
 }
 
+static void
+sh3_load (desc, file, hashmark)
+     serial_t desc;
+     char *file;
+     int hashmark;
+{
+  monitor_printf ("il;s:x\r");
+  monitor_expect ("\005", NULL, 0); /* Look for ENQ */
+  SERIAL_WRITE (desc, "\006", 1); /* Send ACK */
+  monitor_expect ("LO x\r", NULL, 0); /* Look for filename */
+
+  load_srec (desc, file, 80, SREC_ALL, hashmark);
+
+  monitor_expect ("\005", NULL, 0); /* Look for ENQ */
+  SERIAL_WRITE (desc, "\006", 1); /* Send ACK */
+  monitor_expect_prompt (NULL, 0);
+}
+
 /* This array of registers need to match the indexes used by GDB.
    This exists because the various ROM monitors use different strings
    than does GDB, and don't necessarily support all the registers
@@ -167,8 +186,8 @@ static struct monitor_ops sh3_cmds =
                                /* register_pattern */
   "\\(\\w+\\)=\\([0-9a-fA-F]+\\( +[0-9a-fA-F]+\\b\\)*\\)",
   sh3_supply_register,         /* supply_register */
-  NULL,                                /* load_routine (defaults to SRECs) */
-  "il;s:x\r\006",              /* download command */
+  sh3_load,                    /* load_routine */
+  NULL,                                /* download command */
   NULL,                                /* Load response */
   "\n:",                       /* monitor command prompt */
   "\r",                                /* end-of-line terminator */
diff --git a/gdb/srec.c b/gdb/srec.c
new file mode 100644 (file)
index 0000000..daf97c9
--- /dev/null
@@ -0,0 +1,254 @@
+/* S-record download support for GDB, the GNU debugger.
+   Copyright 1995 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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 2 of the License, or
+(at your option) any later version.
+
+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 this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+#include "defs.h"
+#include "serial.h"
+#include "srec.h"
+
+extern int remote_debug;
+
+static int make_srec PARAMS ((char *srec, CORE_ADDR targ_addr, bfd *abfd,
+                             asection *sect, int sectoff, int *maxrecsize,
+                             int flags));
+
+/*  Download an executable by converting it to S records.  DESC is a serial_t
+    to send the data to.  FILE is the name of the file to be loaded.
+    MAXRECSIZE is the length in chars of the largest S-record the host can
+    accomodate.  This is measured from the starting `S' to the last char of the
+    checksum.  FLAGS is various random flags, and HASHMARK is non-zero to cause
+    a `#' to be printed out for each record loaded.  */
+
+void
+load_srec (desc, file, maxrecsize, flags, hashmark)
+     serial_t desc;
+     const char *file;
+     int maxrecsize;
+     int flags;
+     int hashmark;
+{
+  bfd *abfd;
+  asection *s;
+  char *buffer, srec[1024];
+  int i;
+  int reclen;
+
+  buffer = alloca (maxrecsize + 1);
+
+  abfd = bfd_openr (file, 0);
+  if (!abfd)
+    {
+      printf_filtered ("Unable to open file %s\n", file);
+      return;
+    }
+
+  if (bfd_check_format (abfd, bfd_object) == 0)
+    {
+      printf_filtered ("File is not an object file\n");
+      return;
+    }
+  
+  for (s = abfd->sections; s; s = s->next)
+    if (s->flags & SEC_LOAD)
+      {
+       int numbytes;
+
+       printf_filtered ("%s\t: 0x%4x .. 0x%4x  ", s->name, s->vma,
+                        s->vma + s->_raw_size);
+       gdb_flush (gdb_stdout);
+
+       for (i = 0; i < s->_raw_size; i += numbytes)
+         {
+           reclen = maxrecsize;
+           numbytes = make_srec (srec, s->vma + i, abfd, s, i, &reclen,
+                                 flags);
+
+           if (remote_debug)
+             fprintf_unfiltered (gdb_stderr, "%.*s", reclen, srec);
+           SERIAL_WRITE (desc, srec, reclen);
+
+           if (hashmark)
+             {
+               putchar_unfiltered ('#');
+               gdb_flush (gdb_stdout);
+             }
+         }                     /* Per-packet (or S-record) loop */
+
+       putchar_unfiltered ('\n');
+      }                                /* Loadable sections */
+
+  if (hashmark) 
+    putchar_unfiltered ('\n');
+  
+  /* Write a type 7 terminator record. no data for a type 7, and there
+     is no data, so len is 0.  */
+
+  reclen = maxrecsize;
+  make_srec (srec, abfd->start_address, NULL, NULL, 0, &reclen, flags);
+
+  if (remote_debug)
+    fprintf_unfiltered (gdb_stderr, "%.*s", reclen, srec);
+  SERIAL_WRITE (desc, srec, reclen);
+
+  SERIAL_WRITE (desc, "\r\r", 2); /* Some monitors need these to wake up */
+
+  SERIAL_FLUSH_INPUT (desc);
+}
+
+/*
+ * make_srec -- make an srecord. This writes each line, one at a
+ *     time, each with it's own header and trailer line.
+ *     An srecord looks like this:
+ *
+ * byte count-+     address
+ * start ---+ |        |       data        +- checksum
+ *         | |        |                   |
+ *       S01000006F6B692D746573742E73726563E4
+ *       S315000448600000000000000000FC00005900000000E9
+ *       S31A0004000023C1400037DE00F023604000377B009020825000348D
+ *       S30B0004485A0000000000004E
+ *       S70500040000F6
+ *
+ *     S<type><length><address><data><checksum>
+ *
+ *      Where
+ *      - length
+ *        is the number of bytes following upto the checksum. Note that
+ *        this is not the number of chars following, since it takes two
+ *        chars to represent a byte.
+ *      - type
+ *        is one of:
+ *        0) header record
+ *        1) two byte address data record
+ *        2) three byte address data record
+ *        3) four byte address data record
+ *        7) four byte address termination record
+ *        8) three byte address termination record
+ *        9) two byte address termination record
+ *       
+ *      - address
+ *        is the start address of the data following, or in the case of
+ *        a termination record, the start address of the image
+ *      - data
+ *        is the data.
+ *      - checksum
+ *       is the sum of all the raw byte data in the record, from the length
+ *        upwards, modulo 256 and subtracted from 255.
+ *
+ * This routine returns the length of the S-record.
+ *
+ */
+
+static int
+make_srec (srec, targ_addr, abfd, sect, sectoff, maxrecsize, flags)
+     char *srec;
+     CORE_ADDR targ_addr;
+     bfd *abfd;
+     asection *sect;
+     int sectoff;
+     int *maxrecsize;
+     int flags;
+{
+  unsigned char checksum;
+  int tmp;
+  const static char hextab[] = "0123456789ABCDEF";
+  const static char data_code_table[] = "xx123";
+  const static char term_code_table[] = "xx987";
+  const static char *formats[] = {NULL, NULL, "S%c%02X%04X", "S%c%02X%06X",
+                                   "S%c%02X%08X"};
+  char const *code_table;
+  int addr_size;
+  int payload_size;
+  int type_code;
+  char *binbuf;
+  char *p;
+
+  if (sect)
+    {
+      tmp = flags;             /* Data record */
+      code_table = data_code_table;
+      binbuf = alloca (*maxrecsize/2);
+    }
+  else
+    {
+      tmp = flags >> SREC_TERM_SHIFT; /* Term record */
+      code_table = term_code_table;
+    }
+
+  if (tmp & SREC_4_BYTE_ADDR && targ_addr > 0xffffff)
+    addr_size = 4;
+  else if (tmp & SREC_3_BYTE_ADDR && targ_addr > 0xffff)
+    addr_size = 3;
+  else if (tmp & SREC_2_BYTE_ADDR && targ_addr > 0xff)
+    addr_size = 2;
+  else
+    fatal ("make_srec:  Bad address (0x%x), or bad flags (0x%x).", targ_addr,
+          flags);
+
+/* Now that we know the address size, we can figure out how much data this
+   record can hold.  */
+
+  if (sect)
+    {
+      payload_size = (*maxrecsize - (1 + 1 + 2 + addr_size * 2 + 2)) / 2;
+      payload_size = min (payload_size, sect->_raw_size - sectoff);
+
+      bfd_get_section_contents (abfd, sect, binbuf, sectoff, payload_size);
+    }
+  else
+    payload_size = 0;          /* Term packets have no payload */
+
+/* Output the header.  */
+
+  sprintf (srec, formats[addr_size], code_table[addr_size],
+          addr_size + payload_size + 1, targ_addr);
+
+/* Note that the checksum is calculated on the raw data, not the hexified
+   data.  It includes the length, address and the data portions of the
+   packet.  */
+
+  checksum = 0;
+  
+  checksum += (payload_size + addr_size + 1 /* Packet length */
+              + (targ_addr & 0xff)     /* Address... */
+              + ((targ_addr >>  8) & 0xff)
+              + ((targ_addr >> 16) & 0xff)
+              + ((targ_addr >> 24) & 0xff));
+  
+  p = srec + 1 + 1 + 2 + addr_size * 2;
+
+  /* build the srecord */
+  for (tmp = 0; tmp < payload_size; tmp++)
+    {
+      unsigned char k;
+
+      k = binbuf[tmp];
+      *p++ = hextab [k >> 4];
+      *p++ = hextab [k & 0xf];
+      checksum += k;
+    }
+
+  checksum = ~checksum;
+
+  *p++ = hextab[checksum >> 4];
+  *p++ = hextab[checksum & 0xf];
+  *p++ = '\r';
+
+  *maxrecsize = p - srec;
+  return payload_size;
+}
diff --git a/gdb/srec.h b/gdb/srec.h
new file mode 100644 (file)
index 0000000..1446bda
--- /dev/null
@@ -0,0 +1,35 @@
+/* S-record download support for GDB, the GNU debugger.
+   Copyright 1995 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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 2 of the License, or
+(at your option) any later version.
+
+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 this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+void load_srec PARAMS ((serial_t desc, const char *file, int maxrecsize,
+                       int flags, int hashmark));
+
+/* S-record capability flags */
+
+/* Which record types are supported */
+#define SREC_2_BYTE_ADDR 0x00000001
+#define SREC_3_BYTE_ADDR 0x00000002
+#define SREC_4_BYTE_ADDR 0x00000004
+#define SREC_TERM_SHIFT 3
+
+#define SREC_ALL (SREC_2_BYTE_ADDR | SREC_3_BYTE_ADDR | SREC_4_BYTE_ADDR \
+                 | ((SREC_2_BYTE_ADDR | SREC_3_BYTE_ADDR | SREC_4_BYTE_ADDR) \
+                    << SREC_TERM_SHIFT))
+
+#define SREC_BINARY    0x00000040 /* Supports binary form of S-records */