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