xref: /dragonfly/contrib/binutils-2.34/bfd/srec.c (revision ec21d9fb)
1 /* BFD back-end for s-record objects.
2    Copyright (C) 1990-2020 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 bfd_boolean _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 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 
192 static bfd_boolean
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, 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 
236 static void
237 srec_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 	(_("%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 bfd_boolean
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 bfd_boolean
296 srec_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 (_("%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 		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 		      (_("%pB:%d: bad checksum in S-record file"),
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 		      (_("%pB:%d: bad checksum in S-record file"),
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 
649 static const bfd_target *
650 srec_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 
684 static const bfd_target *
685 symbolsrec_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 
719 static bfd_boolean
720 srec_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 
833 static bfd_boolean
834 srec_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 
869 static bfd_boolean
870 srec_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 
881 static bfd_boolean
882 srec_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, NULL);
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       /* If _bfd_srec_forceS3 is TRUE then always select S3 records,
908 	 regardless of the size of the addresses.  */
909       if (_bfd_srec_forceS3)
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 
953 static bfd_boolean
954 srec_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 
1015 static bfd_boolean
1016 srec_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 
1029 static bfd_boolean
1030 srec_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 (_bfd_srec_len == 0)
1044     _bfd_srec_len = 1;
1045   else if (_bfd_srec_len > MAXCHUNK - tdata->type - 2)
1046     _bfd_srec_len = 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 > _bfd_srec_len)
1054 	octets_this_chunk = _bfd_srec_len;
1055 
1056       address = list->where + (octets_written
1057 			       / bfd_octets_per_byte (abfd, NULL));
1058 
1059       if (! srec_write_record (abfd,
1060 			       tdata->type,
1061 			       address,
1062 			       location,
1063 			       location + octets_this_chunk))
1064 	return FALSE;
1065 
1066       octets_written += octets_this_chunk;
1067       location += octets_this_chunk;
1068     }
1069 
1070   return TRUE;
1071 }
1072 
1073 static bfd_boolean
1074 srec_write_terminator (bfd *abfd, tdata_type *tdata)
1075 {
1076   return srec_write_record (abfd, 10 - tdata->type,
1077 			    abfd->start_address, NULL, NULL);
1078 }
1079 
1080 static bfd_boolean
1081 srec_write_symbols (bfd *abfd)
1082 {
1083   /* Dump out the symbols of a bfd.  */
1084   int i;
1085   int count = bfd_get_symcount (abfd);
1086 
1087   if (count)
1088     {
1089       bfd_size_type len;
1090       asymbol **table = bfd_get_outsymbols (abfd);
1091 
1092       len = strlen (abfd->filename);
1093       if (bfd_bwrite ("$$ ", (bfd_size_type) 3, abfd) != 3
1094 	  || bfd_bwrite (abfd->filename, len, abfd) != len
1095 	  || bfd_bwrite ("\r\n", (bfd_size_type) 2, abfd) != 2)
1096 	return FALSE;
1097 
1098       for (i = 0; i < count; i++)
1099 	{
1100 	  asymbol *s = table[i];
1101 	  if (! bfd_is_local_label (abfd, s)
1102 	      && (s->flags & BSF_DEBUGGING) == 0)
1103 	    {
1104 	      /* Just dump out non debug symbols.  */
1105 	      char buf[43], *p;
1106 
1107 	      len = strlen (s->name);
1108 	      if (bfd_bwrite ("  ", (bfd_size_type) 2, abfd) != 2
1109 		  || bfd_bwrite (s->name, len, abfd) != len)
1110 		return FALSE;
1111 
1112 	      sprintf_vma (buf + 2, (s->value
1113 				     + s->section->output_section->lma
1114 				     + s->section->output_offset));
1115 	      p = buf + 2;
1116 	      while (p[0] == '0' && p[1] != 0)
1117 		p++;
1118 	      len = strlen (p);
1119 	      p[len] = '\r';
1120 	      p[len + 1] = '\n';
1121 	      *--p = '$';
1122 	      *--p = ' ';
1123 	      len += 4;
1124 	      if (bfd_bwrite (p, len, abfd) != len)
1125 		return FALSE;
1126 	    }
1127 	}
1128       if (bfd_bwrite ("$$ \r\n", (bfd_size_type) 5, abfd) != 5)
1129 	return FALSE;
1130     }
1131 
1132   return TRUE;
1133 }
1134 
1135 static bfd_boolean
1136 internal_srec_write_object_contents (bfd *abfd, int symbols)
1137 {
1138   tdata_type *tdata = abfd->tdata.srec_data;
1139   srec_data_list_type *list;
1140 
1141   if (symbols)
1142     {
1143       if (! srec_write_symbols (abfd))
1144 	return FALSE;
1145     }
1146 
1147   if (! srec_write_header (abfd))
1148     return FALSE;
1149 
1150   /* Now wander though all the sections provided and output them.  */
1151   list = tdata->head;
1152 
1153   while (list != (srec_data_list_type *) NULL)
1154     {
1155       if (! srec_write_section (abfd, tdata, list))
1156 	return FALSE;
1157       list = list->next;
1158     }
1159   return srec_write_terminator (abfd, tdata);
1160 }
1161 
1162 static bfd_boolean
1163 srec_write_object_contents (bfd *abfd)
1164 {
1165   return internal_srec_write_object_contents (abfd, 0);
1166 }
1167 
1168 static bfd_boolean
1169 symbolsrec_write_object_contents (bfd *abfd)
1170 {
1171   return internal_srec_write_object_contents (abfd, 1);
1172 }
1173 
1174 static int
1175 srec_sizeof_headers (bfd *abfd ATTRIBUTE_UNUSED,
1176 		     struct bfd_link_info *info ATTRIBUTE_UNUSED)
1177 {
1178   return 0;
1179 }
1180 
1181 /* Return the amount of memory needed to read the symbol table.  */
1182 
1183 static long
1184 srec_get_symtab_upper_bound (bfd *abfd)
1185 {
1186   return (bfd_get_symcount (abfd) + 1) * sizeof (asymbol *);
1187 }
1188 
1189 /* Return the symbol table.  */
1190 
1191 static long
1192 srec_canonicalize_symtab (bfd *abfd, asymbol **alocation)
1193 {
1194   bfd_size_type symcount = bfd_get_symcount (abfd);
1195   asymbol *csymbols;
1196   unsigned int i;
1197 
1198   csymbols = abfd->tdata.srec_data->csymbols;
1199   if (csymbols == NULL && symcount != 0)
1200     {
1201       asymbol *c;
1202       struct srec_symbol *s;
1203 
1204       csymbols = (asymbol *) bfd_alloc (abfd, symcount * sizeof (asymbol));
1205       if (csymbols == NULL)
1206 	return -1;
1207       abfd->tdata.srec_data->csymbols = csymbols;
1208 
1209       for (s = abfd->tdata.srec_data->symbols, c = csymbols;
1210 	   s != NULL;
1211 	   s = s->next, ++c)
1212 	{
1213 	  c->the_bfd = abfd;
1214 	  c->name = s->name;
1215 	  c->value = s->val;
1216 	  c->flags = BSF_GLOBAL;
1217 	  c->section = bfd_abs_section_ptr;
1218 	  c->udata.p = NULL;
1219 	}
1220     }
1221 
1222   for (i = 0; i < symcount; i++)
1223     *alocation++ = csymbols++;
1224   *alocation = NULL;
1225 
1226   return symcount;
1227 }
1228 
1229 static void
1230 srec_get_symbol_info (bfd *ignore_abfd ATTRIBUTE_UNUSED,
1231 		      asymbol *symbol,
1232 		      symbol_info *ret)
1233 {
1234   bfd_symbol_info (symbol, ret);
1235 }
1236 
1237 static void
1238 srec_print_symbol (bfd *abfd,
1239 		   void * afile,
1240 		   asymbol *symbol,
1241 		   bfd_print_symbol_type how)
1242 {
1243   FILE *file = (FILE *) afile;
1244 
1245   switch (how)
1246     {
1247     case bfd_print_symbol_name:
1248       fprintf (file, "%s", symbol->name);
1249       break;
1250     default:
1251       bfd_print_symbol_vandf (abfd, (void *) file, symbol);
1252       fprintf (file, " %-5s %s",
1253 	       symbol->section->name,
1254 	       symbol->name);
1255     }
1256 }
1257 
1258 #define	srec_close_and_cleanup			  _bfd_generic_close_and_cleanup
1259 #define srec_bfd_free_cached_info		  _bfd_generic_bfd_free_cached_info
1260 #define srec_new_section_hook			  _bfd_generic_new_section_hook
1261 #define srec_bfd_is_target_special_symbol	  _bfd_bool_bfd_asymbol_false
1262 #define srec_bfd_is_local_label_name		  bfd_generic_is_local_label_name
1263 #define srec_get_lineno				  _bfd_nosymbols_get_lineno
1264 #define srec_find_nearest_line			  _bfd_nosymbols_find_nearest_line
1265 #define srec_find_line				  _bfd_nosymbols_find_line
1266 #define srec_find_inliner_info			  _bfd_nosymbols_find_inliner_info
1267 #define srec_make_empty_symbol			  _bfd_generic_make_empty_symbol
1268 #define srec_get_symbol_version_string		  _bfd_nosymbols_get_symbol_version_string
1269 #define srec_bfd_make_debug_symbol		  _bfd_nosymbols_bfd_make_debug_symbol
1270 #define srec_read_minisymbols			  _bfd_generic_read_minisymbols
1271 #define srec_minisymbol_to_symbol		  _bfd_generic_minisymbol_to_symbol
1272 #define srec_get_section_contents_in_window	  _bfd_generic_get_section_contents_in_window
1273 #define srec_bfd_get_relocated_section_contents	  bfd_generic_get_relocated_section_contents
1274 #define srec_bfd_relax_section			  bfd_generic_relax_section
1275 #define srec_bfd_gc_sections			  bfd_generic_gc_sections
1276 #define srec_bfd_lookup_section_flags		  bfd_generic_lookup_section_flags
1277 #define srec_bfd_merge_sections			  bfd_generic_merge_sections
1278 #define srec_bfd_is_group_section		  bfd_generic_is_group_section
1279 #define srec_bfd_group_name			  bfd_generic_group_name
1280 #define srec_bfd_discard_group			  bfd_generic_discard_group
1281 #define srec_section_already_linked		  _bfd_generic_section_already_linked
1282 #define srec_bfd_define_common_symbol		  bfd_generic_define_common_symbol
1283 #define srec_bfd_link_hide_symbol		  _bfd_generic_link_hide_symbol
1284 #define srec_bfd_define_start_stop		  bfd_generic_define_start_stop
1285 #define srec_bfd_link_hash_table_create		  _bfd_generic_link_hash_table_create
1286 #define srec_bfd_link_add_symbols		  _bfd_generic_link_add_symbols
1287 #define srec_bfd_link_just_syms			  _bfd_generic_link_just_syms
1288 #define srec_bfd_copy_link_hash_symbol_type	  _bfd_generic_copy_link_hash_symbol_type
1289 #define srec_bfd_final_link			  _bfd_generic_final_link
1290 #define srec_bfd_link_split_section		  _bfd_generic_link_split_section
1291 #define srec_bfd_link_check_relocs		  _bfd_generic_link_check_relocs
1292 
1293 const bfd_target srec_vec =
1294 {
1295   "srec",			/* Name.  */
1296   bfd_target_srec_flavour,
1297   BFD_ENDIAN_UNKNOWN,		/* Target byte order.  */
1298   BFD_ENDIAN_UNKNOWN,		/* Target headers byte order.  */
1299   (HAS_RELOC | EXEC_P |		/* Object flags.  */
1300    HAS_LINENO | HAS_DEBUG |
1301    HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
1302   (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS
1303    | SEC_ALLOC | SEC_LOAD | SEC_RELOC),	/* Section flags.  */
1304   0,				/* Leading underscore.  */
1305   ' ',				/* AR_pad_char.  */
1306   16,				/* AR_max_namelen.  */
1307   0,				/* match priority.  */
1308   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
1309   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
1310   bfd_getb16, bfd_getb_signed_16, bfd_putb16,	/* Data.  */
1311   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
1312   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
1313   bfd_getb16, bfd_getb_signed_16, bfd_putb16,	/* Hdrs.  */
1314 
1315   {
1316     _bfd_dummy_target,
1317     srec_object_p,		/* bfd_check_format.  */
1318     _bfd_dummy_target,
1319     _bfd_dummy_target,
1320   },
1321   {
1322     _bfd_bool_bfd_false_error,
1323     srec_mkobject,
1324     _bfd_generic_mkarchive,
1325     _bfd_bool_bfd_false_error,
1326   },
1327   {				/* bfd_write_contents.  */
1328     _bfd_bool_bfd_false_error,
1329     srec_write_object_contents,
1330     _bfd_write_archive_contents,
1331     _bfd_bool_bfd_false_error,
1332   },
1333 
1334   BFD_JUMP_TABLE_GENERIC (srec),
1335   BFD_JUMP_TABLE_COPY (_bfd_generic),
1336   BFD_JUMP_TABLE_CORE (_bfd_nocore),
1337   BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
1338   BFD_JUMP_TABLE_SYMBOLS (srec),
1339   BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
1340   BFD_JUMP_TABLE_WRITE (srec),
1341   BFD_JUMP_TABLE_LINK (srec),
1342   BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
1343 
1344   NULL,
1345 
1346   NULL
1347 };
1348 
1349 const bfd_target symbolsrec_vec =
1350 {
1351   "symbolsrec",			/* Name.  */
1352   bfd_target_srec_flavour,
1353   BFD_ENDIAN_UNKNOWN,		/* Target byte order.  */
1354   BFD_ENDIAN_UNKNOWN,		/* Target headers byte order.  */
1355   (HAS_RELOC | EXEC_P |		/* Object flags.  */
1356    HAS_LINENO | HAS_DEBUG |
1357    HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
1358   (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS
1359    | SEC_ALLOC | SEC_LOAD | SEC_RELOC),	/* Section flags.  */
1360   0,				/* Leading underscore.  */
1361   ' ',				/* AR_pad_char.  */
1362   16,				/* AR_max_namelen.  */
1363   0,				/* match priority.  */
1364   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
1365   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
1366   bfd_getb16, bfd_getb_signed_16, bfd_putb16,	/* Data.  */
1367   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
1368   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
1369   bfd_getb16, bfd_getb_signed_16, bfd_putb16,	/* Headers.  */
1370 
1371   {
1372     _bfd_dummy_target,
1373     symbolsrec_object_p,	/* bfd_check_format.  */
1374     _bfd_dummy_target,
1375     _bfd_dummy_target,
1376   },
1377   {
1378     _bfd_bool_bfd_false_error,
1379     srec_mkobject,
1380     _bfd_generic_mkarchive,
1381     _bfd_bool_bfd_false_error,
1382   },
1383   {				/* bfd_write_contents.  */
1384     _bfd_bool_bfd_false_error,
1385     symbolsrec_write_object_contents,
1386     _bfd_write_archive_contents,
1387     _bfd_bool_bfd_false_error,
1388   },
1389 
1390   BFD_JUMP_TABLE_GENERIC (srec),
1391   BFD_JUMP_TABLE_COPY (_bfd_generic),
1392   BFD_JUMP_TABLE_CORE (_bfd_nocore),
1393   BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
1394   BFD_JUMP_TABLE_SYMBOLS (srec),
1395   BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
1396   BFD_JUMP_TABLE_WRITE (srec),
1397   BFD_JUMP_TABLE_LINK (srec),
1398   BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
1399 
1400   NULL,
1401 
1402   NULL
1403 };
1404