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
];
107 #define enda(x) (x->vma + x->size)
109 called once per input srecord, used to work out vma and size of data.
112 static bfd_vma low
,high
;
114 size_srec(abfd
, section
, address
, raw
, length
)
118 byte_as_two_char_type
*raw
;
123 if (address
+ length
> high
)
124 high
= address
+ length
;
129 called once per input srecord, copies data from input into bfd_alloc'd area
133 fillup(abfd
, section
, address
, raw
, length
)
137 byte_as_two_char_type
*raw
;
141 bfd_byte
*dst
= (bfd_byte
*)(section
->used_by_bfd
) + address
- section
->vma
;
142 for (i
= 0; i
< length
; i
++) {
150 pass over an srecord file calling one of the above functions on each
154 pass_over(abfd
, func
, section
)
159 unsigned int bytes_on_line
;
162 /* To the front of the file */
163 bfd_seek(abfd
, (file_ptr
)0, SEEK_SET
);
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;
175 bfd_read(&buffer
.type
, 1, 3, abfd
);
177 bytes_on_line
= HEX(&buffer
.size
);
179 bfd_read((PTR
)buffer
.u
.data
, 1 , bytes_on_line
* 2, abfd
);
181 switch (buffer
.type
) {
183 /* Prologue - ignore */
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);
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);
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);
219 bfd_seek(abfd
, (file_ptr
)0, SEEK_SET
);
220 bfd_read(&b
, 1,1,abfd
);
221 if (b
!= 'S') return (bfd_target
*)NULL
;
224 We create one section called data for all the contents,
225 and allocate enough room for the entire file
229 section
= bfd_make_section(abfd
, ".text");
231 section
->vma
= 0xffffffff;
234 pass_over(abfd
, size_srec
, section
);
235 section
->size
= high
- low
;
248 srec_get_section_contents (abfd
, section
, location
, offset
, count
)
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
);
259 (void) memcpy(location
, (bfd_byte
*)(section
->used_by_bfd
) + offset
, count
);
266 srec_set_arch_mach (abfd
, arch
, machine
)
268 enum bfd_architecture arch
;
269 unsigned long machine
;
271 abfd
->obj_arch
= arch
;
272 abfd
->obj_machine
= machine
;
279 srec_set_section_contents (abfd
, section
, location
, offset
, bytes_to_do
)
282 unsigned char *location
;
293 if (section
->vma
<= 0xffff)
295 else if (section
->vma
<= 0xffffff)
301 buffer
.type
= '0' + type
;
303 while (bytes_written
< bytes_to_do
) {
305 unsigned int check_sum
;
306 byte_as_two_char_type
*data
;
307 unsigned int bytes_this_chunk
= bytes_to_do
- bytes_written
;
309 if (bytes_this_chunk
> CHUNK
) {
310 bytes_this_chunk
= CHUNK
;
313 address
= section
->vma
+ offset
+ bytes_written
;
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
;
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
;
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
;
340 for (i
= 0; i
< bytes_this_chunk
; i
++) {
341 check_sum
+= TOHEX(data
, (location
[i
]));
345 check_sum
+= TOHEX(&(buffer
.size
), size
);
346 (void) TOHEX(data
, ~check_sum
);
349 * ( (char *)(data
)) = '\n';
350 bfd_write((PTR
)&buffer
, 1, (char *)data
- (char *)&buffer
+ 1 , abfd
);
352 bytes_written
+= bytes_this_chunk
;
353 location
+= bytes_this_chunk
;
361 srec_write_object_contents (abfd
)
364 bfd_write("S9030000FC\n", 1,11,abfd
);
369 DEFUN(srec_sizeof_headers
,(abfd
, exec
),
377 DEFUN(srec_make_empty_symbol
, (abfd
),
380 asymbol
*new= (asymbol
*)bfd_zalloc (abfd
, sizeof (asymbol
));
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
391 #define srec_print_symbol (FOO(void,(*),(bfd *, PTR, asymbol *, bfd_print_symbol_enum_type))) bfd_void
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
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
412 bfd_target srec_vec
=
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 */
430 srec_object_p
, /* bfd_check_format */
431 (struct bfd_target
*(*)()) bfd_nullvoidptr
,
432 (struct bfd_target
*(*)()) bfd_nullvoidptr
,
436 bfd_true
, /* mkobject */
437 _bfd_generic_mkarchive
,
440 { /* bfd_write_contents */
442 srec_write_object_contents
,
443 _bfd_write_archive_contents
,