xref: /netbsd-src/external/gpl3/binutils.old/dist/bfd/srec.c (revision e992f068c547fd6e84b3f104dc2340adcc955732)
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
srec_init(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
srec_mkobject(bfd * abfd)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
srec_get_byte(bfd * abfd,bool * errorptr)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
srec_bad_byte(bfd * abfd,unsigned int lineno,int c,bool error)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
srec_new_symbol(bfd * abfd,const char * name,bfd_vma val)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
srec_scan(bfd * abfd)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
srec_object_p(bfd * abfd)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
symbolsrec_object_p(bfd * abfd)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
srec_read_section(bfd * abfd,asection * section,bfd_byte * contents)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
srec_get_section_contents(bfd * abfd,asection * section,void * location,file_ptr offset,bfd_size_type count)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
srec_set_arch_mach(bfd * abfd,enum bfd_architecture arch,unsigned long mach)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
srec_set_section_contents(bfd * abfd,sec_ptr section,const void * location,file_ptr offset,bfd_size_type bytes_to_do)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
srec_write_record(bfd * abfd,unsigned int type,bfd_vma address,const bfd_byte * data,const bfd_byte * end)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
srec_write_header(bfd * abfd)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
srec_write_section(bfd * abfd,tdata_type * tdata,srec_data_list_type * list)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
srec_write_terminator(bfd * abfd,tdata_type * tdata)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
srec_write_symbols(bfd * abfd)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], *p;
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_vma (buf + 2, (s->value
1107 				     + s->section->output_section->lma
1108 				     + s->section->output_offset));
1109 	      p = buf + 2;
1110 	      while (p[0] == '0' && p[1] != 0)
1111 		p++;
1112 	      len = strlen (p);
1113 	      p[len] = '\r';
1114 	      p[len + 1] = '\n';
1115 	      *--p = '$';
1116 	      *--p = ' ';
1117 	      len += 4;
1118 	      if (bfd_bwrite (p, len, abfd) != len)
1119 		return false;
1120 	    }
1121 	}
1122       if (bfd_bwrite ("$$ \r\n", (bfd_size_type) 5, abfd) != 5)
1123 	return false;
1124     }
1125 
1126   return true;
1127 }
1128 
1129 static bool
internal_srec_write_object_contents(bfd * abfd,int symbols)1130 internal_srec_write_object_contents (bfd *abfd, int symbols)
1131 {
1132   tdata_type *tdata = abfd->tdata.srec_data;
1133   srec_data_list_type *list;
1134 
1135   if (symbols)
1136     {
1137       if (! srec_write_symbols (abfd))
1138 	return false;
1139     }
1140 
1141   if (! srec_write_header (abfd))
1142     return false;
1143 
1144   /* Now wander though all the sections provided and output them.  */
1145   list = tdata->head;
1146 
1147   while (list != (srec_data_list_type *) NULL)
1148     {
1149       if (! srec_write_section (abfd, tdata, list))
1150 	return false;
1151       list = list->next;
1152     }
1153   return srec_write_terminator (abfd, tdata);
1154 }
1155 
1156 static bool
srec_write_object_contents(bfd * abfd)1157 srec_write_object_contents (bfd *abfd)
1158 {
1159   return internal_srec_write_object_contents (abfd, 0);
1160 }
1161 
1162 static bool
symbolsrec_write_object_contents(bfd * abfd)1163 symbolsrec_write_object_contents (bfd *abfd)
1164 {
1165   return internal_srec_write_object_contents (abfd, 1);
1166 }
1167 
1168 static int
srec_sizeof_headers(bfd * abfd ATTRIBUTE_UNUSED,struct bfd_link_info * info ATTRIBUTE_UNUSED)1169 srec_sizeof_headers (bfd *abfd ATTRIBUTE_UNUSED,
1170 		     struct bfd_link_info *info ATTRIBUTE_UNUSED)
1171 {
1172   return 0;
1173 }
1174 
1175 /* Return the amount of memory needed to read the symbol table.  */
1176 
1177 static long
srec_get_symtab_upper_bound(bfd * abfd)1178 srec_get_symtab_upper_bound (bfd *abfd)
1179 {
1180   return (bfd_get_symcount (abfd) + 1) * sizeof (asymbol *);
1181 }
1182 
1183 /* Return the symbol table.  */
1184 
1185 static long
srec_canonicalize_symtab(bfd * abfd,asymbol ** alocation)1186 srec_canonicalize_symtab (bfd *abfd, asymbol **alocation)
1187 {
1188   bfd_size_type symcount = bfd_get_symcount (abfd);
1189   asymbol *csymbols;
1190   unsigned int i;
1191 
1192   csymbols = abfd->tdata.srec_data->csymbols;
1193   if (csymbols == NULL && symcount != 0)
1194     {
1195       asymbol *c;
1196       struct srec_symbol *s;
1197 
1198       csymbols = (asymbol *) bfd_alloc (abfd, symcount * sizeof (asymbol));
1199       if (csymbols == NULL)
1200 	return -1;
1201       abfd->tdata.srec_data->csymbols = csymbols;
1202 
1203       for (s = abfd->tdata.srec_data->symbols, c = csymbols;
1204 	   s != NULL;
1205 	   s = s->next, ++c)
1206 	{
1207 	  c->the_bfd = abfd;
1208 	  c->name = s->name;
1209 	  c->value = s->val;
1210 	  c->flags = BSF_GLOBAL;
1211 	  c->section = bfd_abs_section_ptr;
1212 	  c->udata.p = NULL;
1213 	}
1214     }
1215 
1216   for (i = 0; i < symcount; i++)
1217     *alocation++ = csymbols++;
1218   *alocation = NULL;
1219 
1220   return symcount;
1221 }
1222 
1223 static void
srec_get_symbol_info(bfd * ignore_abfd ATTRIBUTE_UNUSED,asymbol * symbol,symbol_info * ret)1224 srec_get_symbol_info (bfd *ignore_abfd ATTRIBUTE_UNUSED,
1225 		      asymbol *symbol,
1226 		      symbol_info *ret)
1227 {
1228   bfd_symbol_info (symbol, ret);
1229 }
1230 
1231 static void
srec_print_symbol(bfd * abfd,void * afile,asymbol * symbol,bfd_print_symbol_type how)1232 srec_print_symbol (bfd *abfd,
1233 		   void * afile,
1234 		   asymbol *symbol,
1235 		   bfd_print_symbol_type how)
1236 {
1237   FILE *file = (FILE *) afile;
1238 
1239   switch (how)
1240     {
1241     case bfd_print_symbol_name:
1242       fprintf (file, "%s", symbol->name);
1243       break;
1244     default:
1245       bfd_print_symbol_vandf (abfd, (void *) file, symbol);
1246       fprintf (file, " %-5s %s",
1247 	       symbol->section->name,
1248 	       symbol->name);
1249     }
1250 }
1251 
1252 #define	srec_close_and_cleanup			  _bfd_generic_close_and_cleanup
1253 #define srec_bfd_free_cached_info		  _bfd_generic_bfd_free_cached_info
1254 #define srec_new_section_hook			  _bfd_generic_new_section_hook
1255 #define srec_bfd_is_target_special_symbol	  _bfd_bool_bfd_asymbol_false
1256 #define srec_bfd_is_local_label_name		  bfd_generic_is_local_label_name
1257 #define srec_get_lineno				  _bfd_nosymbols_get_lineno
1258 #define srec_find_nearest_line			  _bfd_nosymbols_find_nearest_line
1259 #define srec_find_line				  _bfd_nosymbols_find_line
1260 #define srec_find_inliner_info			  _bfd_nosymbols_find_inliner_info
1261 #define srec_make_empty_symbol			  _bfd_generic_make_empty_symbol
1262 #define srec_get_symbol_version_string		  _bfd_nosymbols_get_symbol_version_string
1263 #define srec_bfd_make_debug_symbol		  _bfd_nosymbols_bfd_make_debug_symbol
1264 #define srec_read_minisymbols			  _bfd_generic_read_minisymbols
1265 #define srec_minisymbol_to_symbol		  _bfd_generic_minisymbol_to_symbol
1266 #define srec_get_section_contents_in_window	  _bfd_generic_get_section_contents_in_window
1267 #define srec_bfd_get_relocated_section_contents	  bfd_generic_get_relocated_section_contents
1268 #define srec_bfd_relax_section			  bfd_generic_relax_section
1269 #define srec_bfd_gc_sections			  bfd_generic_gc_sections
1270 #define srec_bfd_lookup_section_flags		  bfd_generic_lookup_section_flags
1271 #define srec_bfd_merge_sections			  bfd_generic_merge_sections
1272 #define srec_bfd_is_group_section		  bfd_generic_is_group_section
1273 #define srec_bfd_group_name			  bfd_generic_group_name
1274 #define srec_bfd_discard_group			  bfd_generic_discard_group
1275 #define srec_section_already_linked		  _bfd_generic_section_already_linked
1276 #define srec_bfd_define_common_symbol		  bfd_generic_define_common_symbol
1277 #define srec_bfd_link_hide_symbol		  _bfd_generic_link_hide_symbol
1278 #define srec_bfd_define_start_stop		  bfd_generic_define_start_stop
1279 #define srec_bfd_link_hash_table_create		  _bfd_generic_link_hash_table_create
1280 #define srec_bfd_link_add_symbols		  _bfd_generic_link_add_symbols
1281 #define srec_bfd_link_just_syms			  _bfd_generic_link_just_syms
1282 #define srec_bfd_copy_link_hash_symbol_type	  _bfd_generic_copy_link_hash_symbol_type
1283 #define srec_bfd_final_link			  _bfd_generic_final_link
1284 #define srec_bfd_link_split_section		  _bfd_generic_link_split_section
1285 #define srec_bfd_link_check_relocs		  _bfd_generic_link_check_relocs
1286 
1287 const bfd_target srec_vec =
1288 {
1289   "srec",			/* Name.  */
1290   bfd_target_srec_flavour,
1291   BFD_ENDIAN_UNKNOWN,		/* Target byte order.  */
1292   BFD_ENDIAN_UNKNOWN,		/* Target headers byte order.  */
1293   (HAS_RELOC | EXEC_P |		/* Object flags.  */
1294    HAS_LINENO | HAS_DEBUG |
1295    HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
1296   (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS
1297    | SEC_ALLOC | SEC_LOAD | SEC_RELOC),	/* Section flags.  */
1298   0,				/* Leading underscore.  */
1299   ' ',				/* AR_pad_char.  */
1300   16,				/* AR_max_namelen.  */
1301   0,				/* match priority.  */
1302   TARGET_KEEP_UNUSED_SECTION_SYMBOLS, /* keep unused section symbols.  */
1303   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
1304   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
1305   bfd_getb16, bfd_getb_signed_16, bfd_putb16,	/* Data.  */
1306   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
1307   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
1308   bfd_getb16, bfd_getb_signed_16, bfd_putb16,	/* Hdrs.  */
1309 
1310   {
1311     _bfd_dummy_target,
1312     srec_object_p,		/* bfd_check_format.  */
1313     _bfd_dummy_target,
1314     _bfd_dummy_target,
1315   },
1316   {
1317     _bfd_bool_bfd_false_error,
1318     srec_mkobject,
1319     _bfd_generic_mkarchive,
1320     _bfd_bool_bfd_false_error,
1321   },
1322   {				/* bfd_write_contents.  */
1323     _bfd_bool_bfd_false_error,
1324     srec_write_object_contents,
1325     _bfd_write_archive_contents,
1326     _bfd_bool_bfd_false_error,
1327   },
1328 
1329   BFD_JUMP_TABLE_GENERIC (srec),
1330   BFD_JUMP_TABLE_COPY (_bfd_generic),
1331   BFD_JUMP_TABLE_CORE (_bfd_nocore),
1332   BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
1333   BFD_JUMP_TABLE_SYMBOLS (srec),
1334   BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
1335   BFD_JUMP_TABLE_WRITE (srec),
1336   BFD_JUMP_TABLE_LINK (srec),
1337   BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
1338 
1339   NULL,
1340 
1341   NULL
1342 };
1343 
1344 const bfd_target symbolsrec_vec =
1345 {
1346   "symbolsrec",			/* Name.  */
1347   bfd_target_srec_flavour,
1348   BFD_ENDIAN_UNKNOWN,		/* Target byte order.  */
1349   BFD_ENDIAN_UNKNOWN,		/* Target headers byte order.  */
1350   (HAS_RELOC | EXEC_P |		/* Object flags.  */
1351    HAS_LINENO | HAS_DEBUG |
1352    HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
1353   (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS
1354    | SEC_ALLOC | SEC_LOAD | SEC_RELOC),	/* Section flags.  */
1355   0,				/* Leading underscore.  */
1356   ' ',				/* AR_pad_char.  */
1357   16,				/* AR_max_namelen.  */
1358   0,				/* match priority.  */
1359   TARGET_KEEP_UNUSED_SECTION_SYMBOLS, /* keep unused section symbols.  */
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_bool_bfd_false_error,
1375     srec_mkobject,
1376     _bfd_generic_mkarchive,
1377     _bfd_bool_bfd_false_error,
1378   },
1379   {				/* bfd_write_contents.  */
1380     _bfd_bool_bfd_false_error,
1381     symbolsrec_write_object_contents,
1382     _bfd_write_archive_contents,
1383     _bfd_bool_bfd_false_error,
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