* 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.
This commit is contained in:
Ian Lance Taylor 1995-12-04 22:08:45 +00:00
parent 545bf026d5
commit 55cac92082
2 changed files with 124 additions and 39 deletions

View File

@ -4,6 +4,12 @@ Mon Dec 4 16:40:47 1995 Kim Knuttila <krk@cygnus.com>
Mon Dec 4 11:25:39 1995 Ian Lance Taylor <ian@cygnus.com> Mon Dec 4 11:25:39 1995 Ian Lance Taylor <ian@cygnus.com>
* 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 * elflink.h (elf_link_output_extsym): Just ignore warning and
indirect references to symbols which don't really exist. indirect references to symbols which don't really exist.

View File

@ -85,6 +85,25 @@ B. INTEL 2
18..19 Checksum in hex notation 18..19 Checksum in hex notation
20..21 Carriage return, line feed 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" #include "bfd.h"
@ -237,7 +256,8 @@ static boolean
ihex_scan (abfd) ihex_scan (abfd)
bfd *abfd; bfd *abfd;
{ {
bfd_vma base; bfd_vma segbase;
bfd_vma extbase;
asection *sec; asection *sec;
int lineno; int lineno;
boolean error; boolean error;
@ -248,7 +268,10 @@ ihex_scan (abfd)
if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0) if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
goto error_return; goto error_return;
base = 0; abfd->start_address = 0;
extbase = 0;
segbase = 0;
sec = NULL; sec = NULL;
lineno = 1; lineno = 1;
error = false; error = false;
@ -343,7 +366,7 @@ ihex_scan (abfd)
case 0: case 0:
/* This is a data record. */ /* This is a data record. */
if (sec != NULL 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 /* This data goes at the end of the section we are
currently building. */ currently building. */
@ -363,8 +386,8 @@ ihex_scan (abfd)
if (sec == NULL) if (sec == NULL)
goto error_return; goto error_return;
sec->flags = SEC_HAS_CONTENTS | SEC_LOAD | SEC_ALLOC; sec->flags = SEC_HAS_CONTENTS | SEC_LOAD | SEC_ALLOC;
sec->vma = base + addr; sec->vma = extbase + segbase + addr;
sec->lma = base + addr; sec->lma = extbase + segbase + addr;
sec->_raw_size = len; sec->_raw_size = len;
sec->filepos = pos; sec->filepos = pos;
} }
@ -389,7 +412,7 @@ ihex_scan (abfd)
goto error_return; goto error_return;
} }
base = HEX4 (buf) << 4; segbase = HEX4 (buf) << 4;
sec = NULL; sec = NULL;
@ -406,7 +429,41 @@ ihex_scan (abfd)
goto error_return; 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; sec = NULL;
@ -473,7 +530,7 @@ ihex_object_p (abfd)
} }
type = HEX2 (b + 7); type = HEX2 (b + 7);
if (type > 3) if (type > 5)
{ {
bfd_set_error (bfd_error_wrong_format); bfd_set_error (bfd_error_wrong_format);
return NULL; return NULL;
@ -631,19 +688,6 @@ ihex_set_section_contents (abfd, section, location, offset, count)
|| (section->flags & SEC_LOAD) == 0) || (section->flags & SEC_LOAD) == 0)
return true; 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 *) n = ((struct ihex_data_list *)
bfd_alloc (abfd, sizeof (struct ihex_data_list))); bfd_alloc (abfd, sizeof (struct ihex_data_list)));
if (n == NULL) if (n == NULL)
@ -734,10 +778,12 @@ static boolean
ihex_write_object_contents (abfd) ihex_write_object_contents (abfd)
bfd *abfd; bfd *abfd;
{ {
bfd_vma base; bfd_vma extbase;
bfd_vma segbase;
struct ihex_data_list *l; struct ihex_data_list *l;
base = 0; extbase = 0;
segbase = 0;
for (l = abfd->tdata.ihex_data->head; l != NULL; l = l->next) for (l = abfd->tdata.ihex_data->head; l != NULL; l = l->next)
{ {
bfd_vma where; bfd_vma where;
@ -755,21 +801,42 @@ ihex_write_object_contents (abfd)
if (now > CHUNK) if (now > CHUNK)
now = CHUNK; now = CHUNK;
if (where > base + 0xffff) if (where > extbase + segbase + 0xffff)
{ {
bfd_byte addr[2]; bfd_byte addr[2];
/* We need a new base address. We've already checked in /* We need a new base address. */
set_section_contents to make sure that we can if (where <= 0xfffff)
represent the address. */ {
base = where & 0xf0000; segbase = where & 0xf0000;
addr[0] = (base >> 12) & 0xff; addr[0] = (segbase >> 12) & 0xff;
addr[1] = (base >> 4) & 0xff; addr[1] = (segbase >> 4) & 0xff;
if (! ihex_write_record (abfd, 2, 0, 2, addr)) if (! ihex_write_record (abfd, 2, 0, 2, addr))
return false; 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; return false;
where += now; where += now;
@ -780,13 +847,25 @@ ihex_write_object_contents (abfd)
if (abfd->start_address != 0) if (abfd->start_address != 0)
{ {
bfd_byte start[4]; bfd_vma start;
bfd_byte startbuf[4];
start[0] = ((abfd->start_address & 0xf0000) >> 12) & 0xff; start = abfd->start_address;
start[1] = 0;
start[2] = (abfd->start_address >> 8) & 0xff; if (start > 0xfffff)
start[3] = abfd->start_address & 0xff; {
if (! ihex_write_record (abfd, 4, 0, 3, start)) startbuf[0] = (start >> 24) & 0xff;
startbuf[1] = (start >> 16) & 0xff;
if (! ihex_write_record (abfd, 2, 0, 5, startbuf))
return false;
start &= 0xffff;
}
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; return false;
} }