1 /* BFD back-end for s-record objects.
2 Copyright 1990, 1991, 1992 Free Software Foundation, Inc.
3 Written by Steve Chamberlain of Cygnus Support <sac@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. */
27 S-records cannot hold anything but addresses and data, so
28 that's all that we implement.
30 The only interesting thing is that s-records may come out of
31 order and there is no header, so an initial scan is required
32 to discover the minimum and maximum addresses used to create
33 the vma and size of the only section we create. We
34 arbitrarily call this section ".text".
36 When bfd_get_section_contents is called the file is read
37 again, and this time the data is placed into a bfd_alloc'd
40 Any number of sections may be created for output, we save them
41 up and output them when it's time to close the bfd.
43 An s record looks like:
46 S<type><length><address><data><checksum>
51 is the number of bytes following upto the checksum. Note that
52 this is not the number of chars following, since it takes two
53 chars to represent a byte.
57 1) two byte address data record
58 2) three byte address data record
59 3) four byte address data record
60 7) four byte address termination record
61 8) three byte address termination record
62 9) two byte address termination record
65 is the start address of the data following, or in the case of
66 a termination record, the start address of the image
70 is the sum of all the raw byte data in the record, from the length
71 upwards, modulo 256 and subtracted from 255.
79 /* Macros for converting between hex and binary */
81 static CONST char digs[] = "0123456789ABCDEF";
83 static char hex_value[1 + (unsigned char)~0];
86 #define NIBBLE(x) hex_value[(unsigned char)(x)]
87 #define HEX(buffer) ((NIBBLE((buffer)[0])<<4) + NIBBLE((buffer)[1]))
88 #define TOHEX(d, x, ch) \
89 d[1] = digs[(x) & 0xf]; \
90 d[0] = digs[((x)>>4)&0xf]; \
92 #define ISHEX(x) (hex_value[(unsigned char)(x)] != NOT_HEX)
100 static boolean inited = false;
107 for (i = 0; i < sizeof (hex_value); i++)
109 hex_value[i] = NOT_HEX;
112 for (i = 0; i < 10; i++)
114 hex_value[i + '0'] = i;
117 for (i = 0; i < 6; i++)
119 hex_value[i + 'a'] = i+10;
120 hex_value[i + 'A'] = i+10;
126 /* The maximum number of bytes on a line is FF */
127 #define MAXCHUNK 0xff
128 /* The number of bytes we fit onto a line on output */
131 /* We cannot output our srecords as we see them, we have to glue them
132 together, this is done in this structure : */
134 struct srec_data_list_struct
139 struct srec_data_list_struct *next;
142 typedef struct srec_data_list_struct srec_data_list_type;
145 typedef struct srec_data_struct
147 srec_data_list_type *head;
154 #define enda(x) (x->vma + x->size)
156 called once per input s-record, used to work out vma and size of data.
159 static bfd_vma low,high;
162 DEFUN(size_srec,(abfd, section, address, raw, length),
164 asection *section AND
171 if (address + length > high)
172 high = address + length -1;
177 called once per input s-record, copies data from input into bfd_alloc'd area
181 DEFUN(fillup,(abfd, section, address, raw, length),
183 asection *section AND
190 (bfd_byte *)(section->used_by_bfd) +
191 address - section->vma;
192 /* length -1 because we don't read in the checksum */
193 for (i = 0; i < length -1 ; i++) {
200 /* Pass over an s-record file, calling one of the above functions on each
204 DEFUN(pass_over,(abfd, func, section),
209 unsigned int bytes_on_line;
212 /* To the front of the file */
213 bfd_seek(abfd, (file_ptr)0, SEEK_SET);
216 char buffer[MAXCHUNK];
222 eof = (boolean)(bfd_read(src, 1, 1, abfd) != 1);
223 while (*src!= 'S' && !eof) {
224 eof = (boolean)(bfd_read(src, 1, 1, abfd) != 1);
229 /* Fetch the type and the length */
230 bfd_read(src, 1, 3, abfd);
234 if (!ISHEX (src[0]) || !ISHEX (src[1]))
237 bytes_on_line = HEX(src);
239 if (bytes_on_line > MAXCHUNK/2)
243 bfd_read(src, 1 , bytes_on_line * 2, abfd);
248 /* Prologue - ignore */
256 address = HEX(src) | (address<<8) ;
260 address = HEX(src) | (address<<8) ;
262 address = HEX(src) | (address<<8) ;
265 func(abfd,section, address, src, bytes_on_line);
277 DEFUN(srec_object_p, (abfd),
284 bfd_seek(abfd, (file_ptr)0, SEEK_SET);
285 bfd_read(b, 1, 4, abfd);
287 if (b[0] != 'S' || !ISHEX(b[1]) || !ISHEX(b[2]) || !ISHEX(b[3]))
288 return (bfd_target*) NULL;
290 /* We create one section called .text for all the contents,
291 and allocate enough room for the entire file. */
293 section = bfd_make_section(abfd, ".text");
294 section->_raw_size = 0;
295 section->vma = 0xffffffff;
298 pass_over(abfd, size_srec, section);
299 section->_raw_size = high - low;
301 section->flags = SEC_HAS_CONTENTS | SEC_LOAD | SEC_ALLOC;
308 DEFUN(srec_get_section_contents,(abfd, section, location, offset, count),
310 asection *section AND
315 if (section->used_by_bfd == (PTR)NULL)
317 section->used_by_bfd = (PTR)bfd_alloc (abfd, section->_raw_size);
318 pass_over(abfd, fillup, section);
320 (void) memcpy((PTR)location,
321 (PTR)((char *)(section->used_by_bfd) + offset),
329 DEFUN(srec_set_arch_mach,(abfd, arch, machine),
331 enum bfd_architecture arch AND
332 unsigned long machine)
334 return bfd_default_set_arch_mach(abfd, arch, machine);
338 /* we have to save up all the Srecords for a splurge before output,
342 DEFUN(srec_set_section_contents,(abfd, section, location, offset, bytes_to_do),
347 bfd_size_type bytes_to_do)
349 tdata_type *tdata = abfd->tdata.srec_data;
350 srec_data_list_type *entry = (srec_data_list_type *)
351 bfd_alloc(abfd, sizeof(srec_data_list_type));
352 if ((section->flags & SEC_ALLOC)
353 && (section->flags & SEC_LOAD))
355 unsigned char *data = (unsigned char *) bfd_alloc(abfd, bytes_to_do);
356 memcpy(data, location, bytes_to_do);
358 if ((section->vma + offset + bytes_to_do) <= 0xffff)
362 else if ((section->vma + offset + bytes_to_do) <= 0xffffff
373 entry->where = section->vma + offset;
374 entry->size = bytes_to_do;
375 entry->next = tdata->head;
381 /* Write a record of type, of the supplied number of bytes. The
382 supplied bytes and length don't have a checksum. That's worked out
386 void DEFUN(srec_write_record,(abfd, type, address, data, end),
390 CONST unsigned char *data AND
391 CONST unsigned char *end)
394 char buffer[MAXCHUNK];
396 unsigned int check_sum = 0;
397 unsigned CONST char *src = data;
406 dst+=2; /* leave room for dst*/
412 TOHEX(dst, (address >> 24), check_sum);
416 TOHEX(dst, (address >> 16), check_sum);
421 TOHEX(dst, (address >> 8), check_sum);
423 TOHEX(dst, (address), check_sum);
428 for (src = data; src < end; src++)
430 TOHEX(dst, *src, check_sum);
434 /* Fill in the length */
435 TOHEX(length, (dst - length)/2, check_sum);
437 check_sum = 255 - check_sum;
438 TOHEX(dst, check_sum, check_sum);
443 bfd_write((PTR)buffer, 1, dst - buffer , abfd);
449 DEFUN(srec_write_header,(abfd),
452 unsigned char buffer[MAXCHUNK];
453 unsigned char *dst = buffer;
456 /* I'll put an arbitary 40 char limit on header size */
457 for (i = 0; i < 40 && abfd->filename[i]; i++)
459 *dst++ = abfd->filename[i];
461 srec_write_record(abfd,0, 0, buffer, dst);
465 DEFUN(srec_write_section,(abfd, tdata, list),
467 tdata_type *tdata AND
468 srec_data_list_type *list)
470 unsigned int bytes_written = 0;
471 unsigned char *location = list->data;
473 while (bytes_written < list->size)
477 unsigned int bytes_this_chunk = list->size - bytes_written;
479 if (bytes_this_chunk > CHUNK)
481 bytes_this_chunk = CHUNK;
484 address = list->where + bytes_written;
486 srec_write_record(abfd,
490 location + bytes_this_chunk);
492 bytes_written += bytes_this_chunk;
493 location += bytes_this_chunk;
499 DEFUN(srec_write_terminator,(abfd, tdata),
503 unsigned char buffer[2];
505 srec_write_record(abfd, 10 - tdata->type,
506 abfd->start_address, buffer, buffer);
510 DEFUN(srec_mkobject, (abfd),
513 tdata_type *tdata = (tdata_type *)bfd_alloc(abfd, sizeof(tdata_type));
514 abfd->tdata.srec_data = tdata;
516 tdata->head = (srec_data_list_type *)NULL;
523 DEFUN(srec_write_object_contents,(abfd),
527 tdata_type *tdata = abfd->tdata.srec_data;
528 srec_data_list_type *list;
534 srec_write_header(abfd);
536 /* Now wander though all the sections provided and output them */
539 while (list != (srec_data_list_type*)NULL)
541 srec_write_section(abfd, tdata, list);
544 srec_write_terminator(abfd, tdata);
549 DEFUN(srec_sizeof_headers,(abfd, exec),
557 DEFUN(srec_make_empty_symbol, (abfd),
560 asymbol *new= (asymbol *)bfd_zalloc (abfd, sizeof (asymbol));
565 #define srec_new_section_hook (FOO(boolean, (*), (bfd *, asection *)))bfd_true
566 #define srec_get_symtab_upper_bound (PROTO(unsigned int, (*),(bfd *)))bfd_false
567 #define srec_get_symtab (FOO(unsigned int, (*), (bfd *, asymbol **)))bfd_0
568 #define srec_get_reloc_upper_bound (FOO(unsigned int, (*),(bfd*, asection *)))bfd_false
569 #define srec_canonicalize_reloc (FOO(unsigned int, (*),(bfd*,asection *, arelent **, asymbol **))) bfd_0
571 #define srec_print_symbol (FOO(void,(*),(bfd *, PTR, asymbol *, bfd_print_symbol_type))) bfd_void
573 #define srec_openr_next_archived_file (FOO(bfd *, (*), (bfd*,bfd*))) bfd_nullvoidptr
574 #define srec_find_nearest_line (FOO(boolean, (*),(bfd*,asection*,asymbol**,bfd_vma, CONST char**, CONST char**, unsigned int *))) bfd_false
575 #define srec_generic_stat_arch_elt (FOO(int, (*), (bfd *,struct stat *))) bfd_0
578 #define srec_core_file_failing_command (char *(*)())(bfd_nullvoidptr)
579 #define srec_core_file_failing_signal (int (*)())bfd_0
580 #define srec_core_file_matches_executable_p (FOO(boolean, (*),(bfd*, bfd*)))bfd_false
581 #define srec_slurp_armap bfd_true
582 #define srec_slurp_extended_name_table bfd_true
583 #define srec_truncate_arname (void (*)())bfd_nullvoidptr
584 #define srec_write_armap (FOO( boolean, (*),(bfd *, unsigned int, struct orl *, unsigned int, int))) bfd_nullvoidptr
585 #define srec_get_lineno (struct lineno_cache_entry *(*)())bfd_nullvoidptr
586 #define srec_close_and_cleanup bfd_generic_close_and_cleanup
587 #define srec_bfd_debug_info_start bfd_void
588 #define srec_bfd_debug_info_end bfd_void
589 #define srec_bfd_debug_info_accumulate (FOO(void, (*), (bfd *, asection *))) bfd_void
590 #define srec_bfd_get_relocated_section_contents bfd_generic_get_relocated_section_contents
591 #define srec_bfd_relax_section bfd_generic_relax_section
592 #define srec_bfd_seclet_link bfd_generic_seclet_link
594 bfd_target srec_vec =
597 bfd_target_srec_flavour,
598 true, /* target byte order */
599 true, /* target headers byte order */
600 (HAS_RELOC | EXEC_P | /* object flags */
601 HAS_LINENO | HAS_DEBUG |
602 HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT | D_PAGED),
603 (SEC_CODE|SEC_DATA|SEC_ROM|SEC_HAS_CONTENTS
604 |SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
605 0, /* leading underscore */
606 ' ', /* ar_pad_char */
607 16, /* ar_max_namelen */
608 1, /* minimum alignment */
609 _do_getb64, _do_putb64, _do_getb32,
610 _do_putb32, _do_getb16, _do_putb16, /* data */
611 _do_getb64, _do_putb64, _do_getb32,
612 _do_putb32, _do_getb16, _do_putb16, /* hdrs */
616 srec_object_p, /* bfd_check_format */
617 (struct bfd_target *(*)()) bfd_nullvoidptr,
618 (struct bfd_target *(*)()) bfd_nullvoidptr,
623 _bfd_generic_mkarchive,
626 { /* bfd_write_contents */
628 srec_write_object_contents,
629 _bfd_write_archive_contents,