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