Fix minor pointer type problems that "cc" complains about.
[external/binutils.git] / bfd / srec.c
1 /* Copyright (C) 1990, 1991 Free Software Foundation, Inc.
2
3 This file is part of BFD, the Binary File Diddler.
4
5 BFD is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 1, or (at your option)
8 any later version.
9
10 BFD is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with BFD; see the file COPYING.  If not, write to
17 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
18
19 /*
20
21  bfd backend for srecord objects.
22
23  Srecords cannot hold anything but addresses and data, so that's all
24  that we impliment.
25  
26  The only interesting thing is that srecords may come out of order and
27  there is no header, so an initial scan is required to discover the
28  minimum and maximum addresses used to create the vma and size of the
29  only section we create. We arbitarily call this section ".text".
30
31  When bfd_get_section_contents is called the file is read again, and
32  this time the data is placed into a malloced area.
33
34  Any number of sections may be created for output, we just output them
35  in the order provided to bfd_set_section_contents.
36
37
38  Steve Chamberlain steve@cygnus.com
39
40  */
41
42
43 /* $Id$
44  * $Log$
45  * Revision 1.6  1991/04/25 04:06:21  gnu
46  * Fix minor pointer type problems that "cc" complains about.
47  *
48  * Revision 1.5  1991/04/23  22:44:14  steve
49  * *** empty log message ***
50  *
51  * Revision 1.4  1991/04/23  16:01:02  steve
52  * *** empty log message ***
53  *
54  * Revision 1.3  1991/04/08  23:22:31  steve
55  * *** empty log message ***
56  *
57  * Revision 1.2  1991/04/03  22:10:51  steve
58  * Fixed typo
59  *
60  * Revision 1.1.1.1  1991/03/21  21:11:22  gumby
61  * Back from Intel with Steve
62  *
63  * Revision 1.1  1991/03/21  21:11:20  gumby
64  * Initial revision
65  *
66  * Revision 1.1  1991/03/13  00:22:29  chrisb
67  * Initial revision
68  *
69  * Revision 1.3  1991/03/10  19:11:40  rich
70  *  Modified Files:
71  *      bfd.c coff-code.h libbfd.c libbfd.h srec.c sunos.c
72  *
73  * Working bugs out of coff support.
74  *
75  * Revision 1.2  1991/03/07  02:26:18  sac
76  * Tidied up xfer table
77  *
78  * Revision 1.1  1991/03/05  16:28:12  sac
79  * Initial revision
80  *
81  */
82 #include "sysdep.h"
83 #include "bfd.h"
84 #include "libbfd.h"
85
86
87 static char digs[] = "0123456789ABCDEF";
88
89 /* Macros for converting between hex and binary */
90
91 #define NIBBLE(x) ((x >= '0' && x <= '9') ? (x - '0') : (x - 'A' + 10))
92 #define HEX(buffer) ((NIBBLE((buffer)->high) <<4) + NIBBLE((buffer)->low))
93 #define TOHEX(d,x) \
94   ((d)->low = digs[(x) & 0xf], (d)->high = digs[((x)>>4)&0xf], x)
95
96 typedef struct {
97   char high;
98   char low;
99 } byte_as_two_char_type;
100
101 /* The maximum number of bytes on a line is FF */
102 #define MAXCHUNK 0xff 
103 /* The number of bytes we fit onto a line on output */
104 #define CHUNK 16 
105
106 /* The shape of an srecord .. */
107 typedef struct 
108 {
109   char S;
110   char type;
111   byte_as_two_char_type size;
112   union {
113     struct {
114       byte_as_two_char_type address[4];
115       byte_as_two_char_type data[MAXCHUNK];
116       /* If there isn't MAXCHUNK bytes of data then the checksum will 
117          appear earlier */
118       byte_as_two_char_type checksum;
119       char nl;
120     } type_3;
121     struct {
122       byte_as_two_char_type address[4];
123       byte_as_two_char_type data[MAXCHUNK];
124       byte_as_two_char_type checksum;
125       char nl;
126     } type_6;
127
128     struct {
129       byte_as_two_char_type address[3];
130       byte_as_two_char_type data[MAXCHUNK];
131       byte_as_two_char_type checksum;
132       char nl;
133     } type_2;
134
135     struct {
136       byte_as_two_char_type address[2];
137       byte_as_two_char_type data[MAXCHUNK];
138       byte_as_two_char_type checksum;
139       char nl;
140     } type_1;
141     byte_as_two_char_type data[MAXCHUNK];
142   } u;
143 } srec_type;
144
145
146 /* 
147    called once per input srecord, used to work out vma and size of data.
148  */
149
150 static void
151 size_srec(abfd, section, address, raw, length)
152 bfd *abfd;
153 asection *section;
154 bfd_vma address;
155 byte_as_two_char_type *raw;
156 unsigned int length;
157 {
158   if (address < section->vma)
159     section->vma = address;
160
161   if (address + length  > section->vma + section->size)
162     section->size = (address+length) -  section->vma;
163 }
164
165 /*
166  called once per input srecord, copies data from input into malloced area
167  */
168
169 static void
170 fillup(abfd, section, address, raw, length)
171 bfd *abfd;
172 asection *section;
173 bfd_vma address;
174 byte_as_two_char_type *raw;
175 unsigned int length;
176 {
177   unsigned int i;
178   bfd_byte *dst = (bfd_byte *)(section->used_by_bfd) +  address - section->vma;
179   for (i = 0; i < length; i++) {
180     *dst = HEX(raw);
181     dst++;
182     raw++;
183   }
184 }
185
186 /*
187  pass over an srecord file calling one of the above functions on each
188  record
189  */
190 static void
191 pass_over(abfd, func, section)
192 bfd *abfd;
193 void (*func)();
194 asection *section;
195 {
196   unsigned int bytes_on_line;
197   boolean eof = false;
198   bfd_vma address;
199   /* To the front of the file */
200   bfd_seek(abfd, (file_ptr)0, SEEK_SET);
201   while (eof == false)
202     {
203       srec_type buffer;
204
205       /* Find first 'S' */
206       eof =  bfd_read(&buffer.S, 1, 1, abfd) != 1;
207       while (buffer.S != 'S' && !eof) {
208         eof =  bfd_read(&buffer.S, 1, 1, abfd) != 1;
209       }
210       if (eof) break;
211
212       bfd_read(&buffer.type, 1, 3, abfd);
213
214       bytes_on_line = HEX(&buffer.size);
215     
216       bfd_read(buffer.u.data, 1 , bytes_on_line * 2, abfd);
217
218       switch (buffer.type) {
219       case '6':
220         /* Prologue - ignore */
221         break;
222       case '3':
223         address = (HEX(buffer.u.type_3.address+0) << 24)
224           + (HEX(buffer.u.type_3.address+1) << 16)
225             + (HEX(buffer.u.type_3.address+2) << 8) 
226               + (HEX(buffer.u.type_3.address+3));
227         func(abfd,section, address, buffer.u.type_2.data, bytes_on_line -1);
228
229         break;
230
231       case '2':
232         address = (HEX(buffer.u.type_2.address+0) << 16)+
233           (HEX(buffer.u.type_2.address+1) << 8) +
234         (HEX(buffer.u.type_2.address+2));
235         func(abfd,section, address, buffer.u.type_2.data, bytes_on_line -1);
236
237         break;
238       case '1':
239         address =
240           (HEX(buffer.u.type_1.address+0) << 8) 
241             + (HEX(buffer.u.type_1.address+1));
242         func(abfd, section, address, buffer.u.type_1.data, bytes_on_line -1);
243         break;
244
245       }
246     }
247 }
248
249
250 bfd_target *
251 srec_object_p (abfd)
252 bfd *abfd;
253 {
254   char b;
255   asection *section;
256   bfd_seek(abfd, (file_ptr)0, SEEK_SET);
257   bfd_read(&b, 1,1,abfd);
258   if (b != 'S') return (bfd_target*)NULL;
259
260   /* 
261      We create one section called data for all the contents, 
262      and allocate enough room for the entire file
263      */
264
265
266   section =  bfd_make_section(abfd, ".text");
267   section->size = 0;
268   section->vma = 0xffffffff;
269   pass_over(abfd, size_srec, section);
270
271   return abfd->xvec;
272 }
273
274
275
276
277
278
279
280
281 static boolean
282 srec_get_section_contents (abfd, section, location, offset, count)
283 bfd *abfd;
284 sec_ptr section;
285 void  *location;
286 file_ptr offset;
287 unsigned      int count;
288 {
289   if (section->used_by_bfd == (PTR)NULL) {
290     section->used_by_bfd = (PTR)malloc(section->size);
291     pass_over(abfd, fillup, section);
292   }
293   (void) memcpy(location, (bfd_byte *)(section->used_by_bfd) + offset, count);
294   return true;
295 }
296       
297
298
299 boolean
300 srec_set_arch_mach (abfd, arch, machine)
301 bfd *abfd;
302 enum bfd_architecture arch;
303 unsigned long machine;
304 {
305   abfd->obj_arch = arch;
306   abfd->obj_machine = machine;
307   return true;
308 }
309
310
311
312 boolean
313 srec_set_section_contents (abfd, section, location, offset, bytes_to_do)
314 bfd *abfd;
315 sec_ptr section;
316 unsigned char *location;
317 file_ptr offset;
318 int bytes_to_do;
319 {
320   bfd_vma address;
321   int bytes_written;
322
323   int type;
324   unsigned int i;
325   srec_type buffer;
326   bytes_written = 0;
327   if (section->size <= 0xffff) 
328     type = 1;
329   else if (section->size <= 0xffffff) 
330     type = 2;
331   else
332     type = 3;
333
334   buffer.S = 'S';
335   buffer.type = '0' + type;
336
337   while (bytes_written < bytes_to_do) {
338     unsigned int size;
339     unsigned int check_sum;
340     byte_as_two_char_type *data; 
341  unsigned   int bytes_this_chunk = bytes_to_do - bytes_written;
342
343     if (bytes_this_chunk > CHUNK) {
344       bytes_this_chunk = CHUNK;
345     }
346
347     address = section->vma + offset + bytes_written;
348
349     switch (type) {
350     case 3:
351       check_sum = TOHEX(buffer.u.type_3.address, address >> 24);
352       check_sum += TOHEX(buffer.u.type_3.address+1, address >> 16);
353       check_sum += TOHEX(buffer.u.type_3.address+2, address >> 8);
354       check_sum += TOHEX(buffer.u.type_3.address+3, address >> 0);
355       size = bytes_this_chunk + 5;
356       data = buffer.u.type_3.data;
357
358     case 2:
359       check_sum = TOHEX(buffer.u.type_3.address, address >> 16);
360       check_sum += TOHEX(buffer.u.type_3.address+1, address >> 8);
361       check_sum += TOHEX(buffer.u.type_3.address+2, address >> 0);
362       size = bytes_this_chunk + 4;
363       data = buffer.u.type_2.data;
364       break;
365
366     case 1:
367       check_sum = TOHEX(buffer.u.type_3.address+0, address >> 8);
368       check_sum += TOHEX(buffer.u.type_3.address+1, address >> 0);
369       size = bytes_this_chunk + 3;
370       data = buffer.u.type_1.data;
371     }
372
373     for (i = 0; i < bytes_this_chunk; i++) {
374       check_sum += TOHEX(data, (location[i]));
375       data++;
376     }
377
378     check_sum += TOHEX(&(buffer.size), size );
379     (void) TOHEX(data, ~check_sum);
380     data++;
381
382     * ( (char *)(data)) = '\n';
383     bfd_write(&buffer, 1, (char *)data - (char *)&buffer + 1 , abfd);
384
385     bytes_written += bytes_this_chunk;
386     location += bytes_this_chunk;
387   }
388
389
390   return true;
391 }
392
393
394 boolean
395 srec_close_and_cleanup (abfd)
396 bfd *abfd;
397 {
398   asection *s;
399   if (bfd_read_p (abfd) == false) {
400     switch (abfd->format) {
401     case bfd_archive:
402       if (!_bfd_write_archive_contents (abfd)) {
403         return false;
404       }
405       break;
406     case bfd_object:
407       bfd_write("S9030000FC\n", 1,11,abfd);
408       break;
409     default:
410       bfd_error = invalid_operation;
411       return false;
412     }
413   }
414   for (s = abfd->sections; s != (asection *)NULL;s = s->next) {
415     if (s->used_by_bfd != (void *)NULL) {
416       free(s->used_by_bfd);
417     }
418   }
419   return true;
420 }
421
422 static int 
423 DEFUN(srec_sizeof_headers,(abfd),
424       bfd *abfd)
425 {
426 return 0;
427 }
428
429 /*SUPPRESS 460 */
430 #define srec_core_file_failing_command bfd_false
431 #define srec_core_file_failing_signal bfd_false
432 #define srec_core_file_matches_executable_p bfd_false
433 #define srec_slurp_armap bfd_false
434 #define srec_slurp_extended_name_table bfd_false
435 #define srec_truncate_arname bfd_false
436 #define srec_write_armap bfd_false
437 #define srec_new_section_hook bfd_false
438 #define srec_get_symtab_upper_bound bfd_false
439 #define srec_get_symtab bfd_false
440 #define srec_get_reloc_upper_bound bfd_false
441 #define srec_canonicalize_reloc bfd_false
442 #define srec_make_empty_symbol bfd_false
443 #define srec_print_symbol bfd_false
444 #define srec_get_lineno bfd_false
445 #define srec_openr_next_archived_file bfd_false
446 #define srec_find_nearest_line bfd_false
447 #define srec_generic_stat_arch_elt bfd_false
448
449 bfd_target srec_vec =
450 {
451   "srec",                       /* name */
452   bfd_target_srec_flavour_enum,
453   true,                         /* target byte order */
454   true,                         /* target headers byte order */
455   (HAS_RELOC | EXEC_P |         /* object flags */
456    HAS_LINENO | HAS_DEBUG |
457    HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT | D_PAGED),
458   (SEC_CODE|SEC_DATA|SEC_ROM|SEC_HAS_CONTENTS
459    |SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
460   ' ',                          /* ar_pad_char */
461   16,                           /* ar_max_namelen */
462   _do_getblong, _do_putblong, _do_getbshort, _do_putbshort, /* data */
463   _do_getblong, _do_putblong, _do_getbshort, _do_putbshort, /* hdrs */
464
465   {_bfd_dummy_target,
466      srec_object_p,             /* bfd_check_format */
467      (struct bfd_target *(*)()) bfd_nullvoidptr,
468      (struct bfd_target *(*)())     bfd_nullvoidptr,
469    },
470   {
471     bfd_false,
472     bfd_true,                   /* mkobject */
473     _bfd_generic_mkarchive,
474     bfd_false,
475   },
476 JUMP_TABLE(srec)
477 };