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

Subversion Repositories or1k

[/] [or1k/] [branches/] [oc/] [gdb-5.0/] [bfd/] [srec.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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