From 55cac92082c7d16f531da393584ac3528549f692 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Mon, 4 Dec 1995 22:08:45 +0000 Subject: * ihex.c (ihex_scan): Handle record types 4 and 5. (ihex_object_p): Permit types 4 and 5. (ihex_set_section_contents): Remove check for out of range addresses. (ihex_write_object_contents): Generate types 4 and 5. --- bfd/ChangeLog | 6 +++ bfd/ihex.c | 157 +++++++++++++++++++++++++++++++++++++++++++--------------- 2 files changed, 124 insertions(+), 39 deletions(-) (limited to 'bfd') diff --git a/bfd/ChangeLog b/bfd/ChangeLog index efe2186..558c7ad 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -4,6 +4,12 @@ Mon Dec 4 16:40:47 1995 Kim Knuttila Mon Dec 4 11:25:39 1995 Ian Lance Taylor + * ihex.c (ihex_scan): Handle record types 4 and 5. + (ihex_object_p): Permit types 4 and 5. + (ihex_set_section_contents): Remove check for out of range + addresses. + (ihex_write_object_contents): Generate types 4 and 5. + * elflink.h (elf_link_output_extsym): Just ignore warning and indirect references to symbols which don't really exist. diff --git a/bfd/ihex.c b/bfd/ihex.c index c356bcb..512bf47 100644 --- a/bfd/ihex.c +++ b/bfd/ihex.c @@ -85,6 +85,25 @@ B. INTEL 2 18..19 Checksum in hex notation 20..21 Carriage return, line feed +Another document reports these additional types: + + EXTENDED LINEAR ADDRESS RECORD + Byte 1 Header = colon (:) + 2..3 The byte count, must be "02" + 4..7 Load address, must be "0000" + 8..9 Record type, must be "04" + 10..13 Upper 16 bits of address of subsequent records + 14..15 Checksum in hex notation + 16..17 Carriage return, line feed + + START LINEAR ADDRESS RECORD + Byte 1 Header = colon (:) + 2..3 The byte count, must be "02" + 4..7 Load address, must be "0000" + 8..9 Record type, must be "05" + 10..13 Upper 16 bits of start address + 14..15 Checksum in hex notation + 16..17 Carriage return, line feed */ #include "bfd.h" @@ -237,7 +256,8 @@ static boolean ihex_scan (abfd) bfd *abfd; { - bfd_vma base; + bfd_vma segbase; + bfd_vma extbase; asection *sec; int lineno; boolean error; @@ -248,7 +268,10 @@ ihex_scan (abfd) if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0) goto error_return; - base = 0; + abfd->start_address = 0; + + extbase = 0; + segbase = 0; sec = NULL; lineno = 1; error = false; @@ -343,7 +366,7 @@ ihex_scan (abfd) case 0: /* This is a data record. */ if (sec != NULL - && sec->vma + sec->_raw_size == base + addr) + && sec->vma + sec->_raw_size == extbase + segbase + addr) { /* This data goes at the end of the section we are currently building. */ @@ -363,8 +386,8 @@ ihex_scan (abfd) if (sec == NULL) goto error_return; sec->flags = SEC_HAS_CONTENTS | SEC_LOAD | SEC_ALLOC; - sec->vma = base + addr; - sec->lma = base + addr; + sec->vma = extbase + segbase + addr; + sec->lma = extbase + segbase + addr; sec->_raw_size = len; sec->filepos = pos; } @@ -389,7 +412,7 @@ ihex_scan (abfd) goto error_return; } - base = HEX4 (buf) << 4; + segbase = HEX4 (buf) << 4; sec = NULL; @@ -406,7 +429,41 @@ ihex_scan (abfd) goto error_return; } - abfd->start_address = (HEX4 (buf) << 4) + HEX4 (buf + 4); + abfd->start_address += (HEX4 (buf) << 4) + HEX4 (buf + 4); + + sec = NULL; + + break; + + case 4: + /* An extended linear address record. */ + if (len != 2) + { + (*_bfd_error_handler) + ("%s:%d: bad extended linear address record length in Intel Hex file", + bfd_get_filename (abfd), lineno); + bfd_set_error (bfd_error_bad_value); + goto error_return; + } + + segbase = HEX4 (buf) << 16; + + sec = NULL; + + break; + + case 5: + /* An extended linear start address record. */ + if (len != 2) + { + (*_bfd_error_handler) + ("%s:%d: bad extended linear start address length in Intel Hex file", + bfd_get_filename (abfd), lineno); + bfd_set_error (bfd_error_bad_value); + goto error_return; + } + + abfd->start_address += HEX4 (buf) << 16; sec = NULL; @@ -473,7 +530,7 @@ ihex_object_p (abfd) } type = HEX2 (b + 7); - if (type > 3) + if (type > 5) { bfd_set_error (bfd_error_wrong_format); return NULL; @@ -631,19 +688,6 @@ ihex_set_section_contents (abfd, section, location, offset, count) || (section->flags & SEC_LOAD) == 0) return true; - /* Intel Hex files can only represent a limited number of addresses. */ - if (section->lma + offset + count >= ((0xffff) << 4) + 0xffff) - { - char buf[50]; - - sprintf_vma (buf, section->lma + offset + count); - (*_bfd_error_handler) - ("%s: address 0x%s out of range for Intel Hex file", - bfd_get_filename (abfd), buf); - bfd_set_error (bfd_error_invalid_operation); - return false; - } - n = ((struct ihex_data_list *) bfd_alloc (abfd, sizeof (struct ihex_data_list))); if (n == NULL) @@ -734,10 +778,12 @@ static boolean ihex_write_object_contents (abfd) bfd *abfd; { - bfd_vma base; + bfd_vma extbase; + bfd_vma segbase; struct ihex_data_list *l; - base = 0; + extbase = 0; + segbase = 0; for (l = abfd->tdata.ihex_data->head; l != NULL; l = l->next) { bfd_vma where; @@ -755,21 +801,42 @@ ihex_write_object_contents (abfd) if (now > CHUNK) now = CHUNK; - if (where > base + 0xffff) + if (where > extbase + segbase + 0xffff) { bfd_byte addr[2]; - /* We need a new base address. We've already checked in - set_section_contents to make sure that we can - represent the address. */ - base = where & 0xf0000; - addr[0] = (base >> 12) & 0xff; - addr[1] = (base >> 4) & 0xff; - if (! ihex_write_record (abfd, 2, 0, 2, addr)) - return false; + /* We need a new base address. */ + if (where <= 0xfffff) + { + segbase = where & 0xf0000; + addr[0] = (segbase >> 12) & 0xff; + addr[1] = (segbase >> 4) & 0xff; + if (! ihex_write_record (abfd, 2, 0, 2, addr)) + return false; + } + else + { + extbase = where & 0xffff0000; + if (where > extbase + 0xffff) + { + char buf[20]; + + sprintf_vma (buf, where); + (*_bfd_error_handler) + ("%s: address 0x%s out of range for Intex Hex file", + bfd_get_filename (abfd), buf); + bfd_set_error (bfd_error_bad_value); + return false; + } + addr[0] = (extbase >> 24) & 0xff; + addr[1] = (extbase >> 16) & 0xff; + if (! ihex_write_record (abfd, 2, 0, 4, addr)) + return false; + } } - if (! ihex_write_record (abfd, now, where - base, 0, p)) + if (! ihex_write_record (abfd, now, where - (extbase + segbase), + 0, p)) return false; where += now; @@ -780,13 +847,25 @@ ihex_write_object_contents (abfd) if (abfd->start_address != 0) { - bfd_byte start[4]; + bfd_vma start; + bfd_byte startbuf[4]; + + start = abfd->start_address; + + if (start > 0xfffff) + { + startbuf[0] = (start >> 24) & 0xff; + startbuf[1] = (start >> 16) & 0xff; + if (! ihex_write_record (abfd, 2, 0, 5, startbuf)) + return false; + start &= 0xffff; + } - start[0] = ((abfd->start_address & 0xf0000) >> 12) & 0xff; - start[1] = 0; - start[2] = (abfd->start_address >> 8) & 0xff; - start[3] = abfd->start_address & 0xff; - if (! ihex_write_record (abfd, 4, 0, 3, start)) + startbuf[0] = ((start & 0xf0000) >> 12) & 0xff; + startbuf[1] = 0; + startbuf[2] = (start >> 8) & 0xff; + startbuf[3] = start & 0xff; + if (! ihex_write_record (abfd, 4, 0, 3, startbuf)) return false; } -- cgit v1.1