Home | History | Annotate | Line # | Download | only in bfd
      1   1.1  christos /* BFD back-end for s-record objects.
      2  1.10  christos    Copyright (C) 1990-2025 Free Software Foundation, Inc.
      3   1.1  christos    Written by Steve Chamberlain of Cygnus Support <sac (at) cygnus.com>.
      4   1.1  christos 
      5   1.1  christos    This file is part of BFD, the Binary File Descriptor library.
      6   1.1  christos 
      7   1.1  christos    This program is free software; you can redistribute it and/or modify
      8   1.1  christos    it under the terms of the GNU General Public License as published by
      9   1.1  christos    the Free Software Foundation; either version 3 of the License, or
     10   1.1  christos    (at your option) any later version.
     11   1.1  christos 
     12   1.1  christos    This program is distributed in the hope that it will be useful,
     13   1.1  christos    but WITHOUT ANY WARRANTY; without even the implied warranty of
     14   1.1  christos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15   1.1  christos    GNU General Public License for more details.
     16   1.1  christos 
     17   1.1  christos    You should have received a copy of the GNU General Public License
     18   1.1  christos    along with this program; if not, write to the Free Software
     19   1.1  christos    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
     20   1.1  christos    MA 02110-1301, USA.  */
     21   1.1  christos 
     22   1.1  christos 
     23   1.1  christos /* SUBSECTION
     24   1.1  christos 	S-Record handling
     25   1.1  christos 
     26   1.1  christos    DESCRIPTION
     27   1.1  christos 
     28   1.1  christos 	Ordinary S-Records cannot hold anything but addresses and
     29   1.1  christos 	data, so that's all that we implement.
     30   1.1  christos 
     31   1.1  christos 	The only interesting thing is that S-Records may come out of
     32   1.1  christos 	order and there is no header, so an initial scan is required
     33   1.1  christos 	to discover the minimum and maximum addresses used to create
     34   1.1  christos 	the vma and size of the only section we create.  We
     35   1.1  christos 	arbitrarily call this section ".text".
     36   1.1  christos 
     37   1.1  christos 	When bfd_get_section_contents is called the file is read
     38   1.1  christos 	again, and this time the data is placed into a bfd_alloc'd
     39   1.1  christos 	area.
     40   1.1  christos 
     41   1.1  christos 	Any number of sections may be created for output, we save them
     42   1.1  christos 	up and output them when it's time to close the bfd.
     43   1.1  christos 
     44   1.1  christos 	An s record looks like:
     45   1.1  christos 
     46   1.1  christos    EXAMPLE
     47   1.1  christos 	S<type><length><address><data><checksum>
     48   1.1  christos 
     49   1.1  christos    DESCRIPTION
     50   1.1  christos 	Where
     51   1.1  christos 	o length
     52   1.1  christos 	is the number of bytes following upto the checksum. Note that
     53   1.1  christos 	this is not the number of chars following, since it takes two
     54   1.1  christos 	chars to represent a byte.
     55   1.1  christos 	o type
     56   1.1  christos 	is one of:
     57   1.1  christos 	0) header record
     58   1.1  christos 	1) two byte address data record
     59   1.1  christos 	2) three byte address data record
     60   1.1  christos 	3) four byte address data record
     61   1.1  christos 	7) four byte address termination record
     62   1.1  christos 	8) three byte address termination record
     63   1.1  christos 	9) two byte address termination record
     64   1.1  christos 
     65   1.1  christos 	o address
     66   1.1  christos 	is the start address of the data following, or in the case of
     67   1.1  christos 	a termination record, the start address of the image
     68   1.1  christos 	o data
     69   1.1  christos 	is the data.
     70   1.1  christos 	o checksum
     71   1.1  christos 	is the sum of all the raw byte data in the record, from the length
     72   1.1  christos 	upwards, modulo 256 and subtracted from 255.
     73   1.1  christos 
     74   1.1  christos    SUBSECTION
     75   1.1  christos 	Symbol S-Record handling
     76   1.1  christos 
     77   1.1  christos    DESCRIPTION
     78   1.1  christos 	Some ICE equipment understands an addition to the standard
     79   1.1  christos 	S-Record format; symbols and their addresses can be sent
     80   1.1  christos 	before the data.
     81   1.1  christos 
     82   1.1  christos 	The format of this is:
     83   1.1  christos 	($$ <modulename>
     84   1.1  christos 		(<space> <symbol> <address>)*)
     85   1.1  christos 	$$
     86   1.1  christos 
     87   1.1  christos 	so a short symbol table could look like:
     88   1.1  christos 
     89   1.1  christos    EXAMPLE
     90   1.1  christos 	$$ flash.x
     91   1.1  christos 	$$ flash.c
     92   1.1  christos 	  _port6 $0
     93   1.1  christos 	  _delay $4
     94   1.1  christos 	  _start $14
     95   1.1  christos 	  _etext $8036
     96   1.1  christos 	  _edata $8036
     97   1.6  christos 	  _end $8036
     98   1.1  christos 	$$
     99   1.1  christos 
    100   1.1  christos    DESCRIPTION
    101   1.1  christos 	We allow symbols to be anywhere in the data stream - the module names
    102   1.1  christos 	are always ignored.  */
    103   1.1  christos 
    104   1.1  christos #include "sysdep.h"
    105   1.1  christos #include "bfd.h"
    106   1.1  christos #include "libbfd.h"
    107   1.1  christos #include "libiberty.h"
    108   1.1  christos #include "safe-ctype.h"
    109   1.1  christos 
    110   1.1  christos 
    111   1.1  christos /* Macros for converting between hex and binary.  */
    112   1.1  christos 
    113   1.1  christos static const char digs[] = "0123456789ABCDEF";
    114   1.1  christos 
    115   1.1  christos #define NIBBLE(x)    hex_value(x)
    116   1.1  christos #define HEX(buffer) ((NIBBLE ((buffer)[0])<<4) + NIBBLE ((buffer)[1]))
    117   1.1  christos #define TOHEX(d, x, ch) \
    118   1.1  christos 	d[1] = digs[(x) & 0xf]; \
    119   1.1  christos 	d[0] = digs[((x)>>4)&0xf]; \
    120   1.1  christos 	ch += ((x) & 0xff);
    121   1.1  christos #define	ISHEX(x)    hex_p(x)
    122   1.1  christos 
    123   1.1  christos /* The maximum number of address+data+crc bytes on a line is FF.  */
    124   1.1  christos #define MAXCHUNK 0xff
    125   1.1  christos 
    126   1.1  christos /* Default size for a CHUNK.  */
    127   1.1  christos #define DEFAULT_CHUNK 16
    128   1.1  christos 
    129   1.1  christos /* The number of data bytes we actually fit onto a line on output.
    130   1.1  christos    This variable can be modified by objcopy's --srec-len parameter.
    131   1.1  christos    For a 0x75 byte record you should set --srec-len=0x70.  */
    132   1.6  christos unsigned int _bfd_srec_len = DEFAULT_CHUNK;
    133   1.1  christos 
    134   1.1  christos /* The type of srec output (free or forced to S3).
    135   1.1  christos    This variable can be modified by objcopy's --srec-forceS3
    136   1.1  christos    parameter.  */
    137   1.8  christos bool _bfd_srec_forceS3 = false;
    138   1.1  christos 
    139   1.1  christos /* When writing an S-record file, the S-records can not be output as
    140   1.1  christos    they are seen.  This structure is used to hold them in memory.  */
    141   1.1  christos 
    142   1.1  christos struct srec_data_list_struct
    143   1.1  christos {
    144   1.1  christos   struct srec_data_list_struct *next;
    145   1.1  christos   bfd_byte *data;
    146   1.1  christos   bfd_vma where;
    147   1.1  christos   bfd_size_type size;
    148   1.1  christos };
    149   1.1  christos 
    150   1.1  christos typedef struct srec_data_list_struct srec_data_list_type;
    151   1.1  christos 
    152   1.1  christos /* When scanning the S-record file, a linked list of srec_symbol
    153   1.1  christos    structures is built to represent the symbol table (if there is
    154   1.1  christos    one).  */
    155   1.1  christos 
    156   1.1  christos struct srec_symbol
    157   1.1  christos {
    158   1.1  christos   struct srec_symbol *next;
    159   1.1  christos   const char *name;
    160   1.1  christos   bfd_vma val;
    161   1.1  christos };
    162   1.1  christos 
    163   1.1  christos /* The S-record tdata information.  */
    164   1.1  christos 
    165   1.1  christos typedef struct srec_data_struct
    166   1.1  christos   {
    167   1.1  christos     srec_data_list_type *head;
    168   1.1  christos     srec_data_list_type *tail;
    169   1.1  christos     unsigned int type;
    170   1.1  christos     struct srec_symbol *symbols;
    171   1.1  christos     struct srec_symbol *symtail;
    172   1.1  christos     asymbol *csymbols;
    173   1.1  christos   }
    174   1.1  christos tdata_type;
    175   1.1  christos 
    176   1.1  christos /* Initialize by filling in the hex conversion array.  */
    177   1.1  christos 
    178   1.1  christos static void
    179   1.1  christos srec_init (void)
    180   1.1  christos {
    181   1.8  christos   static bool inited = false;
    182   1.1  christos 
    183   1.1  christos   if (! inited)
    184   1.1  christos     {
    185   1.8  christos       inited = true;
    186   1.1  christos       hex_init ();
    187   1.1  christos     }
    188   1.1  christos }
    189   1.1  christos 
    190   1.1  christos /* Set up the S-record tdata information.  */
    191   1.1  christos 
    192   1.8  christos static bool
    193   1.1  christos srec_mkobject (bfd *abfd)
    194   1.1  christos {
    195   1.1  christos   tdata_type *tdata;
    196   1.1  christos 
    197   1.1  christos   srec_init ();
    198   1.1  christos 
    199   1.1  christos   tdata = (tdata_type *) bfd_alloc (abfd, sizeof (tdata_type));
    200   1.1  christos   if (tdata == NULL)
    201   1.8  christos     return false;
    202   1.1  christos 
    203   1.1  christos   abfd->tdata.srec_data = tdata;
    204   1.1  christos   tdata->type = 1;
    205   1.1  christos   tdata->head = NULL;
    206   1.1  christos   tdata->tail = NULL;
    207   1.1  christos   tdata->symbols = NULL;
    208   1.1  christos   tdata->symtail = NULL;
    209   1.1  christos   tdata->csymbols = NULL;
    210   1.1  christos 
    211   1.8  christos   return true;
    212   1.1  christos }
    213   1.1  christos 
    214   1.1  christos /* Read a byte from an S record file.  Set *ERRORPTR if an error
    215   1.1  christos    occurred.  Return EOF on error or end of file.  */
    216   1.1  christos 
    217   1.1  christos static int
    218   1.8  christos srec_get_byte (bfd *abfd, bool *errorptr)
    219   1.1  christos {
    220   1.1  christos   bfd_byte c;
    221   1.1  christos 
    222   1.9  christos   if (bfd_read (&c, 1, abfd) != 1)
    223   1.1  christos     {
    224   1.1  christos       if (bfd_get_error () != bfd_error_file_truncated)
    225   1.8  christos 	*errorptr = true;
    226   1.1  christos       return EOF;
    227   1.1  christos     }
    228   1.1  christos 
    229   1.1  christos   return (int) (c & 0xff);
    230   1.1  christos }
    231   1.1  christos 
    232   1.1  christos /* Report a problem in an S record file.  FIXME: This probably should
    233   1.1  christos    not call fprintf, but we really do need some mechanism for printing
    234   1.1  christos    error messages.  */
    235   1.1  christos 
    236   1.1  christos static void
    237   1.1  christos srec_bad_byte (bfd *abfd,
    238   1.1  christos 	       unsigned int lineno,
    239   1.1  christos 	       int c,
    240   1.8  christos 	       bool error)
    241   1.1  christos {
    242   1.1  christos   if (c == EOF)
    243   1.1  christos     {
    244   1.1  christos       if (! error)
    245   1.1  christos 	bfd_set_error (bfd_error_file_truncated);
    246   1.1  christos     }
    247   1.1  christos   else
    248   1.1  christos     {
    249   1.3  christos       char buf[40];
    250   1.1  christos 
    251   1.1  christos       if (! ISPRINT (c))
    252   1.3  christos 	sprintf (buf, "\\%03o", (unsigned int) c & 0xff);
    253   1.1  christos       else
    254   1.1  christos 	{
    255   1.1  christos 	  buf[0] = c;
    256   1.1  christos 	  buf[1] = '\0';
    257   1.1  christos 	}
    258   1.6  christos       _bfd_error_handler
    259   1.6  christos 	/* xgettext:c-format */
    260   1.6  christos 	(_("%pB:%d: unexpected character `%s' in S-record file"),
    261   1.1  christos 	 abfd, lineno, buf);
    262   1.1  christos       bfd_set_error (bfd_error_bad_value);
    263   1.1  christos     }
    264   1.1  christos }
    265   1.1  christos 
    266   1.1  christos /* Add a new symbol found in an S-record file.  */
    267   1.1  christos 
    268   1.8  christos static bool
    269   1.1  christos srec_new_symbol (bfd *abfd, const char *name, bfd_vma val)
    270   1.1  christos {
    271   1.1  christos   struct srec_symbol *n;
    272   1.1  christos 
    273   1.1  christos   n = (struct srec_symbol *) bfd_alloc (abfd, sizeof (* n));
    274   1.1  christos   if (n == NULL)
    275   1.8  christos     return false;
    276   1.1  christos 
    277   1.1  christos   n->name = name;
    278   1.1  christos   n->val = val;
    279   1.1  christos 
    280   1.1  christos   if (abfd->tdata.srec_data->symbols == NULL)
    281   1.1  christos     abfd->tdata.srec_data->symbols = n;
    282   1.1  christos   else
    283   1.1  christos     abfd->tdata.srec_data->symtail->next = n;
    284   1.1  christos   abfd->tdata.srec_data->symtail = n;
    285   1.1  christos   n->next = NULL;
    286   1.1  christos 
    287   1.1  christos   ++abfd->symcount;
    288   1.1  christos 
    289   1.8  christos   return true;
    290   1.1  christos }
    291   1.1  christos 
    292   1.1  christos /* Read the S record file and turn it into sections.  We create a new
    293   1.1  christos    section for each contiguous set of bytes.  */
    294   1.1  christos 
    295   1.8  christos static bool
    296   1.1  christos srec_scan (bfd *abfd)
    297   1.1  christos {
    298   1.1  christos   int c;
    299   1.1  christos   unsigned int lineno = 1;
    300   1.8  christos   bool error = false;
    301   1.1  christos   bfd_byte *buf = NULL;
    302   1.1  christos   size_t bufsize = 0;
    303   1.1  christos   asection *sec = NULL;
    304   1.1  christos   char *symbuf = NULL;
    305   1.1  christos 
    306   1.9  christos   if (bfd_seek (abfd, 0, SEEK_SET) != 0)
    307   1.1  christos     goto error_return;
    308   1.1  christos 
    309   1.1  christos   while ((c = srec_get_byte (abfd, &error)) != EOF)
    310   1.1  christos     {
    311   1.1  christos       /* We only build sections from contiguous S-records, so if this
    312   1.1  christos 	 is not an S-record, then stop building a section.  */
    313   1.1  christos       if (c != 'S' && c != '\r' && c != '\n')
    314   1.1  christos 	sec = NULL;
    315   1.1  christos 
    316   1.1  christos       switch (c)
    317   1.1  christos 	{
    318   1.1  christos 	default:
    319   1.1  christos 	  srec_bad_byte (abfd, lineno, c, error);
    320   1.1  christos 	  goto error_return;
    321   1.1  christos 
    322   1.1  christos 	case '\n':
    323   1.1  christos 	  ++lineno;
    324   1.1  christos 	  break;
    325   1.1  christos 
    326   1.1  christos 	case '\r':
    327   1.1  christos 	  break;
    328   1.1  christos 
    329   1.1  christos 	case '$':
    330   1.1  christos 	  /* Starting a module name, which we ignore.  */
    331   1.1  christos 	  while ((c = srec_get_byte (abfd, &error)) != '\n'
    332   1.1  christos 		 && c != EOF)
    333   1.1  christos 	    ;
    334   1.1  christos 	  if (c == EOF)
    335   1.1  christos 	    {
    336   1.1  christos 	      srec_bad_byte (abfd, lineno, c, error);
    337   1.1  christos 	      goto error_return;
    338   1.1  christos 	    }
    339   1.1  christos 
    340   1.1  christos 	  ++lineno;
    341   1.1  christos 	  break;
    342   1.1  christos 
    343   1.1  christos 	case ' ':
    344   1.1  christos 	  do
    345   1.1  christos 	    {
    346   1.1  christos 	      bfd_size_type alc;
    347   1.1  christos 	      char *p, *symname;
    348   1.1  christos 	      bfd_vma symval;
    349   1.1  christos 
    350   1.1  christos 	      /* Starting a symbol definition.  */
    351   1.1  christos 	      while ((c = srec_get_byte (abfd, &error)) != EOF
    352   1.1  christos 		     && (c == ' ' || c == '\t'))
    353   1.1  christos 		;
    354   1.1  christos 
    355   1.1  christos 	      if (c == '\n' || c == '\r')
    356   1.1  christos 		break;
    357   1.1  christos 
    358   1.1  christos 	      if (c == EOF)
    359   1.1  christos 		{
    360   1.1  christos 		  srec_bad_byte (abfd, lineno, c, error);
    361   1.1  christos 		  goto error_return;
    362   1.1  christos 		}
    363   1.1  christos 
    364   1.1  christos 	      alc = 10;
    365   1.1  christos 	      symbuf = (char *) bfd_malloc (alc + 1);
    366   1.1  christos 	      if (symbuf == NULL)
    367   1.1  christos 		goto error_return;
    368   1.1  christos 
    369   1.1  christos 	      p = symbuf;
    370   1.1  christos 
    371   1.1  christos 	      *p++ = c;
    372   1.1  christos 	      while ((c = srec_get_byte (abfd, &error)) != EOF
    373   1.1  christos 		     && ! ISSPACE (c))
    374   1.1  christos 		{
    375   1.1  christos 		  if ((bfd_size_type) (p - symbuf) >= alc)
    376   1.1  christos 		    {
    377   1.1  christos 		      char *n;
    378   1.1  christos 
    379   1.1  christos 		      alc *= 2;
    380   1.1  christos 		      n = (char *) bfd_realloc (symbuf, alc + 1);
    381   1.1  christos 		      if (n == NULL)
    382   1.1  christos 			goto error_return;
    383   1.1  christos 		      p = n + (p - symbuf);
    384   1.1  christos 		      symbuf = n;
    385   1.1  christos 		    }
    386   1.1  christos 
    387   1.1  christos 		  *p++ = c;
    388   1.1  christos 		}
    389   1.1  christos 
    390   1.1  christos 	      if (c == EOF)
    391   1.1  christos 		{
    392   1.1  christos 		  srec_bad_byte (abfd, lineno, c, error);
    393   1.1  christos 		  goto error_return;
    394   1.1  christos 		}
    395   1.1  christos 
    396   1.1  christos 	      *p++ = '\0';
    397   1.1  christos 	      symname = (char *) bfd_alloc (abfd, (bfd_size_type) (p - symbuf));
    398   1.1  christos 	      if (symname == NULL)
    399   1.1  christos 		goto error_return;
    400   1.1  christos 	      strcpy (symname, symbuf);
    401   1.1  christos 	      free (symbuf);
    402   1.1  christos 	      symbuf = NULL;
    403   1.1  christos 
    404   1.1  christos 	      while ((c = srec_get_byte (abfd, &error)) != EOF
    405   1.1  christos 		     && (c == ' ' || c == '\t'))
    406   1.1  christos 		;
    407   1.1  christos 	      if (c == EOF)
    408   1.1  christos 		{
    409   1.1  christos 		  srec_bad_byte (abfd, lineno, c, error);
    410   1.1  christos 		  goto error_return;
    411   1.1  christos 		}
    412   1.1  christos 
    413   1.1  christos 	      /* Skip a dollar sign before the hex value.  */
    414   1.1  christos 	      if (c == '$')
    415   1.1  christos 		{
    416   1.1  christos 		  c = srec_get_byte (abfd, &error);
    417   1.1  christos 		  if (c == EOF)
    418   1.1  christos 		    {
    419   1.1  christos 		      srec_bad_byte (abfd, lineno, c, error);
    420   1.1  christos 		      goto error_return;
    421   1.1  christos 		    }
    422   1.1  christos 		}
    423   1.1  christos 
    424   1.1  christos 	      symval = 0;
    425   1.1  christos 	      while (ISHEX (c))
    426   1.1  christos 		{
    427   1.1  christos 		  symval <<= 4;
    428   1.1  christos 		  symval += NIBBLE (c);
    429   1.1  christos 		  c = srec_get_byte (abfd, &error);
    430   1.1  christos 		  if (c == EOF)
    431   1.1  christos 		    {
    432   1.1  christos 		      srec_bad_byte (abfd, lineno, c, error);
    433   1.1  christos 		      goto error_return;
    434   1.1  christos 		    }
    435   1.1  christos 		}
    436   1.1  christos 
    437   1.1  christos 	      if (! srec_new_symbol (abfd, symname, symval))
    438   1.1  christos 		goto error_return;
    439   1.1  christos 	    }
    440   1.1  christos 	  while (c == ' ' || c == '\t')
    441   1.1  christos 	    ;
    442   1.1  christos 
    443   1.1  christos 	  if (c == '\n')
    444   1.1  christos 	    ++lineno;
    445   1.1  christos 	  else if (c != '\r')
    446   1.1  christos 	    {
    447   1.1  christos 	      srec_bad_byte (abfd, lineno, c, error);
    448   1.1  christos 	      goto error_return;
    449   1.1  christos 	    }
    450   1.1  christos 
    451   1.1  christos 	  break;
    452   1.1  christos 
    453   1.1  christos 	case 'S':
    454   1.1  christos 	  {
    455   1.1  christos 	    file_ptr pos;
    456   1.3  christos 	    unsigned char hdr[3];
    457   1.3  christos 	    unsigned int bytes, min_bytes;
    458   1.1  christos 	    bfd_vma address;
    459   1.1  christos 	    bfd_byte *data;
    460   1.1  christos 	    unsigned char check_sum;
    461   1.1  christos 
    462   1.1  christos 	    /* Starting an S-record.  */
    463   1.1  christos 
    464   1.1  christos 	    pos = bfd_tell (abfd) - 1;
    465   1.1  christos 
    466   1.9  christos 	    if (bfd_read (hdr, 3, abfd) != 3)
    467   1.1  christos 	      goto error_return;
    468   1.1  christos 
    469   1.1  christos 	    if (! ISHEX (hdr[1]) || ! ISHEX (hdr[2]))
    470   1.1  christos 	      {
    471   1.1  christos 		if (! ISHEX (hdr[1]))
    472   1.1  christos 		  c = hdr[1];
    473   1.1  christos 		else
    474   1.1  christos 		  c = hdr[2];
    475   1.1  christos 		srec_bad_byte (abfd, lineno, c, error);
    476   1.1  christos 		goto error_return;
    477   1.1  christos 	      }
    478   1.1  christos 
    479   1.1  christos 	    check_sum = bytes = HEX (hdr + 1);
    480   1.3  christos 	    min_bytes = 3;
    481   1.3  christos 	    if (hdr[0] == '2' || hdr[0] == '8')
    482   1.3  christos 	      min_bytes = 4;
    483   1.3  christos 	    else if (hdr[0] == '3' || hdr[0] == '7')
    484   1.3  christos 	      min_bytes = 5;
    485   1.3  christos 	    if (bytes < min_bytes)
    486   1.3  christos 	      {
    487   1.6  christos 		/* xgettext:c-format */
    488   1.6  christos 		_bfd_error_handler (_("%pB:%d: byte count %d too small"),
    489   1.6  christos 				    abfd, lineno, bytes);
    490   1.3  christos 		bfd_set_error (bfd_error_bad_value);
    491   1.3  christos 		goto error_return;
    492   1.3  christos 	      }
    493   1.3  christos 
    494   1.1  christos 	    if (bytes * 2 > bufsize)
    495   1.1  christos 	      {
    496   1.8  christos 		free (buf);
    497   1.9  christos 		buf = bfd_malloc (bytes * 2);
    498   1.1  christos 		if (buf == NULL)
    499   1.1  christos 		  goto error_return;
    500   1.1  christos 		bufsize = bytes * 2;
    501   1.1  christos 	      }
    502   1.1  christos 
    503   1.9  christos 	    if (bfd_read (buf, bytes * 2, abfd) != bytes * 2)
    504   1.1  christos 	      goto error_return;
    505   1.1  christos 
    506   1.1  christos 	    /* Ignore the checksum byte.  */
    507   1.1  christos 	    --bytes;
    508   1.1  christos 
    509   1.1  christos 	    address = 0;
    510   1.1  christos 	    data = buf;
    511   1.1  christos 	    switch (hdr[0])
    512   1.1  christos 	      {
    513   1.1  christos 	      case '0':
    514   1.1  christos 	      case '5':
    515   1.1  christos 		/* Prologue--ignore the file name, but stop building a
    516   1.1  christos 		   section at this point.  */
    517   1.1  christos 		sec = NULL;
    518   1.1  christos 		break;
    519   1.1  christos 
    520   1.1  christos 	      case '3':
    521   1.1  christos 		check_sum += HEX (data);
    522   1.1  christos 		address = HEX (data);
    523   1.1  christos 		data += 2;
    524   1.1  christos 		--bytes;
    525   1.1  christos 		/* Fall through.  */
    526   1.1  christos 	      case '2':
    527   1.1  christos 		check_sum += HEX (data);
    528   1.1  christos 		address = (address << 8) | HEX (data);
    529   1.1  christos 		data += 2;
    530   1.1  christos 		--bytes;
    531   1.1  christos 		/* Fall through.  */
    532   1.1  christos 	      case '1':
    533   1.1  christos 		check_sum += HEX (data);
    534   1.1  christos 		address = (address << 8) | HEX (data);
    535   1.1  christos 		data += 2;
    536   1.1  christos 		check_sum += HEX (data);
    537   1.1  christos 		address = (address << 8) | HEX (data);
    538   1.1  christos 		data += 2;
    539   1.1  christos 		bytes -= 2;
    540   1.1  christos 
    541   1.1  christos 		if (sec != NULL
    542   1.1  christos 		    && sec->vma + sec->size == address)
    543   1.1  christos 		  {
    544   1.1  christos 		    /* This data goes at the end of the section we are
    545   1.1  christos 		       currently building.  */
    546   1.1  christos 		    sec->size += bytes;
    547   1.1  christos 		  }
    548   1.1  christos 		else
    549   1.1  christos 		  {
    550   1.1  christos 		    char secbuf[20];
    551   1.1  christos 		    char *secname;
    552   1.8  christos 		    size_t amt;
    553   1.1  christos 		    flagword flags;
    554   1.1  christos 
    555   1.1  christos 		    sprintf (secbuf, ".sec%d", bfd_count_sections (abfd) + 1);
    556   1.1  christos 		    amt = strlen (secbuf) + 1;
    557   1.1  christos 		    secname = (char *) bfd_alloc (abfd, amt);
    558   1.1  christos 		    strcpy (secname, secbuf);
    559   1.1  christos 		    flags = SEC_HAS_CONTENTS | SEC_LOAD | SEC_ALLOC;
    560   1.1  christos 		    sec = bfd_make_section_with_flags (abfd, secname, flags);
    561   1.1  christos 		    if (sec == NULL)
    562   1.1  christos 		      goto error_return;
    563   1.1  christos 		    sec->vma = address;
    564   1.1  christos 		    sec->lma = address;
    565   1.1  christos 		    sec->size = bytes;
    566   1.1  christos 		    sec->filepos = pos;
    567   1.1  christos 		  }
    568   1.1  christos 
    569   1.1  christos 		while (bytes > 0)
    570   1.1  christos 		  {
    571   1.1  christos 		    check_sum += HEX (data);
    572   1.1  christos 		    data += 2;
    573   1.1  christos 		    bytes--;
    574   1.1  christos 		  }
    575   1.1  christos 		check_sum = 255 - (check_sum & 0xff);
    576   1.1  christos 		if (check_sum != HEX (data))
    577   1.1  christos 		  {
    578   1.6  christos 		    _bfd_error_handler
    579   1.6  christos 		      /* xgettext:c-format */
    580   1.6  christos 		      (_("%pB:%d: bad checksum in S-record file"),
    581   1.1  christos 		       abfd, lineno);
    582   1.1  christos 		    bfd_set_error (bfd_error_bad_value);
    583   1.1  christos 		    goto error_return;
    584   1.1  christos 		  }
    585   1.1  christos 
    586   1.1  christos 		break;
    587   1.1  christos 
    588   1.1  christos 	      case '7':
    589   1.1  christos 		check_sum += HEX (data);
    590   1.1  christos 		address = HEX (data);
    591   1.1  christos 		data += 2;
    592   1.1  christos 		/* Fall through.  */
    593   1.1  christos 	      case '8':
    594   1.1  christos 		check_sum += HEX (data);
    595   1.1  christos 		address = (address << 8) | HEX (data);
    596   1.1  christos 		data += 2;
    597   1.1  christos 		/* Fall through.  */
    598   1.1  christos 	      case '9':
    599   1.1  christos 		check_sum += HEX (data);
    600   1.1  christos 		address = (address << 8) | HEX (data);
    601   1.1  christos 		data += 2;
    602   1.1  christos 		check_sum += HEX (data);
    603   1.1  christos 		address = (address << 8) | HEX (data);
    604   1.1  christos 		data += 2;
    605   1.1  christos 
    606   1.1  christos 		/* This is a termination record.  */
    607   1.1  christos 		abfd->start_address = address;
    608   1.1  christos 
    609   1.1  christos 		check_sum = 255 - (check_sum & 0xff);
    610   1.1  christos 		if (check_sum != HEX (data))
    611   1.1  christos 		  {
    612   1.6  christos 		    _bfd_error_handler
    613   1.6  christos 		      /* xgettext:c-format */
    614   1.6  christos 		      (_("%pB:%d: bad checksum in S-record file"),
    615   1.1  christos 		       abfd, lineno);
    616   1.1  christos 		    bfd_set_error (bfd_error_bad_value);
    617   1.1  christos 		    goto error_return;
    618   1.1  christos 		  }
    619   1.1  christos 
    620   1.8  christos 		free (buf);
    621   1.8  christos 		return true;
    622   1.1  christos 	      }
    623   1.1  christos 	  }
    624   1.1  christos 	  break;
    625   1.1  christos 	}
    626   1.1  christos     }
    627   1.1  christos 
    628   1.1  christos   if (error)
    629   1.1  christos     goto error_return;
    630   1.1  christos 
    631   1.8  christos   free (buf);
    632   1.8  christos   return true;
    633   1.1  christos 
    634   1.1  christos  error_return:
    635   1.8  christos   free (symbuf);
    636   1.8  christos   free (buf);
    637   1.8  christos   return false;
    638   1.1  christos }
    639   1.1  christos 
    640   1.1  christos /* Check whether an existing file is an S-record file.  */
    641   1.1  christos 
    642   1.8  christos static bfd_cleanup
    643   1.1  christos srec_object_p (bfd *abfd)
    644   1.1  christos {
    645   1.1  christos   bfd_byte b[4];
    646   1.1  christos 
    647   1.1  christos   srec_init ();
    648   1.1  christos 
    649   1.9  christos   if (bfd_seek (abfd, 0, SEEK_SET) != 0
    650   1.9  christos       || bfd_read (b, 4, abfd) != 4)
    651   1.1  christos     return NULL;
    652   1.1  christos 
    653   1.1  christos   if (b[0] != 'S' || !ISHEX (b[1]) || !ISHEX (b[2]) || !ISHEX (b[3]))
    654   1.1  christos     {
    655   1.1  christos       bfd_set_error (bfd_error_wrong_format);
    656   1.1  christos       return NULL;
    657   1.1  christos     }
    658   1.1  christos 
    659  1.10  christos   if (!srec_mkobject (abfd))
    660  1.10  christos     return NULL;
    661  1.10  christos 
    662  1.10  christos   if (!srec_scan (abfd))
    663   1.1  christos     {
    664  1.10  christos       bfd_release (abfd, abfd->tdata.any);
    665   1.1  christos       return NULL;
    666   1.1  christos     }
    667   1.1  christos 
    668   1.1  christos   if (abfd->symcount > 0)
    669   1.1  christos     abfd->flags |= HAS_SYMS;
    670   1.1  christos 
    671   1.8  christos   return _bfd_no_cleanup;
    672   1.1  christos }
    673   1.1  christos 
    674   1.1  christos /* Check whether an existing file is an S-record file with symbols.  */
    675   1.1  christos 
    676   1.8  christos static bfd_cleanup
    677   1.1  christos symbolsrec_object_p (bfd *abfd)
    678   1.1  christos {
    679   1.1  christos   char b[2];
    680   1.1  christos 
    681   1.1  christos   srec_init ();
    682   1.1  christos 
    683   1.9  christos   if (bfd_seek (abfd, 0, SEEK_SET) != 0
    684   1.9  christos       || bfd_read (b, 2, abfd) != 2)
    685   1.1  christos     return NULL;
    686   1.1  christos 
    687   1.1  christos   if (b[0] != '$' || b[1] != '$')
    688   1.1  christos     {
    689   1.1  christos       bfd_set_error (bfd_error_wrong_format);
    690   1.1  christos       return NULL;
    691   1.1  christos     }
    692   1.1  christos 
    693  1.10  christos   if (!srec_mkobject (abfd))
    694  1.10  christos     return NULL;
    695  1.10  christos 
    696  1.10  christos   if (!srec_scan (abfd))
    697   1.1  christos     {
    698  1.10  christos       bfd_release (abfd, abfd->tdata.any);
    699   1.1  christos       return NULL;
    700   1.1  christos     }
    701   1.1  christos 
    702   1.1  christos   if (abfd->symcount > 0)
    703   1.1  christos     abfd->flags |= HAS_SYMS;
    704   1.1  christos 
    705   1.8  christos   return _bfd_no_cleanup;
    706   1.1  christos }
    707   1.1  christos 
    708   1.1  christos /* Read in the contents of a section in an S-record file.  */
    709   1.1  christos 
    710   1.8  christos static bool
    711   1.1  christos srec_read_section (bfd *abfd, asection *section, bfd_byte *contents)
    712   1.1  christos {
    713   1.1  christos   int c;
    714   1.1  christos   bfd_size_type sofar = 0;
    715   1.8  christos   bool error = false;
    716   1.1  christos   bfd_byte *buf = NULL;
    717   1.1  christos   size_t bufsize = 0;
    718   1.1  christos 
    719   1.1  christos   if (bfd_seek (abfd, section->filepos, SEEK_SET) != 0)
    720   1.1  christos     goto error_return;
    721   1.1  christos 
    722   1.1  christos   while ((c = srec_get_byte (abfd, &error)) != EOF)
    723   1.1  christos     {
    724   1.1  christos       bfd_byte hdr[3];
    725   1.1  christos       unsigned int bytes;
    726   1.1  christos       bfd_vma address;
    727   1.1  christos       bfd_byte *data;
    728   1.1  christos 
    729   1.1  christos       if (c == '\r' || c == '\n')
    730   1.1  christos 	continue;
    731   1.1  christos 
    732   1.1  christos       /* This is called after srec_scan has already been called, so we
    733   1.1  christos 	 ought to know the exact format.  */
    734   1.8  christos       if (c != 'S')
    735   1.8  christos 	goto error_return;
    736   1.1  christos 
    737   1.9  christos       if (bfd_read (hdr, 3, abfd) != 3)
    738   1.1  christos 	goto error_return;
    739   1.1  christos 
    740   1.1  christos       BFD_ASSERT (ISHEX (hdr[1]) && ISHEX (hdr[2]));
    741   1.1  christos 
    742   1.1  christos       bytes = HEX (hdr + 1);
    743   1.1  christos 
    744   1.1  christos       if (bytes * 2 > bufsize)
    745   1.1  christos 	{
    746   1.8  christos 	  free (buf);
    747   1.9  christos 	  buf = bfd_malloc (bytes * 2);
    748   1.1  christos 	  if (buf == NULL)
    749   1.1  christos 	    goto error_return;
    750   1.1  christos 	  bufsize = bytes * 2;
    751   1.1  christos 	}
    752   1.1  christos 
    753   1.9  christos       if (bfd_read (buf, bytes * 2, abfd) != bytes * 2)
    754   1.1  christos 	goto error_return;
    755   1.1  christos 
    756   1.1  christos       address = 0;
    757   1.1  christos       data = buf;
    758   1.1  christos       switch (hdr[0])
    759   1.1  christos 	{
    760   1.1  christos 	default:
    761   1.8  christos 	  if (sofar != section->size)
    762   1.8  christos 	    goto error_return;
    763   1.8  christos 	  free (buf);
    764   1.8  christos 	  return true;
    765   1.1  christos 
    766   1.1  christos 	case '3':
    767   1.1  christos 	  address = HEX (data);
    768   1.1  christos 	  data += 2;
    769   1.1  christos 	  --bytes;
    770   1.1  christos 	  /* Fall through.  */
    771   1.1  christos 	case '2':
    772   1.1  christos 	  address = (address << 8) | HEX (data);
    773   1.1  christos 	  data += 2;
    774   1.1  christos 	  --bytes;
    775   1.1  christos 	  /* Fall through.  */
    776   1.1  christos 	case '1':
    777   1.1  christos 	  address = (address << 8) | HEX (data);
    778   1.1  christos 	  data += 2;
    779   1.1  christos 	  address = (address << 8) | HEX (data);
    780   1.1  christos 	  data += 2;
    781   1.1  christos 	  bytes -= 2;
    782   1.1  christos 
    783   1.1  christos 	  if (address != section->vma + sofar)
    784   1.1  christos 	    {
    785   1.1  christos 	      /* We've come to the end of this section.  */
    786   1.8  christos 	      if (sofar != section->size)
    787   1.8  christos 		goto error_return;
    788   1.8  christos 	      free (buf);
    789   1.8  christos 	      return true;
    790   1.1  christos 	    }
    791   1.1  christos 
    792   1.1  christos 	  /* Don't consider checksum.  */
    793   1.1  christos 	  --bytes;
    794   1.1  christos 
    795   1.1  christos 	  while (bytes-- != 0)
    796   1.1  christos 	    {
    797   1.1  christos 	      contents[sofar] = HEX (data);
    798   1.1  christos 	      data += 2;
    799   1.1  christos 	      ++sofar;
    800   1.1  christos 	    }
    801   1.1  christos 
    802   1.1  christos 	  break;
    803   1.1  christos 	}
    804   1.1  christos     }
    805   1.1  christos 
    806   1.1  christos   if (error)
    807   1.1  christos     goto error_return;
    808   1.1  christos 
    809   1.8  christos   if (sofar != section->size)
    810   1.8  christos     goto error_return;
    811   1.1  christos 
    812   1.8  christos   free (buf);
    813   1.8  christos   return true;
    814   1.1  christos 
    815   1.1  christos  error_return:
    816   1.8  christos   free (buf);
    817   1.8  christos   return false;
    818   1.1  christos }
    819   1.1  christos 
    820   1.1  christos /* Get the contents of a section in an S-record file.  */
    821   1.1  christos 
    822   1.8  christos static bool
    823   1.1  christos srec_get_section_contents (bfd *abfd,
    824   1.1  christos 			   asection *section,
    825   1.1  christos 			   void * location,
    826   1.1  christos 			   file_ptr offset,
    827   1.1  christos 			   bfd_size_type count)
    828   1.1  christos {
    829   1.1  christos   if (count == 0)
    830   1.8  christos     return true;
    831   1.1  christos 
    832   1.1  christos   if (offset + count < count
    833   1.1  christos       || offset + count > section->size)
    834   1.1  christos     {
    835   1.1  christos       bfd_set_error (bfd_error_invalid_operation);
    836   1.8  christos       return false;
    837   1.1  christos     }
    838   1.1  christos 
    839   1.1  christos   if (section->used_by_bfd == NULL)
    840   1.1  christos     {
    841   1.1  christos       section->used_by_bfd = bfd_alloc (abfd, section->size);
    842   1.1  christos       if (section->used_by_bfd == NULL)
    843   1.8  christos 	return false;
    844   1.1  christos 
    845   1.1  christos       if (! srec_read_section (abfd, section,
    846   1.6  christos 			       (bfd_byte *) section->used_by_bfd))
    847   1.8  christos 	return false;
    848   1.1  christos     }
    849   1.1  christos 
    850   1.1  christos   memcpy (location, (bfd_byte *) section->used_by_bfd + offset,
    851   1.1  christos 	  (size_t) count);
    852   1.1  christos 
    853   1.8  christos   return true;
    854   1.1  christos }
    855   1.1  christos 
    856   1.1  christos /* Set the architecture.  We accept an unknown architecture here.  */
    857   1.1  christos 
    858   1.8  christos static bool
    859   1.1  christos srec_set_arch_mach (bfd *abfd, enum bfd_architecture arch, unsigned long mach)
    860   1.1  christos {
    861   1.1  christos   if (arch != bfd_arch_unknown)
    862   1.1  christos     return bfd_default_set_arch_mach (abfd, arch, mach);
    863   1.1  christos 
    864   1.1  christos   abfd->arch_info = & bfd_default_arch_struct;
    865   1.8  christos   return true;
    866   1.1  christos }
    867   1.1  christos 
    868   1.1  christos /* We have to save up all the Srecords for a splurge before output.  */
    869   1.1  christos 
    870   1.8  christos static bool
    871   1.1  christos srec_set_section_contents (bfd *abfd,
    872   1.1  christos 			   sec_ptr section,
    873   1.1  christos 			   const void * location,
    874   1.1  christos 			   file_ptr offset,
    875   1.1  christos 			   bfd_size_type bytes_to_do)
    876   1.1  christos {
    877   1.7  christos   int opb = bfd_octets_per_byte (abfd, NULL);
    878   1.1  christos   tdata_type *tdata = abfd->tdata.srec_data;
    879   1.1  christos   srec_data_list_type *entry;
    880   1.1  christos 
    881   1.1  christos   entry = (srec_data_list_type *) bfd_alloc (abfd, sizeof (* entry));
    882   1.1  christos   if (entry == NULL)
    883   1.8  christos     return false;
    884   1.1  christos 
    885   1.1  christos   if (bytes_to_do
    886   1.1  christos       && (section->flags & SEC_ALLOC)
    887   1.1  christos       && (section->flags & SEC_LOAD))
    888   1.1  christos     {
    889   1.1  christos       bfd_byte *data;
    890   1.1  christos 
    891   1.1  christos       data = (bfd_byte *) bfd_alloc (abfd, bytes_to_do);
    892   1.1  christos       if (data == NULL)
    893   1.8  christos 	return false;
    894   1.1  christos       memcpy ((void *) data, location, (size_t) bytes_to_do);
    895   1.1  christos 
    896   1.6  christos       /* If _bfd_srec_forceS3 is TRUE then always select S3 records,
    897   1.6  christos 	 regardless of the size of the addresses.  */
    898   1.6  christos       if (_bfd_srec_forceS3)
    899   1.1  christos 	tdata->type = 3;
    900   1.3  christos       else if ((section->lma + (offset + bytes_to_do) / opb - 1) <= 0xffff)
    901   1.1  christos 	;  /* The default, S1, is OK.  */
    902   1.3  christos       else if ((section->lma + (offset + bytes_to_do) / opb - 1) <= 0xffffff
    903   1.1  christos 	       && tdata->type <= 2)
    904   1.1  christos 	tdata->type = 2;
    905   1.1  christos       else
    906   1.1  christos 	tdata->type = 3;
    907   1.1  christos 
    908   1.1  christos       entry->data = data;
    909   1.3  christos       entry->where = section->lma + offset / opb;
    910   1.1  christos       entry->size = bytes_to_do;
    911   1.1  christos 
    912   1.1  christos       /* Sort the records by address.  Optimize for the common case of
    913   1.1  christos 	 adding a record to the end of the list.  */
    914   1.1  christos       if (tdata->tail != NULL
    915   1.1  christos 	  && entry->where >= tdata->tail->where)
    916   1.1  christos 	{
    917   1.1  christos 	  tdata->tail->next = entry;
    918   1.1  christos 	  entry->next = NULL;
    919   1.1  christos 	  tdata->tail = entry;
    920   1.1  christos 	}
    921   1.1  christos       else
    922   1.1  christos 	{
    923   1.1  christos 	  srec_data_list_type **look;
    924   1.1  christos 
    925   1.1  christos 	  for (look = &tdata->head;
    926   1.1  christos 	       *look != NULL && (*look)->where < entry->where;
    927   1.1  christos 	       look = &(*look)->next)
    928   1.1  christos 	    ;
    929   1.1  christos 	  entry->next = *look;
    930   1.1  christos 	  *look = entry;
    931   1.1  christos 	  if (entry->next == NULL)
    932   1.1  christos 	    tdata->tail = entry;
    933   1.1  christos 	}
    934   1.1  christos     }
    935   1.8  christos   return true;
    936   1.1  christos }
    937   1.1  christos 
    938   1.1  christos /* Write a record of type, of the supplied number of bytes. The
    939   1.1  christos    supplied bytes and length don't have a checksum. That's worked out
    940   1.1  christos    here.  */
    941   1.1  christos 
    942   1.8  christos static bool
    943   1.1  christos srec_write_record (bfd *abfd,
    944   1.1  christos 		   unsigned int type,
    945   1.1  christos 		   bfd_vma address,
    946   1.1  christos 		   const bfd_byte *data,
    947   1.1  christos 		   const bfd_byte *end)
    948   1.1  christos {
    949   1.1  christos   char buffer[2 * MAXCHUNK + 6];
    950   1.1  christos   unsigned int check_sum = 0;
    951   1.1  christos   const bfd_byte *src = data;
    952   1.1  christos   char *dst = buffer;
    953   1.1  christos   char *length;
    954   1.1  christos   bfd_size_type wrlen;
    955   1.1  christos 
    956   1.1  christos   *dst++ = 'S';
    957   1.1  christos   *dst++ = '0' + type;
    958   1.1  christos 
    959   1.1  christos   length = dst;
    960   1.1  christos   dst += 2;			/* Leave room for dst.  */
    961   1.1  christos 
    962   1.1  christos   switch (type)
    963   1.1  christos     {
    964   1.1  christos     case 3:
    965   1.1  christos     case 7:
    966   1.1  christos       TOHEX (dst, (address >> 24), check_sum);
    967   1.1  christos       dst += 2;
    968   1.6  christos       /* Fall through.  */
    969   1.1  christos     case 8:
    970   1.1  christos     case 2:
    971   1.1  christos       TOHEX (dst, (address >> 16), check_sum);
    972   1.1  christos       dst += 2;
    973   1.6  christos       /* Fall through.  */
    974   1.1  christos     case 9:
    975   1.1  christos     case 1:
    976   1.1  christos     case 0:
    977   1.1  christos       TOHEX (dst, (address >> 8), check_sum);
    978   1.1  christos       dst += 2;
    979   1.1  christos       TOHEX (dst, (address), check_sum);
    980   1.1  christos       dst += 2;
    981   1.1  christos       break;
    982   1.1  christos 
    983   1.1  christos     }
    984   1.1  christos   for (src = data; src < end; src++)
    985   1.1  christos     {
    986   1.1  christos       TOHEX (dst, *src, check_sum);
    987   1.1  christos       dst += 2;
    988   1.1  christos     }
    989   1.1  christos 
    990   1.1  christos   /* Fill in the length.  */
    991   1.1  christos   TOHEX (length, (dst - length) / 2, check_sum);
    992   1.1  christos   check_sum &= 0xff;
    993   1.1  christos   check_sum = 255 - check_sum;
    994   1.1  christos   TOHEX (dst, check_sum, check_sum);
    995   1.1  christos   dst += 2;
    996   1.1  christos 
    997   1.1  christos   *dst++ = '\r';
    998   1.1  christos   *dst++ = '\n';
    999   1.1  christos   wrlen = dst - buffer;
   1000   1.1  christos 
   1001   1.9  christos   return bfd_write (buffer, wrlen, abfd) == wrlen;
   1002   1.1  christos }
   1003   1.1  christos 
   1004   1.8  christos static bool
   1005   1.1  christos srec_write_header (bfd *abfd)
   1006   1.1  christos {
   1007   1.8  christos   unsigned int len = strlen (bfd_get_filename (abfd));
   1008   1.1  christos 
   1009   1.1  christos   /* I'll put an arbitrary 40 char limit on header size.  */
   1010   1.1  christos   if (len > 40)
   1011   1.1  christos     len = 40;
   1012   1.1  christos 
   1013   1.1  christos   return srec_write_record (abfd, 0, (bfd_vma) 0,
   1014   1.8  christos 			    (bfd_byte *) bfd_get_filename (abfd),
   1015   1.8  christos 			    (bfd_byte *) bfd_get_filename (abfd) + len);
   1016   1.1  christos }
   1017   1.1  christos 
   1018   1.8  christos static bool
   1019   1.1  christos srec_write_section (bfd *abfd,
   1020   1.1  christos 		    tdata_type *tdata,
   1021   1.1  christos 		    srec_data_list_type *list)
   1022   1.1  christos {
   1023   1.1  christos   unsigned int octets_written = 0;
   1024   1.1  christos   bfd_byte *location = list->data;
   1025   1.1  christos 
   1026   1.1  christos   /* Validate number of data bytes to write.  The srec length byte
   1027   1.1  christos      counts the address, data and crc bytes.  S1 (tdata->type == 1)
   1028   1.1  christos      records have two address bytes, S2 (tdata->type == 2) records
   1029   1.1  christos      have three, and S3 (tdata->type == 3) records have four.
   1030   1.1  christos      The total length can't exceed 255, and a zero data length will
   1031   1.1  christos      spin for a long time.  */
   1032   1.6  christos   if (_bfd_srec_len == 0)
   1033   1.6  christos     _bfd_srec_len = 1;
   1034   1.6  christos   else if (_bfd_srec_len > MAXCHUNK - tdata->type - 2)
   1035   1.6  christos     _bfd_srec_len = MAXCHUNK - tdata->type - 2;
   1036   1.1  christos 
   1037   1.1  christos   while (octets_written < list->size)
   1038   1.1  christos     {
   1039   1.1  christos       bfd_vma address;
   1040   1.1  christos       unsigned int octets_this_chunk = list->size - octets_written;
   1041   1.1  christos 
   1042   1.6  christos       if (octets_this_chunk > _bfd_srec_len)
   1043   1.6  christos 	octets_this_chunk = _bfd_srec_len;
   1044   1.1  christos 
   1045   1.7  christos       address = list->where + (octets_written
   1046   1.7  christos 			       / bfd_octets_per_byte (abfd, NULL));
   1047   1.1  christos 
   1048   1.1  christos       if (! srec_write_record (abfd,
   1049   1.1  christos 			       tdata->type,
   1050   1.1  christos 			       address,
   1051   1.1  christos 			       location,
   1052   1.1  christos 			       location + octets_this_chunk))
   1053   1.8  christos 	return false;
   1054   1.1  christos 
   1055   1.1  christos       octets_written += octets_this_chunk;
   1056   1.1  christos       location += octets_this_chunk;
   1057   1.1  christos     }
   1058   1.1  christos 
   1059   1.8  christos   return true;
   1060   1.1  christos }
   1061   1.1  christos 
   1062   1.8  christos static bool
   1063   1.1  christos srec_write_terminator (bfd *abfd, tdata_type *tdata)
   1064   1.1  christos {
   1065   1.1  christos   return srec_write_record (abfd, 10 - tdata->type,
   1066   1.1  christos 			    abfd->start_address, NULL, NULL);
   1067   1.1  christos }
   1068   1.1  christos 
   1069   1.8  christos static bool
   1070   1.1  christos srec_write_symbols (bfd *abfd)
   1071   1.1  christos {
   1072   1.1  christos   /* Dump out the symbols of a bfd.  */
   1073   1.1  christos   int i;
   1074   1.1  christos   int count = bfd_get_symcount (abfd);
   1075   1.1  christos 
   1076   1.1  christos   if (count)
   1077   1.1  christos     {
   1078   1.1  christos       bfd_size_type len;
   1079   1.1  christos       asymbol **table = bfd_get_outsymbols (abfd);
   1080   1.1  christos 
   1081   1.8  christos       len = strlen (bfd_get_filename (abfd));
   1082   1.9  christos       if (bfd_write ("$$ ", 3, abfd) != 3
   1083   1.9  christos 	  || bfd_write (bfd_get_filename (abfd), len, abfd) != len
   1084   1.9  christos 	  || bfd_write ("\r\n", 2, abfd) != 2)
   1085  1.10  christos 	goto fail;
   1086   1.1  christos 
   1087   1.1  christos       for (i = 0; i < count; i++)
   1088   1.1  christos 	{
   1089   1.1  christos 	  asymbol *s = table[i];
   1090   1.8  christos 
   1091   1.1  christos 	  if (! bfd_is_local_label (abfd, s)
   1092   1.8  christos 	      && (s->flags & BSF_DEBUGGING) == 0
   1093   1.8  christos 	      && s->section != NULL
   1094   1.8  christos 	      && s->section->output_section != NULL)
   1095   1.1  christos 	    {
   1096   1.1  christos 	      /* Just dump out non debug symbols.  */
   1097   1.9  christos 	      char buf[43];
   1098   1.1  christos 
   1099   1.1  christos 	      len = strlen (s->name);
   1100   1.9  christos 	      if (bfd_write ("  ", 2, abfd) != 2
   1101   1.9  christos 		  || bfd_write (s->name, len, abfd) != len)
   1102  1.10  christos 		goto fail;
   1103   1.1  christos 
   1104   1.9  christos 	      sprintf (buf, " $%" PRIx64 "\r\n",
   1105   1.9  christos 		       (uint64_t) (s->value
   1106   1.9  christos 				   + s->section->output_section->lma
   1107   1.9  christos 				   + s->section->output_offset));
   1108   1.9  christos 	      len = strlen (buf);
   1109   1.9  christos 	      if (bfd_write (buf, len, abfd) != len)
   1110  1.10  christos 		goto fail;
   1111   1.1  christos 	    }
   1112   1.1  christos 	}
   1113   1.9  christos       if (bfd_write ("$$ \r\n", 5, abfd) != 5)
   1114  1.10  christos 	goto fail;
   1115   1.1  christos     }
   1116   1.1  christos 
   1117   1.8  christos   return true;
   1118  1.10  christos 
   1119  1.10  christos  fail:
   1120  1.10  christos   return false;
   1121   1.1  christos }
   1122   1.1  christos 
   1123   1.8  christos static bool
   1124   1.1  christos internal_srec_write_object_contents (bfd *abfd, int symbols)
   1125   1.1  christos {
   1126   1.1  christos   tdata_type *tdata = abfd->tdata.srec_data;
   1127   1.1  christos   srec_data_list_type *list;
   1128   1.1  christos 
   1129   1.1  christos   if (symbols)
   1130   1.1  christos     {
   1131   1.1  christos       if (! srec_write_symbols (abfd))
   1132   1.8  christos 	return false;
   1133   1.1  christos     }
   1134   1.1  christos 
   1135   1.1  christos   if (! srec_write_header (abfd))
   1136   1.8  christos     return false;
   1137   1.1  christos 
   1138   1.1  christos   /* Now wander though all the sections provided and output them.  */
   1139   1.1  christos   list = tdata->head;
   1140   1.1  christos 
   1141   1.1  christos   while (list != (srec_data_list_type *) NULL)
   1142   1.1  christos     {
   1143   1.1  christos       if (! srec_write_section (abfd, tdata, list))
   1144   1.8  christos 	return false;
   1145   1.1  christos       list = list->next;
   1146   1.1  christos     }
   1147   1.1  christos   return srec_write_terminator (abfd, tdata);
   1148   1.1  christos }
   1149   1.1  christos 
   1150   1.8  christos static bool
   1151   1.1  christos srec_write_object_contents (bfd *abfd)
   1152   1.1  christos {
   1153   1.1  christos   return internal_srec_write_object_contents (abfd, 0);
   1154   1.1  christos }
   1155   1.1  christos 
   1156   1.8  christos static bool
   1157   1.1  christos symbolsrec_write_object_contents (bfd *abfd)
   1158   1.1  christos {
   1159   1.1  christos   return internal_srec_write_object_contents (abfd, 1);
   1160   1.1  christos }
   1161   1.1  christos 
   1162   1.1  christos static int
   1163   1.1  christos srec_sizeof_headers (bfd *abfd ATTRIBUTE_UNUSED,
   1164   1.1  christos 		     struct bfd_link_info *info ATTRIBUTE_UNUSED)
   1165   1.1  christos {
   1166   1.1  christos   return 0;
   1167   1.1  christos }
   1168   1.1  christos 
   1169   1.1  christos /* Return the amount of memory needed to read the symbol table.  */
   1170   1.1  christos 
   1171   1.1  christos static long
   1172   1.1  christos srec_get_symtab_upper_bound (bfd *abfd)
   1173   1.1  christos {
   1174   1.1  christos   return (bfd_get_symcount (abfd) + 1) * sizeof (asymbol *);
   1175   1.1  christos }
   1176   1.1  christos 
   1177   1.1  christos /* Return the symbol table.  */
   1178   1.1  christos 
   1179   1.1  christos static long
   1180   1.1  christos srec_canonicalize_symtab (bfd *abfd, asymbol **alocation)
   1181   1.1  christos {
   1182   1.1  christos   bfd_size_type symcount = bfd_get_symcount (abfd);
   1183   1.1  christos   asymbol *csymbols;
   1184   1.1  christos   unsigned int i;
   1185   1.1  christos 
   1186   1.1  christos   csymbols = abfd->tdata.srec_data->csymbols;
   1187   1.1  christos   if (csymbols == NULL && symcount != 0)
   1188   1.1  christos     {
   1189   1.1  christos       asymbol *c;
   1190   1.1  christos       struct srec_symbol *s;
   1191   1.1  christos 
   1192   1.1  christos       csymbols = (asymbol *) bfd_alloc (abfd, symcount * sizeof (asymbol));
   1193   1.1  christos       if (csymbols == NULL)
   1194   1.1  christos 	return -1;
   1195   1.1  christos       abfd->tdata.srec_data->csymbols = csymbols;
   1196   1.1  christos 
   1197   1.1  christos       for (s = abfd->tdata.srec_data->symbols, c = csymbols;
   1198   1.1  christos 	   s != NULL;
   1199   1.1  christos 	   s = s->next, ++c)
   1200   1.1  christos 	{
   1201   1.1  christos 	  c->the_bfd = abfd;
   1202   1.1  christos 	  c->name = s->name;
   1203   1.1  christos 	  c->value = s->val;
   1204   1.1  christos 	  c->flags = BSF_GLOBAL;
   1205   1.1  christos 	  c->section = bfd_abs_section_ptr;
   1206   1.1  christos 	  c->udata.p = NULL;
   1207   1.1  christos 	}
   1208   1.1  christos     }
   1209   1.1  christos 
   1210   1.1  christos   for (i = 0; i < symcount; i++)
   1211   1.1  christos     *alocation++ = csymbols++;
   1212   1.1  christos   *alocation = NULL;
   1213   1.1  christos 
   1214   1.1  christos   return symcount;
   1215   1.1  christos }
   1216   1.1  christos 
   1217   1.1  christos static void
   1218   1.1  christos srec_get_symbol_info (bfd *ignore_abfd ATTRIBUTE_UNUSED,
   1219   1.1  christos 		      asymbol *symbol,
   1220   1.1  christos 		      symbol_info *ret)
   1221   1.1  christos {
   1222   1.1  christos   bfd_symbol_info (symbol, ret);
   1223   1.1  christos }
   1224   1.1  christos 
   1225   1.1  christos static void
   1226   1.1  christos srec_print_symbol (bfd *abfd,
   1227   1.1  christos 		   void * afile,
   1228   1.1  christos 		   asymbol *symbol,
   1229   1.1  christos 		   bfd_print_symbol_type how)
   1230   1.1  christos {
   1231   1.1  christos   FILE *file = (FILE *) afile;
   1232   1.1  christos 
   1233   1.1  christos   switch (how)
   1234   1.1  christos     {
   1235   1.1  christos     case bfd_print_symbol_name:
   1236   1.1  christos       fprintf (file, "%s", symbol->name);
   1237   1.1  christos       break;
   1238   1.1  christos     default:
   1239   1.1  christos       bfd_print_symbol_vandf (abfd, (void *) file, symbol);
   1240   1.1  christos       fprintf (file, " %-5s %s",
   1241   1.1  christos 	       symbol->section->name,
   1242   1.1  christos 	       symbol->name);
   1243   1.1  christos     }
   1244   1.1  christos }
   1245   1.1  christos 
   1246   1.6  christos #define	srec_close_and_cleanup			  _bfd_generic_close_and_cleanup
   1247   1.6  christos #define srec_bfd_free_cached_info		  _bfd_generic_bfd_free_cached_info
   1248   1.6  christos #define srec_new_section_hook			  _bfd_generic_new_section_hook
   1249   1.6  christos #define srec_bfd_is_target_special_symbol	  _bfd_bool_bfd_asymbol_false
   1250   1.6  christos #define srec_bfd_is_local_label_name		  bfd_generic_is_local_label_name
   1251   1.6  christos #define srec_get_lineno				  _bfd_nosymbols_get_lineno
   1252   1.6  christos #define srec_find_nearest_line			  _bfd_nosymbols_find_nearest_line
   1253   1.9  christos #define srec_find_nearest_line_with_alt		  _bfd_nosymbols_find_nearest_line_with_alt
   1254   1.6  christos #define srec_find_line				  _bfd_nosymbols_find_line
   1255   1.6  christos #define srec_find_inliner_info			  _bfd_nosymbols_find_inliner_info
   1256   1.6  christos #define srec_make_empty_symbol			  _bfd_generic_make_empty_symbol
   1257   1.3  christos #define srec_get_symbol_version_string		  _bfd_nosymbols_get_symbol_version_string
   1258   1.6  christos #define srec_bfd_make_debug_symbol		  _bfd_nosymbols_bfd_make_debug_symbol
   1259   1.6  christos #define srec_read_minisymbols			  _bfd_generic_read_minisymbols
   1260   1.6  christos #define srec_minisymbol_to_symbol		  _bfd_generic_minisymbol_to_symbol
   1261   1.6  christos #define srec_bfd_get_relocated_section_contents	  bfd_generic_get_relocated_section_contents
   1262   1.6  christos #define srec_bfd_relax_section			  bfd_generic_relax_section
   1263   1.6  christos #define srec_bfd_gc_sections			  bfd_generic_gc_sections
   1264   1.6  christos #define srec_bfd_lookup_section_flags		  bfd_generic_lookup_section_flags
   1265   1.6  christos #define srec_bfd_merge_sections			  bfd_generic_merge_sections
   1266   1.6  christos #define srec_bfd_is_group_section		  bfd_generic_is_group_section
   1267   1.7  christos #define srec_bfd_group_name			  bfd_generic_group_name
   1268   1.6  christos #define srec_bfd_discard_group			  bfd_generic_discard_group
   1269   1.6  christos #define srec_section_already_linked		  _bfd_generic_section_already_linked
   1270   1.6  christos #define srec_bfd_define_common_symbol		  bfd_generic_define_common_symbol
   1271   1.6  christos #define srec_bfd_link_hide_symbol		  _bfd_generic_link_hide_symbol
   1272   1.6  christos #define srec_bfd_define_start_stop		  bfd_generic_define_start_stop
   1273   1.6  christos #define srec_bfd_link_hash_table_create		  _bfd_generic_link_hash_table_create
   1274   1.6  christos #define srec_bfd_link_add_symbols		  _bfd_generic_link_add_symbols
   1275   1.6  christos #define srec_bfd_link_just_syms			  _bfd_generic_link_just_syms
   1276   1.6  christos #define srec_bfd_copy_link_hash_symbol_type	  _bfd_generic_copy_link_hash_symbol_type
   1277   1.6  christos #define srec_bfd_final_link			  _bfd_generic_final_link
   1278   1.6  christos #define srec_bfd_link_split_section		  _bfd_generic_link_split_section
   1279   1.6  christos #define srec_bfd_link_check_relocs		  _bfd_generic_link_check_relocs
   1280   1.1  christos 
   1281   1.1  christos const bfd_target srec_vec =
   1282   1.1  christos {
   1283   1.1  christos   "srec",			/* Name.  */
   1284   1.1  christos   bfd_target_srec_flavour,
   1285   1.1  christos   BFD_ENDIAN_UNKNOWN,		/* Target byte order.  */
   1286   1.1  christos   BFD_ENDIAN_UNKNOWN,		/* Target headers byte order.  */
   1287  1.10  christos   EXEC_P,			/* Object flags.  */
   1288   1.1  christos   (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS
   1289  1.10  christos    | SEC_ALLOC | SEC_LOAD),	/* Section flags.  */
   1290   1.1  christos   0,				/* Leading underscore.  */
   1291   1.1  christos   ' ',				/* AR_pad_char.  */
   1292   1.1  christos   16,				/* AR_max_namelen.  */
   1293   1.1  christos   0,				/* match priority.  */
   1294   1.8  christos   TARGET_KEEP_UNUSED_SECTION_SYMBOLS, /* keep unused section symbols.  */
   1295   1.1  christos   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
   1296   1.1  christos   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
   1297   1.1  christos   bfd_getb16, bfd_getb_signed_16, bfd_putb16,	/* Data.  */
   1298   1.1  christos   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
   1299   1.1  christos   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
   1300   1.1  christos   bfd_getb16, bfd_getb_signed_16, bfd_putb16,	/* Hdrs.  */
   1301   1.1  christos 
   1302   1.1  christos   {
   1303   1.1  christos     _bfd_dummy_target,
   1304   1.1  christos     srec_object_p,		/* bfd_check_format.  */
   1305   1.1  christos     _bfd_dummy_target,
   1306   1.1  christos     _bfd_dummy_target,
   1307   1.1  christos   },
   1308   1.1  christos   {
   1309   1.6  christos     _bfd_bool_bfd_false_error,
   1310   1.1  christos     srec_mkobject,
   1311  1.10  christos     _bfd_bool_bfd_false_error,
   1312   1.6  christos     _bfd_bool_bfd_false_error,
   1313   1.1  christos   },
   1314   1.1  christos   {				/* bfd_write_contents.  */
   1315   1.6  christos     _bfd_bool_bfd_false_error,
   1316   1.1  christos     srec_write_object_contents,
   1317  1.10  christos     _bfd_bool_bfd_false_error,
   1318   1.6  christos     _bfd_bool_bfd_false_error,
   1319   1.1  christos   },
   1320   1.1  christos 
   1321   1.1  christos   BFD_JUMP_TABLE_GENERIC (srec),
   1322   1.1  christos   BFD_JUMP_TABLE_COPY (_bfd_generic),
   1323   1.1  christos   BFD_JUMP_TABLE_CORE (_bfd_nocore),
   1324   1.1  christos   BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
   1325   1.1  christos   BFD_JUMP_TABLE_SYMBOLS (srec),
   1326   1.1  christos   BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
   1327   1.1  christos   BFD_JUMP_TABLE_WRITE (srec),
   1328   1.1  christos   BFD_JUMP_TABLE_LINK (srec),
   1329   1.1  christos   BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
   1330   1.1  christos 
   1331   1.1  christos   NULL,
   1332   1.1  christos 
   1333   1.1  christos   NULL
   1334   1.1  christos };
   1335   1.1  christos 
   1336   1.1  christos const bfd_target symbolsrec_vec =
   1337   1.1  christos {
   1338   1.1  christos   "symbolsrec",			/* Name.  */
   1339   1.1  christos   bfd_target_srec_flavour,
   1340   1.1  christos   BFD_ENDIAN_UNKNOWN,		/* Target byte order.  */
   1341   1.1  christos   BFD_ENDIAN_UNKNOWN,		/* Target headers byte order.  */
   1342  1.10  christos   EXEC_P | HAS_SYMS,		/* Object flags.  */
   1343   1.1  christos   (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS
   1344  1.10  christos    | SEC_ALLOC | SEC_LOAD),	/* Section flags.  */
   1345   1.1  christos   0,				/* Leading underscore.  */
   1346   1.1  christos   ' ',				/* AR_pad_char.  */
   1347   1.1  christos   16,				/* AR_max_namelen.  */
   1348   1.1  christos   0,				/* match priority.  */
   1349   1.8  christos   TARGET_KEEP_UNUSED_SECTION_SYMBOLS, /* keep unused section symbols.  */
   1350   1.1  christos   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
   1351   1.1  christos   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
   1352   1.1  christos   bfd_getb16, bfd_getb_signed_16, bfd_putb16,	/* Data.  */
   1353   1.1  christos   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
   1354   1.1  christos   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
   1355   1.1  christos   bfd_getb16, bfd_getb_signed_16, bfd_putb16,	/* Headers.  */
   1356   1.1  christos 
   1357   1.1  christos   {
   1358   1.1  christos     _bfd_dummy_target,
   1359   1.1  christos     symbolsrec_object_p,	/* bfd_check_format.  */
   1360   1.1  christos     _bfd_dummy_target,
   1361   1.1  christos     _bfd_dummy_target,
   1362   1.1  christos   },
   1363   1.1  christos   {
   1364   1.6  christos     _bfd_bool_bfd_false_error,
   1365   1.1  christos     srec_mkobject,
   1366  1.10  christos     _bfd_bool_bfd_false_error,
   1367   1.6  christos     _bfd_bool_bfd_false_error,
   1368   1.1  christos   },
   1369   1.1  christos   {				/* bfd_write_contents.  */
   1370   1.6  christos     _bfd_bool_bfd_false_error,
   1371   1.1  christos     symbolsrec_write_object_contents,
   1372  1.10  christos     _bfd_bool_bfd_false_error,
   1373   1.6  christos     _bfd_bool_bfd_false_error,
   1374   1.1  christos   },
   1375   1.1  christos 
   1376   1.1  christos   BFD_JUMP_TABLE_GENERIC (srec),
   1377   1.1  christos   BFD_JUMP_TABLE_COPY (_bfd_generic),
   1378   1.1  christos   BFD_JUMP_TABLE_CORE (_bfd_nocore),
   1379   1.1  christos   BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
   1380   1.1  christos   BFD_JUMP_TABLE_SYMBOLS (srec),
   1381   1.1  christos   BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
   1382   1.1  christos   BFD_JUMP_TABLE_WRITE (srec),
   1383   1.1  christos   BFD_JUMP_TABLE_LINK (srec),
   1384   1.1  christos   BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
   1385   1.1  christos 
   1386   1.1  christos   NULL,
   1387   1.1  christos 
   1388   1.1  christos   NULL
   1389   1.1  christos };
   1390