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