Insert copyright notices in all BFD files that need them.
[external/binutils.git] / bfd / srec.c
1 /* BFD back-end for s-record objects.
2    Copyright 1990, 1991, 1992 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         S-records cannot hold anything but addresses and data, so
28         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
75 #include "bfd.h"
76 #include "sysdep.h"
77 #include "libbfd.h"
78
79 /* Macros for converting between hex and binary */
80
81 static const char digs[] = "0123456789ABCDEF";
82
83 static char hex_value[1 + (unsigned char)~0];
84
85 #define NOT_HEX 20
86 #define NIBBLE(x) hex_value[(unsigned char)(x)]
87 #define HEX(buffer) ((NIBBLE((buffer)[0])<<4) + NIBBLE((buffer)[1]))
88 #define TOHEX(d, x, ch) \
89         d[1] = digs[(x) & 0xf]; \
90         d[0] = digs[((x)>>4)&0xf]; \
91         ch += ((x) & 0xff);
92 #define ISHEX(x)  (hex_value[(unsigned char)(x)] != NOT_HEX)
93
94
95
96 static void
97 DEFUN_VOID(srec_init) 
98 {
99     unsigned int i;
100     static boolean inited = false;
101     
102     if (inited == false) 
103     {
104         
105         inited = true;
106         
107         for (i = 0; i < sizeof (hex_value); i++) 
108         {
109             hex_value[i] = NOT_HEX;
110         }
111     
112         for (i = 0; i < 10; i++) 
113         {
114             hex_value[i + '0'] = i;
115         
116         }
117         for (i = 0; i < 6; i++) 
118         {
119             hex_value[i + 'a'] = i+10;
120             hex_value[i + 'A'] = i+10;
121         }
122     }    
123 }
124
125
126 /* The maximum number of bytes on a line is FF */
127 #define MAXCHUNK 0xff 
128 /* The number of bytes we fit onto a line on output */
129 #define CHUNK 21
130
131 /* We cannot output our srecords as we see them, we have to glue them
132    together, this is done in this structure : */
133
134 struct srec_data_list_struct
135 {
136     unsigned    char *data;
137     bfd_vma where;
138     bfd_size_type size;
139     struct srec_data_list_struct *next;
140     
141 } ;
142 typedef struct srec_data_list_struct srec_data_list_type;
143
144
145 typedef struct  srec_data_struct
146 {
147     srec_data_list_type *head;    
148     unsigned int type;
149
150 } tdata_type;
151
152
153
154 #define enda(x) (x->vma + x->size)
155 /* 
156    called once per input s-record, used to work out vma and size of data.
157  */
158
159 static bfd_vma low,high;
160
161 static void
162 DEFUN(size_srec,(abfd, section, address, raw, length),
163       bfd *abfd AND
164       asection *section AND
165       bfd_vma address AND
166       bfd_byte *raw AND
167       unsigned int length)
168 {
169   if (address < low)
170     low = address;
171   if (address + length > high) 
172     high = address + length -1;
173 }
174
175
176 /*
177  called once per input s-record, copies data from input into bfd_alloc'd area
178  */
179
180 static void
181 DEFUN(fillup,(abfd, section, address, raw, length),
182 bfd *abfd AND
183 asection *section AND
184 bfd_vma address AND
185 bfd_byte *raw AND
186 unsigned int length)
187 {
188     unsigned int i;
189     bfd_byte *dst =
190      (bfd_byte *)(section->used_by_bfd) +
191      address - section->vma;
192     /* length -1 because we don't read in the checksum */
193     for (i = 0; i < length -1 ; i++) {
194             *dst = HEX(raw);
195             dst++;
196             raw+=2;
197         }
198 }
199
200 /* Pass over an s-record file, calling one of the above functions on each
201    record.  */
202
203 static void
204 DEFUN(pass_over,(abfd, func, section),
205       bfd *abfd AND
206       void (*func)() AND
207       asection *section)
208 {
209     unsigned int bytes_on_line;
210     boolean eof = false;
211
212     /* To the front of the file */
213     bfd_seek(abfd, (file_ptr)0, SEEK_SET);
214     while (eof == false)
215     {
216         char buffer[MAXCHUNK];
217         char *src = buffer;
218         char type;
219         bfd_vma address = 0;
220
221         /* Find first 'S' */
222         eof =  (boolean)(bfd_read(src, 1, 1, abfd) != 1);
223         while (*src!= 'S' && !eof) {
224                 eof = (boolean)(bfd_read(src, 1, 1, abfd) != 1);
225             }
226         if (eof) break;
227         src++;
228
229         /* Fetch the type and the length */
230         bfd_read(src, 1, 3, abfd);
231
232         type = *src++;
233
234         if (!ISHEX (src[0]) || !ISHEX (src[1]))
235          break;
236
237         bytes_on_line = HEX(src);
238
239         if (bytes_on_line > MAXCHUNK/2)
240          break;
241         src+=2 ;
242
243         bfd_read(src, 1 , bytes_on_line * 2, abfd);
244
245         switch (type) {
246               case '0':
247               case '5':
248                 /* Prologue - ignore */
249                 break;
250              case '3':
251                 address = HEX(src);
252                 src+=2;
253                 bytes_on_line--;
254                 
255               case '2':
256                 address = HEX(src) | (address<<8) ;
257                 src+=2;
258                 bytes_on_line--;
259               case '1':
260                 address = HEX(src) | (address<<8) ;
261                 src+=2;
262                 address = HEX(src) | (address<<8) ;
263                 src+=2;
264                 bytes_on_line-=2;
265                 func(abfd,section, address, src, bytes_on_line);
266                 break;
267               default:
268                 return;
269             }
270     }
271
272 }
273
274
275
276 static bfd_target *
277 DEFUN(srec_object_p, (abfd),
278       bfd *abfd)
279 {
280   char b[4];
281   asection *section;
282   srec_init();
283   
284   bfd_seek(abfd, (file_ptr)0, SEEK_SET);
285   bfd_read(b, 1, 4, abfd);
286
287   if (b[0] != 'S' || !ISHEX(b[1]) || !ISHEX(b[2]) || !ISHEX(b[3]))
288     return (bfd_target*) NULL;
289   
290   /* We create one section called .text for all the contents, 
291      and allocate enough room for the entire file.  */
292
293   section =  bfd_make_section(abfd, ".text");
294   section->_raw_size = 0;
295   section->vma = 0xffffffff;
296   low = 0xffffffff;
297   high = 0;
298   pass_over(abfd, size_srec, section);
299   section->_raw_size = high - low;
300   section->vma = low;
301   section->flags = SEC_HAS_CONTENTS | SEC_LOAD | SEC_ALLOC;
302   
303   return abfd->xvec;
304 }
305
306
307 static boolean
308 DEFUN(srec_get_section_contents,(abfd, section, location, offset, count),
309       bfd *abfd AND
310       asection *section AND
311       PTR location AND
312       file_ptr offset AND
313       bfd_size_type count)
314 {
315     if (section->used_by_bfd == (PTR)NULL) 
316     {
317         section->used_by_bfd = (PTR)bfd_alloc (abfd, section->_raw_size);
318         pass_over(abfd, fillup, section);
319     }
320     (void) memcpy((PTR)location,
321                   (PTR)((char *)(section->used_by_bfd) + offset),
322                   count);
323     return true;
324 }
325       
326
327
328 boolean
329 DEFUN(srec_set_arch_mach,(abfd, arch, machine),
330       bfd *abfd AND
331       enum bfd_architecture arch AND
332       unsigned long machine)
333 {
334   return bfd_default_set_arch_mach(abfd, arch, machine);
335 }
336
337
338 /* we have to save up all the Srecords for a splurge before output,
339    also remember   */
340
341 static boolean
342 DEFUN(srec_set_section_contents,(abfd, section, location, offset, bytes_to_do),
343       bfd *abfd AND
344       sec_ptr section AND
345       PTR location AND
346       file_ptr offset AND
347       bfd_size_type bytes_to_do)
348 {
349   tdata_type  *tdata = abfd->tdata.srec_data;
350   srec_data_list_type *entry = (srec_data_list_type *)
351    bfd_alloc(abfd, sizeof(srec_data_list_type));
352   if ((section->flags & SEC_ALLOC)
353       && (section->flags & SEC_LOAD)) 
354   {
355     unsigned  char *data = (unsigned char *) bfd_alloc(abfd, bytes_to_do);
356     memcpy(data, location, bytes_to_do);
357
358     if ((section->vma + offset + bytes_to_do) <= 0xffff)  
359     {
360
361     }
362     else if ((section->vma + offset + bytes_to_do) <= 0xffffff 
363              && tdata->type < 2) 
364     {
365       tdata->type = 2;
366     }
367     else 
368     {
369       tdata->type = 3;
370     }
371
372     entry->data = data;
373     entry->where = section->vma + offset;
374     entry->size = bytes_to_do;
375     entry->next = tdata->head;
376     tdata->head = entry;
377   }
378   return true;    
379 }
380
381 /* Write a record of type, of the supplied number of bytes. The
382    supplied bytes and length don't have a checksum. That's worked out
383    here
384 */
385 static
386 void DEFUN(srec_write_record,(abfd, type, address, data, end),
387            bfd *abfd AND
388            char type AND
389            bfd_vma address AND
390            CONST unsigned char *data AND
391            CONST unsigned char *end)
392
393 {
394     char buffer[MAXCHUNK];
395     
396     unsigned int check_sum = 0;
397     unsigned CONST char *src = data;
398     char *dst =buffer;
399     char *length;
400     
401
402     *dst++ = 'S';
403     *dst++ = '0' + type;
404
405     length = dst;
406     dst+=2;                     /* leave room for dst*/
407     
408     switch (type) 
409     {
410       case 3:
411       case 7:
412         TOHEX(dst, (address >> 24), check_sum);
413         dst+=2;
414       case 8:
415       case 2:
416         TOHEX(dst, (address >> 16), check_sum);
417         dst+=2;
418       case 9:
419       case 1:
420       case 0:
421         TOHEX(dst, (address >> 8), check_sum);
422         dst+=2;
423         TOHEX(dst, (address), check_sum);
424         dst+=2;
425         break;
426
427     }
428     for (src = data; src < end; src++) 
429     {
430         TOHEX(dst, *src, check_sum);
431         dst+=2;
432     }
433
434     /* Fill in the length */
435     TOHEX(length, (dst - length)/2, check_sum);
436     check_sum &= 0xff;
437     check_sum = 255 - check_sum;
438     TOHEX(dst, check_sum, check_sum);
439     dst+=2;
440     
441     *dst ++ = '\n';
442     bfd_write((PTR)buffer, 1, dst - buffer , abfd);
443 }
444
445
446
447 static void
448 DEFUN(srec_write_header,(abfd),
449       bfd *abfd)
450 {
451     unsigned char buffer[MAXCHUNK];
452     unsigned char *dst = buffer;
453     unsigned int i;
454
455     /* I'll put an arbitary 40 char limit on header size */
456     for (i = 0; i < 40 && abfd->filename[i];  i++) 
457     {
458         *dst++ = abfd->filename[i];
459     }
460     srec_write_record(abfd,0, 0, buffer, dst);
461 }
462
463 static void
464 DEFUN(srec_write_section,(abfd, tdata, list),
465        bfd *abfd AND
466        tdata_type *tdata AND
467        srec_data_list_type *list)
468 {
469     unsigned int bytes_written = 0;
470     unsigned char *location = list->data;
471
472     while (bytes_written < list->size)
473     {
474         bfd_vma address;
475         
476         unsigned int bytes_this_chunk = list->size - bytes_written;
477
478         if (bytes_this_chunk > CHUNK) 
479         {
480             bytes_this_chunk = CHUNK;
481         }
482
483         address = list->where +  bytes_written;
484
485         srec_write_record(abfd,
486                           tdata->type,
487                           address,
488                           location,
489                           location + bytes_this_chunk);
490
491         bytes_written += bytes_this_chunk;
492         location += bytes_this_chunk;
493     }
494
495 }
496
497 static void
498 DEFUN(srec_write_terminator,(abfd, tdata),
499       bfd *abfd AND
500       tdata_type *tdata)
501 {
502     unsigned    char buffer[2];
503     
504     srec_write_record(abfd, 10 - tdata->type,
505                       abfd->start_address, buffer, buffer);
506
507
508 }
509 static boolean
510 DEFUN(srec_mkobject, (abfd), 
511       bfd *abfd)
512 {
513     tdata_type *tdata = (tdata_type *)bfd_alloc(abfd,  sizeof(tdata_type));
514     abfd->tdata.srec_data = tdata;
515     tdata->type = 1;
516     tdata->head = (srec_data_list_type *)NULL;
517     return true;
518     
519 }
520
521       
522 static boolean
523 DEFUN(srec_write_object_contents,(abfd),
524      bfd *abfd)
525 {
526     int bytes_written;
527     tdata_type *tdata = abfd->tdata.srec_data;
528     srec_data_list_type *list;
529
530     bytes_written = 0;
531
532
533     
534     srec_write_header(abfd);
535     
536     /* Now wander though all the sections provided and output them */
537     list = tdata->head;
538
539     while (list != (srec_data_list_type*)NULL) 
540     {
541         srec_write_section(abfd, tdata, list); 
542         list = list->next;
543     }
544     srec_write_terminator(abfd, tdata);
545     return true;
546 }
547
548 static int 
549 DEFUN(srec_sizeof_headers,(abfd, exec),
550       bfd *abfd AND
551       boolean exec)
552 {
553 return 0;
554 }
555
556 static asymbol *
557 DEFUN(srec_make_empty_symbol, (abfd),
558       bfd*abfd)
559 {
560   asymbol *new=  (asymbol *)bfd_zalloc (abfd, sizeof (asymbol));
561   new->the_bfd = abfd;
562   return new;
563 }
564 #define FOO PROTO
565 #define srec_new_section_hook (FOO(boolean, (*), (bfd *, asection *)))bfd_true
566 #define srec_get_symtab_upper_bound (PROTO(unsigned int, (*),(bfd *)))bfd_false
567 #define srec_get_symtab (FOO(unsigned int, (*), (bfd *, asymbol **)))bfd_0
568 #define srec_get_reloc_upper_bound (FOO(unsigned int, (*),(bfd*, asection *)))bfd_false
569 #define srec_canonicalize_reloc (FOO(unsigned int, (*),(bfd*,asection *, arelent **, asymbol **))) bfd_0
570
571 #define srec_print_symbol (FOO(void,(*),(bfd *, PTR, asymbol *, bfd_print_symbol_type))) bfd_void
572
573 #define srec_openr_next_archived_file (FOO(bfd *, (*), (bfd*,bfd*))) bfd_nullvoidptr
574 #define srec_find_nearest_line (FOO(boolean, (*),(bfd*,asection*,asymbol**,bfd_vma, CONST char**, CONST char**, unsigned int *))) bfd_false
575 #define srec_generic_stat_arch_elt  (FOO(int, (*), (bfd *,struct stat *))) bfd_0
576
577
578 #define srec_core_file_failing_command (char *(*)())(bfd_nullvoidptr)
579 #define srec_core_file_failing_signal (int (*)())bfd_0
580 #define srec_core_file_matches_executable_p (FOO(boolean, (*),(bfd*, bfd*)))bfd_false
581 #define srec_slurp_armap bfd_true
582 #define srec_slurp_extended_name_table bfd_true
583 #define srec_truncate_arname (void (*)())bfd_nullvoidptr
584 #define srec_write_armap  (FOO( boolean, (*),(bfd *, unsigned int, struct orl *, unsigned int, int))) bfd_nullvoidptr
585 #define srec_get_lineno (struct lineno_cache_entry *(*)())bfd_nullvoidptr
586 #define srec_close_and_cleanup  bfd_generic_close_and_cleanup
587 #define srec_bfd_debug_info_start bfd_void
588 #define srec_bfd_debug_info_end bfd_void
589 #define srec_bfd_debug_info_accumulate  (FOO(void, (*), (bfd *,  asection *))) bfd_void
590 #define srec_bfd_get_relocated_section_contents bfd_generic_get_relocated_section_contents
591 #define srec_bfd_relax_section bfd_generic_relax_section
592 bfd_target srec_vec =
593 {
594     "srec",                     /* name */
595     bfd_target_srec_flavour,
596     true,                       /* target byte order */
597     true,                       /* target headers byte order */
598     (HAS_RELOC | EXEC_P |       /* object flags */
599      HAS_LINENO | HAS_DEBUG |
600      HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT | D_PAGED),
601     (SEC_CODE|SEC_DATA|SEC_ROM|SEC_HAS_CONTENTS
602      |SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
603      0,                         /* leading underscore */
604     ' ',                        /* ar_pad_char */
605     16,                         /* ar_max_namelen */
606     1,                          /* minimum alignment */
607     _do_getb64, _do_putb64,  _do_getb32,
608     _do_putb32, _do_getb16, _do_putb16, /* data */
609     _do_getb64, _do_putb64,  _do_getb32,
610     _do_putb32, _do_getb16, _do_putb16, /* hdrs */
611
612   {
613       _bfd_dummy_target,
614       srec_object_p,            /* bfd_check_format */
615       (struct bfd_target *(*)()) bfd_nullvoidptr,
616       (struct bfd_target *(*)())     bfd_nullvoidptr,
617   },
618   {
619       bfd_false,
620       srec_mkobject,
621       _bfd_generic_mkarchive,
622       bfd_false,
623   },
624   {                             /* bfd_write_contents */
625       bfd_false,
626       srec_write_object_contents,
627       _bfd_write_archive_contents,
628       bfd_false,
629   },
630     JUMP_TABLE(srec)
631  };
632