1 /* BFD back-end for s-record objects.
2 Copyright 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
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 Ordinary S-Records cannot hold anything but addresses and
28 data, so 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.
75 Symbol S-Record handling
78 Some ICE equipment understands an addition to the standard
79 S-Record format; symbols and their addresses can be sent
82 The format of this is:
84 (<space> <symbol> <address>)*)
87 so a short symbol table could look like:
101 We allow symbols to be anywhere in the data stream - the module names
110 static boolean srec_write_record PARAMS ((bfd *, int, bfd_vma,
111 const unsigned char *,
112 const unsigned char *));
113 static boolean srec_write_header PARAMS ((bfd *));
114 static boolean srec_write_symbols PARAMS ((bfd *));
116 /* Macros for converting between hex and binary. */
118 static CONST char digs[] = "0123456789ABCDEF";
120 /* Table that gets filled in with numbers corresponding to hex chars. */
122 static char hex_value[256];
125 #define NIBBLE(x) hex_value[(unsigned char)(x)]
126 #define HEX(buffer) ((NIBBLE((buffer)[0])<<4) + NIBBLE((buffer)[1]))
127 #define TOHEX(d, x, ch) \
128 d[1] = digs[(x) & 0xf]; \
129 d[0] = digs[((x)>>4)&0xf]; \
131 #define ISHEX(x) (hex_value[(unsigned char)(x)] != NOT_HEX)
133 /* Initialize by filling in the hex conversion array. */
139 static boolean inited = false;
145 for (i = 0; i < sizeof (hex_value); i++)
147 hex_value[i] = NOT_HEX;
149 for (i = 0; i < 10; i++)
151 hex_value[i + '0'] = i;
153 for (i = 0; i < 6; i++)
155 hex_value[i + 'a'] = i + 10;
156 hex_value[i + 'A'] = i + 10;
162 /* The maximum number of bytes on a line is FF */
163 #define MAXCHUNK 0xff
164 /* The number of bytes we fit onto a line on output */
167 /* We cannot output our srecords as we see them, we have to glue them
168 together, this is done in this structure : */
170 struct srec_data_list_struct
175 struct srec_data_list_struct *next;
179 typedef struct srec_data_list_struct srec_data_list_type;
182 typedef struct srec_data_struct
184 srec_data_list_type *head;
187 int done_symbol_read;
197 static boolean srec_write_section PARAMS ((bfd *, tdata_type *,
198 srec_data_list_type *));
199 static boolean srec_write_terminator PARAMS ((bfd *, tdata_type *));
202 called once per input S-Record, used to work out vma and size of data.
205 static bfd_vma low, high;
209 size_symbols (abfd, buf, len, val)
216 abfd->tdata.srec_data->string_size += len + 1;
220 fillup_symbols (abfd, buf, len, val)
226 if (!abfd->tdata.srec_data->done_symbol_read)
229 if (abfd->tdata.srec_data->symbols == 0)
231 abfd->tdata.srec_data->symbols = (asymbol *) bfd_alloc (abfd, abfd->symcount * sizeof (asymbol));
232 abfd->tdata.srec_data->strings = (char *) bfd_alloc (abfd, abfd->tdata.srec_data->string_size);
233 if (!abfd->tdata.srec_data->symbols || !abfd->tdata.srec_data->strings)
235 bfd_set_error (bfd_error_no_memory);
236 abort (); /* FIXME */
238 abfd->tdata.srec_data->symbol_idx = 0;
239 abfd->tdata.srec_data->string_idx = 0;
242 p = abfd->tdata.srec_data->symbols + abfd->tdata.srec_data->symbol_idx++;
244 p->name = abfd->tdata.srec_data->strings + abfd->tdata.srec_data->string_idx;
245 memcpy ((char *) (p->name), buf, len + 1);
246 abfd->tdata.srec_data->string_idx += len + 1;
248 p->flags = BSF_EXPORT | BSF_GLOBAL;
249 p->section = &bfd_abs_section;
255 size_srec (abfd, section, address, raw, length)
264 if (address + length > high)
265 high = address + length - 1;
270 called once per input S-Record, copies data from input into bfd_alloc'd area
275 fillup (abfd, section, address, raw, length)
284 (bfd_byte *) (section->used_by_bfd) + address - section->vma;
285 /* length -1 because we don't read in the checksum */
286 for (i = 0; i < length - 1; i++)
294 /* Pass over an S-Record file, calling one of the above functions on each
301 return (x == ' ' || x == '\t' || x == '\n' || x == '\r');
304 skipwhite (src, abfd)
309 while (white (*src) && !eof)
311 eof = (boolean) (bfd_read (src, 1, 1, abfd) != 1);
320 if (abfd->tdata.srec_data == 0)
322 tdata_type *tdata = (tdata_type *) bfd_alloc (abfd, sizeof (tdata_type));
325 bfd_set_error (bfd_error_no_memory);
328 abfd->tdata.srec_data = tdata;
330 tdata->head = (srec_data_list_type *) NULL;
337 pass_over (abfd, func, symbolfunc, section)
340 void (*symbolfunc) ();
343 unsigned int bytes_on_line;
346 srec_mkobject (abfd);
347 /* To the front of the file */
348 if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
352 char buffer[MAXCHUNK];
357 /* Find first 'S' or $ */
358 eof = (boolean) (bfd_read (src, 1, 1, abfd) != 1);
367 /* Inside a symbol definition - just ignore the module name */
368 while (*src != '\n' && !eof)
370 eof = (boolean) (bfd_read (src, 1, 1, abfd) != 1);
375 /* spaces - maybe just before a symbol */
376 while (*src != '\n' && *src != '\r' && white (*src))
378 eof = skipwhite (src, abfd);
383 char symbol[MAXCHUNK];
385 /* get the symbol part */
386 while (!eof && !white (*src) && slen < MAXCHUNK)
388 symbol[slen++] = *src;
389 eof = (boolean) (bfd_read (src, 1, 1, abfd) != 1);
392 eof = skipwhite (src, abfd);
393 /* skip the $ for the hex value */
396 eof = (boolean) (bfd_read (src, 1, 1, abfd) != 1);
399 /* Scan off the hex number */
400 while (isxdigit (*src))
405 else if (isupper (*src))
407 val += *src - 'A' + 10;
411 val += *src - 'a' + 10;
413 eof = (boolean) (bfd_read (src, 1, 1, abfd) != 1);
415 symbolfunc (abfd, symbol, slen, val);
422 /* Fetch the type and the length */
423 if (bfd_read (src, 1, 3, abfd) != 3)
424 abort (); /* FIXME */
428 if (!ISHEX (src[0]) || !ISHEX (src[1]))
431 bytes_on_line = HEX (src);
433 if (bytes_on_line > MAXCHUNK / 2)
437 if (bfd_read (src, 1, bytes_on_line * 2, abfd) != bytes_on_line * 2)
438 abort (); /* FIXME */
444 /* Prologue - ignore */
452 address = HEX (src) | (address << 8);
456 address = HEX (src) | (address << 8);
458 address = HEX (src) | (address << 8);
461 func (abfd, section, address, src, bytes_on_line);
476 /* We create one section called .text for all the contents,
477 and allocate enough room for the entire file. */
479 section = bfd_make_section (abfd, ".text");
480 section->_raw_size = 0;
481 section->vma = 0xffffffff;
484 pass_over (abfd, size_srec, size_symbols, section);
485 section->_raw_size = high - low;
487 section->flags = SEC_HAS_CONTENTS | SEC_LOAD | SEC_ALLOC;
490 abfd->flags |= HAS_SYMS;
502 if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0
503 || bfd_read (b, 1, 4, abfd) != 4)
506 if (b[0] != 'S' || !ISHEX (b[1]) || !ISHEX (b[2]) || !ISHEX (b[3]))
507 return (bfd_target *) NULL;
509 /* We create one section called .text for all the contents,
510 and allocate enough room for the entire file. */
512 return object_p (abfd);
517 symbolsrec_object_p (abfd)
524 if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0
525 || bfd_read (b, 1, 4, abfd) != 4)
528 if (b[0] != '$' || b[1] != '$')
529 return (bfd_target *) NULL;
531 return object_p (abfd);
536 srec_get_section_contents (abfd, section, location, offset, count)
543 if (section->used_by_bfd == (PTR) NULL)
545 section->used_by_bfd = (PTR) bfd_alloc (abfd, section->_raw_size);
546 if (!section->used_by_bfd)
548 bfd_set_error (bfd_error_no_memory);
552 pass_over (abfd, fillup, fillup_symbols, section);
554 memcpy ((PTR) location,
555 (PTR) ((char *) (section->used_by_bfd) + offset),
563 srec_set_arch_mach (abfd, arch, machine)
565 enum bfd_architecture arch;
566 unsigned long machine;
568 return bfd_default_set_arch_mach (abfd, arch, machine);
572 /* we have to save up all the Srecords for a splurge before output,
576 srec_set_section_contents (abfd, section, location, offset, bytes_to_do)
581 bfd_size_type bytes_to_do;
583 tdata_type *tdata = abfd->tdata.srec_data;
584 srec_data_list_type *entry = (srec_data_list_type *)
585 bfd_alloc (abfd, sizeof (srec_data_list_type));
589 bfd_set_error (bfd_error_no_memory);
593 if ((section->flags & SEC_ALLOC)
594 && (section->flags & SEC_LOAD))
596 unsigned char *data = (unsigned char *) bfd_alloc (abfd, bytes_to_do);
599 bfd_set_error (bfd_error_no_memory);
602 memcpy ((PTR) data, location, bytes_to_do);
604 if ((section->lma + offset + bytes_to_do) <= 0xffff)
608 else if ((section->lma + offset + bytes_to_do) <= 0xffffff
619 entry->where = section->lma + offset;
620 entry->size = bytes_to_do;
621 entry->next = tdata->head;
627 /* Write a record of type, of the supplied number of bytes. The
628 supplied bytes and length don't have a checksum. That's worked out
632 srec_write_record (abfd, type, address, data, end)
636 const unsigned char *data;
637 const unsigned char *end;
639 char buffer[MAXCHUNK];
641 unsigned int check_sum = 0;
642 CONST unsigned char *src = data;
651 dst += 2; /* leave room for dst*/
657 TOHEX (dst, (address >> 24), check_sum);
661 TOHEX (dst, (address >> 16), check_sum);
666 TOHEX (dst, (address >> 8), check_sum);
668 TOHEX (dst, (address), check_sum);
673 for (src = data; src < end; src++)
675 TOHEX (dst, *src, check_sum);
679 /* Fill in the length */
680 TOHEX (length, (dst - length) / 2, check_sum);
682 check_sum = 255 - check_sum;
683 TOHEX (dst, check_sum, check_sum);
688 if (bfd_write ((PTR) buffer, 1, dst - buffer, abfd) != dst - buffer)
696 srec_write_header (abfd)
699 unsigned char buffer[MAXCHUNK];
700 unsigned char *dst = buffer;
703 /* I'll put an arbitary 40 char limit on header size */
704 for (i = 0; i < 40 && abfd->filename[i]; i++)
706 *dst++ = abfd->filename[i];
708 return srec_write_record (abfd, 0, 0, buffer, dst);
712 srec_write_section (abfd, tdata, list)
715 srec_data_list_type *list;
717 unsigned int bytes_written = 0;
718 unsigned char *location = list->data;
720 while (bytes_written < list->size)
724 unsigned int bytes_this_chunk = list->size - bytes_written;
726 if (bytes_this_chunk > CHUNK)
728 bytes_this_chunk = CHUNK;
731 address = list->where + bytes_written;
733 if (! srec_write_record (abfd,
737 location + bytes_this_chunk))
740 bytes_written += bytes_this_chunk;
741 location += bytes_this_chunk;
748 srec_write_terminator (abfd, tdata)
752 unsigned char buffer[2];
754 return srec_write_record (abfd, 10 - tdata->type,
755 abfd->start_address, buffer, buffer);
761 srec_write_symbols (abfd)
764 char buffer[MAXCHUNK];
765 /* Dump out the symbols of a bfd */
767 int len = bfd_get_symcount (abfd);
772 asymbol **table = bfd_get_outsymbols (abfd);
773 sprintf (buffer, "$$ %s\r\n", abfd->filename);
775 len = strlen (buffer) + 1;
776 if (bfd_write (buffer, len, 1, abfd) != len)
779 for (i = 0; i < len; i++)
781 asymbol *s = table[i];
783 int len = strlen (s->name);
785 /* If this symbol has a .[ocs] in it, it's probably a file name
786 and we'll output that as the module name */
788 if (len > 3 && s->name[len - 2] == '.')
791 sprintf (buffer, "$$ %s\r\n", s->name);
793 if (bfd_write (buffer, l, 1, abfd) != l)
798 if (s->flags & (BSF_GLOBAL | BSF_LOCAL)
799 && (s->flags & BSF_DEBUGGING) == 0
801 && s->name[0] != 't')
803 /* Just dump out non debug symbols */
809 s->value + s->section->output_section->lma
810 + s->section->output_offset);
812 while (p[0] == '0' && p[1] != 0)
814 sprintf (buffer, " %s $%s\r\n", s->name, p);
816 if (bfd_write (buffer, l, 1, abfd) != l)
820 sprintf (buffer, "$$ \r\n");
821 len = strlen (buffer) + 1;
822 if (bfd_write (buffer, len, 1, abfd) != len)
830 internal_srec_write_object_contents (abfd, symbols)
834 tdata_type *tdata = abfd->tdata.srec_data;
835 srec_data_list_type *list;
839 if (! srec_write_symbols (abfd))
843 if (! srec_write_header (abfd))
846 /* Now wander though all the sections provided and output them */
849 while (list != (srec_data_list_type *) NULL)
851 if (! srec_write_section (abfd, tdata, list))
855 return srec_write_terminator (abfd, tdata);
859 srec_write_object_contents (abfd)
862 return internal_srec_write_object_contents (abfd, 0);
866 symbolsrec_write_object_contents (abfd)
869 return internal_srec_write_object_contents (abfd, 1);
874 srec_sizeof_headers (abfd, exec)
882 srec_make_empty_symbol (abfd)
885 asymbol *new = (asymbol *) bfd_zalloc (abfd, sizeof (asymbol));
892 srec_get_symtab_upper_bound (abfd)
895 /* Read in all the info */
896 if (! srec_get_section_contents (abfd, abfd->sections, 0, 0, 0))
898 return (bfd_get_symcount (abfd) + 1) * (sizeof (asymbol *));
902 srec_get_symtab (abfd, alocation)
906 int lim = abfd->symcount;
908 for (i = 0; i < lim; i++)
910 alocation[i] = abfd->tdata.srec_data->symbols + i;
918 srec_get_symbol_info (ignore_abfd, symbol, ret)
923 bfd_symbol_info (symbol, ret);
928 srec_print_symbol (ignore_abfd, afile, symbol, how)
932 bfd_print_symbol_type how;
934 FILE *file = (FILE *) afile;
937 case bfd_print_symbol_name:
938 fprintf (file, "%s", symbol->name);
941 bfd_print_symbol_vandf ((PTR) file, symbol);
942 fprintf (file, " %-5s %s",
943 symbol->section->name,
949 #define srec_close_and_cleanup _bfd_generic_close_and_cleanup
950 #define srec_bfd_free_cached_info _bfd_generic_bfd_free_cached_info
951 #define srec_new_section_hook _bfd_generic_new_section_hook
953 #define srec_bfd_is_local_label bfd_generic_is_local_label
954 #define srec_get_lineno _bfd_nosymbols_get_lineno
955 #define srec_find_nearest_line _bfd_nosymbols_find_nearest_line
956 #define srec_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol
958 #define srec_bfd_get_relocated_section_contents \
959 bfd_generic_get_relocated_section_contents
960 #define srec_bfd_relax_section bfd_generic_relax_section
961 #define srec_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
962 #define srec_bfd_link_add_symbols _bfd_generic_link_add_symbols
963 #define srec_bfd_final_link _bfd_generic_final_link
965 bfd_target srec_vec =
968 bfd_target_srec_flavour,
969 true, /* target byte order */
970 true, /* target headers byte order */
971 (HAS_RELOC | EXEC_P | /* object flags */
972 HAS_LINENO | HAS_DEBUG |
973 HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
974 (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS
975 | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
976 0, /* leading underscore */
977 ' ', /* ar_pad_char */
978 16, /* ar_max_namelen */
979 1, /* minimum alignment */
980 bfd_getb64, bfd_getb_signed_64, bfd_putb64,
981 bfd_getb32, bfd_getb_signed_32, bfd_putb32,
982 bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* data */
983 bfd_getb64, bfd_getb_signed_64, bfd_putb64,
984 bfd_getb32, bfd_getb_signed_32, bfd_putb32,
985 bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* hdrs */
989 srec_object_p, /* bfd_check_format */
990 (struct bfd_target * (*)()) bfd_nullvoidptr,
991 (struct bfd_target * (*)()) bfd_nullvoidptr,
996 _bfd_generic_mkarchive,
999 { /* bfd_write_contents */
1001 srec_write_object_contents,
1002 _bfd_write_archive_contents,
1006 BFD_JUMP_TABLE_GENERIC (srec),
1007 BFD_JUMP_TABLE_COPY (_bfd_generic),
1008 BFD_JUMP_TABLE_CORE (_bfd_nocore),
1009 BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
1010 BFD_JUMP_TABLE_SYMBOLS (srec),
1011 BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
1012 BFD_JUMP_TABLE_WRITE (srec),
1013 BFD_JUMP_TABLE_LINK (srec),
1014 BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
1021 bfd_target symbolsrec_vec =
1023 "symbolsrec", /* name */
1024 bfd_target_srec_flavour,
1025 true, /* target byte order */
1026 true, /* target headers byte order */
1027 (HAS_RELOC | EXEC_P | /* object flags */
1028 HAS_LINENO | HAS_DEBUG |
1029 HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
1030 (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS
1031 | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
1032 0, /* leading underscore */
1033 ' ', /* ar_pad_char */
1034 16, /* ar_max_namelen */
1035 1, /* minimum alignment */
1036 bfd_getb64, bfd_getb_signed_64, bfd_putb64,
1037 bfd_getb32, bfd_getb_signed_32, bfd_putb32,
1038 bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* data */
1039 bfd_getb64, bfd_getb_signed_64, bfd_putb64,
1040 bfd_getb32, bfd_getb_signed_32, bfd_putb32,
1041 bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* hdrs */
1045 symbolsrec_object_p, /* bfd_check_format */
1046 (struct bfd_target * (*)()) bfd_nullvoidptr,
1047 (struct bfd_target * (*)()) bfd_nullvoidptr,
1052 _bfd_generic_mkarchive,
1055 { /* bfd_write_contents */
1057 symbolsrec_write_object_contents,
1058 _bfd_write_archive_contents,
1062 BFD_JUMP_TABLE_GENERIC (srec),
1063 BFD_JUMP_TABLE_COPY (_bfd_generic),
1064 BFD_JUMP_TABLE_CORE (_bfd_nocore),
1065 BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
1066 BFD_JUMP_TABLE_SYMBOLS (srec),
1067 BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
1068 BFD_JUMP_TABLE_WRITE (srec),
1069 BFD_JUMP_TABLE_LINK (srec),
1070 BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),