* opncls.c (bfd_alloc_by_size_t): Set bfd_error_no_memory if
[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 *) malloc (bytes * 2);
465                 if (buf == NULL)
466                   {
467                     bfd_set_error (bfd_error_no_memory);
468                     goto error_return;
469                   }
470                 bufsize = bytes * 2;
471               }
472
473             if (bfd_read (buf, 1, bytes * 2, abfd) != bytes * 2)
474               goto error_return;
475
476             /* Ignore the checksum byte.  */
477             --bytes;
478
479             address = 0;
480             data = buf;
481             switch (hdr[0])
482               {
483               case '0':
484               case '5':
485                 /* Prologue--ignore the file name, but stop building a
486                    section at this point.  */
487                 sec = NULL;
488                 break;
489
490               case '3':
491                 address = HEX (data);
492                 data += 2;
493                 --bytes;
494                 /* Fall through.  */
495               case '2':
496                 address = (address << 8) | HEX (data);
497                 data += 2;
498                 --bytes;
499                 /* Fall through.  */
500               case '1':
501                 address = (address << 8) | HEX (data);
502                 data += 2;
503                 address = (address << 8) | HEX (data);
504                 data += 2;
505                 bytes -= 2;
506
507                 if (sec != NULL
508                     && sec->vma + sec->_raw_size == address)
509                   {
510                     /* This data goes at the end of the section we are
511                        currently building.  */
512                     sec->_raw_size += bytes;
513                   }
514                 else
515                   {
516                     char secbuf[20];
517                     char *secname;
518
519                     sprintf (secbuf, ".sec%d", bfd_count_sections (abfd) + 1);
520                     secname = (char *) bfd_alloc (abfd, strlen (secbuf) + 1);
521                     strcpy (secname, secbuf);
522                     sec = bfd_make_section (abfd, secname);
523                     if (sec == NULL)
524                       goto error_return;
525                     sec->flags = SEC_HAS_CONTENTS | SEC_LOAD | SEC_ALLOC;
526                     sec->vma = address;
527                     sec->_raw_size = bytes;
528                     sec->filepos = pos;
529                   }
530
531                 break;
532
533               case '7':
534                 address = HEX (data);
535                 data += 2;
536                 /* Fall through.  */
537               case '8':
538                 address = (address << 8) | HEX (data);
539                 data += 2;
540                 /* Fall through.  */
541               case '9':
542                 address = (address << 8) | HEX (data);
543                 data += 2;
544                 address = (address << 8) | HEX (data);
545                 data += 2;
546
547                 /* This is a termination record.  */
548                 abfd->start_address = address;
549
550                 if (buf != NULL)
551                   free (buf);
552
553                 return true;
554               }
555           }
556           break;
557         }
558     }
559
560   if (error)
561     goto error_return;
562
563   if (buf != NULL)
564     free (buf);
565
566   return true;
567
568  error_return:
569   if (buf != NULL)
570     free (buf);
571   return false;
572 }
573
574 /* Check whether an existing file is an S-record file.  */
575
576 static const bfd_target *
577 srec_object_p (abfd)
578      bfd *abfd;
579 {
580   bfd_byte b[4];
581
582   srec_init ();
583
584   if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0
585       || bfd_read (b, 1, 4, abfd) != 4)
586     return NULL;
587
588   if (b[0] != 'S' || !ISHEX (b[1]) || !ISHEX (b[2]) || !ISHEX (b[3]))
589     {
590       bfd_set_error (bfd_error_wrong_format);
591       return NULL;
592     }
593
594   if (! srec_mkobject (abfd)
595       || ! srec_scan (abfd))
596     return NULL;
597
598   return abfd->xvec;
599 }
600
601 /* Check whether an existing file is an S-record file with symbols.  */
602
603 static const bfd_target *
604 symbolsrec_object_p (abfd)
605      bfd *abfd;
606 {
607   char b[2];
608
609   srec_init ();
610
611   if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0
612       || bfd_read (b, 1, 2, abfd) != 2)
613     return NULL;
614
615   if (b[0] != '$' || b[1] != '$')
616     {
617       bfd_set_error (bfd_error_wrong_format);
618       return NULL;
619     }
620
621   if (! srec_mkobject (abfd)
622       || ! srec_scan (abfd))
623     return NULL;
624
625   return abfd->xvec;
626 }
627
628 /* Read in the contents of a section in an S-record file.  */
629
630 static boolean
631 srec_read_section (abfd, section, contents)
632      bfd *abfd;
633      asection *section;
634      bfd_byte *contents;
635 {
636   int c;
637   bfd_size_type sofar = 0;
638   boolean error = false;
639   bfd_byte *buf = NULL;
640   size_t bufsize = 0;
641
642   if (bfd_seek (abfd, section->filepos, SEEK_SET) != 0)
643     goto error_return;
644
645   while ((c = srec_get_byte (abfd, &error)) != EOF)
646     {
647       bfd_byte hdr[3];
648       unsigned int bytes;
649       bfd_vma address;
650       bfd_byte *data;
651
652       if (c == '\r' || c == '\n')
653         continue;
654
655       /* This is called after srec_scan has already been called, so we
656          ought to know the exact format.  */
657       BFD_ASSERT (c == 'S');
658
659       if (bfd_read (hdr, 1, 3, abfd) != 3)
660         goto error_return;
661
662       BFD_ASSERT (ISHEX (hdr[1]) && ISHEX (hdr[2]));
663
664       bytes = HEX (hdr + 1);
665
666       if (bytes * 2 > bufsize)
667         {
668           if (buf != NULL)
669             free (buf);
670           buf = (bfd_byte *) malloc (bytes * 2);
671           if (buf == NULL)
672             {
673               bfd_set_error (bfd_error_no_memory);
674               goto error_return;
675             }
676           bufsize = bytes * 2;
677         }
678
679       if (bfd_read (buf, 1, bytes * 2, abfd) != bytes * 2)
680         goto error_return;
681
682       address = 0;
683       data = buf;
684       switch (hdr[0])
685         {
686         default:
687           BFD_ASSERT (sofar == section->_raw_size);
688           if (buf != NULL)
689             free (buf);
690           return true;
691
692         case '3':
693           address = HEX (data);
694           data += 2;
695           --bytes;
696           /* Fall through.  */
697         case '2':
698           address = (address << 8) | HEX (data);
699           data += 2;
700           --bytes;
701           /* Fall through.  */
702         case '1':
703           address = (address << 8) | HEX (data);
704           data += 2;
705           address = (address << 8) | HEX (data);
706           data += 2;
707           bytes -= 2;
708
709           if (address != section->vma + sofar)
710             {
711               /* We've come to the end of this section.  */
712               BFD_ASSERT (sofar == section->_raw_size);
713               if (buf != NULL)
714                 free (buf);
715               return true;
716             }
717
718           /* Don't consider checksum.  */
719           --bytes;
720
721           while (bytes-- != 0)
722             {
723               contents[sofar] = HEX (data);
724               data += 2;
725               ++sofar;
726             }
727
728           break;
729         }
730     }
731
732   if (error)
733     goto error_return;
734
735   BFD_ASSERT (sofar == section->_raw_size);
736
737   if (buf != NULL)
738     free (buf);
739
740   return true;
741
742  error_return:
743   if (buf != NULL)
744     free (buf);
745   return false;
746 }
747
748 /* Get the contents of a section in an S-record file.  */
749
750 static boolean
751 srec_get_section_contents (abfd, section, location, offset, count)
752      bfd *abfd;
753      asection *section;
754      PTR location;
755      file_ptr offset;
756      bfd_size_type count;
757 {
758   if (section->used_by_bfd == NULL)
759     {
760       section->used_by_bfd = bfd_alloc (abfd, section->_raw_size);
761       if (section->used_by_bfd == NULL
762           && section->_raw_size != 0)
763         return false;
764
765       if (! srec_read_section (abfd, section, section->used_by_bfd))
766         return false;
767     }
768
769   memcpy (location, (bfd_byte *) section->used_by_bfd + offset,
770           (size_t) count);
771
772   return true;
773 }
774
775 /* we have to save up all the Srecords for a splurge before output */
776
777 static boolean
778 srec_set_section_contents (abfd, section, location, offset, bytes_to_do)
779      bfd *abfd;
780      sec_ptr section;
781      PTR location;
782      file_ptr offset;
783      bfd_size_type bytes_to_do;
784 {
785   tdata_type *tdata = abfd->tdata.srec_data;
786   register srec_data_list_type *entry;
787
788   entry = ((srec_data_list_type *)
789            bfd_alloc (abfd, sizeof (srec_data_list_type)));
790   if (entry == NULL)
791     return false;
792
793   if (bytes_to_do
794       && (section->flags & SEC_ALLOC)
795       && (section->flags & SEC_LOAD))
796     {
797       bfd_byte *data = (bfd_byte *) bfd_alloc (abfd, bytes_to_do);
798       if (data == NULL)
799         return false;
800       memcpy ((PTR) data, location, (size_t) bytes_to_do);
801
802       if ((section->lma + offset + bytes_to_do - 1) <= 0xffff)
803         {
804
805         }
806       else if ((section->lma + offset + bytes_to_do - 1) <= 0xffffff
807                && tdata->type < 2)
808         {
809           tdata->type = 2;
810         }
811       else
812         {
813           tdata->type = 3;
814         }
815
816       entry->data = data;
817       entry->where = section->lma + offset;
818       entry->size = bytes_to_do;
819
820       /* Sort the records by address.  Optimize for the common case of
821          adding a record to the end of the list.  */
822       if (tdata->tail != NULL
823           && entry->where >= tdata->tail->where)
824         {
825           tdata->tail->next = entry;
826           entry->next = NULL;
827           tdata->tail = entry;
828         }
829       else
830         {
831           register srec_data_list_type **look;
832
833           for (look = &tdata->head;
834                *look != NULL && (*look)->where < entry->where;
835                look = &(*look)->next)
836             ;
837           entry->next = *look;
838           *look = entry;
839           if (entry->next == NULL)
840             tdata->tail = entry;
841         }
842     }
843   return true;
844 }
845
846 /* Write a record of type, of the supplied number of bytes. The
847    supplied bytes and length don't have a checksum. That's worked out
848    here
849 */
850 static boolean
851 srec_write_record (abfd, type, address, data, end)
852      bfd *abfd;
853      int type;
854      bfd_vma address;
855      const bfd_byte *data;
856      const bfd_byte *end;
857 {
858   char buffer[MAXCHUNK];
859   unsigned int check_sum = 0;
860   CONST bfd_byte *src = data;
861   char *dst = buffer;
862   char *length;
863   bfd_size_type wrlen;
864
865   *dst++ = 'S';
866   *dst++ = '0' + type;
867
868   length = dst;
869   dst += 2;                     /* leave room for dst*/
870
871   switch (type)
872     {
873     case 3:
874     case 7:
875       TOHEX (dst, (address >> 24), check_sum);
876       dst += 2;
877     case 8:
878     case 2:
879       TOHEX (dst, (address >> 16), check_sum);
880       dst += 2;
881     case 9:
882     case 1:
883     case 0:
884       TOHEX (dst, (address >> 8), check_sum);
885       dst += 2;
886       TOHEX (dst, (address), check_sum);
887       dst += 2;
888       break;
889
890     }
891   for (src = data; src < end; src++)
892     {
893       TOHEX (dst, *src, check_sum);
894       dst += 2;
895     }
896
897   /* Fill in the length */
898   TOHEX (length, (dst - length) / 2, check_sum);
899   check_sum &= 0xff;
900   check_sum = 255 - check_sum;
901   TOHEX (dst, check_sum, check_sum);
902   dst += 2;
903
904   *dst++ = '\r';
905   *dst++ = '\n';
906   wrlen = dst - buffer;
907   if (bfd_write ((PTR) buffer, 1, wrlen, abfd) != wrlen)
908     return false;
909   return true;
910 }
911
912
913
914 static boolean
915 srec_write_header (abfd)
916      bfd *abfd;
917 {
918   bfd_byte buffer[MAXCHUNK];
919   bfd_byte *dst = buffer;
920   unsigned int i;
921
922   /* I'll put an arbitary 40 char limit on header size */
923   for (i = 0; i < 40 && abfd->filename[i]; i++)
924     {
925       *dst++ = abfd->filename[i];
926     }
927   return srec_write_record (abfd, 0, 0, buffer, dst);
928 }
929
930 static boolean
931 srec_write_section (abfd, tdata, list)
932      bfd *abfd;
933      tdata_type *tdata;
934      srec_data_list_type *list;
935 {
936   unsigned int bytes_written = 0;
937   bfd_byte *location = list->data;
938
939   while (bytes_written < list->size)
940     {
941       bfd_vma address;
942
943       unsigned int bytes_this_chunk = list->size - bytes_written;
944
945       if (bytes_this_chunk > CHUNK)
946         {
947           bytes_this_chunk = CHUNK;
948         }
949
950       address = list->where + bytes_written;
951
952       if (! srec_write_record (abfd,
953                                tdata->type,
954                                address,
955                                location,
956                                location + bytes_this_chunk))
957         return false;
958
959       bytes_written += bytes_this_chunk;
960       location += bytes_this_chunk;
961     }
962
963   return true;
964 }
965
966 static boolean
967 srec_write_terminator (abfd, tdata)
968      bfd *abfd;
969      tdata_type *tdata;
970 {
971   bfd_byte buffer[2];
972
973   return srec_write_record (abfd, 10 - tdata->type,
974                             abfd->start_address, buffer, buffer);
975 }
976
977
978
979 static boolean
980 srec_write_symbols (abfd)
981      bfd *abfd;
982 {
983   char buffer[MAXCHUNK];
984   /* Dump out the symbols of a bfd */
985   int i;
986   int count = bfd_get_symcount (abfd);
987
988   if (count)
989     {
990       size_t len;
991       asymbol **table = bfd_get_outsymbols (abfd);
992       sprintf (buffer, "$$ %s\r\n", abfd->filename);
993
994       len = strlen (buffer);
995       if (bfd_write (buffer, len, 1, abfd) != len)
996         return false;
997
998       for (i = 0; i < count; i++)
999         {
1000           asymbol *s = table[i];
1001 #if 0
1002           int len = strlen (s->name);
1003
1004           /* If this symbol has a .[ocs] in it, it's probably a file name
1005          and we'll output that as the module name */
1006
1007           if (len > 3 && s->name[len - 2] == '.')
1008             {
1009               int l;
1010               sprintf (buffer, "$$ %s\r\n", s->name);
1011               l = strlen (buffer);
1012               if (bfd_write (buffer, l, 1, abfd) != l)
1013                 return false;
1014             }
1015           else
1016 #endif
1017             if (s->flags & (BSF_GLOBAL | BSF_LOCAL)
1018                 && (s->flags & BSF_DEBUGGING) == 0
1019                 && s->name[0] != '.'
1020                 && s->name[0] != 't')
1021             {
1022               /* Just dump out non debug symbols */
1023               bfd_size_type l;
1024               char buf2[40], *p;
1025
1026               sprintf_vma (buf2,
1027                            s->value + s->section->output_section->lma
1028                            + s->section->output_offset);
1029               p = buf2;
1030               while (p[0] == '0' && p[1] != 0)
1031                 p++;
1032               sprintf (buffer, "  %s $%s\r\n", s->name, p);
1033               l = strlen (buffer);
1034               if (bfd_write (buffer, l, 1, abfd) != l)
1035                 return false;
1036             }
1037         }
1038       sprintf (buffer, "$$ \r\n");
1039       len = strlen (buffer);
1040       if (bfd_write (buffer, len, 1, abfd) != len)
1041         return false;
1042     }
1043
1044   return true;
1045 }
1046
1047 static boolean
1048 internal_srec_write_object_contents (abfd, symbols)
1049      bfd *abfd;
1050      int symbols;
1051 {
1052   tdata_type *tdata = abfd->tdata.srec_data;
1053   srec_data_list_type *list;
1054
1055   if (symbols)
1056     {
1057       if (! srec_write_symbols (abfd))
1058         return false;
1059     }
1060
1061   if (! srec_write_header (abfd))
1062     return false;
1063
1064   /* Now wander though all the sections provided and output them */
1065   list = tdata->head;
1066
1067   while (list != (srec_data_list_type *) NULL)
1068     {
1069       if (! srec_write_section (abfd, tdata, list))
1070         return false;
1071       list = list->next;
1072     }
1073   return srec_write_terminator (abfd, tdata);
1074 }
1075
1076 static boolean
1077 srec_write_object_contents (abfd)
1078      bfd *abfd;
1079 {
1080   return internal_srec_write_object_contents (abfd, 0);
1081 }
1082
1083 static boolean
1084 symbolsrec_write_object_contents (abfd)
1085      bfd *abfd;
1086 {
1087   return internal_srec_write_object_contents (abfd, 1);
1088 }
1089
1090 /*ARGSUSED*/
1091 static int
1092 srec_sizeof_headers (abfd, exec)
1093      bfd *abfd;
1094      boolean exec;
1095 {
1096   return 0;
1097 }
1098
1099 static asymbol *
1100 srec_make_empty_symbol (abfd)
1101      bfd *abfd;
1102 {
1103   asymbol *new = (asymbol *) bfd_zalloc (abfd, sizeof (asymbol));
1104   if (new)
1105     new->the_bfd = abfd;
1106   return new;
1107 }
1108
1109 /* Return the amount of memory needed to read the symbol table.  */
1110
1111 static long
1112 srec_get_symtab_upper_bound (abfd)
1113      bfd *abfd;
1114 {
1115   return (bfd_get_symcount (abfd) + 1) * sizeof (asymbol *);
1116 }
1117
1118 /* Return the symbol table.  */
1119
1120 static long
1121 srec_get_symtab (abfd, alocation)
1122      bfd *abfd;
1123      asymbol **alocation;
1124 {
1125   unsigned int symcount = bfd_get_symcount (abfd);
1126   asymbol *csymbols;
1127   unsigned int i;
1128
1129   csymbols = abfd->tdata.srec_data->csymbols;
1130   if (csymbols == NULL)
1131     {
1132       asymbol *c;
1133       struct srec_symbol *s;
1134
1135       csymbols = (asymbol *) bfd_alloc (abfd, symcount * sizeof (asymbol));
1136       if (csymbols == NULL && symcount != 0)
1137         return false;
1138       abfd->tdata.srec_data->csymbols = csymbols;
1139
1140       for (s = abfd->tdata.srec_data->symbols, c = csymbols;
1141            s != NULL;
1142            s = s->next, ++c)
1143         {
1144           c->the_bfd = abfd;
1145           c->name = s->name;
1146           c->value = s->val;
1147           c->flags = BSF_GLOBAL;
1148           c->section = bfd_abs_section_ptr;
1149           c->udata.p = NULL;
1150         }
1151     }
1152         
1153   for (i = 0; i < symcount; i++)
1154     *alocation++ = csymbols++;
1155   *alocation = NULL;
1156
1157   return symcount;
1158 }
1159
1160 /*ARGSUSED*/
1161 void
1162 srec_get_symbol_info (ignore_abfd, symbol, ret)
1163      bfd *ignore_abfd;
1164      asymbol *symbol;
1165      symbol_info *ret;
1166 {
1167   bfd_symbol_info (symbol, ret);
1168 }
1169
1170 /*ARGSUSED*/
1171 void
1172 srec_print_symbol (ignore_abfd, afile, symbol, how)
1173      bfd *ignore_abfd;
1174      PTR afile;
1175      asymbol *symbol;
1176      bfd_print_symbol_type how;
1177 {
1178   FILE *file = (FILE *) afile;
1179   switch (how)
1180     {
1181     case bfd_print_symbol_name:
1182       fprintf (file, "%s", symbol->name);
1183       break;
1184     default:
1185       bfd_print_symbol_vandf ((PTR) file, symbol);
1186       fprintf (file, " %-5s %s",
1187                symbol->section->name,
1188                symbol->name);
1189
1190     }
1191 }
1192
1193 #define srec_close_and_cleanup _bfd_generic_close_and_cleanup
1194 #define srec_bfd_free_cached_info _bfd_generic_bfd_free_cached_info
1195 #define srec_new_section_hook _bfd_generic_new_section_hook
1196
1197 #define srec_bfd_is_local_label bfd_generic_is_local_label
1198 #define srec_get_lineno _bfd_nosymbols_get_lineno
1199 #define srec_find_nearest_line _bfd_nosymbols_find_nearest_line
1200 #define srec_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol
1201 #define srec_read_minisymbols _bfd_generic_read_minisymbols
1202 #define srec_minisymbol_to_symbol _bfd_generic_minisymbol_to_symbol
1203
1204 #define srec_get_reloc_upper_bound \
1205   ((long (*) PARAMS ((bfd *, asection *))) bfd_0l)
1206 #define srec_canonicalize_reloc \
1207   ((long (*) PARAMS ((bfd *, asection *, arelent **, asymbol **))) bfd_0l)
1208 #define srec_bfd_reloc_type_lookup _bfd_norelocs_bfd_reloc_type_lookup
1209
1210 #define srec_get_section_contents_in_window \
1211   _bfd_generic_get_section_contents_in_window
1212
1213 #define srec_set_arch_mach bfd_default_set_arch_mach
1214
1215 #define srec_bfd_get_relocated_section_contents \
1216   bfd_generic_get_relocated_section_contents
1217 #define srec_bfd_relax_section bfd_generic_relax_section
1218 #define srec_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
1219 #define srec_bfd_link_add_symbols _bfd_generic_link_add_symbols
1220 #define srec_bfd_final_link _bfd_generic_final_link
1221 #define srec_bfd_link_split_section _bfd_generic_link_split_section
1222
1223 const bfd_target srec_vec =
1224 {
1225   "srec",                       /* name */
1226   bfd_target_srec_flavour,
1227   true,                         /* target byte order */
1228   true,                         /* target headers byte order */
1229   (HAS_RELOC | EXEC_P |         /* object flags */
1230    HAS_LINENO | HAS_DEBUG |
1231    HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
1232   (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS
1233    | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
1234   0,                            /* leading underscore */
1235   ' ',                          /* ar_pad_char */
1236   16,                           /* ar_max_namelen */
1237   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
1238   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
1239   bfd_getb16, bfd_getb_signed_16, bfd_putb16,   /* data */
1240   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
1241   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
1242   bfd_getb16, bfd_getb_signed_16, bfd_putb16,   /* hdrs */
1243
1244   {
1245     _bfd_dummy_target,
1246     srec_object_p,              /* bfd_check_format */
1247     _bfd_dummy_target,
1248     _bfd_dummy_target,
1249   },
1250   {
1251     bfd_false,
1252     srec_mkobject,
1253     _bfd_generic_mkarchive,
1254     bfd_false,
1255   },
1256   {                             /* bfd_write_contents */
1257     bfd_false,
1258     srec_write_object_contents,
1259     _bfd_write_archive_contents,
1260     bfd_false,
1261   },
1262
1263   BFD_JUMP_TABLE_GENERIC (srec),
1264   BFD_JUMP_TABLE_COPY (_bfd_generic),
1265   BFD_JUMP_TABLE_CORE (_bfd_nocore),
1266   BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
1267   BFD_JUMP_TABLE_SYMBOLS (srec),
1268   BFD_JUMP_TABLE_RELOCS (srec),
1269   BFD_JUMP_TABLE_WRITE (srec),
1270   BFD_JUMP_TABLE_LINK (srec),
1271   BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
1272
1273   (PTR) 0
1274 };
1275
1276
1277
1278 const bfd_target symbolsrec_vec =
1279 {
1280   "symbolsrec",                 /* name */
1281   bfd_target_srec_flavour,
1282   true,                         /* target byte order */
1283   true,                         /* target headers byte order */
1284   (HAS_RELOC | EXEC_P |         /* object flags */
1285    HAS_LINENO | HAS_DEBUG |
1286    HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
1287   (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS
1288    | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
1289   0,                            /* leading underscore */
1290   ' ',                          /* ar_pad_char */
1291   16,                           /* ar_max_namelen */
1292   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
1293   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
1294   bfd_getb16, bfd_getb_signed_16, bfd_putb16,   /* data */
1295   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
1296   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
1297   bfd_getb16, bfd_getb_signed_16, bfd_putb16,   /* hdrs */
1298
1299   {
1300     _bfd_dummy_target,
1301     symbolsrec_object_p,        /* bfd_check_format */
1302     _bfd_dummy_target,
1303     _bfd_dummy_target,
1304   },
1305   {
1306     bfd_false,
1307     srec_mkobject,
1308     _bfd_generic_mkarchive,
1309     bfd_false,
1310   },
1311   {                             /* bfd_write_contents */
1312     bfd_false,
1313     symbolsrec_write_object_contents,
1314     _bfd_write_archive_contents,
1315     bfd_false,
1316   },
1317
1318   BFD_JUMP_TABLE_GENERIC (srec),
1319   BFD_JUMP_TABLE_COPY (_bfd_generic),
1320   BFD_JUMP_TABLE_CORE (_bfd_nocore),
1321   BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
1322   BFD_JUMP_TABLE_SYMBOLS (srec),
1323   BFD_JUMP_TABLE_RELOCS (srec),
1324   BFD_JUMP_TABLE_WRITE (srec),
1325   BFD_JUMP_TABLE_LINK (srec),
1326   BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
1327
1328   (PTR) 0
1329 };