GDB (API)
/home/stan/gdb/src/gdb/dsrec.c
Go to the documentation of this file.
00001 /* S-record download support for GDB, the GNU debugger.
00002    Copyright (C) 1995-2013 Free Software Foundation, Inc.
00003 
00004    This file is part of GDB.
00005 
00006    This program is free software; you can redistribute it and/or modify
00007    it under the terms of the GNU General Public License as published by
00008    the Free Software Foundation; either version 3 of the License, or
00009    (at your option) any later version.
00010 
00011    This program is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014    GNU General Public License for more details.
00015 
00016    You should have received a copy of the GNU General Public License
00017    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
00018 
00019 #include "defs.h"
00020 #include "serial.h"
00021 #include "srec.h"
00022 #include <sys/time.h>
00023 #include <time.h>
00024 #include "gdb_assert.h"
00025 #include "gdb_string.h"
00026 #include "gdb_bfd.h"
00027 
00028 extern int remote_debug;
00029 
00030 static int make_srec (char *srec, CORE_ADDR targ_addr, bfd * abfd,
00031                       asection * sect, int sectoff, int *maxrecsize,
00032                       int flags);
00033 
00034 /* Download an executable by converting it to S records.  DESC is a
00035    `struct serial *' to send the data to.  FILE is the name of the
00036    file to be loaded.  LOAD_OFFSET is the offset into memory to load
00037    data into.  It is usually specified by the user and is useful with
00038    the a.out file format.  MAXRECSIZE is the length in chars of the
00039    largest S-record the host can accomodate.  This is measured from
00040    the starting `S' to the last char of the checksum.  FLAGS is
00041    various random flags, and HASHMARK is non-zero to cause a `#' to be
00042    printed out for each record loaded.  WAITACK, if non-NULL, is a
00043    function that waits for an acknowledgement after each S-record, and
00044    returns non-zero if the ack is read correctly.  */
00045 
00046 void
00047 load_srec (struct serial *desc, const char *file, bfd_vma load_offset,
00048            int maxrecsize,
00049            int flags, int hashmark, int (*waitack) (void))
00050 {
00051   bfd *abfd;
00052   asection *s;
00053   char *srec;
00054   int i;
00055   int reclen;
00056   struct timeval start_time, end_time;
00057   unsigned long data_count = 0;
00058   struct cleanup *cleanup;
00059 
00060   srec = (char *) alloca (maxrecsize + 1);
00061 
00062   abfd = gdb_bfd_open (file, NULL, -1);
00063   if (!abfd)
00064     {
00065       printf_filtered (_("Unable to open file %s\n"), file);
00066       return;
00067     }
00068 
00069   cleanup = make_cleanup_bfd_unref (abfd);
00070   if (bfd_check_format (abfd, bfd_object) == 0)
00071     {
00072       printf_filtered (_("File is not an object file\n"));
00073       do_cleanups (cleanup);
00074       return;
00075     }
00076 
00077   gettimeofday (&start_time, NULL);
00078 
00079   /* Write a type 0 header record. no data for a type 0, and there
00080      is no data, so len is 0.  */
00081 
00082   reclen = maxrecsize;
00083   make_srec (srec, 0, NULL, (asection *) 1, 0, &reclen, flags);
00084   if (remote_debug)
00085     {
00086       srec[reclen] = '\0';
00087       puts_debug ("sent -->", srec, "<--");
00088     }
00089   serial_write (desc, srec, reclen);
00090 
00091   for (s = abfd->sections; s; s = s->next)
00092     if (s->flags & SEC_LOAD)
00093       {
00094         int numbytes;
00095 
00096         bfd_vma addr = bfd_get_section_vma (abfd, s) + load_offset;
00097         bfd_size_type size = bfd_get_section_size (s);
00098         char *section_name = (char *) bfd_get_section_name (abfd, s);
00099         /* Both GDB and BFD have mechanisms for printing addresses.
00100            In the below, GDB's is used so that the address is
00101            consistent with the rest of GDB.  BFD's printf_vma() could
00102            have also been used.  cagney 1999-09-01 */
00103         printf_filtered ("%s\t: %s .. %s  ",
00104                          section_name,
00105                          paddress (target_gdbarch (), addr),
00106                          paddress (target_gdbarch (), addr + size));
00107         gdb_flush (gdb_stdout);
00108 
00109         data_count += size;
00110 
00111         for (i = 0; i < size; i += numbytes)
00112           {
00113             reclen = maxrecsize;
00114             numbytes = make_srec (srec, (CORE_ADDR) (addr + i), abfd, s,
00115                                   i, &reclen, flags);
00116 
00117             if (remote_debug)
00118               {
00119                 srec[reclen] = '\0';
00120                 puts_debug ("sent -->", srec, "<--");
00121               }
00122 
00123             /* Repeatedly send the S-record until a good
00124                acknowledgement is sent back.  */
00125             do
00126               {
00127                 serial_write (desc, srec, reclen);
00128                 if (deprecated_ui_load_progress_hook)
00129                   if (deprecated_ui_load_progress_hook (section_name,
00130                                                         (unsigned long) i))
00131                     error (_("Canceled the download"));
00132               }
00133             while (waitack != NULL && !waitack ());
00134 
00135             if (hashmark)
00136               {
00137                 putchar_unfiltered ('#');
00138                 gdb_flush (gdb_stdout);
00139               }
00140           }                     /* Per-packet (or S-record) loop.  */
00141 
00142         if (deprecated_ui_load_progress_hook)
00143           if (deprecated_ui_load_progress_hook (section_name,
00144                                                 (unsigned long) i))
00145             error (_("Canceled the download"));
00146         putchar_unfiltered ('\n');
00147       }
00148 
00149   if (hashmark)
00150     putchar_unfiltered ('\n');
00151 
00152   gettimeofday (&end_time, NULL);
00153 
00154   /* Write a terminator record.  */
00155 
00156   reclen = maxrecsize;
00157   make_srec (srec, abfd->start_address, NULL, NULL, 0, &reclen, flags);
00158 
00159   if (remote_debug)
00160     {
00161       srec[reclen] = '\0';
00162       puts_debug ("sent -->", srec, "<--");
00163     }
00164 
00165   serial_write (desc, srec, reclen);
00166 
00167   /* Some monitors need these to wake up properly.  (Which ones? -sts)  */
00168   serial_write (desc, "\r\r", 2);
00169   if (remote_debug)
00170     puts_debug ("sent -->", "\r\r", "<---");
00171 
00172   serial_flush_input (desc);
00173 
00174   print_transfer_performance (gdb_stdout, data_count, 0,
00175                               &start_time, &end_time);
00176   do_cleanups (cleanup);
00177 }
00178 
00179 /*
00180  * make_srec -- make an srecord.  This writes each line, one at a
00181  *      time, each with it's own header and trailer line.
00182  *      An srecord looks like this:
00183  *
00184  * byte count-+     address
00185  * start ---+ |        |       data        +- checksum
00186  *          | |        |                   |
00187  *        S01000006F6B692D746573742E73726563E4
00188  *        S315000448600000000000000000FC00005900000000E9
00189  *        S31A0004000023C1400037DE00F023604000377B009020825000348D
00190  *        S30B0004485A0000000000004E
00191  *        S70500040000F6
00192  *
00193  *      S<type><length><address><data><checksum>
00194  *
00195  *      Where
00196  *      - length
00197  *        is the number of bytes following upto the checksum.  Note
00198  *        that this is not the number of chars following, since it
00199  *        takes two chars to represent a byte.
00200  *      - type
00201  *        is one of:
00202  *        0) header record
00203  *        1) two byte address data record
00204  *        2) three byte address data record
00205  *        3) four byte address data record
00206  *        7) four byte address termination record
00207  *        8) three byte address termination record
00208  *        9) two byte address termination record
00209  *       
00210  *      - address
00211  *        is the start address of the data following, or in the case of
00212  *        a termination record, the start address of the image
00213  *      - data
00214  *        is the data.
00215  *      - checksum
00216  *        is the sum of all the raw byte data in the record, from the length
00217  *        upwards, modulo 256 and subtracted from 255.
00218  *
00219  * This routine returns the length of the S-record.
00220  *
00221  */
00222 
00223 static int
00224 make_srec (char *srec, CORE_ADDR targ_addr, bfd *abfd, asection *sect,
00225            int sectoff, int *maxrecsize, int flags)
00226 {
00227   unsigned char checksum;
00228   int tmp;
00229   static const char hextab[] = "0123456789ABCDEF";
00230   static const char data_code_table[] = "123";
00231   static const char term_code_table[] = "987";
00232   static const char header_code_table[] = "000";
00233   char const *code_table;
00234   int addr_size;
00235   int payload_size;
00236   char *binbuf;
00237   char *p;
00238 
00239   if (sect)
00240     {
00241       tmp = flags;              /* Data or header record */
00242       code_table = abfd ? data_code_table : header_code_table;
00243       binbuf = alloca (*maxrecsize / 2);
00244     }
00245   else
00246     {
00247       tmp = flags >> SREC_TERM_SHIFT;   /* Term record */
00248       code_table = term_code_table;
00249       binbuf = NULL;
00250     }
00251 
00252   if ((tmp & SREC_2_BYTE_ADDR) && (targ_addr <= 0xffff))
00253     addr_size = 2;
00254   else if ((tmp & SREC_3_BYTE_ADDR) && (targ_addr <= 0xffffff))
00255     addr_size = 3;
00256   else if (tmp & SREC_4_BYTE_ADDR)
00257     addr_size = 4;
00258   else
00259     internal_error (__FILE__, __LINE__,
00260                     _("make_srec:  Bad address (%s), or bad flags (0x%x)."),
00261                     paddress (target_gdbarch (), targ_addr), flags);
00262 
00263   /* Now that we know the address size, we can figure out how much
00264      data this record can hold.  */
00265 
00266   if (sect && abfd)
00267     {
00268       payload_size = (*maxrecsize - (1 + 1 + 2 + addr_size * 2 + 2)) / 2;
00269       payload_size = min (payload_size, bfd_get_section_size (sect) - sectoff);
00270 
00271       bfd_get_section_contents (abfd, sect, binbuf, sectoff, payload_size);
00272     }
00273   else
00274     payload_size = 0;           /* Term or header packets have no payload.  */
00275 
00276   /* Output the header.  */
00277   snprintf (srec, (*maxrecsize) + 1, "S%c%02X%0*X",
00278             code_table[addr_size - 2],
00279             addr_size + payload_size + 1,
00280             addr_size * 2, (int) targ_addr);
00281 
00282   /* Note that the checksum is calculated on the raw data, not the
00283      hexified data.  It includes the length, address and the data
00284      portions of the packet.  */
00285 
00286   checksum = 0;
00287 
00288   checksum += (payload_size + addr_size + 1     /* Packet length */
00289                + (targ_addr & 0xff)             /* Address...  */
00290                + ((targ_addr >> 8) & 0xff)
00291                + ((targ_addr >> 16) & 0xff)
00292                + ((targ_addr >> 24) & 0xff));
00293 
00294   /* NOTE: cagney/2003-08-10: The equation is old.  Check that the
00295      recent snprintf changes match that equation.  */
00296   gdb_assert (strlen (srec) == 1 + 1 + 2 + addr_size * 2);
00297   p = srec + 1 + 1 + 2 + addr_size * 2;
00298 
00299   /* Build the Srecord.  */
00300   for (tmp = 0; tmp < payload_size; tmp++)
00301     {
00302       unsigned char k;
00303 
00304       k = binbuf[tmp];
00305       *p++ = hextab[k >> 4];
00306       *p++ = hextab[k & 0xf];
00307       checksum += k;
00308     }
00309 
00310   checksum = ~checksum;
00311 
00312   *p++ = hextab[checksum >> 4];
00313   *p++ = hextab[checksum & 0xf];
00314   *p++ = '\r';
00315 
00316   *maxrecsize = p - srec;
00317   return payload_size;
00318 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines