Fix typo; some progress in ppcbug support
[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 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;
524 sec->_raw_size = bytes;
525 sec->filepos = pos;
526 }
527
528 break;
529
530 case '7':
531 address = HEX (data);
532 data += 2;
533 /* Fall through. */
534 case '8':
535 address = (address << 8) | HEX (data);
536 data += 2;
537 /* Fall through. */
538 case '9':
539 address = (address << 8) | HEX (data);
540 data += 2;
541 address = (address << 8) | HEX (data);
542 data += 2;
543
544 /* This is a termination record. */
545 abfd->start_address = address;
546
547 if (buf != NULL)
548 free (buf);
549
550 return true;
551 }
552 }
553 break;
8f8fefcc 554 }
4a81b561 555 }
9898b929 556
7f4c005d
KR
557 if (error)
558 goto error_return;
4a81b561 559
7f4c005d
KR
560 if (buf != NULL)
561 free (buf);
562
563 return true;
564
565 error_return:
566 if (buf != NULL)
567 free (buf);
568 return false;
8f8fefcc 569}
9898b929 570
7f4c005d
KR
571/* Check whether an existing file is an S-record file. */
572
2f3508ad 573static const bfd_target *
57a1867e
DM
574srec_object_p (abfd)
575 bfd *abfd;
4a81b561 576{
7f4c005d 577 bfd_byte b[4];
8f8fefcc 578
9783e04a 579 srec_init ();
9898b929 580
6d4f7715
ILT
581 if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0
582 || bfd_read (b, 1, 4, abfd) != 4)
583 return NULL;
9783e04a
DM
584
585 if (b[0] != 'S' || !ISHEX (b[1]) || !ISHEX (b[2]) || !ISHEX (b[3]))
7f4c005d
KR
586 {
587 bfd_set_error (bfd_error_wrong_format);
588 return NULL;
589 }
9783e04a 590
7f4c005d
KR
591 if (! srec_mkobject (abfd)
592 || ! srec_scan (abfd))
593 return NULL;
4a81b561 594
7f4c005d 595 return abfd->xvec;
8f8fefcc
JG
596}
597
7f4c005d 598/* Check whether an existing file is an S-record file with symbols. */
8f8fefcc 599
2f3508ad 600static const bfd_target *
57a1867e
DM
601symbolsrec_object_p (abfd)
602 bfd *abfd;
8f8fefcc 603{
7f4c005d 604 char b[2];
8f8fefcc 605
9783e04a
DM
606 srec_init ();
607
6d4f7715 608 if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0
7f4c005d 609 || bfd_read (b, 1, 2, abfd) != 2)
6d4f7715 610 return NULL;
8f8fefcc
JG
611
612 if (b[0] != '$' || b[1] != '$')
7f4c005d
KR
613 {
614 bfd_set_error (bfd_error_wrong_format);
615 return NULL;
616 }
8f8fefcc 617
7f4c005d
KR
618 if (! srec_mkobject (abfd)
619 || ! srec_scan (abfd))
620 return NULL;
621
622 return abfd->xvec;
4a81b561
DHW
623}
624
7f4c005d
KR
625/* Read in the contents of a section in an S-record file. */
626
627static boolean
628srec_read_section (abfd, section, contents)
629 bfd *abfd;
630 asection *section;
631 bfd_byte *contents;
632{
633 int c;
634 bfd_size_type sofar = 0;
635 boolean error = false;
636 bfd_byte *buf = NULL;
637 size_t bufsize = 0;
638
639 if (bfd_seek (abfd, section->filepos, SEEK_SET) != 0)
640 goto error_return;
641
642 while ((c = srec_get_byte (abfd, &error)) != EOF)
643 {
644 bfd_byte hdr[3];
645 unsigned int bytes;
646 bfd_vma address;
647 bfd_byte *data;
648
649 if (c == '\r' || c == '\n')
650 continue;
651
652 /* This is called after srec_scan has already been called, so we
653 ought to know the exact format. */
654 BFD_ASSERT (c == 'S');
655
656 if (bfd_read (hdr, 1, 3, abfd) != 3)
657 goto error_return;
658
659 BFD_ASSERT (ISHEX (hdr[1]) && ISHEX (hdr[2]));
660
661 bytes = HEX (hdr + 1);
662
663 if (bytes * 2 > bufsize)
664 {
665 if (buf != NULL)
666 free (buf);
58142f10 667 buf = (bfd_byte *) bfd_malloc (bytes * 2);
7f4c005d 668 if (buf == NULL)
58142f10 669 goto error_return;
7f4c005d
KR
670 bufsize = bytes * 2;
671 }
672
673 if (bfd_read (buf, 1, bytes * 2, abfd) != bytes * 2)
674 goto error_return;
675
676 address = 0;
677 data = buf;
678 switch (hdr[0])
679 {
680 default:
681 BFD_ASSERT (sofar == section->_raw_size);
682 if (buf != NULL)
683 free (buf);
684 return true;
685
686 case '3':
687 address = HEX (data);
688 data += 2;
689 --bytes;
690 /* Fall through. */
691 case '2':
692 address = (address << 8) | HEX (data);
693 data += 2;
694 --bytes;
695 /* Fall through. */
696 case '1':
697 address = (address << 8) | HEX (data);
698 data += 2;
699 address = (address << 8) | HEX (data);
700 data += 2;
701 bytes -= 2;
702
703 if (address != section->vma + sofar)
704 {
705 /* We've come to the end of this section. */
706 BFD_ASSERT (sofar == section->_raw_size);
707 if (buf != NULL)
708 free (buf);
709 return true;
710 }
711
712 /* Don't consider checksum. */
713 --bytes;
714
715 while (bytes-- != 0)
716 {
717 contents[sofar] = HEX (data);
718 data += 2;
719 ++sofar;
720 }
721
722 break;
723 }
724 }
725
726 if (error)
727 goto error_return;
728
729 BFD_ASSERT (sofar == section->_raw_size);
730
731 if (buf != NULL)
732 free (buf);
733
734 return true;
735
736 error_return:
737 if (buf != NULL)
738 free (buf);
739 return false;
740}
741
742/* Get the contents of a section in an S-record file. */
4a81b561 743
4a81b561 744static boolean
57a1867e
DM
745srec_get_section_contents (abfd, section, location, offset, count)
746 bfd *abfd;
747 asection *section;
748 PTR location;
749 file_ptr offset;
750 bfd_size_type count;
9783e04a 751{
7f4c005d 752 if (section->used_by_bfd == NULL)
9898b929 753 {
7f4c005d
KR
754 section->used_by_bfd = bfd_alloc (abfd, section->_raw_size);
755 if (section->used_by_bfd == NULL
756 && section->_raw_size != 0)
a9713b91 757 return false;
9783e04a 758
7f4c005d
KR
759 if (! srec_read_section (abfd, section, section->used_by_bfd))
760 return false;
9898b929 761 }
9783e04a 762
b7577823
ILT
763 memcpy (location, (bfd_byte *) section->used_by_bfd + offset,
764 (size_t) count);
4a81b561 765
7f4c005d 766 return true;
4a81b561
DHW
767}
768
c3246d9b 769/* we have to save up all the Srecords for a splurge before output */
4a81b561 770
9898b929 771static boolean
57a1867e
DM
772srec_set_section_contents (abfd, section, location, offset, bytes_to_do)
773 bfd *abfd;
774 sec_ptr section;
775 PTR location;
776 file_ptr offset;
777 bfd_size_type bytes_to_do;
9783e04a
DM
778{
779 tdata_type *tdata = abfd->tdata.srec_data;
d4d16683 780 register srec_data_list_type *entry;
9783e04a 781
d4d16683
ILT
782 entry = ((srec_data_list_type *)
783 bfd_alloc (abfd, sizeof (srec_data_list_type)));
784 if (entry == NULL)
a9713b91 785 return false;
8f8fefcc 786
c3246d9b
ILT
787 if (bytes_to_do
788 && (section->flags & SEC_ALLOC)
9783e04a 789 && (section->flags & SEC_LOAD))
9898b929 790 {
7f4c005d 791 bfd_byte *data = (bfd_byte *) bfd_alloc (abfd, bytes_to_do);
d4d16683 792 if (data == NULL)
a9713b91 793 return false;
b7577823 794 memcpy ((PTR) data, location, (size_t) bytes_to_do);
9898b929 795
c3246d9b 796 if ((section->lma + offset + bytes_to_do - 1) <= 0xffff)
8f8fefcc 797 {
9898b929 798
8f8fefcc 799 }
c3246d9b 800 else if ((section->lma + offset + bytes_to_do - 1) <= 0xffffff
9783e04a 801 && tdata->type < 2)
8f8fefcc
JG
802 {
803 tdata->type = 2;
804 }
9783e04a 805 else
8f8fefcc
JG
806 {
807 tdata->type = 3;
808 }
809
810 entry->data = data;
811 entry->where = section->lma + offset;
812 entry->size = bytes_to_do;
d4d16683
ILT
813
814 /* Sort the records by address. Optimize for the common case of
815 adding a record to the end of the list. */
816 if (tdata->tail != NULL
817 && entry->where >= tdata->tail->where)
818 {
819 tdata->tail->next = entry;
820 entry->next = NULL;
821 tdata->tail = entry;
822 }
823 else
824 {
825 register srec_data_list_type **look;
826
827 for (look = &tdata->head;
828 *look != NULL && (*look)->where < entry->where;
829 look = &(*look)->next)
830 ;
831 entry->next = *look;
832 *look = entry;
833 if (entry->next == NULL)
834 tdata->tail = entry;
835 }
8f8fefcc 836 }
9783e04a 837 return true;
9898b929
JG
838}
839
840/* Write a record of type, of the supplied number of bytes. The
841 supplied bytes and length don't have a checksum. That's worked out
842 here
843*/
6d4f7715 844static boolean
57a1867e
DM
845srec_write_record (abfd, type, address, data, end)
846 bfd *abfd;
6d4f7715 847 int type;
57a1867e 848 bfd_vma address;
7f4c005d
KR
849 const bfd_byte *data;
850 const bfd_byte *end;
9783e04a
DM
851{
852 char buffer[MAXCHUNK];
9783e04a 853 unsigned int check_sum = 0;
7f4c005d 854 CONST bfd_byte *src = data;
9783e04a
DM
855 char *dst = buffer;
856 char *length;
ae115e51 857 bfd_size_type wrlen;
9783e04a 858
9783e04a
DM
859 *dst++ = 'S';
860 *dst++ = '0' + type;
861
862 length = dst;
863 dst += 2; /* leave room for dst*/
864
865 switch (type)
9898b929 866 {
9783e04a
DM
867 case 3:
868 case 7:
869 TOHEX (dst, (address >> 24), check_sum);
870 dst += 2;
871 case 8:
872 case 2:
873 TOHEX (dst, (address >> 16), check_sum);
874 dst += 2;
875 case 9:
876 case 1:
877 case 0:
878 TOHEX (dst, (address >> 8), check_sum);
879 dst += 2;
880 TOHEX (dst, (address), check_sum);
881 dst += 2;
882 break;
4a81b561 883
4a81b561 884 }
9783e04a 885 for (src = data; src < end; src++)
9898b929 886 {
9783e04a
DM
887 TOHEX (dst, *src, check_sum);
888 dst += 2;
4a81b561
DHW
889 }
890
9783e04a
DM
891 /* Fill in the length */
892 TOHEX (length, (dst - length) / 2, check_sum);
893 check_sum &= 0xff;
894 check_sum = 255 - check_sum;
895 TOHEX (dst, check_sum, check_sum);
896 dst += 2;
897
898 *dst++ = '\r';
899 *dst++ = '\n';
ae115e51
ILT
900 wrlen = dst - buffer;
901 if (bfd_write ((PTR) buffer, 1, wrlen, abfd) != wrlen)
6d4f7715
ILT
902 return false;
903 return true;
9898b929 904}
4a81b561 905
4a81b561 906
4a81b561 907
6d4f7715 908static boolean
57a1867e
DM
909srec_write_header (abfd)
910 bfd *abfd;
9898b929 911{
7f4c005d
KR
912 bfd_byte buffer[MAXCHUNK];
913 bfd_byte *dst = buffer;
9783e04a 914 unsigned int i;
4a81b561 915
9783e04a
DM
916 /* I'll put an arbitary 40 char limit on header size */
917 for (i = 0; i < 40 && abfd->filename[i]; i++)
9898b929 918 {
9783e04a 919 *dst++ = abfd->filename[i];
9898b929 920 }
6d4f7715 921 return srec_write_record (abfd, 0, 0, buffer, dst);
4a81b561
DHW
922}
923
6d4f7715 924static boolean
57a1867e
DM
925srec_write_section (abfd, tdata, list)
926 bfd *abfd;
927 tdata_type *tdata;
928 srec_data_list_type *list;
9898b929 929{
9783e04a 930 unsigned int bytes_written = 0;
7f4c005d 931 bfd_byte *location = list->data;
9898b929 932
9783e04a 933 while (bytes_written < list->size)
9898b929 934 {
9783e04a
DM
935 bfd_vma address;
936
937 unsigned int bytes_this_chunk = list->size - bytes_written;
9898b929 938
9783e04a 939 if (bytes_this_chunk > CHUNK)
9898b929 940 {
9783e04a 941 bytes_this_chunk = CHUNK;
9898b929
JG
942 }
943
9783e04a 944 address = list->where + bytes_written;
9898b929 945
6d4f7715
ILT
946 if (! srec_write_record (abfd,
947 tdata->type,
948 address,
949 location,
950 location + bytes_this_chunk))
951 return false;
9898b929 952
9783e04a
DM
953 bytes_written += bytes_this_chunk;
954 location += bytes_this_chunk;
9898b929
JG
955 }
956
6d4f7715 957 return true;
9898b929
JG
958}
959
6d4f7715 960static boolean
57a1867e
DM
961srec_write_terminator (abfd, tdata)
962 bfd *abfd;
963 tdata_type *tdata;
9783e04a 964{
7f4c005d 965 bfd_byte buffer[2];
9783e04a 966
6d4f7715
ILT
967 return srec_write_record (abfd, 10 - tdata->type,
968 abfd->start_address, buffer, buffer);
9898b929 969}
3039e8ee 970
8f8fefcc 971
9783e04a 972
6d4f7715 973static boolean
9783e04a 974srec_write_symbols (abfd)
2c3b9e47 975 bfd *abfd;
9898b929 976{
8f8fefcc
JG
977 char buffer[MAXCHUNK];
978 /* Dump out the symbols of a bfd */
979 int i;
2f3508ad 980 int count = bfd_get_symcount (abfd);
8f8fefcc 981
2f3508ad 982 if (count)
9783e04a 983 {
6d4f7715 984 size_t len;
9783e04a
DM
985 asymbol **table = bfd_get_outsymbols (abfd);
986 sprintf (buffer, "$$ %s\r\n", abfd->filename);
8f8fefcc 987
2f3508ad 988 len = strlen (buffer);
6d4f7715
ILT
989 if (bfd_write (buffer, len, 1, abfd) != len)
990 return false;
8f8fefcc 991
2f3508ad 992 for (i = 0; i < count; i++)
9783e04a
DM
993 {
994 asymbol *s = table[i];
8f8fefcc 995#if 0
9783e04a 996 int len = strlen (s->name);
8f8fefcc 997
9783e04a 998 /* If this symbol has a .[ocs] in it, it's probably a file name
8f8fefcc
JG
999 and we'll output that as the module name */
1000
9783e04a
DM
1001 if (len > 3 && s->name[len - 2] == '.')
1002 {
1003 int l;
1004 sprintf (buffer, "$$ %s\r\n", s->name);
1005 l = strlen (buffer);
6d4f7715
ILT
1006 if (bfd_write (buffer, l, 1, abfd) != l)
1007 return false;
9783e04a
DM
1008 }
1009 else
8f8fefcc 1010#endif
9783e04a
DM
1011 if (s->flags & (BSF_GLOBAL | BSF_LOCAL)
1012 && (s->flags & BSF_DEBUGGING) == 0
1013 && s->name[0] != '.'
1014 && s->name[0] != 't')
1015 {
1016 /* Just dump out non debug symbols */
ae115e51 1017 bfd_size_type l;
9783e04a
DM
1018 char buf2[40], *p;
1019
1020 sprintf_vma (buf2,
1021 s->value + s->section->output_section->lma
1022 + s->section->output_offset);
1023 p = buf2;
1024 while (p[0] == '0' && p[1] != 0)
1025 p++;
1026 sprintf (buffer, " %s $%s\r\n", s->name, p);
1027 l = strlen (buffer);
6d4f7715
ILT
1028 if (bfd_write (buffer, l, 1, abfd) != l)
1029 return false;
9783e04a
DM
1030 }
1031 }
1032 sprintf (buffer, "$$ \r\n");
2f3508ad 1033 len = strlen (buffer);
6d4f7715
ILT
1034 if (bfd_write (buffer, len, 1, abfd) != len)
1035 return false;
8f8fefcc 1036 }
6d4f7715
ILT
1037
1038 return true;
9898b929
JG
1039}
1040
9898b929 1041static boolean
9783e04a 1042internal_srec_write_object_contents (abfd, symbols)
8f8fefcc
JG
1043 bfd *abfd;
1044 int symbols;
4a81b561 1045{
9783e04a
DM
1046 tdata_type *tdata = abfd->tdata.srec_data;
1047 srec_data_list_type *list;
9898b929 1048
9783e04a 1049 if (symbols)
6d4f7715
ILT
1050 {
1051 if (! srec_write_symbols (abfd))
1052 return false;
1053 }
8f8fefcc 1054
6d4f7715
ILT
1055 if (! srec_write_header (abfd))
1056 return false;
8f8fefcc 1057
9783e04a
DM
1058 /* Now wander though all the sections provided and output them */
1059 list = tdata->head;
9898b929 1060
9783e04a 1061 while (list != (srec_data_list_type *) NULL)
9898b929 1062 {
6d4f7715
ILT
1063 if (! srec_write_section (abfd, tdata, list))
1064 return false;
9783e04a 1065 list = list->next;
9898b929 1066 }
6d4f7715 1067 return srec_write_terminator (abfd, tdata);
4a81b561
DHW
1068}
1069
8f8fefcc 1070static boolean
9783e04a 1071srec_write_object_contents (abfd)
8f8fefcc
JG
1072 bfd *abfd;
1073{
9783e04a 1074 return internal_srec_write_object_contents (abfd, 0);
8f8fefcc
JG
1075}
1076
1077static boolean
9783e04a 1078symbolsrec_write_object_contents (abfd)
8f8fefcc
JG
1079 bfd *abfd;
1080{
9783e04a 1081 return internal_srec_write_object_contents (abfd, 1);
8f8fefcc
JG
1082}
1083
9783e04a
DM
1084/*ARGSUSED*/
1085static int
57a1867e
DM
1086srec_sizeof_headers (abfd, exec)
1087 bfd *abfd;
1088 boolean exec;
39a2ce33 1089{
9783e04a 1090 return 0;
39a2ce33
SC
1091}
1092
357a1f38 1093static asymbol *
57a1867e
DM
1094srec_make_empty_symbol (abfd)
1095 bfd *abfd;
357a1f38 1096{
9783e04a
DM
1097 asymbol *new = (asymbol *) bfd_zalloc (abfd, sizeof (asymbol));
1098 if (new)
1099 new->the_bfd = abfd;
357a1f38
SC
1100 return new;
1101}
8f8fefcc 1102
7f4c005d
KR
1103/* Return the amount of memory needed to read the symbol table. */
1104
326e32d7 1105static long
9783e04a
DM
1106srec_get_symtab_upper_bound (abfd)
1107 bfd *abfd;
8f8fefcc 1108{
7f4c005d 1109 return (bfd_get_symcount (abfd) + 1) * sizeof (asymbol *);
8f8fefcc
JG
1110}
1111
7f4c005d
KR
1112/* Return the symbol table. */
1113
326e32d7 1114static long
57a1867e
DM
1115srec_get_symtab (abfd, alocation)
1116 bfd *abfd;
1117 asymbol **alocation;
8f8fefcc 1118{
7f4c005d
KR
1119 unsigned int symcount = bfd_get_symcount (abfd);
1120 asymbol *csymbols;
1121 unsigned int i;
1122
1123 csymbols = abfd->tdata.srec_data->csymbols;
1124 if (csymbols == NULL)
9783e04a 1125 {
7f4c005d
KR
1126 asymbol *c;
1127 struct srec_symbol *s;
1128
1129 csymbols = (asymbol *) bfd_alloc (abfd, symcount * sizeof (asymbol));
1130 if (csymbols == NULL && symcount != 0)
a9713b91 1131 return false;
7f4c005d
KR
1132 abfd->tdata.srec_data->csymbols = csymbols;
1133
1134 for (s = abfd->tdata.srec_data->symbols, c = csymbols;
1135 s != NULL;
1136 s = s->next, ++c)
1137 {
1138 c->the_bfd = abfd;
1139 c->name = s->name;
1140 c->value = s->val;
1141 c->flags = BSF_GLOBAL;
1142 c->section = bfd_abs_section_ptr;
1143 c->udata.p = NULL;
1144 }
9783e04a 1145 }
7f4c005d
KR
1146
1147 for (i = 0; i < symcount; i++)
1148 *alocation++ = csymbols++;
1149 *alocation = NULL;
1150
1151 return symcount;
8f8fefcc
JG
1152}
1153
9783e04a
DM
1154/*ARGSUSED*/
1155void
57a1867e
DM
1156srec_get_symbol_info (ignore_abfd, symbol, ret)
1157 bfd *ignore_abfd;
1158 asymbol *symbol;
1159 symbol_info *ret;
2c3b9e47
KR
1160{
1161 bfd_symbol_info (symbol, ret);
1162}
1163
9783e04a
DM
1164/*ARGSUSED*/
1165void
57a1867e
DM
1166srec_print_symbol (ignore_abfd, afile, symbol, how)
1167 bfd *ignore_abfd;
1168 PTR afile;
1169 asymbol *symbol;
1170 bfd_print_symbol_type how;
9783e04a
DM
1171{
1172 FILE *file = (FILE *) afile;
1173 switch (how)
1174 {
1175 case bfd_print_symbol_name:
1176 fprintf (file, "%s", symbol->name);
1177 break;
1178 default:
1179 bfd_print_symbol_vandf ((PTR) file, symbol);
1180 fprintf (file, " %-5s %s",
1181 symbol->section->name,
1182 symbol->name);
8f8fefcc 1183
9783e04a 1184 }
8f8fefcc
JG
1185}
1186
6812b607
ILT
1187#define srec_close_and_cleanup _bfd_generic_close_and_cleanup
1188#define srec_bfd_free_cached_info _bfd_generic_bfd_free_cached_info
1189#define srec_new_section_hook _bfd_generic_new_section_hook
9872a49c 1190
6812b607
ILT
1191#define srec_bfd_is_local_label bfd_generic_is_local_label
1192#define srec_get_lineno _bfd_nosymbols_get_lineno
1193#define srec_find_nearest_line _bfd_nosymbols_find_nearest_line
1194#define srec_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol
c3246d9b
ILT
1195#define srec_read_minisymbols _bfd_generic_read_minisymbols
1196#define srec_minisymbol_to_symbol _bfd_generic_minisymbol_to_symbol
d0ec7a8e 1197
7f4c005d
KR
1198#define srec_get_reloc_upper_bound \
1199 ((long (*) PARAMS ((bfd *, asection *))) bfd_0l)
1200#define srec_canonicalize_reloc \
1201 ((long (*) PARAMS ((bfd *, asection *, arelent **, asymbol **))) bfd_0l)
1202#define srec_bfd_reloc_type_lookup _bfd_norelocs_bfd_reloc_type_lookup
1203
a9713b91
ILT
1204#define srec_get_section_contents_in_window \
1205 _bfd_generic_get_section_contents_in_window
1206
7f4c005d
KR
1207#define srec_set_arch_mach bfd_default_set_arch_mach
1208
6812b607
ILT
1209#define srec_bfd_get_relocated_section_contents \
1210 bfd_generic_get_relocated_section_contents
294eaca4 1211#define srec_bfd_relax_section bfd_generic_relax_section
4c3721d5
ILT
1212#define srec_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
1213#define srec_bfd_link_add_symbols _bfd_generic_link_add_symbols
1214#define srec_bfd_final_link _bfd_generic_final_link
c3246d9b 1215#define srec_bfd_link_split_section _bfd_generic_link_split_section
3039e8ee 1216
2f3508ad 1217const bfd_target srec_vec =
4a81b561 1218{
9783e04a
DM
1219 "srec", /* name */
1220 bfd_target_srec_flavour,
1221 true, /* target byte order */
1222 true, /* target headers byte order */
1223 (HAS_RELOC | EXEC_P | /* object flags */
1224 HAS_LINENO | HAS_DEBUG |
1225 HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
1226 (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS
1227 | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
1228 0, /* leading underscore */
1229 ' ', /* ar_pad_char */
1230 16, /* ar_max_namelen */
9783e04a
DM
1231 bfd_getb64, bfd_getb_signed_64, bfd_putb64,
1232 bfd_getb32, bfd_getb_signed_32, bfd_putb32,
1233 bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* data */
1234 bfd_getb64, bfd_getb_signed_64, bfd_putb64,
1235 bfd_getb32, bfd_getb_signed_32, bfd_putb32,
1236 bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* hdrs */
9898b929
JG
1237
1238 {
9783e04a
DM
1239 _bfd_dummy_target,
1240 srec_object_p, /* bfd_check_format */
2f3508ad
ILT
1241 _bfd_dummy_target,
1242 _bfd_dummy_target,
9898b929
JG
1243 },
1244 {
9783e04a
DM
1245 bfd_false,
1246 srec_mkobject,
1247 _bfd_generic_mkarchive,
1248 bfd_false,
9898b929
JG
1249 },
1250 { /* bfd_write_contents */
9783e04a
DM
1251 bfd_false,
1252 srec_write_object_contents,
1253 _bfd_write_archive_contents,
1254 bfd_false,
9898b929 1255 },
6812b607
ILT
1256
1257 BFD_JUMP_TABLE_GENERIC (srec),
1258 BFD_JUMP_TABLE_COPY (_bfd_generic),
1259 BFD_JUMP_TABLE_CORE (_bfd_nocore),
1260 BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
1261 BFD_JUMP_TABLE_SYMBOLS (srec),
7f4c005d 1262 BFD_JUMP_TABLE_RELOCS (srec),
6812b607
ILT
1263 BFD_JUMP_TABLE_WRITE (srec),
1264 BFD_JUMP_TABLE_LINK (srec),
dfc1c006 1265 BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
6812b607
ILT
1266
1267 (PTR) 0
9783e04a 1268};
9898b929 1269
8f8fefcc
JG
1270
1271
2f3508ad 1272const bfd_target symbolsrec_vec =
8f8fefcc 1273{
9783e04a
DM
1274 "symbolsrec", /* name */
1275 bfd_target_srec_flavour,
1276 true, /* target byte order */
1277 true, /* target headers byte order */
1278 (HAS_RELOC | EXEC_P | /* object flags */
1279 HAS_LINENO | HAS_DEBUG |
1280 HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
1281 (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS
1282 | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
1283 0, /* leading underscore */
1284 ' ', /* ar_pad_char */
1285 16, /* ar_max_namelen */
9783e04a
DM
1286 bfd_getb64, bfd_getb_signed_64, bfd_putb64,
1287 bfd_getb32, bfd_getb_signed_32, bfd_putb32,
1288 bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* data */
1289 bfd_getb64, bfd_getb_signed_64, bfd_putb64,
1290 bfd_getb32, bfd_getb_signed_32, bfd_putb32,
1291 bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* hdrs */
8f8fefcc
JG
1292
1293 {
9783e04a
DM
1294 _bfd_dummy_target,
1295 symbolsrec_object_p, /* bfd_check_format */
2f3508ad
ILT
1296 _bfd_dummy_target,
1297 _bfd_dummy_target,
8f8fefcc
JG
1298 },
1299 {
9783e04a
DM
1300 bfd_false,
1301 srec_mkobject,
1302 _bfd_generic_mkarchive,
1303 bfd_false,
8f8fefcc
JG
1304 },
1305 { /* bfd_write_contents */
9783e04a
DM
1306 bfd_false,
1307 symbolsrec_write_object_contents,
1308 _bfd_write_archive_contents,
1309 bfd_false,
8f8fefcc 1310 },
6812b607
ILT
1311
1312 BFD_JUMP_TABLE_GENERIC (srec),
1313 BFD_JUMP_TABLE_COPY (_bfd_generic),
1314 BFD_JUMP_TABLE_CORE (_bfd_nocore),
1315 BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
1316 BFD_JUMP_TABLE_SYMBOLS (srec),
7f4c005d 1317 BFD_JUMP_TABLE_RELOCS (srec),
6812b607
ILT
1318 BFD_JUMP_TABLE_WRITE (srec),
1319 BFD_JUMP_TABLE_LINK (srec),
dfc1c006 1320 BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
6812b607 1321
9783e04a
DM
1322 (PTR) 0
1323};
This page took 0.233985 seconds and 4 git commands to generate.