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