* srec.c (tdata_type): Add field tail.
[external/binutils.git] / bfd / srec.c
1 /* BFD back-end for s-record objects.
2    Copyright 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
3    Written by Steve Chamberlain of Cygnus Support <sac@cygnus.com>.
4
5 This file is part of BFD, the Binary File Descriptor library.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
20
21 /*
22 SUBSECTION
23         S-Record handling
24
25 DESCRIPTION
26         
27         Ordinary S-Records cannot hold anything but addresses and
28         data, so that's all that we implement.
29
30         The only interesting thing is that S-Records may come out of
31         order and there is no header, so an initial scan is required
32         to discover the minimum and maximum addresses used to create
33         the vma and size of the only section we create.  We
34         arbitrarily call this section ".text".
35
36         When bfd_get_section_contents is called the file is read
37         again, and this time the data is placed into a bfd_alloc'd
38         area.
39
40         Any number of sections may be created for output, we save them
41         up and output them when it's time to close the bfd.
42
43         An s record looks like:
44         
45 EXAMPLE
46         S<type><length><address><data><checksum>
47         
48 DESCRIPTION
49         Where
50         o length
51         is the number of bytes following upto the checksum. Note that
52         this is not the number of chars following, since it takes two
53         chars to represent a byte.
54         o type
55         is one of:
56         0) header record
57         1) two byte address data record
58         2) three byte address data record
59         3) four byte address data record
60         7) four byte address termination record
61         8) three byte address termination record
62         9) two byte address termination record
63         
64         o address
65         is the start address of the data following, or in the case of
66         a termination record, the start address of the image
67         o data
68         is the data.
69         o checksum
70         is the sum of all the raw byte data in the record, from the length
71         upwards, modulo 256 and subtracted from 255.
72
73
74 SUBSECTION
75         Symbol S-Record handling
76
77 DESCRIPTION
78         Some ICE equipment understands an addition to the standard
79         S-Record format; symbols and their addresses can be sent
80         before the data.
81
82         The format of this is:
83         ($$ <modulename>
84                 (<space> <symbol> <address>)*)
85         $$
86
87         so a short symbol table could look like:
88
89 EXAMPLE
90         $$ flash.x
91         $$ flash.c
92           _port6 $0
93           _delay $4
94           _start $14
95           _etext $8036
96           _edata $8036
97           _end $8036
98         $$
99
100 DESCRIPTION
101         We allow symbols to be anywhere in the data stream - the module names
102         are always ignored.
103                 
104 */
105
106 #include "bfd.h"
107 #include "sysdep.h"
108 #include "libbfd.h"
109
110 static boolean srec_write_record PARAMS ((bfd *, int, bfd_vma,
111                                           const unsigned char *,
112                                           const unsigned char *));
113 static boolean srec_write_header PARAMS ((bfd *));
114 static boolean srec_write_symbols PARAMS ((bfd *));
115
116 /* Macros for converting between hex and binary. */
117
118 static CONST char digs[] = "0123456789ABCDEF";
119
120 /* Table that gets filled in with numbers corresponding to hex chars. */
121
122 static char hex_value[256];
123
124 #define NOT_HEX 20
125 #define NIBBLE(x) hex_value[(unsigned char)(x)]
126 #define HEX(buffer) ((NIBBLE((buffer)[0])<<4) + NIBBLE((buffer)[1]))
127 #define TOHEX(d, x, ch) \
128         d[1] = digs[(x) & 0xf]; \
129         d[0] = digs[((x)>>4)&0xf]; \
130         ch += ((x) & 0xff);
131 #define ISHEX(x)  (hex_value[(unsigned char)(x)] != NOT_HEX)
132
133 /* Initialize by filling in the hex conversion array. */
134
135 static void
136 srec_init ()
137 {
138   unsigned int i;
139   static boolean inited = false;
140
141   if (inited == false)
142     {
143       inited = true;
144
145       for (i = 0; i < sizeof (hex_value); i++)
146         {
147           hex_value[i] = NOT_HEX;
148         }
149       for (i = 0; i < 10; i++)
150         {
151           hex_value[i + '0'] = i;
152         }
153       for (i = 0; i < 6; i++)
154         {
155           hex_value[i + 'a'] = i + 10;
156           hex_value[i + 'A'] = i + 10;
157         }
158     }
159 }
160
161
162 /* The maximum number of bytes on a line is FF */
163 #define MAXCHUNK 0xff
164 /* The number of bytes we fit onto a line on output */
165 #define CHUNK 21
166
167 /* We cannot output our srecords as we see them, we have to glue them
168    together, this is done in this structure : */
169
170 struct srec_data_list_struct
171 {
172   unsigned char *data;
173   bfd_vma where;
174   bfd_size_type size;
175   struct srec_data_list_struct *next;
176
177
178 };
179 typedef struct srec_data_list_struct srec_data_list_type;
180
181
182 typedef struct srec_data_struct
183   {
184     srec_data_list_type *head;
185     srec_data_list_type *tail;
186     unsigned int type;
187
188     int done_symbol_read;
189     int count;
190     asymbol *symbols;
191     char *strings;
192     int symbol_idx;
193     int string_size;
194     int string_idx;
195   }
196 tdata_type;
197
198 static boolean srec_write_section PARAMS ((bfd *, tdata_type *,
199                                            srec_data_list_type *));
200 static boolean srec_write_terminator PARAMS ((bfd *, tdata_type *));
201
202 /*
203    called once per input S-Record, used to work out vma and size of data.
204  */
205
206 static bfd_vma low, high;
207
208 /*ARGSUSED*/
209 static void
210 size_symbols (abfd, buf, len, val)
211      bfd *abfd;
212      char *buf;
213      int len;
214      int val;
215 {
216   abfd->symcount++;
217   abfd->tdata.srec_data->string_size += len + 1;
218 }
219
220 static void
221 fillup_symbols (abfd, buf, len, val)
222      bfd *abfd;
223      char *buf;
224      int len;
225      int val;
226 {
227   if (!abfd->tdata.srec_data->done_symbol_read)
228     {
229       asymbol *p;
230       if (abfd->tdata.srec_data->symbols == 0)
231         {
232           abfd->tdata.srec_data->symbols = (asymbol *) bfd_alloc (abfd, abfd->symcount * sizeof (asymbol));
233           abfd->tdata.srec_data->strings = (char *) bfd_alloc (abfd, abfd->tdata.srec_data->string_size);
234           if (!abfd->tdata.srec_data->symbols || !abfd->tdata.srec_data->strings)
235             {
236               bfd_set_error (bfd_error_no_memory);
237               abort ();         /* FIXME */
238             }
239           abfd->tdata.srec_data->symbol_idx = 0;
240           abfd->tdata.srec_data->string_idx = 0;
241         }
242
243       p = abfd->tdata.srec_data->symbols + abfd->tdata.srec_data->symbol_idx++;
244       p->the_bfd = abfd;
245       p->name = abfd->tdata.srec_data->strings + abfd->tdata.srec_data->string_idx;
246       memcpy ((char *) (p->name), buf, len + 1);
247       abfd->tdata.srec_data->string_idx += len + 1;
248       p->value = val;
249       p->flags = BSF_EXPORT | BSF_GLOBAL;
250       p->section = bfd_abs_section_ptr;
251       p->udata.p = NULL;
252     }
253 }
254 /*ARGSUSED*/
255 static void
256 size_srec (abfd, section, address, raw, length)
257      bfd *abfd;
258      asection *section;
259      bfd_vma address;
260      bfd_byte *raw;
261      unsigned int length;
262 {
263   if (address < low)
264     low = address;
265   if (address + length > high)
266     high = address + length - 1;
267 }
268
269
270 /*
271  called once per input S-Record, copies data from input into bfd_alloc'd area
272  */
273
274 /*ARGSUSED*/
275 static void
276 fillup (abfd, section, address, raw, length)
277      bfd *abfd;
278      asection *section;
279      bfd_vma address;
280      bfd_byte *raw;
281      unsigned int length;
282 {
283   unsigned int i;
284   bfd_byte *dst =
285   (bfd_byte *) (section->used_by_bfd) + address - section->vma;
286   /* length -1 because we don't read in the checksum */
287   for (i = 0; i < length - 1; i++)
288     {
289       *dst = HEX (raw);
290       dst++;
291       raw += 2;
292     }
293 }
294
295 /* Pass over an S-Record file, calling one of the above functions on each
296    record.  */
297
298 static int
299 white (x)
300      char x;
301 {
302   return (x == ' ' || x == '\t' || x == '\n' || x == '\r');
303 }
304 static int
305 skipwhite (src, abfd)
306      char *src;
307      bfd *abfd;
308 {
309   int eof = 0;
310   while (white (*src) && !eof)
311     {
312       eof = (boolean) (bfd_read (src, 1, 1, abfd) != 1);
313     }
314   return eof;
315 }
316
317 static boolean
318 srec_mkobject (abfd)
319      bfd *abfd;
320 {
321   if (abfd->tdata.srec_data == 0)
322     {
323       tdata_type *tdata = (tdata_type *) bfd_alloc (abfd, sizeof (tdata_type));
324       if (!tdata)
325         {
326           bfd_set_error (bfd_error_no_memory);
327           return false;
328         }
329       abfd->tdata.srec_data = tdata;
330       tdata->type = 1;
331       tdata->head = NULL;
332       tdata->tail = NULL;
333     }
334   return true;
335
336 }
337
338 static void
339 pass_over (abfd, func, symbolfunc, section)
340      bfd *abfd;
341      void (*func) ();
342      void (*symbolfunc) ();
343      asection *section;
344 {
345   unsigned int bytes_on_line;
346   boolean eof = false;
347
348   srec_mkobject (abfd);
349   /* To the front of the file */
350   if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
351     abort ();
352   while (eof == false)
353     {
354       char buffer[MAXCHUNK];
355       char *src = buffer;
356       char type;
357       bfd_vma address = 0;
358
359       /* Find first 'S' or $ */
360       eof = (boolean) (bfd_read (src, 1, 1, abfd) != 1);
361       switch (*src)
362         {
363         default:
364           if (eof)
365             return;
366           break;
367
368         case '$':
369           /* Inside a symbol definition - just ignore the module name */
370           while (*src != '\n' && !eof)
371             {
372               eof = (boolean) (bfd_read (src, 1, 1, abfd) != 1);
373             }
374           break;
375
376         case ' ':
377           /* spaces - maybe just before a symbol */
378           while (*src != '\n' && *src != '\r' && white (*src))
379             {
380               eof = skipwhite (src, abfd);
381
382               {
383                 int val = 0;
384                 int slen = 0;
385                 char symbol[MAXCHUNK];
386
387                 /* get the symbol part */
388                 while (!eof && !white (*src) && slen < MAXCHUNK)
389                   {
390                     symbol[slen++] = *src;
391                     eof = (boolean) (bfd_read (src, 1, 1, abfd) != 1);
392                   }
393                 symbol[slen] = 0;
394                 eof = skipwhite (src, abfd);
395                 /* skip the $ for the hex value */
396                 if (*src == '$')
397                   {
398                     eof = (boolean) (bfd_read (src, 1, 1, abfd) != 1);
399                   }
400
401                 /* Scan off the hex number */
402                 while (isxdigit (*src))
403                   {
404                     val *= 16;
405                     if (isdigit (*src))
406                       val += *src - '0';
407                     else if (isupper (*src))
408                       {
409                         val += *src - 'A' + 10;
410                       }
411                     else
412                       {
413                         val += *src - 'a' + 10;
414                       }
415                     eof = (boolean) (bfd_read (src, 1, 1, abfd) != 1);
416                   }
417                 symbolfunc (abfd, symbol, slen, val);
418               }
419             }
420           break;
421         case 'S':
422           src++;
423
424           /* Fetch the type and the length */
425           if (bfd_read (src, 1, 3, abfd) != 3)
426             abort (); /* FIXME */
427
428           type = *src++;
429
430           if (!ISHEX (src[0]) || !ISHEX (src[1]))
431             break;
432
433           bytes_on_line = HEX (src);
434
435           if (bytes_on_line > MAXCHUNK / 2)
436             break;
437           src += 2;
438
439           if (bfd_read (src, 1, bytes_on_line * 2, abfd) != bytes_on_line * 2)
440             abort (); /* FIXME */
441
442           switch (type)
443             {
444             case '0':
445             case '5':
446               /* Prologue - ignore */
447               break;
448             case '3':
449               address = HEX (src);
450               src += 2;
451               bytes_on_line--;
452
453             case '2':
454               address = HEX (src) | (address << 8);
455               src += 2;
456               bytes_on_line--;
457             case '1':
458               address = HEX (src) | (address << 8);
459               src += 2;
460               address = HEX (src) | (address << 8);
461               src += 2;
462               bytes_on_line -= 2;
463               func (abfd, section, address, src, bytes_on_line);
464               break;
465
466             case '7':
467               address = HEX (src);
468               src += 2;
469               bytes_on_line--;
470             case '8':
471               address = HEX (src) | (address << 8);
472               src += 2;
473               bytes_on_line--;
474             case '9':
475               address = HEX (src) | (address << 8);
476               src += 2;
477               address = HEX (src) | (address << 8);
478               src += 2;
479               bytes_on_line -= 2;
480               abfd->start_address = address;
481               return;
482
483             default:
484               return;
485             }
486         }
487     }
488
489 }
490
491 static const bfd_target *
492 object_p (abfd)
493      bfd *abfd;
494 {
495   asection *section;
496   /* We create one section called .text for all the contents,
497      and allocate enough room for the entire file.  */
498
499   section = bfd_make_section (abfd, ".text");
500   section->_raw_size = 0;
501   section->vma = 0xffffffff;
502   low = 0xffffffff;
503   high = 0;
504   pass_over (abfd, size_srec, size_symbols, section);
505   section->_raw_size = high - low;
506   section->vma = low;
507   section->flags = SEC_HAS_CONTENTS | SEC_LOAD | SEC_ALLOC;
508
509   if (abfd->symcount)
510     abfd->flags |= HAS_SYMS;
511   return abfd->xvec;
512 }
513
514 static const bfd_target *
515 srec_object_p (abfd)
516      bfd *abfd;
517 {
518   char b[4];
519
520   srec_init ();
521
522   if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0
523       || bfd_read (b, 1, 4, abfd) != 4)
524     return NULL;
525
526   if (b[0] != 'S' || !ISHEX (b[1]) || !ISHEX (b[2]) || !ISHEX (b[3]))
527     return (const bfd_target *) NULL;
528
529   /* We create one section called .text for all the contents,
530      and allocate enough room for the entire file.  */
531
532   return object_p (abfd);
533 }
534
535
536 static const bfd_target *
537 symbolsrec_object_p (abfd)
538      bfd *abfd;
539 {
540   char b[4];
541
542   srec_init ();
543
544   if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0
545       || bfd_read (b, 1, 4, abfd) != 4)
546     return NULL;
547
548   if (b[0] != '$' || b[1] != '$')
549     return (const bfd_target *) NULL;
550
551   return object_p (abfd);
552 }
553
554
555 static boolean
556 srec_get_section_contents (abfd, section, location, offset, count)
557      bfd *abfd;
558      asection *section;
559      PTR location;
560      file_ptr offset;
561      bfd_size_type count;
562 {
563   if (section->used_by_bfd == (PTR) NULL)
564     {
565       section->used_by_bfd = (PTR) bfd_alloc (abfd, section->_raw_size);
566       if (!section->used_by_bfd)
567         {
568           bfd_set_error (bfd_error_no_memory);
569           return false;
570         }
571
572       pass_over (abfd, fillup, fillup_symbols, section);
573     }
574   memcpy ((PTR) location,
575           (PTR) ((char *) (section->used_by_bfd) + offset),
576           count);
577   return true;
578 }
579
580
581
582 boolean
583 srec_set_arch_mach (abfd, arch, machine)
584      bfd *abfd;
585      enum bfd_architecture arch;
586      unsigned long machine;
587 {
588   return bfd_default_set_arch_mach (abfd, arch, machine);
589 }
590
591
592 /* we have to save up all the Srecords for a splurge before output,
593    also remember   */
594
595 static boolean
596 srec_set_section_contents (abfd, section, location, offset, bytes_to_do)
597      bfd *abfd;
598      sec_ptr section;
599      PTR location;
600      file_ptr offset;
601      bfd_size_type bytes_to_do;
602 {
603   tdata_type *tdata = abfd->tdata.srec_data;
604   register srec_data_list_type *entry;
605
606   entry = ((srec_data_list_type *)
607            bfd_alloc (abfd, sizeof (srec_data_list_type)));
608   if (entry == NULL)
609     {
610       bfd_set_error (bfd_error_no_memory);
611       return false;
612     }
613
614   if ((section->flags & SEC_ALLOC)
615       && (section->flags & SEC_LOAD))
616     {
617       unsigned char *data = (unsigned char *) bfd_alloc (abfd, bytes_to_do);
618       if (data == NULL)
619         {
620           bfd_set_error (bfd_error_no_memory);
621           return false;
622         }
623       memcpy ((PTR) data, location, bytes_to_do);
624
625       if ((section->lma + offset + bytes_to_do) <= 0xffff)
626         {
627
628         }
629       else if ((section->lma + offset + bytes_to_do) <= 0xffffff
630                && tdata->type < 2)
631         {
632           tdata->type = 2;
633         }
634       else
635         {
636           tdata->type = 3;
637         }
638
639       entry->data = data;
640       entry->where = section->lma + offset;
641       entry->size = bytes_to_do;
642
643       /* Sort the records by address.  Optimize for the common case of
644          adding a record to the end of the list.  */
645       if (tdata->tail != NULL
646           && entry->where >= tdata->tail->where)
647         {
648           tdata->tail->next = entry;
649           entry->next = NULL;
650           tdata->tail = entry;
651         }
652       else
653         {
654           register srec_data_list_type **look;
655
656           for (look = &tdata->head;
657                *look != NULL && (*look)->where < entry->where;
658                look = &(*look)->next)
659             ;
660           entry->next = *look;
661           *look = entry;
662           if (entry->next == NULL)
663             tdata->tail = entry;
664         }
665     }
666   return true;
667 }
668
669 /* Write a record of type, of the supplied number of bytes. The
670    supplied bytes and length don't have a checksum. That's worked out
671    here
672 */
673 static boolean
674 srec_write_record (abfd, type, address, data, end)
675      bfd *abfd;
676      int type;
677      bfd_vma address;
678      const unsigned char *data;
679      const unsigned char *end;
680 {
681   char buffer[MAXCHUNK];
682
683   unsigned int check_sum = 0;
684   CONST unsigned char *src = data;
685   char *dst = buffer;
686   char *length;
687
688
689   *dst++ = 'S';
690   *dst++ = '0' + type;
691
692   length = dst;
693   dst += 2;                     /* leave room for dst*/
694
695   switch (type)
696     {
697     case 3:
698     case 7:
699       TOHEX (dst, (address >> 24), check_sum);
700       dst += 2;
701     case 8:
702     case 2:
703       TOHEX (dst, (address >> 16), check_sum);
704       dst += 2;
705     case 9:
706     case 1:
707     case 0:
708       TOHEX (dst, (address >> 8), check_sum);
709       dst += 2;
710       TOHEX (dst, (address), check_sum);
711       dst += 2;
712       break;
713
714     }
715   for (src = data; src < end; src++)
716     {
717       TOHEX (dst, *src, check_sum);
718       dst += 2;
719     }
720
721   /* Fill in the length */
722   TOHEX (length, (dst - length) / 2, check_sum);
723   check_sum &= 0xff;
724   check_sum = 255 - check_sum;
725   TOHEX (dst, check_sum, check_sum);
726   dst += 2;
727
728   *dst++ = '\r';
729   *dst++ = '\n';
730   if (bfd_write ((PTR) buffer, 1, dst - buffer, abfd) != dst - buffer)
731     return false;
732   return true;
733 }
734
735
736
737 static boolean
738 srec_write_header (abfd)
739      bfd *abfd;
740 {
741   unsigned char buffer[MAXCHUNK];
742   unsigned char *dst = buffer;
743   unsigned int i;
744
745   /* I'll put an arbitary 40 char limit on header size */
746   for (i = 0; i < 40 && abfd->filename[i]; i++)
747     {
748       *dst++ = abfd->filename[i];
749     }
750   return srec_write_record (abfd, 0, 0, buffer, dst);
751 }
752
753 static boolean
754 srec_write_section (abfd, tdata, list)
755      bfd *abfd;
756      tdata_type *tdata;
757      srec_data_list_type *list;
758 {
759   unsigned int bytes_written = 0;
760   unsigned char *location = list->data;
761
762   while (bytes_written < list->size)
763     {
764       bfd_vma address;
765
766       unsigned int bytes_this_chunk = list->size - bytes_written;
767
768       if (bytes_this_chunk > CHUNK)
769         {
770           bytes_this_chunk = CHUNK;
771         }
772
773       address = list->where + bytes_written;
774
775       if (! srec_write_record (abfd,
776                                tdata->type,
777                                address,
778                                location,
779                                location + bytes_this_chunk))
780         return false;
781
782       bytes_written += bytes_this_chunk;
783       location += bytes_this_chunk;
784     }
785
786   return true;
787 }
788
789 static boolean
790 srec_write_terminator (abfd, tdata)
791      bfd *abfd;
792      tdata_type *tdata;
793 {
794   unsigned char buffer[2];
795
796   return srec_write_record (abfd, 10 - tdata->type,
797                             abfd->start_address, buffer, buffer);
798 }
799
800
801
802 static boolean
803 srec_write_symbols (abfd)
804      bfd *abfd;
805 {
806   char buffer[MAXCHUNK];
807   /* Dump out the symbols of a bfd */
808   int i;
809   int count = bfd_get_symcount (abfd);
810
811   if (count)
812     {
813       size_t len;
814       asymbol **table = bfd_get_outsymbols (abfd);
815       sprintf (buffer, "$$ %s\r\n", abfd->filename);
816
817       len = strlen (buffer);
818       if (bfd_write (buffer, len, 1, abfd) != len)
819         return false;
820
821       for (i = 0; i < count; i++)
822         {
823           asymbol *s = table[i];
824 #if 0
825           int len = strlen (s->name);
826
827           /* If this symbol has a .[ocs] in it, it's probably a file name
828          and we'll output that as the module name */
829
830           if (len > 3 && s->name[len - 2] == '.')
831             {
832               int l;
833               sprintf (buffer, "$$ %s\r\n", s->name);
834               l = strlen (buffer);
835               if (bfd_write (buffer, l, 1, abfd) != l)
836                 return false;
837             }
838           else
839 #endif
840             if (s->flags & (BSF_GLOBAL | BSF_LOCAL)
841                 && (s->flags & BSF_DEBUGGING) == 0
842                 && s->name[0] != '.'
843                 && s->name[0] != 't')
844             {
845               /* Just dump out non debug symbols */
846
847               int l;
848               char buf2[40], *p;
849
850               sprintf_vma (buf2,
851                            s->value + s->section->output_section->lma
852                            + s->section->output_offset);
853               p = buf2;
854               while (p[0] == '0' && p[1] != 0)
855                 p++;
856               sprintf (buffer, "  %s $%s\r\n", s->name, p);
857               l = strlen (buffer);
858               if (bfd_write (buffer, l, 1, abfd) != l)
859                 return false;
860             }
861         }
862       sprintf (buffer, "$$ \r\n");
863       len = strlen (buffer);
864       if (bfd_write (buffer, len, 1, abfd) != len)
865         return false;
866     }
867
868   return true;
869 }
870
871 static boolean
872 internal_srec_write_object_contents (abfd, symbols)
873      bfd *abfd;
874      int symbols;
875 {
876   tdata_type *tdata = abfd->tdata.srec_data;
877   srec_data_list_type *list;
878
879   if (symbols)
880     {
881       if (! srec_write_symbols (abfd))
882         return false;
883     }
884
885   if (! srec_write_header (abfd))
886     return false;
887
888   /* Now wander though all the sections provided and output them */
889   list = tdata->head;
890
891   while (list != (srec_data_list_type *) NULL)
892     {
893       if (! srec_write_section (abfd, tdata, list))
894         return false;
895       list = list->next;
896     }
897   return srec_write_terminator (abfd, tdata);
898 }
899
900 static boolean
901 srec_write_object_contents (abfd)
902      bfd *abfd;
903 {
904   return internal_srec_write_object_contents (abfd, 0);
905 }
906
907 static boolean
908 symbolsrec_write_object_contents (abfd)
909      bfd *abfd;
910 {
911   return internal_srec_write_object_contents (abfd, 1);
912 }
913
914 /*ARGSUSED*/
915 static int
916 srec_sizeof_headers (abfd, exec)
917      bfd *abfd;
918      boolean exec;
919 {
920   return 0;
921 }
922
923 static asymbol *
924 srec_make_empty_symbol (abfd)
925      bfd *abfd;
926 {
927   asymbol *new = (asymbol *) bfd_zalloc (abfd, sizeof (asymbol));
928   if (new)
929     new->the_bfd = abfd;
930   return new;
931 }
932
933 static long
934 srec_get_symtab_upper_bound (abfd)
935      bfd *abfd;
936 {
937   /* Read in all the info */
938   if (! srec_get_section_contents (abfd, abfd->sections, 0, 0, 0))
939     return -1;
940   return (bfd_get_symcount (abfd) + 1) * (sizeof (asymbol *));
941 }
942
943 static long
944 srec_get_symtab (abfd, alocation)
945      bfd *abfd;
946      asymbol **alocation;
947 {
948   int lim = abfd->symcount;
949   int i;
950   for (i = 0; i < lim; i++)
951     {
952       alocation[i] = abfd->tdata.srec_data->symbols + i;
953     }
954   alocation[i] = 0;
955   return lim;
956 }
957
958 /*ARGSUSED*/
959 void
960 srec_get_symbol_info (ignore_abfd, symbol, ret)
961      bfd *ignore_abfd;
962      asymbol *symbol;
963      symbol_info *ret;
964 {
965   bfd_symbol_info (symbol, ret);
966 }
967
968 /*ARGSUSED*/
969 void
970 srec_print_symbol (ignore_abfd, afile, symbol, how)
971      bfd *ignore_abfd;
972      PTR afile;
973      asymbol *symbol;
974      bfd_print_symbol_type how;
975 {
976   FILE *file = (FILE *) afile;
977   switch (how)
978     {
979     case bfd_print_symbol_name:
980       fprintf (file, "%s", symbol->name);
981       break;
982     default:
983       bfd_print_symbol_vandf ((PTR) file, symbol);
984       fprintf (file, " %-5s %s",
985                symbol->section->name,
986                symbol->name);
987
988     }
989 }
990
991 #define srec_close_and_cleanup _bfd_generic_close_and_cleanup
992 #define srec_bfd_free_cached_info _bfd_generic_bfd_free_cached_info
993 #define srec_new_section_hook _bfd_generic_new_section_hook
994
995 #define srec_bfd_is_local_label bfd_generic_is_local_label
996 #define srec_get_lineno _bfd_nosymbols_get_lineno
997 #define srec_find_nearest_line _bfd_nosymbols_find_nearest_line
998 #define srec_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol
999
1000 #define srec_bfd_get_relocated_section_contents \
1001   bfd_generic_get_relocated_section_contents
1002 #define srec_bfd_relax_section bfd_generic_relax_section
1003 #define srec_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
1004 #define srec_bfd_link_add_symbols _bfd_generic_link_add_symbols
1005 #define srec_bfd_final_link _bfd_generic_final_link
1006
1007 const bfd_target srec_vec =
1008 {
1009   "srec",                       /* name */
1010   bfd_target_srec_flavour,
1011   true,                         /* target byte order */
1012   true,                         /* target headers byte order */
1013   (HAS_RELOC | EXEC_P |         /* object flags */
1014    HAS_LINENO | HAS_DEBUG |
1015    HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
1016   (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS
1017    | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
1018   0,                            /* leading underscore */
1019   ' ',                          /* ar_pad_char */
1020   16,                           /* ar_max_namelen */
1021   1,                            /* minimum alignment */
1022   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
1023   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
1024   bfd_getb16, bfd_getb_signed_16, bfd_putb16,   /* data */
1025   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
1026   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
1027   bfd_getb16, bfd_getb_signed_16, bfd_putb16,   /* hdrs */
1028
1029   {
1030     _bfd_dummy_target,
1031     srec_object_p,              /* bfd_check_format */
1032     _bfd_dummy_target,
1033     _bfd_dummy_target,
1034   },
1035   {
1036     bfd_false,
1037     srec_mkobject,
1038     _bfd_generic_mkarchive,
1039     bfd_false,
1040   },
1041   {                             /* bfd_write_contents */
1042     bfd_false,
1043     srec_write_object_contents,
1044     _bfd_write_archive_contents,
1045     bfd_false,
1046   },
1047
1048   BFD_JUMP_TABLE_GENERIC (srec),
1049   BFD_JUMP_TABLE_COPY (_bfd_generic),
1050   BFD_JUMP_TABLE_CORE (_bfd_nocore),
1051   BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
1052   BFD_JUMP_TABLE_SYMBOLS (srec),
1053   BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
1054   BFD_JUMP_TABLE_WRITE (srec),
1055   BFD_JUMP_TABLE_LINK (srec),
1056   BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
1057
1058   (PTR) 0
1059 };
1060
1061
1062
1063 const bfd_target symbolsrec_vec =
1064 {
1065   "symbolsrec",                 /* name */
1066   bfd_target_srec_flavour,
1067   true,                         /* target byte order */
1068   true,                         /* target headers byte order */
1069   (HAS_RELOC | EXEC_P |         /* object flags */
1070    HAS_LINENO | HAS_DEBUG |
1071    HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
1072   (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS
1073    | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
1074   0,                            /* leading underscore */
1075   ' ',                          /* ar_pad_char */
1076   16,                           /* ar_max_namelen */
1077   1,                            /* minimum alignment */
1078   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
1079   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
1080   bfd_getb16, bfd_getb_signed_16, bfd_putb16,   /* data */
1081   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
1082   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
1083   bfd_getb16, bfd_getb_signed_16, bfd_putb16,   /* hdrs */
1084
1085   {
1086     _bfd_dummy_target,
1087     symbolsrec_object_p,        /* bfd_check_format */
1088     _bfd_dummy_target,
1089     _bfd_dummy_target,
1090   },
1091   {
1092     bfd_false,
1093     srec_mkobject,
1094     _bfd_generic_mkarchive,
1095     bfd_false,
1096   },
1097   {                             /* bfd_write_contents */
1098     bfd_false,
1099     symbolsrec_write_object_contents,
1100     _bfd_write_archive_contents,
1101     bfd_false,
1102   },
1103
1104   BFD_JUMP_TABLE_GENERIC (srec),
1105   BFD_JUMP_TABLE_COPY (_bfd_generic),
1106   BFD_JUMP_TABLE_CORE (_bfd_nocore),
1107   BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
1108   BFD_JUMP_TABLE_SYMBOLS (srec),
1109   BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
1110   BFD_JUMP_TABLE_WRITE (srec),
1111   BFD_JUMP_TABLE_LINK (srec),
1112   BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
1113
1114   (PTR) 0
1115 };