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