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