X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=bfd%2Fsrec.c;h=a370b775bc90c0d89906a991c681a3adf599474e;hb=4c6ee6465acc58f0f86c44668c4e862901186239;hp=a5f588c231e99c811e3f5d8990900f5218745541;hpb=b9da616afe44eb7d00a669dad47bc6860e9b23d3;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/srec.c b/bfd/srec.c index a5f588c231..a370b775bc 100644 --- a/bfd/srec.c +++ b/bfd/srec.c @@ -1,7 +1,5 @@ /* BFD back-end for s-record objects. - Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, - 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 - Free Software Foundation, Inc. + Copyright (C) 1990-2020 Free Software Foundation, Inc. Written by Steve Chamberlain of Cygnus Support . This file is part of BFD, the Binary File Descriptor library. @@ -96,7 +94,7 @@ _start $14 _etext $8036 _edata $8036 - _end $8036 + _end $8036 $$ DESCRIPTION @@ -131,12 +129,12 @@ static const char digs[] = "0123456789ABCDEF"; /* The number of data bytes we actually fit onto a line on output. This variable can be modified by objcopy's --srec-len parameter. For a 0x75 byte record you should set --srec-len=0x70. */ -unsigned int Chunk = DEFAULT_CHUNK; +unsigned int _bfd_srec_len = DEFAULT_CHUNK; /* The type of srec output (free or forced to S3). This variable can be modified by objcopy's --srec-forceS3 parameter. */ -bfd_boolean S3Forced = FALSE; +bfd_boolean _bfd_srec_forceS3 = FALSE; /* When writing an S-record file, the S-records can not be output as they are seen. This structure is used to hold them in memory. */ @@ -198,7 +196,7 @@ srec_mkobject (bfd *abfd) srec_init (); - tdata = bfd_alloc (abfd, sizeof (tdata_type)); + tdata = (tdata_type *) bfd_alloc (abfd, sizeof (tdata_type)); if (tdata == NULL) return FALSE; @@ -248,17 +246,18 @@ srec_bad_byte (bfd *abfd, } else { - char buf[10]; + char buf[40]; if (! ISPRINT (c)) - sprintf (buf, "\\%03o", (unsigned int) c); + sprintf (buf, "\\%03o", (unsigned int) c & 0xff); else { buf[0] = c; buf[1] = '\0'; } - (*_bfd_error_handler) - (_("%B:%d: Unexpected character `%s' in S-record file\n"), + _bfd_error_handler + /* xgettext:c-format */ + (_("%pB:%d: unexpected character `%s' in S-record file"), abfd, lineno, buf); bfd_set_error (bfd_error_bad_value); } @@ -271,7 +270,7 @@ srec_new_symbol (bfd *abfd, const char *name, bfd_vma val) { struct srec_symbol *n; - n = bfd_alloc (abfd, sizeof (* n)); + n = (struct srec_symbol *) bfd_alloc (abfd, sizeof (* n)); if (n == NULL) return FALSE; @@ -363,7 +362,7 @@ srec_scan (bfd *abfd) } alc = 10; - symbuf = bfd_malloc (alc + 1); + symbuf = (char *) bfd_malloc (alc + 1); if (symbuf == NULL) goto error_return; @@ -378,7 +377,7 @@ srec_scan (bfd *abfd) char *n; alc *= 2; - n = bfd_realloc (symbuf, alc + 1); + n = (char *) bfd_realloc (symbuf, alc + 1); if (n == NULL) goto error_return; p = n + (p - symbuf); @@ -395,7 +394,7 @@ srec_scan (bfd *abfd) } *p++ = '\0'; - symname = bfd_alloc (abfd, (bfd_size_type) (p - symbuf)); + symname = (char *) bfd_alloc (abfd, (bfd_size_type) (p - symbuf)); if (symname == NULL) goto error_return; strcpy (symname, symbuf); @@ -428,6 +427,11 @@ srec_scan (bfd *abfd) symval <<= 4; symval += NIBBLE (c); c = srec_get_byte (abfd, &error); + if (c == EOF) + { + srec_bad_byte (abfd, lineno, c, error); + goto error_return; + } } if (! srec_new_symbol (abfd, symname, symval)) @@ -449,10 +453,11 @@ srec_scan (bfd *abfd) case 'S': { file_ptr pos; - char hdr[3]; - unsigned int bytes; + unsigned char hdr[3]; + unsigned int bytes, min_bytes; bfd_vma address; bfd_byte *data; + unsigned char check_sum; /* Starting an S-record. */ @@ -471,12 +476,26 @@ srec_scan (bfd *abfd) goto error_return; } - bytes = HEX (hdr + 1); + check_sum = bytes = HEX (hdr + 1); + min_bytes = 3; + if (hdr[0] == '2' || hdr[0] == '8') + min_bytes = 4; + else if (hdr[0] == '3' || hdr[0] == '7') + min_bytes = 5; + if (bytes < min_bytes) + { + /* xgettext:c-format */ + _bfd_error_handler (_("%pB:%d: byte count %d too small"), + abfd, lineno, bytes); + bfd_set_error (bfd_error_bad_value); + goto error_return; + } + if (bytes * 2 > bufsize) { if (buf != NULL) free (buf); - buf = bfd_malloc ((bfd_size_type) bytes * 2); + buf = (bfd_byte *) bfd_malloc ((bfd_size_type) bytes * 2); if (buf == NULL) goto error_return; bufsize = bytes * 2; @@ -500,18 +519,22 @@ srec_scan (bfd *abfd) break; case '3': + check_sum += HEX (data); address = HEX (data); data += 2; --bytes; /* Fall through. */ case '2': + check_sum += HEX (data); address = (address << 8) | HEX (data); data += 2; --bytes; /* Fall through. */ case '1': + check_sum += HEX (data); address = (address << 8) | HEX (data); data += 2; + check_sum += HEX (data); address = (address << 8) | HEX (data); data += 2; bytes -= 2; @@ -532,7 +555,7 @@ srec_scan (bfd *abfd) sprintf (secbuf, ".sec%d", bfd_count_sections (abfd) + 1); amt = strlen (secbuf) + 1; - secname = bfd_alloc (abfd, amt); + secname = (char *) bfd_alloc (abfd, amt); strcpy (secname, secbuf); flags = SEC_HAS_CONTENTS | SEC_LOAD | SEC_ALLOC; sec = bfd_make_section_with_flags (abfd, secname, flags); @@ -543,25 +566,58 @@ srec_scan (bfd *abfd) sec->size = bytes; sec->filepos = pos; } + + while (bytes > 0) + { + check_sum += HEX (data); + data += 2; + bytes--; + } + check_sum = 255 - (check_sum & 0xff); + if (check_sum != HEX (data)) + { + _bfd_error_handler + /* xgettext:c-format */ + (_("%pB:%d: bad checksum in S-record file"), + abfd, lineno); + bfd_set_error (bfd_error_bad_value); + goto error_return; + } + break; case '7': + check_sum += HEX (data); address = HEX (data); data += 2; /* Fall through. */ case '8': + check_sum += HEX (data); address = (address << 8) | HEX (data); data += 2; /* Fall through. */ case '9': + check_sum += HEX (data); address = (address << 8) | HEX (data); data += 2; + check_sum += HEX (data); address = (address << 8) | HEX (data); data += 2; /* This is a termination record. */ abfd->start_address = address; + check_sum = 255 - (check_sum & 0xff); + if (check_sum != HEX (data)) + { + _bfd_error_handler + /* xgettext:c-format */ + (_("%pB:%d: bad checksum in S-record file"), + abfd, lineno); + bfd_set_error (bfd_error_bad_value); + goto error_return; + } + if (buf != NULL) free (buf); @@ -697,7 +753,7 @@ srec_read_section (bfd *abfd, asection *section, bfd_byte *contents) { if (buf != NULL) free (buf); - buf = bfd_malloc ((bfd_size_type) bytes * 2); + buf = (bfd_byte *) bfd_malloc ((bfd_size_type) bytes * 2); if (buf == NULL) goto error_return; bufsize = bytes * 2; @@ -781,13 +837,24 @@ srec_get_section_contents (bfd *abfd, file_ptr offset, bfd_size_type count) { + if (count == 0) + return TRUE; + + if (offset + count < count + || offset + count > section->size) + { + bfd_set_error (bfd_error_invalid_operation); + return FALSE; + } + if (section->used_by_bfd == NULL) { section->used_by_bfd = bfd_alloc (abfd, section->size); - if (section->used_by_bfd == NULL && section->size != 0) + if (section->used_by_bfd == NULL) return FALSE; - if (! srec_read_section (abfd, section, section->used_by_bfd)) + if (! srec_read_section (abfd, section, + (bfd_byte *) section->used_by_bfd)) return FALSE; } @@ -818,10 +885,11 @@ srec_set_section_contents (bfd *abfd, file_ptr offset, bfd_size_type bytes_to_do) { + int opb = bfd_octets_per_byte (abfd, NULL); tdata_type *tdata = abfd->tdata.srec_data; srec_data_list_type *entry; - entry = bfd_alloc (abfd, sizeof (* entry)); + entry = (srec_data_list_type *) bfd_alloc (abfd, sizeof (* entry)); if (entry == NULL) return FALSE; @@ -831,25 +899,25 @@ srec_set_section_contents (bfd *abfd, { bfd_byte *data; - data = bfd_alloc (abfd, bytes_to_do); + data = (bfd_byte *) bfd_alloc (abfd, bytes_to_do); if (data == NULL) return FALSE; memcpy ((void *) data, location, (size_t) bytes_to_do); - /* Ff S3Forced is TRUE then always select S3 records, - regardless of the siez of the addresses. */ - if (S3Forced) + /* If _bfd_srec_forceS3 is TRUE then always select S3 records, + regardless of the size of the addresses. */ + if (_bfd_srec_forceS3) tdata->type = 3; - else if ((section->lma + offset + bytes_to_do - 1) <= 0xffff) + else if ((section->lma + (offset + bytes_to_do) / opb - 1) <= 0xffff) ; /* The default, S1, is OK. */ - else if ((section->lma + offset + bytes_to_do - 1) <= 0xffffff + else if ((section->lma + (offset + bytes_to_do) / opb - 1) <= 0xffffff && tdata->type <= 2) tdata->type = 2; else tdata->type = 3; entry->data = data; - entry->where = section->lma + offset; + entry->where = section->lma + offset / opb; entry->size = bytes_to_do; /* Sort the records by address. Optimize for the common case of @@ -908,10 +976,12 @@ srec_write_record (bfd *abfd, case 7: TOHEX (dst, (address >> 24), check_sum); dst += 2; + /* Fall through. */ case 8: case 2: TOHEX (dst, (address >> 16), check_sum); dst += 2; + /* Fall through. */ case 9: case 1: case 0: @@ -970,20 +1040,21 @@ srec_write_section (bfd *abfd, have three, and S3 (tdata->type == 3) records have four. The total length can't exceed 255, and a zero data length will spin for a long time. */ - if (Chunk == 0) - Chunk = 1; - else if (Chunk > MAXCHUNK - tdata->type - 2) - Chunk = MAXCHUNK - tdata->type - 2; + if (_bfd_srec_len == 0) + _bfd_srec_len = 1; + else if (_bfd_srec_len > MAXCHUNK - tdata->type - 2) + _bfd_srec_len = MAXCHUNK - tdata->type - 2; while (octets_written < list->size) { bfd_vma address; unsigned int octets_this_chunk = list->size - octets_written; - if (octets_this_chunk > Chunk) - octets_this_chunk = Chunk; + if (octets_this_chunk > _bfd_srec_len) + octets_this_chunk = _bfd_srec_len; - address = list->where + octets_written / bfd_octets_per_byte (abfd); + address = list->where + (octets_written + / bfd_octets_per_byte (abfd, NULL)); if (! srec_write_record (abfd, tdata->type, @@ -1130,7 +1201,7 @@ srec_canonicalize_symtab (bfd *abfd, asymbol **alocation) asymbol *c; struct srec_symbol *s; - csymbols = bfd_alloc (abfd, symcount * sizeof (asymbol)); + csymbols = (asymbol *) bfd_alloc (abfd, symcount * sizeof (asymbol)); if (csymbols == NULL) return -1; abfd->tdata.srec_data->csymbols = csymbols; @@ -1184,32 +1255,40 @@ srec_print_symbol (bfd *abfd, } } -#define srec_close_and_cleanup _bfd_generic_close_and_cleanup -#define srec_bfd_free_cached_info _bfd_generic_bfd_free_cached_info -#define srec_new_section_hook _bfd_generic_new_section_hook -#define srec_bfd_is_target_special_symbol ((bfd_boolean (*) (bfd *, asymbol *)) bfd_false) -#define srec_bfd_is_local_label_name bfd_generic_is_local_label_name -#define srec_get_lineno _bfd_nosymbols_get_lineno -#define srec_find_nearest_line _bfd_nosymbols_find_nearest_line -#define srec_find_inliner_info _bfd_nosymbols_find_inliner_info -#define srec_make_empty_symbol _bfd_generic_make_empty_symbol -#define srec_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol -#define srec_read_minisymbols _bfd_generic_read_minisymbols -#define srec_minisymbol_to_symbol _bfd_generic_minisymbol_to_symbol -#define srec_get_section_contents_in_window _bfd_generic_get_section_contents_in_window -#define srec_bfd_get_relocated_section_contents bfd_generic_get_relocated_section_contents -#define srec_bfd_relax_section bfd_generic_relax_section -#define srec_bfd_gc_sections bfd_generic_gc_sections -#define srec_bfd_merge_sections bfd_generic_merge_sections -#define srec_bfd_is_group_section bfd_generic_is_group_section -#define srec_bfd_discard_group bfd_generic_discard_group -#define srec_section_already_linked _bfd_generic_section_already_linked -#define srec_bfd_link_hash_table_create _bfd_generic_link_hash_table_create -#define srec_bfd_link_hash_table_free _bfd_generic_link_hash_table_free -#define srec_bfd_link_add_symbols _bfd_generic_link_add_symbols -#define srec_bfd_link_just_syms _bfd_generic_link_just_syms -#define srec_bfd_final_link _bfd_generic_final_link -#define srec_bfd_link_split_section _bfd_generic_link_split_section +#define srec_close_and_cleanup _bfd_generic_close_and_cleanup +#define srec_bfd_free_cached_info _bfd_generic_bfd_free_cached_info +#define srec_new_section_hook _bfd_generic_new_section_hook +#define srec_bfd_is_target_special_symbol _bfd_bool_bfd_asymbol_false +#define srec_bfd_is_local_label_name bfd_generic_is_local_label_name +#define srec_get_lineno _bfd_nosymbols_get_lineno +#define srec_find_nearest_line _bfd_nosymbols_find_nearest_line +#define srec_find_line _bfd_nosymbols_find_line +#define srec_find_inliner_info _bfd_nosymbols_find_inliner_info +#define srec_make_empty_symbol _bfd_generic_make_empty_symbol +#define srec_get_symbol_version_string _bfd_nosymbols_get_symbol_version_string +#define srec_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol +#define srec_read_minisymbols _bfd_generic_read_minisymbols +#define srec_minisymbol_to_symbol _bfd_generic_minisymbol_to_symbol +#define srec_get_section_contents_in_window _bfd_generic_get_section_contents_in_window +#define srec_bfd_get_relocated_section_contents bfd_generic_get_relocated_section_contents +#define srec_bfd_relax_section bfd_generic_relax_section +#define srec_bfd_gc_sections bfd_generic_gc_sections +#define srec_bfd_lookup_section_flags bfd_generic_lookup_section_flags +#define srec_bfd_merge_sections bfd_generic_merge_sections +#define srec_bfd_is_group_section bfd_generic_is_group_section +#define srec_bfd_group_name bfd_generic_group_name +#define srec_bfd_discard_group bfd_generic_discard_group +#define srec_section_already_linked _bfd_generic_section_already_linked +#define srec_bfd_define_common_symbol bfd_generic_define_common_symbol +#define srec_bfd_link_hide_symbol _bfd_generic_link_hide_symbol +#define srec_bfd_define_start_stop bfd_generic_define_start_stop +#define srec_bfd_link_hash_table_create _bfd_generic_link_hash_table_create +#define srec_bfd_link_add_symbols _bfd_generic_link_add_symbols +#define srec_bfd_link_just_syms _bfd_generic_link_just_syms +#define srec_bfd_copy_link_hash_symbol_type _bfd_generic_copy_link_hash_symbol_type +#define srec_bfd_final_link _bfd_generic_final_link +#define srec_bfd_link_split_section _bfd_generic_link_split_section +#define srec_bfd_link_check_relocs _bfd_generic_link_check_relocs const bfd_target srec_vec = { @@ -1225,6 +1304,7 @@ const bfd_target srec_vec = 0, /* Leading underscore. */ ' ', /* AR_pad_char. */ 16, /* AR_max_namelen. */ + 0, /* match priority. */ bfd_getb64, bfd_getb_signed_64, bfd_putb64, bfd_getb32, bfd_getb_signed_32, bfd_putb32, bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* Data. */ @@ -1239,16 +1319,16 @@ const bfd_target srec_vec = _bfd_dummy_target, }, { - bfd_false, + _bfd_bool_bfd_false_error, srec_mkobject, _bfd_generic_mkarchive, - bfd_false, + _bfd_bool_bfd_false_error, }, { /* bfd_write_contents. */ - bfd_false, + _bfd_bool_bfd_false_error, srec_write_object_contents, _bfd_write_archive_contents, - bfd_false, + _bfd_bool_bfd_false_error, }, BFD_JUMP_TABLE_GENERIC (srec), @@ -1280,6 +1360,7 @@ const bfd_target symbolsrec_vec = 0, /* Leading underscore. */ ' ', /* AR_pad_char. */ 16, /* AR_max_namelen. */ + 0, /* match priority. */ bfd_getb64, bfd_getb_signed_64, bfd_putb64, bfd_getb32, bfd_getb_signed_32, bfd_putb32, bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* Data. */ @@ -1294,16 +1375,16 @@ const bfd_target symbolsrec_vec = _bfd_dummy_target, }, { - bfd_false, + _bfd_bool_bfd_false_error, srec_mkobject, _bfd_generic_mkarchive, - bfd_false, + _bfd_bool_bfd_false_error, }, { /* bfd_write_contents. */ - bfd_false, + _bfd_bool_bfd_false_error, symbolsrec_write_object_contents, _bfd_write_archive_contents, - bfd_false, + _bfd_bool_bfd_false_error, }, BFD_JUMP_TABLE_GENERIC (srec),