OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-stable/] [binutils-2.20.1/] [bfd/] [ihex.c] - Blame information for rev 827

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.