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