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