Subversion Repositories Kolibri OS

Rev

Rev 5197 | Details | Compare with Previous | Last modification | View Log | RSS feed

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