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