Now full of documentation. Yum Yum.
[deliverable/binutils-gdb.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 bfd_alloc'd 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
44 #include <sysdep.h>
45 #include "bfd.h"
46 #include "libbfd.h"
47
48
49 static char digs[] = "0123456789ABCDEF";
50
51 /* Macros for converting between hex and binary */
52
53 #define NIBBLE(x) ((x >= '0' && x <= '9') ? (x - '0') : (x - 'A' + 10))
54 #define HEX(buffer) ((NIBBLE((buffer)->high) <<4) + NIBBLE((buffer)->low))
55 #define TOHEX(d,x) \
56 ((d)->low = digs[(x) & 0xf], (d)->high = digs[((x)>>4)&0xf], x)
57
58 typedef struct {
59 char high;
60 char low;
61 } byte_as_two_char_type;
62
63 /* The maximum number of bytes on a line is FF */
64 #define MAXCHUNK 0xff
65 /* The number of bytes we fit onto a line on output */
66 #define CHUNK 16
67
68 /* The shape of an srecord .. */
69 typedef struct
70 {
71 char S;
72 char type;
73 byte_as_two_char_type size;
74 union {
75 struct {
76 byte_as_two_char_type address[4];
77 byte_as_two_char_type data[MAXCHUNK];
78 /* If there isn't MAXCHUNK bytes of data then the checksum will
79 appear earlier */
80 byte_as_two_char_type checksum;
81 char nl;
82 } type_3;
83 struct {
84 byte_as_two_char_type address[4];
85 byte_as_two_char_type data[MAXCHUNK];
86 byte_as_two_char_type checksum;
87 char nl;
88 } type_6;
89
90 struct {
91 byte_as_two_char_type address[3];
92 byte_as_two_char_type data[MAXCHUNK];
93 byte_as_two_char_type checksum;
94 char nl;
95 } type_2;
96
97 struct {
98 byte_as_two_char_type address[2];
99 byte_as_two_char_type data[MAXCHUNK];
100 byte_as_two_char_type checksum;
101 char nl;
102 } type_1;
103 byte_as_two_char_type data[MAXCHUNK];
104 } u;
105 } srec_type;
106
107 #define enda(x) (x->vma + x->size)
108 /*
109 called once per input srecord, used to work out vma and size of data.
110 */
111
112 static bfd_vma low,high;
113 static void
114 size_srec(abfd, section, address, raw, length)
115 bfd *abfd;
116 asection *section;
117 bfd_vma address;
118 byte_as_two_char_type *raw;
119 unsigned int length;
120 {
121 if (address < low)
122 low = address;
123 if (address + length > high)
124 high = address + length;
125 }
126
127
128 /*
129 called once per input srecord, copies data from input into bfd_alloc'd area
130 */
131
132 static void
133 fillup(abfd, section, address, raw, length)
134 bfd *abfd;
135 asection *section;
136 bfd_vma address;
137 byte_as_two_char_type *raw;
138 unsigned int length;
139 {
140 unsigned int i;
141 bfd_byte *dst = (bfd_byte *)(section->used_by_bfd) + address - section->vma;
142 for (i = 0; i < length; i++) {
143 *dst = HEX(raw);
144 dst++;
145 raw++;
146 }
147 }
148
149 /*
150 pass over an srecord file calling one of the above functions on each
151 record
152 */
153 static void
154 pass_over(abfd, func, section)
155 bfd *abfd;
156 void (*func)();
157 asection *section;
158 {
159 unsigned int bytes_on_line;
160 boolean eof = false;
161 bfd_vma address;
162 /* To the front of the file */
163 bfd_seek(abfd, (file_ptr)0, SEEK_SET);
164 while (eof == false)
165 {
166 srec_type buffer;
167
168 /* Find first 'S' */
169 eof = bfd_read(&buffer.S, 1, 1, abfd) != 1;
170 while (buffer.S != 'S' && !eof) {
171 eof = bfd_read(&buffer.S, 1, 1, abfd) != 1;
172 }
173 if (eof) break;
174
175 bfd_read(&buffer.type, 1, 3, abfd);
176
177 bytes_on_line = HEX(&buffer.size);
178
179 bfd_read((PTR)buffer.u.data, 1 , bytes_on_line * 2, abfd);
180
181 switch (buffer.type) {
182 case '6':
183 /* Prologue - ignore */
184 break;
185 case '3':
186 address = (HEX(buffer.u.type_3.address+0) << 24)
187 + (HEX(buffer.u.type_3.address+1) << 16)
188 + (HEX(buffer.u.type_3.address+2) << 8)
189 + (HEX(buffer.u.type_3.address+3));
190 func(abfd,section, address, buffer.u.type_3.data, bytes_on_line -1);
191
192 break;
193
194 case '2':
195 address = (HEX(buffer.u.type_2.address+0) << 16)+
196 (HEX(buffer.u.type_2.address+1) << 8) +
197 (HEX(buffer.u.type_2.address+2));
198 func(abfd,section, address, buffer.u.type_2.data, bytes_on_line -1);
199
200 break;
201 case '1':
202 address =
203 (HEX(buffer.u.type_1.address+0) << 8)
204 + (HEX(buffer.u.type_1.address+1));
205 func(abfd, section, address, buffer.u.type_1.data, bytes_on_line -1);
206 break;
207
208 }
209 }
210 }
211
212
213 bfd_target *
214 srec_object_p (abfd)
215 bfd *abfd;
216 {
217 char b;
218 asection *section;
219 bfd_seek(abfd, (file_ptr)0, SEEK_SET);
220 bfd_read(&b, 1,1,abfd);
221 if (b != 'S') return (bfd_target*)NULL;
222
223 /*
224 We create one section called data for all the contents,
225 and allocate enough room for the entire file
226 */
227
228
229 section = bfd_make_section(abfd, ".text");
230 section->size = 0;
231 section->vma = 0xffffffff;
232 low = 0xffffffff;
233 high = 0;
234 pass_over(abfd, size_srec, section);
235 section->size = high - low;
236 section->vma = low;
237 return abfd->xvec;
238 }
239
240
241
242
243
244
245
246
247 static boolean
248 srec_get_section_contents (abfd, section, location, offset, count)
249 bfd *abfd;
250 sec_ptr section;
251 void *location;
252 file_ptr offset;
253 unsigned int count;
254 {
255 if (section->used_by_bfd == (PTR)NULL) {
256 section->used_by_bfd = (PTR)bfd_alloc (abfd, section->size);
257 pass_over(abfd, fillup, section);
258 }
259 (void) memcpy(location, (bfd_byte *)(section->used_by_bfd) + offset, count);
260 return true;
261 }
262
263
264
265 boolean
266 srec_set_arch_mach (abfd, arch, machine)
267 bfd *abfd;
268 enum bfd_architecture arch;
269 unsigned long machine;
270 {
271 abfd->obj_arch = arch;
272 abfd->obj_machine = machine;
273 return true;
274 }
275
276
277
278 boolean
279 srec_set_section_contents (abfd, section, location, offset, bytes_to_do)
280 bfd *abfd;
281 sec_ptr section;
282 unsigned char *location;
283 file_ptr offset;
284 int bytes_to_do;
285 {
286 bfd_vma address;
287 int bytes_written;
288
289 int type;
290 unsigned int i;
291 srec_type buffer;
292 bytes_written = 0;
293 if (section->vma <= 0xffff)
294 type = 1;
295 else if (section->vma <= 0xffffff)
296 type = 2;
297 else
298 type = 3;
299
300 buffer.S = 'S';
301 buffer.type = '0' + type;
302
303 while (bytes_written < bytes_to_do) {
304 unsigned int size;
305 unsigned int check_sum;
306 byte_as_two_char_type *data;
307 unsigned int bytes_this_chunk = bytes_to_do - bytes_written;
308
309 if (bytes_this_chunk > CHUNK) {
310 bytes_this_chunk = CHUNK;
311 }
312
313 address = section->vma + offset + bytes_written;
314
315 switch (type) {
316 case 3:
317 check_sum = TOHEX(buffer.u.type_3.address, address >> 24);
318 check_sum += TOHEX(buffer.u.type_3.address+1, address >> 16);
319 check_sum += TOHEX(buffer.u.type_3.address+2, address >> 8);
320 check_sum += TOHEX(buffer.u.type_3.address+3, address >> 0);
321 size = bytes_this_chunk + 5;
322 data = buffer.u.type_3.data;
323 break;
324 case 2:
325 check_sum = TOHEX(buffer.u.type_3.address, address >> 16);
326 check_sum += TOHEX(buffer.u.type_3.address+1, address >> 8);
327 check_sum += TOHEX(buffer.u.type_3.address+2, address >> 0);
328 size = bytes_this_chunk + 4;
329 data = buffer.u.type_2.data;
330 break;
331
332 case 1:
333 check_sum = TOHEX(buffer.u.type_3.address+0, address >> 8);
334 check_sum += TOHEX(buffer.u.type_3.address+1, address >> 0);
335 size = bytes_this_chunk + 3;
336 data = buffer.u.type_1.data;
337 break;
338 }
339
340 for (i = 0; i < bytes_this_chunk; i++) {
341 check_sum += TOHEX(data, (location[i]));
342 data++;
343 }
344
345 check_sum += TOHEX(&(buffer.size), size );
346 (void) TOHEX(data, ~check_sum);
347 data++;
348
349 * ( (char *)(data)) = '\n';
350 bfd_write((PTR)&buffer, 1, (char *)data - (char *)&buffer + 1 , abfd);
351
352 bytes_written += bytes_this_chunk;
353 location += bytes_this_chunk;
354 }
355
356
357 return true;
358 }
359
360 boolean
361 srec_write_object_contents (abfd)
362 bfd *abfd;
363 {
364 bfd_write("S9030000FC\n", 1,11,abfd);
365 return true;
366 }
367
368 static int
369 DEFUN(srec_sizeof_headers,(abfd, exec),
370 bfd *abfd AND
371 boolean exec)
372 {
373 return 0;
374 }
375
376 static asymbol *
377 DEFUN(srec_make_empty_symbol, (abfd),
378 bfd*abfd)
379 {
380 asymbol *new= (asymbol *)bfd_zalloc (abfd, sizeof (asymbol));
381 new->the_bfd = abfd;
382 return new;
383 }
384 #define FOO PROTO
385 #define srec_new_section_hook (FOO(boolean, (*), (bfd *, asection *)))bfd_true
386 #define srec_get_symtab_upper_bound bfd_false
387 #define srec_get_symtab (FOO(unsigned int, (*), (bfd *, asymbol **)))bfd_0
388 #define srec_get_reloc_upper_bound (FOO(unsigned int, (*),(bfd*, asection *)))bfd_false
389 #define srec_canonicalize_reloc (FOO(unsigned int, (*),(bfd*,asection *, arelent **, asymbol **))) bfd_0
390
391 #define srec_print_symbol (FOO(void,(*),(bfd *, PTR, asymbol *, bfd_print_symbol_enum_type))) bfd_void
392
393 #define srec_openr_next_archived_file (FOO(bfd *, (*), (bfd*,bfd*))) bfd_nullvoidptr
394 #define srec_find_nearest_line (FOO(boolean, (*),(bfd*,asection*,asymbol**,bfd_vma, CONST char**, CONST char**, unsigned int *))) bfd_false
395 #define srec_generic_stat_arch_elt (FOO(int, (*), (bfd *,struct stat *))) bfd_0
396
397
398 #define srec_core_file_failing_command (char *(*)())(bfd_nullvoidptr)
399 #define srec_core_file_failing_signal (int (*)())bfd_0
400 #define srec_core_file_matches_executable_p (FOO(boolean, (*),(bfd*, bfd*)))bfd_false
401 #define srec_slurp_armap bfd_true
402 #define srec_slurp_extended_name_table bfd_true
403 #define srec_truncate_arname (void (*)())bfd_nullvoidptr
404 #define srec_write_armap (FOO( boolean, (*),(bfd *, unsigned int, struct orl *, int, int))) bfd_nullvoidptr
405 #define srec_get_lineno (struct lineno_cache_entry *(*)())bfd_nullvoidptr
406 #define srec_close_and_cleanup bfd_generic_close_and_cleanup
407 #define srec_bfd_debug_info_start bfd_void
408 #define srec_bfd_debug_info_end bfd_void
409 #define srec_bfd_debug_info_accumulate (FOO(void, (*), (bfd *, asection *))) bfd_void
410
411
412 bfd_target srec_vec =
413 {
414 "srec", /* name */
415 bfd_target_srec_flavour_enum,
416 true, /* target byte order */
417 true, /* target headers byte order */
418 (HAS_RELOC | EXEC_P | /* object flags */
419 HAS_LINENO | HAS_DEBUG |
420 HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT | D_PAGED),
421 (SEC_CODE|SEC_DATA|SEC_ROM|SEC_HAS_CONTENTS
422 |SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
423 ' ', /* ar_pad_char */
424 16, /* ar_max_namelen */
425 1, /* minimum alignment */
426 _do_getb64, _do_putb64, _do_getb32, _do_putb32, _do_getb16, _do_putb16, /* data */
427 _do_getb64, _do_putb64, _do_getb32, _do_putb32, _do_getb16, _do_putb16, /* hdrs */
428
429 {_bfd_dummy_target,
430 srec_object_p, /* bfd_check_format */
431 (struct bfd_target *(*)()) bfd_nullvoidptr,
432 (struct bfd_target *(*)()) bfd_nullvoidptr,
433 },
434 {
435 bfd_false,
436 bfd_true, /* mkobject */
437 _bfd_generic_mkarchive,
438 bfd_false,
439 },
440 { /* bfd_write_contents */
441 bfd_false,
442 srec_write_object_contents,
443 _bfd_write_archive_contents,
444 bfd_false,
445 },
446 JUMP_TABLE(srec)
447 };
This page took 0.039453 seconds and 5 git commands to generate.