* Makefile.in (TE_OBJS): Add empty definition.
[deliverable/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
KR
109#include "libiberty.h"
110
111static void srec_init PARAMS ((void));
112static boolean srec_mkobject PARAMS ((bfd *));
113static int srec_get_byte PARAMS ((bfd *, boolean *));
114static void srec_bad_byte PARAMS ((bfd *, unsigned int, int, boolean));
115static boolean srec_scan PARAMS ((bfd *));
116static const bfd_target *srec_object_p PARAMS ((bfd *));
117static const bfd_target *symbolsrec_object_p PARAMS ((bfd *));
118static boolean srec_read_section PARAMS ((bfd *, asection *, bfd_byte *));
4a81b561 119
6d4f7715 120static boolean srec_write_record PARAMS ((bfd *, int, bfd_vma,
7f4c005d
KR
121 const bfd_byte *,
122 const bfd_byte *));
6d4f7715
ILT
123static boolean srec_write_header PARAMS ((bfd *));
124static boolean srec_write_symbols PARAMS ((bfd *));
125
4c8d6c9f 126/* Macros for converting between hex and binary. */
4a81b561 127
3039e8ee 128static CONST char digs[] = "0123456789ABCDEF";
5f9ca960 129
7f4c005d 130#define NIBBLE(x) hex_value(x)
9898b929 131#define HEX(buffer) ((NIBBLE((buffer)[0])<<4) + NIBBLE((buffer)[1]))
5f9ca960
JG
132#define TOHEX(d, x, ch) \
133 d[1] = digs[(x) & 0xf]; \
134 d[0] = digs[((x)>>4)&0xf]; \
135 ch += ((x) & 0xff);
7f4c005d 136#define ISHEX(x) hex_p(x)
4a81b561 137
4c8d6c9f 138/* Initialize by filling in the hex conversion array. */
9898b929 139
e98e6ec1 140static void
57a1867e 141srec_init ()
9898b929 142{
9783e04a
DM
143 static boolean inited = false;
144
145 if (inited == false)
9898b929 146 {
9783e04a 147 inited = true;
7f4c005d 148 hex_init ();
9783e04a 149 }
9898b929
JG
150}
151
4a81b561 152/* The maximum number of bytes on a line is FF */
9783e04a 153#define MAXCHUNK 0xff
4a81b561 154/* The number of bytes we fit onto a line on output */
9898b929
JG
155#define CHUNK 21
156
7f4c005d
KR
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. */
9898b929
JG
159
160struct srec_data_list_struct
161{
7f4c005d
KR
162 struct srec_data_list_struct *next;
163 bfd_byte *data;
9783e04a
DM
164 bfd_vma where;
165 bfd_size_type size;
7f4c005d 166};
9783e04a 167
7f4c005d 168typedef struct srec_data_list_struct srec_data_list_type;
8f8fefcc 169
7f4c005d
KR
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
174struct srec_symbol
175{
176 struct srec_symbol *next;
177 const char *name;
178 bfd_vma val;
9783e04a 179};
9898b929 180
7f4c005d 181/* The S-record tdata information. */
4a81b561 182
9783e04a
DM
183typedef struct srec_data_struct
184 {
185 srec_data_list_type *head;
d4d16683 186 srec_data_list_type *tail;
9898b929 187 unsigned int type;
7f4c005d
KR
188 struct srec_symbol *symbols;
189 struct srec_symbol *symtail;
190 asymbol *csymbols;
9783e04a
DM
191 }
192tdata_type;
9898b929 193
6d4f7715
ILT
194static boolean srec_write_section PARAMS ((bfd *, tdata_type *,
195 srec_data_list_type *));
196static boolean srec_write_terminator PARAMS ((bfd *, tdata_type *));
9898b929 197
7f4c005d 198/* Set up the S-record tdata information. */
9898b929 199
7f4c005d
KR
200static boolean
201srec_mkobject (abfd)
9783e04a 202 bfd *abfd;
9783e04a 203{
7f4c005d 204 srec_init ();
8f8fefcc 205
7f4c005d 206 if (abfd->tdata.srec_data == NULL)
8f8fefcc 207 {
7f4c005d
KR
208 tdata_type *tdata = (tdata_type *) bfd_alloc (abfd, sizeof (tdata_type));
209 if (tdata == NULL)
9783e04a 210 {
7f4c005d
KR
211 bfd_set_error (bfd_error_no_memory);
212 return false;
9783e04a 213 }
7f4c005d
KR
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;
9783e04a 221 }
4a81b561 222
7f4c005d
KR
223 return true;
224}
357a1f38 225
7f4c005d
KR
226/* Read a byte from an S record file. Set *ERRORPTR if an error
227 occurred. Return EOF on error or end of file. */
4a81b561 228
7f4c005d
KR
229static int
230srec_get_byte (abfd, errorptr)
57a1867e 231 bfd *abfd;
7f4c005d 232 boolean *errorptr;
9783e04a 233{
7f4c005d
KR
234 bfd_byte c;
235
236 if (bfd_read (&c, 1, 1, abfd) != 1)
9783e04a 237 {
7f4c005d
KR
238 if (bfd_get_error () != bfd_error_file_truncated)
239 *errorptr = true;
240 return EOF;
9783e04a 241 }
7f4c005d
KR
242
243 return (int) (c & 0xff);
4a81b561
DHW
244}
245
7f4c005d
KR
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. */
387cbb2b 249
7f4c005d
KR
250static void
251srec_bad_byte (abfd, lineno, c, error)
9783e04a 252 bfd *abfd;
7f4c005d
KR
253 unsigned int lineno;
254 int c;
255 boolean error;
8f8fefcc 256{
7f4c005d 257 if (c == EOF)
9783e04a 258 {
7f4c005d
KR
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);
9783e04a 276 }
8f8fefcc
JG
277}
278
7f4c005d
KR
279/* Add a new symbol found in an S-record file. */
280
8f8fefcc 281static boolean
7f4c005d 282srec_new_symbol (abfd, name, val)
57a1867e 283 bfd *abfd;
7f4c005d
KR
284 const char *name;
285 bfd_vma val;
8f8fefcc 286{
7f4c005d
KR
287 struct srec_symbol *n;
288
289 n = (struct srec_symbol *) bfd_alloc (abfd, sizeof (struct srec_symbol));
290 if (n == NULL)
9783e04a 291 {
7f4c005d
KR
292 bfd_set_error (bfd_error_no_memory);
293 return false;
9783e04a 294 }
9783e04a 295
7f4c005d
KR
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;
8f8fefcc
JG
309}
310
7f4c005d
KR
311/* Read the S record file and turn it into sections. We create a new
312 section for each contiguous set of bytes. */
313
314static boolean
315srec_scan (abfd)
4c3721d5 316 bfd *abfd;
4a81b561 317{
7f4c005d
KR
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;
e98e6ec1 324
6d4f7715 325 if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
7f4c005d
KR
326 goto error_return;
327
328 while ((c = srec_get_byte (abfd, &error)) != EOF)
4a81b561 329 {
7f4c005d
KR
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)
8f8fefcc 336 {
9783e04a 337 default:
7f4c005d
KR
338 srec_bad_byte (abfd, lineno, c, error);
339 goto error_return;
340
341 case '\n':
342 ++lineno;
343 break;
344
345 case '\r':
9783e04a
DM
346 break;
347
348 case '$':
7f4c005d
KR
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)
9783e04a 354 {
7f4c005d
KR
355 srec_bad_byte (abfd, lineno, c, error);
356 goto error_return;
9783e04a 357 }
7f4c005d
KR
358
359 ++lineno;
360
9783e04a
DM
361 break;
362
363 case ' ':
7f4c005d
KR
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 }
4c3721d5 377
7f4c005d
KR
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)
4c3721d5 383 {
7f4c005d
KR
384 srec_bad_byte (abfd, lineno, c, error);
385 goto error_return;
386 }
9783e04a 387
7f4c005d
KR
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 }
9783e04a 403
7f4c005d
KR
404 /* Skip a dollar sign before the hex value. */
405 if (c == '$')
406 {
407 c = srec_get_byte (abfd, &error);
408 if (c == EOF)
9783e04a 409 {
7f4c005d
KR
410 srec_bad_byte (abfd, lineno, c, error);
411 goto error_return;
9783e04a 412 }
4c3721d5 413 }
7f4c005d
KR
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 }
9783e04a 436 break;
7f4c005d 437
9783e04a 438 case 'S':
7f4c005d
KR
439 {
440 file_ptr pos;
441 char hdr[3];
442 unsigned int bytes;
443 bfd_vma address;
444 bfd_byte *data;
9783e04a 445
7f4c005d 446 /* Starting an S-record. */
9783e04a 447
7f4c005d 448 pos = bfd_tell (abfd) - 1;
9783e04a 449
7f4c005d
KR
450 if (bfd_read (hdr, 1, 3, abfd) != 3)
451 goto error_return;
9783e04a 452
7f4c005d
KR
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 }
9783e04a 462
7f4c005d
KR
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 }
9783e04a 476
7f4c005d
KR
477 if (bfd_read (buf, 1, bytes * 2, abfd) != bytes * 2)
478 goto error_return;
9783e04a 479
7f4c005d
KR
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;
8f8fefcc 561 }
4a81b561 562 }
9898b929 563
7f4c005d
KR
564 if (error)
565 goto error_return;
4a81b561 566
7f4c005d
KR
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;
8f8fefcc 576}
9898b929 577
7f4c005d
KR
578/* Check whether an existing file is an S-record file. */
579
2f3508ad 580static const bfd_target *
57a1867e
DM
581srec_object_p (abfd)
582 bfd *abfd;
4a81b561 583{
7f4c005d 584 bfd_byte b[4];
8f8fefcc 585
9783e04a 586 srec_init ();
9898b929 587
6d4f7715
ILT
588 if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0
589 || bfd_read (b, 1, 4, abfd) != 4)
590 return NULL;
9783e04a
DM
591
592 if (b[0] != 'S' || !ISHEX (b[1]) || !ISHEX (b[2]) || !ISHEX (b[3]))
7f4c005d
KR
593 {
594 bfd_set_error (bfd_error_wrong_format);
595 return NULL;
596 }
9783e04a 597
7f4c005d
KR
598 if (! srec_mkobject (abfd)
599 || ! srec_scan (abfd))
600 return NULL;
4a81b561 601
7f4c005d 602 return abfd->xvec;
8f8fefcc
JG
603}
604
7f4c005d 605/* Check whether an existing file is an S-record file with symbols. */
8f8fefcc 606
2f3508ad 607static const bfd_target *
57a1867e
DM
608symbolsrec_object_p (abfd)
609 bfd *abfd;
8f8fefcc 610{
7f4c005d 611 char b[2];
8f8fefcc 612
9783e04a
DM
613 srec_init ();
614
6d4f7715 615 if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0
7f4c005d 616 || bfd_read (b, 1, 2, abfd) != 2)
6d4f7715 617 return NULL;
8f8fefcc
JG
618
619 if (b[0] != '$' || b[1] != '$')
7f4c005d
KR
620 {
621 bfd_set_error (bfd_error_wrong_format);
622 return NULL;
623 }
8f8fefcc 624
7f4c005d
KR
625 if (! srec_mkobject (abfd)
626 || ! srec_scan (abfd))
627 return NULL;
628
629 return abfd->xvec;
4a81b561
DHW
630}
631
7f4c005d
KR
632/* Read in the contents of a section in an S-record file. */
633
634static boolean
635srec_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. */
4a81b561 753
4a81b561 754static boolean
57a1867e
DM
755srec_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;
9783e04a 761{
7f4c005d 762 if (section->used_by_bfd == NULL)
9898b929 763 {
7f4c005d
KR
764 section->used_by_bfd = bfd_alloc (abfd, section->_raw_size);
765 if (section->used_by_bfd == NULL
766 && section->_raw_size != 0)
9783e04a 767 {
5e808126 768 bfd_set_error (bfd_error_no_memory);
9783e04a
DM
769 return false;
770 }
771
7f4c005d
KR
772 if (! srec_read_section (abfd, section, section->used_by_bfd))
773 return false;
9898b929 774 }
9783e04a 775
7f4c005d 776 memcpy (location, (bfd_byte *) section->used_by_bfd + offset, count);
4a81b561 777
7f4c005d 778 return true;
4a81b561
DHW
779}
780
c3246d9b 781/* we have to save up all the Srecords for a splurge before output */
4a81b561 782
9898b929 783static boolean
57a1867e
DM
784srec_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;
9783e04a
DM
790{
791 tdata_type *tdata = abfd->tdata.srec_data;
d4d16683 792 register srec_data_list_type *entry;
9783e04a 793
d4d16683
ILT
794 entry = ((srec_data_list_type *)
795 bfd_alloc (abfd, sizeof (srec_data_list_type)));
796 if (entry == NULL)
9783e04a 797 {
5e808126 798 bfd_set_error (bfd_error_no_memory);
9783e04a
DM
799 return false;
800 }
8f8fefcc 801
c3246d9b
ILT
802 if (bytes_to_do
803 && (section->flags & SEC_ALLOC)
9783e04a 804 && (section->flags & SEC_LOAD))
9898b929 805 {
7f4c005d 806 bfd_byte *data = (bfd_byte *) bfd_alloc (abfd, bytes_to_do);
d4d16683 807 if (data == NULL)
9783e04a 808 {
5e808126 809 bfd_set_error (bfd_error_no_memory);
9783e04a
DM
810 return false;
811 }
68241b2b 812 memcpy ((PTR) data, location, bytes_to_do);
9898b929 813
c3246d9b 814 if ((section->lma + offset + bytes_to_do - 1) <= 0xffff)
8f8fefcc 815 {
9898b929 816
8f8fefcc 817 }
c3246d9b 818 else if ((section->lma + offset + bytes_to_do - 1) <= 0xffffff
9783e04a 819 && tdata->type < 2)
8f8fefcc
JG
820 {
821 tdata->type = 2;
822 }
9783e04a 823 else
8f8fefcc
JG
824 {
825 tdata->type = 3;
826 }
827
828 entry->data = data;
829 entry->where = section->lma + offset;
830 entry->size = bytes_to_do;
d4d16683
ILT
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 }
8f8fefcc 854 }
9783e04a 855 return true;
9898b929
JG
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*/
6d4f7715 862static boolean
57a1867e
DM
863srec_write_record (abfd, type, address, data, end)
864 bfd *abfd;
6d4f7715 865 int type;
57a1867e 866 bfd_vma address;
7f4c005d
KR
867 const bfd_byte *data;
868 const bfd_byte *end;
9783e04a
DM
869{
870 char buffer[MAXCHUNK];
9783e04a 871 unsigned int check_sum = 0;
7f4c005d 872 CONST bfd_byte *src = data;
9783e04a
DM
873 char *dst = buffer;
874 char *length;
875
9783e04a
DM
876 *dst++ = 'S';
877 *dst++ = '0' + type;
878
879 length = dst;
880 dst += 2; /* leave room for dst*/
881
882 switch (type)
9898b929 883 {
9783e04a
DM
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;
4a81b561 900
4a81b561 901 }
9783e04a 902 for (src = data; src < end; src++)
9898b929 903 {
9783e04a
DM
904 TOHEX (dst, *src, check_sum);
905 dst += 2;
4a81b561
DHW
906 }
907
9783e04a
DM
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';
6d4f7715
ILT
917 if (bfd_write ((PTR) buffer, 1, dst - buffer, abfd) != dst - buffer)
918 return false;
919 return true;
9898b929 920}
4a81b561 921
4a81b561 922
4a81b561 923
6d4f7715 924static boolean
57a1867e
DM
925srec_write_header (abfd)
926 bfd *abfd;
9898b929 927{
7f4c005d
KR
928 bfd_byte buffer[MAXCHUNK];
929 bfd_byte *dst = buffer;
9783e04a 930 unsigned int i;
4a81b561 931
9783e04a
DM
932 /* I'll put an arbitary 40 char limit on header size */
933 for (i = 0; i < 40 && abfd->filename[i]; i++)
9898b929 934 {
9783e04a 935 *dst++ = abfd->filename[i];
9898b929 936 }
6d4f7715 937 return srec_write_record (abfd, 0, 0, buffer, dst);
4a81b561
DHW
938}
939
6d4f7715 940static boolean
57a1867e
DM
941srec_write_section (abfd, tdata, list)
942 bfd *abfd;
943 tdata_type *tdata;
944 srec_data_list_type *list;
9898b929 945{
9783e04a 946 unsigned int bytes_written = 0;
7f4c005d 947 bfd_byte *location = list->data;
9898b929 948
9783e04a 949 while (bytes_written < list->size)
9898b929 950 {
9783e04a
DM
951 bfd_vma address;
952
953 unsigned int bytes_this_chunk = list->size - bytes_written;
9898b929 954
9783e04a 955 if (bytes_this_chunk > CHUNK)
9898b929 956 {
9783e04a 957 bytes_this_chunk = CHUNK;
9898b929
JG
958 }
959
9783e04a 960 address = list->where + bytes_written;
9898b929 961
6d4f7715
ILT
962 if (! srec_write_record (abfd,
963 tdata->type,
964 address,
965 location,
966 location + bytes_this_chunk))
967 return false;
9898b929 968
9783e04a
DM
969 bytes_written += bytes_this_chunk;
970 location += bytes_this_chunk;
9898b929
JG
971 }
972
6d4f7715 973 return true;
9898b929
JG
974}
975
6d4f7715 976static boolean
57a1867e
DM
977srec_write_terminator (abfd, tdata)
978 bfd *abfd;
979 tdata_type *tdata;
9783e04a 980{
7f4c005d 981 bfd_byte buffer[2];
9783e04a 982
6d4f7715
ILT
983 return srec_write_record (abfd, 10 - tdata->type,
984 abfd->start_address, buffer, buffer);
9898b929 985}
3039e8ee 986
8f8fefcc 987
9783e04a 988
6d4f7715 989static boolean
9783e04a 990srec_write_symbols (abfd)
2c3b9e47 991 bfd *abfd;
9898b929 992{
8f8fefcc
JG
993 char buffer[MAXCHUNK];
994 /* Dump out the symbols of a bfd */
995 int i;
2f3508ad 996 int count = bfd_get_symcount (abfd);
8f8fefcc 997
2f3508ad 998 if (count)
9783e04a 999 {
6d4f7715 1000 size_t len;
9783e04a
DM
1001 asymbol **table = bfd_get_outsymbols (abfd);
1002 sprintf (buffer, "$$ %s\r\n", abfd->filename);
8f8fefcc 1003
2f3508ad 1004 len = strlen (buffer);
6d4f7715
ILT
1005 if (bfd_write (buffer, len, 1, abfd) != len)
1006 return false;
8f8fefcc 1007
2f3508ad 1008 for (i = 0; i < count; i++)
9783e04a
DM
1009 {
1010 asymbol *s = table[i];
8f8fefcc 1011#if 0
9783e04a 1012 int len = strlen (s->name);
8f8fefcc 1013
9783e04a 1014 /* If this symbol has a .[ocs] in it, it's probably a file name
8f8fefcc
JG
1015 and we'll output that as the module name */
1016
9783e04a
DM
1017 if (len > 3 && s->name[len - 2] == '.')
1018 {
1019 int l;
1020 sprintf (buffer, "$$ %s\r\n", s->name);
1021 l = strlen (buffer);
6d4f7715
ILT
1022 if (bfd_write (buffer, l, 1, abfd) != l)
1023 return false;
9783e04a
DM
1024 }
1025 else
8f8fefcc 1026#endif
9783e04a
DM
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);
6d4f7715
ILT
1045 if (bfd_write (buffer, l, 1, abfd) != l)
1046 return false;
9783e04a
DM
1047 }
1048 }
1049 sprintf (buffer, "$$ \r\n");
2f3508ad 1050 len = strlen (buffer);
6d4f7715
ILT
1051 if (bfd_write (buffer, len, 1, abfd) != len)
1052 return false;
8f8fefcc 1053 }
6d4f7715
ILT
1054
1055 return true;
9898b929
JG
1056}
1057
9898b929 1058static boolean
9783e04a 1059internal_srec_write_object_contents (abfd, symbols)
8f8fefcc
JG
1060 bfd *abfd;
1061 int symbols;
4a81b561 1062{
9783e04a
DM
1063 tdata_type *tdata = abfd->tdata.srec_data;
1064 srec_data_list_type *list;
9898b929 1065
9783e04a 1066 if (symbols)
6d4f7715
ILT
1067 {
1068 if (! srec_write_symbols (abfd))
1069 return false;
1070 }
8f8fefcc 1071
6d4f7715
ILT
1072 if (! srec_write_header (abfd))
1073 return false;
8f8fefcc 1074
9783e04a
DM
1075 /* Now wander though all the sections provided and output them */
1076 list = tdata->head;
9898b929 1077
9783e04a 1078 while (list != (srec_data_list_type *) NULL)
9898b929 1079 {
6d4f7715
ILT
1080 if (! srec_write_section (abfd, tdata, list))
1081 return false;
9783e04a 1082 list = list->next;
9898b929 1083 }
6d4f7715 1084 return srec_write_terminator (abfd, tdata);
4a81b561
DHW
1085}
1086
8f8fefcc 1087static boolean
9783e04a 1088srec_write_object_contents (abfd)
8f8fefcc
JG
1089 bfd *abfd;
1090{
9783e04a 1091 return internal_srec_write_object_contents (abfd, 0);
8f8fefcc
JG
1092}
1093
1094static boolean
9783e04a 1095symbolsrec_write_object_contents (abfd)
8f8fefcc
JG
1096 bfd *abfd;
1097{
9783e04a 1098 return internal_srec_write_object_contents (abfd, 1);
8f8fefcc
JG
1099}
1100
9783e04a
DM
1101/*ARGSUSED*/
1102static int
57a1867e
DM
1103srec_sizeof_headers (abfd, exec)
1104 bfd *abfd;
1105 boolean exec;
39a2ce33 1106{
9783e04a 1107 return 0;
39a2ce33
SC
1108}
1109
357a1f38 1110static asymbol *
57a1867e
DM
1111srec_make_empty_symbol (abfd)
1112 bfd *abfd;
357a1f38 1113{
9783e04a
DM
1114 asymbol *new = (asymbol *) bfd_zalloc (abfd, sizeof (asymbol));
1115 if (new)
1116 new->the_bfd = abfd;
357a1f38
SC
1117 return new;
1118}
8f8fefcc 1119
7f4c005d
KR
1120/* Return the amount of memory needed to read the symbol table. */
1121
326e32d7 1122static long
9783e04a
DM
1123srec_get_symtab_upper_bound (abfd)
1124 bfd *abfd;
8f8fefcc 1125{
7f4c005d 1126 return (bfd_get_symcount (abfd) + 1) * sizeof (asymbol *);
8f8fefcc
JG
1127}
1128
7f4c005d
KR
1129/* Return the symbol table. */
1130
326e32d7 1131static long
57a1867e
DM
1132srec_get_symtab (abfd, alocation)
1133 bfd *abfd;
1134 asymbol **alocation;
8f8fefcc 1135{
7f4c005d
KR
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)
9783e04a 1142 {
7f4c005d
KR
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 }
9783e04a 1165 }
7f4c005d
KR
1166
1167 for (i = 0; i < symcount; i++)
1168 *alocation++ = csymbols++;
1169 *alocation = NULL;
1170
1171 return symcount;
8f8fefcc
JG
1172}
1173
9783e04a
DM
1174/*ARGSUSED*/
1175void
57a1867e
DM
1176srec_get_symbol_info (ignore_abfd, symbol, ret)
1177 bfd *ignore_abfd;
1178 asymbol *symbol;
1179 symbol_info *ret;
2c3b9e47
KR
1180{
1181 bfd_symbol_info (symbol, ret);
1182}
1183
9783e04a
DM
1184/*ARGSUSED*/
1185void
57a1867e
DM
1186srec_print_symbol (ignore_abfd, afile, symbol, how)
1187 bfd *ignore_abfd;
1188 PTR afile;
1189 asymbol *symbol;
1190 bfd_print_symbol_type how;
9783e04a
DM
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);
8f8fefcc 1203
9783e04a 1204 }
8f8fefcc
JG
1205}
1206
6812b607
ILT
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
9872a49c 1210
6812b607
ILT
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
c3246d9b
ILT
1215#define srec_read_minisymbols _bfd_generic_read_minisymbols
1216#define srec_minisymbol_to_symbol _bfd_generic_minisymbol_to_symbol
d0ec7a8e 1217
7f4c005d
KR
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
6812b607
ILT
1226#define srec_bfd_get_relocated_section_contents \
1227 bfd_generic_get_relocated_section_contents
294eaca4 1228#define srec_bfd_relax_section bfd_generic_relax_section
4c3721d5
ILT
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
c3246d9b 1232#define srec_bfd_link_split_section _bfd_generic_link_split_section
3039e8ee 1233
2f3508ad 1234const bfd_target srec_vec =
4a81b561 1235{
9783e04a
DM
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 */
9898b929
JG
1255
1256 {
9783e04a
DM
1257 _bfd_dummy_target,
1258 srec_object_p, /* bfd_check_format */
2f3508ad
ILT
1259 _bfd_dummy_target,
1260 _bfd_dummy_target,
9898b929
JG
1261 },
1262 {
9783e04a
DM
1263 bfd_false,
1264 srec_mkobject,
1265 _bfd_generic_mkarchive,
1266 bfd_false,
9898b929
JG
1267 },
1268 { /* bfd_write_contents */
9783e04a
DM
1269 bfd_false,
1270 srec_write_object_contents,
1271 _bfd_write_archive_contents,
1272 bfd_false,
9898b929 1273 },
6812b607
ILT
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),
7f4c005d 1280 BFD_JUMP_TABLE_RELOCS (srec),
6812b607
ILT
1281 BFD_JUMP_TABLE_WRITE (srec),
1282 BFD_JUMP_TABLE_LINK (srec),
dfc1c006 1283 BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
6812b607
ILT
1284
1285 (PTR) 0
9783e04a 1286};
9898b929 1287
8f8fefcc
JG
1288
1289
2f3508ad 1290const bfd_target symbolsrec_vec =
8f8fefcc 1291{
9783e04a
DM
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 */
8f8fefcc
JG
1311
1312 {
9783e04a
DM
1313 _bfd_dummy_target,
1314 symbolsrec_object_p, /* bfd_check_format */
2f3508ad
ILT
1315 _bfd_dummy_target,
1316 _bfd_dummy_target,
8f8fefcc
JG
1317 },
1318 {
9783e04a
DM
1319 bfd_false,
1320 srec_mkobject,
1321 _bfd_generic_mkarchive,
1322 bfd_false,
8f8fefcc
JG
1323 },
1324 { /* bfd_write_contents */
9783e04a
DM
1325 bfd_false,
1326 symbolsrec_write_object_contents,
1327 _bfd_write_archive_contents,
1328 bfd_false,
8f8fefcc 1329 },
6812b607
ILT
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),
7f4c005d 1336 BFD_JUMP_TABLE_RELOCS (srec),
6812b607
ILT
1337 BFD_JUMP_TABLE_WRITE (srec),
1338 BFD_JUMP_TABLE_LINK (srec),
dfc1c006 1339 BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
6812b607 1340
9783e04a
DM
1341 (PTR) 0
1342};
This page took 0.217563 seconds and 4 git commands to generate.