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