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 s-record objects.
6324 serge 2
   Copyright (C) 1990-2015 Free Software Foundation, Inc.
5197 serge 3
   Written by Steve Chamberlain 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
/* SUBSECTION
24
	S-Record handling
25
 
26
   DESCRIPTION
27
 
28
	Ordinary S-Records cannot hold anything but addresses and
29
	data, so that's all that we implement.
30
 
31
	The only interesting thing is that S-Records may come out of
32
	order and there is no header, so an initial scan is required
33
	to discover the minimum and maximum addresses used to create
34
	the vma and size of the only section we create.  We
35
	arbitrarily call this section ".text".
36
 
37
	When bfd_get_section_contents is called the file is read
38
	again, and this time the data is placed into a bfd_alloc'd
39
	area.
40
 
41
	Any number of sections may be created for output, we save them
42
	up and output them when it's time to close the bfd.
43
 
44
	An s record looks like:
45
 
46
   EXAMPLE
47
	S
48
 
49
   DESCRIPTION
50
	Where
51
	o length
52
	is the number of bytes following upto the checksum. Note that
53
	this is not the number of chars following, since it takes two
54
	chars to represent a byte.
55
	o type
56
	is one of:
57
	0) header record
58
	1) two byte address data record
59
	2) three byte address data record
60
	3) four byte address data record
61
	7) four byte address termination record
62
	8) three byte address termination record
63
	9) two byte address termination record
64
 
65
	o address
66
	is the start address of the data following, or in the case of
67
	a termination record, the start address of the image
68
	o data
69
	is the data.
70
	o checksum
71
	is the sum of all the raw byte data in the record, from the length
72
	upwards, modulo 256 and subtracted from 255.
73
 
74
   SUBSECTION
75
	Symbol S-Record handling
76
 
77
   DESCRIPTION
78
	Some ICE equipment understands an addition to the standard
79
	S-Record format; symbols and their addresses can be sent
80
	before the data.
81
 
82
	The format of this is:
83
	($$ 
84
		(  
)*)
85
	$$
86
 
87
	so a short symbol table could look like:
88
 
89
   EXAMPLE
90
	$$ flash.x
91
	$$ flash.c
92
	  _port6 $0
93
	  _delay $4
94
	  _start $14
95
	  _etext $8036
96
	  _edata $8036
97
 	  _end $8036
98
	$$
99
 
100
   DESCRIPTION
101
	We allow symbols to be anywhere in the data stream - the module names
102
	are always ignored.  */
103
 
104
#include "sysdep.h"
105
#include "bfd.h"
106
#include "libbfd.h"
107
#include "libiberty.h"
108
#include "safe-ctype.h"
109
 
110
 
111
/* Macros for converting between hex and binary.  */
112
 
113
static const char digs[] = "0123456789ABCDEF";
114
 
115
#define NIBBLE(x)    hex_value(x)
116
#define HEX(buffer) ((NIBBLE ((buffer)[0])<<4) + NIBBLE ((buffer)[1]))
117
#define TOHEX(d, x, ch) \
118
	d[1] = digs[(x) & 0xf]; \
119
	d[0] = digs[((x)>>4)&0xf]; \
120
	ch += ((x) & 0xff);
121
#define	ISHEX(x)    hex_p(x)
122
 
123
/* The maximum number of address+data+crc bytes on a line is FF.  */
124
#define MAXCHUNK 0xff
125
 
126
/* Default size for a CHUNK.  */
127
#define DEFAULT_CHUNK 16
128
 
129
/* The number of data bytes we actually fit onto a line on output.
130
   This variable can be modified by objcopy's --srec-len parameter.
131
   For a 0x75 byte record you should set --srec-len=0x70.  */
132
unsigned int Chunk = DEFAULT_CHUNK;
133
 
134
/* The type of srec output (free or forced to S3).
135
   This variable can be modified by objcopy's --srec-forceS3
136
   parameter.  */
137
bfd_boolean S3Forced = FALSE;
138
 
139
/* When writing an S-record file, the S-records can not be output as
140
   they are seen.  This structure is used to hold them in memory.  */
141
 
142
struct srec_data_list_struct
143
{
144
  struct srec_data_list_struct *next;
145
  bfd_byte *data;
146
  bfd_vma where;
147
  bfd_size_type size;
148
};
149
 
150
typedef struct srec_data_list_struct srec_data_list_type;
151
 
152
/* When scanning the S-record file, a linked list of srec_symbol
153
   structures is built to represent the symbol table (if there is
154
   one).  */
155
 
156
struct srec_symbol
157
{
158
  struct srec_symbol *next;
159
  const char *name;
160
  bfd_vma val;
161
};
162
 
163
/* The S-record tdata information.  */
164
 
165
typedef struct srec_data_struct
166
  {
167
    srec_data_list_type *head;
168
    srec_data_list_type *tail;
169
    unsigned int type;
170
    struct srec_symbol *symbols;
171
    struct srec_symbol *symtail;
172
    asymbol *csymbols;
173
  }
174
tdata_type;
175
 
176
/* Initialize by filling in the hex conversion array.  */
177
 
178
static void
179
srec_init (void)
180
{
181
  static bfd_boolean inited = FALSE;
182
 
183
  if (! inited)
184
    {
185
      inited = TRUE;
186
      hex_init ();
187
    }
188
}
189
 
190
/* Set up the S-record tdata information.  */
191
 
192
static bfd_boolean
193
srec_mkobject (bfd *abfd)
194
{
195
  tdata_type *tdata;
196
 
197
  srec_init ();
198
 
199
  tdata = (tdata_type *) bfd_alloc (abfd, sizeof (tdata_type));
200
  if (tdata == NULL)
201
    return FALSE;
202
 
203
  abfd->tdata.srec_data = tdata;
204
  tdata->type = 1;
205
  tdata->head = NULL;
206
  tdata->tail = NULL;
207
  tdata->symbols = NULL;
208
  tdata->symtail = NULL;
209
  tdata->csymbols = NULL;
210
 
211
  return TRUE;
212
}
213
 
214
/* Read a byte from an S record file.  Set *ERRORPTR if an error
215
   occurred.  Return EOF on error or end of file.  */
216
 
217
static int
218
srec_get_byte (bfd *abfd, bfd_boolean *errorptr)
219
{
220
  bfd_byte c;
221
 
222
  if (bfd_bread (&c, (bfd_size_type) 1, abfd) != 1)
223
    {
224
      if (bfd_get_error () != bfd_error_file_truncated)
225
	*errorptr = TRUE;
226
      return EOF;
227
    }
228
 
229
  return (int) (c & 0xff);
230
}
231
 
232
/* Report a problem in an S record file.  FIXME: This probably should
233
   not call fprintf, but we really do need some mechanism for printing
234
   error messages.  */
235
 
236
static void
237
srec_bad_byte (bfd *abfd,
238
	       unsigned int lineno,
239
	       int c,
240
	       bfd_boolean error)
241
{
242
  if (c == EOF)
243
    {
244
      if (! error)
245
	bfd_set_error (bfd_error_file_truncated);
246
    }
247
  else
248
    {
6324 serge 249
      char buf[40];
5197 serge 250
 
251
      if (! ISPRINT (c))
6324 serge 252
	sprintf (buf, "\\%03o", (unsigned int) c & 0xff);
5197 serge 253
      else
254
	{
255
	  buf[0] = c;
256
	  buf[1] = '\0';
257
	}
258
      (*_bfd_error_handler)
259
	(_("%B:%d: Unexpected character `%s' in S-record file\n"),
260
	 abfd, lineno, buf);
261
      bfd_set_error (bfd_error_bad_value);
262
    }
263
}
264
 
265
/* Add a new symbol found in an S-record file.  */
266
 
267
static bfd_boolean
268
srec_new_symbol (bfd *abfd, const char *name, bfd_vma val)
269
{
270
  struct srec_symbol *n;
271
 
272
  n = (struct srec_symbol *) bfd_alloc (abfd, sizeof (* n));
273
  if (n == NULL)
274
    return FALSE;
275
 
276
  n->name = name;
277
  n->val = val;
278
 
279
  if (abfd->tdata.srec_data->symbols == NULL)
280
    abfd->tdata.srec_data->symbols = n;
281
  else
282
    abfd->tdata.srec_data->symtail->next = n;
283
  abfd->tdata.srec_data->symtail = n;
284
  n->next = NULL;
285
 
286
  ++abfd->symcount;
287
 
288
  return TRUE;
289
}
290
 
291
/* Read the S record file and turn it into sections.  We create a new
292
   section for each contiguous set of bytes.  */
293
 
294
static bfd_boolean
295
srec_scan (bfd *abfd)
296
{
297
  int c;
298
  unsigned int lineno = 1;
299
  bfd_boolean error = FALSE;
300
  bfd_byte *buf = NULL;
301
  size_t bufsize = 0;
302
  asection *sec = NULL;
303
  char *symbuf = NULL;
304
 
305
  if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
306
    goto error_return;
307
 
308
  while ((c = srec_get_byte (abfd, &error)) != EOF)
309
    {
310
      /* We only build sections from contiguous S-records, so if this
311
	 is not an S-record, then stop building a section.  */
312
      if (c != 'S' && c != '\r' && c != '\n')
313
	sec = NULL;
314
 
315
      switch (c)
316
	{
317
	default:
318
	  srec_bad_byte (abfd, lineno, c, error);
319
	  goto error_return;
320
 
321
	case '\n':
322
	  ++lineno;
323
	  break;
324
 
325
	case '\r':
326
	  break;
327
 
328
	case '$':
329
	  /* Starting a module name, which we ignore.  */
330
	  while ((c = srec_get_byte (abfd, &error)) != '\n'
331
		 && c != EOF)
332
	    ;
333
	  if (c == EOF)
334
	    {
335
	      srec_bad_byte (abfd, lineno, c, error);
336
	      goto error_return;
337
	    }
338
 
339
	  ++lineno;
340
	  break;
341
 
342
	case ' ':
343
	  do
344
	    {
345
	      bfd_size_type alc;
346
	      char *p, *symname;
347
	      bfd_vma symval;
348
 
349
	      /* Starting a symbol definition.  */
350
	      while ((c = srec_get_byte (abfd, &error)) != EOF
351
		     && (c == ' ' || c == '\t'))
352
		;
353
 
354
	      if (c == '\n' || c == '\r')
355
		break;
356
 
357
	      if (c == EOF)
358
		{
359
		  srec_bad_byte (abfd, lineno, c, error);
360
		  goto error_return;
361
		}
362
 
363
	      alc = 10;
364
	      symbuf = (char *) bfd_malloc (alc + 1);
365
	      if (symbuf == NULL)
366
		goto error_return;
367
 
368
	      p = symbuf;
369
 
370
	      *p++ = c;
371
	      while ((c = srec_get_byte (abfd, &error)) != EOF
372
		     && ! ISSPACE (c))
373
		{
374
		  if ((bfd_size_type) (p - symbuf) >= alc)
375
		    {
376
		      char *n;
377
 
378
		      alc *= 2;
379
		      n = (char *) bfd_realloc (symbuf, alc + 1);
380
		      if (n == NULL)
381
			goto error_return;
382
		      p = n + (p - symbuf);
383
		      symbuf = n;
384
		    }
385
 
386
		  *p++ = c;
387
		}
388
 
389
	      if (c == EOF)
390
		{
391
		  srec_bad_byte (abfd, lineno, c, error);
392
		  goto error_return;
393
		}
394
 
395
	      *p++ = '\0';
396
	      symname = (char *) bfd_alloc (abfd, (bfd_size_type) (p - symbuf));
397
	      if (symname == NULL)
398
		goto error_return;
399
	      strcpy (symname, symbuf);
400
	      free (symbuf);
401
	      symbuf = NULL;
402
 
403
	      while ((c = srec_get_byte (abfd, &error)) != EOF
404
		     && (c == ' ' || c == '\t'))
405
		;
406
	      if (c == EOF)
407
		{
408
		  srec_bad_byte (abfd, lineno, c, error);
409
		  goto error_return;
410
		}
411
 
412
	      /* Skip a dollar sign before the hex value.  */
413
	      if (c == '$')
414
		{
415
		  c = srec_get_byte (abfd, &error);
416
		  if (c == EOF)
417
		    {
418
		      srec_bad_byte (abfd, lineno, c, error);
419
		      goto error_return;
420
		    }
421
		}
422
 
423
	      symval = 0;
424
	      while (ISHEX (c))
425
		{
426
		  symval <<= 4;
427
		  symval += NIBBLE (c);
428
		  c = srec_get_byte (abfd, &error);
429
		  if (c == EOF)
430
		    {
431
		      srec_bad_byte (abfd, lineno, c, error);
432
		      goto error_return;
433
		    }
434
		}
435
 
436
	      if (! srec_new_symbol (abfd, symname, symval))
437
		goto error_return;
438
	    }
439
	  while (c == ' ' || c == '\t')
440
	    ;
441
 
442
	  if (c == '\n')
443
	    ++lineno;
444
	  else if (c != '\r')
445
	    {
446
	      srec_bad_byte (abfd, lineno, c, error);
447
	      goto error_return;
448
	    }
449
 
450
	  break;
451
 
452
	case 'S':
453
	  {
454
	    file_ptr pos;
6324 serge 455
	    unsigned char hdr[3];
456
	    unsigned int bytes, min_bytes;
5197 serge 457
	    bfd_vma address;
458
	    bfd_byte *data;
459
	    unsigned char check_sum;
460
 
461
	    /* Starting an S-record.  */
462
 
463
	    pos = bfd_tell (abfd) - 1;
464
 
465
	    if (bfd_bread (hdr, (bfd_size_type) 3, abfd) != 3)
466
	      goto error_return;
467
 
468
	    if (! ISHEX (hdr[1]) || ! ISHEX (hdr[2]))
469
	      {
470
		if (! ISHEX (hdr[1]))
471
		  c = hdr[1];
472
		else
473
		  c = hdr[2];
474
		srec_bad_byte (abfd, lineno, c, error);
475
		goto error_return;
476
	      }
477
 
478
	    check_sum = bytes = HEX (hdr + 1);
6324 serge 479
	    min_bytes = 3;
480
	    if (hdr[0] == '2' || hdr[0] == '8')
481
	      min_bytes = 4;
482
	    else if (hdr[0] == '3' || hdr[0] == '7')
483
	      min_bytes = 5;
484
	    if (bytes < min_bytes)
485
	      {
486
		(*_bfd_error_handler) (_("%B:%d: byte count %d too small\n"),
487
				       abfd, lineno, bytes);
488
		bfd_set_error (bfd_error_bad_value);
489
		goto error_return;
490
	      }
491
 
5197 serge 492
	    if (bytes * 2 > bufsize)
493
	      {
494
		if (buf != NULL)
495
		  free (buf);
496
		buf = (bfd_byte *) bfd_malloc ((bfd_size_type) bytes * 2);
497
		if (buf == NULL)
498
		  goto error_return;
499
		bufsize = bytes * 2;
500
	      }
501
 
502
	    if (bfd_bread (buf, (bfd_size_type) bytes * 2, abfd) != bytes * 2)
503
	      goto error_return;
504
 
505
	    /* Ignore the checksum byte.  */
506
	    --bytes;
507
 
508
	    address = 0;
509
	    data = buf;
510
	    switch (hdr[0])
511
	      {
512
	      case '0':
513
	      case '5':
514
		/* Prologue--ignore the file name, but stop building a
515
		   section at this point.  */
516
		sec = NULL;
517
		break;
518
 
519
	      case '3':
520
		check_sum += HEX (data);
521
		address = HEX (data);
522
		data += 2;
523
		--bytes;
524
		/* Fall through.  */
525
	      case '2':
526
		check_sum += HEX (data);
527
		address = (address << 8) | HEX (data);
528
		data += 2;
529
		--bytes;
530
		/* Fall through.  */
531
	      case '1':
532
		check_sum += HEX (data);
533
		address = (address << 8) | HEX (data);
534
		data += 2;
535
		check_sum += HEX (data);
536
		address = (address << 8) | HEX (data);
537
		data += 2;
538
		bytes -= 2;
539
 
540
		if (sec != NULL
541
		    && sec->vma + sec->size == address)
542
		  {
543
		    /* This data goes at the end of the section we are
544
		       currently building.  */
545
		    sec->size += bytes;
546
		  }
547
		else
548
		  {
549
		    char secbuf[20];
550
		    char *secname;
551
		    bfd_size_type amt;
552
		    flagword flags;
553
 
554
		    sprintf (secbuf, ".sec%d", bfd_count_sections (abfd) + 1);
555
		    amt = strlen (secbuf) + 1;
556
		    secname = (char *) bfd_alloc (abfd, amt);
557
		    strcpy (secname, secbuf);
558
		    flags = SEC_HAS_CONTENTS | SEC_LOAD | SEC_ALLOC;
559
		    sec = bfd_make_section_with_flags (abfd, secname, flags);
560
		    if (sec == NULL)
561
		      goto error_return;
562
		    sec->vma = address;
563
		    sec->lma = address;
564
		    sec->size = bytes;
565
		    sec->filepos = pos;
566
		  }
567
 
568
		while (bytes > 0)
569
		  {
570
		    check_sum += HEX (data);
571
		    data += 2;
572
		    bytes--;
573
		  }
574
		check_sum = 255 - (check_sum & 0xff);
575
		if (check_sum != HEX (data))
576
		  {
577
		    (*_bfd_error_handler)
578
		      (_("%B:%d: Bad checksum in S-record file\n"),
579
		       abfd, lineno);
580
		    bfd_set_error (bfd_error_bad_value);
581
		    goto error_return;
582
		  }
583
 
584
		break;
585
 
586
	      case '7':
587
		check_sum += HEX (data);
588
		address = HEX (data);
589
		data += 2;
590
		/* Fall through.  */
591
	      case '8':
592
		check_sum += HEX (data);
593
		address = (address << 8) | HEX (data);
594
		data += 2;
595
		/* Fall through.  */
596
	      case '9':
597
		check_sum += HEX (data);
598
		address = (address << 8) | HEX (data);
599
		data += 2;
600
		check_sum += HEX (data);
601
		address = (address << 8) | HEX (data);
602
		data += 2;
603
 
604
		/* This is a termination record.  */
605
		abfd->start_address = address;
606
 
607
		check_sum = 255 - (check_sum & 0xff);
608
		if (check_sum != HEX (data))
609
		  {
610
		    (*_bfd_error_handler)
611
		      (_("%B:%d: Bad checksum in S-record file\n"),
612
		       abfd, lineno);
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
	  }
623
	  break;
624
	}
625
    }
626
 
627
  if (error)
628
    goto error_return;
629
 
630
  if (buf != NULL)
631
    free (buf);
632
 
633
  return TRUE;
634
 
635
 error_return:
636
  if (symbuf != NULL)
637
    free (symbuf);
638
  if (buf != NULL)
639
    free (buf);
640
  return FALSE;
641
}
642
 
643
/* Check whether an existing file is an S-record file.  */
644
 
645
static const bfd_target *
646
srec_object_p (bfd *abfd)
647
{
648
  void * tdata_save;
649
  bfd_byte b[4];
650
 
651
  srec_init ();
652
 
653
  if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0
654
      || bfd_bread (b, (bfd_size_type) 4, abfd) != 4)
655
    return NULL;
656
 
657
  if (b[0] != 'S' || !ISHEX (b[1]) || !ISHEX (b[2]) || !ISHEX (b[3]))
658
    {
659
      bfd_set_error (bfd_error_wrong_format);
660
      return NULL;
661
    }
662
 
663
  tdata_save = abfd->tdata.any;
664
  if (! srec_mkobject (abfd) || ! srec_scan (abfd))
665
    {
666
      if (abfd->tdata.any != tdata_save && abfd->tdata.any != NULL)
667
	bfd_release (abfd, abfd->tdata.any);
668
      abfd->tdata.any = tdata_save;
669
      return NULL;
670
    }
671
 
672
  if (abfd->symcount > 0)
673
    abfd->flags |= HAS_SYMS;
674
 
675
  return abfd->xvec;
676
}
677
 
678
/* Check whether an existing file is an S-record file with symbols.  */
679
 
680
static const bfd_target *
681
symbolsrec_object_p (bfd *abfd)
682
{
683
  void * tdata_save;
684
  char b[2];
685
 
686
  srec_init ();
687
 
688
  if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0
689
      || bfd_bread (b, (bfd_size_type) 2, abfd) != 2)
690
    return NULL;
691
 
692
  if (b[0] != '$' || b[1] != '$')
693
    {
694
      bfd_set_error (bfd_error_wrong_format);
695
      return NULL;
696
    }
697
 
698
  tdata_save = abfd->tdata.any;
699
  if (! srec_mkobject (abfd) || ! srec_scan (abfd))
700
    {
701
      if (abfd->tdata.any != tdata_save && abfd->tdata.any != NULL)
702
	bfd_release (abfd, abfd->tdata.any);
703
      abfd->tdata.any = tdata_save;
704
      return NULL;
705
    }
706
 
707
  if (abfd->symcount > 0)
708
    abfd->flags |= HAS_SYMS;
709
 
710
  return abfd->xvec;
711
}
712
 
713
/* Read in the contents of a section in an S-record file.  */
714
 
715
static bfd_boolean
716
srec_read_section (bfd *abfd, asection *section, bfd_byte *contents)
717
{
718
  int c;
719
  bfd_size_type sofar = 0;
720
  bfd_boolean error = FALSE;
721
  bfd_byte *buf = NULL;
722
  size_t bufsize = 0;
723
 
724
  if (bfd_seek (abfd, section->filepos, SEEK_SET) != 0)
725
    goto error_return;
726
 
727
  while ((c = srec_get_byte (abfd, &error)) != EOF)
728
    {
729
      bfd_byte hdr[3];
730
      unsigned int bytes;
731
      bfd_vma address;
732
      bfd_byte *data;
733
 
734
      if (c == '\r' || c == '\n')
735
	continue;
736
 
737
      /* This is called after srec_scan has already been called, so we
738
	 ought to know the exact format.  */
739
      BFD_ASSERT (c == 'S');
740
 
741
      if (bfd_bread (hdr, (bfd_size_type) 3, abfd) != 3)
742
	goto error_return;
743
 
744
      BFD_ASSERT (ISHEX (hdr[1]) && ISHEX (hdr[2]));
745
 
746
      bytes = HEX (hdr + 1);
747
 
748
      if (bytes * 2 > bufsize)
749
	{
750
	  if (buf != NULL)
751
	    free (buf);
752
	  buf = (bfd_byte *) bfd_malloc ((bfd_size_type) bytes * 2);
753
	  if (buf == NULL)
754
	    goto error_return;
755
	  bufsize = bytes * 2;
756
	}
757
 
758
      if (bfd_bread (buf, (bfd_size_type) bytes * 2, abfd) != bytes * 2)
759
	goto error_return;
760
 
761
      address = 0;
762
      data = buf;
763
      switch (hdr[0])
764
	{
765
	default:
766
	  BFD_ASSERT (sofar == section->size);
767
	  if (buf != NULL)
768
	    free (buf);
769
	  return TRUE;
770
 
771
	case '3':
772
	  address = HEX (data);
773
	  data += 2;
774
	  --bytes;
775
	  /* Fall through.  */
776
	case '2':
777
	  address = (address << 8) | HEX (data);
778
	  data += 2;
779
	  --bytes;
780
	  /* Fall through.  */
781
	case '1':
782
	  address = (address << 8) | HEX (data);
783
	  data += 2;
784
	  address = (address << 8) | HEX (data);
785
	  data += 2;
786
	  bytes -= 2;
787
 
788
	  if (address != section->vma + sofar)
789
	    {
790
	      /* We've come to the end of this section.  */
791
	      BFD_ASSERT (sofar == section->size);
792
	      if (buf != NULL)
793
		free (buf);
794
	      return TRUE;
795
	    }
796
 
797
	  /* Don't consider checksum.  */
798
	  --bytes;
799
 
800
	  while (bytes-- != 0)
801
	    {
802
	      contents[sofar] = HEX (data);
803
	      data += 2;
804
	      ++sofar;
805
	    }
806
 
807
	  break;
808
	}
809
    }
810
 
811
  if (error)
812
    goto error_return;
813
 
814
  BFD_ASSERT (sofar == section->size);
815
 
816
  if (buf != NULL)
817
    free (buf);
818
 
819
  return TRUE;
820
 
821
 error_return:
822
  if (buf != NULL)
823
    free (buf);
824
  return FALSE;
825
}
826
 
827
/* Get the contents of a section in an S-record file.  */
828
 
829
static bfd_boolean
830
srec_get_section_contents (bfd *abfd,
831
			   asection *section,
832
			   void * location,
833
			   file_ptr offset,
834
			   bfd_size_type count)
835
{
836
  if (count == 0)
837
    return TRUE;
838
 
839
  if (offset + count < count
840
      || offset + count > section->size)
841
    {
842
      bfd_set_error (bfd_error_invalid_operation);
843
      return FALSE;
844
    }
845
 
846
  if (section->used_by_bfd == NULL)
847
    {
848
      section->used_by_bfd = bfd_alloc (abfd, section->size);
849
      if (section->used_by_bfd == NULL)
850
	return FALSE;
851
 
852
      if (! srec_read_section (abfd, section,
853
                               (bfd_byte *) section->used_by_bfd))
854
	return FALSE;
855
    }
856
 
857
  memcpy (location, (bfd_byte *) section->used_by_bfd + offset,
858
	  (size_t) count);
859
 
860
  return TRUE;
861
}
862
 
863
/* Set the architecture.  We accept an unknown architecture here.  */
864
 
865
static bfd_boolean
866
srec_set_arch_mach (bfd *abfd, enum bfd_architecture arch, unsigned long mach)
867
{
868
  if (arch != bfd_arch_unknown)
869
    return bfd_default_set_arch_mach (abfd, arch, mach);
870
 
871
  abfd->arch_info = & bfd_default_arch_struct;
872
  return TRUE;
873
}
874
 
875
/* We have to save up all the Srecords for a splurge before output.  */
876
 
877
static bfd_boolean
878
srec_set_section_contents (bfd *abfd,
879
			   sec_ptr section,
880
			   const void * location,
881
			   file_ptr offset,
882
			   bfd_size_type bytes_to_do)
883
{
884
  int opb = bfd_octets_per_byte (abfd);
885
  tdata_type *tdata = abfd->tdata.srec_data;
886
  srec_data_list_type *entry;
887
 
888
  entry = (srec_data_list_type *) bfd_alloc (abfd, sizeof (* entry));
889
  if (entry == NULL)
890
    return FALSE;
891
 
892
  if (bytes_to_do
893
      && (section->flags & SEC_ALLOC)
894
      && (section->flags & SEC_LOAD))
895
    {
896
      bfd_byte *data;
897
 
898
      data = (bfd_byte *) bfd_alloc (abfd, bytes_to_do);
899
      if (data == NULL)
900
	return FALSE;
901
      memcpy ((void *) data, location, (size_t) bytes_to_do);
902
 
903
      /* Ff S3Forced is TRUE then always select S3 records,
904
	 regardless of the siez of the addresses.  */
905
      if (S3Forced)
906
	tdata->type = 3;
907
      else if ((section->lma + (offset + bytes_to_do) / opb - 1) <= 0xffff)
908
	;  /* The default, S1, is OK.  */
909
      else if ((section->lma + (offset + bytes_to_do) / opb - 1) <= 0xffffff
910
	       && tdata->type <= 2)
911
	tdata->type = 2;
912
      else
913
	tdata->type = 3;
914
 
915
      entry->data = data;
916
      entry->where = section->lma + offset / opb;
917
      entry->size = bytes_to_do;
918
 
919
      /* Sort the records by address.  Optimize for the common case of
920
	 adding a record to the end of the list.  */
921
      if (tdata->tail != NULL
922
	  && entry->where >= tdata->tail->where)
923
	{
924
	  tdata->tail->next = entry;
925
	  entry->next = NULL;
926
	  tdata->tail = entry;
927
	}
928
      else
929
	{
930
	  srec_data_list_type **look;
931
 
932
	  for (look = &tdata->head;
933
	       *look != NULL && (*look)->where < entry->where;
934
	       look = &(*look)->next)
935
	    ;
936
	  entry->next = *look;
937
	  *look = entry;
938
	  if (entry->next == NULL)
939
	    tdata->tail = entry;
940
	}
941
    }
942
  return TRUE;
943
}
944
 
945
/* Write a record of type, of the supplied number of bytes. The
946
   supplied bytes and length don't have a checksum. That's worked out
947
   here.  */
948
 
949
static bfd_boolean
950
srec_write_record (bfd *abfd,
951
		   unsigned int type,
952
		   bfd_vma address,
953
		   const bfd_byte *data,
954
		   const bfd_byte *end)
955
{
956
  char buffer[2 * MAXCHUNK + 6];
957
  unsigned int check_sum = 0;
958
  const bfd_byte *src = data;
959
  char *dst = buffer;
960
  char *length;
961
  bfd_size_type wrlen;
962
 
963
  *dst++ = 'S';
964
  *dst++ = '0' + type;
965
 
966
  length = dst;
967
  dst += 2;			/* Leave room for dst.  */
968
 
969
  switch (type)
970
    {
971
    case 3:
972
    case 7:
973
      TOHEX (dst, (address >> 24), check_sum);
974
      dst += 2;
975
    case 8:
976
    case 2:
977
      TOHEX (dst, (address >> 16), check_sum);
978
      dst += 2;
979
    case 9:
980
    case 1:
981
    case 0:
982
      TOHEX (dst, (address >> 8), check_sum);
983
      dst += 2;
984
      TOHEX (dst, (address), check_sum);
985
      dst += 2;
986
      break;
987
 
988
    }
989
  for (src = data; src < end; src++)
990
    {
991
      TOHEX (dst, *src, check_sum);
992
      dst += 2;
993
    }
994
 
995
  /* Fill in the length.  */
996
  TOHEX (length, (dst - length) / 2, check_sum);
997
  check_sum &= 0xff;
998
  check_sum = 255 - check_sum;
999
  TOHEX (dst, check_sum, check_sum);
1000
  dst += 2;
1001
 
1002
  *dst++ = '\r';
1003
  *dst++ = '\n';
1004
  wrlen = dst - buffer;
1005
 
1006
  return bfd_bwrite ((void *) buffer, wrlen, abfd) == wrlen;
1007
}
1008
 
1009
static bfd_boolean
1010
srec_write_header (bfd *abfd)
1011
{
1012
  unsigned int len = strlen (abfd->filename);
1013
 
1014
  /* I'll put an arbitrary 40 char limit on header size.  */
1015
  if (len > 40)
1016
    len = 40;
1017
 
1018
  return srec_write_record (abfd, 0, (bfd_vma) 0,
1019
			    (bfd_byte *) abfd->filename,
1020
			    (bfd_byte *) abfd->filename + len);
1021
}
1022
 
1023
static bfd_boolean
1024
srec_write_section (bfd *abfd,
1025
		    tdata_type *tdata,
1026
		    srec_data_list_type *list)
1027
{
1028
  unsigned int octets_written = 0;
1029
  bfd_byte *location = list->data;
1030
 
1031
  /* Validate number of data bytes to write.  The srec length byte
1032
     counts the address, data and crc bytes.  S1 (tdata->type == 1)
1033
     records have two address bytes, S2 (tdata->type == 2) records
1034
     have three, and S3 (tdata->type == 3) records have four.
1035
     The total length can't exceed 255, and a zero data length will
1036
     spin for a long time.  */
1037
  if (Chunk == 0)
1038
    Chunk = 1;
1039
  else if (Chunk > MAXCHUNK - tdata->type - 2)
1040
    Chunk = MAXCHUNK - tdata->type - 2;
1041
 
1042
  while (octets_written < list->size)
1043
    {
1044
      bfd_vma address;
1045
      unsigned int octets_this_chunk = list->size - octets_written;
1046
 
1047
      if (octets_this_chunk > Chunk)
1048
	octets_this_chunk = Chunk;
1049
 
1050
      address = list->where + octets_written / bfd_octets_per_byte (abfd);
1051
 
1052
      if (! srec_write_record (abfd,
1053
			       tdata->type,
1054
			       address,
1055
			       location,
1056
			       location + octets_this_chunk))
1057
	return FALSE;
1058
 
1059
      octets_written += octets_this_chunk;
1060
      location += octets_this_chunk;
1061
    }
1062
 
1063
  return TRUE;
1064
}
1065
 
1066
static bfd_boolean
1067
srec_write_terminator (bfd *abfd, tdata_type *tdata)
1068
{
1069
  return srec_write_record (abfd, 10 - tdata->type,
1070
			    abfd->start_address, NULL, NULL);
1071
}
1072
 
1073
static bfd_boolean
1074
srec_write_symbols (bfd *abfd)
1075
{
1076
  /* Dump out the symbols of a bfd.  */
1077
  int i;
1078
  int count = bfd_get_symcount (abfd);
1079
 
1080
  if (count)
1081
    {
1082
      bfd_size_type len;
1083
      asymbol **table = bfd_get_outsymbols (abfd);
1084
 
1085
      len = strlen (abfd->filename);
1086
      if (bfd_bwrite ("$$ ", (bfd_size_type) 3, abfd) != 3
1087
	  || bfd_bwrite (abfd->filename, len, abfd) != len
1088
	  || bfd_bwrite ("\r\n", (bfd_size_type) 2, abfd) != 2)
1089
	return FALSE;
1090
 
1091
      for (i = 0; i < count; i++)
1092
	{
1093
	  asymbol *s = table[i];
1094
	  if (! bfd_is_local_label (abfd, s)
1095
	      && (s->flags & BSF_DEBUGGING) == 0)
1096
	    {
1097
	      /* Just dump out non debug symbols.  */
1098
	      char buf[43], *p;
1099
 
1100
	      len = strlen (s->name);
1101
	      if (bfd_bwrite ("  ", (bfd_size_type) 2, abfd) != 2
1102
		  || bfd_bwrite (s->name, len, abfd) != len)
1103
		return FALSE;
1104
 
1105
	      sprintf_vma (buf + 2, (s->value
1106
				     + s->section->output_section->lma
1107
				     + s->section->output_offset));
1108
	      p = buf + 2;
1109
	      while (p[0] == '0' && p[1] != 0)
1110
		p++;
1111
	      len = strlen (p);
1112
	      p[len] = '\r';
1113
	      p[len + 1] = '\n';
1114
	      *--p = '$';
1115
	      *--p = ' ';
1116
	      len += 4;
1117
	      if (bfd_bwrite (p, len, abfd) != len)
1118
		return FALSE;
1119
	    }
1120
	}
1121
      if (bfd_bwrite ("$$ \r\n", (bfd_size_type) 5, abfd) != 5)
1122
	return FALSE;
1123
    }
1124
 
1125
  return TRUE;
1126
}
1127
 
1128
static bfd_boolean
1129
internal_srec_write_object_contents (bfd *abfd, int symbols)
1130
{
1131
  tdata_type *tdata = abfd->tdata.srec_data;
1132
  srec_data_list_type *list;
1133
 
1134
  if (symbols)
1135
    {
1136
      if (! srec_write_symbols (abfd))
1137
	return FALSE;
1138
    }
1139
 
1140
  if (! srec_write_header (abfd))
1141
    return FALSE;
1142
 
1143
  /* Now wander though all the sections provided and output them.  */
1144
  list = tdata->head;
1145
 
1146
  while (list != (srec_data_list_type *) NULL)
1147
    {
1148
      if (! srec_write_section (abfd, tdata, list))
1149
	return FALSE;
1150
      list = list->next;
1151
    }
1152
  return srec_write_terminator (abfd, tdata);
1153
}
1154
 
1155
static bfd_boolean
1156
srec_write_object_contents (bfd *abfd)
1157
{
1158
  return internal_srec_write_object_contents (abfd, 0);
1159
}
1160
 
1161
static bfd_boolean
1162
symbolsrec_write_object_contents (bfd *abfd)
1163
{
1164
  return internal_srec_write_object_contents (abfd, 1);
1165
}
1166
 
1167
static int
1168
srec_sizeof_headers (bfd *abfd ATTRIBUTE_UNUSED,
1169
		     struct bfd_link_info *info ATTRIBUTE_UNUSED)
1170
{
1171
  return 0;
1172
}
1173
 
1174
/* Return the amount of memory needed to read the symbol table.  */
1175
 
1176
static long
1177
srec_get_symtab_upper_bound (bfd *abfd)
1178
{
1179
  return (bfd_get_symcount (abfd) + 1) * sizeof (asymbol *);
1180
}
1181
 
1182
/* Return the symbol table.  */
1183
 
1184
static long
1185
srec_canonicalize_symtab (bfd *abfd, asymbol **alocation)
1186
{
1187
  bfd_size_type symcount = bfd_get_symcount (abfd);
1188
  asymbol *csymbols;
1189
  unsigned int i;
1190
 
1191
  csymbols = abfd->tdata.srec_data->csymbols;
1192
  if (csymbols == NULL && symcount != 0)
1193
    {
1194
      asymbol *c;
1195
      struct srec_symbol *s;
1196
 
1197
      csymbols = (asymbol *) bfd_alloc (abfd, symcount * sizeof (asymbol));
1198
      if (csymbols == NULL)
1199
	return -1;
1200
      abfd->tdata.srec_data->csymbols = csymbols;
1201
 
1202
      for (s = abfd->tdata.srec_data->symbols, c = csymbols;
1203
	   s != NULL;
1204
	   s = s->next, ++c)
1205
	{
1206
	  c->the_bfd = abfd;
1207
	  c->name = s->name;
1208
	  c->value = s->val;
1209
	  c->flags = BSF_GLOBAL;
1210
	  c->section = bfd_abs_section_ptr;
1211
	  c->udata.p = NULL;
1212
	}
1213
    }
1214
 
1215
  for (i = 0; i < symcount; i++)
1216
    *alocation++ = csymbols++;
1217
  *alocation = NULL;
1218
 
1219
  return symcount;
1220
}
1221
 
1222
static void
1223
srec_get_symbol_info (bfd *ignore_abfd ATTRIBUTE_UNUSED,
1224
		      asymbol *symbol,
1225
		      symbol_info *ret)
1226
{
1227
  bfd_symbol_info (symbol, ret);
1228
}
1229
 
1230
static void
1231
srec_print_symbol (bfd *abfd,
1232
		   void * afile,
1233
		   asymbol *symbol,
1234
		   bfd_print_symbol_type how)
1235
{
1236
  FILE *file = (FILE *) afile;
1237
 
1238
  switch (how)
1239
    {
1240
    case bfd_print_symbol_name:
1241
      fprintf (file, "%s", symbol->name);
1242
      break;
1243
    default:
1244
      bfd_print_symbol_vandf (abfd, (void *) file, symbol);
1245
      fprintf (file, " %-5s %s",
1246
	       symbol->section->name,
1247
	       symbol->name);
1248
    }
1249
}
1250
 
1251
#define	srec_close_and_cleanup                    _bfd_generic_close_and_cleanup
1252
#define srec_bfd_free_cached_info                 _bfd_generic_bfd_free_cached_info
1253
#define srec_new_section_hook                     _bfd_generic_new_section_hook
1254
#define srec_bfd_is_target_special_symbol         ((bfd_boolean (*) (bfd *, asymbol *)) bfd_false)
1255
#define srec_bfd_is_local_label_name              bfd_generic_is_local_label_name
1256
#define srec_get_lineno                           _bfd_nosymbols_get_lineno
1257
#define srec_find_nearest_line                    _bfd_nosymbols_find_nearest_line
6324 serge 1258
#define srec_find_line                            _bfd_nosymbols_find_line
5197 serge 1259
#define srec_find_inliner_info                    _bfd_nosymbols_find_inliner_info
1260
#define srec_make_empty_symbol                    _bfd_generic_make_empty_symbol
6324 serge 1261
#define srec_get_symbol_version_string		  _bfd_nosymbols_get_symbol_version_string
5197 serge 1262
#define srec_bfd_make_debug_symbol                _bfd_nosymbols_bfd_make_debug_symbol
1263
#define srec_read_minisymbols                     _bfd_generic_read_minisymbols
1264
#define srec_minisymbol_to_symbol                 _bfd_generic_minisymbol_to_symbol
1265
#define srec_get_section_contents_in_window       _bfd_generic_get_section_contents_in_window
1266
#define srec_bfd_get_relocated_section_contents   bfd_generic_get_relocated_section_contents
1267
#define srec_bfd_relax_section                    bfd_generic_relax_section
1268
#define srec_bfd_gc_sections                      bfd_generic_gc_sections
1269
#define srec_bfd_lookup_section_flags             bfd_generic_lookup_section_flags
1270
#define srec_bfd_merge_sections                   bfd_generic_merge_sections
1271
#define srec_bfd_is_group_section                 bfd_generic_is_group_section
1272
#define srec_bfd_discard_group                    bfd_generic_discard_group
1273
#define srec_section_already_linked               _bfd_generic_section_already_linked
1274
#define srec_bfd_define_common_symbol             bfd_generic_define_common_symbol
1275
#define srec_bfd_link_hash_table_create           _bfd_generic_link_hash_table_create
1276
#define srec_bfd_link_add_symbols                 _bfd_generic_link_add_symbols
1277
#define srec_bfd_link_just_syms                   _bfd_generic_link_just_syms
1278
#define srec_bfd_copy_link_hash_symbol_type \
1279
  _bfd_generic_copy_link_hash_symbol_type
1280
#define srec_bfd_final_link                       _bfd_generic_final_link
1281
#define srec_bfd_link_split_section               _bfd_generic_link_split_section
1282
 
1283
const bfd_target srec_vec =
1284
{
1285
  "srec",			/* Name.  */
1286
  bfd_target_srec_flavour,
1287
  BFD_ENDIAN_UNKNOWN,		/* Target byte order.  */
1288
  BFD_ENDIAN_UNKNOWN,		/* Target headers byte order.  */
1289
  (HAS_RELOC | EXEC_P |		/* Object flags.  */
1290
   HAS_LINENO | HAS_DEBUG |
1291
   HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
1292
  (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS
1293
   | SEC_ALLOC | SEC_LOAD | SEC_RELOC),	/* Section flags.  */
1294
  0,				/* Leading underscore.  */
1295
  ' ',				/* AR_pad_char.  */
1296
  16,				/* AR_max_namelen.  */
1297
  0,				/* match priority.  */
1298
  bfd_getb64, bfd_getb_signed_64, bfd_putb64,
1299
  bfd_getb32, bfd_getb_signed_32, bfd_putb32,
1300
  bfd_getb16, bfd_getb_signed_16, bfd_putb16,	/* Data.  */
1301
  bfd_getb64, bfd_getb_signed_64, bfd_putb64,
1302
  bfd_getb32, bfd_getb_signed_32, bfd_putb32,
1303
  bfd_getb16, bfd_getb_signed_16, bfd_putb16,	/* Hdrs.  */
1304
 
1305
  {
1306
    _bfd_dummy_target,
1307
    srec_object_p,		/* bfd_check_format.  */
1308
    _bfd_dummy_target,
1309
    _bfd_dummy_target,
1310
  },
1311
  {
1312
    bfd_false,
1313
    srec_mkobject,
1314
    _bfd_generic_mkarchive,
1315
    bfd_false,
1316
  },
1317
  {				/* bfd_write_contents.  */
1318
    bfd_false,
1319
    srec_write_object_contents,
1320
    _bfd_write_archive_contents,
1321
    bfd_false,
1322
  },
1323
 
1324
  BFD_JUMP_TABLE_GENERIC (srec),
1325
  BFD_JUMP_TABLE_COPY (_bfd_generic),
1326
  BFD_JUMP_TABLE_CORE (_bfd_nocore),
1327
  BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
1328
  BFD_JUMP_TABLE_SYMBOLS (srec),
1329
  BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
1330
  BFD_JUMP_TABLE_WRITE (srec),
1331
  BFD_JUMP_TABLE_LINK (srec),
1332
  BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
1333
 
1334
  NULL,
1335
 
1336
  NULL
1337
};
1338
 
1339
const bfd_target symbolsrec_vec =
1340
{
1341
  "symbolsrec",			/* Name.  */
1342
  bfd_target_srec_flavour,
1343
  BFD_ENDIAN_UNKNOWN,		/* Target byte order.  */
1344
  BFD_ENDIAN_UNKNOWN,		/* Target headers byte order.  */
1345
  (HAS_RELOC | EXEC_P |		/* Object flags.  */
1346
   HAS_LINENO | HAS_DEBUG |
1347
   HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
1348
  (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS
1349
   | SEC_ALLOC | SEC_LOAD | SEC_RELOC),	/* Section flags.  */
1350
  0,				/* Leading underscore.  */
1351
  ' ',				/* AR_pad_char.  */
1352
  16,				/* AR_max_namelen.  */
1353
  0,				/* match priority.  */
1354
  bfd_getb64, bfd_getb_signed_64, bfd_putb64,
1355
  bfd_getb32, bfd_getb_signed_32, bfd_putb32,
1356
  bfd_getb16, bfd_getb_signed_16, bfd_putb16,	/* Data.  */
1357
  bfd_getb64, bfd_getb_signed_64, bfd_putb64,
1358
  bfd_getb32, bfd_getb_signed_32, bfd_putb32,
1359
  bfd_getb16, bfd_getb_signed_16, bfd_putb16,	/* Headers.  */
1360
 
1361
  {
1362
    _bfd_dummy_target,
1363
    symbolsrec_object_p,	/* bfd_check_format.  */
1364
    _bfd_dummy_target,
1365
    _bfd_dummy_target,
1366
  },
1367
  {
1368
    bfd_false,
1369
    srec_mkobject,
1370
    _bfd_generic_mkarchive,
1371
    bfd_false,
1372
  },
1373
  {				/* bfd_write_contents.  */
1374
    bfd_false,
1375
    symbolsrec_write_object_contents,
1376
    _bfd_write_archive_contents,
1377
    bfd_false,
1378
  },
1379
 
1380
  BFD_JUMP_TABLE_GENERIC (srec),
1381
  BFD_JUMP_TABLE_COPY (_bfd_generic),
1382
  BFD_JUMP_TABLE_CORE (_bfd_nocore),
1383
  BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
1384
  BFD_JUMP_TABLE_SYMBOLS (srec),
1385
  BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
1386
  BFD_JUMP_TABLE_WRITE (srec),
1387
  BFD_JUMP_TABLE_LINK (srec),
1388
  BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
1389
 
1390
  NULL,
1391
 
1392
  NULL
1393
};