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