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