1 /* BFD backend for s-record objects.
2 Copyright (C) 1990-1991 Free Software Foundation, Inc.
3 Written by Steve Chamberlain of Cygnus Support <steve@cygnus.com>.
5 This file is part of BFD, the Binary File Descriptor library.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
21 /* S-records cannot hold anything but addresses and data, so that's all
24 The only interesting thing is that s-records may come out of order and
25 there is no header, so an initial scan is required to discover the
26 minimum and maximum addresses used to create the vma and size of the
27 only section we create. We arbitrarily call this section ".text".
29 When bfd_get_section_contents is called the file is read again, and
30 this time the data is placed into a bfd_alloc'd area.
32 Any number of sections may be created for output, we just output them
33 in the order provided to bfd_set_section_contents. */
40 static char digs[] = "0123456789ABCDEF";
42 /* Macros for converting between hex and binary */
44 #define NIBBLE(x) (((x) >= '0' && (x) <= '9') ? ((x) - '0') : ((x) - 'A' + 10))
45 #define HEX(buffer) ((NIBBLE((buffer)->high) <<4) + NIBBLE((buffer)->low))
47 ((d)->low = digs[(x) & 0xf], (d)->high = digs[((x)>>4)&0xf], (x))
48 #define ISHEX(x) (((x) >= '0' && (x) <= '9') || ((x) >= 'A' && (x) <= 'F'))
53 } byte_as_two_char_type;
55 /* The maximum number of bytes on a line is FF */
57 /* The number of bytes we fit onto a line on output */
60 /* The shape of an s-record .. */
65 byte_as_two_char_type size;
68 byte_as_two_char_type address[4];
69 byte_as_two_char_type data[MAXCHUNK];
70 /* If there isn't MAXCHUNK bytes of data then the checksum will
72 byte_as_two_char_type checksum;
76 byte_as_two_char_type address[4];
77 byte_as_two_char_type data[MAXCHUNK];
78 byte_as_two_char_type checksum;
83 byte_as_two_char_type address[3];
84 byte_as_two_char_type data[MAXCHUNK];
85 byte_as_two_char_type checksum;
90 byte_as_two_char_type address[2];
91 byte_as_two_char_type data[MAXCHUNK];
92 byte_as_two_char_type checksum;
95 byte_as_two_char_type data[MAXCHUNK];
99 #define enda(x) (x->vma + x->size)
101 called once per input s-record, used to work out vma and size of data.
104 static bfd_vma low,high;
106 size_srec(abfd, section, address, raw, length)
110 byte_as_two_char_type *raw;
115 if (address + length > high)
116 high = address + length;
121 called once per input s-record, copies data from input into bfd_alloc'd area
125 fillup(abfd, section, address, raw, length)
129 byte_as_two_char_type *raw;
133 bfd_byte *dst = (bfd_byte *)(section->used_by_bfd) + address - section->vma;
134 for (i = 0; i < length; i++) {
141 /* Pass over an s-record file, calling one of the above functions on each
145 pass_over(abfd, func, section)
150 unsigned int bytes_on_line;
153 /* To the front of the file */
154 bfd_seek(abfd, (file_ptr)0, SEEK_SET);
160 eof = bfd_read(&buffer.S, 1, 1, abfd) != 1;
161 while (buffer.S != 'S' && !eof) {
162 eof = bfd_read(&buffer.S, 1, 1, abfd) != 1;
166 bfd_read(&buffer.type, 1, 3, abfd);
168 if (!ISHEX (buffer.size.high) || !ISHEX (buffer.size.low))
170 bytes_on_line = HEX(&buffer.size);
171 if (bytes_on_line > MAXCHUNK/2)
174 bfd_read((PTR)buffer.u.data, 1 , bytes_on_line * 2, abfd);
176 switch (buffer.type) {
178 /* Prologue - ignore */
182 address = (HEX(buffer.u.type_3.address+0) << 24)
183 + (HEX(buffer.u.type_3.address+1) << 16)
184 + (HEX(buffer.u.type_3.address+2) << 8)
185 + (HEX(buffer.u.type_3.address+3));
186 func(abfd,section, address, buffer.u.type_3.data, bytes_on_line -1);
190 address = (HEX(buffer.u.type_2.address+0) << 16)
191 + (HEX(buffer.u.type_2.address+1) << 8)
192 + (HEX(buffer.u.type_2.address+2));
193 func(abfd,section, address, buffer.u.type_2.data, bytes_on_line -1);
197 address = (HEX(buffer.u.type_1.address+0) << 8)
198 + (HEX(buffer.u.type_1.address+1));
199 func(abfd, section, address, buffer.u.type_1.data, bytes_on_line -1);
216 bfd_seek(abfd, (file_ptr)0, SEEK_SET);
217 bfd_read(b, 1, 4, abfd);
218 if (b[0] != 'S' || !ISHEX(b[1]) || !ISHEX(b[2]) || !ISHEX(b[3]))
219 return (bfd_target*) NULL;
221 /* We create one section called .text for all the contents,
222 and allocate enough room for the entire file. */
224 section = bfd_make_section(abfd, ".text");
226 section->vma = 0xffffffff;
229 pass_over(abfd, size_srec, section);
230 section->size = high - low;
237 srec_get_section_contents (abfd, section, location, offset, count)
244 if (section->used_by_bfd == (PTR)NULL) {
245 section->used_by_bfd = (PTR)bfd_alloc (abfd, section->size);
246 pass_over(abfd, fillup, section);
248 (void) memcpy((PTR)location, (PTR)((char *)(section->used_by_bfd) + offset), count);
255 srec_set_arch_mach (abfd, arch, machine)
257 enum bfd_architecture arch;
258 unsigned long machine;
260 abfd->obj_arch = arch;
261 abfd->obj_machine = machine;
268 srec_set_section_contents (abfd, section, location, offset, bytes_to_do)
271 unsigned char *location;
282 if (section->vma <= 0xffff)
284 else if (section->vma <= 0xffffff)
290 buffer.type = '0' + type;
292 while (bytes_written < bytes_to_do) {
294 unsigned int check_sum;
295 byte_as_two_char_type *data;
296 unsigned int bytes_this_chunk = bytes_to_do - bytes_written;
298 if (bytes_this_chunk > CHUNK) {
299 bytes_this_chunk = CHUNK;
302 address = section->vma + offset + bytes_written;
306 check_sum = TOHEX(buffer.u.type_3.address, address >> 24);
307 check_sum += TOHEX(buffer.u.type_3.address+1, address >> 16);
308 check_sum += TOHEX(buffer.u.type_3.address+2, address >> 8);
309 check_sum += TOHEX(buffer.u.type_3.address+3, address >> 0);
310 size = bytes_this_chunk + 5;
311 data = buffer.u.type_3.data;
314 check_sum = TOHEX(buffer.u.type_3.address, address >> 16);
315 check_sum += TOHEX(buffer.u.type_3.address+1, address >> 8);
316 check_sum += TOHEX(buffer.u.type_3.address+2, address >> 0);
317 size = bytes_this_chunk + 4;
318 data = buffer.u.type_2.data;
322 check_sum = TOHEX(buffer.u.type_3.address+0, address >> 8);
323 check_sum += TOHEX(buffer.u.type_3.address+1, address >> 0);
324 size = bytes_this_chunk + 3;
325 data = buffer.u.type_1.data;
329 for (i = 0; i < bytes_this_chunk; i++) {
330 check_sum += TOHEX(data, (location[i]));
334 check_sum += TOHEX(&(buffer.size), size );
335 (void) TOHEX(data, ~check_sum);
338 * ( (char *)(data)) = '\n';
339 bfd_write((PTR)&buffer, 1, (char *)data - (char *)&buffer + 1 , abfd);
341 bytes_written += bytes_this_chunk;
342 location += bytes_this_chunk;
350 srec_write_object_contents (abfd)
353 bfd_write("S9030000FC\n", 1,11,abfd);
358 DEFUN(srec_sizeof_headers,(abfd, exec),
366 DEFUN(srec_make_empty_symbol, (abfd),
369 asymbol *new= (asymbol *)bfd_zalloc (abfd, sizeof (asymbol));
374 #define srec_new_section_hook (FOO(boolean, (*), (bfd *, asection *)))bfd_true
375 #define srec_get_symtab_upper_bound (PROTO(unsigned int, (*),(bfd *)))bfd_false
376 #define srec_get_symtab (FOO(unsigned int, (*), (bfd *, asymbol **)))bfd_0
377 #define srec_get_reloc_upper_bound (FOO(unsigned int, (*),(bfd*, asection *)))bfd_false
378 #define srec_canonicalize_reloc (FOO(unsigned int, (*),(bfd*,asection *, arelent **, asymbol **))) bfd_0
380 #define srec_print_symbol (FOO(void,(*),(bfd *, PTR, asymbol *, bfd_print_symbol_enum_type))) bfd_void
382 #define srec_openr_next_archived_file (FOO(bfd *, (*), (bfd*,bfd*))) bfd_nullvoidptr
383 #define srec_find_nearest_line (FOO(boolean, (*),(bfd*,asection*,asymbol**,bfd_vma, CONST char**, CONST char**, unsigned int *))) bfd_false
384 #define srec_generic_stat_arch_elt (FOO(int, (*), (bfd *,struct stat *))) bfd_0
387 #define srec_core_file_failing_command (char *(*)())(bfd_nullvoidptr)
388 #define srec_core_file_failing_signal (int (*)())bfd_0
389 #define srec_core_file_matches_executable_p (FOO(boolean, (*),(bfd*, bfd*)))bfd_false
390 #define srec_slurp_armap bfd_true
391 #define srec_slurp_extended_name_table bfd_true
392 #define srec_truncate_arname (void (*)())bfd_nullvoidptr
393 #define srec_write_armap (FOO( boolean, (*),(bfd *, unsigned int, struct orl *, int, int))) bfd_nullvoidptr
394 #define srec_get_lineno (struct lineno_cache_entry *(*)())bfd_nullvoidptr
395 #define srec_close_and_cleanup bfd_generic_close_and_cleanup
396 #define srec_bfd_debug_info_start bfd_void
397 #define srec_bfd_debug_info_end bfd_void
398 #define srec_bfd_debug_info_accumulate (FOO(void, (*), (bfd *, asection *))) bfd_void
401 bfd_target srec_vec =
404 bfd_target_srec_flavour_enum,
405 true, /* target byte order */
406 true, /* target headers byte order */
407 (HAS_RELOC | EXEC_P | /* object flags */
408 HAS_LINENO | HAS_DEBUG |
409 HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT | D_PAGED),
410 (SEC_CODE|SEC_DATA|SEC_ROM|SEC_HAS_CONTENTS
411 |SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
412 ' ', /* ar_pad_char */
413 16, /* ar_max_namelen */
414 1, /* minimum alignment */
415 _do_getb64, _do_putb64, _do_getb32, _do_putb32, _do_getb16, _do_putb16, /* data */
416 _do_getb64, _do_putb64, _do_getb32, _do_putb32, _do_getb16, _do_putb16, /* hdrs */
419 srec_object_p, /* bfd_check_format */
420 (struct bfd_target *(*)()) bfd_nullvoidptr,
421 (struct bfd_target *(*)()) bfd_nullvoidptr,
425 bfd_true, /* mkobject */
426 _bfd_generic_mkarchive,
429 { /* bfd_write_contents */
431 srec_write_object_contents,
432 _bfd_write_archive_contents,