133965Sjdp/* BFD back-end for Intel Hex objects. 2218822Sdim Copyright 1995, 1996, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 3218822Sdim 2006, 2007 Free Software Foundation, Inc. 433965Sjdp Written by Ian Lance Taylor of Cygnus Support <ian@cygnus.com>. 533965Sjdp 6104834Sobrien This file is part of BFD, the Binary File Descriptor library. 733965Sjdp 8104834Sobrien This program is free software; you can redistribute it and/or modify 9104834Sobrien it under the terms of the GNU General Public License as published by 10104834Sobrien the Free Software Foundation; either version 2 of the License, or 11104834Sobrien (at your option) any later version. 1233965Sjdp 13104834Sobrien This program is distributed in the hope that it will be useful, 14104834Sobrien but WITHOUT ANY WARRANTY; without even the implied warranty of 15104834Sobrien MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16104834Sobrien GNU General Public License for more details. 1733965Sjdp 18104834Sobrien You should have received a copy of the GNU General Public License 19104834Sobrien along with this program; if not, write to the Free Software 20218822Sdim Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ 2133965Sjdp 2233965Sjdp/* This is what Intel Hex files look like: 2333965Sjdp 2433965Sjdp1. INTEL FORMATS 2533965Sjdp 2633965SjdpA. Intel 1 2733965Sjdp 2833965Sjdp 16-bit address-field format, for files 64k bytes in length or less. 2933965Sjdp 3033965Sjdp DATA RECORD 3133965Sjdp Byte 1 Header = colon(:) 3233965Sjdp 2..3 The number of data bytes in hex notation 3333965Sjdp 4..5 High byte of the record load address 3433965Sjdp 6..7 Low byte of the record load address 3533965Sjdp 8..9 Record type, must be "00" 3633965Sjdp 10..x Data bytes in hex notation: 3733965Sjdp x = (number of bytes - 1) * 2 + 11 3833965Sjdp x+1..x+2 Checksum in hex notation 3933965Sjdp x+3..x+4 Carriage return, line feed 4033965Sjdp 4133965Sjdp END RECORD 4233965Sjdp Byte 1 Header = colon (:) 4333965Sjdp 2..3 The byte count, must be "00" 4433965Sjdp 4..7 Transfer-address (usually "0000") 4533965Sjdp the jump-to address, execution start address 4633965Sjdp 8..9 Record type, must be "01" 4733965Sjdp 10..11 Checksum, in hex notation 4833965Sjdp 12..13 Carriage return, line feed 4933965Sjdp 5033965SjdpB. INTEL 2 5133965Sjdp 5233965Sjdp MCS-86 format, using a 20-bit address for files larger than 64K bytes. 5333965Sjdp 5433965Sjdp DATA RECORD 5533965Sjdp Byte 1 Header = colon (:) 5633965Sjdp 2..3 The byte count of this record, hex notation 5733965Sjdp 4..5 High byte of the record load address 5833965Sjdp 6..7 Low byte of the record load address 5933965Sjdp 8..9 Record type, must be "00" 6033965Sjdp 10..x The data bytes in hex notation: 6133965Sjdp x = (number of data bytes - 1) * 2 + 11 6233965Sjdp x+1..x+2 Checksum in hex notation 6333965Sjdp x+3..x+4 Carriage return, line feed 6433965Sjdp 6533965Sjdp EXTENDED ADDRESS RECORD 6633965Sjdp Byte 1 Header = colon(:) 6733965Sjdp 2..3 The byte count, must be "02" 6833965Sjdp 4..7 Load address, must be "0000" 6933965Sjdp 8..9 Record type, must be "02" 7033965Sjdp 10..11 High byte of the offset address 7133965Sjdp 12..13 Low byte of the offset address 7233965Sjdp 14..15 Checksum in hex notation 7333965Sjdp 16..17 Carriage return, line feed 7433965Sjdp 7533965Sjdp The checksums are the two's complement of the 8-bit sum 7633965Sjdp without carry of the byte count, offset address, and the 7733965Sjdp record type. 7833965Sjdp 7933965Sjdp START ADDRESS RECORD 8033965Sjdp Byte 1 Header = colon (:) 8133965Sjdp 2..3 The byte count, must be "04" 8233965Sjdp 4..7 Load address, must be "0000" 8333965Sjdp 8..9 Record type, must be "03" 8433965Sjdp 10..13 8086 CS value 8533965Sjdp 14..17 8086 IP value 8633965Sjdp 18..19 Checksum in hex notation 8733965Sjdp 20..21 Carriage return, line feed 8833965Sjdp 8933965SjdpAnother document reports these additional types: 9033965Sjdp 9133965Sjdp EXTENDED LINEAR ADDRESS RECORD 9233965Sjdp Byte 1 Header = colon (:) 9333965Sjdp 2..3 The byte count, must be "02" 9433965Sjdp 4..7 Load address, must be "0000" 9533965Sjdp 8..9 Record type, must be "04" 9633965Sjdp 10..13 Upper 16 bits of address of subsequent records 9733965Sjdp 14..15 Checksum in hex notation 9833965Sjdp 16..17 Carriage return, line feed 9933965Sjdp 10033965Sjdp START LINEAR ADDRESS RECORD 10133965Sjdp Byte 1 Header = colon (:) 10233965Sjdp 2..3 The byte count, must be "02" 10333965Sjdp 4..7 Load address, must be "0000" 10433965Sjdp 8..9 Record type, must be "05" 10533965Sjdp 10..13 Upper 16 bits of start address 10633965Sjdp 14..15 Checksum in hex notation 10733965Sjdp 16..17 Carriage return, line feed 10833965Sjdp 10933965SjdpThe MRI compiler uses this, which is a repeat of type 5: 11033965Sjdp 11133965Sjdp EXTENDED START RECORD 11233965Sjdp Byte 1 Header = colon (:) 11333965Sjdp 2..3 The byte count, must be "04" 11433965Sjdp 4..7 Load address, must be "0000" 11533965Sjdp 8..9 Record type, must be "05" 11633965Sjdp 10..13 Upper 16 bits of start address 11733965Sjdp 14..17 Lower 16 bits of start address 11833965Sjdp 18..19 Checksum in hex notation 119218822Sdim 20..21 Carriage return, line feed. */ 12033965Sjdp 121218822Sdim#include "sysdep.h" 12233965Sjdp#include "bfd.h" 12333965Sjdp#include "libbfd.h" 12433965Sjdp#include "libiberty.h" 12589857Sobrien#include "safe-ctype.h" 12633965Sjdp 12733965Sjdp/* The number of bytes we put on one line during output. */ 12833965Sjdp 12960484Sobrien#define CHUNK 16 13033965Sjdp 131104834Sobrien/* Macros for converting between hex and binary. */ 13233965Sjdp 133104834Sobrien#define NIBBLE(x) (hex_value (x)) 13433965Sjdp#define HEX2(buffer) ((NIBBLE ((buffer)[0]) << 4) + NIBBLE ((buffer)[1])) 13533965Sjdp#define HEX4(buffer) ((HEX2 (buffer) << 8) + HEX2 ((buffer) + 2)) 136104834Sobrien#define ISHEX(x) (hex_p (x)) 13733965Sjdp 13833965Sjdp/* When we write out an ihex value, the values can not be output as 13933965Sjdp they are seen. Instead, we hold them in memory in this structure. */ 14033965Sjdp 14133965Sjdpstruct ihex_data_list 14233965Sjdp{ 14333965Sjdp struct ihex_data_list *next; 14433965Sjdp bfd_byte *data; 14533965Sjdp bfd_vma where; 14633965Sjdp bfd_size_type size; 14733965Sjdp}; 14833965Sjdp 14933965Sjdp/* The ihex tdata information. */ 15033965Sjdp 15133965Sjdpstruct ihex_data_struct 15233965Sjdp{ 15333965Sjdp struct ihex_data_list *head; 15433965Sjdp struct ihex_data_list *tail; 15533965Sjdp}; 15633965Sjdp 15733965Sjdp/* Initialize by filling in the hex conversion array. */ 15833965Sjdp 15933965Sjdpstatic void 160218822Sdimihex_init (void) 16133965Sjdp{ 162130561Sobrien static bfd_boolean inited; 16333965Sjdp 16433965Sjdp if (! inited) 16533965Sjdp { 166130561Sobrien inited = TRUE; 16733965Sjdp hex_init (); 16833965Sjdp } 16933965Sjdp} 17033965Sjdp 17133965Sjdp/* Create an ihex object. */ 17233965Sjdp 173130561Sobrienstatic bfd_boolean 174218822Sdimihex_mkobject (bfd *abfd) 17533965Sjdp{ 176104834Sobrien struct ihex_data_struct *tdata; 17733965Sjdp 178218822Sdim tdata = bfd_alloc (abfd, sizeof (* tdata)); 179104834Sobrien if (tdata == NULL) 180130561Sobrien return FALSE; 18133965Sjdp 182104834Sobrien abfd->tdata.ihex_data = tdata; 183104834Sobrien tdata->head = NULL; 184104834Sobrien tdata->tail = NULL; 185130561Sobrien return TRUE; 18633965Sjdp} 18733965Sjdp 18833965Sjdp/* Read a byte from a BFD. Set *ERRORPTR if an error occurred. 18933965Sjdp Return EOF on error or end of file. */ 19033965Sjdp 19133965Sjdpstatic INLINE int 192218822Sdimihex_get_byte (bfd *abfd, bfd_boolean *errorptr) 19333965Sjdp{ 19433965Sjdp bfd_byte c; 19533965Sjdp 19689857Sobrien if (bfd_bread (&c, (bfd_size_type) 1, abfd) != 1) 19733965Sjdp { 19833965Sjdp if (bfd_get_error () != bfd_error_file_truncated) 199130561Sobrien *errorptr = TRUE; 20033965Sjdp return EOF; 20133965Sjdp } 20233965Sjdp 20333965Sjdp return (int) (c & 0xff); 20433965Sjdp} 20533965Sjdp 20633965Sjdp/* Report a problem in an Intel Hex file. */ 20733965Sjdp 20833965Sjdpstatic void 209218822Sdimihex_bad_byte (bfd *abfd, unsigned int lineno, int c, bfd_boolean error) 21033965Sjdp{ 21133965Sjdp if (c == EOF) 21233965Sjdp { 21333965Sjdp if (! error) 21433965Sjdp bfd_set_error (bfd_error_file_truncated); 21533965Sjdp } 21633965Sjdp else 21733965Sjdp { 21833965Sjdp char buf[10]; 21933965Sjdp 22089857Sobrien if (! ISPRINT (c)) 22133965Sjdp sprintf (buf, "\\%03o", (unsigned int) c); 22233965Sjdp else 22333965Sjdp { 22433965Sjdp buf[0] = c; 22533965Sjdp buf[1] = '\0'; 22633965Sjdp } 22733965Sjdp (*_bfd_error_handler) 228218822Sdim (_("%B:%d: unexpected character `%s' in Intel Hex file"), 229218822Sdim abfd, lineno, buf); 23033965Sjdp bfd_set_error (bfd_error_bad_value); 23133965Sjdp } 23233965Sjdp} 23333965Sjdp 23433965Sjdp/* Read an Intel hex file and turn it into sections. We create a new 23533965Sjdp section for each contiguous set of bytes. */ 23633965Sjdp 237130561Sobrienstatic bfd_boolean 238218822Sdimihex_scan (bfd *abfd) 23933965Sjdp{ 24033965Sjdp bfd_vma segbase; 24138889Sjdp bfd_vma extbase; 24233965Sjdp asection *sec; 24389857Sobrien unsigned int lineno; 244130561Sobrien bfd_boolean error; 24533965Sjdp bfd_byte *buf = NULL; 24633965Sjdp size_t bufsize; 24733965Sjdp int c; 24833965Sjdp 24933965Sjdp if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0) 25033965Sjdp goto error_return; 25133965Sjdp 25233965Sjdp abfd->start_address = 0; 25333965Sjdp 25433965Sjdp segbase = 0; 25538889Sjdp extbase = 0; 25633965Sjdp sec = NULL; 25733965Sjdp lineno = 1; 258130561Sobrien error = FALSE; 25933965Sjdp bufsize = 0; 260104834Sobrien 26133965Sjdp while ((c = ihex_get_byte (abfd, &error)) != EOF) 26233965Sjdp { 26333965Sjdp if (c == '\r') 26433965Sjdp continue; 26533965Sjdp else if (c == '\n') 26633965Sjdp { 26733965Sjdp ++lineno; 26833965Sjdp continue; 26933965Sjdp } 27033965Sjdp else if (c != ':') 27133965Sjdp { 27233965Sjdp ihex_bad_byte (abfd, lineno, c, error); 27333965Sjdp goto error_return; 27433965Sjdp } 27533965Sjdp else 27633965Sjdp { 27733965Sjdp file_ptr pos; 27833965Sjdp char hdr[8]; 27933965Sjdp unsigned int i; 28033965Sjdp unsigned int len; 28133965Sjdp bfd_vma addr; 28233965Sjdp unsigned int type; 28333965Sjdp unsigned int chars; 28433965Sjdp unsigned int chksum; 28533965Sjdp 28633965Sjdp /* This is a data record. */ 28733965Sjdp pos = bfd_tell (abfd) - 1; 28833965Sjdp 28933965Sjdp /* Read the header bytes. */ 29089857Sobrien if (bfd_bread (hdr, (bfd_size_type) 8, abfd) != 8) 29133965Sjdp goto error_return; 29233965Sjdp 29333965Sjdp for (i = 0; i < 8; i++) 29433965Sjdp { 29533965Sjdp if (! ISHEX (hdr[i])) 29633965Sjdp { 29733965Sjdp ihex_bad_byte (abfd, lineno, hdr[i], error); 29833965Sjdp goto error_return; 29933965Sjdp } 30033965Sjdp } 30133965Sjdp 30233965Sjdp len = HEX2 (hdr); 30333965Sjdp addr = HEX4 (hdr + 2); 30433965Sjdp type = HEX2 (hdr + 6); 30533965Sjdp 30633965Sjdp /* Read the data bytes. */ 30733965Sjdp chars = len * 2 + 2; 30833965Sjdp if (chars >= bufsize) 30933965Sjdp { 310218822Sdim buf = bfd_realloc (buf, (bfd_size_type) chars); 31133965Sjdp if (buf == NULL) 31233965Sjdp goto error_return; 31333965Sjdp bufsize = chars; 31433965Sjdp } 31533965Sjdp 31689857Sobrien if (bfd_bread (buf, (bfd_size_type) chars, abfd) != chars) 31733965Sjdp goto error_return; 31833965Sjdp 31933965Sjdp for (i = 0; i < chars; i++) 32033965Sjdp { 32133965Sjdp if (! ISHEX (buf[i])) 32233965Sjdp { 323326382Semaste ihex_bad_byte (abfd, lineno, buf[i], error); 32433965Sjdp goto error_return; 32533965Sjdp } 32633965Sjdp } 32733965Sjdp 32833965Sjdp /* Check the checksum. */ 32933965Sjdp chksum = len + addr + (addr >> 8) + type; 33033965Sjdp for (i = 0; i < len; i++) 33133965Sjdp chksum += HEX2 (buf + 2 * i); 33233965Sjdp if (((- chksum) & 0xff) != (unsigned int) HEX2 (buf + 2 * i)) 33333965Sjdp { 33433965Sjdp (*_bfd_error_handler) 335218822Sdim (_("%B:%u: bad checksum in Intel Hex file (expected %u, found %u)"), 336218822Sdim abfd, lineno, 33733965Sjdp (- chksum) & 0xff, (unsigned int) HEX2 (buf + 2 * i)); 33833965Sjdp bfd_set_error (bfd_error_bad_value); 33933965Sjdp goto error_return; 34033965Sjdp } 34133965Sjdp 34233965Sjdp switch (type) 34333965Sjdp { 34433965Sjdp case 0: 34533965Sjdp /* This is a data record. */ 34633965Sjdp if (sec != NULL 347218822Sdim && sec->vma + sec->size == extbase + segbase + addr) 34833965Sjdp { 34933965Sjdp /* This data goes at the end of the section we are 35033965Sjdp currently building. */ 351218822Sdim sec->size += len; 35233965Sjdp } 35333965Sjdp else if (len > 0) 35433965Sjdp { 35533965Sjdp char secbuf[20]; 35633965Sjdp char *secname; 35789857Sobrien bfd_size_type amt; 358218822Sdim flagword flags; 35933965Sjdp 36033965Sjdp sprintf (secbuf, ".sec%d", bfd_count_sections (abfd) + 1); 36189857Sobrien amt = strlen (secbuf) + 1; 362218822Sdim secname = bfd_alloc (abfd, amt); 36333965Sjdp if (secname == NULL) 36433965Sjdp goto error_return; 36533965Sjdp strcpy (secname, secbuf); 366218822Sdim flags = SEC_HAS_CONTENTS | SEC_LOAD | SEC_ALLOC; 367218822Sdim sec = bfd_make_section_with_flags (abfd, secname, flags); 36833965Sjdp if (sec == NULL) 36933965Sjdp goto error_return; 37038889Sjdp sec->vma = extbase + segbase + addr; 37138889Sjdp sec->lma = extbase + segbase + addr; 372218822Sdim sec->size = len; 37333965Sjdp sec->filepos = pos; 37433965Sjdp } 37533965Sjdp break; 37633965Sjdp 37733965Sjdp case 1: 37833965Sjdp /* An end record. */ 37933965Sjdp if (abfd->start_address == 0) 38033965Sjdp abfd->start_address = addr; 38133965Sjdp if (buf != NULL) 38233965Sjdp free (buf); 383130561Sobrien return TRUE; 38433965Sjdp 38533965Sjdp case 2: 38633965Sjdp /* An extended address record. */ 38733965Sjdp if (len != 2) 38833965Sjdp { 38933965Sjdp (*_bfd_error_handler) 390218822Sdim (_("%B:%u: bad extended address record length in Intel Hex file"), 391218822Sdim abfd, lineno); 39233965Sjdp bfd_set_error (bfd_error_bad_value); 39333965Sjdp goto error_return; 39433965Sjdp } 39533965Sjdp 39633965Sjdp segbase = HEX4 (buf) << 4; 39733965Sjdp 39833965Sjdp sec = NULL; 39933965Sjdp 40033965Sjdp break; 40133965Sjdp 40233965Sjdp case 3: 40333965Sjdp /* An extended start address record. */ 40433965Sjdp if (len != 4) 40533965Sjdp { 40633965Sjdp (*_bfd_error_handler) 407218822Sdim (_("%B:%u: bad extended start address length in Intel Hex file"), 408218822Sdim abfd, lineno); 40933965Sjdp bfd_set_error (bfd_error_bad_value); 41033965Sjdp goto error_return; 41133965Sjdp } 41233965Sjdp 41333965Sjdp abfd->start_address += (HEX4 (buf) << 4) + HEX4 (buf + 4); 41433965Sjdp 41533965Sjdp sec = NULL; 41633965Sjdp 41733965Sjdp break; 41833965Sjdp 41933965Sjdp case 4: 42033965Sjdp /* An extended linear address record. */ 42133965Sjdp if (len != 2) 42233965Sjdp { 42333965Sjdp (*_bfd_error_handler) 424218822Sdim (_("%B:%u: bad extended linear address record length in Intel Hex file"), 425218822Sdim abfd, lineno); 42633965Sjdp bfd_set_error (bfd_error_bad_value); 42733965Sjdp goto error_return; 42833965Sjdp } 42933965Sjdp 43038889Sjdp extbase = HEX4 (buf) << 16; 43133965Sjdp 43233965Sjdp sec = NULL; 43333965Sjdp 43433965Sjdp break; 43533965Sjdp 43633965Sjdp case 5: 43733965Sjdp /* An extended linear start address record. */ 43833965Sjdp if (len != 2 && len != 4) 43933965Sjdp { 44033965Sjdp (*_bfd_error_handler) 441218822Sdim (_("%B:%u: bad extended linear start address length in Intel Hex file"), 442218822Sdim abfd, lineno); 44333965Sjdp bfd_set_error (bfd_error_bad_value); 44433965Sjdp goto error_return; 44533965Sjdp } 44633965Sjdp 44733965Sjdp if (len == 2) 44833965Sjdp abfd->start_address += HEX4 (buf) << 16; 44933965Sjdp else 45033965Sjdp abfd->start_address = (HEX4 (buf) << 16) + HEX4 (buf + 4); 45133965Sjdp 45233965Sjdp sec = NULL; 45333965Sjdp 45433965Sjdp break; 45533965Sjdp 45633965Sjdp default: 45733965Sjdp (*_bfd_error_handler) 458218822Sdim (_("%B:%u: unrecognized ihex type %u in Intel Hex file"), 459218822Sdim abfd, lineno, type); 46033965Sjdp bfd_set_error (bfd_error_bad_value); 46133965Sjdp goto error_return; 46233965Sjdp } 46333965Sjdp } 46433965Sjdp } 46533965Sjdp 46633965Sjdp if (error) 46733965Sjdp goto error_return; 46833965Sjdp 46933965Sjdp if (buf != NULL) 47033965Sjdp free (buf); 47133965Sjdp 472130561Sobrien return TRUE; 47333965Sjdp 47433965Sjdp error_return: 47533965Sjdp if (buf != NULL) 47633965Sjdp free (buf); 477130561Sobrien return FALSE; 47833965Sjdp} 47933965Sjdp 48033965Sjdp/* Try to recognize an Intel Hex file. */ 48133965Sjdp 48233965Sjdpstatic const bfd_target * 483218822Sdimihex_object_p (bfd *abfd) 48433965Sjdp{ 485218822Sdim void * tdata_save; 48633965Sjdp bfd_byte b[9]; 48733965Sjdp unsigned int i; 48833965Sjdp unsigned int type; 48933965Sjdp 49033965Sjdp ihex_init (); 49133965Sjdp 49233965Sjdp if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0) 49333965Sjdp return NULL; 49489857Sobrien if (bfd_bread (b, (bfd_size_type) 9, abfd) != 9) 49533965Sjdp { 49633965Sjdp if (bfd_get_error () == bfd_error_file_truncated) 49733965Sjdp bfd_set_error (bfd_error_wrong_format); 49833965Sjdp return NULL; 49933965Sjdp } 50033965Sjdp 50133965Sjdp if (b[0] != ':') 50233965Sjdp { 50333965Sjdp bfd_set_error (bfd_error_wrong_format); 50433965Sjdp return NULL; 50533965Sjdp } 50633965Sjdp 50733965Sjdp for (i = 1; i < 9; i++) 50833965Sjdp { 50933965Sjdp if (! ISHEX (b[i])) 51033965Sjdp { 51133965Sjdp bfd_set_error (bfd_error_wrong_format); 51233965Sjdp return NULL; 51333965Sjdp } 51433965Sjdp } 51533965Sjdp 51633965Sjdp type = HEX2 (b + 7); 51733965Sjdp if (type > 5) 51833965Sjdp { 51933965Sjdp bfd_set_error (bfd_error_wrong_format); 52033965Sjdp return NULL; 52133965Sjdp } 52233965Sjdp 52333965Sjdp /* OK, it looks like it really is an Intel Hex file. */ 524104834Sobrien tdata_save = abfd->tdata.any; 525104834Sobrien if (! ihex_mkobject (abfd) || ! ihex_scan (abfd)) 526104834Sobrien { 527104834Sobrien if (abfd->tdata.any != tdata_save && abfd->tdata.any != NULL) 528104834Sobrien bfd_release (abfd, abfd->tdata.any); 529104834Sobrien abfd->tdata.any = tdata_save; 530104834Sobrien return NULL; 531104834Sobrien } 53233965Sjdp 53333965Sjdp return abfd->xvec; 53433965Sjdp} 53533965Sjdp 53633965Sjdp/* Read the contents of a section in an Intel Hex file. */ 53733965Sjdp 538130561Sobrienstatic bfd_boolean 539218822Sdimihex_read_section (bfd *abfd, asection *section, bfd_byte *contents) 54033965Sjdp{ 54133965Sjdp int c; 54233965Sjdp bfd_byte *p; 54333965Sjdp bfd_byte *buf = NULL; 54433965Sjdp size_t bufsize; 545130561Sobrien bfd_boolean error; 54633965Sjdp 54733965Sjdp if (bfd_seek (abfd, section->filepos, SEEK_SET) != 0) 54833965Sjdp goto error_return; 54933965Sjdp 55033965Sjdp p = contents; 55133965Sjdp bufsize = 0; 552130561Sobrien error = FALSE; 55333965Sjdp while ((c = ihex_get_byte (abfd, &error)) != EOF) 55433965Sjdp { 55533965Sjdp char hdr[8]; 55633965Sjdp unsigned int len; 55733965Sjdp unsigned int type; 55833965Sjdp unsigned int i; 55933965Sjdp 56033965Sjdp if (c == '\r' || c == '\n') 56133965Sjdp continue; 56233965Sjdp 56333965Sjdp /* This is called after ihex_scan has succeeded, so we ought to 56433965Sjdp know the exact format. */ 56533965Sjdp BFD_ASSERT (c == ':'); 56633965Sjdp 56789857Sobrien if (bfd_bread (hdr, (bfd_size_type) 8, abfd) != 8) 56833965Sjdp goto error_return; 56933965Sjdp 57033965Sjdp len = HEX2 (hdr); 57133965Sjdp type = HEX2 (hdr + 6); 57233965Sjdp 57333965Sjdp /* We should only see type 0 records here. */ 57433965Sjdp if (type != 0) 57533965Sjdp { 57633965Sjdp (*_bfd_error_handler) 577218822Sdim (_("%B: internal error in ihex_read_section"), abfd); 57833965Sjdp bfd_set_error (bfd_error_bad_value); 57933965Sjdp goto error_return; 58033965Sjdp } 58133965Sjdp 58233965Sjdp if (len * 2 > bufsize) 58333965Sjdp { 584218822Sdim buf = bfd_realloc (buf, (bfd_size_type) len * 2); 58533965Sjdp if (buf == NULL) 58633965Sjdp goto error_return; 58733965Sjdp bufsize = len * 2; 58833965Sjdp } 58933965Sjdp 59089857Sobrien if (bfd_bread (buf, (bfd_size_type) len * 2, abfd) != len * 2) 59133965Sjdp goto error_return; 59233965Sjdp 59333965Sjdp for (i = 0; i < len; i++) 59433965Sjdp *p++ = HEX2 (buf + 2 * i); 595218822Sdim if ((bfd_size_type) (p - contents) >= section->size) 59633965Sjdp { 59733965Sjdp /* We've read everything in the section. */ 59833965Sjdp if (buf != NULL) 59933965Sjdp free (buf); 600130561Sobrien return TRUE; 60133965Sjdp } 60233965Sjdp 60333965Sjdp /* Skip the checksum. */ 60489857Sobrien if (bfd_bread (buf, (bfd_size_type) 2, abfd) != 2) 60533965Sjdp goto error_return; 60633965Sjdp } 60733965Sjdp 608218822Sdim if ((bfd_size_type) (p - contents) < section->size) 60933965Sjdp { 61033965Sjdp (*_bfd_error_handler) 611218822Sdim (_("%B: bad section length in ihex_read_section"), abfd); 61233965Sjdp bfd_set_error (bfd_error_bad_value); 61333965Sjdp goto error_return; 61433965Sjdp } 61533965Sjdp 61633965Sjdp if (buf != NULL) 61733965Sjdp free (buf); 61833965Sjdp 619130561Sobrien return TRUE; 62033965Sjdp 62133965Sjdp error_return: 62233965Sjdp if (buf != NULL) 62333965Sjdp free (buf); 624130561Sobrien return FALSE; 62533965Sjdp} 62633965Sjdp 62733965Sjdp/* Get the contents of a section in an Intel Hex file. */ 62833965Sjdp 629130561Sobrienstatic bfd_boolean 630218822Sdimihex_get_section_contents (bfd *abfd, 631218822Sdim asection *section, 632218822Sdim void * location, 633218822Sdim file_ptr offset, 634218822Sdim bfd_size_type count) 63533965Sjdp{ 63633965Sjdp if (section->used_by_bfd == NULL) 63733965Sjdp { 638218822Sdim section->used_by_bfd = bfd_alloc (abfd, section->size); 63933965Sjdp if (section->used_by_bfd == NULL) 640130561Sobrien return FALSE; 64133965Sjdp if (! ihex_read_section (abfd, section, section->used_by_bfd)) 642130561Sobrien return FALSE; 64333965Sjdp } 64433965Sjdp 64533965Sjdp memcpy (location, (bfd_byte *) section->used_by_bfd + offset, 64633965Sjdp (size_t) count); 64733965Sjdp 648130561Sobrien return TRUE; 64933965Sjdp} 65033965Sjdp 65133965Sjdp/* Set the contents of a section in an Intel Hex file. */ 65233965Sjdp 653130561Sobrienstatic bfd_boolean 654218822Sdimihex_set_section_contents (bfd *abfd, 655218822Sdim asection *section, 656218822Sdim const void * location, 657218822Sdim file_ptr offset, 658218822Sdim bfd_size_type count) 65933965Sjdp{ 66033965Sjdp struct ihex_data_list *n; 66133965Sjdp bfd_byte *data; 66233965Sjdp struct ihex_data_struct *tdata; 66333965Sjdp 66433965Sjdp if (count == 0 66533965Sjdp || (section->flags & SEC_ALLOC) == 0 66633965Sjdp || (section->flags & SEC_LOAD) == 0) 667130561Sobrien return TRUE; 66833965Sjdp 669218822Sdim n = bfd_alloc (abfd, sizeof (* n)); 67033965Sjdp if (n == NULL) 671130561Sobrien return FALSE; 67233965Sjdp 673218822Sdim data = bfd_alloc (abfd, count); 67433965Sjdp if (data == NULL) 675130561Sobrien return FALSE; 67633965Sjdp memcpy (data, location, (size_t) count); 67733965Sjdp 67833965Sjdp n->data = data; 67933965Sjdp n->where = section->lma + offset; 68033965Sjdp n->size = count; 68133965Sjdp 68233965Sjdp /* Sort the records by address. Optimize for the common case of 68333965Sjdp adding a record to the end of the list. */ 68433965Sjdp tdata = abfd->tdata.ihex_data; 68533965Sjdp if (tdata->tail != NULL 68633965Sjdp && n->where >= tdata->tail->where) 68733965Sjdp { 68833965Sjdp tdata->tail->next = n; 68933965Sjdp n->next = NULL; 69033965Sjdp tdata->tail = n; 69133965Sjdp } 69233965Sjdp else 69333965Sjdp { 694218822Sdim struct ihex_data_list **pp; 69533965Sjdp 69633965Sjdp for (pp = &tdata->head; 69733965Sjdp *pp != NULL && (*pp)->where < n->where; 69833965Sjdp pp = &(*pp)->next) 69933965Sjdp ; 70033965Sjdp n->next = *pp; 70133965Sjdp *pp = n; 70233965Sjdp if (n->next == NULL) 70333965Sjdp tdata->tail = n; 70433965Sjdp } 70533965Sjdp 706130561Sobrien return TRUE; 70733965Sjdp} 70833965Sjdp 70933965Sjdp/* Write a record out to an Intel Hex file. */ 71033965Sjdp 711130561Sobrienstatic bfd_boolean 712218822Sdimihex_write_record (bfd *abfd, 713218822Sdim size_t count, 714218822Sdim unsigned int addr, 715218822Sdim unsigned int type, 716218822Sdim bfd_byte *data) 71733965Sjdp{ 71833965Sjdp static const char digs[] = "0123456789ABCDEF"; 71933965Sjdp char buf[9 + CHUNK * 2 + 4]; 72033965Sjdp char *p; 72133965Sjdp unsigned int chksum; 72233965Sjdp unsigned int i; 72389857Sobrien size_t total; 72433965Sjdp 72533965Sjdp#define TOHEX(buf, v) \ 72633965Sjdp ((buf)[0] = digs[((v) >> 4) & 0xf], (buf)[1] = digs[(v) & 0xf]) 72733965Sjdp 72833965Sjdp buf[0] = ':'; 72933965Sjdp TOHEX (buf + 1, count); 73033965Sjdp TOHEX (buf + 3, (addr >> 8) & 0xff); 73133965Sjdp TOHEX (buf + 5, addr & 0xff); 73233965Sjdp TOHEX (buf + 7, type); 73333965Sjdp 73433965Sjdp chksum = count + addr + (addr >> 8) + type; 73533965Sjdp 73633965Sjdp for (i = 0, p = buf + 9; i < count; i++, p += 2, data++) 73733965Sjdp { 73833965Sjdp TOHEX (p, *data); 73933965Sjdp chksum += *data; 74033965Sjdp } 74133965Sjdp 74233965Sjdp TOHEX (p, (- chksum) & 0xff); 74333965Sjdp p[2] = '\r'; 74433965Sjdp p[3] = '\n'; 74533965Sjdp 74689857Sobrien total = 9 + count * 2 + 4; 74789857Sobrien if (bfd_bwrite (buf, (bfd_size_type) total, abfd) != total) 748130561Sobrien return FALSE; 74933965Sjdp 750130561Sobrien return TRUE; 75133965Sjdp} 75233965Sjdp 75333965Sjdp/* Write out an Intel Hex file. */ 75433965Sjdp 755130561Sobrienstatic bfd_boolean 756218822Sdimihex_write_object_contents (bfd *abfd) 75733965Sjdp{ 75833965Sjdp bfd_vma segbase; 75938889Sjdp bfd_vma extbase; 76033965Sjdp struct ihex_data_list *l; 76133965Sjdp 76233965Sjdp segbase = 0; 76338889Sjdp extbase = 0; 76433965Sjdp for (l = abfd->tdata.ihex_data->head; l != NULL; l = l->next) 76533965Sjdp { 76633965Sjdp bfd_vma where; 76733965Sjdp bfd_byte *p; 76833965Sjdp bfd_size_type count; 76933965Sjdp 77033965Sjdp where = l->where; 77133965Sjdp p = l->data; 77233965Sjdp count = l->size; 773218822Sdim 77433965Sjdp while (count > 0) 77533965Sjdp { 77689857Sobrien size_t now; 77789857Sobrien unsigned int rec_addr; 77833965Sjdp 77933965Sjdp now = count; 78089857Sobrien if (count > CHUNK) 78133965Sjdp now = CHUNK; 78233965Sjdp 78338889Sjdp if (where > segbase + extbase + 0xffff) 78433965Sjdp { 78533965Sjdp bfd_byte addr[2]; 78633965Sjdp 78733965Sjdp /* We need a new base address. */ 78833965Sjdp if (where <= 0xfffff) 78933965Sjdp { 79038889Sjdp /* The addresses should be sorted. */ 79138889Sjdp BFD_ASSERT (extbase == 0); 79238889Sjdp 79333965Sjdp segbase = where & 0xf0000; 79433965Sjdp addr[0] = (bfd_byte)(segbase >> 12) & 0xff; 79533965Sjdp addr[1] = (bfd_byte)(segbase >> 4) & 0xff; 79633965Sjdp if (! ihex_write_record (abfd, 2, 0, 2, addr)) 797130561Sobrien return FALSE; 79833965Sjdp } 79933965Sjdp else 80033965Sjdp { 80138889Sjdp /* The extended address record and the extended 80238889Sjdp linear address record are combined, at least by 80338889Sjdp some readers. We need an extended linear address 80438889Sjdp record here, so if we've already written out an 80538889Sjdp extended address record, zero it out to avoid 80638889Sjdp confusion. */ 80738889Sjdp if (segbase != 0) 80833965Sjdp { 80938889Sjdp addr[0] = 0; 81038889Sjdp addr[1] = 0; 81138889Sjdp if (! ihex_write_record (abfd, 2, 0, 2, addr)) 812130561Sobrien return FALSE; 81338889Sjdp segbase = 0; 81438889Sjdp } 81538889Sjdp 81638889Sjdp extbase = where & 0xffff0000; 81738889Sjdp if (where > extbase + 0xffff) 81838889Sjdp { 81933965Sjdp char buf[20]; 82033965Sjdp 82133965Sjdp sprintf_vma (buf, where); 82233965Sjdp (*_bfd_error_handler) 82391041Sobrien (_("%s: address 0x%s out of range for Intel Hex file"), 82433965Sjdp bfd_get_filename (abfd), buf); 82533965Sjdp bfd_set_error (bfd_error_bad_value); 826130561Sobrien return FALSE; 82733965Sjdp } 82838889Sjdp addr[0] = (bfd_byte)(extbase >> 24) & 0xff; 82938889Sjdp addr[1] = (bfd_byte)(extbase >> 16) & 0xff; 83033965Sjdp if (! ihex_write_record (abfd, 2, 0, 4, addr)) 831130561Sobrien return FALSE; 83233965Sjdp } 83333965Sjdp } 83433965Sjdp 83589857Sobrien rec_addr = where - (extbase + segbase); 83694536Sobrien 83794536Sobrien /* Output records shouldn't cross 64K boundaries. */ 83899461Sobrien if (rec_addr + now > 0xffff) 83999461Sobrien now = 0x10000 - rec_addr; 84094536Sobrien 84189857Sobrien if (! ihex_write_record (abfd, now, rec_addr, 0, p)) 842130561Sobrien return FALSE; 84333965Sjdp 84433965Sjdp where += now; 84533965Sjdp p += now; 84633965Sjdp count -= now; 84733965Sjdp } 84833965Sjdp } 84933965Sjdp 85033965Sjdp if (abfd->start_address != 0) 85133965Sjdp { 85233965Sjdp bfd_vma start; 85333965Sjdp bfd_byte startbuf[4]; 85433965Sjdp 85533965Sjdp start = abfd->start_address; 85633965Sjdp 85733965Sjdp if (start <= 0xfffff) 85833965Sjdp { 85933965Sjdp startbuf[0] = (bfd_byte)((start & 0xf0000) >> 12) & 0xff; 86033965Sjdp startbuf[1] = 0; 86133965Sjdp startbuf[2] = (bfd_byte)(start >> 8) & 0xff; 86233965Sjdp startbuf[3] = (bfd_byte)start & 0xff; 86333965Sjdp if (! ihex_write_record (abfd, 4, 0, 3, startbuf)) 864130561Sobrien return FALSE; 86533965Sjdp } 86633965Sjdp else 86733965Sjdp { 86833965Sjdp startbuf[0] = (bfd_byte)(start >> 24) & 0xff; 86933965Sjdp startbuf[1] = (bfd_byte)(start >> 16) & 0xff; 87033965Sjdp startbuf[2] = (bfd_byte)(start >> 8) & 0xff; 87133965Sjdp startbuf[3] = (bfd_byte)start & 0xff; 87233965Sjdp if (! ihex_write_record (abfd, 4, 0, 5, startbuf)) 873130561Sobrien return FALSE; 87433965Sjdp } 87533965Sjdp } 87633965Sjdp 87733965Sjdp if (! ihex_write_record (abfd, 0, 0, 1, NULL)) 878130561Sobrien return FALSE; 87933965Sjdp 880130561Sobrien return TRUE; 88133965Sjdp} 88233965Sjdp 88333965Sjdp/* Set the architecture for the output file. The architecture is 88433965Sjdp irrelevant, so we ignore errors about unknown architectures. */ 88533965Sjdp 886130561Sobrienstatic bfd_boolean 887218822Sdimihex_set_arch_mach (bfd *abfd, 888218822Sdim enum bfd_architecture arch, 889218822Sdim unsigned long mach) 89033965Sjdp{ 89133965Sjdp if (! bfd_default_set_arch_mach (abfd, arch, mach)) 89233965Sjdp { 89333965Sjdp if (arch != bfd_arch_unknown) 894130561Sobrien return FALSE; 89533965Sjdp } 896130561Sobrien return TRUE; 89733965Sjdp} 89833965Sjdp 89933965Sjdp/* Get the size of the headers, for the linker. */ 90033965Sjdp 90133965Sjdpstatic int 902218822Sdimihex_sizeof_headers (bfd *abfd ATTRIBUTE_UNUSED, 903218822Sdim struct bfd_link_info *info ATTRIBUTE_UNUSED) 90433965Sjdp{ 90533965Sjdp return 0; 90633965Sjdp} 90733965Sjdp 90833965Sjdp/* Some random definitions for the target vector. */ 90933965Sjdp 910218822Sdim#define ihex_close_and_cleanup _bfd_generic_close_and_cleanup 911218822Sdim#define ihex_bfd_free_cached_info _bfd_generic_bfd_free_cached_info 912218822Sdim#define ihex_new_section_hook _bfd_generic_new_section_hook 913218822Sdim#define ihex_get_section_contents_in_window _bfd_generic_get_section_contents_in_window 914218822Sdim#define ihex_get_symtab_upper_bound bfd_0l 915218822Sdim#define ihex_canonicalize_symtab ((long (*) (bfd *, asymbol **)) bfd_0l) 916218822Sdim#define ihex_make_empty_symbol _bfd_generic_make_empty_symbol 917218822Sdim#define ihex_print_symbol _bfd_nosymbols_print_symbol 918218822Sdim#define ihex_get_symbol_info _bfd_nosymbols_get_symbol_info 919218822Sdim#define ihex_bfd_is_target_special_symbol ((bfd_boolean (*) (bfd *, asymbol *)) bfd_false) 920218822Sdim#define ihex_bfd_is_local_label_name _bfd_nosymbols_bfd_is_local_label_name 921218822Sdim#define ihex_get_lineno _bfd_nosymbols_get_lineno 922218822Sdim#define ihex_find_nearest_line _bfd_nosymbols_find_nearest_line 923218822Sdim#define ihex_find_inliner_info _bfd_nosymbols_find_inliner_info 924218822Sdim#define ihex_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol 925218822Sdim#define ihex_read_minisymbols _bfd_nosymbols_read_minisymbols 926218822Sdim#define ihex_minisymbol_to_symbol _bfd_nosymbols_minisymbol_to_symbol 927218822Sdim#define ihex_bfd_get_relocated_section_contents bfd_generic_get_relocated_section_contents 928218822Sdim#define ihex_bfd_relax_section bfd_generic_relax_section 929218822Sdim#define ihex_bfd_gc_sections bfd_generic_gc_sections 930218822Sdim#define ihex_bfd_merge_sections bfd_generic_merge_sections 931218822Sdim#define ihex_bfd_is_group_section bfd_generic_is_group_section 932218822Sdim#define ihex_bfd_discard_group bfd_generic_discard_group 933218822Sdim#define ihex_section_already_linked _bfd_generic_section_already_linked 934218822Sdim#define ihex_bfd_link_hash_table_create _bfd_generic_link_hash_table_create 935218822Sdim#define ihex_bfd_link_hash_table_free _bfd_generic_link_hash_table_free 936218822Sdim#define ihex_bfd_link_add_symbols _bfd_generic_link_add_symbols 937218822Sdim#define ihex_bfd_link_just_syms _bfd_generic_link_just_syms 938218822Sdim#define ihex_bfd_final_link _bfd_generic_final_link 939218822Sdim#define ihex_bfd_link_split_section _bfd_generic_link_split_section 94033965Sjdp 94133965Sjdp/* The Intel Hex target vector. */ 94233965Sjdp 94333965Sjdpconst bfd_target ihex_vec = 94433965Sjdp{ 945218822Sdim "ihex", /* Name. */ 94633965Sjdp bfd_target_ihex_flavour, 947218822Sdim BFD_ENDIAN_UNKNOWN, /* Target byte order. */ 948218822Sdim BFD_ENDIAN_UNKNOWN, /* Target headers byte order. */ 949218822Sdim 0, /* Object flags. */ 950218822Sdim (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD), /* Section flags. */ 951218822Sdim 0, /* Leading underscore. */ 952218822Sdim ' ', /* AR_pad_char. */ 953218822Sdim 16, /* AR_max_namelen. */ 95433965Sjdp bfd_getb64, bfd_getb_signed_64, bfd_putb64, 95533965Sjdp bfd_getb32, bfd_getb_signed_32, bfd_putb32, 956218822Sdim bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* Data. */ 95733965Sjdp bfd_getb64, bfd_getb_signed_64, bfd_putb64, 95833965Sjdp bfd_getb32, bfd_getb_signed_32, bfd_putb32, 959218822Sdim bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* Headers. */ 96033965Sjdp 96133965Sjdp { 96233965Sjdp _bfd_dummy_target, 963218822Sdim ihex_object_p, /* bfd_check_format. */ 96433965Sjdp _bfd_dummy_target, 96533965Sjdp _bfd_dummy_target, 96633965Sjdp }, 96733965Sjdp { 96833965Sjdp bfd_false, 96933965Sjdp ihex_mkobject, 97033965Sjdp _bfd_generic_mkarchive, 97133965Sjdp bfd_false, 97233965Sjdp }, 973218822Sdim { /* bfd_write_contents. */ 97433965Sjdp bfd_false, 97533965Sjdp ihex_write_object_contents, 97633965Sjdp _bfd_write_archive_contents, 97733965Sjdp bfd_false, 97833965Sjdp }, 97933965Sjdp 98033965Sjdp BFD_JUMP_TABLE_GENERIC (ihex), 98133965Sjdp BFD_JUMP_TABLE_COPY (_bfd_generic), 98233965Sjdp BFD_JUMP_TABLE_CORE (_bfd_nocore), 98333965Sjdp BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive), 98433965Sjdp BFD_JUMP_TABLE_SYMBOLS (ihex), 985218822Sdim BFD_JUMP_TABLE_RELOCS (_bfd_norelocs), 98633965Sjdp BFD_JUMP_TABLE_WRITE (ihex), 98733965Sjdp BFD_JUMP_TABLE_LINK (ihex), 98833965Sjdp BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic), 98933965Sjdp 99060484Sobrien NULL, 99189857Sobrien 992218822Sdim NULL 99333965Sjdp}; 994