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

Subversion Repositories open8_urisc

[/] [open8_urisc/] [trunk/] [gnu/] [binutils/] [bfd/] [srec.c] - Blame information for rev 14

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

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

powered by: WebSVN 2.1.0

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