xref: /openbsd/gnu/usr.bin/binutils/bfd/srec.c (revision b55d4692)
12159047fSniklas /* BFD back-end for s-record objects.
2*b55d4692Sfgsch    Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
3*b55d4692Sfgsch    2000
4b305b0f1Sespie    Free Software Foundation, Inc.
52159047fSniklas    Written by Steve Chamberlain of Cygnus Support <sac@cygnus.com>.
62159047fSniklas 
72159047fSniklas This file is part of BFD, the Binary File Descriptor library.
82159047fSniklas 
92159047fSniklas This program is free software; you can redistribute it and/or modify
102159047fSniklas it under the terms of the GNU General Public License as published by
112159047fSniklas the Free Software Foundation; either version 2 of the License, or
122159047fSniklas (at your option) any later version.
132159047fSniklas 
142159047fSniklas This program is distributed in the hope that it will be useful,
152159047fSniklas but WITHOUT ANY WARRANTY; without even the implied warranty of
162159047fSniklas MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
172159047fSniklas GNU General Public License for more details.
182159047fSniklas 
192159047fSniklas You should have received a copy of the GNU General Public License
202159047fSniklas along with this program; if not, write to the Free Software
212159047fSniklas Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
222159047fSniklas 
232159047fSniklas /*
242159047fSniklas SUBSECTION
252159047fSniklas 	S-Record handling
262159047fSniklas 
272159047fSniklas DESCRIPTION
282159047fSniklas 
292159047fSniklas 	Ordinary S-Records cannot hold anything but addresses and
302159047fSniklas 	data, so that's all that we implement.
312159047fSniklas 
322159047fSniklas 	The only interesting thing is that S-Records may come out of
332159047fSniklas 	order and there is no header, so an initial scan is required
342159047fSniklas 	to discover the minimum and maximum addresses used to create
352159047fSniklas 	the vma and size of the only section we create.  We
362159047fSniklas 	arbitrarily call this section ".text".
372159047fSniklas 
382159047fSniklas 	When bfd_get_section_contents is called the file is read
392159047fSniklas 	again, and this time the data is placed into a bfd_alloc'd
402159047fSniklas 	area.
412159047fSniklas 
422159047fSniklas 	Any number of sections may be created for output, we save them
432159047fSniklas 	up and output them when it's time to close the bfd.
442159047fSniklas 
452159047fSniklas 	An s record looks like:
462159047fSniklas 
472159047fSniklas EXAMPLE
482159047fSniklas 	S<type><length><address><data><checksum>
492159047fSniklas 
502159047fSniklas DESCRIPTION
512159047fSniklas 	Where
522159047fSniklas 	o length
532159047fSniklas 	is the number of bytes following upto the checksum. Note that
542159047fSniklas 	this is not the number of chars following, since it takes two
552159047fSniklas 	chars to represent a byte.
562159047fSniklas 	o type
572159047fSniklas 	is one of:
582159047fSniklas 	0) header record
592159047fSniklas 	1) two byte address data record
602159047fSniklas 	2) three byte address data record
612159047fSniklas 	3) four byte address data record
622159047fSniklas 	7) four byte address termination record
632159047fSniklas 	8) three byte address termination record
642159047fSniklas 	9) two byte address termination record
652159047fSniklas 
662159047fSniklas 	o address
672159047fSniklas 	is the start address of the data following, or in the case of
682159047fSniklas 	a termination record, the start address of the image
692159047fSniklas 	o data
702159047fSniklas 	is the data.
712159047fSniklas 	o checksum
722159047fSniklas 	is the sum of all the raw byte data in the record, from the length
732159047fSniklas 	upwards, modulo 256 and subtracted from 255.
742159047fSniklas 
752159047fSniklas SUBSECTION
762159047fSniklas 	Symbol S-Record handling
772159047fSniklas 
782159047fSniklas DESCRIPTION
792159047fSniklas 	Some ICE equipment understands an addition to the standard
802159047fSniklas 	S-Record format; symbols and their addresses can be sent
812159047fSniklas 	before the data.
822159047fSniklas 
832159047fSniklas 	The format of this is:
842159047fSniklas 	($$ <modulename>
852159047fSniklas 		(<space> <symbol> <address>)*)
862159047fSniklas 	$$
872159047fSniklas 
882159047fSniklas 	so a short symbol table could look like:
892159047fSniklas 
902159047fSniklas EXAMPLE
912159047fSniklas 	$$ flash.x
922159047fSniklas 	$$ flash.c
932159047fSniklas 	  _port6 $0
942159047fSniklas 	  _delay $4
952159047fSniklas 	  _start $14
962159047fSniklas 	  _etext $8036
972159047fSniklas 	  _edata $8036
982159047fSniklas  	  _end $8036
992159047fSniklas 	$$
1002159047fSniklas 
1012159047fSniklas DESCRIPTION
1022159047fSniklas 	We allow symbols to be anywhere in the data stream - the module names
1032159047fSniklas 	are always ignored.
1042159047fSniklas 
1052159047fSniklas */
1062159047fSniklas 
1072159047fSniklas #include "bfd.h"
1082159047fSniklas #include "sysdep.h"
1092159047fSniklas #include "libbfd.h"
1102159047fSniklas #include "libiberty.h"
1112159047fSniklas #include <ctype.h>
1122159047fSniklas 
113b305b0f1Sespie static void srec_get_symbol_info PARAMS ((bfd *, asymbol *, symbol_info *));
114e93f7393Sniklas static void srec_print_symbol
115e93f7393Sniklas  PARAMS ((bfd *, PTR, asymbol *, bfd_print_symbol_type));
1162159047fSniklas static void srec_init PARAMS ((void));
1172159047fSniklas static boolean srec_mkobject PARAMS ((bfd *));
1182159047fSniklas static int srec_get_byte PARAMS ((bfd *, boolean *));
1192159047fSniklas static void srec_bad_byte PARAMS ((bfd *, unsigned int, int, boolean));
1202159047fSniklas static boolean srec_scan PARAMS ((bfd *));
1212159047fSniklas static const bfd_target *srec_object_p PARAMS ((bfd *));
1222159047fSniklas static const bfd_target *symbolsrec_object_p PARAMS ((bfd *));
1232159047fSniklas static boolean srec_read_section PARAMS ((bfd *, asection *, bfd_byte *));
1242159047fSniklas 
1252159047fSniklas static boolean srec_write_record PARAMS ((bfd *, int, bfd_vma,
1262159047fSniklas 					  const bfd_byte *,
1272159047fSniklas 					  const bfd_byte *));
1282159047fSniklas static boolean srec_write_header PARAMS ((bfd *));
1292159047fSniklas static boolean srec_write_symbols PARAMS ((bfd *));
130e93f7393Sniklas static boolean srec_new_symbol PARAMS ((bfd *, const char *, bfd_vma));
131e93f7393Sniklas static boolean srec_get_section_contents
132e93f7393Sniklas   PARAMS ((bfd *, asection *, PTR, file_ptr, bfd_size_type));
133e93f7393Sniklas static boolean srec_set_arch_mach
134e93f7393Sniklas   PARAMS ((bfd *, enum bfd_architecture, unsigned long));
135e93f7393Sniklas static boolean srec_set_section_contents
136e93f7393Sniklas   PARAMS ((bfd *, sec_ptr, PTR, file_ptr, bfd_size_type));
137e93f7393Sniklas static boolean internal_srec_write_object_contents PARAMS ((bfd *, int));
138e93f7393Sniklas static boolean srec_write_object_contents PARAMS ((bfd *));
139e93f7393Sniklas static boolean symbolsrec_write_object_contents PARAMS ((bfd *));
140e93f7393Sniklas static int srec_sizeof_headers PARAMS ((bfd *, boolean));
141e93f7393Sniklas static asymbol *srec_make_empty_symbol PARAMS ((bfd *));
142e93f7393Sniklas static long srec_get_symtab_upper_bound PARAMS ((bfd *));
143e93f7393Sniklas static long srec_get_symtab PARAMS ((bfd *, asymbol **));
1442159047fSniklas 
1452159047fSniklas /* Macros for converting between hex and binary.  */
1462159047fSniklas 
1472159047fSniklas static CONST char digs[] = "0123456789ABCDEF";
1482159047fSniklas 
1492159047fSniklas #define NIBBLE(x) hex_value(x)
1502159047fSniklas #define HEX(buffer) ((NIBBLE((buffer)[0])<<4) + NIBBLE((buffer)[1]))
1512159047fSniklas #define TOHEX(d, x, ch) \
1522159047fSniklas 	d[1] = digs[(x) & 0xf]; \
1532159047fSniklas 	d[0] = digs[((x)>>4)&0xf]; \
1542159047fSniklas 	ch += ((x) & 0xff);
1552159047fSniklas #define	ISHEX(x)  hex_p(x)
1562159047fSniklas 
1572159047fSniklas /* Initialize by filling in the hex conversion array.  */
1582159047fSniklas 
1592159047fSniklas static void
1602159047fSniklas srec_init ()
1612159047fSniklas {
1622159047fSniklas   static boolean inited = false;
1632159047fSniklas 
1642159047fSniklas   if (inited == false)
1652159047fSniklas     {
1662159047fSniklas       inited = true;
1672159047fSniklas       hex_init ();
1682159047fSniklas     }
1692159047fSniklas }
1702159047fSniklas 
171*b55d4692Sfgsch /* The maximum number of bytes on a line is FF.  */
1722159047fSniklas #define MAXCHUNK 0xff
173*b55d4692Sfgsch 
174*b55d4692Sfgsch /* Default size for a CHUNK.  */
175*b55d4692Sfgsch #define DEFAULT_CHUNK 16
176*b55d4692Sfgsch 
177*b55d4692Sfgsch /* The number of bytes we actually fit onto a line on output.
178*b55d4692Sfgsch    This variable can be modified by objcopy's --srec-len parameter.
179*b55d4692Sfgsch    For a 0x75 byte record you should set --srec-len=0x70.  */
180*b55d4692Sfgsch unsigned int Chunk = DEFAULT_CHUNK;
181*b55d4692Sfgsch 
182*b55d4692Sfgsch /* The type of srec output (free or forced to S3).
183*b55d4692Sfgsch    This variable can be modified by objcopy's --srec-forceS3
184*b55d4692Sfgsch    parameter.  */
185*b55d4692Sfgsch boolean S3Forced = 0;
1862159047fSniklas 
1872159047fSniklas /* When writing an S-record file, the S-records can not be output as
1882159047fSniklas    they are seen.  This structure is used to hold them in memory.  */
1892159047fSniklas 
1902159047fSniklas struct srec_data_list_struct
1912159047fSniklas {
1922159047fSniklas   struct srec_data_list_struct *next;
1932159047fSniklas   bfd_byte *data;
1942159047fSniklas   bfd_vma where;
1952159047fSniklas   bfd_size_type size;
1962159047fSniklas };
1972159047fSniklas 
1982159047fSniklas typedef struct srec_data_list_struct srec_data_list_type;
1992159047fSniklas 
2002159047fSniklas /* When scanning the S-record file, a linked list of srec_symbol
2012159047fSniklas    structures is built to represent the symbol table (if there is
2022159047fSniklas    one).  */
2032159047fSniklas 
2042159047fSniklas struct srec_symbol
2052159047fSniklas {
2062159047fSniklas   struct srec_symbol *next;
2072159047fSniklas   const char *name;
2082159047fSniklas   bfd_vma val;
2092159047fSniklas };
2102159047fSniklas 
2112159047fSniklas /* The S-record tdata information.  */
2122159047fSniklas 
2132159047fSniklas typedef struct srec_data_struct
2142159047fSniklas   {
2152159047fSniklas     srec_data_list_type *head;
2162159047fSniklas     srec_data_list_type *tail;
2172159047fSniklas     unsigned int type;
2182159047fSniklas     struct srec_symbol *symbols;
2192159047fSniklas     struct srec_symbol *symtail;
2202159047fSniklas     asymbol *csymbols;
2212159047fSniklas   }
2222159047fSniklas tdata_type;
2232159047fSniklas 
2242159047fSniklas static boolean srec_write_section PARAMS ((bfd *, tdata_type *,
2252159047fSniklas 					   srec_data_list_type *));
2262159047fSniklas static boolean srec_write_terminator PARAMS ((bfd *, tdata_type *));
2272159047fSniklas 
2282159047fSniklas /* Set up the S-record tdata information.  */
2292159047fSniklas 
2302159047fSniklas static boolean
2312159047fSniklas srec_mkobject (abfd)
2322159047fSniklas      bfd *abfd;
2332159047fSniklas {
2342159047fSniklas   srec_init ();
2352159047fSniklas 
2362159047fSniklas   if (abfd->tdata.srec_data == NULL)
2372159047fSniklas     {
2382159047fSniklas       tdata_type *tdata = (tdata_type *) bfd_alloc (abfd, sizeof (tdata_type));
2392159047fSniklas       if (tdata == NULL)
2402159047fSniklas 	return false;
2412159047fSniklas       abfd->tdata.srec_data = tdata;
2422159047fSniklas       tdata->type = 1;
2432159047fSniklas       tdata->head = NULL;
2442159047fSniklas       tdata->tail = NULL;
2452159047fSniklas       tdata->symbols = NULL;
2462159047fSniklas       tdata->symtail = NULL;
2472159047fSniklas       tdata->csymbols = NULL;
2482159047fSniklas     }
2492159047fSniklas 
2502159047fSniklas   return true;
2512159047fSniklas }
2522159047fSniklas 
2532159047fSniklas /* Read a byte from an S record file.  Set *ERRORPTR if an error
2542159047fSniklas    occurred.  Return EOF on error or end of file.  */
2552159047fSniklas 
2562159047fSniklas static int
2572159047fSniklas srec_get_byte (abfd, errorptr)
2582159047fSniklas      bfd *abfd;
2592159047fSniklas      boolean *errorptr;
2602159047fSniklas {
2612159047fSniklas   bfd_byte c;
2622159047fSniklas 
2632159047fSniklas   if (bfd_read (&c, 1, 1, abfd) != 1)
2642159047fSniklas     {
2652159047fSniklas       if (bfd_get_error () != bfd_error_file_truncated)
2662159047fSniklas 	*errorptr = true;
2672159047fSniklas       return EOF;
2682159047fSniklas     }
2692159047fSniklas 
2702159047fSniklas   return (int) (c & 0xff);
2712159047fSniklas }
2722159047fSniklas 
2732159047fSniklas /* Report a problem in an S record file.  FIXME: This probably should
2742159047fSniklas    not call fprintf, but we really do need some mechanism for printing
2752159047fSniklas    error messages.  */
2762159047fSniklas 
2772159047fSniklas static void
2782159047fSniklas srec_bad_byte (abfd, lineno, c, error)
2792159047fSniklas      bfd *abfd;
2802159047fSniklas      unsigned int lineno;
2812159047fSniklas      int c;
2822159047fSniklas      boolean error;
2832159047fSniklas {
2842159047fSniklas   if (c == EOF)
2852159047fSniklas     {
2862159047fSniklas       if (! error)
2872159047fSniklas 	bfd_set_error (bfd_error_file_truncated);
2882159047fSniklas     }
2892159047fSniklas   else
2902159047fSniklas     {
2912159047fSniklas       char buf[10];
2922159047fSniklas 
2932159047fSniklas       if (! isprint (c))
2942159047fSniklas 	sprintf (buf, "\\%03o", (unsigned int) c);
2952159047fSniklas       else
2962159047fSniklas 	{
2972159047fSniklas 	  buf[0] = c;
2982159047fSniklas 	  buf[1] = '\0';
2992159047fSniklas 	}
3002159047fSniklas       (*_bfd_error_handler)
301b305b0f1Sespie 	(_("%s:%d: Unexpected character `%s' in S-record file\n"),
3022159047fSniklas 	 bfd_get_filename (abfd), lineno, buf);
3032159047fSniklas       bfd_set_error (bfd_error_bad_value);
3042159047fSniklas     }
3052159047fSniklas }
3062159047fSniklas 
3072159047fSniklas /* Add a new symbol found in an S-record file.  */
3082159047fSniklas 
3092159047fSniklas static boolean
3102159047fSniklas srec_new_symbol (abfd, name, val)
3112159047fSniklas      bfd *abfd;
3122159047fSniklas      const char *name;
3132159047fSniklas      bfd_vma val;
3142159047fSniklas {
3152159047fSniklas   struct srec_symbol *n;
3162159047fSniklas 
3172159047fSniklas   n = (struct srec_symbol *) bfd_alloc (abfd, sizeof (struct srec_symbol));
3182159047fSniklas   if (n == NULL)
3192159047fSniklas     return false;
3202159047fSniklas 
3212159047fSniklas   n->name = name;
3222159047fSniklas   n->val = val;
3232159047fSniklas 
3242159047fSniklas   if (abfd->tdata.srec_data->symbols == NULL)
3252159047fSniklas     abfd->tdata.srec_data->symbols = n;
3262159047fSniklas   else
3272159047fSniklas     abfd->tdata.srec_data->symtail->next = n;
3282159047fSniklas   abfd->tdata.srec_data->symtail = n;
3292159047fSniklas   n->next = NULL;
3302159047fSniklas 
3312159047fSniklas   ++abfd->symcount;
3322159047fSniklas 
3332159047fSniklas   return true;
3342159047fSniklas }
3352159047fSniklas 
3362159047fSniklas /* Read the S record file and turn it into sections.  We create a new
3372159047fSniklas    section for each contiguous set of bytes.  */
3382159047fSniklas 
3392159047fSniklas static boolean
3402159047fSniklas srec_scan (abfd)
3412159047fSniklas      bfd *abfd;
3422159047fSniklas {
3432159047fSniklas   int c;
3442159047fSniklas   unsigned int lineno = 1;
3452159047fSniklas   boolean error = false;
3462159047fSniklas   bfd_byte *buf = NULL;
3472159047fSniklas   size_t bufsize = 0;
3482159047fSniklas   asection *sec = NULL;
349b305b0f1Sespie   char *symbuf = NULL;
3502159047fSniklas 
3512159047fSniklas   if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
3522159047fSniklas     goto error_return;
3532159047fSniklas 
3542159047fSniklas   while ((c = srec_get_byte (abfd, &error)) != EOF)
3552159047fSniklas     {
3562159047fSniklas       /* We only build sections from contiguous S-records, so if this
3572159047fSniklas          is not an S-record, then stop building a section.  */
3582159047fSniklas       if (c != 'S' && c != '\r' && c != '\n')
3592159047fSniklas 	sec = NULL;
3602159047fSniklas 
3612159047fSniklas       switch (c)
3622159047fSniklas 	{
3632159047fSniklas 	default:
3642159047fSniklas 	  srec_bad_byte (abfd, lineno, c, error);
3652159047fSniklas 	  goto error_return;
3662159047fSniklas 
3672159047fSniklas 	case '\n':
3682159047fSniklas 	  ++lineno;
3692159047fSniklas 	  break;
3702159047fSniklas 
3712159047fSniklas 	case '\r':
3722159047fSniklas 	  break;
3732159047fSniklas 
3742159047fSniklas 	case '$':
3752159047fSniklas 	  /* Starting a module name, which we ignore.  */
3762159047fSniklas 	  while ((c = srec_get_byte (abfd, &error)) != '\n'
3772159047fSniklas 		 && c != EOF)
3782159047fSniklas 	    ;
3792159047fSniklas 	  if (c == EOF)
3802159047fSniklas 	    {
3812159047fSniklas 	      srec_bad_byte (abfd, lineno, c, error);
3822159047fSniklas 	      goto error_return;
3832159047fSniklas 	    }
3842159047fSniklas 
3852159047fSniklas 	  ++lineno;
3862159047fSniklas 
3872159047fSniklas 	  break;
3882159047fSniklas 
3892159047fSniklas 	case ' ':
390e93f7393Sniklas 	  do
3912159047fSniklas 	    {
392b305b0f1Sespie 	      unsigned int alc;
393b305b0f1Sespie 	      char *p, *symname;
3942159047fSniklas 	      bfd_vma symval;
3952159047fSniklas 
3962159047fSniklas 	      /* Starting a symbol definition.  */
3972159047fSniklas 	      while ((c = srec_get_byte (abfd, &error)) != EOF
3982159047fSniklas 		     && (c == ' ' || c == '\t'))
3992159047fSniklas 		;
400e93f7393Sniklas 
401b305b0f1Sespie 	      if (c == '\n' || c == '\r')
402e93f7393Sniklas 		break;
403e93f7393Sniklas 
4042159047fSniklas 	      if (c == EOF)
4052159047fSniklas 		{
4062159047fSniklas 		  srec_bad_byte (abfd, lineno, c, error);
4072159047fSniklas 		  goto error_return;
4082159047fSniklas 		}
4092159047fSniklas 
410b305b0f1Sespie 	      alc = 10;
411b305b0f1Sespie 	      symbuf = (char *) bfd_malloc (alc + 1);
412b305b0f1Sespie 	      if (symbuf == NULL)
413b305b0f1Sespie 		goto error_return;
414b305b0f1Sespie 
415b305b0f1Sespie 	      p = symbuf;
416b305b0f1Sespie 
417b305b0f1Sespie 	      *p++ = c;
4182159047fSniklas 	      while ((c = srec_get_byte (abfd, &error)) != EOF
4192159047fSniklas 		     && ! isspace (c))
420b305b0f1Sespie 		{
421b305b0f1Sespie 		  if ((unsigned int) (p - symbuf) >= alc)
422b305b0f1Sespie 		    {
423b305b0f1Sespie 		      char *n;
424b305b0f1Sespie 
425b305b0f1Sespie 		      alc *= 2;
426b305b0f1Sespie 		      n = (char *) bfd_realloc (symbuf, alc + 1);
427b305b0f1Sespie 		      if (n == NULL)
428b305b0f1Sespie 			goto error_return;
429b305b0f1Sespie 		      p = n + (p - symbuf);
430b305b0f1Sespie 		      symbuf = n;
431b305b0f1Sespie 		    }
432b305b0f1Sespie 
433b305b0f1Sespie 		  *p++ = c;
434b305b0f1Sespie 		}
435b305b0f1Sespie 
4362159047fSniklas 	      if (c == EOF)
4372159047fSniklas 		{
4382159047fSniklas 		  srec_bad_byte (abfd, lineno, c, error);
4392159047fSniklas 		  goto error_return;
4402159047fSniklas 		}
4412159047fSniklas 
442b305b0f1Sespie 	      *p++ = '\0';
443b305b0f1Sespie 	      symname = bfd_alloc (abfd, p - symbuf);
4442159047fSniklas 	      if (symname == NULL)
4452159047fSniklas 		goto error_return;
446b305b0f1Sespie 	      strcpy (symname, symbuf);
447b305b0f1Sespie 	      free (symbuf);
448b305b0f1Sespie 	      symbuf = NULL;
4492159047fSniklas 
4502159047fSniklas 	      while ((c = srec_get_byte (abfd, &error)) != EOF
4512159047fSniklas 		     && (c == ' ' || c == '\t'))
4522159047fSniklas 		;
4532159047fSniklas 	      if (c == EOF)
4542159047fSniklas 		{
4552159047fSniklas 		  srec_bad_byte (abfd, lineno, c, error);
4562159047fSniklas 		  goto error_return;
4572159047fSniklas 		}
4582159047fSniklas 
4592159047fSniklas 	      /* Skip a dollar sign before the hex value.  */
4602159047fSniklas 	      if (c == '$')
4612159047fSniklas 		{
4622159047fSniklas 		  c = srec_get_byte (abfd, &error);
4632159047fSniklas 		  if (c == EOF)
4642159047fSniklas 		    {
4652159047fSniklas 		      srec_bad_byte (abfd, lineno, c, error);
4662159047fSniklas 		      goto error_return;
4672159047fSniklas 		    }
4682159047fSniklas 		}
4692159047fSniklas 
4702159047fSniklas 	      symval = 0;
4712159047fSniklas 	      while (ISHEX (c))
4722159047fSniklas 		{
4732159047fSniklas 		  symval <<= 4;
4742159047fSniklas 		  symval += NIBBLE (c);
4752159047fSniklas 		  c = srec_get_byte (abfd, &error);
4762159047fSniklas 		}
4772159047fSniklas 
478e93f7393Sniklas 	      if (! srec_new_symbol (abfd, symname, symval))
479e93f7393Sniklas 		goto error_return;
480e93f7393Sniklas 	    }
481*b55d4692Sfgsch 	  while (c == ' ' || c == '\t')
482*b55d4692Sfgsch 	    ;
483e93f7393Sniklas 
484b305b0f1Sespie 	  if (c == '\n')
485b305b0f1Sespie 	    ++lineno;
486b305b0f1Sespie 	  else if (c != '\r')
4872159047fSniklas 	    {
4882159047fSniklas 	      srec_bad_byte (abfd, lineno, c, error);
4892159047fSniklas 	      goto error_return;
4902159047fSniklas 	    }
4912159047fSniklas 
4922159047fSniklas 	  break;
4932159047fSniklas 
4942159047fSniklas 	case 'S':
4952159047fSniklas 	  {
4962159047fSniklas 	    file_ptr pos;
4972159047fSniklas 	    char hdr[3];
4982159047fSniklas 	    unsigned int bytes;
4992159047fSniklas 	    bfd_vma address;
5002159047fSniklas 	    bfd_byte *data;
5012159047fSniklas 
5022159047fSniklas 	    /* Starting an S-record.  */
5032159047fSniklas 
5042159047fSniklas 	    pos = bfd_tell (abfd) - 1;
5052159047fSniklas 
5062159047fSniklas 	    if (bfd_read (hdr, 1, 3, abfd) != 3)
5072159047fSniklas 	      goto error_return;
5082159047fSniklas 
5092159047fSniklas 	    if (! ISHEX (hdr[1]) || ! ISHEX (hdr[2]))
5102159047fSniklas 	      {
5112159047fSniklas 		if (! ISHEX (hdr[1]))
5122159047fSniklas 		  c = hdr[1];
5132159047fSniklas 		else
5142159047fSniklas 		  c = hdr[2];
5152159047fSniklas 		srec_bad_byte (abfd, lineno, c, error);
5162159047fSniklas 		goto error_return;
5172159047fSniklas 	      }
5182159047fSniklas 
5192159047fSniklas 	    bytes = HEX (hdr + 1);
5202159047fSniklas 	    if (bytes * 2 > bufsize)
5212159047fSniklas 	      {
5222159047fSniklas 		if (buf != NULL)
5232159047fSniklas 		  free (buf);
524c88b1d6cSniklas 		buf = (bfd_byte *) bfd_malloc (bytes * 2);
5252159047fSniklas 		if (buf == NULL)
5262159047fSniklas 		  goto error_return;
5272159047fSniklas 		bufsize = bytes * 2;
5282159047fSniklas 	      }
5292159047fSniklas 
5302159047fSniklas 	    if (bfd_read (buf, 1, bytes * 2, abfd) != bytes * 2)
5312159047fSniklas 	      goto error_return;
5322159047fSniklas 
5332159047fSniklas 	    /* Ignore the checksum byte.  */
5342159047fSniklas 	    --bytes;
5352159047fSniklas 
5362159047fSniklas 	    address = 0;
5372159047fSniklas 	    data = buf;
5382159047fSniklas 	    switch (hdr[0])
5392159047fSniklas 	      {
5402159047fSniklas 	      case '0':
5412159047fSniklas 	      case '5':
5422159047fSniklas 		/* Prologue--ignore the file name, but stop building a
5432159047fSniklas                    section at this point.  */
5442159047fSniklas 		sec = NULL;
5452159047fSniklas 		break;
5462159047fSniklas 
5472159047fSniklas 	      case '3':
5482159047fSniklas 		address = HEX (data);
5492159047fSniklas 		data += 2;
5502159047fSniklas 		--bytes;
5512159047fSniklas 		/* Fall through.  */
5522159047fSniklas 	      case '2':
5532159047fSniklas 		address = (address << 8) | HEX (data);
5542159047fSniklas 		data += 2;
5552159047fSniklas 		--bytes;
5562159047fSniklas 		/* Fall through.  */
5572159047fSniklas 	      case '1':
5582159047fSniklas 		address = (address << 8) | HEX (data);
5592159047fSniklas 		data += 2;
5602159047fSniklas 		address = (address << 8) | HEX (data);
5612159047fSniklas 		data += 2;
5622159047fSniklas 		bytes -= 2;
5632159047fSniklas 
5642159047fSniklas 		if (sec != NULL
5652159047fSniklas 		    && sec->vma + sec->_raw_size == address)
5662159047fSniklas 		  {
5672159047fSniklas 		    /* This data goes at the end of the section we are
5682159047fSniklas                        currently building.  */
5692159047fSniklas 		    sec->_raw_size += bytes;
5702159047fSniklas 		  }
5712159047fSniklas 		else
5722159047fSniklas 		  {
5732159047fSniklas 		    char secbuf[20];
5742159047fSniklas 		    char *secname;
5752159047fSniklas 
5762159047fSniklas 		    sprintf (secbuf, ".sec%d", bfd_count_sections (abfd) + 1);
5772159047fSniklas 		    secname = (char *) bfd_alloc (abfd, strlen (secbuf) + 1);
5782159047fSniklas 		    strcpy (secname, secbuf);
5792159047fSniklas 		    sec = bfd_make_section (abfd, secname);
5802159047fSniklas 		    if (sec == NULL)
5812159047fSniklas 		      goto error_return;
5822159047fSniklas 		    sec->flags = SEC_HAS_CONTENTS | SEC_LOAD | SEC_ALLOC;
5832159047fSniklas 		    sec->vma = address;
584c88b1d6cSniklas 		    sec->lma = address;
5852159047fSniklas 		    sec->_raw_size = bytes;
5862159047fSniklas 		    sec->filepos = pos;
5872159047fSniklas 		  }
5882159047fSniklas 
5892159047fSniklas 		break;
5902159047fSniklas 
5912159047fSniklas 	      case '7':
5922159047fSniklas 		address = HEX (data);
5932159047fSniklas 		data += 2;
5942159047fSniklas 		/* Fall through.  */
5952159047fSniklas 	      case '8':
5962159047fSniklas 		address = (address << 8) | HEX (data);
5972159047fSniklas 		data += 2;
5982159047fSniklas 		/* Fall through.  */
5992159047fSniklas 	      case '9':
6002159047fSniklas 		address = (address << 8) | HEX (data);
6012159047fSniklas 		data += 2;
6022159047fSniklas 		address = (address << 8) | HEX (data);
6032159047fSniklas 		data += 2;
6042159047fSniklas 
6052159047fSniklas 		/* This is a termination record.  */
6062159047fSniklas 		abfd->start_address = address;
6072159047fSniklas 
6082159047fSniklas 		if (buf != NULL)
6092159047fSniklas 		  free (buf);
6102159047fSniklas 
6112159047fSniklas 		return true;
6122159047fSniklas 	      }
6132159047fSniklas 	  }
6142159047fSniklas 	  break;
6152159047fSniklas 	}
6162159047fSniklas     }
6172159047fSniklas 
6182159047fSniklas   if (error)
6192159047fSniklas     goto error_return;
6202159047fSniklas 
6212159047fSniklas   if (buf != NULL)
6222159047fSniklas     free (buf);
6232159047fSniklas 
6242159047fSniklas   return true;
6252159047fSniklas 
6262159047fSniklas  error_return:
627b305b0f1Sespie   if (symbuf != NULL)
628b305b0f1Sespie     free (symbuf);
6292159047fSniklas   if (buf != NULL)
6302159047fSniklas     free (buf);
6312159047fSniklas   return false;
6322159047fSniklas }
6332159047fSniklas 
6342159047fSniklas /* Check whether an existing file is an S-record file.  */
6352159047fSniklas 
6362159047fSniklas static const bfd_target *
6372159047fSniklas srec_object_p (abfd)
6382159047fSniklas      bfd *abfd;
6392159047fSniklas {
6402159047fSniklas   bfd_byte b[4];
6412159047fSniklas 
6422159047fSniklas   srec_init ();
6432159047fSniklas 
6442159047fSniklas   if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0
6452159047fSniklas       || bfd_read (b, 1, 4, abfd) != 4)
6462159047fSniklas     return NULL;
6472159047fSniklas 
6482159047fSniklas   if (b[0] != 'S' || !ISHEX (b[1]) || !ISHEX (b[2]) || !ISHEX (b[3]))
6492159047fSniklas     {
6502159047fSniklas       bfd_set_error (bfd_error_wrong_format);
6512159047fSniklas       return NULL;
6522159047fSniklas     }
6532159047fSniklas 
6542159047fSniklas   if (! srec_mkobject (abfd)
6552159047fSniklas       || ! srec_scan (abfd))
6562159047fSniklas     return NULL;
6572159047fSniklas 
658b305b0f1Sespie   if (abfd->symcount > 0)
659b305b0f1Sespie     abfd->flags |= HAS_SYMS;
660b305b0f1Sespie 
6612159047fSniklas   return abfd->xvec;
6622159047fSniklas }
6632159047fSniklas 
6642159047fSniklas /* Check whether an existing file is an S-record file with symbols.  */
6652159047fSniklas 
6662159047fSniklas static const bfd_target *
6672159047fSniklas symbolsrec_object_p (abfd)
6682159047fSniklas      bfd *abfd;
6692159047fSniklas {
6702159047fSniklas   char b[2];
6712159047fSniklas 
6722159047fSniklas   srec_init ();
6732159047fSniklas 
6742159047fSniklas   if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0
6752159047fSniklas       || bfd_read (b, 1, 2, abfd) != 2)
6762159047fSniklas     return NULL;
6772159047fSniklas 
6782159047fSniklas   if (b[0] != '$' || b[1] != '$')
6792159047fSniklas     {
6802159047fSniklas       bfd_set_error (bfd_error_wrong_format);
6812159047fSniklas       return NULL;
6822159047fSniklas     }
6832159047fSniklas 
6842159047fSniklas   if (! srec_mkobject (abfd)
6852159047fSniklas       || ! srec_scan (abfd))
6862159047fSniklas     return NULL;
6872159047fSniklas 
688b305b0f1Sespie   if (abfd->symcount > 0)
689b305b0f1Sespie     abfd->flags |= HAS_SYMS;
690b305b0f1Sespie 
6912159047fSniklas   return abfd->xvec;
6922159047fSniklas }
6932159047fSniklas 
6942159047fSniklas /* Read in the contents of a section in an S-record file.  */
6952159047fSniklas 
6962159047fSniklas static boolean
6972159047fSniklas srec_read_section (abfd, section, contents)
6982159047fSniklas      bfd *abfd;
6992159047fSniklas      asection *section;
7002159047fSniklas      bfd_byte *contents;
7012159047fSniklas {
7022159047fSniklas   int c;
7032159047fSniklas   bfd_size_type sofar = 0;
7042159047fSniklas   boolean error = false;
7052159047fSniklas   bfd_byte *buf = NULL;
7062159047fSniklas   size_t bufsize = 0;
7072159047fSniklas 
7082159047fSniklas   if (bfd_seek (abfd, section->filepos, SEEK_SET) != 0)
7092159047fSniklas     goto error_return;
7102159047fSniklas 
7112159047fSniklas   while ((c = srec_get_byte (abfd, &error)) != EOF)
7122159047fSniklas     {
7132159047fSniklas       bfd_byte hdr[3];
7142159047fSniklas       unsigned int bytes;
7152159047fSniklas       bfd_vma address;
7162159047fSniklas       bfd_byte *data;
7172159047fSniklas 
7182159047fSniklas       if (c == '\r' || c == '\n')
7192159047fSniklas 	continue;
7202159047fSniklas 
7212159047fSniklas       /* This is called after srec_scan has already been called, so we
7222159047fSniklas          ought to know the exact format.  */
7232159047fSniklas       BFD_ASSERT (c == 'S');
7242159047fSniklas 
7252159047fSniklas       if (bfd_read (hdr, 1, 3, abfd) != 3)
7262159047fSniklas 	goto error_return;
7272159047fSniklas 
7282159047fSniklas       BFD_ASSERT (ISHEX (hdr[1]) && ISHEX (hdr[2]));
7292159047fSniklas 
7302159047fSniklas       bytes = HEX (hdr + 1);
7312159047fSniklas 
7322159047fSniklas       if (bytes * 2 > bufsize)
7332159047fSniklas 	{
7342159047fSniklas 	  if (buf != NULL)
7352159047fSniklas 	    free (buf);
736c88b1d6cSniklas 	  buf = (bfd_byte *) bfd_malloc (bytes * 2);
7372159047fSniklas 	  if (buf == NULL)
7382159047fSniklas 	    goto error_return;
7392159047fSniklas 	  bufsize = bytes * 2;
7402159047fSniklas 	}
7412159047fSniklas 
7422159047fSniklas       if (bfd_read (buf, 1, bytes * 2, abfd) != bytes * 2)
7432159047fSniklas 	goto error_return;
7442159047fSniklas 
7452159047fSniklas       address = 0;
7462159047fSniklas       data = buf;
7472159047fSniklas       switch (hdr[0])
7482159047fSniklas 	{
7492159047fSniklas 	default:
7502159047fSniklas 	  BFD_ASSERT (sofar == section->_raw_size);
7512159047fSniklas 	  if (buf != NULL)
7522159047fSniklas 	    free (buf);
7532159047fSniklas 	  return true;
7542159047fSniklas 
7552159047fSniklas 	case '3':
7562159047fSniklas 	  address = HEX (data);
7572159047fSniklas 	  data += 2;
7582159047fSniklas 	  --bytes;
7592159047fSniklas 	  /* Fall through.  */
7602159047fSniklas 	case '2':
7612159047fSniklas 	  address = (address << 8) | HEX (data);
7622159047fSniklas 	  data += 2;
7632159047fSniklas 	  --bytes;
7642159047fSniklas 	  /* Fall through.  */
7652159047fSniklas 	case '1':
7662159047fSniklas 	  address = (address << 8) | HEX (data);
7672159047fSniklas 	  data += 2;
7682159047fSniklas 	  address = (address << 8) | HEX (data);
7692159047fSniklas 	  data += 2;
7702159047fSniklas 	  bytes -= 2;
7712159047fSniklas 
7722159047fSniklas 	  if (address != section->vma + sofar)
7732159047fSniklas 	    {
7742159047fSniklas 	      /* We've come to the end of this section.  */
7752159047fSniklas 	      BFD_ASSERT (sofar == section->_raw_size);
7762159047fSniklas 	      if (buf != NULL)
7772159047fSniklas 		free (buf);
7782159047fSniklas 	      return true;
7792159047fSniklas 	    }
7802159047fSniklas 
7812159047fSniklas 	  /* Don't consider checksum.  */
7822159047fSniklas 	  --bytes;
7832159047fSniklas 
7842159047fSniklas 	  while (bytes-- != 0)
7852159047fSniklas 	    {
7862159047fSniklas 	      contents[sofar] = HEX (data);
7872159047fSniklas 	      data += 2;
7882159047fSniklas 	      ++sofar;
7892159047fSniklas 	    }
7902159047fSniklas 
7912159047fSniklas 	  break;
7922159047fSniklas 	}
7932159047fSniklas     }
7942159047fSniklas 
7952159047fSniklas   if (error)
7962159047fSniklas     goto error_return;
7972159047fSniklas 
7982159047fSniklas   BFD_ASSERT (sofar == section->_raw_size);
7992159047fSniklas 
8002159047fSniklas   if (buf != NULL)
8012159047fSniklas     free (buf);
8022159047fSniklas 
8032159047fSniklas   return true;
8042159047fSniklas 
8052159047fSniklas  error_return:
8062159047fSniklas   if (buf != NULL)
8072159047fSniklas     free (buf);
8082159047fSniklas   return false;
8092159047fSniklas }
8102159047fSniklas 
8112159047fSniklas /* Get the contents of a section in an S-record file.  */
8122159047fSniklas 
8132159047fSniklas static boolean
8142159047fSniklas srec_get_section_contents (abfd, section, location, offset, count)
8152159047fSniklas      bfd *abfd;
8162159047fSniklas      asection *section;
8172159047fSniklas      PTR location;
8182159047fSniklas      file_ptr offset;
8192159047fSniklas      bfd_size_type count;
8202159047fSniklas {
8212159047fSniklas   if (section->used_by_bfd == NULL)
8222159047fSniklas     {
8232159047fSniklas       section->used_by_bfd = bfd_alloc (abfd, section->_raw_size);
8242159047fSniklas       if (section->used_by_bfd == NULL
8252159047fSniklas 	  && section->_raw_size != 0)
8262159047fSniklas 	return false;
8272159047fSniklas 
8282159047fSniklas       if (! srec_read_section (abfd, section, section->used_by_bfd))
8292159047fSniklas 	return false;
8302159047fSniklas     }
8312159047fSniklas 
8322159047fSniklas   memcpy (location, (bfd_byte *) section->used_by_bfd + offset,
8332159047fSniklas 	  (size_t) count);
8342159047fSniklas 
8352159047fSniklas   return true;
8362159047fSniklas }
8372159047fSniklas 
838c88b1d6cSniklas /* Set the architecture.  We accept an unknown architecture here.  */
839c88b1d6cSniklas 
840c88b1d6cSniklas static boolean
841c88b1d6cSniklas srec_set_arch_mach (abfd, arch, mach)
842c88b1d6cSniklas      bfd *abfd;
843c88b1d6cSniklas      enum bfd_architecture arch;
844c88b1d6cSniklas      unsigned long mach;
845c88b1d6cSniklas {
846c88b1d6cSniklas   if (arch == bfd_arch_unknown)
847c88b1d6cSniklas     {
848c88b1d6cSniklas       abfd->arch_info = &bfd_default_arch_struct;
849c88b1d6cSniklas       return true;
850c88b1d6cSniklas     }
851c88b1d6cSniklas   return bfd_default_set_arch_mach (abfd, arch, mach);
852c88b1d6cSniklas }
853c88b1d6cSniklas 
854*b55d4692Sfgsch /* We have to save up all the Srecords for a splurge before output.  */
8552159047fSniklas 
8562159047fSniklas static boolean
8572159047fSniklas srec_set_section_contents (abfd, section, location, offset, bytes_to_do)
8582159047fSniklas      bfd *abfd;
8592159047fSniklas      sec_ptr section;
8602159047fSniklas      PTR location;
8612159047fSniklas      file_ptr offset;
8622159047fSniklas      bfd_size_type bytes_to_do;
8632159047fSniklas {
8642159047fSniklas   tdata_type *tdata = abfd->tdata.srec_data;
8652159047fSniklas   register srec_data_list_type *entry;
8662159047fSniklas 
8672159047fSniklas   entry = ((srec_data_list_type *)
8682159047fSniklas 	   bfd_alloc (abfd, sizeof (srec_data_list_type)));
8692159047fSniklas   if (entry == NULL)
8702159047fSniklas     return false;
8712159047fSniklas 
8722159047fSniklas   if (bytes_to_do
8732159047fSniklas       && (section->flags & SEC_ALLOC)
8742159047fSniklas       && (section->flags & SEC_LOAD))
8752159047fSniklas     {
8762159047fSniklas       bfd_byte *data = (bfd_byte *) bfd_alloc (abfd, bytes_to_do);
8772159047fSniklas       if (data == NULL)
8782159047fSniklas 	return false;
8792159047fSniklas       memcpy ((PTR) data, location, (size_t) bytes_to_do);
8802159047fSniklas 
881*b55d4692Sfgsch       /* Ff S3Forced is true then always select S3 records,
882*b55d4692Sfgsch 	 regardless of the siez of the addresses.  */
883*b55d4692Sfgsch       if (S3Forced)
884*b55d4692Sfgsch 	tdata->type = 3;
885*b55d4692Sfgsch       else if ((section->lma + offset + bytes_to_do - 1) <= 0xffff)
886*b55d4692Sfgsch 	;  /* The default, S1, is OK.  */
8872159047fSniklas       else if ((section->lma + offset + bytes_to_do - 1) <= 0xffffff
888b305b0f1Sespie 	       && tdata->type <= 2)
8892159047fSniklas 	tdata->type = 2;
8902159047fSniklas       else
8912159047fSniklas 	tdata->type = 3;
8922159047fSniklas 
8932159047fSniklas       entry->data = data;
8942159047fSniklas       entry->where = section->lma + offset;
8952159047fSniklas       entry->size = bytes_to_do;
8962159047fSniklas 
8972159047fSniklas       /* Sort the records by address.  Optimize for the common case of
8982159047fSniklas          adding a record to the end of the list.  */
8992159047fSniklas       if (tdata->tail != NULL
9002159047fSniklas 	  && entry->where >= tdata->tail->where)
9012159047fSniklas 	{
9022159047fSniklas 	  tdata->tail->next = entry;
9032159047fSniklas 	  entry->next = NULL;
9042159047fSniklas 	  tdata->tail = entry;
9052159047fSniklas 	}
9062159047fSniklas       else
9072159047fSniklas 	{
9082159047fSniklas 	  register srec_data_list_type **look;
9092159047fSniklas 
9102159047fSniklas 	  for (look = &tdata->head;
9112159047fSniklas 	       *look != NULL && (*look)->where < entry->where;
9122159047fSniklas 	       look = &(*look)->next)
9132159047fSniklas 	    ;
9142159047fSniklas 	  entry->next = *look;
9152159047fSniklas 	  *look = entry;
9162159047fSniklas 	  if (entry->next == NULL)
9172159047fSniklas 	    tdata->tail = entry;
9182159047fSniklas 	}
9192159047fSniklas     }
9202159047fSniklas   return true;
9212159047fSniklas }
9222159047fSniklas 
9232159047fSniklas /* Write a record of type, of the supplied number of bytes. The
9242159047fSniklas    supplied bytes and length don't have a checksum. That's worked out
925*b55d4692Sfgsch    here.  */
926*b55d4692Sfgsch 
9272159047fSniklas static boolean
9282159047fSniklas srec_write_record (abfd, type, address, data, end)
9292159047fSniklas      bfd *abfd;
9302159047fSniklas      int type;
9312159047fSniklas      bfd_vma address;
9322159047fSniklas      const bfd_byte *data;
9332159047fSniklas      const bfd_byte *end;
9342159047fSniklas {
9352159047fSniklas   char buffer[MAXCHUNK];
9362159047fSniklas   unsigned int check_sum = 0;
9372159047fSniklas   CONST bfd_byte *src = data;
9382159047fSniklas   char *dst = buffer;
9392159047fSniklas   char *length;
9402159047fSniklas   bfd_size_type wrlen;
9412159047fSniklas 
9422159047fSniklas   *dst++ = 'S';
9432159047fSniklas   *dst++ = '0' + type;
9442159047fSniklas 
9452159047fSniklas   length = dst;
946*b55d4692Sfgsch   dst += 2;			/* Leave room for dst.  */
9472159047fSniklas 
9482159047fSniklas   switch (type)
9492159047fSniklas     {
9502159047fSniklas     case 3:
9512159047fSniklas     case 7:
9522159047fSniklas       TOHEX (dst, (address >> 24), check_sum);
9532159047fSniklas       dst += 2;
9542159047fSniklas     case 8:
9552159047fSniklas     case 2:
9562159047fSniklas       TOHEX (dst, (address >> 16), check_sum);
9572159047fSniklas       dst += 2;
9582159047fSniklas     case 9:
9592159047fSniklas     case 1:
9602159047fSniklas     case 0:
9612159047fSniklas       TOHEX (dst, (address >> 8), check_sum);
9622159047fSniklas       dst += 2;
9632159047fSniklas       TOHEX (dst, (address), check_sum);
9642159047fSniklas       dst += 2;
9652159047fSniklas       break;
9662159047fSniklas 
9672159047fSniklas     }
9682159047fSniklas   for (src = data; src < end; src++)
9692159047fSniklas     {
9702159047fSniklas       TOHEX (dst, *src, check_sum);
9712159047fSniklas       dst += 2;
9722159047fSniklas     }
9732159047fSniklas 
974*b55d4692Sfgsch   /* Fill in the length.  */
9752159047fSniklas   TOHEX (length, (dst - length) / 2, check_sum);
9762159047fSniklas   check_sum &= 0xff;
9772159047fSniklas   check_sum = 255 - check_sum;
9782159047fSniklas   TOHEX (dst, check_sum, check_sum);
9792159047fSniklas   dst += 2;
9802159047fSniklas 
9812159047fSniklas   *dst++ = '\r';
9822159047fSniklas   *dst++ = '\n';
9832159047fSniklas   wrlen = dst - buffer;
9842159047fSniklas   if (bfd_write ((PTR) buffer, 1, wrlen, abfd) != wrlen)
9852159047fSniklas     return false;
9862159047fSniklas   return true;
9872159047fSniklas }
9882159047fSniklas 
9892159047fSniklas static boolean
9902159047fSniklas srec_write_header (abfd)
9912159047fSniklas      bfd *abfd;
9922159047fSniklas {
9932159047fSniklas   bfd_byte buffer[MAXCHUNK];
9942159047fSniklas   bfd_byte *dst = buffer;
9952159047fSniklas   unsigned int i;
9962159047fSniklas 
997*b55d4692Sfgsch   /* I'll put an arbitary 40 char limit on header size.  */
9982159047fSniklas   for (i = 0; i < 40 && abfd->filename[i]; i++)
9992159047fSniklas     *dst++ = abfd->filename[i];
1000*b55d4692Sfgsch 
10012159047fSniklas   return srec_write_record (abfd, 0, 0, buffer, dst);
10022159047fSniklas }
10032159047fSniklas 
10042159047fSniklas static boolean
10052159047fSniklas srec_write_section (abfd, tdata, list)
10062159047fSniklas      bfd *abfd;
10072159047fSniklas      tdata_type *tdata;
10082159047fSniklas      srec_data_list_type *list;
10092159047fSniklas {
1010b305b0f1Sespie   unsigned int octets_written = 0;
10112159047fSniklas   bfd_byte *location = list->data;
10122159047fSniklas 
1013b305b0f1Sespie   while (octets_written < list->size)
10142159047fSniklas     {
10152159047fSniklas       bfd_vma address;
1016b305b0f1Sespie       unsigned int octets_this_chunk = list->size - octets_written;
10172159047fSniklas 
1018*b55d4692Sfgsch       if (octets_this_chunk > Chunk)
1019*b55d4692Sfgsch 	octets_this_chunk = Chunk;
10202159047fSniklas 
1021b305b0f1Sespie       address = list->where + octets_written / bfd_octets_per_byte (abfd);
10222159047fSniklas 
10232159047fSniklas       if (! srec_write_record (abfd,
10242159047fSniklas 			       tdata->type,
10252159047fSniklas 			       address,
10262159047fSniklas 			       location,
1027b305b0f1Sespie 			       location + octets_this_chunk))
10282159047fSniklas 	return false;
10292159047fSniklas 
1030b305b0f1Sespie       octets_written += octets_this_chunk;
1031b305b0f1Sespie       location += octets_this_chunk;
10322159047fSniklas     }
10332159047fSniklas 
10342159047fSniklas   return true;
10352159047fSniklas }
10362159047fSniklas 
10372159047fSniklas static boolean
10382159047fSniklas srec_write_terminator (abfd, tdata)
10392159047fSniklas      bfd *abfd;
10402159047fSniklas      tdata_type *tdata;
10412159047fSniklas {
10422159047fSniklas   bfd_byte buffer[2];
10432159047fSniklas 
10442159047fSniklas   return srec_write_record (abfd, 10 - tdata->type,
10452159047fSniklas 			    abfd->start_address, buffer, buffer);
10462159047fSniklas }
10472159047fSniklas 
10482159047fSniklas static boolean
10492159047fSniklas srec_write_symbols (abfd)
10502159047fSniklas      bfd *abfd;
10512159047fSniklas {
10522159047fSniklas   char buffer[MAXCHUNK];
1053*b55d4692Sfgsch   /* Dump out the symbols of a bfd.  */
10542159047fSniklas   int i;
10552159047fSniklas   int count = bfd_get_symcount (abfd);
10562159047fSniklas 
10572159047fSniklas   if (count)
10582159047fSniklas     {
10592159047fSniklas       size_t len;
10602159047fSniklas       asymbol **table = bfd_get_outsymbols (abfd);
10612159047fSniklas       sprintf (buffer, "$$ %s\r\n", abfd->filename);
10622159047fSniklas 
10632159047fSniklas       len = strlen (buffer);
10642159047fSniklas       if (bfd_write (buffer, len, 1, abfd) != len)
10652159047fSniklas 	return false;
10662159047fSniklas 
10672159047fSniklas       for (i = 0; i < count; i++)
10682159047fSniklas 	{
10692159047fSniklas 	  asymbol *s = table[i];
1070b305b0f1Sespie 	  if (! bfd_is_local_label (abfd, s)
1071b305b0f1Sespie 	      && (s->flags & BSF_DEBUGGING) == 0)
10722159047fSniklas 	    {
1073*b55d4692Sfgsch 	      /* Just dump out non debug symbols.  */
10742159047fSniklas 	      bfd_size_type l;
10752159047fSniklas 	      char buf2[40], *p;
10762159047fSniklas 
10772159047fSniklas 	      sprintf_vma (buf2,
10782159047fSniklas 			   s->value + s->section->output_section->lma
10792159047fSniklas 			   + s->section->output_offset);
10802159047fSniklas 	      p = buf2;
10812159047fSniklas 	      while (p[0] == '0' && p[1] != 0)
10822159047fSniklas 		p++;
10832159047fSniklas 	      sprintf (buffer, "  %s $%s\r\n", s->name, p);
10842159047fSniklas 	      l = strlen (buffer);
10852159047fSniklas 	      if (bfd_write (buffer, l, 1, abfd) != l)
10862159047fSniklas 		return false;
10872159047fSniklas 	    }
10882159047fSniklas 	}
10892159047fSniklas       sprintf (buffer, "$$ \r\n");
10902159047fSniklas       len = strlen (buffer);
10912159047fSniklas       if (bfd_write (buffer, len, 1, abfd) != len)
10922159047fSniklas 	return false;
10932159047fSniklas     }
10942159047fSniklas 
10952159047fSniklas   return true;
10962159047fSniklas }
10972159047fSniklas 
10982159047fSniklas static boolean
10992159047fSniklas internal_srec_write_object_contents (abfd, symbols)
11002159047fSniklas      bfd *abfd;
11012159047fSniklas      int symbols;
11022159047fSniklas {
11032159047fSniklas   tdata_type *tdata = abfd->tdata.srec_data;
11042159047fSniklas   srec_data_list_type *list;
11052159047fSniklas 
11062159047fSniklas   if (symbols)
11072159047fSniklas     {
11082159047fSniklas       if (! srec_write_symbols (abfd))
11092159047fSniklas 	return false;
11102159047fSniklas     }
11112159047fSniklas 
11122159047fSniklas   if (! srec_write_header (abfd))
11132159047fSniklas     return false;
11142159047fSniklas 
1115*b55d4692Sfgsch   /* Now wander though all the sections provided and output them.  */
11162159047fSniklas   list = tdata->head;
11172159047fSniklas 
11182159047fSniklas   while (list != (srec_data_list_type *) NULL)
11192159047fSniklas     {
11202159047fSniklas       if (! srec_write_section (abfd, tdata, list))
11212159047fSniklas 	return false;
11222159047fSniklas       list = list->next;
11232159047fSniklas     }
11242159047fSniklas   return srec_write_terminator (abfd, tdata);
11252159047fSniklas }
11262159047fSniklas 
11272159047fSniklas static boolean
11282159047fSniklas srec_write_object_contents (abfd)
11292159047fSniklas      bfd *abfd;
11302159047fSniklas {
11312159047fSniklas   return internal_srec_write_object_contents (abfd, 0);
11322159047fSniklas }
11332159047fSniklas 
11342159047fSniklas static boolean
11352159047fSniklas symbolsrec_write_object_contents (abfd)
11362159047fSniklas      bfd *abfd;
11372159047fSniklas {
11382159047fSniklas   return internal_srec_write_object_contents (abfd, 1);
11392159047fSniklas }
11402159047fSniklas 
11412159047fSniklas static int
11422159047fSniklas srec_sizeof_headers (abfd, exec)
1143b305b0f1Sespie      bfd *abfd ATTRIBUTE_UNUSED;
1144b305b0f1Sespie      boolean exec ATTRIBUTE_UNUSED;
11452159047fSniklas {
11462159047fSniklas   return 0;
11472159047fSniklas }
11482159047fSniklas 
11492159047fSniklas static asymbol *
11502159047fSniklas srec_make_empty_symbol (abfd)
11512159047fSniklas      bfd *abfd;
11522159047fSniklas {
11532159047fSniklas   asymbol *new = (asymbol *) bfd_zalloc (abfd, sizeof (asymbol));
11542159047fSniklas   if (new)
11552159047fSniklas     new->the_bfd = abfd;
11562159047fSniklas   return new;
11572159047fSniklas }
11582159047fSniklas 
11592159047fSniklas /* Return the amount of memory needed to read the symbol table.  */
11602159047fSniklas 
11612159047fSniklas static long
11622159047fSniklas srec_get_symtab_upper_bound (abfd)
11632159047fSniklas      bfd *abfd;
11642159047fSniklas {
11652159047fSniklas   return (bfd_get_symcount (abfd) + 1) * sizeof (asymbol *);
11662159047fSniklas }
11672159047fSniklas 
11682159047fSniklas /* Return the symbol table.  */
11692159047fSniklas 
11702159047fSniklas static long
11712159047fSniklas srec_get_symtab (abfd, alocation)
11722159047fSniklas      bfd *abfd;
11732159047fSniklas      asymbol **alocation;
11742159047fSniklas {
11752159047fSniklas   unsigned int symcount = bfd_get_symcount (abfd);
11762159047fSniklas   asymbol *csymbols;
11772159047fSniklas   unsigned int i;
11782159047fSniklas 
11792159047fSniklas   csymbols = abfd->tdata.srec_data->csymbols;
11802159047fSniklas   if (csymbols == NULL)
11812159047fSniklas     {
11822159047fSniklas       asymbol *c;
11832159047fSniklas       struct srec_symbol *s;
11842159047fSniklas 
11852159047fSniklas       csymbols = (asymbol *) bfd_alloc (abfd, symcount * sizeof (asymbol));
11862159047fSniklas       if (csymbols == NULL && symcount != 0)
11872159047fSniklas 	return false;
11882159047fSniklas       abfd->tdata.srec_data->csymbols = csymbols;
11892159047fSniklas 
11902159047fSniklas       for (s = abfd->tdata.srec_data->symbols, c = csymbols;
11912159047fSniklas 	   s != NULL;
11922159047fSniklas 	   s = s->next, ++c)
11932159047fSniklas 	{
11942159047fSniklas 	  c->the_bfd = abfd;
11952159047fSniklas 	  c->name = s->name;
11962159047fSniklas 	  c->value = s->val;
11972159047fSniklas 	  c->flags = BSF_GLOBAL;
11982159047fSniklas 	  c->section = bfd_abs_section_ptr;
11992159047fSniklas 	  c->udata.p = NULL;
12002159047fSniklas 	}
12012159047fSniklas     }
12022159047fSniklas 
12032159047fSniklas   for (i = 0; i < symcount; i++)
12042159047fSniklas     *alocation++ = csymbols++;
12052159047fSniklas   *alocation = NULL;
12062159047fSniklas 
12072159047fSniklas   return symcount;
12082159047fSniklas }
12092159047fSniklas 
1210b305b0f1Sespie static void
12112159047fSniklas srec_get_symbol_info (ignore_abfd, symbol, ret)
1212b305b0f1Sespie      bfd *ignore_abfd ATTRIBUTE_UNUSED;
12132159047fSniklas      asymbol *symbol;
12142159047fSniklas      symbol_info *ret;
12152159047fSniklas {
12162159047fSniklas   bfd_symbol_info (symbol, ret);
12172159047fSniklas }
12182159047fSniklas 
1219e93f7393Sniklas static void
12202159047fSniklas srec_print_symbol (ignore_abfd, afile, symbol, how)
1221b305b0f1Sespie      bfd *ignore_abfd ATTRIBUTE_UNUSED;
12222159047fSniklas      PTR afile;
12232159047fSniklas      asymbol *symbol;
12242159047fSniklas      bfd_print_symbol_type how;
12252159047fSniklas {
12262159047fSniklas   FILE *file = (FILE *) afile;
12272159047fSniklas   switch (how)
12282159047fSniklas     {
12292159047fSniklas     case bfd_print_symbol_name:
12302159047fSniklas       fprintf (file, "%s", symbol->name);
12312159047fSniklas       break;
12322159047fSniklas     default:
12332159047fSniklas       bfd_print_symbol_vandf ((PTR) file, symbol);
12342159047fSniklas       fprintf (file, " %-5s %s",
12352159047fSniklas 	       symbol->section->name,
12362159047fSniklas 	       symbol->name);
12372159047fSniklas 
12382159047fSniklas     }
12392159047fSniklas }
12402159047fSniklas 
12412159047fSniklas #define	srec_close_and_cleanup _bfd_generic_close_and_cleanup
12422159047fSniklas #define srec_bfd_free_cached_info _bfd_generic_bfd_free_cached_info
12432159047fSniklas #define srec_new_section_hook _bfd_generic_new_section_hook
12442159047fSniklas 
1245b305b0f1Sespie #define srec_bfd_is_local_label_name bfd_generic_is_local_label_name
12462159047fSniklas #define srec_get_lineno _bfd_nosymbols_get_lineno
12472159047fSniklas #define srec_find_nearest_line _bfd_nosymbols_find_nearest_line
12482159047fSniklas #define srec_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol
12492159047fSniklas #define srec_read_minisymbols _bfd_generic_read_minisymbols
12502159047fSniklas #define srec_minisymbol_to_symbol _bfd_generic_minisymbol_to_symbol
12512159047fSniklas 
12522159047fSniklas #define srec_get_reloc_upper_bound \
12532159047fSniklas   ((long (*) PARAMS ((bfd *, asection *))) bfd_0l)
12542159047fSniklas #define srec_canonicalize_reloc \
12552159047fSniklas   ((long (*) PARAMS ((bfd *, asection *, arelent **, asymbol **))) bfd_0l)
12562159047fSniklas #define srec_bfd_reloc_type_lookup _bfd_norelocs_bfd_reloc_type_lookup
12572159047fSniklas 
12582159047fSniklas #define srec_get_section_contents_in_window \
12592159047fSniklas   _bfd_generic_get_section_contents_in_window
12602159047fSniklas 
12612159047fSniklas #define srec_bfd_get_relocated_section_contents \
12622159047fSniklas   bfd_generic_get_relocated_section_contents
12632159047fSniklas #define srec_bfd_relax_section bfd_generic_relax_section
1264b305b0f1Sespie #define srec_bfd_gc_sections bfd_generic_gc_sections
12652159047fSniklas #define srec_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
12662159047fSniklas #define srec_bfd_link_add_symbols _bfd_generic_link_add_symbols
12672159047fSniklas #define srec_bfd_final_link _bfd_generic_final_link
12682159047fSniklas #define srec_bfd_link_split_section _bfd_generic_link_split_section
12692159047fSniklas 
12702159047fSniklas const bfd_target srec_vec =
12712159047fSniklas {
12722159047fSniklas   "srec",			/* name */
12732159047fSniklas   bfd_target_srec_flavour,
1274c88b1d6cSniklas   BFD_ENDIAN_UNKNOWN,		/* target byte order */
1275c88b1d6cSniklas   BFD_ENDIAN_UNKNOWN,		/* target headers byte order */
12762159047fSniklas   (HAS_RELOC | EXEC_P |		/* object flags */
12772159047fSniklas    HAS_LINENO | HAS_DEBUG |
12782159047fSniklas    HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
12792159047fSniklas   (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS
12802159047fSniklas    | SEC_ALLOC | SEC_LOAD | SEC_RELOC),	/* section flags */
12812159047fSniklas   0,				/* leading underscore */
12822159047fSniklas   ' ',				/* ar_pad_char */
12832159047fSniklas   16,				/* ar_max_namelen */
12842159047fSniklas   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
12852159047fSniklas   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
12862159047fSniklas   bfd_getb16, bfd_getb_signed_16, bfd_putb16,	/* data */
12872159047fSniklas   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
12882159047fSniklas   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
12892159047fSniklas   bfd_getb16, bfd_getb_signed_16, bfd_putb16,	/* hdrs */
12902159047fSniklas 
12912159047fSniklas   {
12922159047fSniklas     _bfd_dummy_target,
12932159047fSniklas     srec_object_p,		/* bfd_check_format */
12942159047fSniklas     _bfd_dummy_target,
12952159047fSniklas     _bfd_dummy_target,
12962159047fSniklas   },
12972159047fSniklas   {
12982159047fSniklas     bfd_false,
12992159047fSniklas     srec_mkobject,
13002159047fSniklas     _bfd_generic_mkarchive,
13012159047fSniklas     bfd_false,
13022159047fSniklas   },
13032159047fSniklas   {				/* bfd_write_contents */
13042159047fSniklas     bfd_false,
13052159047fSniklas     srec_write_object_contents,
13062159047fSniklas     _bfd_write_archive_contents,
13072159047fSniklas     bfd_false,
13082159047fSniklas   },
13092159047fSniklas 
13102159047fSniklas   BFD_JUMP_TABLE_GENERIC (srec),
13112159047fSniklas   BFD_JUMP_TABLE_COPY (_bfd_generic),
13122159047fSniklas   BFD_JUMP_TABLE_CORE (_bfd_nocore),
13132159047fSniklas   BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
13142159047fSniklas   BFD_JUMP_TABLE_SYMBOLS (srec),
13152159047fSniklas   BFD_JUMP_TABLE_RELOCS (srec),
13162159047fSniklas   BFD_JUMP_TABLE_WRITE (srec),
13172159047fSniklas   BFD_JUMP_TABLE_LINK (srec),
13182159047fSniklas   BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
13192159047fSniklas 
1320b305b0f1Sespie   NULL,
1321b305b0f1Sespie 
13222159047fSniklas   (PTR) 0
13232159047fSniklas };
13242159047fSniklas 
13252159047fSniklas const bfd_target symbolsrec_vec =
13262159047fSniklas {
13272159047fSniklas   "symbolsrec",			/* name */
13282159047fSniklas   bfd_target_srec_flavour,
1329c88b1d6cSniklas   BFD_ENDIAN_UNKNOWN,		/* target byte order */
1330c88b1d6cSniklas   BFD_ENDIAN_UNKNOWN,		/* target headers byte order */
13312159047fSniklas   (HAS_RELOC | EXEC_P |		/* object flags */
13322159047fSniklas    HAS_LINENO | HAS_DEBUG |
13332159047fSniklas    HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
13342159047fSniklas   (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS
13352159047fSniklas    | SEC_ALLOC | SEC_LOAD | SEC_RELOC),	/* section flags */
13362159047fSniklas   0,				/* leading underscore */
13372159047fSniklas   ' ',				/* ar_pad_char */
13382159047fSniklas   16,				/* ar_max_namelen */
13392159047fSniklas   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
13402159047fSniklas   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
13412159047fSniklas   bfd_getb16, bfd_getb_signed_16, bfd_putb16,	/* data */
13422159047fSniklas   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
13432159047fSniklas   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
13442159047fSniklas   bfd_getb16, bfd_getb_signed_16, bfd_putb16,	/* hdrs */
13452159047fSniklas 
13462159047fSniklas   {
13472159047fSniklas     _bfd_dummy_target,
13482159047fSniklas     symbolsrec_object_p,	/* bfd_check_format */
13492159047fSniklas     _bfd_dummy_target,
13502159047fSniklas     _bfd_dummy_target,
13512159047fSniklas   },
13522159047fSniklas   {
13532159047fSniklas     bfd_false,
13542159047fSniklas     srec_mkobject,
13552159047fSniklas     _bfd_generic_mkarchive,
13562159047fSniklas     bfd_false,
13572159047fSniklas   },
13582159047fSniklas   {				/* bfd_write_contents */
13592159047fSniklas     bfd_false,
13602159047fSniklas     symbolsrec_write_object_contents,
13612159047fSniklas     _bfd_write_archive_contents,
13622159047fSniklas     bfd_false,
13632159047fSniklas   },
13642159047fSniklas 
13652159047fSniklas   BFD_JUMP_TABLE_GENERIC (srec),
13662159047fSniklas   BFD_JUMP_TABLE_COPY (_bfd_generic),
13672159047fSniklas   BFD_JUMP_TABLE_CORE (_bfd_nocore),
13682159047fSniklas   BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
13692159047fSniklas   BFD_JUMP_TABLE_SYMBOLS (srec),
13702159047fSniklas   BFD_JUMP_TABLE_RELOCS (srec),
13712159047fSniklas   BFD_JUMP_TABLE_WRITE (srec),
13722159047fSniklas   BFD_JUMP_TABLE_LINK (srec),
13732159047fSniklas   BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
13742159047fSniklas 
1375b305b0f1Sespie   NULL,
1376b305b0f1Sespie 
13772159047fSniklas   (PTR) 0
13782159047fSniklas };
1379