xref: /netbsd-src/external/gpl3/gdb.old/dist/bfd/srec.c (revision 8b657b0747480f8989760d71343d6dd33f8d4cf9)
1 /* BFD back-end for s-record objects.
2    Copyright (C) 1990-2022 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 
113 static 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.  */
132 unsigned int _bfd_srec_len = 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.  */
137 bool _bfd_srec_forceS3 = 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 
142 struct 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 
150 typedef 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 
156 struct 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 
165 typedef 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   }
174 tdata_type;
175 
176 /* Initialize by filling in the hex conversion array.  */
177 
178 static void
179 srec_init (void)
180 {
181   static bool 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 
192 static bool
193 srec_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 
217 static int
218 srec_get_byte (bfd *abfd, bool *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 
236 static void
237 srec_bad_byte (bfd *abfd,
238 	       unsigned int lineno,
239 	       int c,
240 	       bool 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 	(_("%pB:%d: unexpected character `%s' in S-record file"),
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 
268 static bool
269 srec_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 
295 static bool
296 srec_scan (bfd *abfd)
297 {
298   int c;
299   unsigned int lineno = 1;
300   bool 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 (_("%pB:%d: byte count %d too small"),
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 		free (buf);
497 		buf = (bfd_byte *) bfd_malloc ((bfd_size_type) bytes * 2);
498 		if (buf == NULL)
499 		  goto error_return;
500 		bufsize = bytes * 2;
501 	      }
502 
503 	    if (bfd_bread (buf, (bfd_size_type) bytes * 2, abfd) != bytes * 2)
504 	      goto error_return;
505 
506 	    /* Ignore the checksum byte.  */
507 	    --bytes;
508 
509 	    address = 0;
510 	    data = buf;
511 	    switch (hdr[0])
512 	      {
513 	      case '0':
514 	      case '5':
515 		/* Prologue--ignore the file name, but stop building a
516 		   section at this point.  */
517 		sec = NULL;
518 		break;
519 
520 	      case '3':
521 		check_sum += HEX (data);
522 		address = HEX (data);
523 		data += 2;
524 		--bytes;
525 		/* Fall through.  */
526 	      case '2':
527 		check_sum += HEX (data);
528 		address = (address << 8) | HEX (data);
529 		data += 2;
530 		--bytes;
531 		/* Fall through.  */
532 	      case '1':
533 		check_sum += HEX (data);
534 		address = (address << 8) | HEX (data);
535 		data += 2;
536 		check_sum += HEX (data);
537 		address = (address << 8) | HEX (data);
538 		data += 2;
539 		bytes -= 2;
540 
541 		if (sec != NULL
542 		    && sec->vma + sec->size == address)
543 		  {
544 		    /* This data goes at the end of the section we are
545 		       currently building.  */
546 		    sec->size += bytes;
547 		  }
548 		else
549 		  {
550 		    char secbuf[20];
551 		    char *secname;
552 		    size_t amt;
553 		    flagword flags;
554 
555 		    sprintf (secbuf, ".sec%d", bfd_count_sections (abfd) + 1);
556 		    amt = strlen (secbuf) + 1;
557 		    secname = (char *) bfd_alloc (abfd, amt);
558 		    strcpy (secname, secbuf);
559 		    flags = SEC_HAS_CONTENTS | SEC_LOAD | SEC_ALLOC;
560 		    sec = bfd_make_section_with_flags (abfd, secname, flags);
561 		    if (sec == NULL)
562 		      goto error_return;
563 		    sec->vma = address;
564 		    sec->lma = address;
565 		    sec->size = bytes;
566 		    sec->filepos = pos;
567 		  }
568 
569 		while (bytes > 0)
570 		  {
571 		    check_sum += HEX (data);
572 		    data += 2;
573 		    bytes--;
574 		  }
575 		check_sum = 255 - (check_sum & 0xff);
576 		if (check_sum != HEX (data))
577 		  {
578 		    _bfd_error_handler
579 		      /* xgettext:c-format */
580 		      (_("%pB:%d: bad checksum in S-record file"),
581 		       abfd, lineno);
582 		    bfd_set_error (bfd_error_bad_value);
583 		    goto error_return;
584 		  }
585 
586 		break;
587 
588 	      case '7':
589 		check_sum += HEX (data);
590 		address = HEX (data);
591 		data += 2;
592 		/* Fall through.  */
593 	      case '8':
594 		check_sum += HEX (data);
595 		address = (address << 8) | HEX (data);
596 		data += 2;
597 		/* Fall through.  */
598 	      case '9':
599 		check_sum += HEX (data);
600 		address = (address << 8) | HEX (data);
601 		data += 2;
602 		check_sum += HEX (data);
603 		address = (address << 8) | HEX (data);
604 		data += 2;
605 
606 		/* This is a termination record.  */
607 		abfd->start_address = address;
608 
609 		check_sum = 255 - (check_sum & 0xff);
610 		if (check_sum != HEX (data))
611 		  {
612 		    _bfd_error_handler
613 		      /* xgettext:c-format */
614 		      (_("%pB:%d: bad checksum in S-record file"),
615 		       abfd, lineno);
616 		    bfd_set_error (bfd_error_bad_value);
617 		    goto error_return;
618 		  }
619 
620 		free (buf);
621 		return true;
622 	      }
623 	  }
624 	  break;
625 	}
626     }
627 
628   if (error)
629     goto error_return;
630 
631   free (buf);
632   return true;
633 
634  error_return:
635   free (symbuf);
636   free (buf);
637   return false;
638 }
639 
640 /* Check whether an existing file is an S-record file.  */
641 
642 static bfd_cleanup
643 srec_object_p (bfd *abfd)
644 {
645   void * tdata_save;
646   bfd_byte b[4];
647 
648   srec_init ();
649 
650   if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0
651       || bfd_bread (b, (bfd_size_type) 4, abfd) != 4)
652     return NULL;
653 
654   if (b[0] != 'S' || !ISHEX (b[1]) || !ISHEX (b[2]) || !ISHEX (b[3]))
655     {
656       bfd_set_error (bfd_error_wrong_format);
657       return NULL;
658     }
659 
660   tdata_save = abfd->tdata.any;
661   if (! srec_mkobject (abfd) || ! srec_scan (abfd))
662     {
663       if (abfd->tdata.any != tdata_save && abfd->tdata.any != NULL)
664 	bfd_release (abfd, abfd->tdata.any);
665       abfd->tdata.any = tdata_save;
666       return NULL;
667     }
668 
669   if (abfd->symcount > 0)
670     abfd->flags |= HAS_SYMS;
671 
672   return _bfd_no_cleanup;
673 }
674 
675 /* Check whether an existing file is an S-record file with symbols.  */
676 
677 static bfd_cleanup
678 symbolsrec_object_p (bfd *abfd)
679 {
680   void * tdata_save;
681   char b[2];
682 
683   srec_init ();
684 
685   if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0
686       || bfd_bread (b, (bfd_size_type) 2, abfd) != 2)
687     return NULL;
688 
689   if (b[0] != '$' || b[1] != '$')
690     {
691       bfd_set_error (bfd_error_wrong_format);
692       return NULL;
693     }
694 
695   tdata_save = abfd->tdata.any;
696   if (! srec_mkobject (abfd) || ! srec_scan (abfd))
697     {
698       if (abfd->tdata.any != tdata_save && abfd->tdata.any != NULL)
699 	bfd_release (abfd, abfd->tdata.any);
700       abfd->tdata.any = tdata_save;
701       return NULL;
702     }
703 
704   if (abfd->symcount > 0)
705     abfd->flags |= HAS_SYMS;
706 
707   return _bfd_no_cleanup;
708 }
709 
710 /* Read in the contents of a section in an S-record file.  */
711 
712 static bool
713 srec_read_section (bfd *abfd, asection *section, bfd_byte *contents)
714 {
715   int c;
716   bfd_size_type sofar = 0;
717   bool error = false;
718   bfd_byte *buf = NULL;
719   size_t bufsize = 0;
720 
721   if (bfd_seek (abfd, section->filepos, SEEK_SET) != 0)
722     goto error_return;
723 
724   while ((c = srec_get_byte (abfd, &error)) != EOF)
725     {
726       bfd_byte hdr[3];
727       unsigned int bytes;
728       bfd_vma address;
729       bfd_byte *data;
730 
731       if (c == '\r' || c == '\n')
732 	continue;
733 
734       /* This is called after srec_scan has already been called, so we
735 	 ought to know the exact format.  */
736       if (c != 'S')
737 	goto error_return;
738 
739       if (bfd_bread (hdr, (bfd_size_type) 3, abfd) != 3)
740 	goto error_return;
741 
742       BFD_ASSERT (ISHEX (hdr[1]) && ISHEX (hdr[2]));
743 
744       bytes = HEX (hdr + 1);
745 
746       if (bytes * 2 > bufsize)
747 	{
748 	  free (buf);
749 	  buf = (bfd_byte *) bfd_malloc ((bfd_size_type) bytes * 2);
750 	  if (buf == NULL)
751 	    goto error_return;
752 	  bufsize = bytes * 2;
753 	}
754 
755       if (bfd_bread (buf, (bfd_size_type) bytes * 2, abfd) != bytes * 2)
756 	goto error_return;
757 
758       address = 0;
759       data = buf;
760       switch (hdr[0])
761 	{
762 	default:
763 	  if (sofar != section->size)
764 	    goto error_return;
765 	  free (buf);
766 	  return true;
767 
768 	case '3':
769 	  address = HEX (data);
770 	  data += 2;
771 	  --bytes;
772 	  /* Fall through.  */
773 	case '2':
774 	  address = (address << 8) | HEX (data);
775 	  data += 2;
776 	  --bytes;
777 	  /* Fall through.  */
778 	case '1':
779 	  address = (address << 8) | HEX (data);
780 	  data += 2;
781 	  address = (address << 8) | HEX (data);
782 	  data += 2;
783 	  bytes -= 2;
784 
785 	  if (address != section->vma + sofar)
786 	    {
787 	      /* We've come to the end of this section.  */
788 	      if (sofar != section->size)
789 		goto error_return;
790 	      free (buf);
791 	      return true;
792 	    }
793 
794 	  /* Don't consider checksum.  */
795 	  --bytes;
796 
797 	  while (bytes-- != 0)
798 	    {
799 	      contents[sofar] = HEX (data);
800 	      data += 2;
801 	      ++sofar;
802 	    }
803 
804 	  break;
805 	}
806     }
807 
808   if (error)
809     goto error_return;
810 
811   if (sofar != section->size)
812     goto error_return;
813 
814   free (buf);
815   return true;
816 
817  error_return:
818   free (buf);
819   return false;
820 }
821 
822 /* Get the contents of a section in an S-record file.  */
823 
824 static bool
825 srec_get_section_contents (bfd *abfd,
826 			   asection *section,
827 			   void * location,
828 			   file_ptr offset,
829 			   bfd_size_type count)
830 {
831   if (count == 0)
832     return true;
833 
834   if (offset + count < count
835       || offset + count > section->size)
836     {
837       bfd_set_error (bfd_error_invalid_operation);
838       return false;
839     }
840 
841   if (section->used_by_bfd == NULL)
842     {
843       section->used_by_bfd = bfd_alloc (abfd, section->size);
844       if (section->used_by_bfd == NULL)
845 	return false;
846 
847       if (! srec_read_section (abfd, section,
848 			       (bfd_byte *) section->used_by_bfd))
849 	return false;
850     }
851 
852   memcpy (location, (bfd_byte *) section->used_by_bfd + offset,
853 	  (size_t) count);
854 
855   return true;
856 }
857 
858 /* Set the architecture.  We accept an unknown architecture here.  */
859 
860 static bool
861 srec_set_arch_mach (bfd *abfd, enum bfd_architecture arch, unsigned long mach)
862 {
863   if (arch != bfd_arch_unknown)
864     return bfd_default_set_arch_mach (abfd, arch, mach);
865 
866   abfd->arch_info = & bfd_default_arch_struct;
867   return true;
868 }
869 
870 /* We have to save up all the Srecords for a splurge before output.  */
871 
872 static bool
873 srec_set_section_contents (bfd *abfd,
874 			   sec_ptr section,
875 			   const void * location,
876 			   file_ptr offset,
877 			   bfd_size_type bytes_to_do)
878 {
879   int opb = bfd_octets_per_byte (abfd, NULL);
880   tdata_type *tdata = abfd->tdata.srec_data;
881   srec_data_list_type *entry;
882 
883   entry = (srec_data_list_type *) bfd_alloc (abfd, sizeof (* entry));
884   if (entry == NULL)
885     return false;
886 
887   if (bytes_to_do
888       && (section->flags & SEC_ALLOC)
889       && (section->flags & SEC_LOAD))
890     {
891       bfd_byte *data;
892 
893       data = (bfd_byte *) bfd_alloc (abfd, bytes_to_do);
894       if (data == NULL)
895 	return false;
896       memcpy ((void *) data, location, (size_t) bytes_to_do);
897 
898       /* If _bfd_srec_forceS3 is TRUE then always select S3 records,
899 	 regardless of the size of the addresses.  */
900       if (_bfd_srec_forceS3)
901 	tdata->type = 3;
902       else if ((section->lma + (offset + bytes_to_do) / opb - 1) <= 0xffff)
903 	;  /* The default, S1, is OK.  */
904       else if ((section->lma + (offset + bytes_to_do) / opb - 1) <= 0xffffff
905 	       && tdata->type <= 2)
906 	tdata->type = 2;
907       else
908 	tdata->type = 3;
909 
910       entry->data = data;
911       entry->where = section->lma + offset / opb;
912       entry->size = bytes_to_do;
913 
914       /* Sort the records by address.  Optimize for the common case of
915 	 adding a record to the end of the list.  */
916       if (tdata->tail != NULL
917 	  && entry->where >= tdata->tail->where)
918 	{
919 	  tdata->tail->next = entry;
920 	  entry->next = NULL;
921 	  tdata->tail = entry;
922 	}
923       else
924 	{
925 	  srec_data_list_type **look;
926 
927 	  for (look = &tdata->head;
928 	       *look != NULL && (*look)->where < entry->where;
929 	       look = &(*look)->next)
930 	    ;
931 	  entry->next = *look;
932 	  *look = entry;
933 	  if (entry->next == NULL)
934 	    tdata->tail = entry;
935 	}
936     }
937   return true;
938 }
939 
940 /* Write a record of type, of the supplied number of bytes. The
941    supplied bytes and length don't have a checksum. That's worked out
942    here.  */
943 
944 static bool
945 srec_write_record (bfd *abfd,
946 		   unsigned int type,
947 		   bfd_vma address,
948 		   const bfd_byte *data,
949 		   const bfd_byte *end)
950 {
951   char buffer[2 * MAXCHUNK + 6];
952   unsigned int check_sum = 0;
953   const bfd_byte *src = data;
954   char *dst = buffer;
955   char *length;
956   bfd_size_type wrlen;
957 
958   *dst++ = 'S';
959   *dst++ = '0' + type;
960 
961   length = dst;
962   dst += 2;			/* Leave room for dst.  */
963 
964   switch (type)
965     {
966     case 3:
967     case 7:
968       TOHEX (dst, (address >> 24), check_sum);
969       dst += 2;
970       /* Fall through.  */
971     case 8:
972     case 2:
973       TOHEX (dst, (address >> 16), check_sum);
974       dst += 2;
975       /* Fall through.  */
976     case 9:
977     case 1:
978     case 0:
979       TOHEX (dst, (address >> 8), check_sum);
980       dst += 2;
981       TOHEX (dst, (address), check_sum);
982       dst += 2;
983       break;
984 
985     }
986   for (src = data; src < end; src++)
987     {
988       TOHEX (dst, *src, check_sum);
989       dst += 2;
990     }
991 
992   /* Fill in the length.  */
993   TOHEX (length, (dst - length) / 2, check_sum);
994   check_sum &= 0xff;
995   check_sum = 255 - check_sum;
996   TOHEX (dst, check_sum, check_sum);
997   dst += 2;
998 
999   *dst++ = '\r';
1000   *dst++ = '\n';
1001   wrlen = dst - buffer;
1002 
1003   return bfd_bwrite ((void *) buffer, wrlen, abfd) == wrlen;
1004 }
1005 
1006 static bool
1007 srec_write_header (bfd *abfd)
1008 {
1009   unsigned int len = strlen (bfd_get_filename (abfd));
1010 
1011   /* I'll put an arbitrary 40 char limit on header size.  */
1012   if (len > 40)
1013     len = 40;
1014 
1015   return srec_write_record (abfd, 0, (bfd_vma) 0,
1016 			    (bfd_byte *) bfd_get_filename (abfd),
1017 			    (bfd_byte *) bfd_get_filename (abfd) + len);
1018 }
1019 
1020 static bool
1021 srec_write_section (bfd *abfd,
1022 		    tdata_type *tdata,
1023 		    srec_data_list_type *list)
1024 {
1025   unsigned int octets_written = 0;
1026   bfd_byte *location = list->data;
1027 
1028   /* Validate number of data bytes to write.  The srec length byte
1029      counts the address, data and crc bytes.  S1 (tdata->type == 1)
1030      records have two address bytes, S2 (tdata->type == 2) records
1031      have three, and S3 (tdata->type == 3) records have four.
1032      The total length can't exceed 255, and a zero data length will
1033      spin for a long time.  */
1034   if (_bfd_srec_len == 0)
1035     _bfd_srec_len = 1;
1036   else if (_bfd_srec_len > MAXCHUNK - tdata->type - 2)
1037     _bfd_srec_len = MAXCHUNK - tdata->type - 2;
1038 
1039   while (octets_written < list->size)
1040     {
1041       bfd_vma address;
1042       unsigned int octets_this_chunk = list->size - octets_written;
1043 
1044       if (octets_this_chunk > _bfd_srec_len)
1045 	octets_this_chunk = _bfd_srec_len;
1046 
1047       address = list->where + (octets_written
1048 			       / bfd_octets_per_byte (abfd, NULL));
1049 
1050       if (! srec_write_record (abfd,
1051 			       tdata->type,
1052 			       address,
1053 			       location,
1054 			       location + octets_this_chunk))
1055 	return false;
1056 
1057       octets_written += octets_this_chunk;
1058       location += octets_this_chunk;
1059     }
1060 
1061   return true;
1062 }
1063 
1064 static bool
1065 srec_write_terminator (bfd *abfd, tdata_type *tdata)
1066 {
1067   return srec_write_record (abfd, 10 - tdata->type,
1068 			    abfd->start_address, NULL, NULL);
1069 }
1070 
1071 static bool
1072 srec_write_symbols (bfd *abfd)
1073 {
1074   /* Dump out the symbols of a bfd.  */
1075   int i;
1076   int count = bfd_get_symcount (abfd);
1077 
1078   if (count)
1079     {
1080       bfd_size_type len;
1081       asymbol **table = bfd_get_outsymbols (abfd);
1082 
1083       len = strlen (bfd_get_filename (abfd));
1084       if (bfd_bwrite ("$$ ", (bfd_size_type) 3, abfd) != 3
1085 	  || bfd_bwrite (bfd_get_filename (abfd), len, abfd) != len
1086 	  || bfd_bwrite ("\r\n", (bfd_size_type) 2, abfd) != 2)
1087 	return false;
1088 
1089       for (i = 0; i < count; i++)
1090 	{
1091 	  asymbol *s = table[i];
1092 
1093 	  if (! bfd_is_local_label (abfd, s)
1094 	      && (s->flags & BSF_DEBUGGING) == 0
1095 	      && s->section != NULL
1096 	      && s->section->output_section != NULL)
1097 	    {
1098 	      /* Just dump out non debug symbols.  */
1099 	      char buf[43];
1100 
1101 	      len = strlen (s->name);
1102 	      if (bfd_bwrite ("  ", (bfd_size_type) 2, abfd) != 2
1103 		  || bfd_bwrite (s->name, len, abfd) != len)
1104 		return false;
1105 
1106 	      sprintf (buf, " $%" PRIx64 "\r\n",
1107 		       (uint64_t) (s->value
1108 				   + s->section->output_section->lma
1109 				   + s->section->output_offset));
1110 	      len = strlen (buf);
1111 	      if (bfd_bwrite (buf, len, abfd) != len)
1112 		return false;
1113 	    }
1114 	}
1115       if (bfd_bwrite ("$$ \r\n", (bfd_size_type) 5, abfd) != 5)
1116 	return false;
1117     }
1118 
1119   return true;
1120 }
1121 
1122 static bool
1123 internal_srec_write_object_contents (bfd *abfd, int symbols)
1124 {
1125   tdata_type *tdata = abfd->tdata.srec_data;
1126   srec_data_list_type *list;
1127 
1128   if (symbols)
1129     {
1130       if (! srec_write_symbols (abfd))
1131 	return false;
1132     }
1133 
1134   if (! srec_write_header (abfd))
1135     return false;
1136 
1137   /* Now wander though all the sections provided and output them.  */
1138   list = tdata->head;
1139 
1140   while (list != (srec_data_list_type *) NULL)
1141     {
1142       if (! srec_write_section (abfd, tdata, list))
1143 	return false;
1144       list = list->next;
1145     }
1146   return srec_write_terminator (abfd, tdata);
1147 }
1148 
1149 static bool
1150 srec_write_object_contents (bfd *abfd)
1151 {
1152   return internal_srec_write_object_contents (abfd, 0);
1153 }
1154 
1155 static bool
1156 symbolsrec_write_object_contents (bfd *abfd)
1157 {
1158   return internal_srec_write_object_contents (abfd, 1);
1159 }
1160 
1161 static int
1162 srec_sizeof_headers (bfd *abfd ATTRIBUTE_UNUSED,
1163 		     struct bfd_link_info *info ATTRIBUTE_UNUSED)
1164 {
1165   return 0;
1166 }
1167 
1168 /* Return the amount of memory needed to read the symbol table.  */
1169 
1170 static long
1171 srec_get_symtab_upper_bound (bfd *abfd)
1172 {
1173   return (bfd_get_symcount (abfd) + 1) * sizeof (asymbol *);
1174 }
1175 
1176 /* Return the symbol table.  */
1177 
1178 static long
1179 srec_canonicalize_symtab (bfd *abfd, asymbol **alocation)
1180 {
1181   bfd_size_type symcount = bfd_get_symcount (abfd);
1182   asymbol *csymbols;
1183   unsigned int i;
1184 
1185   csymbols = abfd->tdata.srec_data->csymbols;
1186   if (csymbols == NULL && symcount != 0)
1187     {
1188       asymbol *c;
1189       struct srec_symbol *s;
1190 
1191       csymbols = (asymbol *) bfd_alloc (abfd, symcount * sizeof (asymbol));
1192       if (csymbols == NULL)
1193 	return -1;
1194       abfd->tdata.srec_data->csymbols = csymbols;
1195 
1196       for (s = abfd->tdata.srec_data->symbols, c = csymbols;
1197 	   s != NULL;
1198 	   s = s->next, ++c)
1199 	{
1200 	  c->the_bfd = abfd;
1201 	  c->name = s->name;
1202 	  c->value = s->val;
1203 	  c->flags = BSF_GLOBAL;
1204 	  c->section = bfd_abs_section_ptr;
1205 	  c->udata.p = NULL;
1206 	}
1207     }
1208 
1209   for (i = 0; i < symcount; i++)
1210     *alocation++ = csymbols++;
1211   *alocation = NULL;
1212 
1213   return symcount;
1214 }
1215 
1216 static void
1217 srec_get_symbol_info (bfd *ignore_abfd ATTRIBUTE_UNUSED,
1218 		      asymbol *symbol,
1219 		      symbol_info *ret)
1220 {
1221   bfd_symbol_info (symbol, ret);
1222 }
1223 
1224 static void
1225 srec_print_symbol (bfd *abfd,
1226 		   void * afile,
1227 		   asymbol *symbol,
1228 		   bfd_print_symbol_type how)
1229 {
1230   FILE *file = (FILE *) afile;
1231 
1232   switch (how)
1233     {
1234     case bfd_print_symbol_name:
1235       fprintf (file, "%s", symbol->name);
1236       break;
1237     default:
1238       bfd_print_symbol_vandf (abfd, (void *) file, symbol);
1239       fprintf (file, " %-5s %s",
1240 	       symbol->section->name,
1241 	       symbol->name);
1242     }
1243 }
1244 
1245 #define	srec_close_and_cleanup			  _bfd_generic_close_and_cleanup
1246 #define srec_bfd_free_cached_info		  _bfd_generic_bfd_free_cached_info
1247 #define srec_new_section_hook			  _bfd_generic_new_section_hook
1248 #define srec_bfd_is_target_special_symbol	  _bfd_bool_bfd_asymbol_false
1249 #define srec_bfd_is_local_label_name		  bfd_generic_is_local_label_name
1250 #define srec_get_lineno				  _bfd_nosymbols_get_lineno
1251 #define srec_find_nearest_line			  _bfd_nosymbols_find_nearest_line
1252 #define srec_find_nearest_line_with_alt		  _bfd_nosymbols_find_nearest_line_with_alt
1253 #define srec_find_line				  _bfd_nosymbols_find_line
1254 #define srec_find_inliner_info			  _bfd_nosymbols_find_inliner_info
1255 #define srec_make_empty_symbol			  _bfd_generic_make_empty_symbol
1256 #define srec_get_symbol_version_string		  _bfd_nosymbols_get_symbol_version_string
1257 #define srec_bfd_make_debug_symbol		  _bfd_nosymbols_bfd_make_debug_symbol
1258 #define srec_read_minisymbols			  _bfd_generic_read_minisymbols
1259 #define srec_minisymbol_to_symbol		  _bfd_generic_minisymbol_to_symbol
1260 #define srec_get_section_contents_in_window	  _bfd_generic_get_section_contents_in_window
1261 #define srec_bfd_get_relocated_section_contents	  bfd_generic_get_relocated_section_contents
1262 #define srec_bfd_relax_section			  bfd_generic_relax_section
1263 #define srec_bfd_gc_sections			  bfd_generic_gc_sections
1264 #define srec_bfd_lookup_section_flags		  bfd_generic_lookup_section_flags
1265 #define srec_bfd_merge_sections			  bfd_generic_merge_sections
1266 #define srec_bfd_is_group_section		  bfd_generic_is_group_section
1267 #define srec_bfd_group_name			  bfd_generic_group_name
1268 #define srec_bfd_discard_group			  bfd_generic_discard_group
1269 #define srec_section_already_linked		  _bfd_generic_section_already_linked
1270 #define srec_bfd_define_common_symbol		  bfd_generic_define_common_symbol
1271 #define srec_bfd_link_hide_symbol		  _bfd_generic_link_hide_symbol
1272 #define srec_bfd_define_start_stop		  bfd_generic_define_start_stop
1273 #define srec_bfd_link_hash_table_create		  _bfd_generic_link_hash_table_create
1274 #define srec_bfd_link_add_symbols		  _bfd_generic_link_add_symbols
1275 #define srec_bfd_link_just_syms			  _bfd_generic_link_just_syms
1276 #define srec_bfd_copy_link_hash_symbol_type	  _bfd_generic_copy_link_hash_symbol_type
1277 #define srec_bfd_final_link			  _bfd_generic_final_link
1278 #define srec_bfd_link_split_section		  _bfd_generic_link_split_section
1279 #define srec_bfd_link_check_relocs		  _bfd_generic_link_check_relocs
1280 
1281 const bfd_target srec_vec =
1282 {
1283   "srec",			/* Name.  */
1284   bfd_target_srec_flavour,
1285   BFD_ENDIAN_UNKNOWN,		/* Target byte order.  */
1286   BFD_ENDIAN_UNKNOWN,		/* Target headers byte order.  */
1287   (HAS_RELOC | EXEC_P |		/* Object flags.  */
1288    HAS_LINENO | HAS_DEBUG |
1289    HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
1290   (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS
1291    | SEC_ALLOC | SEC_LOAD | SEC_RELOC),	/* Section flags.  */
1292   0,				/* Leading underscore.  */
1293   ' ',				/* AR_pad_char.  */
1294   16,				/* AR_max_namelen.  */
1295   0,				/* match priority.  */
1296   TARGET_KEEP_UNUSED_SECTION_SYMBOLS, /* keep unused section symbols.  */
1297   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
1298   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
1299   bfd_getb16, bfd_getb_signed_16, bfd_putb16,	/* Data.  */
1300   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
1301   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
1302   bfd_getb16, bfd_getb_signed_16, bfd_putb16,	/* Hdrs.  */
1303 
1304   {
1305     _bfd_dummy_target,
1306     srec_object_p,		/* bfd_check_format.  */
1307     _bfd_dummy_target,
1308     _bfd_dummy_target,
1309   },
1310   {
1311     _bfd_bool_bfd_false_error,
1312     srec_mkobject,
1313     _bfd_generic_mkarchive,
1314     _bfd_bool_bfd_false_error,
1315   },
1316   {				/* bfd_write_contents.  */
1317     _bfd_bool_bfd_false_error,
1318     srec_write_object_contents,
1319     _bfd_write_archive_contents,
1320     _bfd_bool_bfd_false_error,
1321   },
1322 
1323   BFD_JUMP_TABLE_GENERIC (srec),
1324   BFD_JUMP_TABLE_COPY (_bfd_generic),
1325   BFD_JUMP_TABLE_CORE (_bfd_nocore),
1326   BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
1327   BFD_JUMP_TABLE_SYMBOLS (srec),
1328   BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
1329   BFD_JUMP_TABLE_WRITE (srec),
1330   BFD_JUMP_TABLE_LINK (srec),
1331   BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
1332 
1333   NULL,
1334 
1335   NULL
1336 };
1337 
1338 const bfd_target symbolsrec_vec =
1339 {
1340   "symbolsrec",			/* Name.  */
1341   bfd_target_srec_flavour,
1342   BFD_ENDIAN_UNKNOWN,		/* Target byte order.  */
1343   BFD_ENDIAN_UNKNOWN,		/* Target headers byte order.  */
1344   (HAS_RELOC | EXEC_P |		/* Object flags.  */
1345    HAS_LINENO | HAS_DEBUG |
1346    HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
1347   (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS
1348    | SEC_ALLOC | SEC_LOAD | SEC_RELOC),	/* Section flags.  */
1349   0,				/* Leading underscore.  */
1350   ' ',				/* AR_pad_char.  */
1351   16,				/* AR_max_namelen.  */
1352   0,				/* match priority.  */
1353   TARGET_KEEP_UNUSED_SECTION_SYMBOLS, /* keep unused section symbols.  */
1354   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
1355   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
1356   bfd_getb16, bfd_getb_signed_16, bfd_putb16,	/* Data.  */
1357   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
1358   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
1359   bfd_getb16, bfd_getb_signed_16, bfd_putb16,	/* Headers.  */
1360 
1361   {
1362     _bfd_dummy_target,
1363     symbolsrec_object_p,	/* bfd_check_format.  */
1364     _bfd_dummy_target,
1365     _bfd_dummy_target,
1366   },
1367   {
1368     _bfd_bool_bfd_false_error,
1369     srec_mkobject,
1370     _bfd_generic_mkarchive,
1371     _bfd_bool_bfd_false_error,
1372   },
1373   {				/* bfd_write_contents.  */
1374     _bfd_bool_bfd_false_error,
1375     symbolsrec_write_object_contents,
1376     _bfd_write_archive_contents,
1377     _bfd_bool_bfd_false_error,
1378   },
1379 
1380   BFD_JUMP_TABLE_GENERIC (srec),
1381   BFD_JUMP_TABLE_COPY (_bfd_generic),
1382   BFD_JUMP_TABLE_CORE (_bfd_nocore),
1383   BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
1384   BFD_JUMP_TABLE_SYMBOLS (srec),
1385   BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
1386   BFD_JUMP_TABLE_WRITE (srec),
1387   BFD_JUMP_TABLE_LINK (srec),
1388   BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
1389 
1390   NULL,
1391 
1392   NULL
1393 };
1394