1 /* Copyright (C) 1990, 1991 Free Software Foundation, Inc.
3 This file is part of BFD, the Binary File Diddler.
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)
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.
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. */
21 bfd backend for srecord objects.
23 Srecords cannot hold anything but addresses and data, so that's all
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".
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.
34 Any number of sections may be created for output, we just output them
35 in the order provided to bfd_set_section_contents.
38 Steve Chamberlain steve@cygnus.com
49 static char digs
[] = "0123456789ABCDEF";
51 /* Macros for converting between hex and binary */
53 #define NIBBLE(x) ((x >= '0' && x <= '9') ? (x - '0') : (x - 'A' + 10))
54 #define HEX(buffer) ((NIBBLE((buffer)->high) <<4) + NIBBLE((buffer)->low))
56 ((d)->low = digs[(x) & 0xf], (d)->high = digs[((x)>>4)&0xf], x)
61 } byte_as_two_char_type
;
63 /* The maximum number of bytes on a line is FF */
65 /* The number of bytes we fit onto a line on output */
68 /* The shape of an srecord .. */
73 byte_as_two_char_type size
;
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
80 byte_as_two_char_type checksum
;
84 byte_as_two_char_type address
[4];
85 byte_as_two_char_type data
[MAXCHUNK
];
86 byte_as_two_char_type checksum
;
91 byte_as_two_char_type address
[3];
92 byte_as_two_char_type data
[MAXCHUNK
];
93 byte_as_two_char_type checksum
;
98 byte_as_two_char_type address
[2];
99 byte_as_two_char_type data
[MAXCHUNK
];
100 byte_as_two_char_type checksum
;
103 byte_as_two_char_type data
[MAXCHUNK
];
109 called once per input srecord, used to work out vma and size of data.
113 size_srec(abfd
, section
, address
, raw
, length
)
117 byte_as_two_char_type
*raw
;
120 if (address
< section
->vma
)
121 section
->vma
= address
;
123 if (address
+ length
> section
->vma
+ section
->size
)
124 section
->size
= (address
+length
) - section
->vma
;
128 called once per input srecord, copies data from input into bfd_alloc'd area
132 fillup(abfd
, section
, address
, raw
, length
)
136 byte_as_two_char_type
*raw
;
140 bfd_byte
*dst
= (bfd_byte
*)(section
->used_by_bfd
) + address
- section
->vma
;
141 for (i
= 0; i
< length
; i
++) {
149 pass over an srecord file calling one of the above functions on each
153 pass_over(abfd
, func
, section
)
158 unsigned int bytes_on_line
;
161 /* To the front of the file */
162 bfd_seek(abfd
, (file_ptr
)0, SEEK_SET
);
168 eof
= bfd_read(&buffer
.S
, 1, 1, abfd
) != 1;
169 while (buffer
.S
!= 'S' && !eof
) {
170 eof
= bfd_read(&buffer
.S
, 1, 1, abfd
) != 1;
174 bfd_read(&buffer
.type
, 1, 3, abfd
);
176 bytes_on_line
= HEX(&buffer
.size
);
178 bfd_read((PTR
)buffer
.u
.data
, 1 , bytes_on_line
* 2, abfd
);
180 switch (buffer
.type
) {
182 /* Prologue - ignore */
185 address
= (HEX(buffer
.u
.type_3
.address
+0) << 24)
186 + (HEX(buffer
.u
.type_3
.address
+1) << 16)
187 + (HEX(buffer
.u
.type_3
.address
+2) << 8)
188 + (HEX(buffer
.u
.type_3
.address
+3));
189 func(abfd
,section
, address
, buffer
.u
.type_2
.data
, bytes_on_line
-1);
194 address
= (HEX(buffer
.u
.type_2
.address
+0) << 16)+
195 (HEX(buffer
.u
.type_2
.address
+1) << 8) +
196 (HEX(buffer
.u
.type_2
.address
+2));
197 func(abfd
,section
, address
, buffer
.u
.type_2
.data
, bytes_on_line
-1);
202 (HEX(buffer
.u
.type_1
.address
+0) << 8)
203 + (HEX(buffer
.u
.type_1
.address
+1));
204 func(abfd
, section
, address
, buffer
.u
.type_1
.data
, bytes_on_line
-1);
218 bfd_seek(abfd
, (file_ptr
)0, SEEK_SET
);
219 bfd_read(&b
, 1,1,abfd
);
220 if (b
!= 'S') return (bfd_target
*)NULL
;
223 We create one section called data for all the contents,
224 and allocate enough room for the entire file
228 section
= bfd_make_section(abfd
, ".text");
230 section
->vma
= 0xffffffff;
231 pass_over(abfd
, size_srec
, section
);
244 srec_get_section_contents (abfd
, section
, location
, offset
, count
)
251 if (section
->used_by_bfd
== (PTR
)NULL
) {
252 section
->used_by_bfd
= (PTR
)bfd_alloc (abfd
, section
->size
);
253 pass_over(abfd
, fillup
, section
);
255 (void) memcpy(location
, (bfd_byte
*)(section
->used_by_bfd
) + offset
, count
);
262 srec_set_arch_mach (abfd
, arch
, machine
)
264 enum bfd_architecture arch
;
265 unsigned long machine
;
267 abfd
->obj_arch
= arch
;
268 abfd
->obj_machine
= machine
;
275 srec_set_section_contents (abfd
, section
, location
, offset
, bytes_to_do
)
278 unsigned char *location
;
289 if (section
->size
<= 0xffff)
291 else if (section
->size
<= 0xffffff)
297 buffer
.type
= '0' + type
;
299 while (bytes_written
< bytes_to_do
) {
301 unsigned int check_sum
;
302 byte_as_two_char_type
*data
;
303 unsigned int bytes_this_chunk
= bytes_to_do
- bytes_written
;
305 if (bytes_this_chunk
> CHUNK
) {
306 bytes_this_chunk
= CHUNK
;
309 address
= section
->vma
+ offset
+ bytes_written
;
313 check_sum
= TOHEX(buffer
.u
.type_3
.address
, address
>> 24);
314 check_sum
+= TOHEX(buffer
.u
.type_3
.address
+1, address
>> 16);
315 check_sum
+= TOHEX(buffer
.u
.type_3
.address
+2, address
>> 8);
316 check_sum
+= TOHEX(buffer
.u
.type_3
.address
+3, address
>> 0);
317 size
= bytes_this_chunk
+ 5;
318 data
= buffer
.u
.type_3
.data
;
321 check_sum
= TOHEX(buffer
.u
.type_3
.address
, address
>> 16);
322 check_sum
+= TOHEX(buffer
.u
.type_3
.address
+1, address
>> 8);
323 check_sum
+= TOHEX(buffer
.u
.type_3
.address
+2, address
>> 0);
324 size
= bytes_this_chunk
+ 4;
325 data
= buffer
.u
.type_2
.data
;
329 check_sum
= TOHEX(buffer
.u
.type_3
.address
+0, address
>> 8);
330 check_sum
+= TOHEX(buffer
.u
.type_3
.address
+1, address
>> 0);
331 size
= bytes_this_chunk
+ 3;
332 data
= buffer
.u
.type_1
.data
;
335 for (i
= 0; i
< bytes_this_chunk
; i
++) {
336 check_sum
+= TOHEX(data
, (location
[i
]));
340 check_sum
+= TOHEX(&(buffer
.size
), size
);
341 (void) TOHEX(data
, ~check_sum
);
344 * ( (char *)(data
)) = '\n';
345 bfd_write((PTR
)&buffer
, 1, (char *)data
- (char *)&buffer
+ 1 , abfd
);
347 bytes_written
+= bytes_this_chunk
;
348 location
+= bytes_this_chunk
;
356 srec_write_object_contents (abfd
)
359 bfd_write("S9030000FC\n", 1,11,abfd
);
364 DEFUN(srec_sizeof_headers
,(abfd
, exec
),
373 #define srec_new_section_hook (PROTO(boolean, (*), (bfd *, asection *)))bfd_false
374 #define srec_get_symtab_upper_bound bfd_false
375 #define srec_get_symtab (PROTO(unsigned int, (*), (bfd *, asymbol **)))bfd_0
376 #define srec_get_reloc_upper_bound (PROTO(unsigned int, (*),(bfd*, asection *)))bfd_false
377 #define srec_canonicalize_reloc (PROTO(unsigned int, (*),(bfd*,asection *, arelent **, asymbol **))) bfd_0
378 #define srec_make_empty_symbol (PROTO(asymbol *,(*),(bfd*))) bfd_nullvoidptr
379 #define srec_print_symbol (PROTO(void,(*),(bfd *, PTR, asymbol *, bfd_print_symbol_enum_type))) bfd_void
381 #define srec_openr_next_archived_file (PROTO(bfd *, (*), (bfd*,bfd*))) bfd_nullvoidptr
382 #define srec_find_nearest_line (PROTO(boolean, (*),(bfd*,asection*,asymbol**,bfd_vma, CONST char**, CONST char**, unsigned int *))) bfd_false
383 #define srec_generic_stat_arch_elt (PROTO(int, (*), (bfd *,struct stat *))) bfd_0
386 #define srec_core_file_failing_command (char *(*)())(bfd_nullvoidptr)
387 #define srec_core_file_failing_signal (int (*)())bfd_0
388 #define srec_core_file_matches_executable_p (PROTO(boolean, (*),(bfd*, bfd*)))bfd_false
389 #define srec_slurp_armap bfd_true
390 #define srec_slurp_extended_name_table bfd_true
391 #define srec_truncate_arname (void (*)())bfd_nullvoidptr
392 #define srec_write_armap (PROTO( boolean, (*),(bfd *, unsigned int, struct orl *, int, int))) bfd_nullvoidptr
393 #define srec_get_lineno (struct lineno_cache_entry *(*)())bfd_nullvoidptr
395 #define srec_close_and_cleanup bfd_generic_close_and_cleanup
398 bfd_target srec_vec
=
401 bfd_target_srec_flavour_enum
,
402 true, /* target byte order */
403 true, /* target headers byte order */
404 (HAS_RELOC
| EXEC_P
| /* object flags */
405 HAS_LINENO
| HAS_DEBUG
|
406 HAS_SYMS
| HAS_LOCALS
| DYNAMIC
| WP_TEXT
| D_PAGED
),
407 (SEC_CODE
|SEC_DATA
|SEC_ROM
|SEC_HAS_CONTENTS
408 |SEC_ALLOC
| SEC_LOAD
| SEC_RELOC
), /* section flags */
409 ' ', /* ar_pad_char */
410 16, /* ar_max_namelen */
411 _do_getb64
, _do_putb64
, _do_getb32
, _do_putb32
, _do_getb16
, _do_putb16
, /* data */
412 _do_getb64
, _do_putb64
, _do_getb32
, _do_putb32
, _do_getb16
, _do_putb16
, /* hdrs */
415 srec_object_p
, /* bfd_check_format */
416 (struct bfd_target
*(*)()) bfd_nullvoidptr
,
417 (struct bfd_target
*(*)()) bfd_nullvoidptr
,
421 bfd_true
, /* mkobject */
422 _bfd_generic_mkarchive
,
425 { /* bfd_write_contents */
427 srec_write_object_contents
,
428 _bfd_write_archive_contents
,