xref: /openbsd-src/gnu/usr.bin/binutils/bfd/ihex.c (revision 007c2a4539b8b8aaa95c5e73e77620090abe113b)
1c88b1d6cSniklas /* BFD back-end for Intel Hex objects.
2*007c2a45Smiod    Copyright 1995, 1996, 1998, 1999, 2000, 2001, 2002, 2003
3c074d1c9Sdrahn    Free Software Foundation, Inc.
4c88b1d6cSniklas    Written by Ian Lance Taylor of Cygnus Support <ian@cygnus.com>.
5c88b1d6cSniklas 
6c88b1d6cSniklas    This file is part of BFD, the Binary File Descriptor library.
7c88b1d6cSniklas 
8c88b1d6cSniklas    This program is free software; you can redistribute it and/or modify
9c88b1d6cSniklas    it under the terms of the GNU General Public License as published by
10c88b1d6cSniklas    the Free Software Foundation; either version 2 of the License, or
11c88b1d6cSniklas    (at your option) any later version.
12c88b1d6cSniklas 
13c88b1d6cSniklas    This program is distributed in the hope that it will be useful,
14c88b1d6cSniklas    but WITHOUT ANY WARRANTY; without even the implied warranty of
15c88b1d6cSniklas    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16c88b1d6cSniklas    GNU General Public License for more details.
17c88b1d6cSniklas 
18c88b1d6cSniklas    You should have received a copy of the GNU General Public License
19c88b1d6cSniklas    along with this program; if not, write to the Free Software
20c88b1d6cSniklas    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
21c88b1d6cSniklas 
22c88b1d6cSniklas /* This is what Intel Hex files look like:
23c88b1d6cSniklas 
24c88b1d6cSniklas 1. INTEL FORMATS
25c88b1d6cSniklas 
26c88b1d6cSniklas A. Intel 1
27c88b1d6cSniklas 
28c88b1d6cSniklas    16-bit address-field format, for files 64k bytes in length or less.
29c88b1d6cSniklas 
30c88b1d6cSniklas    DATA RECORD
31c88b1d6cSniklas    Byte 1	Header = colon(:)
32c88b1d6cSniklas    2..3		The number of data bytes in hex notation
33c88b1d6cSniklas    4..5		High byte of the record load address
34c88b1d6cSniklas    6..7		Low byte of the record load address
35c88b1d6cSniklas    8..9		Record type, must be "00"
36c88b1d6cSniklas    10..x	Data bytes in hex notation:
37c88b1d6cSniklas 	x = (number of bytes - 1) * 2 + 11
38c88b1d6cSniklas    x+1..x+2	Checksum in hex notation
39c88b1d6cSniklas    x+3..x+4	Carriage return, line feed
40c88b1d6cSniklas 
41c88b1d6cSniklas    END RECORD
42c88b1d6cSniklas    Byte 1	Header = colon (:)
43c88b1d6cSniklas    2..3		The byte count, must be "00"
44c88b1d6cSniklas    4..7		Transfer-address (usually "0000")
45c88b1d6cSniklas 		the jump-to address, execution start address
46c88b1d6cSniklas    8..9		Record type, must be "01"
47c88b1d6cSniklas    10..11	Checksum, in hex notation
48c88b1d6cSniklas    12..13	Carriage return, line feed
49c88b1d6cSniklas 
50c88b1d6cSniklas B. INTEL 2
51c88b1d6cSniklas 
52c88b1d6cSniklas    MCS-86 format, using a 20-bit address for files larger than 64K bytes.
53c88b1d6cSniklas 
54c88b1d6cSniklas    DATA RECORD
55c88b1d6cSniklas    Byte 1	Header = colon (:)
56c88b1d6cSniklas    2..3		The byte count of this record, hex notation
57c88b1d6cSniklas    4..5		High byte of the record load address
58c88b1d6cSniklas    6..7		Low byte of the record load address
59c88b1d6cSniklas    8..9		Record type, must be "00"
60c88b1d6cSniklas    10..x	The data bytes in hex notation:
61c88b1d6cSniklas 	x = (number of data bytes - 1) * 2 + 11
62c88b1d6cSniklas    x+1..x+2	Checksum in hex notation
63c88b1d6cSniklas    x+3..x+4	Carriage return, line feed
64c88b1d6cSniklas 
65c88b1d6cSniklas    EXTENDED ADDRESS RECORD
66c88b1d6cSniklas    Byte 1	Header = colon(:)
67c88b1d6cSniklas    2..3		The byte count, must be "02"
68c88b1d6cSniklas    4..7		Load address, must be "0000"
69c88b1d6cSniklas    8..9		Record type, must be "02"
70c88b1d6cSniklas    10..11	High byte of the offset address
71c88b1d6cSniklas    12..13	Low byte of the offset address
72c88b1d6cSniklas    14..15	Checksum in hex notation
73c88b1d6cSniklas    16..17	Carriage return, line feed
74c88b1d6cSniklas 
75c88b1d6cSniklas    The checksums are the two's complement of the 8-bit sum
76c88b1d6cSniklas    without carry of the byte count, offset address, and the
77c88b1d6cSniklas    record type.
78c88b1d6cSniklas 
79c88b1d6cSniklas    START ADDRESS RECORD
80c88b1d6cSniklas    Byte 1	Header = colon (:)
81c88b1d6cSniklas    2..3		The byte count, must be "04"
82c88b1d6cSniklas    4..7		Load address, must be "0000"
83c88b1d6cSniklas    8..9		Record type, must be "03"
84c88b1d6cSniklas    10..13	8086 CS value
85c88b1d6cSniklas    14..17	8086 IP value
86c88b1d6cSniklas    18..19	Checksum in hex notation
87c88b1d6cSniklas    20..21	Carriage return, line feed
88c88b1d6cSniklas 
89c88b1d6cSniklas Another document reports these additional types:
90c88b1d6cSniklas 
91c88b1d6cSniklas    EXTENDED LINEAR ADDRESS RECORD
92c88b1d6cSniklas    Byte 1	Header = colon (:)
93c88b1d6cSniklas    2..3		The byte count, must be "02"
94c88b1d6cSniklas    4..7		Load address, must be "0000"
95c88b1d6cSniklas    8..9		Record type, must be "04"
96c88b1d6cSniklas    10..13	Upper 16 bits of address of subsequent records
97c88b1d6cSniklas    14..15	Checksum in hex notation
98c88b1d6cSniklas    16..17	Carriage return, line feed
99c88b1d6cSniklas 
100c88b1d6cSniklas    START LINEAR ADDRESS RECORD
101c88b1d6cSniklas    Byte 1	Header = colon (:)
102c88b1d6cSniklas    2..3		The byte count, must be "02"
103c88b1d6cSniklas    4..7		Load address, must be "0000"
104c88b1d6cSniklas    8..9		Record type, must be "05"
105c88b1d6cSniklas    10..13	Upper 16 bits of start address
106c88b1d6cSniklas    14..15	Checksum in hex notation
107c88b1d6cSniklas    16..17	Carriage return, line feed
108c88b1d6cSniklas 
109c88b1d6cSniklas The MRI compiler uses this, which is a repeat of type 5:
110c88b1d6cSniklas 
111c88b1d6cSniklas   EXTENDED START RECORD
112c88b1d6cSniklas    Byte 1	Header = colon (:)
113c88b1d6cSniklas    2..3		The byte count, must be "04"
114c88b1d6cSniklas    4..7		Load address, must be "0000"
115c88b1d6cSniklas    8..9		Record type, must be "05"
116c88b1d6cSniklas    10..13	Upper 16 bits of start address
117c88b1d6cSniklas    14..17	Lower 16 bits of start address
118c88b1d6cSniklas    18..19	Checksum in hex notation
119c88b1d6cSniklas    20..21	Carriage return, line feed
120c88b1d6cSniklas */
121c88b1d6cSniklas 
122c88b1d6cSniklas #include "bfd.h"
123c88b1d6cSniklas #include "sysdep.h"
124c88b1d6cSniklas #include "libbfd.h"
125c88b1d6cSniklas #include "libiberty.h"
126c074d1c9Sdrahn #include "safe-ctype.h"
127c88b1d6cSniklas 
128c074d1c9Sdrahn static void ihex_init
129c074d1c9Sdrahn   PARAMS ((void));
130c074d1c9Sdrahn static bfd_boolean ihex_mkobject
131c074d1c9Sdrahn   PARAMS ((bfd *));
132c074d1c9Sdrahn static INLINE int ihex_get_byte
133c074d1c9Sdrahn   PARAMS ((bfd *, bfd_boolean *));
134c074d1c9Sdrahn static void ihex_bad_byte
135c074d1c9Sdrahn   PARAMS ((bfd *, unsigned int, int, bfd_boolean));
136c074d1c9Sdrahn static bfd_boolean ihex_scan
137c074d1c9Sdrahn   PARAMS ((bfd *));
138c074d1c9Sdrahn static const bfd_target *ihex_object_p
139c074d1c9Sdrahn   PARAMS ((bfd *));
140c074d1c9Sdrahn static bfd_boolean ihex_read_section
141c074d1c9Sdrahn   PARAMS ((bfd *, asection *, bfd_byte *));
142c074d1c9Sdrahn static bfd_boolean ihex_get_section_contents
143c88b1d6cSniklas   PARAMS ((bfd *, asection *, PTR, file_ptr, bfd_size_type));
144c074d1c9Sdrahn static bfd_boolean ihex_set_section_contents
145*007c2a45Smiod   PARAMS ((bfd *, asection *, const PTR, file_ptr, bfd_size_type));
146c074d1c9Sdrahn static bfd_boolean ihex_write_record
147c074d1c9Sdrahn   PARAMS ((bfd *, size_t, unsigned int, unsigned int, bfd_byte *));
148c074d1c9Sdrahn static bfd_boolean ihex_write_object_contents
149c074d1c9Sdrahn   PARAMS ((bfd *));
150c074d1c9Sdrahn static bfd_boolean ihex_set_arch_mach
151c88b1d6cSniklas   PARAMS ((bfd *, enum bfd_architecture, unsigned long));
152c074d1c9Sdrahn static int ihex_sizeof_headers
153c074d1c9Sdrahn   PARAMS ((bfd *, bfd_boolean));
154c88b1d6cSniklas 
155c88b1d6cSniklas /* The number of bytes we put on one line during output.  */
156c88b1d6cSniklas 
157b305b0f1Sespie #define CHUNK 16
158c88b1d6cSniklas 
159c88b1d6cSniklas /* Macros for converting between hex and binary.  */
160c88b1d6cSniklas 
161c88b1d6cSniklas #define NIBBLE(x)    (hex_value (x))
162c88b1d6cSniklas #define HEX2(buffer) ((NIBBLE ((buffer)[0]) << 4) + NIBBLE ((buffer)[1]))
163c88b1d6cSniklas #define HEX4(buffer) ((HEX2 (buffer) << 8) + HEX2 ((buffer) + 2))
164c88b1d6cSniklas #define ISHEX(x)     (hex_p (x))
165c88b1d6cSniklas 
166c88b1d6cSniklas /* When we write out an ihex value, the values can not be output as
167c88b1d6cSniklas    they are seen.  Instead, we hold them in memory in this structure.  */
168c88b1d6cSniklas 
169c88b1d6cSniklas struct ihex_data_list
170c88b1d6cSniklas {
171c88b1d6cSniklas   struct ihex_data_list *next;
172c88b1d6cSniklas   bfd_byte *data;
173c88b1d6cSniklas   bfd_vma where;
174c88b1d6cSniklas   bfd_size_type size;
175c88b1d6cSniklas };
176c88b1d6cSniklas 
177c88b1d6cSniklas /* The ihex tdata information.  */
178c88b1d6cSniklas 
179c88b1d6cSniklas struct ihex_data_struct
180c88b1d6cSniklas {
181c88b1d6cSniklas   struct ihex_data_list *head;
182c88b1d6cSniklas   struct ihex_data_list *tail;
183c88b1d6cSniklas };
184c88b1d6cSniklas 
185c88b1d6cSniklas /* Initialize by filling in the hex conversion array.  */
186c88b1d6cSniklas 
187c88b1d6cSniklas static void
ihex_init()188c88b1d6cSniklas ihex_init ()
189c88b1d6cSniklas {
190c074d1c9Sdrahn   static bfd_boolean inited;
191c88b1d6cSniklas 
192c88b1d6cSniklas   if (! inited)
193c88b1d6cSniklas     {
194c074d1c9Sdrahn       inited = TRUE;
195c88b1d6cSniklas       hex_init ();
196c88b1d6cSniklas     }
197c88b1d6cSniklas }
198c88b1d6cSniklas 
199c88b1d6cSniklas /* Create an ihex object.  */
200c88b1d6cSniklas 
201c074d1c9Sdrahn static bfd_boolean
ihex_mkobject(abfd)202c88b1d6cSniklas ihex_mkobject (abfd)
203c88b1d6cSniklas      bfd *abfd;
204c88b1d6cSniklas {
205c88b1d6cSniklas   struct ihex_data_struct *tdata;
206c074d1c9Sdrahn   bfd_size_type amt = sizeof (struct ihex_data_struct);
207c88b1d6cSniklas 
208c074d1c9Sdrahn   tdata = (struct ihex_data_struct *) bfd_alloc (abfd, amt);
209c88b1d6cSniklas   if (tdata == NULL)
210c074d1c9Sdrahn     return FALSE;
211c074d1c9Sdrahn 
212c88b1d6cSniklas   abfd->tdata.ihex_data = tdata;
213c88b1d6cSniklas   tdata->head = NULL;
214c88b1d6cSniklas   tdata->tail = NULL;
215c074d1c9Sdrahn   return TRUE;
216c88b1d6cSniklas }
217c88b1d6cSniklas 
218c88b1d6cSniklas /* Read a byte from a BFD.  Set *ERRORPTR if an error occurred.
219c88b1d6cSniklas    Return EOF on error or end of file.  */
220c88b1d6cSniklas 
221c88b1d6cSniklas static INLINE int
ihex_get_byte(abfd,errorptr)222c88b1d6cSniklas ihex_get_byte (abfd, errorptr)
223c88b1d6cSniklas      bfd *abfd;
224c074d1c9Sdrahn      bfd_boolean *errorptr;
225c88b1d6cSniklas {
226c88b1d6cSniklas   bfd_byte c;
227c88b1d6cSniklas 
228c074d1c9Sdrahn   if (bfd_bread (&c, (bfd_size_type) 1, abfd) != 1)
229c88b1d6cSniklas     {
230c88b1d6cSniklas       if (bfd_get_error () != bfd_error_file_truncated)
231c074d1c9Sdrahn 	*errorptr = TRUE;
232c88b1d6cSniklas       return EOF;
233c88b1d6cSniklas     }
234c88b1d6cSniklas 
235c88b1d6cSniklas   return (int) (c & 0xff);
236c88b1d6cSniklas }
237c88b1d6cSniklas 
238c88b1d6cSniklas /* Report a problem in an Intel Hex file.  */
239c88b1d6cSniklas 
240c88b1d6cSniklas static void
ihex_bad_byte(abfd,lineno,c,error)241c88b1d6cSniklas ihex_bad_byte (abfd, lineno, c, error)
242c88b1d6cSniklas      bfd *abfd;
243c88b1d6cSniklas      unsigned int lineno;
244c88b1d6cSniklas      int c;
245c074d1c9Sdrahn      bfd_boolean error;
246c88b1d6cSniklas {
247c88b1d6cSniklas   if (c == EOF)
248c88b1d6cSniklas     {
249c88b1d6cSniklas       if (! error)
250c88b1d6cSniklas 	bfd_set_error (bfd_error_file_truncated);
251c88b1d6cSniklas     }
252c88b1d6cSniklas   else
253c88b1d6cSniklas     {
254c88b1d6cSniklas       char buf[10];
255c88b1d6cSniklas 
256c074d1c9Sdrahn       if (! ISPRINT (c))
257c88b1d6cSniklas 	sprintf (buf, "\\%03o", (unsigned int) c);
258c88b1d6cSniklas       else
259c88b1d6cSniklas 	{
260c88b1d6cSniklas 	  buf[0] = c;
261c88b1d6cSniklas 	  buf[1] = '\0';
262c88b1d6cSniklas 	}
263c88b1d6cSniklas       (*_bfd_error_handler)
264b305b0f1Sespie 	(_("%s:%d: unexpected character `%s' in Intel Hex file\n"),
265c074d1c9Sdrahn 	 bfd_archive_filename (abfd), lineno, buf);
266c88b1d6cSniklas       bfd_set_error (bfd_error_bad_value);
267c88b1d6cSniklas     }
268c88b1d6cSniklas }
269c88b1d6cSniklas 
270c88b1d6cSniklas /* Read an Intel hex file and turn it into sections.  We create a new
271c88b1d6cSniklas    section for each contiguous set of bytes.  */
272c88b1d6cSniklas 
273c074d1c9Sdrahn static bfd_boolean
ihex_scan(abfd)274c88b1d6cSniklas ihex_scan (abfd)
275c88b1d6cSniklas      bfd *abfd;
276c88b1d6cSniklas {
277c88b1d6cSniklas   bfd_vma segbase;
278b305b0f1Sespie   bfd_vma extbase;
279c88b1d6cSniklas   asection *sec;
280c074d1c9Sdrahn   unsigned int lineno;
281c074d1c9Sdrahn   bfd_boolean error;
282b305b0f1Sespie   bfd_byte *buf = NULL;
283c88b1d6cSniklas   size_t bufsize;
284c88b1d6cSniklas   int c;
285c88b1d6cSniklas 
286c88b1d6cSniklas   if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
287c88b1d6cSniklas     goto error_return;
288c88b1d6cSniklas 
289c88b1d6cSniklas   abfd->start_address = 0;
290c88b1d6cSniklas 
291c88b1d6cSniklas   segbase = 0;
292b305b0f1Sespie   extbase = 0;
293c88b1d6cSniklas   sec = NULL;
294c88b1d6cSniklas   lineno = 1;
295c074d1c9Sdrahn   error = FALSE;
296c88b1d6cSniklas   bufsize = 0;
297c074d1c9Sdrahn 
298c88b1d6cSniklas   while ((c = ihex_get_byte (abfd, &error)) != EOF)
299c88b1d6cSniklas     {
300c88b1d6cSniklas       if (c == '\r')
301c88b1d6cSniklas 	continue;
302c88b1d6cSniklas       else if (c == '\n')
303c88b1d6cSniklas 	{
304c88b1d6cSniklas 	  ++lineno;
305c88b1d6cSniklas 	  continue;
306c88b1d6cSniklas 	}
307c88b1d6cSniklas       else if (c != ':')
308c88b1d6cSniklas 	{
309c88b1d6cSniklas 	  ihex_bad_byte (abfd, lineno, c, error);
310c88b1d6cSniklas 	  goto error_return;
311c88b1d6cSniklas 	}
312c88b1d6cSniklas       else
313c88b1d6cSniklas 	{
314c88b1d6cSniklas 	  file_ptr pos;
315c88b1d6cSniklas 	  char hdr[8];
316c88b1d6cSniklas 	  unsigned int i;
317c88b1d6cSniklas 	  unsigned int len;
318c88b1d6cSniklas 	  bfd_vma addr;
319c88b1d6cSniklas 	  unsigned int type;
320c88b1d6cSniklas 	  unsigned int chars;
321c88b1d6cSniklas 	  unsigned int chksum;
322c88b1d6cSniklas 
323c88b1d6cSniklas 	  /* This is a data record.  */
324c88b1d6cSniklas 	  pos = bfd_tell (abfd) - 1;
325c88b1d6cSniklas 
326c88b1d6cSniklas 	  /* Read the header bytes.  */
327c074d1c9Sdrahn 	  if (bfd_bread (hdr, (bfd_size_type) 8, abfd) != 8)
328c88b1d6cSniklas 	    goto error_return;
329c88b1d6cSniklas 
330c88b1d6cSniklas 	  for (i = 0; i < 8; i++)
331c88b1d6cSniklas 	    {
332c88b1d6cSniklas 	      if (! ISHEX (hdr[i]))
333c88b1d6cSniklas 		{
334c88b1d6cSniklas 		  ihex_bad_byte (abfd, lineno, hdr[i], error);
335c88b1d6cSniklas 		  goto error_return;
336c88b1d6cSniklas 		}
337c88b1d6cSniklas 	    }
338c88b1d6cSniklas 
339c88b1d6cSniklas 	  len = HEX2 (hdr);
340c88b1d6cSniklas 	  addr = HEX4 (hdr + 2);
341c88b1d6cSniklas 	  type = HEX2 (hdr + 6);
342c88b1d6cSniklas 
343c88b1d6cSniklas 	  /* Read the data bytes.  */
344c88b1d6cSniklas 	  chars = len * 2 + 2;
345c88b1d6cSniklas 	  if (chars >= bufsize)
346c88b1d6cSniklas 	    {
347c074d1c9Sdrahn 	      buf = (bfd_byte *) bfd_realloc (buf, (bfd_size_type) chars);
348c88b1d6cSniklas 	      if (buf == NULL)
349c88b1d6cSniklas 		goto error_return;
350c88b1d6cSniklas 	      bufsize = chars;
351c88b1d6cSniklas 	    }
352c88b1d6cSniklas 
353c074d1c9Sdrahn 	  if (bfd_bread (buf, (bfd_size_type) chars, abfd) != chars)
354c88b1d6cSniklas 	    goto error_return;
355c88b1d6cSniklas 
356c88b1d6cSniklas 	  for (i = 0; i < chars; i++)
357c88b1d6cSniklas 	    {
358c88b1d6cSniklas 	      if (! ISHEX (buf[i]))
359c88b1d6cSniklas 		{
360c88b1d6cSniklas 		  ihex_bad_byte (abfd, lineno, hdr[i], error);
361c88b1d6cSniklas 		  goto error_return;
362c88b1d6cSniklas 		}
363c88b1d6cSniklas 	    }
364c88b1d6cSniklas 
365c88b1d6cSniklas 	  /* Check the checksum.  */
366c88b1d6cSniklas 	  chksum = len + addr + (addr >> 8) + type;
367c88b1d6cSniklas 	  for (i = 0; i < len; i++)
368c88b1d6cSniklas 	    chksum += HEX2 (buf + 2 * i);
369c88b1d6cSniklas 	  if (((- chksum) & 0xff) != (unsigned int) HEX2 (buf + 2 * i))
370c88b1d6cSniklas 	    {
371c88b1d6cSniklas 	      (*_bfd_error_handler)
372c074d1c9Sdrahn 		(_("%s:%u: bad checksum in Intel Hex file (expected %u, found %u)"),
373c074d1c9Sdrahn 		 bfd_archive_filename (abfd), lineno,
374c88b1d6cSniklas 		 (- chksum) & 0xff, (unsigned int) HEX2 (buf + 2 * i));
375c88b1d6cSniklas 	      bfd_set_error (bfd_error_bad_value);
376c88b1d6cSniklas 	      goto error_return;
377c88b1d6cSniklas 	    }
378c88b1d6cSniklas 
379c88b1d6cSniklas 	  switch (type)
380c88b1d6cSniklas 	    {
381c88b1d6cSniklas 	    case 0:
382c88b1d6cSniklas 	      /* This is a data record.  */
383c88b1d6cSniklas 	      if (sec != NULL
384b305b0f1Sespie 		  && sec->vma + sec->_raw_size == extbase + segbase + addr)
385c88b1d6cSniklas 		{
386c88b1d6cSniklas 		  /* This data goes at the end of the section we are
387c88b1d6cSniklas                      currently building.  */
388c88b1d6cSniklas 		  sec->_raw_size += len;
389c88b1d6cSniklas 		}
390c88b1d6cSniklas 	      else if (len > 0)
391c88b1d6cSniklas 		{
392c88b1d6cSniklas 		  char secbuf[20];
393c88b1d6cSniklas 		  char *secname;
394c074d1c9Sdrahn 		  bfd_size_type amt;
395c88b1d6cSniklas 
396c88b1d6cSniklas 		  sprintf (secbuf, ".sec%d", bfd_count_sections (abfd) + 1);
397c074d1c9Sdrahn 		  amt = strlen (secbuf) + 1;
398c074d1c9Sdrahn 		  secname = (char *) bfd_alloc (abfd, amt);
399c88b1d6cSniklas 		  if (secname == NULL)
400c88b1d6cSniklas 		    goto error_return;
401c88b1d6cSniklas 		  strcpy (secname, secbuf);
402c88b1d6cSniklas 		  sec = bfd_make_section (abfd, secname);
403c88b1d6cSniklas 		  if (sec == NULL)
404c88b1d6cSniklas 		    goto error_return;
405c88b1d6cSniklas 		  sec->flags = SEC_HAS_CONTENTS | SEC_LOAD | SEC_ALLOC;
406b305b0f1Sespie 		  sec->vma = extbase + segbase + addr;
407b305b0f1Sespie 		  sec->lma = extbase + segbase + addr;
408c88b1d6cSniklas 		  sec->_raw_size = len;
409c88b1d6cSniklas 		  sec->filepos = pos;
410c88b1d6cSniklas 		}
411c88b1d6cSniklas 	      break;
412c88b1d6cSniklas 
413c88b1d6cSniklas 	    case 1:
414c88b1d6cSniklas 	      /* An end record.  */
415c88b1d6cSniklas 	      if (abfd->start_address == 0)
416c88b1d6cSniklas 		abfd->start_address = addr;
417c88b1d6cSniklas 	      if (buf != NULL)
418c88b1d6cSniklas 		free (buf);
419c074d1c9Sdrahn 	      return TRUE;
420c88b1d6cSniklas 
421c88b1d6cSniklas 	    case 2:
422c88b1d6cSniklas 	      /* An extended address record.  */
423c88b1d6cSniklas 	      if (len != 2)
424c88b1d6cSniklas 		{
425c88b1d6cSniklas 		  (*_bfd_error_handler)
426c074d1c9Sdrahn 		    (_("%s:%u: bad extended address record length in Intel Hex file"),
427c074d1c9Sdrahn 		     bfd_archive_filename (abfd), lineno);
428c88b1d6cSniklas 		  bfd_set_error (bfd_error_bad_value);
429c88b1d6cSniklas 		  goto error_return;
430c88b1d6cSniklas 		}
431c88b1d6cSniklas 
432c88b1d6cSniklas 	      segbase = HEX4 (buf) << 4;
433c88b1d6cSniklas 
434c88b1d6cSniklas 	      sec = NULL;
435c88b1d6cSniklas 
436c88b1d6cSniklas 	      break;
437c88b1d6cSniklas 
438c88b1d6cSniklas 	    case 3:
439c88b1d6cSniklas 	      /* An extended start address record.  */
440c88b1d6cSniklas 	      if (len != 4)
441c88b1d6cSniklas 		{
442c88b1d6cSniklas 		  (*_bfd_error_handler)
443c074d1c9Sdrahn 		    (_("%s:%u: bad extended start address length in Intel Hex file"),
444c074d1c9Sdrahn 		     bfd_archive_filename (abfd), lineno);
445c88b1d6cSniklas 		  bfd_set_error (bfd_error_bad_value);
446c88b1d6cSniklas 		  goto error_return;
447c88b1d6cSniklas 		}
448c88b1d6cSniklas 
449c88b1d6cSniklas 	      abfd->start_address += (HEX4 (buf) << 4) + HEX4 (buf + 4);
450c88b1d6cSniklas 
451c88b1d6cSniklas 	      sec = NULL;
452c88b1d6cSniklas 
453c88b1d6cSniklas 	      break;
454c88b1d6cSniklas 
455c88b1d6cSniklas 	    case 4:
456c88b1d6cSniklas 	      /* An extended linear address record.  */
457c88b1d6cSniklas 	      if (len != 2)
458c88b1d6cSniklas 		{
459c88b1d6cSniklas 		  (*_bfd_error_handler)
460c074d1c9Sdrahn 		    (_("%s:%u: bad extended linear address record length in Intel Hex file"),
461c074d1c9Sdrahn 		     bfd_archive_filename (abfd), lineno);
462c88b1d6cSniklas 		  bfd_set_error (bfd_error_bad_value);
463c88b1d6cSniklas 		  goto error_return;
464c88b1d6cSniklas 		}
465c88b1d6cSniklas 
466b305b0f1Sespie 	      extbase = HEX4 (buf) << 16;
467c88b1d6cSniklas 
468c88b1d6cSniklas 	      sec = NULL;
469c88b1d6cSniklas 
470c88b1d6cSniklas 	      break;
471c88b1d6cSniklas 
472c88b1d6cSniklas 	    case 5:
473c88b1d6cSniklas 	      /* An extended linear start address record.  */
474c88b1d6cSniklas 	      if (len != 2 && len != 4)
475c88b1d6cSniklas 		{
476c88b1d6cSniklas 		  (*_bfd_error_handler)
477c074d1c9Sdrahn 		    (_("%s:%u: bad extended linear start address length in Intel Hex file"),
478c074d1c9Sdrahn 		     bfd_archive_filename (abfd), lineno);
479c88b1d6cSniklas 		  bfd_set_error (bfd_error_bad_value);
480c88b1d6cSniklas 		  goto error_return;
481c88b1d6cSniklas 		}
482c88b1d6cSniklas 
483c88b1d6cSniklas 	      if (len == 2)
484c88b1d6cSniklas 		abfd->start_address += HEX4 (buf) << 16;
485c88b1d6cSniklas 	      else
486c88b1d6cSniklas 		abfd->start_address = (HEX4 (buf) << 16) + HEX4 (buf + 4);
487c88b1d6cSniklas 
488c88b1d6cSniklas 	      sec = NULL;
489c88b1d6cSniklas 
490c88b1d6cSniklas 	      break;
491c88b1d6cSniklas 
492c88b1d6cSniklas 	    default:
493c88b1d6cSniklas 	      (*_bfd_error_handler)
494c074d1c9Sdrahn 		(_("%s:%u: unrecognized ihex type %u in Intel Hex file\n"),
495c074d1c9Sdrahn 		 bfd_archive_filename (abfd), lineno, type);
496c88b1d6cSniklas 	      bfd_set_error (bfd_error_bad_value);
497c88b1d6cSniklas 	      goto error_return;
498c88b1d6cSniklas 	    }
499c88b1d6cSniklas 	}
500c88b1d6cSniklas     }
501c88b1d6cSniklas 
502c88b1d6cSniklas   if (error)
503c88b1d6cSniklas     goto error_return;
504c88b1d6cSniklas 
505c88b1d6cSniklas   if (buf != NULL)
506c88b1d6cSniklas     free (buf);
507c88b1d6cSniklas 
508c074d1c9Sdrahn   return TRUE;
509c88b1d6cSniklas 
510c88b1d6cSniklas  error_return:
511c88b1d6cSniklas   if (buf != NULL)
512c88b1d6cSniklas     free (buf);
513c074d1c9Sdrahn   return FALSE;
514c88b1d6cSniklas }
515c88b1d6cSniklas 
516c88b1d6cSniklas /* Try to recognize an Intel Hex file.  */
517c88b1d6cSniklas 
518c88b1d6cSniklas static const bfd_target *
ihex_object_p(abfd)519c88b1d6cSniklas ihex_object_p (abfd)
520c88b1d6cSniklas      bfd *abfd;
521c88b1d6cSniklas {
522c074d1c9Sdrahn   PTR tdata_save;
523c88b1d6cSniklas   bfd_byte b[9];
524c88b1d6cSniklas   unsigned int i;
525c88b1d6cSniklas   unsigned int type;
526c88b1d6cSniklas 
527c88b1d6cSniklas   ihex_init ();
528c88b1d6cSniklas 
529c88b1d6cSniklas   if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
530c88b1d6cSniklas     return NULL;
531c074d1c9Sdrahn   if (bfd_bread (b, (bfd_size_type) 9, abfd) != 9)
532c88b1d6cSniklas     {
533c88b1d6cSniklas       if (bfd_get_error () == bfd_error_file_truncated)
534c88b1d6cSniklas 	bfd_set_error (bfd_error_wrong_format);
535c88b1d6cSniklas       return NULL;
536c88b1d6cSniklas     }
537c88b1d6cSniklas 
538c88b1d6cSniklas   if (b[0] != ':')
539c88b1d6cSniklas     {
540c88b1d6cSniklas       bfd_set_error (bfd_error_wrong_format);
541c88b1d6cSniklas       return NULL;
542c88b1d6cSniklas     }
543c88b1d6cSniklas 
544c88b1d6cSniklas   for (i = 1; i < 9; i++)
545c88b1d6cSniklas     {
546c88b1d6cSniklas       if (! ISHEX (b[i]))
547c88b1d6cSniklas 	{
548c88b1d6cSniklas 	  bfd_set_error (bfd_error_wrong_format);
549c88b1d6cSniklas 	  return NULL;
550c88b1d6cSniklas 	}
551c88b1d6cSniklas     }
552c88b1d6cSniklas 
553c88b1d6cSniklas   type = HEX2 (b + 7);
554c88b1d6cSniklas   if (type > 5)
555c88b1d6cSniklas     {
556c88b1d6cSniklas       bfd_set_error (bfd_error_wrong_format);
557c88b1d6cSniklas       return NULL;
558c88b1d6cSniklas     }
559c88b1d6cSniklas 
560c88b1d6cSniklas   /* OK, it looks like it really is an Intel Hex file.  */
561c074d1c9Sdrahn   tdata_save = abfd->tdata.any;
562c074d1c9Sdrahn   if (! ihex_mkobject (abfd) || ! ihex_scan (abfd))
563c074d1c9Sdrahn     {
564c074d1c9Sdrahn       if (abfd->tdata.any != tdata_save && abfd->tdata.any != NULL)
565c074d1c9Sdrahn 	bfd_release (abfd, abfd->tdata.any);
566c074d1c9Sdrahn       abfd->tdata.any = tdata_save;
567c88b1d6cSniklas       return NULL;
568c074d1c9Sdrahn     }
569c88b1d6cSniklas 
570c88b1d6cSniklas   return abfd->xvec;
571c88b1d6cSniklas }
572c88b1d6cSniklas 
573c88b1d6cSniklas /* Read the contents of a section in an Intel Hex file.  */
574c88b1d6cSniklas 
575c074d1c9Sdrahn static bfd_boolean
ihex_read_section(abfd,section,contents)576c88b1d6cSniklas ihex_read_section (abfd, section, contents)
577c88b1d6cSniklas      bfd *abfd;
578c88b1d6cSniklas      asection *section;
579c88b1d6cSniklas      bfd_byte *contents;
580c88b1d6cSniklas {
581c88b1d6cSniklas   int c;
582c88b1d6cSniklas   bfd_byte *p;
583b305b0f1Sespie   bfd_byte *buf = NULL;
584c88b1d6cSniklas   size_t bufsize;
585c074d1c9Sdrahn   bfd_boolean error;
586c88b1d6cSniklas 
587c88b1d6cSniklas   if (bfd_seek (abfd, section->filepos, SEEK_SET) != 0)
588c88b1d6cSniklas     goto error_return;
589c88b1d6cSniklas 
590c88b1d6cSniklas   p = contents;
591c88b1d6cSniklas   bufsize = 0;
592c074d1c9Sdrahn   error = FALSE;
593c88b1d6cSniklas   while ((c = ihex_get_byte (abfd, &error)) != EOF)
594c88b1d6cSniklas     {
595c88b1d6cSniklas       char hdr[8];
596c88b1d6cSniklas       unsigned int len;
597c88b1d6cSniklas       bfd_vma addr;
598c88b1d6cSniklas       unsigned int type;
599c88b1d6cSniklas       unsigned int i;
600c88b1d6cSniklas 
601c88b1d6cSniklas       if (c == '\r' || c == '\n')
602c88b1d6cSniklas 	continue;
603c88b1d6cSniklas 
604c88b1d6cSniklas       /* This is called after ihex_scan has succeeded, so we ought to
605c88b1d6cSniklas          know the exact format.  */
606c88b1d6cSniklas       BFD_ASSERT (c == ':');
607c88b1d6cSniklas 
608c074d1c9Sdrahn       if (bfd_bread (hdr, (bfd_size_type) 8, abfd) != 8)
609c88b1d6cSniklas 	goto error_return;
610c88b1d6cSniklas 
611c88b1d6cSniklas       len = HEX2 (hdr);
612c88b1d6cSniklas       addr = HEX4 (hdr + 2);
613c88b1d6cSniklas       type = HEX2 (hdr + 6);
614c88b1d6cSniklas 
615c88b1d6cSniklas       /* We should only see type 0 records here.  */
616c88b1d6cSniklas       if (type != 0)
617c88b1d6cSniklas 	{
618c88b1d6cSniklas 	  (*_bfd_error_handler)
619b305b0f1Sespie 	    (_("%s: internal error in ihex_read_section"),
620c074d1c9Sdrahn 	     bfd_archive_filename (abfd));
621c88b1d6cSniklas 	  bfd_set_error (bfd_error_bad_value);
622c88b1d6cSniklas 	  goto error_return;
623c88b1d6cSniklas 	}
624c88b1d6cSniklas 
625c88b1d6cSniklas       if (len * 2 > bufsize)
626c88b1d6cSniklas 	{
627c074d1c9Sdrahn 	  buf = (bfd_byte *) bfd_realloc (buf, (bfd_size_type) len * 2);
628c88b1d6cSniklas 	  if (buf == NULL)
629c88b1d6cSniklas 	    goto error_return;
630c88b1d6cSniklas 	  bufsize = len * 2;
631c88b1d6cSniklas 	}
632c88b1d6cSniklas 
633c074d1c9Sdrahn       if (bfd_bread (buf, (bfd_size_type) len * 2, abfd) != len * 2)
634c88b1d6cSniklas 	goto error_return;
635c88b1d6cSniklas 
636c88b1d6cSniklas       for (i = 0; i < len; i++)
637c88b1d6cSniklas 	*p++ = HEX2 (buf + 2 * i);
638c88b1d6cSniklas       if ((bfd_size_type) (p - contents) >= section->_raw_size)
639c88b1d6cSniklas 	{
640c88b1d6cSniklas 	  /* We've read everything in the section.  */
641c88b1d6cSniklas 	  if (buf != NULL)
642c88b1d6cSniklas 	    free (buf);
643c074d1c9Sdrahn 	  return TRUE;
644c88b1d6cSniklas 	}
645c88b1d6cSniklas 
646c88b1d6cSniklas       /* Skip the checksum.  */
647c074d1c9Sdrahn       if (bfd_bread (buf, (bfd_size_type) 2, abfd) != 2)
648c88b1d6cSniklas 	goto error_return;
649c88b1d6cSniklas     }
650c88b1d6cSniklas 
651c88b1d6cSniklas   if ((bfd_size_type) (p - contents) < section->_raw_size)
652c88b1d6cSniklas     {
653c88b1d6cSniklas       (*_bfd_error_handler)
654b305b0f1Sespie 	(_("%s: bad section length in ihex_read_section"),
655c074d1c9Sdrahn 	 bfd_archive_filename (abfd));
656c88b1d6cSniklas       bfd_set_error (bfd_error_bad_value);
657c88b1d6cSniklas       goto error_return;
658c88b1d6cSniklas     }
659c88b1d6cSniklas 
660c88b1d6cSniklas   if (buf != NULL)
661c88b1d6cSniklas     free (buf);
662c88b1d6cSniklas 
663c074d1c9Sdrahn   return TRUE;
664c88b1d6cSniklas 
665c88b1d6cSniklas  error_return:
666c88b1d6cSniklas   if (buf != NULL)
667c88b1d6cSniklas     free (buf);
668c074d1c9Sdrahn   return FALSE;
669c88b1d6cSniklas }
670c88b1d6cSniklas 
671c88b1d6cSniklas /* Get the contents of a section in an Intel Hex file.  */
672c88b1d6cSniklas 
673c074d1c9Sdrahn static bfd_boolean
ihex_get_section_contents(abfd,section,location,offset,count)674c88b1d6cSniklas ihex_get_section_contents (abfd, section, location, offset, count)
675c88b1d6cSniklas      bfd *abfd;
676c88b1d6cSniklas      asection *section;
677c88b1d6cSniklas      PTR location;
678c88b1d6cSniklas      file_ptr offset;
679c88b1d6cSniklas      bfd_size_type count;
680c88b1d6cSniklas {
681c88b1d6cSniklas   if (section->used_by_bfd == NULL)
682c88b1d6cSniklas     {
683c88b1d6cSniklas       section->used_by_bfd = bfd_alloc (abfd, section->_raw_size);
684c88b1d6cSniklas       if (section->used_by_bfd == NULL)
685c074d1c9Sdrahn 	return FALSE;
686c88b1d6cSniklas       if (! ihex_read_section (abfd, section, section->used_by_bfd))
687c074d1c9Sdrahn 	return FALSE;
688c88b1d6cSniklas     }
689c88b1d6cSniklas 
690c88b1d6cSniklas   memcpy (location, (bfd_byte *) section->used_by_bfd + offset,
691c88b1d6cSniklas 	  (size_t) count);
692c88b1d6cSniklas 
693c074d1c9Sdrahn   return TRUE;
694c88b1d6cSniklas }
695c88b1d6cSniklas 
696c88b1d6cSniklas /* Set the contents of a section in an Intel Hex file.  */
697c88b1d6cSniklas 
698c074d1c9Sdrahn static bfd_boolean
ihex_set_section_contents(abfd,section,location,offset,count)699c88b1d6cSniklas ihex_set_section_contents (abfd, section, location, offset, count)
700c88b1d6cSniklas      bfd *abfd;
701c88b1d6cSniklas      asection *section;
702*007c2a45Smiod      const PTR location;
703c88b1d6cSniklas      file_ptr offset;
704c88b1d6cSniklas      bfd_size_type count;
705c88b1d6cSniklas {
706c88b1d6cSniklas   struct ihex_data_list *n;
707c88b1d6cSniklas   bfd_byte *data;
708c88b1d6cSniklas   struct ihex_data_struct *tdata;
709c074d1c9Sdrahn   bfd_size_type amt;
710c88b1d6cSniklas 
711c88b1d6cSniklas   if (count == 0
712c88b1d6cSniklas       || (section->flags & SEC_ALLOC) == 0
713c88b1d6cSniklas       || (section->flags & SEC_LOAD) == 0)
714c074d1c9Sdrahn     return TRUE;
715c88b1d6cSniklas 
716c074d1c9Sdrahn   amt = sizeof (struct ihex_data_list);
717c074d1c9Sdrahn   n = (struct ihex_data_list *) bfd_alloc (abfd, amt);
718c88b1d6cSniklas   if (n == NULL)
719c074d1c9Sdrahn     return FALSE;
720c88b1d6cSniklas 
721c88b1d6cSniklas   data = (bfd_byte *) bfd_alloc (abfd, count);
722c88b1d6cSniklas   if (data == NULL)
723c074d1c9Sdrahn     return FALSE;
724c88b1d6cSniklas   memcpy (data, location, (size_t) count);
725c88b1d6cSniklas 
726c88b1d6cSniklas   n->data = data;
727c88b1d6cSniklas   n->where = section->lma + offset;
728c88b1d6cSniklas   n->size = count;
729c88b1d6cSniklas 
730c88b1d6cSniklas   /* Sort the records by address.  Optimize for the common case of
731c88b1d6cSniklas      adding a record to the end of the list.  */
732c88b1d6cSniklas   tdata = abfd->tdata.ihex_data;
733c88b1d6cSniklas   if (tdata->tail != NULL
734c88b1d6cSniklas       && n->where >= tdata->tail->where)
735c88b1d6cSniklas     {
736c88b1d6cSniklas       tdata->tail->next = n;
737c88b1d6cSniklas       n->next = NULL;
738c88b1d6cSniklas       tdata->tail = n;
739c88b1d6cSniklas     }
740c88b1d6cSniklas   else
741c88b1d6cSniklas     {
742c88b1d6cSniklas       register struct ihex_data_list **pp;
743c88b1d6cSniklas 
744c88b1d6cSniklas       for (pp = &tdata->head;
745c88b1d6cSniklas 	   *pp != NULL && (*pp)->where < n->where;
746c88b1d6cSniklas 	   pp = &(*pp)->next)
747c88b1d6cSniklas 	;
748c88b1d6cSniklas       n->next = *pp;
749c88b1d6cSniklas       *pp = n;
750c88b1d6cSniklas       if (n->next == NULL)
751c88b1d6cSniklas 	tdata->tail = n;
752c88b1d6cSniklas     }
753c88b1d6cSniklas 
754c074d1c9Sdrahn   return TRUE;
755c88b1d6cSniklas }
756c88b1d6cSniklas 
757c88b1d6cSniklas /* Write a record out to an Intel Hex file.  */
758c88b1d6cSniklas 
759c074d1c9Sdrahn static bfd_boolean
ihex_write_record(abfd,count,addr,type,data)760c88b1d6cSniklas ihex_write_record (abfd, count, addr, type, data)
761c88b1d6cSniklas      bfd *abfd;
762c074d1c9Sdrahn      size_t count;
763c074d1c9Sdrahn      unsigned int addr;
764c88b1d6cSniklas      unsigned int type;
765c88b1d6cSniklas      bfd_byte *data;
766c88b1d6cSniklas {
767c88b1d6cSniklas   static const char digs[] = "0123456789ABCDEF";
768c88b1d6cSniklas   char buf[9 + CHUNK * 2 + 4];
769c88b1d6cSniklas   char *p;
770c88b1d6cSniklas   unsigned int chksum;
771c88b1d6cSniklas   unsigned int i;
772c074d1c9Sdrahn   size_t total;
773c88b1d6cSniklas 
774c88b1d6cSniklas #define TOHEX(buf, v) \
775c88b1d6cSniklas   ((buf)[0] = digs[((v) >> 4) & 0xf], (buf)[1] = digs[(v) & 0xf])
776c88b1d6cSniklas 
777c88b1d6cSniklas   buf[0] = ':';
778c88b1d6cSniklas   TOHEX (buf + 1, count);
779c88b1d6cSniklas   TOHEX (buf + 3, (addr >> 8) & 0xff);
780c88b1d6cSniklas   TOHEX (buf + 5, addr & 0xff);
781c88b1d6cSniklas   TOHEX (buf + 7, type);
782c88b1d6cSniklas 
783c88b1d6cSniklas   chksum = count + addr + (addr >> 8) + type;
784c88b1d6cSniklas 
785c88b1d6cSniklas   for (i = 0, p = buf + 9; i < count; i++, p += 2, data++)
786c88b1d6cSniklas     {
787c88b1d6cSniklas       TOHEX (p, *data);
788c88b1d6cSniklas       chksum += *data;
789c88b1d6cSniklas     }
790c88b1d6cSniklas 
791c88b1d6cSniklas   TOHEX (p, (- chksum) & 0xff);
792c88b1d6cSniklas   p[2] = '\r';
793c88b1d6cSniklas   p[3] = '\n';
794c88b1d6cSniklas 
795c074d1c9Sdrahn   total = 9 + count * 2 + 4;
796c074d1c9Sdrahn   if (bfd_bwrite (buf, (bfd_size_type) total, abfd) != total)
797c074d1c9Sdrahn     return FALSE;
798c88b1d6cSniklas 
799c074d1c9Sdrahn   return TRUE;
800c88b1d6cSniklas }
801c88b1d6cSniklas 
802c88b1d6cSniklas /* Write out an Intel Hex file.  */
803c88b1d6cSniklas 
804c074d1c9Sdrahn static bfd_boolean
ihex_write_object_contents(abfd)805c88b1d6cSniklas ihex_write_object_contents (abfd)
806c88b1d6cSniklas      bfd *abfd;
807c88b1d6cSniklas {
808c88b1d6cSniklas   bfd_vma segbase;
809b305b0f1Sespie   bfd_vma extbase;
810c88b1d6cSniklas   struct ihex_data_list *l;
811c88b1d6cSniklas 
812c88b1d6cSniklas   segbase = 0;
813b305b0f1Sespie   extbase = 0;
814c88b1d6cSniklas   for (l = abfd->tdata.ihex_data->head; l != NULL; l = l->next)
815c88b1d6cSniklas     {
816c88b1d6cSniklas       bfd_vma where;
817c88b1d6cSniklas       bfd_byte *p;
818c88b1d6cSniklas       bfd_size_type count;
819c88b1d6cSniklas 
820c88b1d6cSniklas       where = l->where;
821c88b1d6cSniklas       p = l->data;
822c88b1d6cSniklas       count = l->size;
823c88b1d6cSniklas       while (count > 0)
824c88b1d6cSniklas 	{
825c074d1c9Sdrahn 	  size_t now;
826c074d1c9Sdrahn 	  unsigned int rec_addr;
827c88b1d6cSniklas 
828c88b1d6cSniklas 	  now = count;
829c074d1c9Sdrahn 	  if (count > CHUNK)
830c88b1d6cSniklas 	    now = CHUNK;
831c88b1d6cSniklas 
832b305b0f1Sespie 	  if (where > segbase + extbase + 0xffff)
833c88b1d6cSniklas 	    {
834c88b1d6cSniklas 	      bfd_byte addr[2];
835c88b1d6cSniklas 
836c88b1d6cSniklas 	      /* We need a new base address.  */
837c88b1d6cSniklas 	      if (where <= 0xfffff)
838c88b1d6cSniklas 		{
839b305b0f1Sespie 		  /* The addresses should be sorted.  */
840b305b0f1Sespie 		  BFD_ASSERT (extbase == 0);
841b305b0f1Sespie 
842c88b1d6cSniklas 		  segbase = where & 0xf0000;
843b305b0f1Sespie 		  addr[0] = (bfd_byte)(segbase >> 12) & 0xff;
844b305b0f1Sespie 		  addr[1] = (bfd_byte)(segbase >> 4) & 0xff;
845c88b1d6cSniklas 		  if (! ihex_write_record (abfd, 2, 0, 2, addr))
846c074d1c9Sdrahn 		    return FALSE;
847c88b1d6cSniklas 		}
848c88b1d6cSniklas 	      else
849c88b1d6cSniklas 		{
850b305b0f1Sespie 		  /* The extended address record and the extended
851b305b0f1Sespie                      linear address record are combined, at least by
852b305b0f1Sespie                      some readers.  We need an extended linear address
853b305b0f1Sespie                      record here, so if we've already written out an
854b305b0f1Sespie                      extended address record, zero it out to avoid
855b305b0f1Sespie                      confusion.  */
856b305b0f1Sespie 		  if (segbase != 0)
857b305b0f1Sespie 		    {
858b305b0f1Sespie 		      addr[0] = 0;
859b305b0f1Sespie 		      addr[1] = 0;
860b305b0f1Sespie 		      if (! ihex_write_record (abfd, 2, 0, 2, addr))
861c074d1c9Sdrahn 			return FALSE;
862b305b0f1Sespie 		      segbase = 0;
863b305b0f1Sespie 		    }
864b305b0f1Sespie 
865b305b0f1Sespie 		  extbase = where & 0xffff0000;
866b305b0f1Sespie 		  if (where > extbase + 0xffff)
867c88b1d6cSniklas 		    {
868c88b1d6cSniklas 		      char buf[20];
869c88b1d6cSniklas 
870c88b1d6cSniklas 		      sprintf_vma (buf, where);
871c88b1d6cSniklas 		      (*_bfd_error_handler)
872c074d1c9Sdrahn 			(_("%s: address 0x%s out of range for Intel Hex file"),
873c88b1d6cSniklas 			 bfd_get_filename (abfd), buf);
874c88b1d6cSniklas 		      bfd_set_error (bfd_error_bad_value);
875c074d1c9Sdrahn 		      return FALSE;
876c88b1d6cSniklas 		    }
877b305b0f1Sespie 		  addr[0] = (bfd_byte)(extbase >> 24) & 0xff;
878b305b0f1Sespie 		  addr[1] = (bfd_byte)(extbase >> 16) & 0xff;
879c88b1d6cSniklas 		  if (! ihex_write_record (abfd, 2, 0, 4, addr))
880c074d1c9Sdrahn 		    return FALSE;
881c88b1d6cSniklas 		}
882c88b1d6cSniklas 	    }
883c88b1d6cSniklas 
884c074d1c9Sdrahn 	  rec_addr = where - (extbase + segbase);
885c074d1c9Sdrahn 
886c074d1c9Sdrahn           /* Output records shouldn't cross 64K boundaries.  */
887c074d1c9Sdrahn           if (rec_addr + now > 0xffff)
888c074d1c9Sdrahn             now = 0x10000 - rec_addr;
889c074d1c9Sdrahn 
890c074d1c9Sdrahn 	  if (! ihex_write_record (abfd, now, rec_addr, 0, p))
891c074d1c9Sdrahn 	    return FALSE;
892c88b1d6cSniklas 
893c88b1d6cSniklas 	  where += now;
894c88b1d6cSniklas 	  p += now;
895c88b1d6cSniklas 	  count -= now;
896c88b1d6cSniklas 	}
897c88b1d6cSniklas     }
898c88b1d6cSniklas 
899c88b1d6cSniklas   if (abfd->start_address != 0)
900c88b1d6cSniklas     {
901c88b1d6cSniklas       bfd_vma start;
902c88b1d6cSniklas       bfd_byte startbuf[4];
903c88b1d6cSniklas 
904c88b1d6cSniklas       start = abfd->start_address;
905c88b1d6cSniklas 
906c88b1d6cSniklas       if (start <= 0xfffff)
907c88b1d6cSniklas 	{
908b305b0f1Sespie 	  startbuf[0] = (bfd_byte)((start & 0xf0000) >> 12) & 0xff;
909c88b1d6cSniklas 	  startbuf[1] = 0;
910b305b0f1Sespie 	  startbuf[2] = (bfd_byte)(start >> 8) & 0xff;
911b305b0f1Sespie 	  startbuf[3] = (bfd_byte)start & 0xff;
912c88b1d6cSniklas 	  if (! ihex_write_record (abfd, 4, 0, 3, startbuf))
913c074d1c9Sdrahn 	    return FALSE;
914c88b1d6cSniklas 	}
915c88b1d6cSniklas       else
916c88b1d6cSniklas 	{
917b305b0f1Sespie 	  startbuf[0] = (bfd_byte)(start >> 24) & 0xff;
918b305b0f1Sespie 	  startbuf[1] = (bfd_byte)(start >> 16) & 0xff;
919b305b0f1Sespie 	  startbuf[2] = (bfd_byte)(start >> 8) & 0xff;
920b305b0f1Sespie 	  startbuf[3] = (bfd_byte)start & 0xff;
921c88b1d6cSniklas 	  if (! ihex_write_record (abfd, 4, 0, 5, startbuf))
922c074d1c9Sdrahn 	    return FALSE;
923c88b1d6cSniklas 	}
924c88b1d6cSniklas     }
925c88b1d6cSniklas 
926c88b1d6cSniklas   if (! ihex_write_record (abfd, 0, 0, 1, NULL))
927c074d1c9Sdrahn     return FALSE;
928c88b1d6cSniklas 
929c074d1c9Sdrahn   return TRUE;
930c88b1d6cSniklas }
931c88b1d6cSniklas 
932c88b1d6cSniklas /* Set the architecture for the output file.  The architecture is
933c88b1d6cSniklas    irrelevant, so we ignore errors about unknown architectures.  */
934c88b1d6cSniklas 
935c074d1c9Sdrahn static bfd_boolean
ihex_set_arch_mach(abfd,arch,mach)936c88b1d6cSniklas ihex_set_arch_mach (abfd, arch, mach)
937c88b1d6cSniklas      bfd *abfd;
938c88b1d6cSniklas      enum bfd_architecture arch;
939c88b1d6cSniklas      unsigned long mach;
940c88b1d6cSniklas {
941c88b1d6cSniklas   if (! bfd_default_set_arch_mach (abfd, arch, mach))
942c88b1d6cSniklas     {
943c88b1d6cSniklas       if (arch != bfd_arch_unknown)
944c074d1c9Sdrahn 	return FALSE;
945c88b1d6cSniklas     }
946c074d1c9Sdrahn   return TRUE;
947c88b1d6cSniklas }
948c88b1d6cSniklas 
949c88b1d6cSniklas /* Get the size of the headers, for the linker.  */
950c88b1d6cSniklas 
951c88b1d6cSniklas static int
ihex_sizeof_headers(abfd,exec)952c88b1d6cSniklas ihex_sizeof_headers (abfd, exec)
953b305b0f1Sespie      bfd *abfd ATTRIBUTE_UNUSED;
954c074d1c9Sdrahn      bfd_boolean exec ATTRIBUTE_UNUSED;
955c88b1d6cSniklas {
956c88b1d6cSniklas   return 0;
957c88b1d6cSniklas }
958c88b1d6cSniklas 
959c88b1d6cSniklas /* Some random definitions for the target vector.  */
960c88b1d6cSniklas 
961c88b1d6cSniklas #define	ihex_close_and_cleanup _bfd_generic_close_and_cleanup
962c88b1d6cSniklas #define ihex_bfd_free_cached_info _bfd_generic_bfd_free_cached_info
963c88b1d6cSniklas #define ihex_new_section_hook _bfd_generic_new_section_hook
964c88b1d6cSniklas #define ihex_get_section_contents_in_window \
965c88b1d6cSniklas   _bfd_generic_get_section_contents_in_window
966c88b1d6cSniklas 
967c88b1d6cSniklas #define ihex_get_symtab_upper_bound bfd_0l
968*007c2a45Smiod #define ihex_canonicalize_symtab \
969c88b1d6cSniklas   ((long (*) PARAMS ((bfd *, asymbol **))) bfd_0l)
970c074d1c9Sdrahn #define ihex_make_empty_symbol _bfd_generic_make_empty_symbol
971c88b1d6cSniklas #define ihex_print_symbol _bfd_nosymbols_print_symbol
972c88b1d6cSniklas #define ihex_get_symbol_info _bfd_nosymbols_get_symbol_info
973b305b0f1Sespie #define ihex_bfd_is_local_label_name _bfd_nosymbols_bfd_is_local_label_name
974c88b1d6cSniklas #define ihex_get_lineno _bfd_nosymbols_get_lineno
975c88b1d6cSniklas #define ihex_find_nearest_line _bfd_nosymbols_find_nearest_line
976c88b1d6cSniklas #define ihex_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol
977c88b1d6cSniklas #define ihex_read_minisymbols _bfd_nosymbols_read_minisymbols
978c88b1d6cSniklas #define ihex_minisymbol_to_symbol _bfd_nosymbols_minisymbol_to_symbol
979c88b1d6cSniklas 
980c88b1d6cSniklas #define ihex_get_reloc_upper_bound \
981c88b1d6cSniklas   ((long (*) PARAMS ((bfd *, asection *))) bfd_0l)
982c88b1d6cSniklas #define ihex_canonicalize_reloc \
983c88b1d6cSniklas   ((long (*) PARAMS ((bfd *, asection *, arelent **, asymbol **))) bfd_0l)
984c88b1d6cSniklas #define ihex_bfd_reloc_type_lookup _bfd_norelocs_bfd_reloc_type_lookup
985c88b1d6cSniklas 
986c88b1d6cSniklas #define ihex_bfd_get_relocated_section_contents \
987c88b1d6cSniklas   bfd_generic_get_relocated_section_contents
988c88b1d6cSniklas #define ihex_bfd_relax_section bfd_generic_relax_section
989b305b0f1Sespie #define ihex_bfd_gc_sections bfd_generic_gc_sections
990c074d1c9Sdrahn #define ihex_bfd_merge_sections bfd_generic_merge_sections
991c074d1c9Sdrahn #define ihex_bfd_discard_group bfd_generic_discard_group
992c88b1d6cSniklas #define ihex_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
993c074d1c9Sdrahn #define ihex_bfd_link_hash_table_free _bfd_generic_link_hash_table_free
994c88b1d6cSniklas #define ihex_bfd_link_add_symbols _bfd_generic_link_add_symbols
995c074d1c9Sdrahn #define ihex_bfd_link_just_syms _bfd_generic_link_just_syms
996c88b1d6cSniklas #define ihex_bfd_final_link _bfd_generic_final_link
997c88b1d6cSniklas #define ihex_bfd_link_split_section _bfd_generic_link_split_section
998c88b1d6cSniklas 
999c88b1d6cSniklas /* The Intel Hex target vector.  */
1000c88b1d6cSniklas 
1001c88b1d6cSniklas const bfd_target ihex_vec =
1002c88b1d6cSniklas {
1003c88b1d6cSniklas   "ihex",			/* name */
1004c88b1d6cSniklas   bfd_target_ihex_flavour,
1005c88b1d6cSniklas   BFD_ENDIAN_UNKNOWN,		/* target byte order */
1006c88b1d6cSniklas   BFD_ENDIAN_UNKNOWN,		/* target headers byte order */
1007c88b1d6cSniklas   0,				/* object flags */
1008c88b1d6cSniklas   (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD),	/* section flags */
1009c88b1d6cSniklas   0,				/* leading underscore */
1010c88b1d6cSniklas   ' ',				/* ar_pad_char */
1011c88b1d6cSniklas   16,				/* ar_max_namelen */
1012c88b1d6cSniklas   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
1013c88b1d6cSniklas   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
1014c88b1d6cSniklas   bfd_getb16, bfd_getb_signed_16, bfd_putb16,	/* data */
1015c88b1d6cSniklas   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
1016c88b1d6cSniklas   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
1017c88b1d6cSniklas   bfd_getb16, bfd_getb_signed_16, bfd_putb16,	/* hdrs */
1018c88b1d6cSniklas 
1019c88b1d6cSniklas   {
1020c88b1d6cSniklas     _bfd_dummy_target,
1021c88b1d6cSniklas     ihex_object_p,		/* bfd_check_format */
1022c88b1d6cSniklas     _bfd_dummy_target,
1023c88b1d6cSniklas     _bfd_dummy_target,
1024c88b1d6cSniklas   },
1025c88b1d6cSniklas   {
1026c88b1d6cSniklas     bfd_false,
1027c88b1d6cSniklas     ihex_mkobject,
1028c88b1d6cSniklas     _bfd_generic_mkarchive,
1029c88b1d6cSniklas     bfd_false,
1030c88b1d6cSniklas   },
1031c88b1d6cSniklas   {				/* bfd_write_contents */
1032c88b1d6cSniklas     bfd_false,
1033c88b1d6cSniklas     ihex_write_object_contents,
1034c88b1d6cSniklas     _bfd_write_archive_contents,
1035c88b1d6cSniklas     bfd_false,
1036c88b1d6cSniklas   },
1037c88b1d6cSniklas 
1038c88b1d6cSniklas   BFD_JUMP_TABLE_GENERIC (ihex),
1039c88b1d6cSniklas   BFD_JUMP_TABLE_COPY (_bfd_generic),
1040c88b1d6cSniklas   BFD_JUMP_TABLE_CORE (_bfd_nocore),
1041c88b1d6cSniklas   BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
1042c88b1d6cSniklas   BFD_JUMP_TABLE_SYMBOLS (ihex),
1043c88b1d6cSniklas   BFD_JUMP_TABLE_RELOCS (ihex),
1044c88b1d6cSniklas   BFD_JUMP_TABLE_WRITE (ihex),
1045c88b1d6cSniklas   BFD_JUMP_TABLE_LINK (ihex),
1046c88b1d6cSniklas   BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
1047c88b1d6cSniklas 
1048b305b0f1Sespie   NULL,
1049b305b0f1Sespie 
1050c88b1d6cSniklas   (PTR) 0
1051c88b1d6cSniklas };
1052