Back to index

cell-binutils  2.17cvs20070401
ihex.c
Go to the documentation of this file.
00001 /* BFD back-end for Intel Hex objects.
00002    Copyright 1995, 1996, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
00003    2006, 2007 Free Software Foundation, Inc.
00004    Written by Ian Lance Taylor of Cygnus Support <ian@cygnus.com>.
00005 
00006    This file is part of BFD, the Binary File Descriptor library.
00007 
00008    This program is free software; you can redistribute it and/or modify
00009    it under the terms of the GNU General Public License as published by
00010    the Free Software Foundation; either version 2 of the License, or
00011    (at your option) any later version.
00012 
00013    This program is distributed in the hope that it will be useful,
00014    but WITHOUT ANY WARRANTY; without even the implied warranty of
00015    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016    GNU General Public License for more details.
00017 
00018    You should have received a copy of the GNU General Public License
00019    along with this program; if not, write to the Free Software
00020    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
00021 
00022 /* This is what Intel Hex files look like:
00023 
00024 1. INTEL FORMATS
00025 
00026 A. Intel 1
00027 
00028    16-bit address-field format, for files 64k bytes in length or less.
00029 
00030    DATA RECORD
00031    Byte 1     Header = colon(:)
00032    2..3              The number of data bytes in hex notation
00033    4..5              High byte of the record load address
00034    6..7              Low byte of the record load address
00035    8..9              Record type, must be "00"
00036    10..x      Data bytes in hex notation:
00037        x = (number of bytes - 1) * 2 + 11
00038    x+1..x+2   Checksum in hex notation
00039    x+3..x+4   Carriage return, line feed
00040 
00041    END RECORD
00042    Byte 1     Header = colon (:)
00043    2..3              The byte count, must be "00"
00044    4..7              Transfer-address (usually "0000")
00045               the jump-to address, execution start address
00046    8..9              Record type, must be "01"
00047    10..11     Checksum, in hex notation
00048    12..13     Carriage return, line feed
00049 
00050 B. INTEL 2
00051 
00052    MCS-86 format, using a 20-bit address for files larger than 64K bytes.
00053 
00054    DATA RECORD
00055    Byte 1     Header = colon (:)
00056    2..3              The byte count of this record, hex notation
00057    4..5              High byte of the record load address
00058    6..7              Low byte of the record load address
00059    8..9              Record type, must be "00"
00060    10..x      The data bytes in hex notation:
00061        x = (number of data bytes - 1) * 2 + 11
00062    x+1..x+2   Checksum in hex notation
00063    x+3..x+4   Carriage return, line feed
00064 
00065    EXTENDED ADDRESS RECORD
00066    Byte 1     Header = colon(:)
00067    2..3              The byte count, must be "02"
00068    4..7              Load address, must be "0000"
00069    8..9              Record type, must be "02"
00070    10..11     High byte of the offset address
00071    12..13     Low byte of the offset address
00072    14..15     Checksum in hex notation
00073    16..17     Carriage return, line feed
00074 
00075    The checksums are the two's complement of the 8-bit sum
00076    without carry of the byte count, offset address, and the
00077    record type.
00078 
00079    START ADDRESS RECORD
00080    Byte 1     Header = colon (:)
00081    2..3              The byte count, must be "04"
00082    4..7              Load address, must be "0000"
00083    8..9              Record type, must be "03"
00084    10..13     8086 CS value
00085    14..17     8086 IP value
00086    18..19     Checksum in hex notation
00087    20..21     Carriage return, line feed
00088 
00089 Another document reports these additional types:
00090 
00091    EXTENDED LINEAR ADDRESS RECORD
00092    Byte 1     Header = colon (:)
00093    2..3              The byte count, must be "02"
00094    4..7              Load address, must be "0000"
00095    8..9              Record type, must be "04"
00096    10..13     Upper 16 bits of address of subsequent records
00097    14..15     Checksum in hex notation
00098    16..17     Carriage return, line feed
00099 
00100    START LINEAR ADDRESS RECORD
00101    Byte 1     Header = colon (:)
00102    2..3              The byte count, must be "02"
00103    4..7              Load address, must be "0000"
00104    8..9              Record type, must be "05"
00105    10..13     Upper 16 bits of start address
00106    14..15     Checksum in hex notation
00107    16..17     Carriage return, line feed
00108 
00109 The MRI compiler uses this, which is a repeat of type 5:
00110 
00111   EXTENDED START RECORD
00112    Byte 1     Header = colon (:)
00113    2..3              The byte count, must be "04"
00114    4..7              Load address, must be "0000"
00115    8..9              Record type, must be "05"
00116    10..13     Upper 16 bits of start address
00117    14..17     Lower 16 bits of start address
00118    18..19     Checksum in hex notation
00119    20..21     Carriage return, line feed.  */
00120 
00121 #include "bfd.h"
00122 #include "sysdep.h"
00123 #include "libbfd.h"
00124 #include "libiberty.h"
00125 #include "safe-ctype.h"
00126 
00127 /* The number of bytes we put on one line during output.  */
00128 
00129 #define CHUNK 16
00130 
00131 /* Macros for converting between hex and binary.  */
00132 
00133 #define NIBBLE(x)    (hex_value (x))
00134 #define HEX2(buffer) ((NIBBLE ((buffer)[0]) << 4) + NIBBLE ((buffer)[1]))
00135 #define HEX4(buffer) ((HEX2 (buffer) << 8) + HEX2 ((buffer) + 2))
00136 #define ISHEX(x)     (hex_p (x))
00137 
00138 /* When we write out an ihex value, the values can not be output as
00139    they are seen.  Instead, we hold them in memory in this structure.  */
00140 
00141 struct ihex_data_list
00142 {
00143   struct ihex_data_list *next;
00144   bfd_byte *data;
00145   bfd_vma where;
00146   bfd_size_type size;
00147 };
00148 
00149 /* The ihex tdata information.  */
00150 
00151 struct ihex_data_struct
00152 {
00153   struct ihex_data_list *head;
00154   struct ihex_data_list *tail;
00155 };
00156 
00157 /* Initialize by filling in the hex conversion array.  */
00158 
00159 static void
00160 ihex_init (void)
00161 {
00162   static bfd_boolean inited;
00163 
00164   if (! inited)
00165     {
00166       inited = TRUE;
00167       hex_init ();
00168     }
00169 }
00170 
00171 /* Create an ihex object.  */
00172 
00173 static bfd_boolean
00174 ihex_mkobject (bfd *abfd)
00175 {
00176   struct ihex_data_struct *tdata;
00177 
00178   tdata = bfd_alloc (abfd, sizeof (* tdata));
00179   if (tdata == NULL)
00180     return FALSE;
00181 
00182   abfd->tdata.ihex_data = tdata;
00183   tdata->head = NULL;
00184   tdata->tail = NULL;
00185   return TRUE;
00186 }
00187 
00188 /* Read a byte from a BFD.  Set *ERRORPTR if an error occurred.
00189    Return EOF on error or end of file.  */
00190 
00191 static INLINE int
00192 ihex_get_byte (bfd *abfd, bfd_boolean *errorptr)
00193 {
00194   bfd_byte c;
00195 
00196   if (bfd_bread (&c, (bfd_size_type) 1, abfd) != 1)
00197     {
00198       if (bfd_get_error () != bfd_error_file_truncated)
00199        *errorptr = TRUE;
00200       return EOF;
00201     }
00202 
00203   return (int) (c & 0xff);
00204 }
00205 
00206 /* Report a problem in an Intel Hex file.  */
00207 
00208 static void
00209 ihex_bad_byte (bfd *abfd, unsigned int lineno, int c, bfd_boolean error)
00210 {
00211   if (c == EOF)
00212     {
00213       if (! error)
00214        bfd_set_error (bfd_error_file_truncated);
00215     }
00216   else
00217     {
00218       char buf[10];
00219 
00220       if (! ISPRINT (c))
00221        sprintf (buf, "\\%03o", (unsigned int) c);
00222       else
00223        {
00224          buf[0] = c;
00225          buf[1] = '\0';
00226        }
00227       (*_bfd_error_handler)
00228        (_("%B:%d: unexpected character `%s' in Intel Hex file"),
00229         abfd, lineno, buf);
00230       bfd_set_error (bfd_error_bad_value);
00231     }
00232 }
00233 
00234 /* Read an Intel hex file and turn it into sections.  We create a new
00235    section for each contiguous set of bytes.  */
00236 
00237 static bfd_boolean
00238 ihex_scan (bfd *abfd)
00239 {
00240   bfd_vma segbase;
00241   bfd_vma extbase;
00242   asection *sec;
00243   unsigned int lineno;
00244   bfd_boolean error;
00245   bfd_byte *buf = NULL;
00246   size_t bufsize;
00247   int c;
00248 
00249   if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
00250     goto error_return;
00251 
00252   abfd->start_address = 0;
00253 
00254   segbase = 0;
00255   extbase = 0;
00256   sec = NULL;
00257   lineno = 1;
00258   error = FALSE;
00259   bufsize = 0;
00260 
00261   while ((c = ihex_get_byte (abfd, &error)) != EOF)
00262     {
00263       if (c == '\r')
00264        continue;
00265       else if (c == '\n')
00266        {
00267          ++lineno;
00268          continue;
00269        }
00270       else if (c != ':')
00271        {
00272          ihex_bad_byte (abfd, lineno, c, error);
00273          goto error_return;
00274        }
00275       else
00276        {
00277          file_ptr pos;
00278          char hdr[8];
00279          unsigned int i;
00280          unsigned int len;
00281          bfd_vma addr;
00282          unsigned int type;
00283          unsigned int chars;
00284          unsigned int chksum;
00285 
00286          /* This is a data record.  */
00287          pos = bfd_tell (abfd) - 1;
00288 
00289          /* Read the header bytes.  */
00290          if (bfd_bread (hdr, (bfd_size_type) 8, abfd) != 8)
00291            goto error_return;
00292 
00293          for (i = 0; i < 8; i++)
00294            {
00295              if (! ISHEX (hdr[i]))
00296               {
00297                 ihex_bad_byte (abfd, lineno, hdr[i], error);
00298                 goto error_return;
00299               }
00300            }
00301 
00302          len = HEX2 (hdr);
00303          addr = HEX4 (hdr + 2);
00304          type = HEX2 (hdr + 6);
00305 
00306          /* Read the data bytes.  */
00307          chars = len * 2 + 2;
00308          if (chars >= bufsize)
00309            {
00310              buf = bfd_realloc (buf, (bfd_size_type) chars);
00311              if (buf == NULL)
00312               goto error_return;
00313              bufsize = chars;
00314            }
00315 
00316          if (bfd_bread (buf, (bfd_size_type) chars, abfd) != chars)
00317            goto error_return;
00318 
00319          for (i = 0; i < chars; i++)
00320            {
00321              if (! ISHEX (buf[i]))
00322               {
00323                 ihex_bad_byte (abfd, lineno, hdr[i], error);
00324                 goto error_return;
00325               }
00326            }
00327 
00328          /* Check the checksum.  */
00329          chksum = len + addr + (addr >> 8) + type;
00330          for (i = 0; i < len; i++)
00331            chksum += HEX2 (buf + 2 * i);
00332          if (((- chksum) & 0xff) != (unsigned int) HEX2 (buf + 2 * i))
00333            {
00334              (*_bfd_error_handler)
00335               (_("%B:%u: bad checksum in Intel Hex file (expected %u, found %u)"),
00336                abfd, lineno,
00337                (- chksum) & 0xff, (unsigned int) HEX2 (buf + 2 * i));
00338              bfd_set_error (bfd_error_bad_value);
00339              goto error_return;
00340            }
00341 
00342          switch (type)
00343            {
00344            case 0:
00345              /* This is a data record.  */
00346              if (sec != NULL
00347                 && sec->vma + sec->size == extbase + segbase + addr)
00348               {
00349                 /* This data goes at the end of the section we are
00350                      currently building.  */
00351                 sec->size += len;
00352               }
00353              else if (len > 0)
00354               {
00355                 char secbuf[20];
00356                 char *secname;
00357                 bfd_size_type amt;
00358                 flagword flags;
00359 
00360                 sprintf (secbuf, ".sec%d", bfd_count_sections (abfd) + 1);
00361                 amt = strlen (secbuf) + 1;
00362                 secname = bfd_alloc (abfd, amt);
00363                 if (secname == NULL)
00364                   goto error_return;
00365                 strcpy (secname, secbuf);
00366                 flags = SEC_HAS_CONTENTS | SEC_LOAD | SEC_ALLOC;
00367                 sec = bfd_make_section_with_flags (abfd, secname, flags);
00368                 if (sec == NULL)
00369                   goto error_return;
00370                 sec->vma = extbase + segbase + addr;
00371                 sec->lma = extbase + segbase + addr;
00372                 sec->size = len;
00373                 sec->filepos = pos;
00374               }
00375              break;
00376 
00377            case 1:
00378              /* An end record.  */
00379              if (abfd->start_address == 0)
00380               abfd->start_address = addr;
00381              if (buf != NULL)
00382               free (buf);
00383              return TRUE;
00384 
00385            case 2:
00386              /* An extended address record.  */
00387              if (len != 2)
00388               {
00389                 (*_bfd_error_handler)
00390                   (_("%B:%u: bad extended address record length in Intel Hex file"),
00391                    abfd, lineno);
00392                 bfd_set_error (bfd_error_bad_value);
00393                 goto error_return;
00394               }
00395 
00396              segbase = HEX4 (buf) << 4;
00397 
00398              sec = NULL;
00399 
00400              break;
00401 
00402            case 3:
00403              /* An extended start address record.  */
00404              if (len != 4)
00405               {
00406                 (*_bfd_error_handler)
00407                   (_("%B:%u: bad extended start address length in Intel Hex file"),
00408                    abfd, lineno);
00409                 bfd_set_error (bfd_error_bad_value);
00410                 goto error_return;
00411               }
00412 
00413              abfd->start_address += (HEX4 (buf) << 4) + HEX4 (buf + 4);
00414 
00415              sec = NULL;
00416 
00417              break;
00418 
00419            case 4:
00420              /* An extended linear address record.  */
00421              if (len != 2)
00422               {
00423                 (*_bfd_error_handler)
00424                   (_("%B:%u: bad extended linear address record length in Intel Hex file"),
00425                    abfd, lineno);
00426                 bfd_set_error (bfd_error_bad_value);
00427                 goto error_return;
00428               }
00429 
00430              extbase = HEX4 (buf) << 16;
00431 
00432              sec = NULL;
00433 
00434              break;
00435 
00436            case 5:
00437              /* An extended linear start address record.  */
00438              if (len != 2 && len != 4)
00439               {
00440                 (*_bfd_error_handler)
00441                   (_("%B:%u: bad extended linear start address length in Intel Hex file"),
00442                    abfd, lineno);
00443                 bfd_set_error (bfd_error_bad_value);
00444                 goto error_return;
00445               }
00446 
00447              if (len == 2)
00448               abfd->start_address += HEX4 (buf) << 16;
00449              else
00450               abfd->start_address = (HEX4 (buf) << 16) + HEX4 (buf + 4);
00451 
00452              sec = NULL;
00453 
00454              break;
00455 
00456            default:
00457              (*_bfd_error_handler)
00458               (_("%B:%u: unrecognized ihex type %u in Intel Hex file"),
00459                abfd, lineno, type);
00460              bfd_set_error (bfd_error_bad_value);
00461              goto error_return;
00462            }
00463        }
00464     }
00465 
00466   if (error)
00467     goto error_return;
00468 
00469   if (buf != NULL)
00470     free (buf);
00471 
00472   return TRUE;
00473 
00474  error_return:
00475   if (buf != NULL)
00476     free (buf);
00477   return FALSE;
00478 }
00479 
00480 /* Try to recognize an Intel Hex file.  */
00481 
00482 static const bfd_target *
00483 ihex_object_p (bfd *abfd)
00484 {
00485   void * tdata_save;
00486   bfd_byte b[9];
00487   unsigned int i;
00488   unsigned int type;
00489 
00490   ihex_init ();
00491 
00492   if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
00493     return NULL;
00494   if (bfd_bread (b, (bfd_size_type) 9, abfd) != 9)
00495     {
00496       if (bfd_get_error () == bfd_error_file_truncated)
00497        bfd_set_error (bfd_error_wrong_format);
00498       return NULL;
00499     }
00500 
00501   if (b[0] != ':')
00502     {
00503       bfd_set_error (bfd_error_wrong_format);
00504       return NULL;
00505     }
00506 
00507   for (i = 1; i < 9; i++)
00508     {
00509       if (! ISHEX (b[i]))
00510        {
00511          bfd_set_error (bfd_error_wrong_format);
00512          return NULL;
00513        }
00514     }
00515 
00516   type = HEX2 (b + 7);
00517   if (type > 5)
00518     {
00519       bfd_set_error (bfd_error_wrong_format);
00520       return NULL;
00521     }
00522 
00523   /* OK, it looks like it really is an Intel Hex file.  */
00524   tdata_save = abfd->tdata.any;
00525   if (! ihex_mkobject (abfd) || ! ihex_scan (abfd))
00526     {
00527       if (abfd->tdata.any != tdata_save && abfd->tdata.any != NULL)
00528        bfd_release (abfd, abfd->tdata.any);
00529       abfd->tdata.any = tdata_save;
00530       return NULL;
00531     }
00532 
00533   return abfd->xvec;
00534 }
00535 
00536 /* Read the contents of a section in an Intel Hex file.  */
00537 
00538 static bfd_boolean
00539 ihex_read_section (bfd *abfd, asection *section, bfd_byte *contents)
00540 {
00541   int c;
00542   bfd_byte *p;
00543   bfd_byte *buf = NULL;
00544   size_t bufsize;
00545   bfd_boolean error;
00546 
00547   if (bfd_seek (abfd, section->filepos, SEEK_SET) != 0)
00548     goto error_return;
00549 
00550   p = contents;
00551   bufsize = 0;
00552   error = FALSE;
00553   while ((c = ihex_get_byte (abfd, &error)) != EOF)
00554     {
00555       char hdr[8];
00556       unsigned int len;
00557       unsigned int type;
00558       unsigned int i;
00559 
00560       if (c == '\r' || c == '\n')
00561        continue;
00562 
00563       /* This is called after ihex_scan has succeeded, so we ought to
00564          know the exact format.  */
00565       BFD_ASSERT (c == ':');
00566 
00567       if (bfd_bread (hdr, (bfd_size_type) 8, abfd) != 8)
00568        goto error_return;
00569 
00570       len = HEX2 (hdr);
00571       type = HEX2 (hdr + 6);
00572 
00573       /* We should only see type 0 records here.  */
00574       if (type != 0)
00575        {
00576          (*_bfd_error_handler)
00577            (_("%B: internal error in ihex_read_section"), abfd);
00578          bfd_set_error (bfd_error_bad_value);
00579          goto error_return;
00580        }
00581 
00582       if (len * 2 > bufsize)
00583        {
00584          buf = bfd_realloc (buf, (bfd_size_type) len * 2);
00585          if (buf == NULL)
00586            goto error_return;
00587          bufsize = len * 2;
00588        }
00589 
00590       if (bfd_bread (buf, (bfd_size_type) len * 2, abfd) != len * 2)
00591        goto error_return;
00592 
00593       for (i = 0; i < len; i++)
00594        *p++ = HEX2 (buf + 2 * i);
00595       if ((bfd_size_type) (p - contents) >= section->size)
00596        {
00597          /* We've read everything in the section.  */
00598          if (buf != NULL)
00599            free (buf);
00600          return TRUE;
00601        }
00602 
00603       /* Skip the checksum.  */
00604       if (bfd_bread (buf, (bfd_size_type) 2, abfd) != 2)
00605        goto error_return;
00606     }
00607 
00608   if ((bfd_size_type) (p - contents) < section->size)
00609     {
00610       (*_bfd_error_handler)
00611        (_("%B: bad section length in ihex_read_section"), abfd);
00612       bfd_set_error (bfd_error_bad_value);
00613       goto error_return;
00614     }
00615 
00616   if (buf != NULL)
00617     free (buf);
00618 
00619   return TRUE;
00620 
00621  error_return:
00622   if (buf != NULL)
00623     free (buf);
00624   return FALSE;
00625 }
00626 
00627 /* Get the contents of a section in an Intel Hex file.  */
00628 
00629 static bfd_boolean
00630 ihex_get_section_contents (bfd *abfd,
00631                         asection *section,
00632                         void * location,
00633                         file_ptr offset,
00634                         bfd_size_type count)
00635 {
00636   if (section->used_by_bfd == NULL)
00637     {
00638       section->used_by_bfd = bfd_alloc (abfd, section->size);
00639       if (section->used_by_bfd == NULL)
00640        return FALSE;
00641       if (! ihex_read_section (abfd, section, section->used_by_bfd))
00642        return FALSE;
00643     }
00644 
00645   memcpy (location, (bfd_byte *) section->used_by_bfd + offset,
00646          (size_t) count);
00647 
00648   return TRUE;
00649 }
00650 
00651 /* Set the contents of a section in an Intel Hex file.  */
00652 
00653 static bfd_boolean
00654 ihex_set_section_contents (bfd *abfd,
00655                         asection *section,
00656                         const void * location,
00657                         file_ptr offset,
00658                         bfd_size_type count)
00659 {
00660   struct ihex_data_list *n;
00661   bfd_byte *data;
00662   struct ihex_data_struct *tdata;
00663 
00664   if (count == 0
00665       || (section->flags & SEC_ALLOC) == 0
00666       || (section->flags & SEC_LOAD) == 0)
00667     return TRUE;
00668 
00669   n = bfd_alloc (abfd, sizeof (* n));
00670   if (n == NULL)
00671     return FALSE;
00672 
00673   data = bfd_alloc (abfd, count);
00674   if (data == NULL)
00675     return FALSE;
00676   memcpy (data, location, (size_t) count);
00677 
00678   n->data = data;
00679   n->where = section->lma + offset;
00680   n->size = count;
00681 
00682   /* Sort the records by address.  Optimize for the common case of
00683      adding a record to the end of the list.  */
00684   tdata = abfd->tdata.ihex_data;
00685   if (tdata->tail != NULL
00686       && n->where >= tdata->tail->where)
00687     {
00688       tdata->tail->next = n;
00689       n->next = NULL;
00690       tdata->tail = n;
00691     }
00692   else
00693     {
00694       struct ihex_data_list **pp;
00695 
00696       for (pp = &tdata->head;
00697           *pp != NULL && (*pp)->where < n->where;
00698           pp = &(*pp)->next)
00699        ;
00700       n->next = *pp;
00701       *pp = n;
00702       if (n->next == NULL)
00703        tdata->tail = n;
00704     }
00705 
00706   return TRUE;
00707 }
00708 
00709 /* Write a record out to an Intel Hex file.  */
00710 
00711 static bfd_boolean
00712 ihex_write_record (bfd *abfd,
00713                  size_t count,
00714                  unsigned int addr,
00715                  unsigned int type,
00716                  bfd_byte *data)
00717 {
00718   static const char digs[] = "0123456789ABCDEF";
00719   char buf[9 + CHUNK * 2 + 4];
00720   char *p;
00721   unsigned int chksum;
00722   unsigned int i;
00723   size_t total;
00724 
00725 #define TOHEX(buf, v) \
00726   ((buf)[0] = digs[((v) >> 4) & 0xf], (buf)[1] = digs[(v) & 0xf])
00727 
00728   buf[0] = ':';
00729   TOHEX (buf + 1, count);
00730   TOHEX (buf + 3, (addr >> 8) & 0xff);
00731   TOHEX (buf + 5, addr & 0xff);
00732   TOHEX (buf + 7, type);
00733 
00734   chksum = count + addr + (addr >> 8) + type;
00735 
00736   for (i = 0, p = buf + 9; i < count; i++, p += 2, data++)
00737     {
00738       TOHEX (p, *data);
00739       chksum += *data;
00740     }
00741 
00742   TOHEX (p, (- chksum) & 0xff);
00743   p[2] = '\r';
00744   p[3] = '\n';
00745 
00746   total = 9 + count * 2 + 4;
00747   if (bfd_bwrite (buf, (bfd_size_type) total, abfd) != total)
00748     return FALSE;
00749 
00750   return TRUE;
00751 }
00752 
00753 /* Write out an Intel Hex file.  */
00754 
00755 static bfd_boolean
00756 ihex_write_object_contents (bfd *abfd)
00757 {
00758   bfd_vma segbase;
00759   bfd_vma extbase;
00760   struct ihex_data_list *l;
00761 
00762   segbase = 0;
00763   extbase = 0;
00764   for (l = abfd->tdata.ihex_data->head; l != NULL; l = l->next)
00765     {
00766       bfd_vma where;
00767       bfd_byte *p;
00768       bfd_size_type count;
00769 
00770       where = l->where;
00771       p = l->data;
00772       count = l->size;
00773 
00774       while (count > 0)
00775        {
00776          size_t now;
00777          unsigned int rec_addr;
00778 
00779          now = count;
00780          if (count > CHUNK)
00781            now = CHUNK;
00782 
00783          if (where > segbase + extbase + 0xffff)
00784            {
00785              bfd_byte addr[2];
00786 
00787              /* We need a new base address.  */
00788              if (where <= 0xfffff)
00789               {
00790                 /* The addresses should be sorted.  */
00791                 BFD_ASSERT (extbase == 0);
00792 
00793                 segbase = where & 0xf0000;
00794                 addr[0] = (bfd_byte)(segbase >> 12) & 0xff;
00795                 addr[1] = (bfd_byte)(segbase >> 4) & 0xff;
00796                 if (! ihex_write_record (abfd, 2, 0, 2, addr))
00797                   return FALSE;
00798               }
00799              else
00800               {
00801                 /* The extended address record and the extended
00802                      linear address record are combined, at least by
00803                      some readers.  We need an extended linear address
00804                      record here, so if we've already written out an
00805                      extended address record, zero it out to avoid
00806                      confusion.  */
00807                 if (segbase != 0)
00808                   {
00809                     addr[0] = 0;
00810                     addr[1] = 0;
00811                     if (! ihex_write_record (abfd, 2, 0, 2, addr))
00812                      return FALSE;
00813                     segbase = 0;
00814                   }
00815 
00816                 extbase = where & 0xffff0000;
00817                 if (where > extbase + 0xffff)
00818                   {
00819                     char buf[20];
00820 
00821                     sprintf_vma (buf, where);
00822                     (*_bfd_error_handler)
00823                      (_("%s: address 0x%s out of range for Intel Hex file"),
00824                       bfd_get_filename (abfd), buf);
00825                     bfd_set_error (bfd_error_bad_value);
00826                     return FALSE;
00827                   }
00828                 addr[0] = (bfd_byte)(extbase >> 24) & 0xff;
00829                 addr[1] = (bfd_byte)(extbase >> 16) & 0xff;
00830                 if (! ihex_write_record (abfd, 2, 0, 4, addr))
00831                   return FALSE;
00832               }
00833            }
00834 
00835          rec_addr = where - (extbase + segbase);
00836 
00837           /* Output records shouldn't cross 64K boundaries.  */
00838           if (rec_addr + now > 0xffff)
00839             now = 0x10000 - rec_addr;
00840 
00841          if (! ihex_write_record (abfd, now, rec_addr, 0, p))
00842            return FALSE;
00843 
00844          where += now;
00845          p += now;
00846          count -= now;
00847        }
00848     }
00849 
00850   if (abfd->start_address != 0)
00851     {
00852       bfd_vma start;
00853       bfd_byte startbuf[4];
00854 
00855       start = abfd->start_address;
00856 
00857       if (start <= 0xfffff)
00858        {
00859          startbuf[0] = (bfd_byte)((start & 0xf0000) >> 12) & 0xff;
00860          startbuf[1] = 0;
00861          startbuf[2] = (bfd_byte)(start >> 8) & 0xff;
00862          startbuf[3] = (bfd_byte)start & 0xff;
00863          if (! ihex_write_record (abfd, 4, 0, 3, startbuf))
00864            return FALSE;
00865        }
00866       else
00867        {
00868          startbuf[0] = (bfd_byte)(start >> 24) & 0xff;
00869          startbuf[1] = (bfd_byte)(start >> 16) & 0xff;
00870          startbuf[2] = (bfd_byte)(start >> 8) & 0xff;
00871          startbuf[3] = (bfd_byte)start & 0xff;
00872          if (! ihex_write_record (abfd, 4, 0, 5, startbuf))
00873            return FALSE;
00874        }
00875     }
00876 
00877   if (! ihex_write_record (abfd, 0, 0, 1, NULL))
00878     return FALSE;
00879 
00880   return TRUE;
00881 }
00882 
00883 /* Set the architecture for the output file.  The architecture is
00884    irrelevant, so we ignore errors about unknown architectures.  */
00885 
00886 static bfd_boolean
00887 ihex_set_arch_mach (bfd *abfd,
00888                   enum bfd_architecture arch,
00889                   unsigned long mach)
00890 {
00891   if (! bfd_default_set_arch_mach (abfd, arch, mach))
00892     {
00893       if (arch != bfd_arch_unknown)
00894        return FALSE;
00895     }
00896   return TRUE;
00897 }
00898 
00899 /* Get the size of the headers, for the linker.  */
00900 
00901 static int
00902 ihex_sizeof_headers (bfd *abfd ATTRIBUTE_UNUSED,
00903                    struct bfd_link_info *info ATTRIBUTE_UNUSED)
00904 {
00905   return 0;
00906 }
00907 
00908 /* Some random definitions for the target vector.  */
00909 
00910 #define       ihex_close_and_cleanup                    _bfd_generic_close_and_cleanup
00911 #define ihex_bfd_free_cached_info                 _bfd_generic_bfd_free_cached_info
00912 #define ihex_new_section_hook                     _bfd_generic_new_section_hook
00913 #define ihex_get_section_contents_in_window       _bfd_generic_get_section_contents_in_window
00914 #define ihex_get_symtab_upper_bound               bfd_0l
00915 #define ihex_canonicalize_symtab                  ((long (*) (bfd *, asymbol **)) bfd_0l)
00916 #define ihex_make_empty_symbol                    _bfd_generic_make_empty_symbol
00917 #define ihex_print_symbol                         _bfd_nosymbols_print_symbol
00918 #define ihex_get_symbol_info                      _bfd_nosymbols_get_symbol_info
00919 #define ihex_bfd_is_target_special_symbol         ((bfd_boolean (*) (bfd *, asymbol *)) bfd_false)
00920 #define ihex_bfd_is_local_label_name              _bfd_nosymbols_bfd_is_local_label_name
00921 #define ihex_get_lineno                           _bfd_nosymbols_get_lineno
00922 #define ihex_find_nearest_line                    _bfd_nosymbols_find_nearest_line
00923 #define ihex_find_inliner_info                    _bfd_nosymbols_find_inliner_info
00924 #define ihex_bfd_make_debug_symbol                _bfd_nosymbols_bfd_make_debug_symbol
00925 #define ihex_read_minisymbols                     _bfd_nosymbols_read_minisymbols
00926 #define ihex_minisymbol_to_symbol                 _bfd_nosymbols_minisymbol_to_symbol
00927 #define ihex_bfd_get_relocated_section_contents   bfd_generic_get_relocated_section_contents
00928 #define ihex_bfd_relax_section                    bfd_generic_relax_section
00929 #define ihex_bfd_gc_sections                      bfd_generic_gc_sections
00930 #define ihex_bfd_merge_sections                   bfd_generic_merge_sections
00931 #define ihex_bfd_is_group_section                 bfd_generic_is_group_section
00932 #define ihex_bfd_discard_group                    bfd_generic_discard_group
00933 #define ihex_section_already_linked               _bfd_generic_section_already_linked
00934 #define ihex_bfd_link_hash_table_create           _bfd_generic_link_hash_table_create
00935 #define ihex_bfd_link_hash_table_free             _bfd_generic_link_hash_table_free
00936 #define ihex_bfd_link_add_symbols                 _bfd_generic_link_add_symbols
00937 #define ihex_bfd_link_just_syms                   _bfd_generic_link_just_syms
00938 #define ihex_bfd_final_link                       _bfd_generic_final_link
00939 #define ihex_bfd_link_split_section               _bfd_generic_link_split_section
00940 
00941 /* The Intel Hex target vector.  */
00942 
00943 const bfd_target ihex_vec =
00944 {
00945   "ihex",                   /* Name.  */
00946   bfd_target_ihex_flavour,
00947   BFD_ENDIAN_UNKNOWN,              /* Target byte order.  */
00948   BFD_ENDIAN_UNKNOWN,              /* Target headers byte order.  */
00949   0,                        /* Object flags.  */
00950   (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD),     /* Section flags.  */
00951   0,                        /* Leading underscore.  */
00952   ' ',                      /* AR_pad_char.  */
00953   16,                       /* AR_max_namelen.  */
00954   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
00955   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
00956   bfd_getb16, bfd_getb_signed_16, bfd_putb16,    /* Data.  */
00957   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
00958   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
00959   bfd_getb16, bfd_getb_signed_16, bfd_putb16,    /* Headers. */
00960 
00961   {
00962     _bfd_dummy_target,
00963     ihex_object_p,          /* bfd_check_format.  */
00964     _bfd_dummy_target,
00965     _bfd_dummy_target,
00966   },
00967   {
00968     bfd_false,
00969     ihex_mkobject,
00970     _bfd_generic_mkarchive,
00971     bfd_false,
00972   },
00973   {                         /* bfd_write_contents.  */
00974     bfd_false,
00975     ihex_write_object_contents,
00976     _bfd_write_archive_contents,
00977     bfd_false,
00978   },
00979 
00980   BFD_JUMP_TABLE_GENERIC (ihex),
00981   BFD_JUMP_TABLE_COPY (_bfd_generic),
00982   BFD_JUMP_TABLE_CORE (_bfd_nocore),
00983   BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
00984   BFD_JUMP_TABLE_SYMBOLS (ihex),
00985   BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
00986   BFD_JUMP_TABLE_WRITE (ihex),
00987   BFD_JUMP_TABLE_LINK (ihex),
00988   BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
00989 
00990   NULL,
00991 
00992   NULL
00993 };