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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [bfd/] [srec.c] - Blame information for rev 578

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

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

powered by: WebSVN 2.1.0

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