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

Subversion Repositories or1k_old

[/] [or1k_old/] [tags/] [VER_5_3/] [gdb-5.3/] [bfd/] [srec.c] - Blame information for rev 1782

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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