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