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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [binutils-2.18.50/] [bfd/] [srec.c] - Blame information for rev 156

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 38 julius
/* 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
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 = 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 = 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 = 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 = 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 = 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_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 = 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_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, section->used_by_bfd))
842
        return FALSE;
843
    }
844
 
845
  memcpy (location, (bfd_byte *) section->used_by_bfd + offset,
846
          (size_t) count);
847
 
848
  return TRUE;
849
}
850
 
851
/* Set the architecture.  We accept an unknown architecture here.  */
852
 
853
static bfd_boolean
854
srec_set_arch_mach (bfd *abfd, enum bfd_architecture arch, unsigned long mach)
855
{
856
  if (arch != bfd_arch_unknown)
857
    return bfd_default_set_arch_mach (abfd, arch, mach);
858
 
859
  abfd->arch_info = & bfd_default_arch_struct;
860
  return TRUE;
861
}
862
 
863
/* We have to save up all the Srecords for a splurge before output.  */
864
 
865
static bfd_boolean
866
srec_set_section_contents (bfd *abfd,
867
                           sec_ptr section,
868
                           const void * location,
869
                           file_ptr offset,
870
                           bfd_size_type bytes_to_do)
871
{
872
  tdata_type *tdata = abfd->tdata.srec_data;
873
  srec_data_list_type *entry;
874
 
875
  entry = bfd_alloc (abfd, sizeof (* entry));
876
  if (entry == NULL)
877
    return FALSE;
878
 
879
  if (bytes_to_do
880
      && (section->flags & SEC_ALLOC)
881
      && (section->flags & SEC_LOAD))
882
    {
883
      bfd_byte *data;
884
 
885
      data = bfd_alloc (abfd, bytes_to_do);
886
      if (data == NULL)
887
        return FALSE;
888
      memcpy ((void *) data, location, (size_t) bytes_to_do);
889
 
890
      /* Ff S3Forced is TRUE then always select S3 records,
891
         regardless of the siez of the addresses.  */
892
      if (S3Forced)
893
        tdata->type = 3;
894
      else if ((section->lma + offset + bytes_to_do - 1) <= 0xffff)
895
        ;  /* The default, S1, is OK.  */
896
      else if ((section->lma + offset + bytes_to_do - 1) <= 0xffffff
897
               && tdata->type <= 2)
898
        tdata->type = 2;
899
      else
900
        tdata->type = 3;
901
 
902
      entry->data = data;
903
      entry->where = section->lma + offset;
904
      entry->size = bytes_to_do;
905
 
906
      /* Sort the records by address.  Optimize for the common case of
907
         adding a record to the end of the list.  */
908
      if (tdata->tail != NULL
909
          && entry->where >= tdata->tail->where)
910
        {
911
          tdata->tail->next = entry;
912
          entry->next = NULL;
913
          tdata->tail = entry;
914
        }
915
      else
916
        {
917
          srec_data_list_type **look;
918
 
919
          for (look = &tdata->head;
920
               *look != NULL && (*look)->where < entry->where;
921
               look = &(*look)->next)
922
            ;
923
          entry->next = *look;
924
          *look = entry;
925
          if (entry->next == NULL)
926
            tdata->tail = entry;
927
        }
928
    }
929
  return TRUE;
930
}
931
 
932
/* Write a record of type, of the supplied number of bytes. The
933
   supplied bytes and length don't have a checksum. That's worked out
934
   here.  */
935
 
936
static bfd_boolean
937
srec_write_record (bfd *abfd,
938
                   unsigned int type,
939
                   bfd_vma address,
940
                   const bfd_byte *data,
941
                   const bfd_byte *end)
942
{
943
  char buffer[2 * MAXCHUNK + 6];
944
  unsigned int check_sum = 0;
945
  const bfd_byte *src = data;
946
  char *dst = buffer;
947
  char *length;
948
  bfd_size_type wrlen;
949
 
950
  *dst++ = 'S';
951
  *dst++ = '0' + type;
952
 
953
  length = dst;
954
  dst += 2;                     /* Leave room for dst.  */
955
 
956
  switch (type)
957
    {
958
    case 3:
959
    case 7:
960
      TOHEX (dst, (address >> 24), check_sum);
961
      dst += 2;
962
    case 8:
963
    case 2:
964
      TOHEX (dst, (address >> 16), check_sum);
965
      dst += 2;
966
    case 9:
967
    case 1:
968
    case 0:
969
      TOHEX (dst, (address >> 8), check_sum);
970
      dst += 2;
971
      TOHEX (dst, (address), check_sum);
972
      dst += 2;
973
      break;
974
 
975
    }
976
  for (src = data; src < end; src++)
977
    {
978
      TOHEX (dst, *src, check_sum);
979
      dst += 2;
980
    }
981
 
982
  /* Fill in the length.  */
983
  TOHEX (length, (dst - length) / 2, check_sum);
984
  check_sum &= 0xff;
985
  check_sum = 255 - check_sum;
986
  TOHEX (dst, check_sum, check_sum);
987
  dst += 2;
988
 
989
  *dst++ = '\r';
990
  *dst++ = '\n';
991
  wrlen = dst - buffer;
992
 
993
  return bfd_bwrite ((void *) buffer, wrlen, abfd) == wrlen;
994
}
995
 
996
static bfd_boolean
997
srec_write_header (bfd *abfd)
998
{
999
  unsigned int len = strlen (abfd->filename);
1000
 
1001
  /* I'll put an arbitrary 40 char limit on header size.  */
1002
  if (len > 40)
1003
    len = 40;
1004
 
1005
  return srec_write_record (abfd, 0, (bfd_vma) 0,
1006
                            (bfd_byte *) abfd->filename,
1007
                            (bfd_byte *) abfd->filename + len);
1008
}
1009
 
1010
static bfd_boolean
1011
srec_write_section (bfd *abfd,
1012
                    tdata_type *tdata,
1013
                    srec_data_list_type *list)
1014
{
1015
  unsigned int octets_written = 0;
1016
  bfd_byte *location = list->data;
1017
 
1018
  /* Validate number of data bytes to write.  The srec length byte
1019
     counts the address, data and crc bytes.  S1 (tdata->type == 1)
1020
     records have two address bytes, S2 (tdata->type == 2) records
1021
     have three, and S3 (tdata->type == 3) records have four.
1022
     The total length can't exceed 255, and a zero data length will
1023
     spin for a long time.  */
1024
  if (Chunk == 0)
1025
    Chunk = 1;
1026
  else if (Chunk > MAXCHUNK - tdata->type - 2)
1027
    Chunk = MAXCHUNK - tdata->type - 2;
1028
 
1029
  while (octets_written < list->size)
1030
    {
1031
      bfd_vma address;
1032
      unsigned int octets_this_chunk = list->size - octets_written;
1033
 
1034
      if (octets_this_chunk > Chunk)
1035
        octets_this_chunk = Chunk;
1036
 
1037
      address = list->where + octets_written / bfd_octets_per_byte (abfd);
1038
 
1039
      if (! srec_write_record (abfd,
1040
                               tdata->type,
1041
                               address,
1042
                               location,
1043
                               location + octets_this_chunk))
1044
        return FALSE;
1045
 
1046
      octets_written += octets_this_chunk;
1047
      location += octets_this_chunk;
1048
    }
1049
 
1050
  return TRUE;
1051
}
1052
 
1053
static bfd_boolean
1054
srec_write_terminator (bfd *abfd, tdata_type *tdata)
1055
{
1056
  return srec_write_record (abfd, 10 - tdata->type,
1057
                            abfd->start_address, NULL, NULL);
1058
}
1059
 
1060
static bfd_boolean
1061
srec_write_symbols (bfd *abfd)
1062
{
1063
  /* Dump out the symbols of a bfd.  */
1064
  int i;
1065
  int count = bfd_get_symcount (abfd);
1066
 
1067
  if (count)
1068
    {
1069
      bfd_size_type len;
1070
      asymbol **table = bfd_get_outsymbols (abfd);
1071
 
1072
      len = strlen (abfd->filename);
1073
      if (bfd_bwrite ("$$ ", (bfd_size_type) 3, abfd) != 3
1074
          || bfd_bwrite (abfd->filename, len, abfd) != len
1075
          || bfd_bwrite ("\r\n", (bfd_size_type) 2, abfd) != 2)
1076
        return FALSE;
1077
 
1078
      for (i = 0; i < count; i++)
1079
        {
1080
          asymbol *s = table[i];
1081
          if (! bfd_is_local_label (abfd, s)
1082
              && (s->flags & BSF_DEBUGGING) == 0)
1083
            {
1084
              /* Just dump out non debug symbols.  */
1085
              char buf[43], *p;
1086
 
1087
              len = strlen (s->name);
1088
              if (bfd_bwrite ("  ", (bfd_size_type) 2, abfd) != 2
1089
                  || bfd_bwrite (s->name, len, abfd) != len)
1090
                return FALSE;
1091
 
1092
              sprintf_vma (buf + 2, (s->value
1093
                                     + s->section->output_section->lma
1094
                                     + s->section->output_offset));
1095
              p = buf + 2;
1096
              while (p[0] == '0' && p[1] != 0)
1097
                p++;
1098
              len = strlen (p);
1099
              p[len] = '\r';
1100
              p[len + 1] = '\n';
1101
              *--p = '$';
1102
              *--p = ' ';
1103
              len += 4;
1104
              if (bfd_bwrite (p, len, abfd) != len)
1105
                return FALSE;
1106
            }
1107
        }
1108
      if (bfd_bwrite ("$$ \r\n", (bfd_size_type) 5, abfd) != 5)
1109
        return FALSE;
1110
    }
1111
 
1112
  return TRUE;
1113
}
1114
 
1115
static bfd_boolean
1116
internal_srec_write_object_contents (bfd *abfd, int symbols)
1117
{
1118
  tdata_type *tdata = abfd->tdata.srec_data;
1119
  srec_data_list_type *list;
1120
 
1121
  if (symbols)
1122
    {
1123
      if (! srec_write_symbols (abfd))
1124
        return FALSE;
1125
    }
1126
 
1127
  if (! srec_write_header (abfd))
1128
    return FALSE;
1129
 
1130
  /* Now wander though all the sections provided and output them.  */
1131
  list = tdata->head;
1132
 
1133
  while (list != (srec_data_list_type *) NULL)
1134
    {
1135
      if (! srec_write_section (abfd, tdata, list))
1136
        return FALSE;
1137
      list = list->next;
1138
    }
1139
  return srec_write_terminator (abfd, tdata);
1140
}
1141
 
1142
static bfd_boolean
1143
srec_write_object_contents (bfd *abfd)
1144
{
1145
  return internal_srec_write_object_contents (abfd, 0);
1146
}
1147
 
1148
static bfd_boolean
1149
symbolsrec_write_object_contents (bfd *abfd)
1150
{
1151
  return internal_srec_write_object_contents (abfd, 1);
1152
}
1153
 
1154
static int
1155
srec_sizeof_headers (bfd *abfd ATTRIBUTE_UNUSED,
1156
                     struct bfd_link_info *info ATTRIBUTE_UNUSED)
1157
{
1158
  return 0;
1159
}
1160
 
1161
/* Return the amount of memory needed to read the symbol table.  */
1162
 
1163
static long
1164
srec_get_symtab_upper_bound (bfd *abfd)
1165
{
1166
  return (bfd_get_symcount (abfd) + 1) * sizeof (asymbol *);
1167
}
1168
 
1169
/* Return the symbol table.  */
1170
 
1171
static long
1172
srec_canonicalize_symtab (bfd *abfd, asymbol **alocation)
1173
{
1174
  bfd_size_type symcount = bfd_get_symcount (abfd);
1175
  asymbol *csymbols;
1176
  unsigned int i;
1177
 
1178
  csymbols = abfd->tdata.srec_data->csymbols;
1179
  if (csymbols == NULL && symcount != 0)
1180
    {
1181
      asymbol *c;
1182
      struct srec_symbol *s;
1183
 
1184
      csymbols = bfd_alloc (abfd, symcount * sizeof (asymbol));
1185
      if (csymbols == NULL)
1186
        return -1;
1187
      abfd->tdata.srec_data->csymbols = csymbols;
1188
 
1189
      for (s = abfd->tdata.srec_data->symbols, c = csymbols;
1190
           s != NULL;
1191
           s = s->next, ++c)
1192
        {
1193
          c->the_bfd = abfd;
1194
          c->name = s->name;
1195
          c->value = s->val;
1196
          c->flags = BSF_GLOBAL;
1197
          c->section = bfd_abs_section_ptr;
1198
          c->udata.p = NULL;
1199
        }
1200
    }
1201
 
1202
  for (i = 0; i < symcount; i++)
1203
    *alocation++ = csymbols++;
1204
  *alocation = NULL;
1205
 
1206
  return symcount;
1207
}
1208
 
1209
static void
1210
srec_get_symbol_info (bfd *ignore_abfd ATTRIBUTE_UNUSED,
1211
                      asymbol *symbol,
1212
                      symbol_info *ret)
1213
{
1214
  bfd_symbol_info (symbol, ret);
1215
}
1216
 
1217
static void
1218
srec_print_symbol (bfd *abfd,
1219
                   void * afile,
1220
                   asymbol *symbol,
1221
                   bfd_print_symbol_type how)
1222
{
1223
  FILE *file = (FILE *) afile;
1224
 
1225
  switch (how)
1226
    {
1227
    case bfd_print_symbol_name:
1228
      fprintf (file, "%s", symbol->name);
1229
      break;
1230
    default:
1231
      bfd_print_symbol_vandf (abfd, (void *) file, symbol);
1232
      fprintf (file, " %-5s %s",
1233
               symbol->section->name,
1234
               symbol->name);
1235
    }
1236
}
1237
 
1238
#define srec_close_and_cleanup                    _bfd_generic_close_and_cleanup
1239
#define srec_bfd_free_cached_info                 _bfd_generic_bfd_free_cached_info
1240
#define srec_new_section_hook                     _bfd_generic_new_section_hook
1241
#define srec_bfd_is_target_special_symbol         ((bfd_boolean (*) (bfd *, asymbol *)) bfd_false)
1242
#define srec_bfd_is_local_label_name              bfd_generic_is_local_label_name
1243
#define srec_get_lineno                           _bfd_nosymbols_get_lineno
1244
#define srec_find_nearest_line                    _bfd_nosymbols_find_nearest_line
1245
#define srec_find_inliner_info                    _bfd_nosymbols_find_inliner_info
1246
#define srec_make_empty_symbol                    _bfd_generic_make_empty_symbol
1247
#define srec_bfd_make_debug_symbol                _bfd_nosymbols_bfd_make_debug_symbol
1248
#define srec_read_minisymbols                     _bfd_generic_read_minisymbols
1249
#define srec_minisymbol_to_symbol                 _bfd_generic_minisymbol_to_symbol
1250
#define srec_get_section_contents_in_window       _bfd_generic_get_section_contents_in_window
1251
#define srec_bfd_get_relocated_section_contents   bfd_generic_get_relocated_section_contents
1252
#define srec_bfd_relax_section                    bfd_generic_relax_section
1253
#define srec_bfd_gc_sections                      bfd_generic_gc_sections
1254
#define srec_bfd_merge_sections                   bfd_generic_merge_sections
1255
#define srec_bfd_is_group_section                 bfd_generic_is_group_section
1256
#define srec_bfd_discard_group                    bfd_generic_discard_group
1257
#define srec_section_already_linked               _bfd_generic_section_already_linked
1258
#define srec_bfd_link_hash_table_create           _bfd_generic_link_hash_table_create
1259
#define srec_bfd_link_hash_table_free             _bfd_generic_link_hash_table_free
1260
#define srec_bfd_link_add_symbols                 _bfd_generic_link_add_symbols
1261
#define srec_bfd_link_just_syms                   _bfd_generic_link_just_syms
1262
#define srec_bfd_final_link                       _bfd_generic_final_link
1263
#define srec_bfd_link_split_section               _bfd_generic_link_split_section
1264
 
1265
const bfd_target srec_vec =
1266
{
1267
  "srec",                       /* Name.  */
1268
  bfd_target_srec_flavour,
1269
  BFD_ENDIAN_UNKNOWN,           /* Target byte order.  */
1270
  BFD_ENDIAN_UNKNOWN,           /* Target headers byte order.  */
1271
  (HAS_RELOC | EXEC_P |         /* Object flags.  */
1272
   HAS_LINENO | HAS_DEBUG |
1273
   HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
1274
  (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS
1275
   | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* Section flags.  */
1276
  0,                             /* Leading underscore.  */
1277
  ' ',                          /* AR_pad_char.  */
1278
  16,                           /* AR_max_namelen.  */
1279
  bfd_getb64, bfd_getb_signed_64, bfd_putb64,
1280
  bfd_getb32, bfd_getb_signed_32, bfd_putb32,
1281
  bfd_getb16, bfd_getb_signed_16, bfd_putb16,   /* Data.  */
1282
  bfd_getb64, bfd_getb_signed_64, bfd_putb64,
1283
  bfd_getb32, bfd_getb_signed_32, bfd_putb32,
1284
  bfd_getb16, bfd_getb_signed_16, bfd_putb16,   /* Hdrs.  */
1285
 
1286
  {
1287
    _bfd_dummy_target,
1288
    srec_object_p,              /* bfd_check_format.  */
1289
    _bfd_dummy_target,
1290
    _bfd_dummy_target,
1291
  },
1292
  {
1293
    bfd_false,
1294
    srec_mkobject,
1295
    _bfd_generic_mkarchive,
1296
    bfd_false,
1297
  },
1298
  {                             /* bfd_write_contents.  */
1299
    bfd_false,
1300
    srec_write_object_contents,
1301
    _bfd_write_archive_contents,
1302
    bfd_false,
1303
  },
1304
 
1305
  BFD_JUMP_TABLE_GENERIC (srec),
1306
  BFD_JUMP_TABLE_COPY (_bfd_generic),
1307
  BFD_JUMP_TABLE_CORE (_bfd_nocore),
1308
  BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
1309
  BFD_JUMP_TABLE_SYMBOLS (srec),
1310
  BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
1311
  BFD_JUMP_TABLE_WRITE (srec),
1312
  BFD_JUMP_TABLE_LINK (srec),
1313
  BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
1314
 
1315
  NULL,
1316
 
1317
  NULL
1318
};
1319
 
1320
const bfd_target symbolsrec_vec =
1321
{
1322
  "symbolsrec",                 /* Name.  */
1323
  bfd_target_srec_flavour,
1324
  BFD_ENDIAN_UNKNOWN,           /* Target byte order.  */
1325
  BFD_ENDIAN_UNKNOWN,           /* Target headers byte order.  */
1326
  (HAS_RELOC | EXEC_P |         /* Object flags.  */
1327
   HAS_LINENO | HAS_DEBUG |
1328
   HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
1329
  (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS
1330
   | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* Section flags.  */
1331
  0,                             /* Leading underscore.  */
1332
  ' ',                          /* AR_pad_char.  */
1333
  16,                           /* AR_max_namelen.  */
1334
  bfd_getb64, bfd_getb_signed_64, bfd_putb64,
1335
  bfd_getb32, bfd_getb_signed_32, bfd_putb32,
1336
  bfd_getb16, bfd_getb_signed_16, bfd_putb16,   /* Data.  */
1337
  bfd_getb64, bfd_getb_signed_64, bfd_putb64,
1338
  bfd_getb32, bfd_getb_signed_32, bfd_putb32,
1339
  bfd_getb16, bfd_getb_signed_16, bfd_putb16,   /* Headers.  */
1340
 
1341
  {
1342
    _bfd_dummy_target,
1343
    symbolsrec_object_p,        /* bfd_check_format.  */
1344
    _bfd_dummy_target,
1345
    _bfd_dummy_target,
1346
  },
1347
  {
1348
    bfd_false,
1349
    srec_mkobject,
1350
    _bfd_generic_mkarchive,
1351
    bfd_false,
1352
  },
1353
  {                             /* bfd_write_contents.  */
1354
    bfd_false,
1355
    symbolsrec_write_object_contents,
1356
    _bfd_write_archive_contents,
1357
    bfd_false,
1358
  },
1359
 
1360
  BFD_JUMP_TABLE_GENERIC (srec),
1361
  BFD_JUMP_TABLE_COPY (_bfd_generic),
1362
  BFD_JUMP_TABLE_CORE (_bfd_nocore),
1363
  BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
1364
  BFD_JUMP_TABLE_SYMBOLS (srec),
1365
  BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
1366
  BFD_JUMP_TABLE_WRITE (srec),
1367
  BFD_JUMP_TABLE_LINK (srec),
1368
  BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
1369
 
1370
  NULL,
1371
 
1372
  NULL
1373
};

powered by: WebSVN 2.1.0

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