xref: /openbsd/gnu/usr.bin/binutils/bfd/srec.c (revision 007c2a45)
12159047fSniklas /* BFD back-end for s-record objects.
2b55d4692Sfgsch    Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
3*007c2a45Smiod    2000, 2001, 2002, 2003
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"
111c074d1c9Sdrahn #include "safe-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));
117c074d1c9Sdrahn static bfd_boolean srec_mkobject PARAMS ((bfd *));
118c074d1c9Sdrahn static int srec_get_byte PARAMS ((bfd *, bfd_boolean *));
119c074d1c9Sdrahn static void srec_bad_byte PARAMS ((bfd *, unsigned int, int, bfd_boolean));
120c074d1c9Sdrahn static bfd_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 *));
123c074d1c9Sdrahn static bfd_boolean srec_read_section PARAMS ((bfd *, asection *, bfd_byte *));
1242159047fSniklas 
125c074d1c9Sdrahn static bfd_boolean srec_write_record
126c074d1c9Sdrahn   PARAMS ((bfd *, unsigned int, bfd_vma, const bfd_byte *, const bfd_byte *));
127c074d1c9Sdrahn static bfd_boolean srec_write_header PARAMS ((bfd *));
128c074d1c9Sdrahn static bfd_boolean srec_write_symbols PARAMS ((bfd *));
129c074d1c9Sdrahn static bfd_boolean srec_new_symbol PARAMS ((bfd *, const char *, bfd_vma));
130c074d1c9Sdrahn static bfd_boolean srec_get_section_contents
131e93f7393Sniklas   PARAMS ((bfd *, asection *, PTR, file_ptr, bfd_size_type));
132c074d1c9Sdrahn static bfd_boolean srec_set_arch_mach
133e93f7393Sniklas   PARAMS ((bfd *, enum bfd_architecture, unsigned long));
134c074d1c9Sdrahn static bfd_boolean srec_set_section_contents
135*007c2a45Smiod   PARAMS ((bfd *, sec_ptr, const PTR, file_ptr, bfd_size_type));
136c074d1c9Sdrahn static bfd_boolean internal_srec_write_object_contents PARAMS ((bfd *, int));
137c074d1c9Sdrahn static bfd_boolean srec_write_object_contents PARAMS ((bfd *));
138c074d1c9Sdrahn static bfd_boolean symbolsrec_write_object_contents PARAMS ((bfd *));
139c074d1c9Sdrahn static int srec_sizeof_headers PARAMS ((bfd *, bfd_boolean));
140e93f7393Sniklas static long srec_get_symtab_upper_bound PARAMS ((bfd *));
141*007c2a45Smiod static long srec_canonicalize_symtab PARAMS ((bfd *, asymbol **));
1422159047fSniklas 
1432159047fSniklas /* Macros for converting between hex and binary.  */
1442159047fSniklas 
145c074d1c9Sdrahn static const char digs[] = "0123456789ABCDEF";
1462159047fSniklas 
1472159047fSniklas #define NIBBLE(x) hex_value(x)
1482159047fSniklas #define HEX(buffer) ((NIBBLE((buffer)[0])<<4) + NIBBLE((buffer)[1]))
1492159047fSniklas #define TOHEX(d, x, ch) \
1502159047fSniklas 	d[1] = digs[(x) & 0xf]; \
1512159047fSniklas 	d[0] = digs[((x)>>4)&0xf]; \
1522159047fSniklas 	ch += ((x) & 0xff);
1532159047fSniklas #define	ISHEX(x)  hex_p(x)
1542159047fSniklas 
1552159047fSniklas /* Initialize by filling in the hex conversion array.  */
1562159047fSniklas 
1572159047fSniklas static void
srec_init()1582159047fSniklas srec_init ()
1592159047fSniklas {
160c074d1c9Sdrahn   static bfd_boolean inited = FALSE;
1612159047fSniklas 
162c074d1c9Sdrahn   if (! inited)
1632159047fSniklas     {
164c074d1c9Sdrahn       inited = TRUE;
1652159047fSniklas       hex_init ();
1662159047fSniklas     }
1672159047fSniklas }
1682159047fSniklas 
169c074d1c9Sdrahn /* The maximum number of address+data+crc bytes on a line is FF.  */
1702159047fSniklas #define MAXCHUNK 0xff
171b55d4692Sfgsch 
172b55d4692Sfgsch /* Default size for a CHUNK.  */
173b55d4692Sfgsch #define DEFAULT_CHUNK 16
174b55d4692Sfgsch 
175c074d1c9Sdrahn /* The number of data bytes we actually fit onto a line on output.
176b55d4692Sfgsch    This variable can be modified by objcopy's --srec-len parameter.
177b55d4692Sfgsch    For a 0x75 byte record you should set --srec-len=0x70.  */
178b55d4692Sfgsch unsigned int Chunk = DEFAULT_CHUNK;
179b55d4692Sfgsch 
180b55d4692Sfgsch /* The type of srec output (free or forced to S3).
181b55d4692Sfgsch    This variable can be modified by objcopy's --srec-forceS3
182b55d4692Sfgsch    parameter.  */
183c074d1c9Sdrahn bfd_boolean S3Forced = FALSE;
1842159047fSniklas 
1852159047fSniklas /* When writing an S-record file, the S-records can not be output as
1862159047fSniklas    they are seen.  This structure is used to hold them in memory.  */
1872159047fSniklas 
1882159047fSniklas struct srec_data_list_struct
1892159047fSniklas {
1902159047fSniklas   struct srec_data_list_struct *next;
1912159047fSniklas   bfd_byte *data;
1922159047fSniklas   bfd_vma where;
1932159047fSniklas   bfd_size_type size;
1942159047fSniklas };
1952159047fSniklas 
1962159047fSniklas typedef struct srec_data_list_struct srec_data_list_type;
1972159047fSniklas 
1982159047fSniklas /* When scanning the S-record file, a linked list of srec_symbol
1992159047fSniklas    structures is built to represent the symbol table (if there is
2002159047fSniklas    one).  */
2012159047fSniklas 
2022159047fSniklas struct srec_symbol
2032159047fSniklas {
2042159047fSniklas   struct srec_symbol *next;
2052159047fSniklas   const char *name;
2062159047fSniklas   bfd_vma val;
2072159047fSniklas };
2082159047fSniklas 
2092159047fSniklas /* The S-record tdata information.  */
2102159047fSniklas 
2112159047fSniklas typedef struct srec_data_struct
2122159047fSniklas   {
2132159047fSniklas     srec_data_list_type *head;
2142159047fSniklas     srec_data_list_type *tail;
2152159047fSniklas     unsigned int type;
2162159047fSniklas     struct srec_symbol *symbols;
2172159047fSniklas     struct srec_symbol *symtail;
2182159047fSniklas     asymbol *csymbols;
2192159047fSniklas   }
2202159047fSniklas tdata_type;
2212159047fSniklas 
222c074d1c9Sdrahn static bfd_boolean srec_write_section
223c074d1c9Sdrahn   PARAMS ((bfd *, tdata_type *, srec_data_list_type *));
224c074d1c9Sdrahn static bfd_boolean srec_write_terminator
225c074d1c9Sdrahn   PARAMS ((bfd *, tdata_type *));
2262159047fSniklas 
2272159047fSniklas /* Set up the S-record tdata information.  */
2282159047fSniklas 
229c074d1c9Sdrahn static bfd_boolean
srec_mkobject(abfd)2302159047fSniklas srec_mkobject (abfd)
2312159047fSniklas      bfd *abfd;
2322159047fSniklas {
233c074d1c9Sdrahn   bfd_size_type amt;
234c074d1c9Sdrahn   tdata_type *tdata;
235c074d1c9Sdrahn 
2362159047fSniklas   srec_init ();
2372159047fSniklas 
238c074d1c9Sdrahn   amt = sizeof (tdata_type);
239c074d1c9Sdrahn   tdata = (tdata_type *) bfd_alloc (abfd, amt);
2402159047fSniklas   if (tdata == NULL)
241c074d1c9Sdrahn     return FALSE;
242c074d1c9Sdrahn 
2432159047fSniklas   abfd->tdata.srec_data = tdata;
2442159047fSniklas   tdata->type = 1;
2452159047fSniklas   tdata->head = NULL;
2462159047fSniklas   tdata->tail = NULL;
2472159047fSniklas   tdata->symbols = NULL;
2482159047fSniklas   tdata->symtail = NULL;
2492159047fSniklas   tdata->csymbols = NULL;
2502159047fSniklas 
251c074d1c9Sdrahn   return TRUE;
2522159047fSniklas }
2532159047fSniklas 
2542159047fSniklas /* Read a byte from an S record file.  Set *ERRORPTR if an error
2552159047fSniklas    occurred.  Return EOF on error or end of file.  */
2562159047fSniklas 
2572159047fSniklas static int
srec_get_byte(abfd,errorptr)2582159047fSniklas srec_get_byte (abfd, errorptr)
2592159047fSniklas      bfd *abfd;
260c074d1c9Sdrahn      bfd_boolean *errorptr;
2612159047fSniklas {
2622159047fSniklas   bfd_byte c;
2632159047fSniklas 
264c074d1c9Sdrahn   if (bfd_bread (&c, (bfd_size_type) 1, abfd) != 1)
2652159047fSniklas     {
2662159047fSniklas       if (bfd_get_error () != bfd_error_file_truncated)
267c074d1c9Sdrahn 	*errorptr = TRUE;
2682159047fSniklas       return EOF;
2692159047fSniklas     }
2702159047fSniklas 
2712159047fSniklas   return (int) (c & 0xff);
2722159047fSniklas }
2732159047fSniklas 
2742159047fSniklas /* Report a problem in an S record file.  FIXME: This probably should
2752159047fSniklas    not call fprintf, but we really do need some mechanism for printing
2762159047fSniklas    error messages.  */
2772159047fSniklas 
2782159047fSniklas static void
srec_bad_byte(abfd,lineno,c,error)2792159047fSniklas srec_bad_byte (abfd, lineno, c, error)
2802159047fSniklas      bfd *abfd;
2812159047fSniklas      unsigned int lineno;
2822159047fSniklas      int c;
283c074d1c9Sdrahn      bfd_boolean error;
2842159047fSniklas {
2852159047fSniklas   if (c == EOF)
2862159047fSniklas     {
2872159047fSniklas       if (! error)
2882159047fSniklas 	bfd_set_error (bfd_error_file_truncated);
2892159047fSniklas     }
2902159047fSniklas   else
2912159047fSniklas     {
2922159047fSniklas       char buf[10];
2932159047fSniklas 
294c074d1c9Sdrahn       if (! ISPRINT (c))
2952159047fSniklas 	sprintf (buf, "\\%03o", (unsigned int) c);
2962159047fSniklas       else
2972159047fSniklas 	{
2982159047fSniklas 	  buf[0] = c;
2992159047fSniklas 	  buf[1] = '\0';
3002159047fSniklas 	}
3012159047fSniklas       (*_bfd_error_handler)
302b305b0f1Sespie 	(_("%s:%d: Unexpected character `%s' in S-record file\n"),
303c074d1c9Sdrahn 	 bfd_archive_filename (abfd), lineno, buf);
3042159047fSniklas       bfd_set_error (bfd_error_bad_value);
3052159047fSniklas     }
3062159047fSniklas }
3072159047fSniklas 
3082159047fSniklas /* Add a new symbol found in an S-record file.  */
3092159047fSniklas 
310c074d1c9Sdrahn static bfd_boolean
srec_new_symbol(abfd,name,val)3112159047fSniklas srec_new_symbol (abfd, name, val)
3122159047fSniklas      bfd *abfd;
3132159047fSniklas      const char *name;
3142159047fSniklas      bfd_vma val;
3152159047fSniklas {
3162159047fSniklas   struct srec_symbol *n;
317c074d1c9Sdrahn   bfd_size_type amt = sizeof (struct srec_symbol);
3182159047fSniklas 
319c074d1c9Sdrahn   n = (struct srec_symbol *) bfd_alloc (abfd, amt);
3202159047fSniklas   if (n == NULL)
321c074d1c9Sdrahn     return FALSE;
3222159047fSniklas 
3232159047fSniklas   n->name = name;
3242159047fSniklas   n->val = val;
3252159047fSniklas 
3262159047fSniklas   if (abfd->tdata.srec_data->symbols == NULL)
3272159047fSniklas     abfd->tdata.srec_data->symbols = n;
3282159047fSniklas   else
3292159047fSniklas     abfd->tdata.srec_data->symtail->next = n;
3302159047fSniklas   abfd->tdata.srec_data->symtail = n;
3312159047fSniklas   n->next = NULL;
3322159047fSniklas 
3332159047fSniklas   ++abfd->symcount;
3342159047fSniklas 
335c074d1c9Sdrahn   return TRUE;
3362159047fSniklas }
3372159047fSniklas 
3382159047fSniklas /* Read the S record file and turn it into sections.  We create a new
3392159047fSniklas    section for each contiguous set of bytes.  */
3402159047fSniklas 
341c074d1c9Sdrahn static bfd_boolean
srec_scan(abfd)3422159047fSniklas srec_scan (abfd)
3432159047fSniklas      bfd *abfd;
3442159047fSniklas {
3452159047fSniklas   int c;
3462159047fSniklas   unsigned int lineno = 1;
347c074d1c9Sdrahn   bfd_boolean error = FALSE;
3482159047fSniklas   bfd_byte *buf = NULL;
3492159047fSniklas   size_t bufsize = 0;
3502159047fSniklas   asection *sec = NULL;
351b305b0f1Sespie   char *symbuf = NULL;
3522159047fSniklas 
3532159047fSniklas   if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
3542159047fSniklas     goto error_return;
3552159047fSniklas 
3562159047fSniklas   while ((c = srec_get_byte (abfd, &error)) != EOF)
3572159047fSniklas     {
3582159047fSniklas       /* We only build sections from contiguous S-records, so if this
3592159047fSniklas 	 is not an S-record, then stop building a section.  */
3602159047fSniklas       if (c != 'S' && c != '\r' && c != '\n')
3612159047fSniklas 	sec = NULL;
3622159047fSniklas 
3632159047fSniklas       switch (c)
3642159047fSniklas 	{
3652159047fSniklas 	default:
3662159047fSniklas 	  srec_bad_byte (abfd, lineno, c, error);
3672159047fSniklas 	  goto error_return;
3682159047fSniklas 
3692159047fSniklas 	case '\n':
3702159047fSniklas 	  ++lineno;
3712159047fSniklas 	  break;
3722159047fSniklas 
3732159047fSniklas 	case '\r':
3742159047fSniklas 	  break;
3752159047fSniklas 
3762159047fSniklas 	case '$':
3772159047fSniklas 	  /* Starting a module name, which we ignore.  */
3782159047fSniklas 	  while ((c = srec_get_byte (abfd, &error)) != '\n'
3792159047fSniklas 		 && c != EOF)
3802159047fSniklas 	    ;
3812159047fSniklas 	  if (c == EOF)
3822159047fSniklas 	    {
3832159047fSniklas 	      srec_bad_byte (abfd, lineno, c, error);
3842159047fSniklas 	      goto error_return;
3852159047fSniklas 	    }
3862159047fSniklas 
3872159047fSniklas 	  ++lineno;
3882159047fSniklas 
3892159047fSniklas 	  break;
3902159047fSniklas 
3912159047fSniklas 	case ' ':
392e93f7393Sniklas 	  do
3932159047fSniklas 	    {
394c074d1c9Sdrahn 	      bfd_size_type alc;
395b305b0f1Sespie 	      char *p, *symname;
3962159047fSniklas 	      bfd_vma symval;
3972159047fSniklas 
3982159047fSniklas 	      /* Starting a symbol definition.  */
3992159047fSniklas 	      while ((c = srec_get_byte (abfd, &error)) != EOF
4002159047fSniklas 		     && (c == ' ' || c == '\t'))
4012159047fSniklas 		;
402e93f7393Sniklas 
403b305b0f1Sespie 	      if (c == '\n' || c == '\r')
404e93f7393Sniklas 		break;
405e93f7393Sniklas 
4062159047fSniklas 	      if (c == EOF)
4072159047fSniklas 		{
4082159047fSniklas 		  srec_bad_byte (abfd, lineno, c, error);
4092159047fSniklas 		  goto error_return;
4102159047fSniklas 		}
4112159047fSniklas 
412b305b0f1Sespie 	      alc = 10;
413b305b0f1Sespie 	      symbuf = (char *) bfd_malloc (alc + 1);
414b305b0f1Sespie 	      if (symbuf == NULL)
415b305b0f1Sespie 		goto error_return;
416b305b0f1Sespie 
417b305b0f1Sespie 	      p = symbuf;
418b305b0f1Sespie 
419b305b0f1Sespie 	      *p++ = c;
4202159047fSniklas 	      while ((c = srec_get_byte (abfd, &error)) != EOF
421c074d1c9Sdrahn 		     && ! ISSPACE (c))
422b305b0f1Sespie 		{
423c074d1c9Sdrahn 		  if ((bfd_size_type) (p - symbuf) >= alc)
424b305b0f1Sespie 		    {
425b305b0f1Sespie 		      char *n;
426b305b0f1Sespie 
427b305b0f1Sespie 		      alc *= 2;
428b305b0f1Sespie 		      n = (char *) bfd_realloc (symbuf, alc + 1);
429b305b0f1Sespie 		      if (n == NULL)
430b305b0f1Sespie 			goto error_return;
431b305b0f1Sespie 		      p = n + (p - symbuf);
432b305b0f1Sespie 		      symbuf = n;
433b305b0f1Sespie 		    }
434b305b0f1Sespie 
435b305b0f1Sespie 		  *p++ = c;
436b305b0f1Sespie 		}
437b305b0f1Sespie 
4382159047fSniklas 	      if (c == EOF)
4392159047fSniklas 		{
4402159047fSniklas 		  srec_bad_byte (abfd, lineno, c, error);
4412159047fSniklas 		  goto error_return;
4422159047fSniklas 		}
4432159047fSniklas 
444b305b0f1Sespie 	      *p++ = '\0';
445c074d1c9Sdrahn 	      symname = bfd_alloc (abfd, (bfd_size_type) (p - symbuf));
4462159047fSniklas 	      if (symname == NULL)
4472159047fSniklas 		goto error_return;
448b305b0f1Sespie 	      strcpy (symname, symbuf);
449b305b0f1Sespie 	      free (symbuf);
450b305b0f1Sespie 	      symbuf = NULL;
4512159047fSniklas 
4522159047fSniklas 	      while ((c = srec_get_byte (abfd, &error)) != EOF
4532159047fSniklas 		     && (c == ' ' || c == '\t'))
4542159047fSniklas 		;
4552159047fSniklas 	      if (c == EOF)
4562159047fSniklas 		{
4572159047fSniklas 		  srec_bad_byte (abfd, lineno, c, error);
4582159047fSniklas 		  goto error_return;
4592159047fSniklas 		}
4602159047fSniklas 
4612159047fSniklas 	      /* Skip a dollar sign before the hex value.  */
4622159047fSniklas 	      if (c == '$')
4632159047fSniklas 		{
4642159047fSniklas 		  c = srec_get_byte (abfd, &error);
4652159047fSniklas 		  if (c == EOF)
4662159047fSniklas 		    {
4672159047fSniklas 		      srec_bad_byte (abfd, lineno, c, error);
4682159047fSniklas 		      goto error_return;
4692159047fSniklas 		    }
4702159047fSniklas 		}
4712159047fSniklas 
4722159047fSniklas 	      symval = 0;
4732159047fSniklas 	      while (ISHEX (c))
4742159047fSniklas 		{
4752159047fSniklas 		  symval <<= 4;
4762159047fSniklas 		  symval += NIBBLE (c);
4772159047fSniklas 		  c = srec_get_byte (abfd, &error);
4782159047fSniklas 		}
4792159047fSniklas 
480e93f7393Sniklas 	      if (! srec_new_symbol (abfd, symname, symval))
481e93f7393Sniklas 		goto error_return;
482e93f7393Sniklas 	    }
483b55d4692Sfgsch 	  while (c == ' ' || c == '\t')
484b55d4692Sfgsch 	    ;
485e93f7393Sniklas 
486b305b0f1Sespie 	  if (c == '\n')
487b305b0f1Sespie 	    ++lineno;
488b305b0f1Sespie 	  else if (c != '\r')
4892159047fSniklas 	    {
4902159047fSniklas 	      srec_bad_byte (abfd, lineno, c, error);
4912159047fSniklas 	      goto error_return;
4922159047fSniklas 	    }
4932159047fSniklas 
4942159047fSniklas 	  break;
4952159047fSniklas 
4962159047fSniklas 	case 'S':
4972159047fSniklas 	  {
4982159047fSniklas 	    file_ptr pos;
4992159047fSniklas 	    char hdr[3];
5002159047fSniklas 	    unsigned int bytes;
5012159047fSniklas 	    bfd_vma address;
5022159047fSniklas 	    bfd_byte *data;
5032159047fSniklas 
5042159047fSniklas 	    /* Starting an S-record.  */
5052159047fSniklas 
5062159047fSniklas 	    pos = bfd_tell (abfd) - 1;
5072159047fSniklas 
508c074d1c9Sdrahn 	    if (bfd_bread (hdr, (bfd_size_type) 3, abfd) != 3)
5092159047fSniklas 	      goto error_return;
5102159047fSniklas 
5112159047fSniklas 	    if (! ISHEX (hdr[1]) || ! ISHEX (hdr[2]))
5122159047fSniklas 	      {
5132159047fSniklas 		if (! ISHEX (hdr[1]))
5142159047fSniklas 		  c = hdr[1];
5152159047fSniklas 		else
5162159047fSniklas 		  c = hdr[2];
5172159047fSniklas 		srec_bad_byte (abfd, lineno, c, error);
5182159047fSniklas 		goto error_return;
5192159047fSniklas 	      }
5202159047fSniklas 
5212159047fSniklas 	    bytes = HEX (hdr + 1);
5222159047fSniklas 	    if (bytes * 2 > bufsize)
5232159047fSniklas 	      {
5242159047fSniklas 		if (buf != NULL)
5252159047fSniklas 		  free (buf);
526c074d1c9Sdrahn 		buf = (bfd_byte *) bfd_malloc ((bfd_size_type) bytes * 2);
5272159047fSniklas 		if (buf == NULL)
5282159047fSniklas 		  goto error_return;
5292159047fSniklas 		bufsize = bytes * 2;
5302159047fSniklas 	      }
5312159047fSniklas 
532c074d1c9Sdrahn 	    if (bfd_bread (buf, (bfd_size_type) bytes * 2, abfd) != bytes * 2)
5332159047fSniklas 	      goto error_return;
5342159047fSniklas 
5352159047fSniklas 	    /* Ignore the checksum byte.  */
5362159047fSniklas 	    --bytes;
5372159047fSniklas 
5382159047fSniklas 	    address = 0;
5392159047fSniklas 	    data = buf;
5402159047fSniklas 	    switch (hdr[0])
5412159047fSniklas 	      {
5422159047fSniklas 	      case '0':
5432159047fSniklas 	      case '5':
5442159047fSniklas 		/* Prologue--ignore the file name, but stop building a
5452159047fSniklas 		   section at this point.  */
5462159047fSniklas 		sec = NULL;
5472159047fSniklas 		break;
5482159047fSniklas 
5492159047fSniklas 	      case '3':
5502159047fSniklas 		address = HEX (data);
5512159047fSniklas 		data += 2;
5522159047fSniklas 		--bytes;
5532159047fSniklas 		/* Fall through.  */
5542159047fSniklas 	      case '2':
5552159047fSniklas 		address = (address << 8) | HEX (data);
5562159047fSniklas 		data += 2;
5572159047fSniklas 		--bytes;
5582159047fSniklas 		/* Fall through.  */
5592159047fSniklas 	      case '1':
5602159047fSniklas 		address = (address << 8) | HEX (data);
5612159047fSniklas 		data += 2;
5622159047fSniklas 		address = (address << 8) | HEX (data);
5632159047fSniklas 		data += 2;
5642159047fSniklas 		bytes -= 2;
5652159047fSniklas 
5662159047fSniklas 		if (sec != NULL
5672159047fSniklas 		    && sec->vma + sec->_raw_size == address)
5682159047fSniklas 		  {
5692159047fSniklas 		    /* This data goes at the end of the section we are
5702159047fSniklas 		       currently building.  */
5712159047fSniklas 		    sec->_raw_size += bytes;
5722159047fSniklas 		  }
5732159047fSniklas 		else
5742159047fSniklas 		  {
5752159047fSniklas 		    char secbuf[20];
5762159047fSniklas 		    char *secname;
577c074d1c9Sdrahn 		    bfd_size_type amt;
5782159047fSniklas 
5792159047fSniklas 		    sprintf (secbuf, ".sec%d", bfd_count_sections (abfd) + 1);
580c074d1c9Sdrahn 		    amt = strlen (secbuf) + 1;
581c074d1c9Sdrahn 		    secname = (char *) bfd_alloc (abfd, amt);
5822159047fSniklas 		    strcpy (secname, secbuf);
5832159047fSniklas 		    sec = bfd_make_section (abfd, secname);
5842159047fSniklas 		    if (sec == NULL)
5852159047fSniklas 		      goto error_return;
5862159047fSniklas 		    sec->flags = SEC_HAS_CONTENTS | SEC_LOAD | SEC_ALLOC;
5872159047fSniklas 		    sec->vma = address;
588c88b1d6cSniklas 		    sec->lma = address;
5892159047fSniklas 		    sec->_raw_size = bytes;
5902159047fSniklas 		    sec->filepos = pos;
5912159047fSniklas 		  }
5922159047fSniklas 
5932159047fSniklas 		break;
5942159047fSniklas 
5952159047fSniklas 	      case '7':
5962159047fSniklas 		address = HEX (data);
5972159047fSniklas 		data += 2;
5982159047fSniklas 		/* Fall through.  */
5992159047fSniklas 	      case '8':
6002159047fSniklas 		address = (address << 8) | HEX (data);
6012159047fSniklas 		data += 2;
6022159047fSniklas 		/* Fall through.  */
6032159047fSniklas 	      case '9':
6042159047fSniklas 		address = (address << 8) | HEX (data);
6052159047fSniklas 		data += 2;
6062159047fSniklas 		address = (address << 8) | HEX (data);
6072159047fSniklas 		data += 2;
6082159047fSniklas 
6092159047fSniklas 		/* This is a termination record.  */
6102159047fSniklas 		abfd->start_address = address;
6112159047fSniklas 
6122159047fSniklas 		if (buf != NULL)
6132159047fSniklas 		  free (buf);
6142159047fSniklas 
615c074d1c9Sdrahn 		return TRUE;
6162159047fSniklas 	      }
6172159047fSniklas 	  }
6182159047fSniklas 	  break;
6192159047fSniklas 	}
6202159047fSniklas     }
6212159047fSniklas 
6222159047fSniklas   if (error)
6232159047fSniklas     goto error_return;
6242159047fSniklas 
6252159047fSniklas   if (buf != NULL)
6262159047fSniklas     free (buf);
6272159047fSniklas 
628c074d1c9Sdrahn   return TRUE;
6292159047fSniklas 
6302159047fSniklas  error_return:
631b305b0f1Sespie   if (symbuf != NULL)
632b305b0f1Sespie     free (symbuf);
6332159047fSniklas   if (buf != NULL)
6342159047fSniklas     free (buf);
635c074d1c9Sdrahn   return FALSE;
6362159047fSniklas }
6372159047fSniklas 
6382159047fSniklas /* Check whether an existing file is an S-record file.  */
6392159047fSniklas 
6402159047fSniklas static const bfd_target *
srec_object_p(abfd)6412159047fSniklas srec_object_p (abfd)
6422159047fSniklas      bfd *abfd;
6432159047fSniklas {
644c074d1c9Sdrahn   PTR tdata_save;
6452159047fSniklas   bfd_byte b[4];
6462159047fSniklas 
6472159047fSniklas   srec_init ();
6482159047fSniklas 
6492159047fSniklas   if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0
650c074d1c9Sdrahn       || bfd_bread (b, (bfd_size_type) 4, abfd) != 4)
6512159047fSniklas     return NULL;
6522159047fSniklas 
6532159047fSniklas   if (b[0] != 'S' || !ISHEX (b[1]) || !ISHEX (b[2]) || !ISHEX (b[3]))
6542159047fSniklas     {
6552159047fSniklas       bfd_set_error (bfd_error_wrong_format);
6562159047fSniklas       return NULL;
6572159047fSniklas     }
6582159047fSniklas 
659c074d1c9Sdrahn   tdata_save = abfd->tdata.any;
660c074d1c9Sdrahn   if (! srec_mkobject (abfd) || ! srec_scan (abfd))
661c074d1c9Sdrahn     {
662c074d1c9Sdrahn       if (abfd->tdata.any != tdata_save && abfd->tdata.any != NULL)
663c074d1c9Sdrahn 	bfd_release (abfd, abfd->tdata.any);
664c074d1c9Sdrahn       abfd->tdata.any = tdata_save;
6652159047fSniklas       return NULL;
666c074d1c9Sdrahn     }
6672159047fSniklas 
668b305b0f1Sespie   if (abfd->symcount > 0)
669b305b0f1Sespie     abfd->flags |= HAS_SYMS;
670b305b0f1Sespie 
6712159047fSniklas   return abfd->xvec;
6722159047fSniklas }
6732159047fSniklas 
6742159047fSniklas /* Check whether an existing file is an S-record file with symbols.  */
6752159047fSniklas 
6762159047fSniklas static const bfd_target *
symbolsrec_object_p(abfd)6772159047fSniklas symbolsrec_object_p (abfd)
6782159047fSniklas      bfd *abfd;
6792159047fSniklas {
680c074d1c9Sdrahn   PTR tdata_save;
6812159047fSniklas   char b[2];
6822159047fSniklas 
6832159047fSniklas   srec_init ();
6842159047fSniklas 
6852159047fSniklas   if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0
686c074d1c9Sdrahn       || bfd_bread (b, (bfd_size_type) 2, abfd) != 2)
6872159047fSniklas     return NULL;
6882159047fSniklas 
6892159047fSniklas   if (b[0] != '$' || b[1] != '$')
6902159047fSniklas     {
6912159047fSniklas       bfd_set_error (bfd_error_wrong_format);
6922159047fSniklas       return NULL;
6932159047fSniklas     }
6942159047fSniklas 
695c074d1c9Sdrahn   tdata_save = abfd->tdata.any;
696c074d1c9Sdrahn   if (! srec_mkobject (abfd) || ! srec_scan (abfd))
697c074d1c9Sdrahn     {
698c074d1c9Sdrahn       if (abfd->tdata.any != tdata_save && abfd->tdata.any != NULL)
699c074d1c9Sdrahn 	bfd_release (abfd, abfd->tdata.any);
700c074d1c9Sdrahn       abfd->tdata.any = tdata_save;
7012159047fSniklas       return NULL;
702c074d1c9Sdrahn     }
7032159047fSniklas 
704b305b0f1Sespie   if (abfd->symcount > 0)
705b305b0f1Sespie     abfd->flags |= HAS_SYMS;
706b305b0f1Sespie 
7072159047fSniklas   return abfd->xvec;
7082159047fSniklas }
7092159047fSniklas 
7102159047fSniklas /* Read in the contents of a section in an S-record file.  */
7112159047fSniklas 
712c074d1c9Sdrahn static bfd_boolean
srec_read_section(abfd,section,contents)7132159047fSniklas srec_read_section (abfd, section, contents)
7142159047fSniklas      bfd *abfd;
7152159047fSniklas      asection *section;
7162159047fSniklas      bfd_byte *contents;
7172159047fSniklas {
7182159047fSniklas   int c;
7192159047fSniklas   bfd_size_type sofar = 0;
720c074d1c9Sdrahn   bfd_boolean error = FALSE;
7212159047fSniklas   bfd_byte *buf = NULL;
7222159047fSniklas   size_t bufsize = 0;
7232159047fSniklas 
7242159047fSniklas   if (bfd_seek (abfd, section->filepos, SEEK_SET) != 0)
7252159047fSniklas     goto error_return;
7262159047fSniklas 
7272159047fSniklas   while ((c = srec_get_byte (abfd, &error)) != EOF)
7282159047fSniklas     {
7292159047fSniklas       bfd_byte hdr[3];
7302159047fSniklas       unsigned int bytes;
7312159047fSniklas       bfd_vma address;
7322159047fSniklas       bfd_byte *data;
7332159047fSniklas 
7342159047fSniklas       if (c == '\r' || c == '\n')
7352159047fSniklas 	continue;
7362159047fSniklas 
7372159047fSniklas       /* This is called after srec_scan has already been called, so we
7382159047fSniklas 	 ought to know the exact format.  */
7392159047fSniklas       BFD_ASSERT (c == 'S');
7402159047fSniklas 
741c074d1c9Sdrahn       if (bfd_bread (hdr, (bfd_size_type) 3, abfd) != 3)
7422159047fSniklas 	goto error_return;
7432159047fSniklas 
7442159047fSniklas       BFD_ASSERT (ISHEX (hdr[1]) && ISHEX (hdr[2]));
7452159047fSniklas 
7462159047fSniklas       bytes = HEX (hdr + 1);
7472159047fSniklas 
7482159047fSniklas       if (bytes * 2 > bufsize)
7492159047fSniklas 	{
7502159047fSniklas 	  if (buf != NULL)
7512159047fSniklas 	    free (buf);
752c074d1c9Sdrahn 	  buf = (bfd_byte *) bfd_malloc ((bfd_size_type) bytes * 2);
7532159047fSniklas 	  if (buf == NULL)
7542159047fSniklas 	    goto error_return;
7552159047fSniklas 	  bufsize = bytes * 2;
7562159047fSniklas 	}
7572159047fSniklas 
758c074d1c9Sdrahn       if (bfd_bread (buf, (bfd_size_type) bytes * 2, abfd) != bytes * 2)
7592159047fSniklas 	goto error_return;
7602159047fSniklas 
7612159047fSniklas       address = 0;
7622159047fSniklas       data = buf;
7632159047fSniklas       switch (hdr[0])
7642159047fSniklas 	{
7652159047fSniklas 	default:
7662159047fSniklas 	  BFD_ASSERT (sofar == section->_raw_size);
7672159047fSniklas 	  if (buf != NULL)
7682159047fSniklas 	    free (buf);
769c074d1c9Sdrahn 	  return TRUE;
7702159047fSniklas 
7712159047fSniklas 	case '3':
7722159047fSniklas 	  address = HEX (data);
7732159047fSniklas 	  data += 2;
7742159047fSniklas 	  --bytes;
7752159047fSniklas 	  /* Fall through.  */
7762159047fSniklas 	case '2':
7772159047fSniklas 	  address = (address << 8) | HEX (data);
7782159047fSniklas 	  data += 2;
7792159047fSniklas 	  --bytes;
7802159047fSniklas 	  /* Fall through.  */
7812159047fSniklas 	case '1':
7822159047fSniklas 	  address = (address << 8) | HEX (data);
7832159047fSniklas 	  data += 2;
7842159047fSniklas 	  address = (address << 8) | HEX (data);
7852159047fSniklas 	  data += 2;
7862159047fSniklas 	  bytes -= 2;
7872159047fSniklas 
7882159047fSniklas 	  if (address != section->vma + sofar)
7892159047fSniklas 	    {
7902159047fSniklas 	      /* We've come to the end of this section.  */
7912159047fSniklas 	      BFD_ASSERT (sofar == section->_raw_size);
7922159047fSniklas 	      if (buf != NULL)
7932159047fSniklas 		free (buf);
794c074d1c9Sdrahn 	      return TRUE;
7952159047fSniklas 	    }
7962159047fSniklas 
7972159047fSniklas 	  /* Don't consider checksum.  */
7982159047fSniklas 	  --bytes;
7992159047fSniklas 
8002159047fSniklas 	  while (bytes-- != 0)
8012159047fSniklas 	    {
8022159047fSniklas 	      contents[sofar] = HEX (data);
8032159047fSniklas 	      data += 2;
8042159047fSniklas 	      ++sofar;
8052159047fSniklas 	    }
8062159047fSniklas 
8072159047fSniklas 	  break;
8082159047fSniklas 	}
8092159047fSniklas     }
8102159047fSniklas 
8112159047fSniklas   if (error)
8122159047fSniklas     goto error_return;
8132159047fSniklas 
8142159047fSniklas   BFD_ASSERT (sofar == section->_raw_size);
8152159047fSniklas 
8162159047fSniklas   if (buf != NULL)
8172159047fSniklas     free (buf);
8182159047fSniklas 
819c074d1c9Sdrahn   return TRUE;
8202159047fSniklas 
8212159047fSniklas  error_return:
8222159047fSniklas   if (buf != NULL)
8232159047fSniklas     free (buf);
824c074d1c9Sdrahn   return FALSE;
8252159047fSniklas }
8262159047fSniklas 
8272159047fSniklas /* Get the contents of a section in an S-record file.  */
8282159047fSniklas 
829c074d1c9Sdrahn static bfd_boolean
srec_get_section_contents(abfd,section,location,offset,count)8302159047fSniklas srec_get_section_contents (abfd, section, location, offset, count)
8312159047fSniklas      bfd *abfd;
8322159047fSniklas      asection *section;
8332159047fSniklas      PTR location;
8342159047fSniklas      file_ptr offset;
8352159047fSniklas      bfd_size_type count;
8362159047fSniklas {
8372159047fSniklas   if (section->used_by_bfd == NULL)
8382159047fSniklas     {
8392159047fSniklas       section->used_by_bfd = bfd_alloc (abfd, section->_raw_size);
840c074d1c9Sdrahn       if (section->used_by_bfd == NULL && section->_raw_size != 0)
841c074d1c9Sdrahn 	return FALSE;
8422159047fSniklas 
8432159047fSniklas       if (! srec_read_section (abfd, section, section->used_by_bfd))
844c074d1c9Sdrahn 	return FALSE;
8452159047fSniklas     }
8462159047fSniklas 
8472159047fSniklas   memcpy (location, (bfd_byte *) section->used_by_bfd + offset,
8482159047fSniklas 	  (size_t) count);
8492159047fSniklas 
850c074d1c9Sdrahn   return TRUE;
8512159047fSniklas }
8522159047fSniklas 
853c88b1d6cSniklas /* Set the architecture.  We accept an unknown architecture here.  */
854c88b1d6cSniklas 
855c074d1c9Sdrahn static bfd_boolean
srec_set_arch_mach(abfd,arch,mach)856c88b1d6cSniklas srec_set_arch_mach (abfd, arch, mach)
857c88b1d6cSniklas      bfd *abfd;
858c88b1d6cSniklas      enum bfd_architecture arch;
859c88b1d6cSniklas      unsigned long mach;
860c88b1d6cSniklas {
861c88b1d6cSniklas   if (arch == bfd_arch_unknown)
862c88b1d6cSniklas     {
863c88b1d6cSniklas       abfd->arch_info = &bfd_default_arch_struct;
864c074d1c9Sdrahn       return TRUE;
865c88b1d6cSniklas     }
866c88b1d6cSniklas   return bfd_default_set_arch_mach (abfd, arch, mach);
867c88b1d6cSniklas }
868c88b1d6cSniklas 
869b55d4692Sfgsch /* We have to save up all the Srecords for a splurge before output.  */
8702159047fSniklas 
871c074d1c9Sdrahn static bfd_boolean
srec_set_section_contents(abfd,section,location,offset,bytes_to_do)8722159047fSniklas srec_set_section_contents (abfd, section, location, offset, bytes_to_do)
8732159047fSniklas      bfd *abfd;
8742159047fSniklas      sec_ptr section;
875*007c2a45Smiod      const PTR location;
8762159047fSniklas      file_ptr offset;
8772159047fSniklas      bfd_size_type bytes_to_do;
8782159047fSniklas {
8792159047fSniklas   tdata_type *tdata = abfd->tdata.srec_data;
8802159047fSniklas   register srec_data_list_type *entry;
8812159047fSniklas 
8822159047fSniklas   entry = ((srec_data_list_type *)
883c074d1c9Sdrahn 	   bfd_alloc (abfd, (bfd_size_type) sizeof (srec_data_list_type)));
8842159047fSniklas   if (entry == NULL)
885c074d1c9Sdrahn     return FALSE;
8862159047fSniklas 
8872159047fSniklas   if (bytes_to_do
8882159047fSniklas       && (section->flags & SEC_ALLOC)
8892159047fSniklas       && (section->flags & SEC_LOAD))
8902159047fSniklas     {
891c074d1c9Sdrahn       bfd_byte *data;
892c074d1c9Sdrahn 
893c074d1c9Sdrahn       data = (bfd_byte *) bfd_alloc (abfd, bytes_to_do);
8942159047fSniklas       if (data == NULL)
895c074d1c9Sdrahn 	return FALSE;
8962159047fSniklas       memcpy ((PTR) data, location, (size_t) bytes_to_do);
8972159047fSniklas 
898c074d1c9Sdrahn       /* Ff S3Forced is TRUE then always select S3 records,
899b55d4692Sfgsch 	 regardless of the siez of the addresses.  */
900b55d4692Sfgsch       if (S3Forced)
901b55d4692Sfgsch 	tdata->type = 3;
902b55d4692Sfgsch       else if ((section->lma + offset + bytes_to_do - 1) <= 0xffff)
903b55d4692Sfgsch 	;  /* The default, S1, is OK.  */
9042159047fSniklas       else if ((section->lma + offset + bytes_to_do - 1) <= 0xffffff
905b305b0f1Sespie 	       && tdata->type <= 2)
9062159047fSniklas 	tdata->type = 2;
9072159047fSniklas       else
9082159047fSniklas 	tdata->type = 3;
9092159047fSniklas 
9102159047fSniklas       entry->data = data;
9112159047fSniklas       entry->where = section->lma + offset;
9122159047fSniklas       entry->size = bytes_to_do;
9132159047fSniklas 
9142159047fSniklas       /* Sort the records by address.  Optimize for the common case of
9152159047fSniklas 	 adding a record to the end of the list.  */
9162159047fSniklas       if (tdata->tail != NULL
9172159047fSniklas 	  && entry->where >= tdata->tail->where)
9182159047fSniklas 	{
9192159047fSniklas 	  tdata->tail->next = entry;
9202159047fSniklas 	  entry->next = NULL;
9212159047fSniklas 	  tdata->tail = entry;
9222159047fSniklas 	}
9232159047fSniklas       else
9242159047fSniklas 	{
9252159047fSniklas 	  register srec_data_list_type **look;
9262159047fSniklas 
9272159047fSniklas 	  for (look = &tdata->head;
9282159047fSniklas 	       *look != NULL && (*look)->where < entry->where;
9292159047fSniklas 	       look = &(*look)->next)
9302159047fSniklas 	    ;
9312159047fSniklas 	  entry->next = *look;
9322159047fSniklas 	  *look = entry;
9332159047fSniklas 	  if (entry->next == NULL)
9342159047fSniklas 	    tdata->tail = entry;
9352159047fSniklas 	}
9362159047fSniklas     }
937c074d1c9Sdrahn   return TRUE;
9382159047fSniklas }
9392159047fSniklas 
9402159047fSniklas /* Write a record of type, of the supplied number of bytes. The
9412159047fSniklas    supplied bytes and length don't have a checksum. That's worked out
942b55d4692Sfgsch    here.  */
943b55d4692Sfgsch 
944c074d1c9Sdrahn static bfd_boolean
srec_write_record(abfd,type,address,data,end)9452159047fSniklas srec_write_record (abfd, type, address, data, end)
9462159047fSniklas      bfd *abfd;
947c074d1c9Sdrahn      unsigned int type;
9482159047fSniklas      bfd_vma address;
9492159047fSniklas      const bfd_byte *data;
9502159047fSniklas      const bfd_byte *end;
9512159047fSniklas {
952c074d1c9Sdrahn   char buffer[2 * MAXCHUNK + 6];
9532159047fSniklas   unsigned int check_sum = 0;
954c074d1c9Sdrahn   const bfd_byte *src = data;
9552159047fSniklas   char *dst = buffer;
9562159047fSniklas   char *length;
9572159047fSniklas   bfd_size_type wrlen;
9582159047fSniklas 
9592159047fSniklas   *dst++ = 'S';
9602159047fSniklas   *dst++ = '0' + type;
9612159047fSniklas 
9622159047fSniklas   length = dst;
963b55d4692Sfgsch   dst += 2;			/* Leave room for dst.  */
9642159047fSniklas 
9652159047fSniklas   switch (type)
9662159047fSniklas     {
9672159047fSniklas     case 3:
9682159047fSniklas     case 7:
9692159047fSniklas       TOHEX (dst, (address >> 24), check_sum);
9702159047fSniklas       dst += 2;
9712159047fSniklas     case 8:
9722159047fSniklas     case 2:
9732159047fSniklas       TOHEX (dst, (address >> 16), check_sum);
9742159047fSniklas       dst += 2;
9752159047fSniklas     case 9:
9762159047fSniklas     case 1:
9772159047fSniklas     case 0:
9782159047fSniklas       TOHEX (dst, (address >> 8), check_sum);
9792159047fSniklas       dst += 2;
9802159047fSniklas       TOHEX (dst, (address), check_sum);
9812159047fSniklas       dst += 2;
9822159047fSniklas       break;
9832159047fSniklas 
9842159047fSniklas     }
9852159047fSniklas   for (src = data; src < end; src++)
9862159047fSniklas     {
9872159047fSniklas       TOHEX (dst, *src, check_sum);
9882159047fSniklas       dst += 2;
9892159047fSniklas     }
9902159047fSniklas 
991b55d4692Sfgsch   /* Fill in the length.  */
9922159047fSniklas   TOHEX (length, (dst - length) / 2, check_sum);
9932159047fSniklas   check_sum &= 0xff;
9942159047fSniklas   check_sum = 255 - check_sum;
9952159047fSniklas   TOHEX (dst, check_sum, check_sum);
9962159047fSniklas   dst += 2;
9972159047fSniklas 
9982159047fSniklas   *dst++ = '\r';
9992159047fSniklas   *dst++ = '\n';
10002159047fSniklas   wrlen = dst - buffer;
1001c074d1c9Sdrahn   if (bfd_bwrite ((PTR) buffer, wrlen, abfd) != wrlen)
1002c074d1c9Sdrahn     return FALSE;
1003c074d1c9Sdrahn   return TRUE;
10042159047fSniklas }
10052159047fSniklas 
1006c074d1c9Sdrahn static bfd_boolean
srec_write_header(abfd)10072159047fSniklas srec_write_header (abfd)
10082159047fSniklas      bfd *abfd;
10092159047fSniklas {
1010c074d1c9Sdrahn   unsigned int len = strlen (abfd->filename);
10112159047fSniklas 
1012*007c2a45Smiod   /* I'll put an arbitrary 40 char limit on header size.  */
1013c074d1c9Sdrahn   if (len > 40)
1014c074d1c9Sdrahn     len = 40;
1015b55d4692Sfgsch 
1016c074d1c9Sdrahn   return srec_write_record (abfd, 0, (bfd_vma) 0,
1017c074d1c9Sdrahn 			    abfd->filename, abfd->filename + len);
10182159047fSniklas }
10192159047fSniklas 
1020c074d1c9Sdrahn static bfd_boolean
srec_write_section(abfd,tdata,list)10212159047fSniklas srec_write_section (abfd, tdata, list)
10222159047fSniklas      bfd *abfd;
10232159047fSniklas      tdata_type *tdata;
10242159047fSniklas      srec_data_list_type *list;
10252159047fSniklas {
1026b305b0f1Sespie   unsigned int octets_written = 0;
10272159047fSniklas   bfd_byte *location = list->data;
10282159047fSniklas 
1029c074d1c9Sdrahn   /* Validate number of data bytes to write.  The srec length byte
1030c074d1c9Sdrahn      counts the address, data and crc bytes.  S1 (tdata->type == 1)
1031c074d1c9Sdrahn      records have two address bytes, S2 (tdata->type == 2) records
1032c074d1c9Sdrahn      have three, and S3 (tdata->type == 3) records have four.
1033c074d1c9Sdrahn      The total length can't exceed 255, and a zero data length will
1034c074d1c9Sdrahn      spin for a long time.  */
1035c074d1c9Sdrahn   if (Chunk == 0)
1036c074d1c9Sdrahn     Chunk = 1;
1037c074d1c9Sdrahn   else if (Chunk > MAXCHUNK - tdata->type - 2)
1038c074d1c9Sdrahn     Chunk = MAXCHUNK - tdata->type - 2;
1039c074d1c9Sdrahn 
1040b305b0f1Sespie   while (octets_written < list->size)
10412159047fSniklas     {
10422159047fSniklas       bfd_vma address;
1043b305b0f1Sespie       unsigned int octets_this_chunk = list->size - octets_written;
10442159047fSniklas 
1045b55d4692Sfgsch       if (octets_this_chunk > Chunk)
1046b55d4692Sfgsch 	octets_this_chunk = Chunk;
10472159047fSniklas 
1048b305b0f1Sespie       address = list->where + octets_written / bfd_octets_per_byte (abfd);
10492159047fSniklas 
10502159047fSniklas       if (! srec_write_record (abfd,
10512159047fSniklas 			       tdata->type,
10522159047fSniklas 			       address,
10532159047fSniklas 			       location,
1054b305b0f1Sespie 			       location + octets_this_chunk))
1055c074d1c9Sdrahn 	return FALSE;
10562159047fSniklas 
1057b305b0f1Sespie       octets_written += octets_this_chunk;
1058b305b0f1Sespie       location += octets_this_chunk;
10592159047fSniklas     }
10602159047fSniklas 
1061c074d1c9Sdrahn   return TRUE;
10622159047fSniklas }
10632159047fSniklas 
1064c074d1c9Sdrahn static bfd_boolean
srec_write_terminator(abfd,tdata)10652159047fSniklas srec_write_terminator (abfd, tdata)
10662159047fSniklas      bfd *abfd;
10672159047fSniklas      tdata_type *tdata;
10682159047fSniklas {
10692159047fSniklas   return srec_write_record (abfd, 10 - tdata->type,
1070c074d1c9Sdrahn 			    abfd->start_address, NULL, NULL);
10712159047fSniklas }
10722159047fSniklas 
1073c074d1c9Sdrahn static bfd_boolean
srec_write_symbols(abfd)10742159047fSniklas srec_write_symbols (abfd)
10752159047fSniklas      bfd *abfd;
10762159047fSniklas {
1077b55d4692Sfgsch   /* Dump out the symbols of a bfd.  */
10782159047fSniklas   int i;
10792159047fSniklas   int count = bfd_get_symcount (abfd);
10802159047fSniklas 
10812159047fSniklas   if (count)
10822159047fSniklas     {
1083c074d1c9Sdrahn       bfd_size_type len;
10842159047fSniklas       asymbol **table = bfd_get_outsymbols (abfd);
1085c074d1c9Sdrahn       len = strlen (abfd->filename);
1086c074d1c9Sdrahn       if (bfd_bwrite ("$$ ", (bfd_size_type) 3, abfd) != 3
1087c074d1c9Sdrahn 	  || bfd_bwrite (abfd->filename, len, abfd) != len
1088c074d1c9Sdrahn 	  || bfd_bwrite ("\r\n", (bfd_size_type) 2, abfd) != 2)
1089c074d1c9Sdrahn 	return FALSE;
10902159047fSniklas 
10912159047fSniklas       for (i = 0; i < count; i++)
10922159047fSniklas 	{
10932159047fSniklas 	  asymbol *s = table[i];
1094b305b0f1Sespie 	  if (! bfd_is_local_label (abfd, s)
1095b305b0f1Sespie 	      && (s->flags & BSF_DEBUGGING) == 0)
10962159047fSniklas 	    {
1097b55d4692Sfgsch 	      /* Just dump out non debug symbols.  */
1098c074d1c9Sdrahn 	      char buf[43], *p;
10992159047fSniklas 
1100c074d1c9Sdrahn 	      len = strlen (s->name);
1101c074d1c9Sdrahn 	      if (bfd_bwrite ("  ", (bfd_size_type) 2, abfd) != 2
1102c074d1c9Sdrahn 		  || bfd_bwrite (s->name, len, abfd) != len)
1103c074d1c9Sdrahn 		return FALSE;
1104c074d1c9Sdrahn 
1105c074d1c9Sdrahn 	      sprintf_vma (buf + 2, (s->value
1106c074d1c9Sdrahn 				     + s->section->output_section->lma
1107c074d1c9Sdrahn 				     + s->section->output_offset));
1108c074d1c9Sdrahn 	      p = buf + 2;
11092159047fSniklas 	      while (p[0] == '0' && p[1] != 0)
11102159047fSniklas 		p++;
1111c074d1c9Sdrahn 	      len = strlen (p);
1112c074d1c9Sdrahn 	      p[len] = '\r';
1113c074d1c9Sdrahn 	      p[len + 1] = '\n';
1114c074d1c9Sdrahn 	      *--p = '$';
1115c074d1c9Sdrahn 	      *--p = ' ';
1116c074d1c9Sdrahn 	      len += 4;
1117c074d1c9Sdrahn 	      if (bfd_bwrite (p, len, abfd) != len)
1118c074d1c9Sdrahn 		return FALSE;
11192159047fSniklas 	    }
11202159047fSniklas 	}
1121c074d1c9Sdrahn       if (bfd_bwrite ("$$ \r\n", (bfd_size_type) 5, abfd) != 5)
1122c074d1c9Sdrahn 	return FALSE;
11232159047fSniklas     }
11242159047fSniklas 
1125c074d1c9Sdrahn   return TRUE;
11262159047fSniklas }
11272159047fSniklas 
1128c074d1c9Sdrahn static bfd_boolean
internal_srec_write_object_contents(abfd,symbols)11292159047fSniklas internal_srec_write_object_contents (abfd, symbols)
11302159047fSniklas      bfd *abfd;
11312159047fSniklas      int symbols;
11322159047fSniklas {
11332159047fSniklas   tdata_type *tdata = abfd->tdata.srec_data;
11342159047fSniklas   srec_data_list_type *list;
11352159047fSniklas 
11362159047fSniklas   if (symbols)
11372159047fSniklas     {
11382159047fSniklas       if (! srec_write_symbols (abfd))
1139c074d1c9Sdrahn 	return FALSE;
11402159047fSniklas     }
11412159047fSniklas 
11422159047fSniklas   if (! srec_write_header (abfd))
1143c074d1c9Sdrahn     return FALSE;
11442159047fSniklas 
1145b55d4692Sfgsch   /* Now wander though all the sections provided and output them.  */
11462159047fSniklas   list = tdata->head;
11472159047fSniklas 
11482159047fSniklas   while (list != (srec_data_list_type *) NULL)
11492159047fSniklas     {
11502159047fSniklas       if (! srec_write_section (abfd, tdata, list))
1151c074d1c9Sdrahn 	return FALSE;
11522159047fSniklas       list = list->next;
11532159047fSniklas     }
11542159047fSniklas   return srec_write_terminator (abfd, tdata);
11552159047fSniklas }
11562159047fSniklas 
1157c074d1c9Sdrahn static bfd_boolean
srec_write_object_contents(abfd)11582159047fSniklas srec_write_object_contents (abfd)
11592159047fSniklas      bfd *abfd;
11602159047fSniklas {
11612159047fSniklas   return internal_srec_write_object_contents (abfd, 0);
11622159047fSniklas }
11632159047fSniklas 
1164c074d1c9Sdrahn static bfd_boolean
symbolsrec_write_object_contents(abfd)11652159047fSniklas symbolsrec_write_object_contents (abfd)
11662159047fSniklas      bfd *abfd;
11672159047fSniklas {
11682159047fSniklas   return internal_srec_write_object_contents (abfd, 1);
11692159047fSniklas }
11702159047fSniklas 
11712159047fSniklas static int
srec_sizeof_headers(abfd,exec)11722159047fSniklas srec_sizeof_headers (abfd, exec)
1173b305b0f1Sespie      bfd *abfd ATTRIBUTE_UNUSED;
1174c074d1c9Sdrahn      bfd_boolean exec ATTRIBUTE_UNUSED;
11752159047fSniklas {
11762159047fSniklas   return 0;
11772159047fSniklas }
11782159047fSniklas 
11792159047fSniklas /* Return the amount of memory needed to read the symbol table.  */
11802159047fSniklas 
11812159047fSniklas static long
srec_get_symtab_upper_bound(abfd)11822159047fSniklas srec_get_symtab_upper_bound (abfd)
11832159047fSniklas      bfd *abfd;
11842159047fSniklas {
11852159047fSniklas   return (bfd_get_symcount (abfd) + 1) * sizeof (asymbol *);
11862159047fSniklas }
11872159047fSniklas 
11882159047fSniklas /* Return the symbol table.  */
11892159047fSniklas 
11902159047fSniklas static long
srec_canonicalize_symtab(abfd,alocation)1191*007c2a45Smiod srec_canonicalize_symtab (abfd, alocation)
11922159047fSniklas      bfd *abfd;
11932159047fSniklas      asymbol **alocation;
11942159047fSniklas {
1195c074d1c9Sdrahn   bfd_size_type symcount = bfd_get_symcount (abfd);
11962159047fSniklas   asymbol *csymbols;
11972159047fSniklas   unsigned int i;
11982159047fSniklas 
11992159047fSniklas   csymbols = abfd->tdata.srec_data->csymbols;
12002159047fSniklas   if (csymbols == NULL)
12012159047fSniklas     {
12022159047fSniklas       asymbol *c;
12032159047fSniklas       struct srec_symbol *s;
12042159047fSniklas 
12052159047fSniklas       csymbols = (asymbol *) bfd_alloc (abfd, symcount * sizeof (asymbol));
12062159047fSniklas       if (csymbols == NULL && symcount != 0)
1207c074d1c9Sdrahn 	return 0;
12082159047fSniklas       abfd->tdata.srec_data->csymbols = csymbols;
12092159047fSniklas 
12102159047fSniklas       for (s = abfd->tdata.srec_data->symbols, c = csymbols;
12112159047fSniklas 	   s != NULL;
12122159047fSniklas 	   s = s->next, ++c)
12132159047fSniklas 	{
12142159047fSniklas 	  c->the_bfd = abfd;
12152159047fSniklas 	  c->name = s->name;
12162159047fSniklas 	  c->value = s->val;
12172159047fSniklas 	  c->flags = BSF_GLOBAL;
12182159047fSniklas 	  c->section = bfd_abs_section_ptr;
12192159047fSniklas 	  c->udata.p = NULL;
12202159047fSniklas 	}
12212159047fSniklas     }
12222159047fSniklas 
12232159047fSniklas   for (i = 0; i < symcount; i++)
12242159047fSniklas     *alocation++ = csymbols++;
12252159047fSniklas   *alocation = NULL;
12262159047fSniklas 
12272159047fSniklas   return symcount;
12282159047fSniklas }
12292159047fSniklas 
1230b305b0f1Sespie static void
srec_get_symbol_info(ignore_abfd,symbol,ret)12312159047fSniklas srec_get_symbol_info (ignore_abfd, symbol, ret)
1232b305b0f1Sespie      bfd *ignore_abfd ATTRIBUTE_UNUSED;
12332159047fSniklas      asymbol *symbol;
12342159047fSniklas      symbol_info *ret;
12352159047fSniklas {
12362159047fSniklas   bfd_symbol_info (symbol, ret);
12372159047fSniklas }
12382159047fSniklas 
1239e93f7393Sniklas static void
srec_print_symbol(abfd,afile,symbol,how)1240c074d1c9Sdrahn srec_print_symbol (abfd, afile, symbol, how)
1241c074d1c9Sdrahn      bfd *abfd;
12422159047fSniklas      PTR afile;
12432159047fSniklas      asymbol *symbol;
12442159047fSniklas      bfd_print_symbol_type how;
12452159047fSniklas {
12462159047fSniklas   FILE *file = (FILE *) afile;
12472159047fSniklas   switch (how)
12482159047fSniklas     {
12492159047fSniklas     case bfd_print_symbol_name:
12502159047fSniklas       fprintf (file, "%s", symbol->name);
12512159047fSniklas       break;
12522159047fSniklas     default:
1253c074d1c9Sdrahn       bfd_print_symbol_vandf (abfd, (PTR) file, symbol);
12542159047fSniklas       fprintf (file, " %-5s %s",
12552159047fSniklas 	       symbol->section->name,
12562159047fSniklas 	       symbol->name);
12572159047fSniklas 
12582159047fSniklas     }
12592159047fSniklas }
12602159047fSniklas 
12612159047fSniklas #define	srec_close_and_cleanup _bfd_generic_close_and_cleanup
12622159047fSniklas #define srec_bfd_free_cached_info _bfd_generic_bfd_free_cached_info
12632159047fSniklas #define srec_new_section_hook _bfd_generic_new_section_hook
12642159047fSniklas 
1265b305b0f1Sespie #define srec_bfd_is_local_label_name bfd_generic_is_local_label_name
12662159047fSniklas #define srec_get_lineno _bfd_nosymbols_get_lineno
12672159047fSniklas #define srec_find_nearest_line _bfd_nosymbols_find_nearest_line
1268c074d1c9Sdrahn #define srec_make_empty_symbol _bfd_generic_make_empty_symbol
12692159047fSniklas #define srec_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol
12702159047fSniklas #define srec_read_minisymbols _bfd_generic_read_minisymbols
12712159047fSniklas #define srec_minisymbol_to_symbol _bfd_generic_minisymbol_to_symbol
12722159047fSniklas 
12732159047fSniklas #define srec_get_reloc_upper_bound \
12742159047fSniklas   ((long (*) PARAMS ((bfd *, asection *))) bfd_0l)
12752159047fSniklas #define srec_canonicalize_reloc \
12762159047fSniklas   ((long (*) PARAMS ((bfd *, asection *, arelent **, asymbol **))) bfd_0l)
12772159047fSniklas #define srec_bfd_reloc_type_lookup _bfd_norelocs_bfd_reloc_type_lookup
12782159047fSniklas 
12792159047fSniklas #define srec_get_section_contents_in_window \
12802159047fSniklas   _bfd_generic_get_section_contents_in_window
12812159047fSniklas 
12822159047fSniklas #define srec_bfd_get_relocated_section_contents \
12832159047fSniklas   bfd_generic_get_relocated_section_contents
12842159047fSniklas #define srec_bfd_relax_section bfd_generic_relax_section
1285b305b0f1Sespie #define srec_bfd_gc_sections bfd_generic_gc_sections
1286c074d1c9Sdrahn #define srec_bfd_merge_sections bfd_generic_merge_sections
1287c074d1c9Sdrahn #define srec_bfd_discard_group bfd_generic_discard_group
12882159047fSniklas #define srec_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
1289c074d1c9Sdrahn #define srec_bfd_link_hash_table_free _bfd_generic_link_hash_table_free
12902159047fSniklas #define srec_bfd_link_add_symbols _bfd_generic_link_add_symbols
1291c074d1c9Sdrahn #define srec_bfd_link_just_syms _bfd_generic_link_just_syms
12922159047fSniklas #define srec_bfd_final_link _bfd_generic_final_link
12932159047fSniklas #define srec_bfd_link_split_section _bfd_generic_link_split_section
12942159047fSniklas 
12952159047fSniklas const bfd_target srec_vec =
12962159047fSniklas {
12972159047fSniklas   "srec",			/* name */
12982159047fSniklas   bfd_target_srec_flavour,
1299c88b1d6cSniklas   BFD_ENDIAN_UNKNOWN,		/* target byte order */
1300c88b1d6cSniklas   BFD_ENDIAN_UNKNOWN,		/* target headers byte order */
13012159047fSniklas   (HAS_RELOC | EXEC_P |		/* object flags */
13022159047fSniklas    HAS_LINENO | HAS_DEBUG |
13032159047fSniklas    HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
13042159047fSniklas   (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS
13052159047fSniklas    | SEC_ALLOC | SEC_LOAD | SEC_RELOC),	/* section flags */
13062159047fSniklas   0,				/* leading underscore */
13072159047fSniklas   ' ',				/* ar_pad_char */
13082159047fSniklas   16,				/* ar_max_namelen */
13092159047fSniklas   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
13102159047fSniklas   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
13112159047fSniklas   bfd_getb16, bfd_getb_signed_16, bfd_putb16,	/* data */
13122159047fSniklas   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
13132159047fSniklas   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
13142159047fSniklas   bfd_getb16, bfd_getb_signed_16, bfd_putb16,	/* hdrs */
13152159047fSniklas 
13162159047fSniklas   {
13172159047fSniklas     _bfd_dummy_target,
13182159047fSniklas     srec_object_p,		/* bfd_check_format */
13192159047fSniklas     _bfd_dummy_target,
13202159047fSniklas     _bfd_dummy_target,
13212159047fSniklas   },
13222159047fSniklas   {
13232159047fSniklas     bfd_false,
13242159047fSniklas     srec_mkobject,
13252159047fSniklas     _bfd_generic_mkarchive,
13262159047fSniklas     bfd_false,
13272159047fSniklas   },
13282159047fSniklas   {				/* bfd_write_contents */
13292159047fSniklas     bfd_false,
13302159047fSniklas     srec_write_object_contents,
13312159047fSniklas     _bfd_write_archive_contents,
13322159047fSniklas     bfd_false,
13332159047fSniklas   },
13342159047fSniklas 
13352159047fSniklas   BFD_JUMP_TABLE_GENERIC (srec),
13362159047fSniklas   BFD_JUMP_TABLE_COPY (_bfd_generic),
13372159047fSniklas   BFD_JUMP_TABLE_CORE (_bfd_nocore),
13382159047fSniklas   BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
13392159047fSniklas   BFD_JUMP_TABLE_SYMBOLS (srec),
13402159047fSniklas   BFD_JUMP_TABLE_RELOCS (srec),
13412159047fSniklas   BFD_JUMP_TABLE_WRITE (srec),
13422159047fSniklas   BFD_JUMP_TABLE_LINK (srec),
13432159047fSniklas   BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
13442159047fSniklas 
1345b305b0f1Sespie   NULL,
1346b305b0f1Sespie 
13472159047fSniklas   (PTR) 0
13482159047fSniklas };
13492159047fSniklas 
13502159047fSniklas const bfd_target symbolsrec_vec =
13512159047fSniklas {
13522159047fSniklas   "symbolsrec",			/* name */
13532159047fSniklas   bfd_target_srec_flavour,
1354c88b1d6cSniklas   BFD_ENDIAN_UNKNOWN,		/* target byte order */
1355c88b1d6cSniklas   BFD_ENDIAN_UNKNOWN,		/* target headers byte order */
13562159047fSniklas   (HAS_RELOC | EXEC_P |		/* object flags */
13572159047fSniklas    HAS_LINENO | HAS_DEBUG |
13582159047fSniklas    HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
13592159047fSniklas   (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS
13602159047fSniklas    | SEC_ALLOC | SEC_LOAD | SEC_RELOC),	/* section flags */
13612159047fSniklas   0,				/* leading underscore */
13622159047fSniklas   ' ',				/* ar_pad_char */
13632159047fSniklas   16,				/* ar_max_namelen */
13642159047fSniklas   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
13652159047fSniklas   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
13662159047fSniklas   bfd_getb16, bfd_getb_signed_16, bfd_putb16,	/* data */
13672159047fSniklas   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
13682159047fSniklas   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
13692159047fSniklas   bfd_getb16, bfd_getb_signed_16, bfd_putb16,	/* hdrs */
13702159047fSniklas 
13712159047fSniklas   {
13722159047fSniklas     _bfd_dummy_target,
13732159047fSniklas     symbolsrec_object_p,	/* bfd_check_format */
13742159047fSniklas     _bfd_dummy_target,
13752159047fSniklas     _bfd_dummy_target,
13762159047fSniklas   },
13772159047fSniklas   {
13782159047fSniklas     bfd_false,
13792159047fSniklas     srec_mkobject,
13802159047fSniklas     _bfd_generic_mkarchive,
13812159047fSniklas     bfd_false,
13822159047fSniklas   },
13832159047fSniklas   {				/* bfd_write_contents */
13842159047fSniklas     bfd_false,
13852159047fSniklas     symbolsrec_write_object_contents,
13862159047fSniklas     _bfd_write_archive_contents,
13872159047fSniklas     bfd_false,
13882159047fSniklas   },
13892159047fSniklas 
13902159047fSniklas   BFD_JUMP_TABLE_GENERIC (srec),
13912159047fSniklas   BFD_JUMP_TABLE_COPY (_bfd_generic),
13922159047fSniklas   BFD_JUMP_TABLE_CORE (_bfd_nocore),
13932159047fSniklas   BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
13942159047fSniklas   BFD_JUMP_TABLE_SYMBOLS (srec),
13952159047fSniklas   BFD_JUMP_TABLE_RELOCS (srec),
13962159047fSniklas   BFD_JUMP_TABLE_WRITE (srec),
13972159047fSniklas   BFD_JUMP_TABLE_LINK (srec),
13982159047fSniklas   BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
13992159047fSniklas 
1400b305b0f1Sespie   NULL,
1401b305b0f1Sespie 
14022159047fSniklas   (PTR) 0
14032159047fSniklas };
1404