* targets.c (bfd_target): Rearranged fields in target vector.
[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     unsigned int type;
186
187     int done_symbol_read;
188     int count;
189     asymbol *symbols;
190     char *strings;
191     int symbol_idx;
192     int string_size;
193     int string_idx;
194   }
195 tdata_type;
196
197 static boolean srec_write_section PARAMS ((bfd *, tdata_type *,
198                                            srec_data_list_type *));
199 static boolean srec_write_terminator PARAMS ((bfd *, tdata_type *));
200
201 /*
202    called once per input S-Record, used to work out vma and size of data.
203  */
204
205 static bfd_vma low, high;
206
207 /*ARGSUSED*/
208 static void
209 size_symbols (abfd, buf, len, val)
210      bfd *abfd;
211      char *buf;
212      int len;
213      int val;
214 {
215   abfd->symcount++;
216   abfd->tdata.srec_data->string_size += len + 1;
217 }
218
219 static void
220 fillup_symbols (abfd, buf, len, val)
221      bfd *abfd;
222      char *buf;
223      int len;
224      int val;
225 {
226   if (!abfd->tdata.srec_data->done_symbol_read)
227     {
228       asymbol *p;
229       if (abfd->tdata.srec_data->symbols == 0)
230         {
231           abfd->tdata.srec_data->symbols = (asymbol *) bfd_alloc (abfd, abfd->symcount * sizeof (asymbol));
232           abfd->tdata.srec_data->strings = (char *) bfd_alloc (abfd, abfd->tdata.srec_data->string_size);
233           if (!abfd->tdata.srec_data->symbols || !abfd->tdata.srec_data->strings)
234             {
235               bfd_set_error (bfd_error_no_memory);
236               abort ();         /* FIXME */
237             }
238           abfd->tdata.srec_data->symbol_idx = 0;
239           abfd->tdata.srec_data->string_idx = 0;
240         }
241
242       p = abfd->tdata.srec_data->symbols + abfd->tdata.srec_data->symbol_idx++;
243       p->the_bfd = abfd;
244       p->name = abfd->tdata.srec_data->strings + abfd->tdata.srec_data->string_idx;
245       memcpy ((char *) (p->name), buf, len + 1);
246       abfd->tdata.srec_data->string_idx += len + 1;
247       p->value = val;
248       p->flags = BSF_EXPORT | BSF_GLOBAL;
249       p->section = &bfd_abs_section;
250       p->udata = 0;
251     }
252 }
253 /*ARGSUSED*/
254 static void
255 size_srec (abfd, section, address, raw, length)
256      bfd *abfd;
257      asection *section;
258      bfd_vma address;
259      bfd_byte *raw;
260      unsigned int length;
261 {
262   if (address < low)
263     low = address;
264   if (address + length > high)
265     high = address + length - 1;
266 }
267
268
269 /*
270  called once per input S-Record, copies data from input into bfd_alloc'd area
271  */
272
273 /*ARGSUSED*/
274 static void
275 fillup (abfd, section, address, raw, length)
276      bfd *abfd;
277      asection *section;
278      bfd_vma address;
279      bfd_byte *raw;
280      unsigned int length;
281 {
282   unsigned int i;
283   bfd_byte *dst =
284   (bfd_byte *) (section->used_by_bfd) + address - section->vma;
285   /* length -1 because we don't read in the checksum */
286   for (i = 0; i < length - 1; i++)
287     {
288       *dst = HEX (raw);
289       dst++;
290       raw += 2;
291     }
292 }
293
294 /* Pass over an S-Record file, calling one of the above functions on each
295    record.  */
296
297 static int
298 white (x)
299      char x;
300 {
301   return (x == ' ' || x == '\t' || x == '\n' || x == '\r');
302 }
303 static int
304 skipwhite (src, abfd)
305      char *src;
306      bfd *abfd;
307 {
308   int eof = 0;
309   while (white (*src) && !eof)
310     {
311       eof = (boolean) (bfd_read (src, 1, 1, abfd) != 1);
312     }
313   return eof;
314 }
315
316 static boolean
317 srec_mkobject (abfd)
318      bfd *abfd;
319 {
320   if (abfd->tdata.srec_data == 0)
321     {
322       tdata_type *tdata = (tdata_type *) bfd_alloc (abfd, sizeof (tdata_type));
323       if (!tdata)
324         {
325           bfd_set_error (bfd_error_no_memory);
326           return false;
327         }
328       abfd->tdata.srec_data = tdata;
329       tdata->type = 1;
330       tdata->head = (srec_data_list_type *) NULL;
331     }
332   return true;
333
334 }
335
336 static void
337 pass_over (abfd, func, symbolfunc, section)
338      bfd *abfd;
339      void (*func) ();
340      void (*symbolfunc) ();
341      asection *section;
342 {
343   unsigned int bytes_on_line;
344   boolean eof = false;
345
346   srec_mkobject (abfd);
347   /* To the front of the file */
348   if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
349     abort ();
350   while (eof == false)
351     {
352       char buffer[MAXCHUNK];
353       char *src = buffer;
354       char type;
355       bfd_vma address = 0;
356
357       /* Find first 'S' or $ */
358       eof = (boolean) (bfd_read (src, 1, 1, abfd) != 1);
359       switch (*src)
360         {
361         default:
362           if (eof)
363             return;
364           break;
365
366         case '$':
367           /* Inside a symbol definition - just ignore the module name */
368           while (*src != '\n' && !eof)
369             {
370               eof = (boolean) (bfd_read (src, 1, 1, abfd) != 1);
371             }
372           break;
373
374         case ' ':
375           /* spaces - maybe just before a symbol */
376           while (*src != '\n' && *src != '\r' && white (*src))
377             {
378               eof = skipwhite (src, abfd);
379
380               {
381                 int val = 0;
382                 int slen = 0;
383                 char symbol[MAXCHUNK];
384
385                 /* get the symbol part */
386                 while (!eof && !white (*src) && slen < MAXCHUNK)
387                   {
388                     symbol[slen++] = *src;
389                     eof = (boolean) (bfd_read (src, 1, 1, abfd) != 1);
390                   }
391                 symbol[slen] = 0;
392                 eof = skipwhite (src, abfd);
393                 /* skip the $ for the hex value */
394                 if (*src == '$')
395                   {
396                     eof = (boolean) (bfd_read (src, 1, 1, abfd) != 1);
397                   }
398
399                 /* Scan off the hex number */
400                 while (isxdigit (*src))
401                   {
402                     val *= 16;
403                     if (isdigit (*src))
404                       val += *src - '0';
405                     else if (isupper (*src))
406                       {
407                         val += *src - 'A' + 10;
408                       }
409                     else
410                       {
411                         val += *src - 'a' + 10;
412                       }
413                     eof = (boolean) (bfd_read (src, 1, 1, abfd) != 1);
414                   }
415                 symbolfunc (abfd, symbol, slen, val);
416               }
417             }
418           break;
419         case 'S':
420           src++;
421
422           /* Fetch the type and the length */
423           if (bfd_read (src, 1, 3, abfd) != 3)
424             abort (); /* FIXME */
425
426           type = *src++;
427
428           if (!ISHEX (src[0]) || !ISHEX (src[1]))
429             break;
430
431           bytes_on_line = HEX (src);
432
433           if (bytes_on_line > MAXCHUNK / 2)
434             break;
435           src += 2;
436
437           if (bfd_read (src, 1, bytes_on_line * 2, abfd) != bytes_on_line * 2)
438             abort (); /* FIXME */
439
440           switch (type)
441             {
442             case '0':
443             case '5':
444               /* Prologue - ignore */
445               break;
446             case '3':
447               address = HEX (src);
448               src += 2;
449               bytes_on_line--;
450
451             case '2':
452               address = HEX (src) | (address << 8);
453               src += 2;
454               bytes_on_line--;
455             case '1':
456               address = HEX (src) | (address << 8);
457               src += 2;
458               address = HEX (src) | (address << 8);
459               src += 2;
460               bytes_on_line -= 2;
461               func (abfd, section, address, src, bytes_on_line);
462               break;
463             default:
464               return;
465             }
466         }
467     }
468
469 }
470
471 static bfd_target *
472 object_p (abfd)
473      bfd *abfd;
474 {
475   asection *section;
476   /* We create one section called .text for all the contents,
477      and allocate enough room for the entire file.  */
478
479   section = bfd_make_section (abfd, ".text");
480   section->_raw_size = 0;
481   section->vma = 0xffffffff;
482   low = 0xffffffff;
483   high = 0;
484   pass_over (abfd, size_srec, size_symbols, section);
485   section->_raw_size = high - low;
486   section->vma = low;
487   section->flags = SEC_HAS_CONTENTS | SEC_LOAD | SEC_ALLOC;
488
489   if (abfd->symcount)
490     abfd->flags |= HAS_SYMS;
491   return abfd->xvec;
492 }
493
494 static bfd_target *
495 srec_object_p (abfd)
496      bfd *abfd;
497 {
498   char b[4];
499
500   srec_init ();
501
502   if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0
503       || bfd_read (b, 1, 4, abfd) != 4)
504     return NULL;
505
506   if (b[0] != 'S' || !ISHEX (b[1]) || !ISHEX (b[2]) || !ISHEX (b[3]))
507     return (bfd_target *) NULL;
508
509   /* We create one section called .text for all the contents,
510      and allocate enough room for the entire file.  */
511
512   return object_p (abfd);
513 }
514
515
516 static bfd_target *
517 symbolsrec_object_p (abfd)
518      bfd *abfd;
519 {
520   char b[4];
521
522   srec_init ();
523
524   if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0
525       || bfd_read (b, 1, 4, abfd) != 4)
526     return NULL;
527
528   if (b[0] != '$' || b[1] != '$')
529     return (bfd_target *) NULL;
530
531   return object_p (abfd);
532 }
533
534
535 static boolean
536 srec_get_section_contents (abfd, section, location, offset, count)
537      bfd *abfd;
538      asection *section;
539      PTR location;
540      file_ptr offset;
541      bfd_size_type count;
542 {
543   if (section->used_by_bfd == (PTR) NULL)
544     {
545       section->used_by_bfd = (PTR) bfd_alloc (abfd, section->_raw_size);
546       if (!section->used_by_bfd)
547         {
548           bfd_set_error (bfd_error_no_memory);
549           return false;
550         }
551
552       pass_over (abfd, fillup, fillup_symbols, section);
553     }
554   memcpy ((PTR) location,
555           (PTR) ((char *) (section->used_by_bfd) + offset),
556           count);
557   return true;
558 }
559
560
561
562 boolean
563 srec_set_arch_mach (abfd, arch, machine)
564      bfd *abfd;
565      enum bfd_architecture arch;
566      unsigned long machine;
567 {
568   return bfd_default_set_arch_mach (abfd, arch, machine);
569 }
570
571
572 /* we have to save up all the Srecords for a splurge before output,
573    also remember   */
574
575 static boolean
576 srec_set_section_contents (abfd, section, location, offset, bytes_to_do)
577      bfd *abfd;
578      sec_ptr section;
579      PTR location;
580      file_ptr offset;
581      bfd_size_type bytes_to_do;
582 {
583   tdata_type *tdata = abfd->tdata.srec_data;
584   srec_data_list_type *entry = (srec_data_list_type *)
585   bfd_alloc (abfd, sizeof (srec_data_list_type));
586
587   if (!entry)
588     {
589       bfd_set_error (bfd_error_no_memory);
590       return false;
591     }
592
593   if ((section->flags & SEC_ALLOC)
594       && (section->flags & SEC_LOAD))
595     {
596       unsigned char *data = (unsigned char *) bfd_alloc (abfd, bytes_to_do);
597       if (!data)
598         {
599           bfd_set_error (bfd_error_no_memory);
600           return false;
601         }
602       memcpy ((PTR) data, location, bytes_to_do);
603
604       if ((section->lma + offset + bytes_to_do) <= 0xffff)
605         {
606
607         }
608       else if ((section->lma + offset + bytes_to_do) <= 0xffffff
609                && tdata->type < 2)
610         {
611           tdata->type = 2;
612         }
613       else
614         {
615           tdata->type = 3;
616         }
617
618       entry->data = data;
619       entry->where = section->lma + offset;
620       entry->size = bytes_to_do;
621       entry->next = tdata->head;
622       tdata->head = entry;
623     }
624   return true;
625 }
626
627 /* Write a record of type, of the supplied number of bytes. The
628    supplied bytes and length don't have a checksum. That's worked out
629    here
630 */
631 static boolean
632 srec_write_record (abfd, type, address, data, end)
633      bfd *abfd;
634      int type;
635      bfd_vma address;
636      const unsigned char *data;
637      const unsigned char *end;
638 {
639   char buffer[MAXCHUNK];
640
641   unsigned int check_sum = 0;
642   CONST unsigned char *src = data;
643   char *dst = buffer;
644   char *length;
645
646
647   *dst++ = 'S';
648   *dst++ = '0' + type;
649
650   length = dst;
651   dst += 2;                     /* leave room for dst*/
652
653   switch (type)
654     {
655     case 3:
656     case 7:
657       TOHEX (dst, (address >> 24), check_sum);
658       dst += 2;
659     case 8:
660     case 2:
661       TOHEX (dst, (address >> 16), check_sum);
662       dst += 2;
663     case 9:
664     case 1:
665     case 0:
666       TOHEX (dst, (address >> 8), check_sum);
667       dst += 2;
668       TOHEX (dst, (address), check_sum);
669       dst += 2;
670       break;
671
672     }
673   for (src = data; src < end; src++)
674     {
675       TOHEX (dst, *src, check_sum);
676       dst += 2;
677     }
678
679   /* Fill in the length */
680   TOHEX (length, (dst - length) / 2, check_sum);
681   check_sum &= 0xff;
682   check_sum = 255 - check_sum;
683   TOHEX (dst, check_sum, check_sum);
684   dst += 2;
685
686   *dst++ = '\r';
687   *dst++ = '\n';
688   if (bfd_write ((PTR) buffer, 1, dst - buffer, abfd) != dst - buffer)
689     return false;
690   return true;
691 }
692
693
694
695 static boolean
696 srec_write_header (abfd)
697      bfd *abfd;
698 {
699   unsigned char buffer[MAXCHUNK];
700   unsigned char *dst = buffer;
701   unsigned int i;
702
703   /* I'll put an arbitary 40 char limit on header size */
704   for (i = 0; i < 40 && abfd->filename[i]; i++)
705     {
706       *dst++ = abfd->filename[i];
707     }
708   return srec_write_record (abfd, 0, 0, buffer, dst);
709 }
710
711 static boolean
712 srec_write_section (abfd, tdata, list)
713      bfd *abfd;
714      tdata_type *tdata;
715      srec_data_list_type *list;
716 {
717   unsigned int bytes_written = 0;
718   unsigned char *location = list->data;
719
720   while (bytes_written < list->size)
721     {
722       bfd_vma address;
723
724       unsigned int bytes_this_chunk = list->size - bytes_written;
725
726       if (bytes_this_chunk > CHUNK)
727         {
728           bytes_this_chunk = CHUNK;
729         }
730
731       address = list->where + bytes_written;
732
733       if (! srec_write_record (abfd,
734                                tdata->type,
735                                address,
736                                location,
737                                location + bytes_this_chunk))
738         return false;
739
740       bytes_written += bytes_this_chunk;
741       location += bytes_this_chunk;
742     }
743
744   return true;
745 }
746
747 static boolean
748 srec_write_terminator (abfd, tdata)
749      bfd *abfd;
750      tdata_type *tdata;
751 {
752   unsigned char buffer[2];
753
754   return srec_write_record (abfd, 10 - tdata->type,
755                             abfd->start_address, buffer, buffer);
756 }
757
758
759
760 static boolean
761 srec_write_symbols (abfd)
762      bfd *abfd;
763 {
764   char buffer[MAXCHUNK];
765   /* Dump out the symbols of a bfd */
766   int i;
767   int len = bfd_get_symcount (abfd);
768
769   if (len)
770     {
771       size_t len;
772       asymbol **table = bfd_get_outsymbols (abfd);
773       sprintf (buffer, "$$ %s\r\n", abfd->filename);
774
775       len = strlen (buffer) + 1;
776       if (bfd_write (buffer, len, 1, abfd) != len)
777         return false;
778
779       for (i = 0; i < len; i++)
780         {
781           asymbol *s = table[i];
782 #if 0
783           int len = strlen (s->name);
784
785           /* If this symbol has a .[ocs] in it, it's probably a file name
786          and we'll output that as the module name */
787
788           if (len > 3 && s->name[len - 2] == '.')
789             {
790               int l;
791               sprintf (buffer, "$$ %s\r\n", s->name);
792               l = strlen (buffer);
793               if (bfd_write (buffer, l, 1, abfd) != l)
794                 return false;
795             }
796           else
797 #endif
798             if (s->flags & (BSF_GLOBAL | BSF_LOCAL)
799                 && (s->flags & BSF_DEBUGGING) == 0
800                 && s->name[0] != '.'
801                 && s->name[0] != 't')
802             {
803               /* Just dump out non debug symbols */
804
805               int l;
806               char buf2[40], *p;
807
808               sprintf_vma (buf2,
809                            s->value + s->section->output_section->lma
810                            + s->section->output_offset);
811               p = buf2;
812               while (p[0] == '0' && p[1] != 0)
813                 p++;
814               sprintf (buffer, "  %s $%s\r\n", s->name, p);
815               l = strlen (buffer);
816               if (bfd_write (buffer, l, 1, abfd) != l)
817                 return false;
818             }
819         }
820       sprintf (buffer, "$$ \r\n");
821       len = strlen (buffer) + 1;
822       if (bfd_write (buffer, len, 1, abfd) != len)
823         return false;
824     }
825
826   return true;
827 }
828
829 static boolean
830 internal_srec_write_object_contents (abfd, symbols)
831      bfd *abfd;
832      int symbols;
833 {
834   tdata_type *tdata = abfd->tdata.srec_data;
835   srec_data_list_type *list;
836
837   if (symbols)
838     {
839       if (! srec_write_symbols (abfd))
840         return false;
841     }
842
843   if (! srec_write_header (abfd))
844     return false;
845
846   /* Now wander though all the sections provided and output them */
847   list = tdata->head;
848
849   while (list != (srec_data_list_type *) NULL)
850     {
851       if (! srec_write_section (abfd, tdata, list))
852         return false;
853       list = list->next;
854     }
855   return srec_write_terminator (abfd, tdata);
856 }
857
858 static boolean
859 srec_write_object_contents (abfd)
860      bfd *abfd;
861 {
862   return internal_srec_write_object_contents (abfd, 0);
863 }
864
865 static boolean
866 symbolsrec_write_object_contents (abfd)
867      bfd *abfd;
868 {
869   return internal_srec_write_object_contents (abfd, 1);
870 }
871
872 /*ARGSUSED*/
873 static int
874 srec_sizeof_headers (abfd, exec)
875      bfd *abfd;
876      boolean exec;
877 {
878   return 0;
879 }
880
881 static asymbol *
882 srec_make_empty_symbol (abfd)
883      bfd *abfd;
884 {
885   asymbol *new = (asymbol *) bfd_zalloc (abfd, sizeof (asymbol));
886   if (new)
887     new->the_bfd = abfd;
888   return new;
889 }
890
891 static long
892 srec_get_symtab_upper_bound (abfd)
893      bfd *abfd;
894 {
895   /* Read in all the info */
896   if (! srec_get_section_contents (abfd, abfd->sections, 0, 0, 0))
897     return -1;
898   return (bfd_get_symcount (abfd) + 1) * (sizeof (asymbol *));
899 }
900
901 static long
902 srec_get_symtab (abfd, alocation)
903      bfd *abfd;
904      asymbol **alocation;
905 {
906   int lim = abfd->symcount;
907   int i;
908   for (i = 0; i < lim; i++)
909     {
910       alocation[i] = abfd->tdata.srec_data->symbols + i;
911     }
912   alocation[i] = 0;
913   return lim;
914 }
915
916 /*ARGSUSED*/
917 void
918 srec_get_symbol_info (ignore_abfd, symbol, ret)
919      bfd *ignore_abfd;
920      asymbol *symbol;
921      symbol_info *ret;
922 {
923   bfd_symbol_info (symbol, ret);
924 }
925
926 /*ARGSUSED*/
927 void
928 srec_print_symbol (ignore_abfd, afile, symbol, how)
929      bfd *ignore_abfd;
930      PTR afile;
931      asymbol *symbol;
932      bfd_print_symbol_type how;
933 {
934   FILE *file = (FILE *) afile;
935   switch (how)
936     {
937     case bfd_print_symbol_name:
938       fprintf (file, "%s", symbol->name);
939       break;
940     default:
941       bfd_print_symbol_vandf ((PTR) file, symbol);
942       fprintf (file, " %-5s %s",
943                symbol->section->name,
944                symbol->name);
945
946     }
947 }
948
949 #define srec_close_and_cleanup _bfd_generic_close_and_cleanup
950 #define srec_bfd_free_cached_info _bfd_generic_bfd_free_cached_info
951 #define srec_new_section_hook _bfd_generic_new_section_hook
952
953 #define srec_bfd_is_local_label bfd_generic_is_local_label
954 #define srec_get_lineno _bfd_nosymbols_get_lineno
955 #define srec_find_nearest_line _bfd_nosymbols_find_nearest_line
956 #define srec_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol
957
958 #define srec_bfd_get_relocated_section_contents \
959   bfd_generic_get_relocated_section_contents
960 #define srec_bfd_relax_section bfd_generic_relax_section
961 #define srec_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
962 #define srec_bfd_link_add_symbols _bfd_generic_link_add_symbols
963 #define srec_bfd_final_link _bfd_generic_final_link
964
965 bfd_target srec_vec =
966 {
967   "srec",                       /* name */
968   bfd_target_srec_flavour,
969   true,                         /* target byte order */
970   true,                         /* target headers byte order */
971   (HAS_RELOC | EXEC_P |         /* object flags */
972    HAS_LINENO | HAS_DEBUG |
973    HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
974   (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS
975    | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
976   0,                            /* leading underscore */
977   ' ',                          /* ar_pad_char */
978   16,                           /* ar_max_namelen */
979   1,                            /* minimum alignment */
980   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
981   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
982   bfd_getb16, bfd_getb_signed_16, bfd_putb16,   /* data */
983   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
984   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
985   bfd_getb16, bfd_getb_signed_16, bfd_putb16,   /* hdrs */
986
987   {
988     _bfd_dummy_target,
989     srec_object_p,              /* bfd_check_format */
990     (struct bfd_target * (*)()) bfd_nullvoidptr,
991     (struct bfd_target * (*)()) bfd_nullvoidptr,
992   },
993   {
994     bfd_false,
995     srec_mkobject,
996     _bfd_generic_mkarchive,
997     bfd_false,
998   },
999   {                             /* bfd_write_contents */
1000     bfd_false,
1001     srec_write_object_contents,
1002     _bfd_write_archive_contents,
1003     bfd_false,
1004   },
1005
1006   BFD_JUMP_TABLE_GENERIC (srec),
1007   BFD_JUMP_TABLE_COPY (_bfd_generic),
1008   BFD_JUMP_TABLE_CORE (_bfd_nocore),
1009   BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
1010   BFD_JUMP_TABLE_SYMBOLS (srec),
1011   BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
1012   BFD_JUMP_TABLE_WRITE (srec),
1013   BFD_JUMP_TABLE_LINK (srec),
1014
1015   (PTR) 0
1016 };
1017
1018
1019
1020 bfd_target symbolsrec_vec =
1021 {
1022   "symbolsrec",                 /* name */
1023   bfd_target_srec_flavour,
1024   true,                         /* target byte order */
1025   true,                         /* target headers byte order */
1026   (HAS_RELOC | EXEC_P |         /* object flags */
1027    HAS_LINENO | HAS_DEBUG |
1028    HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
1029   (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS
1030    | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
1031   0,                            /* leading underscore */
1032   ' ',                          /* ar_pad_char */
1033   16,                           /* ar_max_namelen */
1034   1,                            /* minimum alignment */
1035   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
1036   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
1037   bfd_getb16, bfd_getb_signed_16, bfd_putb16,   /* data */
1038   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
1039   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
1040   bfd_getb16, bfd_getb_signed_16, bfd_putb16,   /* hdrs */
1041
1042   {
1043     _bfd_dummy_target,
1044     symbolsrec_object_p,        /* bfd_check_format */
1045     (struct bfd_target * (*)()) bfd_nullvoidptr,
1046     (struct bfd_target * (*)()) bfd_nullvoidptr,
1047   },
1048   {
1049     bfd_false,
1050     srec_mkobject,
1051     _bfd_generic_mkarchive,
1052     bfd_false,
1053   },
1054   {                             /* bfd_write_contents */
1055     bfd_false,
1056     symbolsrec_write_object_contents,
1057     _bfd_write_archive_contents,
1058     bfd_false,
1059   },
1060
1061   BFD_JUMP_TABLE_GENERIC (srec),
1062   BFD_JUMP_TABLE_COPY (_bfd_generic),
1063   BFD_JUMP_TABLE_CORE (_bfd_nocore),
1064   BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
1065   BFD_JUMP_TABLE_SYMBOLS (srec),
1066   BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
1067   BFD_JUMP_TABLE_WRITE (srec),
1068   BFD_JUMP_TABLE_LINK (srec),
1069
1070   (PTR) 0
1071 };