xref: /dragonfly/contrib/gdb-7/bfd/ihex.c (revision a45ae5f8)
15796c8dcSSimon Schubert /* BFD back-end for Intel Hex objects.
25796c8dcSSimon Schubert    Copyright 1995, 1996, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
3*a45ae5f8SJohn Marino    2006, 2007, 2009, 2011 Free Software Foundation, Inc.
45796c8dcSSimon Schubert    Written by Ian Lance Taylor of Cygnus Support <ian@cygnus.com>.
55796c8dcSSimon Schubert 
65796c8dcSSimon Schubert    This file is part of BFD, the Binary File Descriptor library.
75796c8dcSSimon Schubert 
85796c8dcSSimon Schubert    This program is free software; you can redistribute it and/or modify
95796c8dcSSimon Schubert    it under the terms of the GNU General Public License as published by
105796c8dcSSimon Schubert    the Free Software Foundation; either version 3 of the License, or
115796c8dcSSimon Schubert    (at your option) any later version.
125796c8dcSSimon Schubert 
135796c8dcSSimon Schubert    This program is distributed in the hope that it will be useful,
145796c8dcSSimon Schubert    but WITHOUT ANY WARRANTY; without even the implied warranty of
155796c8dcSSimon Schubert    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
165796c8dcSSimon Schubert    GNU General Public License for more details.
175796c8dcSSimon Schubert 
185796c8dcSSimon Schubert    You should have received a copy of the GNU General Public License
195796c8dcSSimon Schubert    along with this program; if not, write to the Free Software
205796c8dcSSimon Schubert    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
215796c8dcSSimon Schubert    MA 02110-1301, USA.  */
225796c8dcSSimon Schubert 
235796c8dcSSimon Schubert 
245796c8dcSSimon Schubert /* This is what Intel Hex files look like:
255796c8dcSSimon Schubert 
265796c8dcSSimon Schubert 1. INTEL FORMATS
275796c8dcSSimon Schubert 
285796c8dcSSimon Schubert A. Intel 1
295796c8dcSSimon Schubert 
305796c8dcSSimon Schubert    16-bit address-field format, for files 64k bytes in length or less.
315796c8dcSSimon Schubert 
325796c8dcSSimon Schubert    DATA RECORD
335796c8dcSSimon Schubert    Byte 1	Header = colon(:)
345796c8dcSSimon Schubert    2..3		The number of data bytes in hex notation
355796c8dcSSimon Schubert    4..5		High byte of the record load address
365796c8dcSSimon Schubert    6..7		Low byte of the record load address
375796c8dcSSimon Schubert    8..9		Record type, must be "00"
385796c8dcSSimon Schubert    10..x	Data bytes in hex notation:
395796c8dcSSimon Schubert 	x = (number of bytes - 1) * 2 + 11
405796c8dcSSimon Schubert    x+1..x+2	Checksum in hex notation
415796c8dcSSimon Schubert    x+3..x+4	Carriage return, line feed
425796c8dcSSimon Schubert 
435796c8dcSSimon Schubert    END RECORD
445796c8dcSSimon Schubert    Byte 1	Header = colon (:)
455796c8dcSSimon Schubert    2..3		The byte count, must be "00"
465796c8dcSSimon Schubert    4..7		Transfer-address (usually "0000")
475796c8dcSSimon Schubert 		the jump-to address, execution start address
485796c8dcSSimon Schubert    8..9		Record type, must be "01"
495796c8dcSSimon Schubert    10..11	Checksum, in hex notation
505796c8dcSSimon Schubert    12..13	Carriage return, line feed
515796c8dcSSimon Schubert 
525796c8dcSSimon Schubert B. INTEL 2
535796c8dcSSimon Schubert 
545796c8dcSSimon Schubert    MCS-86 format, using a 20-bit address for files larger than 64K bytes.
555796c8dcSSimon Schubert 
565796c8dcSSimon Schubert    DATA RECORD
575796c8dcSSimon Schubert    Byte 1	Header = colon (:)
585796c8dcSSimon Schubert    2..3		The byte count of this record, hex notation
595796c8dcSSimon Schubert    4..5		High byte of the record load address
605796c8dcSSimon Schubert    6..7		Low byte of the record load address
615796c8dcSSimon Schubert    8..9		Record type, must be "00"
625796c8dcSSimon Schubert    10..x	The data bytes in hex notation:
635796c8dcSSimon Schubert 	x = (number of data bytes - 1) * 2 + 11
645796c8dcSSimon Schubert    x+1..x+2	Checksum in hex notation
655796c8dcSSimon Schubert    x+3..x+4	Carriage return, line feed
665796c8dcSSimon Schubert 
675796c8dcSSimon Schubert    EXTENDED ADDRESS RECORD
685796c8dcSSimon Schubert    Byte 1	Header = colon(:)
695796c8dcSSimon Schubert    2..3		The byte count, must be "02"
705796c8dcSSimon Schubert    4..7		Load address, must be "0000"
715796c8dcSSimon Schubert    8..9		Record type, must be "02"
725796c8dcSSimon Schubert    10..11	High byte of the offset address
735796c8dcSSimon Schubert    12..13	Low byte of the offset address
745796c8dcSSimon Schubert    14..15	Checksum in hex notation
755796c8dcSSimon Schubert    16..17	Carriage return, line feed
765796c8dcSSimon Schubert 
775796c8dcSSimon Schubert    The checksums are the two's complement of the 8-bit sum
785796c8dcSSimon Schubert    without carry of the byte count, offset address, and the
795796c8dcSSimon Schubert    record type.
805796c8dcSSimon Schubert 
815796c8dcSSimon Schubert    START ADDRESS RECORD
825796c8dcSSimon Schubert    Byte 1	Header = colon (:)
835796c8dcSSimon Schubert    2..3		The byte count, must be "04"
845796c8dcSSimon Schubert    4..7		Load address, must be "0000"
855796c8dcSSimon Schubert    8..9		Record type, must be "03"
865796c8dcSSimon Schubert    10..13	8086 CS value
875796c8dcSSimon Schubert    14..17	8086 IP value
885796c8dcSSimon Schubert    18..19	Checksum in hex notation
895796c8dcSSimon Schubert    20..21	Carriage return, line feed
905796c8dcSSimon Schubert 
915796c8dcSSimon Schubert Another document reports these additional types:
925796c8dcSSimon Schubert 
935796c8dcSSimon Schubert    EXTENDED LINEAR ADDRESS RECORD
945796c8dcSSimon Schubert    Byte 1	Header = colon (:)
955796c8dcSSimon Schubert    2..3		The byte count, must be "02"
965796c8dcSSimon Schubert    4..7		Load address, must be "0000"
975796c8dcSSimon Schubert    8..9		Record type, must be "04"
985796c8dcSSimon Schubert    10..13	Upper 16 bits of address of subsequent records
995796c8dcSSimon Schubert    14..15	Checksum in hex notation
1005796c8dcSSimon Schubert    16..17	Carriage return, line feed
1015796c8dcSSimon Schubert 
1025796c8dcSSimon Schubert    START LINEAR ADDRESS RECORD
1035796c8dcSSimon Schubert    Byte 1	Header = colon (:)
1045796c8dcSSimon Schubert    2..3		The byte count, must be "02"
1055796c8dcSSimon Schubert    4..7		Load address, must be "0000"
1065796c8dcSSimon Schubert    8..9		Record type, must be "05"
1075796c8dcSSimon Schubert    10..13	Upper 16 bits of start address
1085796c8dcSSimon Schubert    14..15	Checksum in hex notation
1095796c8dcSSimon Schubert    16..17	Carriage return, line feed
1105796c8dcSSimon Schubert 
1115796c8dcSSimon Schubert The MRI compiler uses this, which is a repeat of type 5:
1125796c8dcSSimon Schubert 
1135796c8dcSSimon Schubert   EXTENDED START RECORD
1145796c8dcSSimon Schubert    Byte 1	Header = colon (:)
1155796c8dcSSimon Schubert    2..3		The byte count, must be "04"
1165796c8dcSSimon Schubert    4..7		Load address, must be "0000"
1175796c8dcSSimon Schubert    8..9		Record type, must be "05"
1185796c8dcSSimon Schubert    10..13	Upper 16 bits of start address
1195796c8dcSSimon Schubert    14..17	Lower 16 bits of start address
1205796c8dcSSimon Schubert    18..19	Checksum in hex notation
1215796c8dcSSimon Schubert    20..21	Carriage return, line feed.  */
1225796c8dcSSimon Schubert 
1235796c8dcSSimon Schubert #include "sysdep.h"
1245796c8dcSSimon Schubert #include "bfd.h"
1255796c8dcSSimon Schubert #include "libbfd.h"
1265796c8dcSSimon Schubert #include "libiberty.h"
1275796c8dcSSimon Schubert #include "safe-ctype.h"
1285796c8dcSSimon Schubert 
1295796c8dcSSimon Schubert /* The number of bytes we put on one line during output.  */
1305796c8dcSSimon Schubert 
1315796c8dcSSimon Schubert #define CHUNK 16
1325796c8dcSSimon Schubert 
1335796c8dcSSimon Schubert /* Macros for converting between hex and binary.  */
1345796c8dcSSimon Schubert 
1355796c8dcSSimon Schubert #define NIBBLE(x)    (hex_value (x))
1365796c8dcSSimon Schubert #define HEX2(buffer) ((NIBBLE ((buffer)[0]) << 4) + NIBBLE ((buffer)[1]))
1375796c8dcSSimon Schubert #define HEX4(buffer) ((HEX2 (buffer) << 8) + HEX2 ((buffer) + 2))
1385796c8dcSSimon Schubert #define ISHEX(x)     (hex_p (x))
1395796c8dcSSimon Schubert 
1405796c8dcSSimon Schubert /* When we write out an ihex value, the values can not be output as
1415796c8dcSSimon Schubert    they are seen.  Instead, we hold them in memory in this structure.  */
1425796c8dcSSimon Schubert 
1435796c8dcSSimon Schubert struct ihex_data_list
1445796c8dcSSimon Schubert {
1455796c8dcSSimon Schubert   struct ihex_data_list *next;
1465796c8dcSSimon Schubert   bfd_byte *data;
1475796c8dcSSimon Schubert   bfd_vma where;
1485796c8dcSSimon Schubert   bfd_size_type size;
1495796c8dcSSimon Schubert };
1505796c8dcSSimon Schubert 
1515796c8dcSSimon Schubert /* The ihex tdata information.  */
1525796c8dcSSimon Schubert 
1535796c8dcSSimon Schubert struct ihex_data_struct
1545796c8dcSSimon Schubert {
1555796c8dcSSimon Schubert   struct ihex_data_list *head;
1565796c8dcSSimon Schubert   struct ihex_data_list *tail;
1575796c8dcSSimon Schubert };
1585796c8dcSSimon Schubert 
1595796c8dcSSimon Schubert /* Initialize by filling in the hex conversion array.  */
1605796c8dcSSimon Schubert 
1615796c8dcSSimon Schubert static void
ihex_init(void)1625796c8dcSSimon Schubert ihex_init (void)
1635796c8dcSSimon Schubert {
1645796c8dcSSimon Schubert   static bfd_boolean inited;
1655796c8dcSSimon Schubert 
1665796c8dcSSimon Schubert   if (! inited)
1675796c8dcSSimon Schubert     {
1685796c8dcSSimon Schubert       inited = TRUE;
1695796c8dcSSimon Schubert       hex_init ();
1705796c8dcSSimon Schubert     }
1715796c8dcSSimon Schubert }
1725796c8dcSSimon Schubert 
1735796c8dcSSimon Schubert /* Create an ihex object.  */
1745796c8dcSSimon Schubert 
1755796c8dcSSimon Schubert static bfd_boolean
ihex_mkobject(bfd * abfd)1765796c8dcSSimon Schubert ihex_mkobject (bfd *abfd)
1775796c8dcSSimon Schubert {
1785796c8dcSSimon Schubert   struct ihex_data_struct *tdata;
1795796c8dcSSimon Schubert 
1805796c8dcSSimon Schubert   tdata = (struct ihex_data_struct *) bfd_alloc (abfd, sizeof (* tdata));
1815796c8dcSSimon Schubert   if (tdata == NULL)
1825796c8dcSSimon Schubert     return FALSE;
1835796c8dcSSimon Schubert 
1845796c8dcSSimon Schubert   abfd->tdata.ihex_data = tdata;
1855796c8dcSSimon Schubert   tdata->head = NULL;
1865796c8dcSSimon Schubert   tdata->tail = NULL;
1875796c8dcSSimon Schubert   return TRUE;
1885796c8dcSSimon Schubert }
1895796c8dcSSimon Schubert 
1905796c8dcSSimon Schubert /* Read a byte from a BFD.  Set *ERRORPTR if an error occurred.
1915796c8dcSSimon Schubert    Return EOF on error or end of file.  */
1925796c8dcSSimon Schubert 
1935796c8dcSSimon Schubert static INLINE int
ihex_get_byte(bfd * abfd,bfd_boolean * errorptr)1945796c8dcSSimon Schubert ihex_get_byte (bfd *abfd, bfd_boolean *errorptr)
1955796c8dcSSimon Schubert {
1965796c8dcSSimon Schubert   bfd_byte c;
1975796c8dcSSimon Schubert 
1985796c8dcSSimon Schubert   if (bfd_bread (&c, (bfd_size_type) 1, abfd) != 1)
1995796c8dcSSimon Schubert     {
2005796c8dcSSimon Schubert       if (bfd_get_error () != bfd_error_file_truncated)
2015796c8dcSSimon Schubert 	*errorptr = TRUE;
2025796c8dcSSimon Schubert       return EOF;
2035796c8dcSSimon Schubert     }
2045796c8dcSSimon Schubert 
2055796c8dcSSimon Schubert   return (int) (c & 0xff);
2065796c8dcSSimon Schubert }
2075796c8dcSSimon Schubert 
2085796c8dcSSimon Schubert /* Report a problem in an Intel Hex file.  */
2095796c8dcSSimon Schubert 
2105796c8dcSSimon Schubert static void
ihex_bad_byte(bfd * abfd,unsigned int lineno,int c,bfd_boolean error)2115796c8dcSSimon Schubert ihex_bad_byte (bfd *abfd, unsigned int lineno, int c, bfd_boolean error)
2125796c8dcSSimon Schubert {
2135796c8dcSSimon Schubert   if (c == EOF)
2145796c8dcSSimon Schubert     {
2155796c8dcSSimon Schubert       if (! error)
2165796c8dcSSimon Schubert 	bfd_set_error (bfd_error_file_truncated);
2175796c8dcSSimon Schubert     }
2185796c8dcSSimon Schubert   else
2195796c8dcSSimon Schubert     {
2205796c8dcSSimon Schubert       char buf[10];
2215796c8dcSSimon Schubert 
2225796c8dcSSimon Schubert       if (! ISPRINT (c))
2235796c8dcSSimon Schubert 	sprintf (buf, "\\%03o", (unsigned int) c);
2245796c8dcSSimon Schubert       else
2255796c8dcSSimon Schubert 	{
2265796c8dcSSimon Schubert 	  buf[0] = c;
2275796c8dcSSimon Schubert 	  buf[1] = '\0';
2285796c8dcSSimon Schubert 	}
2295796c8dcSSimon Schubert       (*_bfd_error_handler)
2305796c8dcSSimon Schubert 	(_("%B:%d: unexpected character `%s' in Intel Hex file"),
2315796c8dcSSimon Schubert 	 abfd, lineno, buf);
2325796c8dcSSimon Schubert       bfd_set_error (bfd_error_bad_value);
2335796c8dcSSimon Schubert     }
2345796c8dcSSimon Schubert }
2355796c8dcSSimon Schubert 
2365796c8dcSSimon Schubert /* Read an Intel hex file and turn it into sections.  We create a new
2375796c8dcSSimon Schubert    section for each contiguous set of bytes.  */
2385796c8dcSSimon Schubert 
2395796c8dcSSimon Schubert static bfd_boolean
ihex_scan(bfd * abfd)2405796c8dcSSimon Schubert ihex_scan (bfd *abfd)
2415796c8dcSSimon Schubert {
2425796c8dcSSimon Schubert   bfd_vma segbase;
2435796c8dcSSimon Schubert   bfd_vma extbase;
2445796c8dcSSimon Schubert   asection *sec;
2455796c8dcSSimon Schubert   unsigned int lineno;
2465796c8dcSSimon Schubert   bfd_boolean error;
2475796c8dcSSimon Schubert   bfd_byte *buf = NULL;
2485796c8dcSSimon Schubert   size_t bufsize;
2495796c8dcSSimon Schubert   int c;
2505796c8dcSSimon Schubert 
2515796c8dcSSimon Schubert   if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
2525796c8dcSSimon Schubert     goto error_return;
2535796c8dcSSimon Schubert 
2545796c8dcSSimon Schubert   abfd->start_address = 0;
2555796c8dcSSimon Schubert 
2565796c8dcSSimon Schubert   segbase = 0;
2575796c8dcSSimon Schubert   extbase = 0;
2585796c8dcSSimon Schubert   sec = NULL;
2595796c8dcSSimon Schubert   lineno = 1;
2605796c8dcSSimon Schubert   error = FALSE;
2615796c8dcSSimon Schubert   bufsize = 0;
2625796c8dcSSimon Schubert 
2635796c8dcSSimon Schubert   while ((c = ihex_get_byte (abfd, &error)) != EOF)
2645796c8dcSSimon Schubert     {
2655796c8dcSSimon Schubert       if (c == '\r')
2665796c8dcSSimon Schubert 	continue;
2675796c8dcSSimon Schubert       else if (c == '\n')
2685796c8dcSSimon Schubert 	{
2695796c8dcSSimon Schubert 	  ++lineno;
2705796c8dcSSimon Schubert 	  continue;
2715796c8dcSSimon Schubert 	}
2725796c8dcSSimon Schubert       else if (c != ':')
2735796c8dcSSimon Schubert 	{
2745796c8dcSSimon Schubert 	  ihex_bad_byte (abfd, lineno, c, error);
2755796c8dcSSimon Schubert 	  goto error_return;
2765796c8dcSSimon Schubert 	}
2775796c8dcSSimon Schubert       else
2785796c8dcSSimon Schubert 	{
2795796c8dcSSimon Schubert 	  file_ptr pos;
2805796c8dcSSimon Schubert 	  char hdr[8];
2815796c8dcSSimon Schubert 	  unsigned int i;
2825796c8dcSSimon Schubert 	  unsigned int len;
2835796c8dcSSimon Schubert 	  bfd_vma addr;
2845796c8dcSSimon Schubert 	  unsigned int type;
2855796c8dcSSimon Schubert 	  unsigned int chars;
2865796c8dcSSimon Schubert 	  unsigned int chksum;
2875796c8dcSSimon Schubert 
2885796c8dcSSimon Schubert 	  /* This is a data record.  */
2895796c8dcSSimon Schubert 	  pos = bfd_tell (abfd) - 1;
2905796c8dcSSimon Schubert 
2915796c8dcSSimon Schubert 	  /* Read the header bytes.  */
2925796c8dcSSimon Schubert 	  if (bfd_bread (hdr, (bfd_size_type) 8, abfd) != 8)
2935796c8dcSSimon Schubert 	    goto error_return;
2945796c8dcSSimon Schubert 
2955796c8dcSSimon Schubert 	  for (i = 0; i < 8; i++)
2965796c8dcSSimon Schubert 	    {
2975796c8dcSSimon Schubert 	      if (! ISHEX (hdr[i]))
2985796c8dcSSimon Schubert 		{
2995796c8dcSSimon Schubert 		  ihex_bad_byte (abfd, lineno, hdr[i], error);
3005796c8dcSSimon Schubert 		  goto error_return;
3015796c8dcSSimon Schubert 		}
3025796c8dcSSimon Schubert 	    }
3035796c8dcSSimon Schubert 
3045796c8dcSSimon Schubert 	  len = HEX2 (hdr);
3055796c8dcSSimon Schubert 	  addr = HEX4 (hdr + 2);
3065796c8dcSSimon Schubert 	  type = HEX2 (hdr + 6);
3075796c8dcSSimon Schubert 
3085796c8dcSSimon Schubert 	  /* Read the data bytes.  */
3095796c8dcSSimon Schubert 	  chars = len * 2 + 2;
3105796c8dcSSimon Schubert 	  if (chars >= bufsize)
3115796c8dcSSimon Schubert 	    {
3125796c8dcSSimon Schubert 	      buf = (bfd_byte *) bfd_realloc (buf, (bfd_size_type) chars);
3135796c8dcSSimon Schubert 	      if (buf == NULL)
3145796c8dcSSimon Schubert 		goto error_return;
3155796c8dcSSimon Schubert 	      bufsize = chars;
3165796c8dcSSimon Schubert 	    }
3175796c8dcSSimon Schubert 
3185796c8dcSSimon Schubert 	  if (bfd_bread (buf, (bfd_size_type) chars, abfd) != chars)
3195796c8dcSSimon Schubert 	    goto error_return;
3205796c8dcSSimon Schubert 
3215796c8dcSSimon Schubert 	  for (i = 0; i < chars; i++)
3225796c8dcSSimon Schubert 	    {
3235796c8dcSSimon Schubert 	      if (! ISHEX (buf[i]))
3245796c8dcSSimon Schubert 		{
3255796c8dcSSimon Schubert 		  ihex_bad_byte (abfd, lineno, hdr[i], error);
3265796c8dcSSimon Schubert 		  goto error_return;
3275796c8dcSSimon Schubert 		}
3285796c8dcSSimon Schubert 	    }
3295796c8dcSSimon Schubert 
3305796c8dcSSimon Schubert 	  /* Check the checksum.  */
3315796c8dcSSimon Schubert 	  chksum = len + addr + (addr >> 8) + type;
3325796c8dcSSimon Schubert 	  for (i = 0; i < len; i++)
3335796c8dcSSimon Schubert 	    chksum += HEX2 (buf + 2 * i);
3345796c8dcSSimon Schubert 	  if (((- chksum) & 0xff) != (unsigned int) HEX2 (buf + 2 * i))
3355796c8dcSSimon Schubert 	    {
3365796c8dcSSimon Schubert 	      (*_bfd_error_handler)
3375796c8dcSSimon Schubert 		(_("%B:%u: bad checksum in Intel Hex file (expected %u, found %u)"),
3385796c8dcSSimon Schubert 		 abfd, lineno,
3395796c8dcSSimon Schubert 		 (- chksum) & 0xff, (unsigned int) HEX2 (buf + 2 * i));
3405796c8dcSSimon Schubert 	      bfd_set_error (bfd_error_bad_value);
3415796c8dcSSimon Schubert 	      goto error_return;
3425796c8dcSSimon Schubert 	    }
3435796c8dcSSimon Schubert 
3445796c8dcSSimon Schubert 	  switch (type)
3455796c8dcSSimon Schubert 	    {
3465796c8dcSSimon Schubert 	    case 0:
3475796c8dcSSimon Schubert 	      /* This is a data record.  */
3485796c8dcSSimon Schubert 	      if (sec != NULL
3495796c8dcSSimon Schubert 		  && sec->vma + sec->size == extbase + segbase + addr)
3505796c8dcSSimon Schubert 		{
3515796c8dcSSimon Schubert 		  /* This data goes at the end of the section we are
3525796c8dcSSimon Schubert                      currently building.  */
3535796c8dcSSimon Schubert 		  sec->size += len;
3545796c8dcSSimon Schubert 		}
3555796c8dcSSimon Schubert 	      else if (len > 0)
3565796c8dcSSimon Schubert 		{
3575796c8dcSSimon Schubert 		  char secbuf[20];
3585796c8dcSSimon Schubert 		  char *secname;
3595796c8dcSSimon Schubert 		  bfd_size_type amt;
3605796c8dcSSimon Schubert 		  flagword flags;
3615796c8dcSSimon Schubert 
3625796c8dcSSimon Schubert 		  sprintf (secbuf, ".sec%d", bfd_count_sections (abfd) + 1);
3635796c8dcSSimon Schubert 		  amt = strlen (secbuf) + 1;
3645796c8dcSSimon Schubert 		  secname = (char *) bfd_alloc (abfd, amt);
3655796c8dcSSimon Schubert 		  if (secname == NULL)
3665796c8dcSSimon Schubert 		    goto error_return;
3675796c8dcSSimon Schubert 		  strcpy (secname, secbuf);
3685796c8dcSSimon Schubert 		  flags = SEC_HAS_CONTENTS | SEC_LOAD | SEC_ALLOC;
3695796c8dcSSimon Schubert 		  sec = bfd_make_section_with_flags (abfd, secname, flags);
3705796c8dcSSimon Schubert 		  if (sec == NULL)
3715796c8dcSSimon Schubert 		    goto error_return;
3725796c8dcSSimon Schubert 		  sec->vma = extbase + segbase + addr;
3735796c8dcSSimon Schubert 		  sec->lma = extbase + segbase + addr;
3745796c8dcSSimon Schubert 		  sec->size = len;
3755796c8dcSSimon Schubert 		  sec->filepos = pos;
3765796c8dcSSimon Schubert 		}
3775796c8dcSSimon Schubert 	      break;
3785796c8dcSSimon Schubert 
3795796c8dcSSimon Schubert 	    case 1:
3805796c8dcSSimon Schubert 	      /* An end record.  */
3815796c8dcSSimon Schubert 	      if (abfd->start_address == 0)
3825796c8dcSSimon Schubert 		abfd->start_address = addr;
3835796c8dcSSimon Schubert 	      if (buf != NULL)
3845796c8dcSSimon Schubert 		free (buf);
3855796c8dcSSimon Schubert 	      return TRUE;
3865796c8dcSSimon Schubert 
3875796c8dcSSimon Schubert 	    case 2:
3885796c8dcSSimon Schubert 	      /* An extended address record.  */
3895796c8dcSSimon Schubert 	      if (len != 2)
3905796c8dcSSimon Schubert 		{
3915796c8dcSSimon Schubert 		  (*_bfd_error_handler)
3925796c8dcSSimon Schubert 		    (_("%B:%u: bad extended address record length in Intel Hex file"),
3935796c8dcSSimon Schubert 		     abfd, lineno);
3945796c8dcSSimon Schubert 		  bfd_set_error (bfd_error_bad_value);
3955796c8dcSSimon Schubert 		  goto error_return;
3965796c8dcSSimon Schubert 		}
3975796c8dcSSimon Schubert 
3985796c8dcSSimon Schubert 	      segbase = HEX4 (buf) << 4;
3995796c8dcSSimon Schubert 
4005796c8dcSSimon Schubert 	      sec = NULL;
4015796c8dcSSimon Schubert 
4025796c8dcSSimon Schubert 	      break;
4035796c8dcSSimon Schubert 
4045796c8dcSSimon Schubert 	    case 3:
4055796c8dcSSimon Schubert 	      /* An extended start address record.  */
4065796c8dcSSimon Schubert 	      if (len != 4)
4075796c8dcSSimon Schubert 		{
4085796c8dcSSimon Schubert 		  (*_bfd_error_handler)
4095796c8dcSSimon Schubert 		    (_("%B:%u: bad extended start address length in Intel Hex file"),
4105796c8dcSSimon Schubert 		     abfd, lineno);
4115796c8dcSSimon Schubert 		  bfd_set_error (bfd_error_bad_value);
4125796c8dcSSimon Schubert 		  goto error_return;
4135796c8dcSSimon Schubert 		}
4145796c8dcSSimon Schubert 
4155796c8dcSSimon Schubert 	      abfd->start_address += (HEX4 (buf) << 4) + HEX4 (buf + 4);
4165796c8dcSSimon Schubert 
4175796c8dcSSimon Schubert 	      sec = NULL;
4185796c8dcSSimon Schubert 
4195796c8dcSSimon Schubert 	      break;
4205796c8dcSSimon Schubert 
4215796c8dcSSimon Schubert 	    case 4:
4225796c8dcSSimon Schubert 	      /* An extended linear address record.  */
4235796c8dcSSimon Schubert 	      if (len != 2)
4245796c8dcSSimon Schubert 		{
4255796c8dcSSimon Schubert 		  (*_bfd_error_handler)
4265796c8dcSSimon Schubert 		    (_("%B:%u: bad extended linear address record length in Intel Hex file"),
4275796c8dcSSimon Schubert 		     abfd, lineno);
4285796c8dcSSimon Schubert 		  bfd_set_error (bfd_error_bad_value);
4295796c8dcSSimon Schubert 		  goto error_return;
4305796c8dcSSimon Schubert 		}
4315796c8dcSSimon Schubert 
4325796c8dcSSimon Schubert 	      extbase = HEX4 (buf) << 16;
4335796c8dcSSimon Schubert 
4345796c8dcSSimon Schubert 	      sec = NULL;
4355796c8dcSSimon Schubert 
4365796c8dcSSimon Schubert 	      break;
4375796c8dcSSimon Schubert 
4385796c8dcSSimon Schubert 	    case 5:
4395796c8dcSSimon Schubert 	      /* An extended linear start address record.  */
4405796c8dcSSimon Schubert 	      if (len != 2 && len != 4)
4415796c8dcSSimon Schubert 		{
4425796c8dcSSimon Schubert 		  (*_bfd_error_handler)
4435796c8dcSSimon Schubert 		    (_("%B:%u: bad extended linear start address length in Intel Hex file"),
4445796c8dcSSimon Schubert 		     abfd, lineno);
4455796c8dcSSimon Schubert 		  bfd_set_error (bfd_error_bad_value);
4465796c8dcSSimon Schubert 		  goto error_return;
4475796c8dcSSimon Schubert 		}
4485796c8dcSSimon Schubert 
4495796c8dcSSimon Schubert 	      if (len == 2)
4505796c8dcSSimon Schubert 		abfd->start_address += HEX4 (buf) << 16;
4515796c8dcSSimon Schubert 	      else
4525796c8dcSSimon Schubert 		abfd->start_address = (HEX4 (buf) << 16) + HEX4 (buf + 4);
4535796c8dcSSimon Schubert 
4545796c8dcSSimon Schubert 	      sec = NULL;
4555796c8dcSSimon Schubert 
4565796c8dcSSimon Schubert 	      break;
4575796c8dcSSimon Schubert 
4585796c8dcSSimon Schubert 	    default:
4595796c8dcSSimon Schubert 	      (*_bfd_error_handler)
4605796c8dcSSimon Schubert 		(_("%B:%u: unrecognized ihex type %u in Intel Hex file"),
4615796c8dcSSimon Schubert 		 abfd, lineno, type);
4625796c8dcSSimon Schubert 	      bfd_set_error (bfd_error_bad_value);
4635796c8dcSSimon Schubert 	      goto error_return;
4645796c8dcSSimon Schubert 	    }
4655796c8dcSSimon Schubert 	}
4665796c8dcSSimon Schubert     }
4675796c8dcSSimon Schubert 
4685796c8dcSSimon Schubert   if (error)
4695796c8dcSSimon Schubert     goto error_return;
4705796c8dcSSimon Schubert 
4715796c8dcSSimon Schubert   if (buf != NULL)
4725796c8dcSSimon Schubert     free (buf);
4735796c8dcSSimon Schubert 
4745796c8dcSSimon Schubert   return TRUE;
4755796c8dcSSimon Schubert 
4765796c8dcSSimon Schubert  error_return:
4775796c8dcSSimon Schubert   if (buf != NULL)
4785796c8dcSSimon Schubert     free (buf);
4795796c8dcSSimon Schubert   return FALSE;
4805796c8dcSSimon Schubert }
4815796c8dcSSimon Schubert 
4825796c8dcSSimon Schubert /* Try to recognize an Intel Hex file.  */
4835796c8dcSSimon Schubert 
4845796c8dcSSimon Schubert static const bfd_target *
ihex_object_p(bfd * abfd)4855796c8dcSSimon Schubert ihex_object_p (bfd *abfd)
4865796c8dcSSimon Schubert {
4875796c8dcSSimon Schubert   void * tdata_save;
4885796c8dcSSimon Schubert   bfd_byte b[9];
4895796c8dcSSimon Schubert   unsigned int i;
4905796c8dcSSimon Schubert   unsigned int type;
4915796c8dcSSimon Schubert 
4925796c8dcSSimon Schubert   ihex_init ();
4935796c8dcSSimon Schubert 
4945796c8dcSSimon Schubert   if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
4955796c8dcSSimon Schubert     return NULL;
4965796c8dcSSimon Schubert   if (bfd_bread (b, (bfd_size_type) 9, abfd) != 9)
4975796c8dcSSimon Schubert     {
4985796c8dcSSimon Schubert       if (bfd_get_error () == bfd_error_file_truncated)
4995796c8dcSSimon Schubert 	bfd_set_error (bfd_error_wrong_format);
5005796c8dcSSimon Schubert       return NULL;
5015796c8dcSSimon Schubert     }
5025796c8dcSSimon Schubert 
5035796c8dcSSimon Schubert   if (b[0] != ':')
5045796c8dcSSimon Schubert     {
5055796c8dcSSimon Schubert       bfd_set_error (bfd_error_wrong_format);
5065796c8dcSSimon Schubert       return NULL;
5075796c8dcSSimon Schubert     }
5085796c8dcSSimon Schubert 
5095796c8dcSSimon Schubert   for (i = 1; i < 9; i++)
5105796c8dcSSimon Schubert     {
5115796c8dcSSimon Schubert       if (! ISHEX (b[i]))
5125796c8dcSSimon Schubert 	{
5135796c8dcSSimon Schubert 	  bfd_set_error (bfd_error_wrong_format);
5145796c8dcSSimon Schubert 	  return NULL;
5155796c8dcSSimon Schubert 	}
5165796c8dcSSimon Schubert     }
5175796c8dcSSimon Schubert 
5185796c8dcSSimon Schubert   type = HEX2 (b + 7);
5195796c8dcSSimon Schubert   if (type > 5)
5205796c8dcSSimon Schubert     {
5215796c8dcSSimon Schubert       bfd_set_error (bfd_error_wrong_format);
5225796c8dcSSimon Schubert       return NULL;
5235796c8dcSSimon Schubert     }
5245796c8dcSSimon Schubert 
5255796c8dcSSimon Schubert   /* OK, it looks like it really is an Intel Hex file.  */
5265796c8dcSSimon Schubert   tdata_save = abfd->tdata.any;
5275796c8dcSSimon Schubert   if (! ihex_mkobject (abfd) || ! ihex_scan (abfd))
5285796c8dcSSimon Schubert     {
5295796c8dcSSimon Schubert       if (abfd->tdata.any != tdata_save && abfd->tdata.any != NULL)
5305796c8dcSSimon Schubert 	bfd_release (abfd, abfd->tdata.any);
5315796c8dcSSimon Schubert       abfd->tdata.any = tdata_save;
5325796c8dcSSimon Schubert       return NULL;
5335796c8dcSSimon Schubert     }
5345796c8dcSSimon Schubert 
5355796c8dcSSimon Schubert   return abfd->xvec;
5365796c8dcSSimon Schubert }
5375796c8dcSSimon Schubert 
5385796c8dcSSimon Schubert /* Read the contents of a section in an Intel Hex file.  */
5395796c8dcSSimon Schubert 
5405796c8dcSSimon Schubert static bfd_boolean
ihex_read_section(bfd * abfd,asection * section,bfd_byte * contents)5415796c8dcSSimon Schubert ihex_read_section (bfd *abfd, asection *section, bfd_byte *contents)
5425796c8dcSSimon Schubert {
5435796c8dcSSimon Schubert   int c;
5445796c8dcSSimon Schubert   bfd_byte *p;
5455796c8dcSSimon Schubert   bfd_byte *buf = NULL;
5465796c8dcSSimon Schubert   size_t bufsize;
5475796c8dcSSimon Schubert   bfd_boolean error;
5485796c8dcSSimon Schubert 
5495796c8dcSSimon Schubert   if (bfd_seek (abfd, section->filepos, SEEK_SET) != 0)
5505796c8dcSSimon Schubert     goto error_return;
5515796c8dcSSimon Schubert 
5525796c8dcSSimon Schubert   p = contents;
5535796c8dcSSimon Schubert   bufsize = 0;
5545796c8dcSSimon Schubert   error = FALSE;
5555796c8dcSSimon Schubert   while ((c = ihex_get_byte (abfd, &error)) != EOF)
5565796c8dcSSimon Schubert     {
5575796c8dcSSimon Schubert       char hdr[8];
5585796c8dcSSimon Schubert       unsigned int len;
5595796c8dcSSimon Schubert       unsigned int type;
5605796c8dcSSimon Schubert       unsigned int i;
5615796c8dcSSimon Schubert 
5625796c8dcSSimon Schubert       if (c == '\r' || c == '\n')
5635796c8dcSSimon Schubert 	continue;
5645796c8dcSSimon Schubert 
5655796c8dcSSimon Schubert       /* This is called after ihex_scan has succeeded, so we ought to
5665796c8dcSSimon Schubert          know the exact format.  */
5675796c8dcSSimon Schubert       BFD_ASSERT (c == ':');
5685796c8dcSSimon Schubert 
5695796c8dcSSimon Schubert       if (bfd_bread (hdr, (bfd_size_type) 8, abfd) != 8)
5705796c8dcSSimon Schubert 	goto error_return;
5715796c8dcSSimon Schubert 
5725796c8dcSSimon Schubert       len = HEX2 (hdr);
5735796c8dcSSimon Schubert       type = HEX2 (hdr + 6);
5745796c8dcSSimon Schubert 
5755796c8dcSSimon Schubert       /* We should only see type 0 records here.  */
5765796c8dcSSimon Schubert       if (type != 0)
5775796c8dcSSimon Schubert 	{
5785796c8dcSSimon Schubert 	  (*_bfd_error_handler)
5795796c8dcSSimon Schubert 	    (_("%B: internal error in ihex_read_section"), abfd);
5805796c8dcSSimon Schubert 	  bfd_set_error (bfd_error_bad_value);
5815796c8dcSSimon Schubert 	  goto error_return;
5825796c8dcSSimon Schubert 	}
5835796c8dcSSimon Schubert 
5845796c8dcSSimon Schubert       if (len * 2 > bufsize)
5855796c8dcSSimon Schubert 	{
5865796c8dcSSimon Schubert 	  buf = (bfd_byte *) bfd_realloc (buf, (bfd_size_type) len * 2);
5875796c8dcSSimon Schubert 	  if (buf == NULL)
5885796c8dcSSimon Schubert 	    goto error_return;
5895796c8dcSSimon Schubert 	  bufsize = len * 2;
5905796c8dcSSimon Schubert 	}
5915796c8dcSSimon Schubert 
5925796c8dcSSimon Schubert       if (bfd_bread (buf, (bfd_size_type) len * 2, abfd) != len * 2)
5935796c8dcSSimon Schubert 	goto error_return;
5945796c8dcSSimon Schubert 
5955796c8dcSSimon Schubert       for (i = 0; i < len; i++)
5965796c8dcSSimon Schubert 	*p++ = HEX2 (buf + 2 * i);
5975796c8dcSSimon Schubert       if ((bfd_size_type) (p - contents) >= section->size)
5985796c8dcSSimon Schubert 	{
5995796c8dcSSimon Schubert 	  /* We've read everything in the section.  */
6005796c8dcSSimon Schubert 	  if (buf != NULL)
6015796c8dcSSimon Schubert 	    free (buf);
6025796c8dcSSimon Schubert 	  return TRUE;
6035796c8dcSSimon Schubert 	}
6045796c8dcSSimon Schubert 
6055796c8dcSSimon Schubert       /* Skip the checksum.  */
6065796c8dcSSimon Schubert       if (bfd_bread (buf, (bfd_size_type) 2, abfd) != 2)
6075796c8dcSSimon Schubert 	goto error_return;
6085796c8dcSSimon Schubert     }
6095796c8dcSSimon Schubert 
6105796c8dcSSimon Schubert   if ((bfd_size_type) (p - contents) < section->size)
6115796c8dcSSimon Schubert     {
6125796c8dcSSimon Schubert       (*_bfd_error_handler)
6135796c8dcSSimon Schubert 	(_("%B: bad section length in ihex_read_section"), abfd);
6145796c8dcSSimon Schubert       bfd_set_error (bfd_error_bad_value);
6155796c8dcSSimon Schubert       goto error_return;
6165796c8dcSSimon Schubert     }
6175796c8dcSSimon Schubert 
6185796c8dcSSimon Schubert   if (buf != NULL)
6195796c8dcSSimon Schubert     free (buf);
6205796c8dcSSimon Schubert 
6215796c8dcSSimon Schubert   return TRUE;
6225796c8dcSSimon Schubert 
6235796c8dcSSimon Schubert  error_return:
6245796c8dcSSimon Schubert   if (buf != NULL)
6255796c8dcSSimon Schubert     free (buf);
6265796c8dcSSimon Schubert   return FALSE;
6275796c8dcSSimon Schubert }
6285796c8dcSSimon Schubert 
6295796c8dcSSimon Schubert /* Get the contents of a section in an Intel Hex file.  */
6305796c8dcSSimon Schubert 
6315796c8dcSSimon Schubert static bfd_boolean
ihex_get_section_contents(bfd * abfd,asection * section,void * location,file_ptr offset,bfd_size_type count)6325796c8dcSSimon Schubert ihex_get_section_contents (bfd *abfd,
6335796c8dcSSimon Schubert 			   asection *section,
6345796c8dcSSimon Schubert 			   void * location,
6355796c8dcSSimon Schubert 			   file_ptr offset,
6365796c8dcSSimon Schubert 			   bfd_size_type count)
6375796c8dcSSimon Schubert {
6385796c8dcSSimon Schubert   if (section->used_by_bfd == NULL)
6395796c8dcSSimon Schubert     {
6405796c8dcSSimon Schubert       section->used_by_bfd = bfd_alloc (abfd, section->size);
6415796c8dcSSimon Schubert       if (section->used_by_bfd == NULL)
6425796c8dcSSimon Schubert 	return FALSE;
6435796c8dcSSimon Schubert       if (! ihex_read_section (abfd, section,
6445796c8dcSSimon Schubert                                (bfd_byte *) section->used_by_bfd))
6455796c8dcSSimon Schubert 	return FALSE;
6465796c8dcSSimon Schubert     }
6475796c8dcSSimon Schubert 
6485796c8dcSSimon Schubert   memcpy (location, (bfd_byte *) section->used_by_bfd + offset,
6495796c8dcSSimon Schubert 	  (size_t) count);
6505796c8dcSSimon Schubert 
6515796c8dcSSimon Schubert   return TRUE;
6525796c8dcSSimon Schubert }
6535796c8dcSSimon Schubert 
6545796c8dcSSimon Schubert /* Set the contents of a section in an Intel Hex file.  */
6555796c8dcSSimon Schubert 
6565796c8dcSSimon Schubert static bfd_boolean
ihex_set_section_contents(bfd * abfd,asection * section,const void * location,file_ptr offset,bfd_size_type count)6575796c8dcSSimon Schubert ihex_set_section_contents (bfd *abfd,
6585796c8dcSSimon Schubert 			   asection *section,
6595796c8dcSSimon Schubert 			   const void * location,
6605796c8dcSSimon Schubert 			   file_ptr offset,
6615796c8dcSSimon Schubert 			   bfd_size_type count)
6625796c8dcSSimon Schubert {
6635796c8dcSSimon Schubert   struct ihex_data_list *n;
6645796c8dcSSimon Schubert   bfd_byte *data;
6655796c8dcSSimon Schubert   struct ihex_data_struct *tdata;
6665796c8dcSSimon Schubert 
6675796c8dcSSimon Schubert   if (count == 0
6685796c8dcSSimon Schubert       || (section->flags & SEC_ALLOC) == 0
6695796c8dcSSimon Schubert       || (section->flags & SEC_LOAD) == 0)
6705796c8dcSSimon Schubert     return TRUE;
6715796c8dcSSimon Schubert 
6725796c8dcSSimon Schubert   n = (struct ihex_data_list *) bfd_alloc (abfd, sizeof (* n));
6735796c8dcSSimon Schubert   if (n == NULL)
6745796c8dcSSimon Schubert     return FALSE;
6755796c8dcSSimon Schubert 
6765796c8dcSSimon Schubert   data = (bfd_byte *) bfd_alloc (abfd, count);
6775796c8dcSSimon Schubert   if (data == NULL)
6785796c8dcSSimon Schubert     return FALSE;
6795796c8dcSSimon Schubert   memcpy (data, location, (size_t) count);
6805796c8dcSSimon Schubert 
6815796c8dcSSimon Schubert   n->data = data;
6825796c8dcSSimon Schubert   n->where = section->lma + offset;
6835796c8dcSSimon Schubert   n->size = count;
6845796c8dcSSimon Schubert 
6855796c8dcSSimon Schubert   /* Sort the records by address.  Optimize for the common case of
6865796c8dcSSimon Schubert      adding a record to the end of the list.  */
6875796c8dcSSimon Schubert   tdata = abfd->tdata.ihex_data;
6885796c8dcSSimon Schubert   if (tdata->tail != NULL
6895796c8dcSSimon Schubert       && n->where >= tdata->tail->where)
6905796c8dcSSimon Schubert     {
6915796c8dcSSimon Schubert       tdata->tail->next = n;
6925796c8dcSSimon Schubert       n->next = NULL;
6935796c8dcSSimon Schubert       tdata->tail = n;
6945796c8dcSSimon Schubert     }
6955796c8dcSSimon Schubert   else
6965796c8dcSSimon Schubert     {
6975796c8dcSSimon Schubert       struct ihex_data_list **pp;
6985796c8dcSSimon Schubert 
6995796c8dcSSimon Schubert       for (pp = &tdata->head;
7005796c8dcSSimon Schubert 	   *pp != NULL && (*pp)->where < n->where;
7015796c8dcSSimon Schubert 	   pp = &(*pp)->next)
7025796c8dcSSimon Schubert 	;
7035796c8dcSSimon Schubert       n->next = *pp;
7045796c8dcSSimon Schubert       *pp = n;
7055796c8dcSSimon Schubert       if (n->next == NULL)
7065796c8dcSSimon Schubert 	tdata->tail = n;
7075796c8dcSSimon Schubert     }
7085796c8dcSSimon Schubert 
7095796c8dcSSimon Schubert   return TRUE;
7105796c8dcSSimon Schubert }
7115796c8dcSSimon Schubert 
7125796c8dcSSimon Schubert /* Write a record out to an Intel Hex file.  */
7135796c8dcSSimon Schubert 
7145796c8dcSSimon Schubert static bfd_boolean
ihex_write_record(bfd * abfd,size_t count,unsigned int addr,unsigned int type,bfd_byte * data)7155796c8dcSSimon Schubert ihex_write_record (bfd *abfd,
7165796c8dcSSimon Schubert 		   size_t count,
7175796c8dcSSimon Schubert 		   unsigned int addr,
7185796c8dcSSimon Schubert 		   unsigned int type,
7195796c8dcSSimon Schubert 		   bfd_byte *data)
7205796c8dcSSimon Schubert {
7215796c8dcSSimon Schubert   static const char digs[] = "0123456789ABCDEF";
7225796c8dcSSimon Schubert   char buf[9 + CHUNK * 2 + 4];
7235796c8dcSSimon Schubert   char *p;
7245796c8dcSSimon Schubert   unsigned int chksum;
7255796c8dcSSimon Schubert   unsigned int i;
7265796c8dcSSimon Schubert   size_t total;
7275796c8dcSSimon Schubert 
7285796c8dcSSimon Schubert #define TOHEX(buf, v) \
7295796c8dcSSimon Schubert   ((buf)[0] = digs[((v) >> 4) & 0xf], (buf)[1] = digs[(v) & 0xf])
7305796c8dcSSimon Schubert 
7315796c8dcSSimon Schubert   buf[0] = ':';
7325796c8dcSSimon Schubert   TOHEX (buf + 1, count);
7335796c8dcSSimon Schubert   TOHEX (buf + 3, (addr >> 8) & 0xff);
7345796c8dcSSimon Schubert   TOHEX (buf + 5, addr & 0xff);
7355796c8dcSSimon Schubert   TOHEX (buf + 7, type);
7365796c8dcSSimon Schubert 
7375796c8dcSSimon Schubert   chksum = count + addr + (addr >> 8) + type;
7385796c8dcSSimon Schubert 
7395796c8dcSSimon Schubert   for (i = 0, p = buf + 9; i < count; i++, p += 2, data++)
7405796c8dcSSimon Schubert     {
7415796c8dcSSimon Schubert       TOHEX (p, *data);
7425796c8dcSSimon Schubert       chksum += *data;
7435796c8dcSSimon Schubert     }
7445796c8dcSSimon Schubert 
7455796c8dcSSimon Schubert   TOHEX (p, (- chksum) & 0xff);
7465796c8dcSSimon Schubert   p[2] = '\r';
7475796c8dcSSimon Schubert   p[3] = '\n';
7485796c8dcSSimon Schubert 
7495796c8dcSSimon Schubert   total = 9 + count * 2 + 4;
7505796c8dcSSimon Schubert   if (bfd_bwrite (buf, (bfd_size_type) total, abfd) != total)
7515796c8dcSSimon Schubert     return FALSE;
7525796c8dcSSimon Schubert 
7535796c8dcSSimon Schubert   return TRUE;
7545796c8dcSSimon Schubert }
7555796c8dcSSimon Schubert 
7565796c8dcSSimon Schubert /* Write out an Intel Hex file.  */
7575796c8dcSSimon Schubert 
7585796c8dcSSimon Schubert static bfd_boolean
ihex_write_object_contents(bfd * abfd)7595796c8dcSSimon Schubert ihex_write_object_contents (bfd *abfd)
7605796c8dcSSimon Schubert {
7615796c8dcSSimon Schubert   bfd_vma segbase;
7625796c8dcSSimon Schubert   bfd_vma extbase;
7635796c8dcSSimon Schubert   struct ihex_data_list *l;
7645796c8dcSSimon Schubert 
7655796c8dcSSimon Schubert   segbase = 0;
7665796c8dcSSimon Schubert   extbase = 0;
7675796c8dcSSimon Schubert   for (l = abfd->tdata.ihex_data->head; l != NULL; l = l->next)
7685796c8dcSSimon Schubert     {
7695796c8dcSSimon Schubert       bfd_vma where;
7705796c8dcSSimon Schubert       bfd_byte *p;
7715796c8dcSSimon Schubert       bfd_size_type count;
7725796c8dcSSimon Schubert 
7735796c8dcSSimon Schubert       where = l->where;
7745796c8dcSSimon Schubert       p = l->data;
7755796c8dcSSimon Schubert       count = l->size;
7765796c8dcSSimon Schubert 
7775796c8dcSSimon Schubert       while (count > 0)
7785796c8dcSSimon Schubert 	{
7795796c8dcSSimon Schubert 	  size_t now;
7805796c8dcSSimon Schubert 	  unsigned int rec_addr;
7815796c8dcSSimon Schubert 
7825796c8dcSSimon Schubert 	  now = count;
7835796c8dcSSimon Schubert 	  if (count > CHUNK)
7845796c8dcSSimon Schubert 	    now = CHUNK;
7855796c8dcSSimon Schubert 
7865796c8dcSSimon Schubert 	  if (where > segbase + extbase + 0xffff)
7875796c8dcSSimon Schubert 	    {
7885796c8dcSSimon Schubert 	      bfd_byte addr[2];
7895796c8dcSSimon Schubert 
7905796c8dcSSimon Schubert 	      /* We need a new base address.  */
7915796c8dcSSimon Schubert 	      if (where <= 0xfffff)
7925796c8dcSSimon Schubert 		{
7935796c8dcSSimon Schubert 		  /* The addresses should be sorted.  */
7945796c8dcSSimon Schubert 		  BFD_ASSERT (extbase == 0);
7955796c8dcSSimon Schubert 
7965796c8dcSSimon Schubert 		  segbase = where & 0xf0000;
7975796c8dcSSimon Schubert 		  addr[0] = (bfd_byte)(segbase >> 12) & 0xff;
7985796c8dcSSimon Schubert 		  addr[1] = (bfd_byte)(segbase >> 4) & 0xff;
7995796c8dcSSimon Schubert 		  if (! ihex_write_record (abfd, 2, 0, 2, addr))
8005796c8dcSSimon Schubert 		    return FALSE;
8015796c8dcSSimon Schubert 		}
8025796c8dcSSimon Schubert 	      else
8035796c8dcSSimon Schubert 		{
8045796c8dcSSimon Schubert 		  /* The extended address record and the extended
8055796c8dcSSimon Schubert                      linear address record are combined, at least by
8065796c8dcSSimon Schubert                      some readers.  We need an extended linear address
8075796c8dcSSimon Schubert                      record here, so if we've already written out an
8085796c8dcSSimon Schubert                      extended address record, zero it out to avoid
8095796c8dcSSimon Schubert                      confusion.  */
8105796c8dcSSimon Schubert 		  if (segbase != 0)
8115796c8dcSSimon Schubert 		    {
8125796c8dcSSimon Schubert 		      addr[0] = 0;
8135796c8dcSSimon Schubert 		      addr[1] = 0;
8145796c8dcSSimon Schubert 		      if (! ihex_write_record (abfd, 2, 0, 2, addr))
8155796c8dcSSimon Schubert 			return FALSE;
8165796c8dcSSimon Schubert 		      segbase = 0;
8175796c8dcSSimon Schubert 		    }
8185796c8dcSSimon Schubert 
8195796c8dcSSimon Schubert 		  extbase = where & 0xffff0000;
8205796c8dcSSimon Schubert 		  if (where > extbase + 0xffff)
8215796c8dcSSimon Schubert 		    {
8225796c8dcSSimon Schubert 		      char buf[20];
8235796c8dcSSimon Schubert 
8245796c8dcSSimon Schubert 		      sprintf_vma (buf, where);
8255796c8dcSSimon Schubert 		      (*_bfd_error_handler)
8265796c8dcSSimon Schubert 			(_("%s: address 0x%s out of range for Intel Hex file"),
8275796c8dcSSimon Schubert 			 bfd_get_filename (abfd), buf);
8285796c8dcSSimon Schubert 		      bfd_set_error (bfd_error_bad_value);
8295796c8dcSSimon Schubert 		      return FALSE;
8305796c8dcSSimon Schubert 		    }
8315796c8dcSSimon Schubert 		  addr[0] = (bfd_byte)(extbase >> 24) & 0xff;
8325796c8dcSSimon Schubert 		  addr[1] = (bfd_byte)(extbase >> 16) & 0xff;
8335796c8dcSSimon Schubert 		  if (! ihex_write_record (abfd, 2, 0, 4, addr))
8345796c8dcSSimon Schubert 		    return FALSE;
8355796c8dcSSimon Schubert 		}
8365796c8dcSSimon Schubert 	    }
8375796c8dcSSimon Schubert 
8385796c8dcSSimon Schubert 	  rec_addr = where - (extbase + segbase);
8395796c8dcSSimon Schubert 
8405796c8dcSSimon Schubert           /* Output records shouldn't cross 64K boundaries.  */
8415796c8dcSSimon Schubert           if (rec_addr + now > 0xffff)
8425796c8dcSSimon Schubert             now = 0x10000 - rec_addr;
8435796c8dcSSimon Schubert 
8445796c8dcSSimon Schubert 	  if (! ihex_write_record (abfd, now, rec_addr, 0, p))
8455796c8dcSSimon Schubert 	    return FALSE;
8465796c8dcSSimon Schubert 
8475796c8dcSSimon Schubert 	  where += now;
8485796c8dcSSimon Schubert 	  p += now;
8495796c8dcSSimon Schubert 	  count -= now;
8505796c8dcSSimon Schubert 	}
8515796c8dcSSimon Schubert     }
8525796c8dcSSimon Schubert 
8535796c8dcSSimon Schubert   if (abfd->start_address != 0)
8545796c8dcSSimon Schubert     {
8555796c8dcSSimon Schubert       bfd_vma start;
8565796c8dcSSimon Schubert       bfd_byte startbuf[4];
8575796c8dcSSimon Schubert 
8585796c8dcSSimon Schubert       start = abfd->start_address;
8595796c8dcSSimon Schubert 
8605796c8dcSSimon Schubert       if (start <= 0xfffff)
8615796c8dcSSimon Schubert 	{
8625796c8dcSSimon Schubert 	  startbuf[0] = (bfd_byte)((start & 0xf0000) >> 12) & 0xff;
8635796c8dcSSimon Schubert 	  startbuf[1] = 0;
8645796c8dcSSimon Schubert 	  startbuf[2] = (bfd_byte)(start >> 8) & 0xff;
8655796c8dcSSimon Schubert 	  startbuf[3] = (bfd_byte)start & 0xff;
8665796c8dcSSimon Schubert 	  if (! ihex_write_record (abfd, 4, 0, 3, startbuf))
8675796c8dcSSimon Schubert 	    return FALSE;
8685796c8dcSSimon Schubert 	}
8695796c8dcSSimon Schubert       else
8705796c8dcSSimon Schubert 	{
8715796c8dcSSimon Schubert 	  startbuf[0] = (bfd_byte)(start >> 24) & 0xff;
8725796c8dcSSimon Schubert 	  startbuf[1] = (bfd_byte)(start >> 16) & 0xff;
8735796c8dcSSimon Schubert 	  startbuf[2] = (bfd_byte)(start >> 8) & 0xff;
8745796c8dcSSimon Schubert 	  startbuf[3] = (bfd_byte)start & 0xff;
8755796c8dcSSimon Schubert 	  if (! ihex_write_record (abfd, 4, 0, 5, startbuf))
8765796c8dcSSimon Schubert 	    return FALSE;
8775796c8dcSSimon Schubert 	}
8785796c8dcSSimon Schubert     }
8795796c8dcSSimon Schubert 
8805796c8dcSSimon Schubert   if (! ihex_write_record (abfd, 0, 0, 1, NULL))
8815796c8dcSSimon Schubert     return FALSE;
8825796c8dcSSimon Schubert 
8835796c8dcSSimon Schubert   return TRUE;
8845796c8dcSSimon Schubert }
8855796c8dcSSimon Schubert 
8865796c8dcSSimon Schubert /* Set the architecture for the output file.  The architecture is
8875796c8dcSSimon Schubert    irrelevant, so we ignore errors about unknown architectures.  */
8885796c8dcSSimon Schubert 
8895796c8dcSSimon Schubert static bfd_boolean
ihex_set_arch_mach(bfd * abfd,enum bfd_architecture arch,unsigned long mach)8905796c8dcSSimon Schubert ihex_set_arch_mach (bfd *abfd,
8915796c8dcSSimon Schubert 		    enum bfd_architecture arch,
8925796c8dcSSimon Schubert 		    unsigned long mach)
8935796c8dcSSimon Schubert {
8945796c8dcSSimon Schubert   if (! bfd_default_set_arch_mach (abfd, arch, mach))
8955796c8dcSSimon Schubert     {
8965796c8dcSSimon Schubert       if (arch != bfd_arch_unknown)
8975796c8dcSSimon Schubert 	return FALSE;
8985796c8dcSSimon Schubert     }
8995796c8dcSSimon Schubert   return TRUE;
9005796c8dcSSimon Schubert }
9015796c8dcSSimon Schubert 
9025796c8dcSSimon Schubert /* Get the size of the headers, for the linker.  */
9035796c8dcSSimon Schubert 
9045796c8dcSSimon Schubert static int
ihex_sizeof_headers(bfd * abfd ATTRIBUTE_UNUSED,struct bfd_link_info * info ATTRIBUTE_UNUSED)9055796c8dcSSimon Schubert ihex_sizeof_headers (bfd *abfd ATTRIBUTE_UNUSED,
9065796c8dcSSimon Schubert 		     struct bfd_link_info *info ATTRIBUTE_UNUSED)
9075796c8dcSSimon Schubert {
9085796c8dcSSimon Schubert   return 0;
9095796c8dcSSimon Schubert }
9105796c8dcSSimon Schubert 
9115796c8dcSSimon Schubert /* Some random definitions for the target vector.  */
9125796c8dcSSimon Schubert 
9135796c8dcSSimon Schubert #define	ihex_close_and_cleanup                    _bfd_generic_close_and_cleanup
9145796c8dcSSimon Schubert #define ihex_bfd_free_cached_info                 _bfd_generic_bfd_free_cached_info
9155796c8dcSSimon Schubert #define ihex_new_section_hook                     _bfd_generic_new_section_hook
9165796c8dcSSimon Schubert #define ihex_get_section_contents_in_window       _bfd_generic_get_section_contents_in_window
9175796c8dcSSimon Schubert #define ihex_get_symtab_upper_bound               bfd_0l
9185796c8dcSSimon Schubert #define ihex_canonicalize_symtab                  ((long (*) (bfd *, asymbol **)) bfd_0l)
9195796c8dcSSimon Schubert #define ihex_make_empty_symbol                    _bfd_generic_make_empty_symbol
9205796c8dcSSimon Schubert #define ihex_print_symbol                         _bfd_nosymbols_print_symbol
9215796c8dcSSimon Schubert #define ihex_get_symbol_info                      _bfd_nosymbols_get_symbol_info
9225796c8dcSSimon Schubert #define ihex_bfd_is_target_special_symbol         ((bfd_boolean (*) (bfd *, asymbol *)) bfd_false)
9235796c8dcSSimon Schubert #define ihex_bfd_is_local_label_name              _bfd_nosymbols_bfd_is_local_label_name
9245796c8dcSSimon Schubert #define ihex_get_lineno                           _bfd_nosymbols_get_lineno
9255796c8dcSSimon Schubert #define ihex_find_nearest_line                    _bfd_nosymbols_find_nearest_line
9265796c8dcSSimon Schubert #define ihex_find_inliner_info                    _bfd_nosymbols_find_inliner_info
9275796c8dcSSimon Schubert #define ihex_bfd_make_debug_symbol                _bfd_nosymbols_bfd_make_debug_symbol
9285796c8dcSSimon Schubert #define ihex_read_minisymbols                     _bfd_nosymbols_read_minisymbols
9295796c8dcSSimon Schubert #define ihex_minisymbol_to_symbol                 _bfd_nosymbols_minisymbol_to_symbol
9305796c8dcSSimon Schubert #define ihex_bfd_get_relocated_section_contents   bfd_generic_get_relocated_section_contents
9315796c8dcSSimon Schubert #define ihex_bfd_relax_section                    bfd_generic_relax_section
9325796c8dcSSimon Schubert #define ihex_bfd_gc_sections                      bfd_generic_gc_sections
933*a45ae5f8SJohn Marino #define ihex_bfd_lookup_section_flags             bfd_generic_lookup_section_flags
9345796c8dcSSimon Schubert #define ihex_bfd_merge_sections                   bfd_generic_merge_sections
9355796c8dcSSimon Schubert #define ihex_bfd_is_group_section                 bfd_generic_is_group_section
9365796c8dcSSimon Schubert #define ihex_bfd_discard_group                    bfd_generic_discard_group
9375796c8dcSSimon Schubert #define ihex_section_already_linked               _bfd_generic_section_already_linked
9385796c8dcSSimon Schubert #define ihex_bfd_define_common_symbol             bfd_generic_define_common_symbol
9395796c8dcSSimon Schubert #define ihex_bfd_link_hash_table_create           _bfd_generic_link_hash_table_create
9405796c8dcSSimon Schubert #define ihex_bfd_link_hash_table_free             _bfd_generic_link_hash_table_free
9415796c8dcSSimon Schubert #define ihex_bfd_link_add_symbols                 _bfd_generic_link_add_symbols
9425796c8dcSSimon Schubert #define ihex_bfd_link_just_syms                   _bfd_generic_link_just_syms
943cf7f2e2dSJohn Marino #define ihex_bfd_copy_link_hash_symbol_type \
944cf7f2e2dSJohn Marino   _bfd_generic_copy_link_hash_symbol_type
9455796c8dcSSimon Schubert #define ihex_bfd_final_link                       _bfd_generic_final_link
9465796c8dcSSimon Schubert #define ihex_bfd_link_split_section               _bfd_generic_link_split_section
9475796c8dcSSimon Schubert 
9485796c8dcSSimon Schubert /* The Intel Hex target vector.  */
9495796c8dcSSimon Schubert 
9505796c8dcSSimon Schubert const bfd_target ihex_vec =
9515796c8dcSSimon Schubert {
9525796c8dcSSimon Schubert   "ihex",			/* Name.  */
9535796c8dcSSimon Schubert   bfd_target_ihex_flavour,
9545796c8dcSSimon Schubert   BFD_ENDIAN_UNKNOWN,		/* Target byte order.  */
9555796c8dcSSimon Schubert   BFD_ENDIAN_UNKNOWN,		/* Target headers byte order.  */
9565796c8dcSSimon Schubert   0,				/* Object flags.  */
9575796c8dcSSimon Schubert   (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD),	/* Section flags.  */
9585796c8dcSSimon Schubert   0,				/* Leading underscore.  */
9595796c8dcSSimon Schubert   ' ',				/* AR_pad_char.  */
9605796c8dcSSimon Schubert   16,				/* AR_max_namelen.  */
961*a45ae5f8SJohn Marino   0,				/* match priority.  */
9625796c8dcSSimon Schubert   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
9635796c8dcSSimon Schubert   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
9645796c8dcSSimon Schubert   bfd_getb16, bfd_getb_signed_16, bfd_putb16,	/* Data.  */
9655796c8dcSSimon Schubert   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
9665796c8dcSSimon Schubert   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
9675796c8dcSSimon Schubert   bfd_getb16, bfd_getb_signed_16, bfd_putb16,	/* Headers. */
9685796c8dcSSimon Schubert 
9695796c8dcSSimon Schubert   {
9705796c8dcSSimon Schubert     _bfd_dummy_target,
9715796c8dcSSimon Schubert     ihex_object_p,		/* bfd_check_format.  */
9725796c8dcSSimon Schubert     _bfd_dummy_target,
9735796c8dcSSimon Schubert     _bfd_dummy_target,
9745796c8dcSSimon Schubert   },
9755796c8dcSSimon Schubert   {
9765796c8dcSSimon Schubert     bfd_false,
9775796c8dcSSimon Schubert     ihex_mkobject,
9785796c8dcSSimon Schubert     _bfd_generic_mkarchive,
9795796c8dcSSimon Schubert     bfd_false,
9805796c8dcSSimon Schubert   },
9815796c8dcSSimon Schubert   {				/* bfd_write_contents.  */
9825796c8dcSSimon Schubert     bfd_false,
9835796c8dcSSimon Schubert     ihex_write_object_contents,
9845796c8dcSSimon Schubert     _bfd_write_archive_contents,
9855796c8dcSSimon Schubert     bfd_false,
9865796c8dcSSimon Schubert   },
9875796c8dcSSimon Schubert 
9885796c8dcSSimon Schubert   BFD_JUMP_TABLE_GENERIC (ihex),
9895796c8dcSSimon Schubert   BFD_JUMP_TABLE_COPY (_bfd_generic),
9905796c8dcSSimon Schubert   BFD_JUMP_TABLE_CORE (_bfd_nocore),
9915796c8dcSSimon Schubert   BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
9925796c8dcSSimon Schubert   BFD_JUMP_TABLE_SYMBOLS (ihex),
9935796c8dcSSimon Schubert   BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
9945796c8dcSSimon Schubert   BFD_JUMP_TABLE_WRITE (ihex),
9955796c8dcSSimon Schubert   BFD_JUMP_TABLE_LINK (ihex),
9965796c8dcSSimon Schubert   BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
9975796c8dcSSimon Schubert 
9985796c8dcSSimon Schubert   NULL,
9995796c8dcSSimon Schubert 
10005796c8dcSSimon Schubert   NULL
10015796c8dcSSimon Schubert };
1002