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