12159047fSniklas /* BFD back-end for s-record objects. 2*b55d4692Sfgsch Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 3*b55d4692Sfgsch 2000 4b305b0f1Sespie Free Software Foundation, Inc. 52159047fSniklas Written by Steve Chamberlain of Cygnus Support <sac@cygnus.com>. 62159047fSniklas 72159047fSniklas This file is part of BFD, the Binary File Descriptor library. 82159047fSniklas 92159047fSniklas This program is free software; you can redistribute it and/or modify 102159047fSniklas it under the terms of the GNU General Public License as published by 112159047fSniklas the Free Software Foundation; either version 2 of the License, or 122159047fSniklas (at your option) any later version. 132159047fSniklas 142159047fSniklas This program is distributed in the hope that it will be useful, 152159047fSniklas but WITHOUT ANY WARRANTY; without even the implied warranty of 162159047fSniklas MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 172159047fSniklas GNU General Public License for more details. 182159047fSniklas 192159047fSniklas You should have received a copy of the GNU General Public License 202159047fSniklas along with this program; if not, write to the Free Software 212159047fSniklas Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 222159047fSniklas 232159047fSniklas /* 242159047fSniklas SUBSECTION 252159047fSniklas S-Record handling 262159047fSniklas 272159047fSniklas DESCRIPTION 282159047fSniklas 292159047fSniklas Ordinary S-Records cannot hold anything but addresses and 302159047fSniklas data, so that's all that we implement. 312159047fSniklas 322159047fSniklas The only interesting thing is that S-Records may come out of 332159047fSniklas order and there is no header, so an initial scan is required 342159047fSniklas to discover the minimum and maximum addresses used to create 352159047fSniklas the vma and size of the only section we create. We 362159047fSniklas arbitrarily call this section ".text". 372159047fSniklas 382159047fSniklas When bfd_get_section_contents is called the file is read 392159047fSniklas again, and this time the data is placed into a bfd_alloc'd 402159047fSniklas area. 412159047fSniklas 422159047fSniklas Any number of sections may be created for output, we save them 432159047fSniklas up and output them when it's time to close the bfd. 442159047fSniklas 452159047fSniklas An s record looks like: 462159047fSniklas 472159047fSniklas EXAMPLE 482159047fSniklas S<type><length><address><data><checksum> 492159047fSniklas 502159047fSniklas DESCRIPTION 512159047fSniklas Where 522159047fSniklas o length 532159047fSniklas is the number of bytes following upto the checksum. Note that 542159047fSniklas this is not the number of chars following, since it takes two 552159047fSniklas chars to represent a byte. 562159047fSniklas o type 572159047fSniklas is one of: 582159047fSniklas 0) header record 592159047fSniklas 1) two byte address data record 602159047fSniklas 2) three byte address data record 612159047fSniklas 3) four byte address data record 622159047fSniklas 7) four byte address termination record 632159047fSniklas 8) three byte address termination record 642159047fSniklas 9) two byte address termination record 652159047fSniklas 662159047fSniklas o address 672159047fSniklas is the start address of the data following, or in the case of 682159047fSniklas a termination record, the start address of the image 692159047fSniklas o data 702159047fSniklas is the data. 712159047fSniklas o checksum 722159047fSniklas is the sum of all the raw byte data in the record, from the length 732159047fSniklas upwards, modulo 256 and subtracted from 255. 742159047fSniklas 752159047fSniklas SUBSECTION 762159047fSniklas Symbol S-Record handling 772159047fSniklas 782159047fSniklas DESCRIPTION 792159047fSniklas Some ICE equipment understands an addition to the standard 802159047fSniklas S-Record format; symbols and their addresses can be sent 812159047fSniklas before the data. 822159047fSniklas 832159047fSniklas The format of this is: 842159047fSniklas ($$ <modulename> 852159047fSniklas (<space> <symbol> <address>)*) 862159047fSniklas $$ 872159047fSniklas 882159047fSniklas so a short symbol table could look like: 892159047fSniklas 902159047fSniklas EXAMPLE 912159047fSniklas $$ flash.x 922159047fSniklas $$ flash.c 932159047fSniklas _port6 $0 942159047fSniklas _delay $4 952159047fSniklas _start $14 962159047fSniklas _etext $8036 972159047fSniklas _edata $8036 982159047fSniklas _end $8036 992159047fSniklas $$ 1002159047fSniklas 1012159047fSniklas DESCRIPTION 1022159047fSniklas We allow symbols to be anywhere in the data stream - the module names 1032159047fSniklas are always ignored. 1042159047fSniklas 1052159047fSniklas */ 1062159047fSniklas 1072159047fSniklas #include "bfd.h" 1082159047fSniklas #include "sysdep.h" 1092159047fSniklas #include "libbfd.h" 1102159047fSniklas #include "libiberty.h" 1112159047fSniklas #include <ctype.h> 1122159047fSniklas 113b305b0f1Sespie static void srec_get_symbol_info PARAMS ((bfd *, asymbol *, symbol_info *)); 114e93f7393Sniklas static void srec_print_symbol 115e93f7393Sniklas PARAMS ((bfd *, PTR, asymbol *, bfd_print_symbol_type)); 1162159047fSniklas static void srec_init PARAMS ((void)); 1172159047fSniklas static boolean srec_mkobject PARAMS ((bfd *)); 1182159047fSniklas static int srec_get_byte PARAMS ((bfd *, boolean *)); 1192159047fSniklas static void srec_bad_byte PARAMS ((bfd *, unsigned int, int, boolean)); 1202159047fSniklas static boolean srec_scan PARAMS ((bfd *)); 1212159047fSniklas static const bfd_target *srec_object_p PARAMS ((bfd *)); 1222159047fSniklas static const bfd_target *symbolsrec_object_p PARAMS ((bfd *)); 1232159047fSniklas static boolean srec_read_section PARAMS ((bfd *, asection *, bfd_byte *)); 1242159047fSniklas 1252159047fSniklas static boolean srec_write_record PARAMS ((bfd *, int, bfd_vma, 1262159047fSniklas const bfd_byte *, 1272159047fSniklas const bfd_byte *)); 1282159047fSniklas static boolean srec_write_header PARAMS ((bfd *)); 1292159047fSniklas static boolean srec_write_symbols PARAMS ((bfd *)); 130e93f7393Sniklas static boolean srec_new_symbol PARAMS ((bfd *, const char *, bfd_vma)); 131e93f7393Sniklas static boolean srec_get_section_contents 132e93f7393Sniklas PARAMS ((bfd *, asection *, PTR, file_ptr, bfd_size_type)); 133e93f7393Sniklas static boolean srec_set_arch_mach 134e93f7393Sniklas PARAMS ((bfd *, enum bfd_architecture, unsigned long)); 135e93f7393Sniklas static boolean srec_set_section_contents 136e93f7393Sniklas PARAMS ((bfd *, sec_ptr, PTR, file_ptr, bfd_size_type)); 137e93f7393Sniklas static boolean internal_srec_write_object_contents PARAMS ((bfd *, int)); 138e93f7393Sniklas static boolean srec_write_object_contents PARAMS ((bfd *)); 139e93f7393Sniklas static boolean symbolsrec_write_object_contents PARAMS ((bfd *)); 140e93f7393Sniklas static int srec_sizeof_headers PARAMS ((bfd *, boolean)); 141e93f7393Sniklas static asymbol *srec_make_empty_symbol PARAMS ((bfd *)); 142e93f7393Sniklas static long srec_get_symtab_upper_bound PARAMS ((bfd *)); 143e93f7393Sniklas static long srec_get_symtab PARAMS ((bfd *, asymbol **)); 1442159047fSniklas 1452159047fSniklas /* Macros for converting between hex and binary. */ 1462159047fSniklas 1472159047fSniklas static CONST char digs[] = "0123456789ABCDEF"; 1482159047fSniklas 1492159047fSniklas #define NIBBLE(x) hex_value(x) 1502159047fSniklas #define HEX(buffer) ((NIBBLE((buffer)[0])<<4) + NIBBLE((buffer)[1])) 1512159047fSniklas #define TOHEX(d, x, ch) \ 1522159047fSniklas d[1] = digs[(x) & 0xf]; \ 1532159047fSniklas d[0] = digs[((x)>>4)&0xf]; \ 1542159047fSniklas ch += ((x) & 0xff); 1552159047fSniklas #define ISHEX(x) hex_p(x) 1562159047fSniklas 1572159047fSniklas /* Initialize by filling in the hex conversion array. */ 1582159047fSniklas 1592159047fSniklas static void 1602159047fSniklas srec_init () 1612159047fSniklas { 1622159047fSniklas static boolean inited = false; 1632159047fSniklas 1642159047fSniklas if (inited == false) 1652159047fSniklas { 1662159047fSniklas inited = true; 1672159047fSniklas hex_init (); 1682159047fSniklas } 1692159047fSniklas } 1702159047fSniklas 171*b55d4692Sfgsch /* The maximum number of bytes on a line is FF. */ 1722159047fSniklas #define MAXCHUNK 0xff 173*b55d4692Sfgsch 174*b55d4692Sfgsch /* Default size for a CHUNK. */ 175*b55d4692Sfgsch #define DEFAULT_CHUNK 16 176*b55d4692Sfgsch 177*b55d4692Sfgsch /* The number of bytes we actually fit onto a line on output. 178*b55d4692Sfgsch This variable can be modified by objcopy's --srec-len parameter. 179*b55d4692Sfgsch For a 0x75 byte record you should set --srec-len=0x70. */ 180*b55d4692Sfgsch unsigned int Chunk = DEFAULT_CHUNK; 181*b55d4692Sfgsch 182*b55d4692Sfgsch /* The type of srec output (free or forced to S3). 183*b55d4692Sfgsch This variable can be modified by objcopy's --srec-forceS3 184*b55d4692Sfgsch parameter. */ 185*b55d4692Sfgsch boolean S3Forced = 0; 1862159047fSniklas 1872159047fSniklas /* When writing an S-record file, the S-records can not be output as 1882159047fSniklas they are seen. This structure is used to hold them in memory. */ 1892159047fSniklas 1902159047fSniklas struct srec_data_list_struct 1912159047fSniklas { 1922159047fSniklas struct srec_data_list_struct *next; 1932159047fSniklas bfd_byte *data; 1942159047fSniklas bfd_vma where; 1952159047fSniklas bfd_size_type size; 1962159047fSniklas }; 1972159047fSniklas 1982159047fSniklas typedef struct srec_data_list_struct srec_data_list_type; 1992159047fSniklas 2002159047fSniklas /* When scanning the S-record file, a linked list of srec_symbol 2012159047fSniklas structures is built to represent the symbol table (if there is 2022159047fSniklas one). */ 2032159047fSniklas 2042159047fSniklas struct srec_symbol 2052159047fSniklas { 2062159047fSniklas struct srec_symbol *next; 2072159047fSniklas const char *name; 2082159047fSniklas bfd_vma val; 2092159047fSniklas }; 2102159047fSniklas 2112159047fSniklas /* The S-record tdata information. */ 2122159047fSniklas 2132159047fSniklas typedef struct srec_data_struct 2142159047fSniklas { 2152159047fSniklas srec_data_list_type *head; 2162159047fSniklas srec_data_list_type *tail; 2172159047fSniklas unsigned int type; 2182159047fSniklas struct srec_symbol *symbols; 2192159047fSniklas struct srec_symbol *symtail; 2202159047fSniklas asymbol *csymbols; 2212159047fSniklas } 2222159047fSniklas tdata_type; 2232159047fSniklas 2242159047fSniklas static boolean srec_write_section PARAMS ((bfd *, tdata_type *, 2252159047fSniklas srec_data_list_type *)); 2262159047fSniklas static boolean srec_write_terminator PARAMS ((bfd *, tdata_type *)); 2272159047fSniklas 2282159047fSniklas /* Set up the S-record tdata information. */ 2292159047fSniklas 2302159047fSniklas static boolean 2312159047fSniklas srec_mkobject (abfd) 2322159047fSniklas bfd *abfd; 2332159047fSniklas { 2342159047fSniklas srec_init (); 2352159047fSniklas 2362159047fSniklas if (abfd->tdata.srec_data == NULL) 2372159047fSniklas { 2382159047fSniklas tdata_type *tdata = (tdata_type *) bfd_alloc (abfd, sizeof (tdata_type)); 2392159047fSniklas if (tdata == NULL) 2402159047fSniklas return false; 2412159047fSniklas abfd->tdata.srec_data = tdata; 2422159047fSniklas tdata->type = 1; 2432159047fSniklas tdata->head = NULL; 2442159047fSniklas tdata->tail = NULL; 2452159047fSniklas tdata->symbols = NULL; 2462159047fSniklas tdata->symtail = NULL; 2472159047fSniklas tdata->csymbols = NULL; 2482159047fSniklas } 2492159047fSniklas 2502159047fSniklas return true; 2512159047fSniklas } 2522159047fSniklas 2532159047fSniklas /* Read a byte from an S record file. Set *ERRORPTR if an error 2542159047fSniklas occurred. Return EOF on error or end of file. */ 2552159047fSniklas 2562159047fSniklas static int 2572159047fSniklas srec_get_byte (abfd, errorptr) 2582159047fSniklas bfd *abfd; 2592159047fSniklas boolean *errorptr; 2602159047fSniklas { 2612159047fSniklas bfd_byte c; 2622159047fSniklas 2632159047fSniklas if (bfd_read (&c, 1, 1, abfd) != 1) 2642159047fSniklas { 2652159047fSniklas if (bfd_get_error () != bfd_error_file_truncated) 2662159047fSniklas *errorptr = true; 2672159047fSniklas return EOF; 2682159047fSniklas } 2692159047fSniklas 2702159047fSniklas return (int) (c & 0xff); 2712159047fSniklas } 2722159047fSniklas 2732159047fSniklas /* Report a problem in an S record file. FIXME: This probably should 2742159047fSniklas not call fprintf, but we really do need some mechanism for printing 2752159047fSniklas error messages. */ 2762159047fSniklas 2772159047fSniklas static void 2782159047fSniklas srec_bad_byte (abfd, lineno, c, error) 2792159047fSniklas bfd *abfd; 2802159047fSniklas unsigned int lineno; 2812159047fSniklas int c; 2822159047fSniklas boolean error; 2832159047fSniklas { 2842159047fSniklas if (c == EOF) 2852159047fSniklas { 2862159047fSniklas if (! error) 2872159047fSniklas bfd_set_error (bfd_error_file_truncated); 2882159047fSniklas } 2892159047fSniklas else 2902159047fSniklas { 2912159047fSniklas char buf[10]; 2922159047fSniklas 2932159047fSniklas if (! isprint (c)) 2942159047fSniklas sprintf (buf, "\\%03o", (unsigned int) c); 2952159047fSniklas else 2962159047fSniklas { 2972159047fSniklas buf[0] = c; 2982159047fSniklas buf[1] = '\0'; 2992159047fSniklas } 3002159047fSniklas (*_bfd_error_handler) 301b305b0f1Sespie (_("%s:%d: Unexpected character `%s' in S-record file\n"), 3022159047fSniklas bfd_get_filename (abfd), lineno, buf); 3032159047fSniklas bfd_set_error (bfd_error_bad_value); 3042159047fSniklas } 3052159047fSniklas } 3062159047fSniklas 3072159047fSniklas /* Add a new symbol found in an S-record file. */ 3082159047fSniklas 3092159047fSniklas static boolean 3102159047fSniklas srec_new_symbol (abfd, name, val) 3112159047fSniklas bfd *abfd; 3122159047fSniklas const char *name; 3132159047fSniklas bfd_vma val; 3142159047fSniklas { 3152159047fSniklas struct srec_symbol *n; 3162159047fSniklas 3172159047fSniklas n = (struct srec_symbol *) bfd_alloc (abfd, sizeof (struct srec_symbol)); 3182159047fSniklas if (n == NULL) 3192159047fSniklas return false; 3202159047fSniklas 3212159047fSniklas n->name = name; 3222159047fSniklas n->val = val; 3232159047fSniklas 3242159047fSniklas if (abfd->tdata.srec_data->symbols == NULL) 3252159047fSniklas abfd->tdata.srec_data->symbols = n; 3262159047fSniklas else 3272159047fSniklas abfd->tdata.srec_data->symtail->next = n; 3282159047fSniklas abfd->tdata.srec_data->symtail = n; 3292159047fSniklas n->next = NULL; 3302159047fSniklas 3312159047fSniklas ++abfd->symcount; 3322159047fSniklas 3332159047fSniklas return true; 3342159047fSniklas } 3352159047fSniklas 3362159047fSniklas /* Read the S record file and turn it into sections. We create a new 3372159047fSniklas section for each contiguous set of bytes. */ 3382159047fSniklas 3392159047fSniklas static boolean 3402159047fSniklas srec_scan (abfd) 3412159047fSniklas bfd *abfd; 3422159047fSniklas { 3432159047fSniklas int c; 3442159047fSniklas unsigned int lineno = 1; 3452159047fSniklas boolean error = false; 3462159047fSniklas bfd_byte *buf = NULL; 3472159047fSniklas size_t bufsize = 0; 3482159047fSniklas asection *sec = NULL; 349b305b0f1Sespie char *symbuf = NULL; 3502159047fSniklas 3512159047fSniklas if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0) 3522159047fSniklas goto error_return; 3532159047fSniklas 3542159047fSniklas while ((c = srec_get_byte (abfd, &error)) != EOF) 3552159047fSniklas { 3562159047fSniklas /* We only build sections from contiguous S-records, so if this 3572159047fSniklas is not an S-record, then stop building a section. */ 3582159047fSniklas if (c != 'S' && c != '\r' && c != '\n') 3592159047fSniklas sec = NULL; 3602159047fSniklas 3612159047fSniklas switch (c) 3622159047fSniklas { 3632159047fSniklas default: 3642159047fSniklas srec_bad_byte (abfd, lineno, c, error); 3652159047fSniklas goto error_return; 3662159047fSniklas 3672159047fSniklas case '\n': 3682159047fSniklas ++lineno; 3692159047fSniklas break; 3702159047fSniklas 3712159047fSniklas case '\r': 3722159047fSniklas break; 3732159047fSniklas 3742159047fSniklas case '$': 3752159047fSniklas /* Starting a module name, which we ignore. */ 3762159047fSniklas while ((c = srec_get_byte (abfd, &error)) != '\n' 3772159047fSniklas && c != EOF) 3782159047fSniklas ; 3792159047fSniklas if (c == EOF) 3802159047fSniklas { 3812159047fSniklas srec_bad_byte (abfd, lineno, c, error); 3822159047fSniklas goto error_return; 3832159047fSniklas } 3842159047fSniklas 3852159047fSniklas ++lineno; 3862159047fSniklas 3872159047fSniklas break; 3882159047fSniklas 3892159047fSniklas case ' ': 390e93f7393Sniklas do 3912159047fSniklas { 392b305b0f1Sespie unsigned int alc; 393b305b0f1Sespie char *p, *symname; 3942159047fSniklas bfd_vma symval; 3952159047fSniklas 3962159047fSniklas /* Starting a symbol definition. */ 3972159047fSniklas while ((c = srec_get_byte (abfd, &error)) != EOF 3982159047fSniklas && (c == ' ' || c == '\t')) 3992159047fSniklas ; 400e93f7393Sniklas 401b305b0f1Sespie if (c == '\n' || c == '\r') 402e93f7393Sniklas break; 403e93f7393Sniklas 4042159047fSniklas if (c == EOF) 4052159047fSniklas { 4062159047fSniklas srec_bad_byte (abfd, lineno, c, error); 4072159047fSniklas goto error_return; 4082159047fSniklas } 4092159047fSniklas 410b305b0f1Sespie alc = 10; 411b305b0f1Sespie symbuf = (char *) bfd_malloc (alc + 1); 412b305b0f1Sespie if (symbuf == NULL) 413b305b0f1Sespie goto error_return; 414b305b0f1Sespie 415b305b0f1Sespie p = symbuf; 416b305b0f1Sespie 417b305b0f1Sespie *p++ = c; 4182159047fSniklas while ((c = srec_get_byte (abfd, &error)) != EOF 4192159047fSniklas && ! isspace (c)) 420b305b0f1Sespie { 421b305b0f1Sespie if ((unsigned int) (p - symbuf) >= alc) 422b305b0f1Sespie { 423b305b0f1Sespie char *n; 424b305b0f1Sespie 425b305b0f1Sespie alc *= 2; 426b305b0f1Sespie n = (char *) bfd_realloc (symbuf, alc + 1); 427b305b0f1Sespie if (n == NULL) 428b305b0f1Sespie goto error_return; 429b305b0f1Sespie p = n + (p - symbuf); 430b305b0f1Sespie symbuf = n; 431b305b0f1Sespie } 432b305b0f1Sespie 433b305b0f1Sespie *p++ = c; 434b305b0f1Sespie } 435b305b0f1Sespie 4362159047fSniklas if (c == EOF) 4372159047fSniklas { 4382159047fSniklas srec_bad_byte (abfd, lineno, c, error); 4392159047fSniklas goto error_return; 4402159047fSniklas } 4412159047fSniklas 442b305b0f1Sespie *p++ = '\0'; 443b305b0f1Sespie symname = bfd_alloc (abfd, p - symbuf); 4442159047fSniklas if (symname == NULL) 4452159047fSniklas goto error_return; 446b305b0f1Sespie strcpy (symname, symbuf); 447b305b0f1Sespie free (symbuf); 448b305b0f1Sespie symbuf = NULL; 4492159047fSniklas 4502159047fSniklas while ((c = srec_get_byte (abfd, &error)) != EOF 4512159047fSniklas && (c == ' ' || c == '\t')) 4522159047fSniklas ; 4532159047fSniklas if (c == EOF) 4542159047fSniklas { 4552159047fSniklas srec_bad_byte (abfd, lineno, c, error); 4562159047fSniklas goto error_return; 4572159047fSniklas } 4582159047fSniklas 4592159047fSniklas /* Skip a dollar sign before the hex value. */ 4602159047fSniklas if (c == '$') 4612159047fSniklas { 4622159047fSniklas c = srec_get_byte (abfd, &error); 4632159047fSniklas if (c == EOF) 4642159047fSniklas { 4652159047fSniklas srec_bad_byte (abfd, lineno, c, error); 4662159047fSniklas goto error_return; 4672159047fSniklas } 4682159047fSniklas } 4692159047fSniklas 4702159047fSniklas symval = 0; 4712159047fSniklas while (ISHEX (c)) 4722159047fSniklas { 4732159047fSniklas symval <<= 4; 4742159047fSniklas symval += NIBBLE (c); 4752159047fSniklas c = srec_get_byte (abfd, &error); 4762159047fSniklas } 4772159047fSniklas 478e93f7393Sniklas if (! srec_new_symbol (abfd, symname, symval)) 479e93f7393Sniklas goto error_return; 480e93f7393Sniklas } 481*b55d4692Sfgsch while (c == ' ' || c == '\t') 482*b55d4692Sfgsch ; 483e93f7393Sniklas 484b305b0f1Sespie if (c == '\n') 485b305b0f1Sespie ++lineno; 486b305b0f1Sespie else if (c != '\r') 4872159047fSniklas { 4882159047fSniklas srec_bad_byte (abfd, lineno, c, error); 4892159047fSniklas goto error_return; 4902159047fSniklas } 4912159047fSniklas 4922159047fSniklas break; 4932159047fSniklas 4942159047fSniklas case 'S': 4952159047fSniklas { 4962159047fSniklas file_ptr pos; 4972159047fSniklas char hdr[3]; 4982159047fSniklas unsigned int bytes; 4992159047fSniklas bfd_vma address; 5002159047fSniklas bfd_byte *data; 5012159047fSniklas 5022159047fSniklas /* Starting an S-record. */ 5032159047fSniklas 5042159047fSniklas pos = bfd_tell (abfd) - 1; 5052159047fSniklas 5062159047fSniklas if (bfd_read (hdr, 1, 3, abfd) != 3) 5072159047fSniklas goto error_return; 5082159047fSniklas 5092159047fSniklas if (! ISHEX (hdr[1]) || ! ISHEX (hdr[2])) 5102159047fSniklas { 5112159047fSniklas if (! ISHEX (hdr[1])) 5122159047fSniklas c = hdr[1]; 5132159047fSniklas else 5142159047fSniklas c = hdr[2]; 5152159047fSniklas srec_bad_byte (abfd, lineno, c, error); 5162159047fSniklas goto error_return; 5172159047fSniklas } 5182159047fSniklas 5192159047fSniklas bytes = HEX (hdr + 1); 5202159047fSniklas if (bytes * 2 > bufsize) 5212159047fSniklas { 5222159047fSniklas if (buf != NULL) 5232159047fSniklas free (buf); 524c88b1d6cSniklas buf = (bfd_byte *) bfd_malloc (bytes * 2); 5252159047fSniklas if (buf == NULL) 5262159047fSniklas goto error_return; 5272159047fSniklas bufsize = bytes * 2; 5282159047fSniklas } 5292159047fSniklas 5302159047fSniklas if (bfd_read (buf, 1, bytes * 2, abfd) != bytes * 2) 5312159047fSniklas goto error_return; 5322159047fSniklas 5332159047fSniklas /* Ignore the checksum byte. */ 5342159047fSniklas --bytes; 5352159047fSniklas 5362159047fSniklas address = 0; 5372159047fSniklas data = buf; 5382159047fSniklas switch (hdr[0]) 5392159047fSniklas { 5402159047fSniklas case '0': 5412159047fSniklas case '5': 5422159047fSniklas /* Prologue--ignore the file name, but stop building a 5432159047fSniklas section at this point. */ 5442159047fSniklas sec = NULL; 5452159047fSniklas break; 5462159047fSniklas 5472159047fSniklas case '3': 5482159047fSniklas address = HEX (data); 5492159047fSniklas data += 2; 5502159047fSniklas --bytes; 5512159047fSniklas /* Fall through. */ 5522159047fSniklas case '2': 5532159047fSniklas address = (address << 8) | HEX (data); 5542159047fSniklas data += 2; 5552159047fSniklas --bytes; 5562159047fSniklas /* Fall through. */ 5572159047fSniklas case '1': 5582159047fSniklas address = (address << 8) | HEX (data); 5592159047fSniklas data += 2; 5602159047fSniklas address = (address << 8) | HEX (data); 5612159047fSniklas data += 2; 5622159047fSniklas bytes -= 2; 5632159047fSniklas 5642159047fSniklas if (sec != NULL 5652159047fSniklas && sec->vma + sec->_raw_size == address) 5662159047fSniklas { 5672159047fSniklas /* This data goes at the end of the section we are 5682159047fSniklas currently building. */ 5692159047fSniklas sec->_raw_size += bytes; 5702159047fSniklas } 5712159047fSniklas else 5722159047fSniklas { 5732159047fSniklas char secbuf[20]; 5742159047fSniklas char *secname; 5752159047fSniklas 5762159047fSniklas sprintf (secbuf, ".sec%d", bfd_count_sections (abfd) + 1); 5772159047fSniklas secname = (char *) bfd_alloc (abfd, strlen (secbuf) + 1); 5782159047fSniklas strcpy (secname, secbuf); 5792159047fSniklas sec = bfd_make_section (abfd, secname); 5802159047fSniklas if (sec == NULL) 5812159047fSniklas goto error_return; 5822159047fSniklas sec->flags = SEC_HAS_CONTENTS | SEC_LOAD | SEC_ALLOC; 5832159047fSniklas sec->vma = address; 584c88b1d6cSniklas sec->lma = address; 5852159047fSniklas sec->_raw_size = bytes; 5862159047fSniklas sec->filepos = pos; 5872159047fSniklas } 5882159047fSniklas 5892159047fSniklas break; 5902159047fSniklas 5912159047fSniklas case '7': 5922159047fSniklas address = HEX (data); 5932159047fSniklas data += 2; 5942159047fSniklas /* Fall through. */ 5952159047fSniklas case '8': 5962159047fSniklas address = (address << 8) | HEX (data); 5972159047fSniklas data += 2; 5982159047fSniklas /* Fall through. */ 5992159047fSniklas case '9': 6002159047fSniklas address = (address << 8) | HEX (data); 6012159047fSniklas data += 2; 6022159047fSniklas address = (address << 8) | HEX (data); 6032159047fSniklas data += 2; 6042159047fSniklas 6052159047fSniklas /* This is a termination record. */ 6062159047fSniklas abfd->start_address = address; 6072159047fSniklas 6082159047fSniklas if (buf != NULL) 6092159047fSniklas free (buf); 6102159047fSniklas 6112159047fSniklas return true; 6122159047fSniklas } 6132159047fSniklas } 6142159047fSniklas break; 6152159047fSniklas } 6162159047fSniklas } 6172159047fSniklas 6182159047fSniklas if (error) 6192159047fSniklas goto error_return; 6202159047fSniklas 6212159047fSniklas if (buf != NULL) 6222159047fSniklas free (buf); 6232159047fSniklas 6242159047fSniklas return true; 6252159047fSniklas 6262159047fSniklas error_return: 627b305b0f1Sespie if (symbuf != NULL) 628b305b0f1Sespie free (symbuf); 6292159047fSniklas if (buf != NULL) 6302159047fSniklas free (buf); 6312159047fSniklas return false; 6322159047fSniklas } 6332159047fSniklas 6342159047fSniklas /* Check whether an existing file is an S-record file. */ 6352159047fSniklas 6362159047fSniklas static const bfd_target * 6372159047fSniklas srec_object_p (abfd) 6382159047fSniklas bfd *abfd; 6392159047fSniklas { 6402159047fSniklas bfd_byte b[4]; 6412159047fSniklas 6422159047fSniklas srec_init (); 6432159047fSniklas 6442159047fSniklas if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0 6452159047fSniklas || bfd_read (b, 1, 4, abfd) != 4) 6462159047fSniklas return NULL; 6472159047fSniklas 6482159047fSniklas if (b[0] != 'S' || !ISHEX (b[1]) || !ISHEX (b[2]) || !ISHEX (b[3])) 6492159047fSniklas { 6502159047fSniklas bfd_set_error (bfd_error_wrong_format); 6512159047fSniklas return NULL; 6522159047fSniklas } 6532159047fSniklas 6542159047fSniklas if (! srec_mkobject (abfd) 6552159047fSniklas || ! srec_scan (abfd)) 6562159047fSniklas return NULL; 6572159047fSniklas 658b305b0f1Sespie if (abfd->symcount > 0) 659b305b0f1Sespie abfd->flags |= HAS_SYMS; 660b305b0f1Sespie 6612159047fSniklas return abfd->xvec; 6622159047fSniklas } 6632159047fSniklas 6642159047fSniklas /* Check whether an existing file is an S-record file with symbols. */ 6652159047fSniklas 6662159047fSniklas static const bfd_target * 6672159047fSniklas symbolsrec_object_p (abfd) 6682159047fSniklas bfd *abfd; 6692159047fSniklas { 6702159047fSniklas char b[2]; 6712159047fSniklas 6722159047fSniklas srec_init (); 6732159047fSniklas 6742159047fSniklas if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0 6752159047fSniklas || bfd_read (b, 1, 2, abfd) != 2) 6762159047fSniklas return NULL; 6772159047fSniklas 6782159047fSniklas if (b[0] != '$' || b[1] != '$') 6792159047fSniklas { 6802159047fSniklas bfd_set_error (bfd_error_wrong_format); 6812159047fSniklas return NULL; 6822159047fSniklas } 6832159047fSniklas 6842159047fSniklas if (! srec_mkobject (abfd) 6852159047fSniklas || ! srec_scan (abfd)) 6862159047fSniklas return NULL; 6872159047fSniklas 688b305b0f1Sespie if (abfd->symcount > 0) 689b305b0f1Sespie abfd->flags |= HAS_SYMS; 690b305b0f1Sespie 6912159047fSniklas return abfd->xvec; 6922159047fSniklas } 6932159047fSniklas 6942159047fSniklas /* Read in the contents of a section in an S-record file. */ 6952159047fSniklas 6962159047fSniklas static boolean 6972159047fSniklas srec_read_section (abfd, section, contents) 6982159047fSniklas bfd *abfd; 6992159047fSniklas asection *section; 7002159047fSniklas bfd_byte *contents; 7012159047fSniklas { 7022159047fSniklas int c; 7032159047fSniklas bfd_size_type sofar = 0; 7042159047fSniklas boolean error = false; 7052159047fSniklas bfd_byte *buf = NULL; 7062159047fSniklas size_t bufsize = 0; 7072159047fSniklas 7082159047fSniklas if (bfd_seek (abfd, section->filepos, SEEK_SET) != 0) 7092159047fSniklas goto error_return; 7102159047fSniklas 7112159047fSniklas while ((c = srec_get_byte (abfd, &error)) != EOF) 7122159047fSniklas { 7132159047fSniklas bfd_byte hdr[3]; 7142159047fSniklas unsigned int bytes; 7152159047fSniklas bfd_vma address; 7162159047fSniklas bfd_byte *data; 7172159047fSniklas 7182159047fSniklas if (c == '\r' || c == '\n') 7192159047fSniklas continue; 7202159047fSniklas 7212159047fSniklas /* This is called after srec_scan has already been called, so we 7222159047fSniklas ought to know the exact format. */ 7232159047fSniklas BFD_ASSERT (c == 'S'); 7242159047fSniklas 7252159047fSniklas if (bfd_read (hdr, 1, 3, abfd) != 3) 7262159047fSniklas goto error_return; 7272159047fSniklas 7282159047fSniklas BFD_ASSERT (ISHEX (hdr[1]) && ISHEX (hdr[2])); 7292159047fSniklas 7302159047fSniklas bytes = HEX (hdr + 1); 7312159047fSniklas 7322159047fSniklas if (bytes * 2 > bufsize) 7332159047fSniklas { 7342159047fSniklas if (buf != NULL) 7352159047fSniklas free (buf); 736c88b1d6cSniklas buf = (bfd_byte *) bfd_malloc (bytes * 2); 7372159047fSniklas if (buf == NULL) 7382159047fSniklas goto error_return; 7392159047fSniklas bufsize = bytes * 2; 7402159047fSniklas } 7412159047fSniklas 7422159047fSniklas if (bfd_read (buf, 1, bytes * 2, abfd) != bytes * 2) 7432159047fSniklas goto error_return; 7442159047fSniklas 7452159047fSniklas address = 0; 7462159047fSniklas data = buf; 7472159047fSniklas switch (hdr[0]) 7482159047fSniklas { 7492159047fSniklas default: 7502159047fSniklas BFD_ASSERT (sofar == section->_raw_size); 7512159047fSniklas if (buf != NULL) 7522159047fSniklas free (buf); 7532159047fSniklas return true; 7542159047fSniklas 7552159047fSniklas case '3': 7562159047fSniklas address = HEX (data); 7572159047fSniklas data += 2; 7582159047fSniklas --bytes; 7592159047fSniklas /* Fall through. */ 7602159047fSniklas case '2': 7612159047fSniklas address = (address << 8) | HEX (data); 7622159047fSniklas data += 2; 7632159047fSniklas --bytes; 7642159047fSniklas /* Fall through. */ 7652159047fSniklas case '1': 7662159047fSniklas address = (address << 8) | HEX (data); 7672159047fSniklas data += 2; 7682159047fSniklas address = (address << 8) | HEX (data); 7692159047fSniklas data += 2; 7702159047fSniklas bytes -= 2; 7712159047fSniklas 7722159047fSniklas if (address != section->vma + sofar) 7732159047fSniklas { 7742159047fSniklas /* We've come to the end of this section. */ 7752159047fSniklas BFD_ASSERT (sofar == section->_raw_size); 7762159047fSniklas if (buf != NULL) 7772159047fSniklas free (buf); 7782159047fSniklas return true; 7792159047fSniklas } 7802159047fSniklas 7812159047fSniklas /* Don't consider checksum. */ 7822159047fSniklas --bytes; 7832159047fSniklas 7842159047fSniklas while (bytes-- != 0) 7852159047fSniklas { 7862159047fSniklas contents[sofar] = HEX (data); 7872159047fSniklas data += 2; 7882159047fSniklas ++sofar; 7892159047fSniklas } 7902159047fSniklas 7912159047fSniklas break; 7922159047fSniklas } 7932159047fSniklas } 7942159047fSniklas 7952159047fSniklas if (error) 7962159047fSniklas goto error_return; 7972159047fSniklas 7982159047fSniklas BFD_ASSERT (sofar == section->_raw_size); 7992159047fSniklas 8002159047fSniklas if (buf != NULL) 8012159047fSniklas free (buf); 8022159047fSniklas 8032159047fSniklas return true; 8042159047fSniklas 8052159047fSniklas error_return: 8062159047fSniklas if (buf != NULL) 8072159047fSniklas free (buf); 8082159047fSniklas return false; 8092159047fSniklas } 8102159047fSniklas 8112159047fSniklas /* Get the contents of a section in an S-record file. */ 8122159047fSniklas 8132159047fSniklas static boolean 8142159047fSniklas srec_get_section_contents (abfd, section, location, offset, count) 8152159047fSniklas bfd *abfd; 8162159047fSniklas asection *section; 8172159047fSniklas PTR location; 8182159047fSniklas file_ptr offset; 8192159047fSniklas bfd_size_type count; 8202159047fSniklas { 8212159047fSniklas if (section->used_by_bfd == NULL) 8222159047fSniklas { 8232159047fSniklas section->used_by_bfd = bfd_alloc (abfd, section->_raw_size); 8242159047fSniklas if (section->used_by_bfd == NULL 8252159047fSniklas && section->_raw_size != 0) 8262159047fSniklas return false; 8272159047fSniklas 8282159047fSniklas if (! srec_read_section (abfd, section, section->used_by_bfd)) 8292159047fSniklas return false; 8302159047fSniklas } 8312159047fSniklas 8322159047fSniklas memcpy (location, (bfd_byte *) section->used_by_bfd + offset, 8332159047fSniklas (size_t) count); 8342159047fSniklas 8352159047fSniklas return true; 8362159047fSniklas } 8372159047fSniklas 838c88b1d6cSniklas /* Set the architecture. We accept an unknown architecture here. */ 839c88b1d6cSniklas 840c88b1d6cSniklas static boolean 841c88b1d6cSniklas srec_set_arch_mach (abfd, arch, mach) 842c88b1d6cSniklas bfd *abfd; 843c88b1d6cSniklas enum bfd_architecture arch; 844c88b1d6cSniklas unsigned long mach; 845c88b1d6cSniklas { 846c88b1d6cSniklas if (arch == bfd_arch_unknown) 847c88b1d6cSniklas { 848c88b1d6cSniklas abfd->arch_info = &bfd_default_arch_struct; 849c88b1d6cSniklas return true; 850c88b1d6cSniklas } 851c88b1d6cSniklas return bfd_default_set_arch_mach (abfd, arch, mach); 852c88b1d6cSniklas } 853c88b1d6cSniklas 854*b55d4692Sfgsch /* We have to save up all the Srecords for a splurge before output. */ 8552159047fSniklas 8562159047fSniklas static boolean 8572159047fSniklas srec_set_section_contents (abfd, section, location, offset, bytes_to_do) 8582159047fSniklas bfd *abfd; 8592159047fSniklas sec_ptr section; 8602159047fSniklas PTR location; 8612159047fSniklas file_ptr offset; 8622159047fSniklas bfd_size_type bytes_to_do; 8632159047fSniklas { 8642159047fSniklas tdata_type *tdata = abfd->tdata.srec_data; 8652159047fSniklas register srec_data_list_type *entry; 8662159047fSniklas 8672159047fSniklas entry = ((srec_data_list_type *) 8682159047fSniklas bfd_alloc (abfd, sizeof (srec_data_list_type))); 8692159047fSniklas if (entry == NULL) 8702159047fSniklas return false; 8712159047fSniklas 8722159047fSniklas if (bytes_to_do 8732159047fSniklas && (section->flags & SEC_ALLOC) 8742159047fSniklas && (section->flags & SEC_LOAD)) 8752159047fSniklas { 8762159047fSniklas bfd_byte *data = (bfd_byte *) bfd_alloc (abfd, bytes_to_do); 8772159047fSniklas if (data == NULL) 8782159047fSniklas return false; 8792159047fSniklas memcpy ((PTR) data, location, (size_t) bytes_to_do); 8802159047fSniklas 881*b55d4692Sfgsch /* Ff S3Forced is true then always select S3 records, 882*b55d4692Sfgsch regardless of the siez of the addresses. */ 883*b55d4692Sfgsch if (S3Forced) 884*b55d4692Sfgsch tdata->type = 3; 885*b55d4692Sfgsch else if ((section->lma + offset + bytes_to_do - 1) <= 0xffff) 886*b55d4692Sfgsch ; /* The default, S1, is OK. */ 8872159047fSniklas else if ((section->lma + offset + bytes_to_do - 1) <= 0xffffff 888b305b0f1Sespie && tdata->type <= 2) 8892159047fSniklas tdata->type = 2; 8902159047fSniklas else 8912159047fSniklas tdata->type = 3; 8922159047fSniklas 8932159047fSniklas entry->data = data; 8942159047fSniklas entry->where = section->lma + offset; 8952159047fSniklas entry->size = bytes_to_do; 8962159047fSniklas 8972159047fSniklas /* Sort the records by address. Optimize for the common case of 8982159047fSniklas adding a record to the end of the list. */ 8992159047fSniklas if (tdata->tail != NULL 9002159047fSniklas && entry->where >= tdata->tail->where) 9012159047fSniklas { 9022159047fSniklas tdata->tail->next = entry; 9032159047fSniklas entry->next = NULL; 9042159047fSniklas tdata->tail = entry; 9052159047fSniklas } 9062159047fSniklas else 9072159047fSniklas { 9082159047fSniklas register srec_data_list_type **look; 9092159047fSniklas 9102159047fSniklas for (look = &tdata->head; 9112159047fSniklas *look != NULL && (*look)->where < entry->where; 9122159047fSniklas look = &(*look)->next) 9132159047fSniklas ; 9142159047fSniklas entry->next = *look; 9152159047fSniklas *look = entry; 9162159047fSniklas if (entry->next == NULL) 9172159047fSniklas tdata->tail = entry; 9182159047fSniklas } 9192159047fSniklas } 9202159047fSniklas return true; 9212159047fSniklas } 9222159047fSniklas 9232159047fSniklas /* Write a record of type, of the supplied number of bytes. The 9242159047fSniklas supplied bytes and length don't have a checksum. That's worked out 925*b55d4692Sfgsch here. */ 926*b55d4692Sfgsch 9272159047fSniklas static boolean 9282159047fSniklas srec_write_record (abfd, type, address, data, end) 9292159047fSniklas bfd *abfd; 9302159047fSniklas int type; 9312159047fSniklas bfd_vma address; 9322159047fSniklas const bfd_byte *data; 9332159047fSniklas const bfd_byte *end; 9342159047fSniklas { 9352159047fSniklas char buffer[MAXCHUNK]; 9362159047fSniklas unsigned int check_sum = 0; 9372159047fSniklas CONST bfd_byte *src = data; 9382159047fSniklas char *dst = buffer; 9392159047fSniklas char *length; 9402159047fSniklas bfd_size_type wrlen; 9412159047fSniklas 9422159047fSniklas *dst++ = 'S'; 9432159047fSniklas *dst++ = '0' + type; 9442159047fSniklas 9452159047fSniklas length = dst; 946*b55d4692Sfgsch dst += 2; /* Leave room for dst. */ 9472159047fSniklas 9482159047fSniklas switch (type) 9492159047fSniklas { 9502159047fSniklas case 3: 9512159047fSniklas case 7: 9522159047fSniklas TOHEX (dst, (address >> 24), check_sum); 9532159047fSniklas dst += 2; 9542159047fSniklas case 8: 9552159047fSniklas case 2: 9562159047fSniklas TOHEX (dst, (address >> 16), check_sum); 9572159047fSniklas dst += 2; 9582159047fSniklas case 9: 9592159047fSniklas case 1: 9602159047fSniklas case 0: 9612159047fSniklas TOHEX (dst, (address >> 8), check_sum); 9622159047fSniklas dst += 2; 9632159047fSniklas TOHEX (dst, (address), check_sum); 9642159047fSniklas dst += 2; 9652159047fSniklas break; 9662159047fSniklas 9672159047fSniklas } 9682159047fSniklas for (src = data; src < end; src++) 9692159047fSniklas { 9702159047fSniklas TOHEX (dst, *src, check_sum); 9712159047fSniklas dst += 2; 9722159047fSniklas } 9732159047fSniklas 974*b55d4692Sfgsch /* Fill in the length. */ 9752159047fSniklas TOHEX (length, (dst - length) / 2, check_sum); 9762159047fSniklas check_sum &= 0xff; 9772159047fSniklas check_sum = 255 - check_sum; 9782159047fSniklas TOHEX (dst, check_sum, check_sum); 9792159047fSniklas dst += 2; 9802159047fSniklas 9812159047fSniklas *dst++ = '\r'; 9822159047fSniklas *dst++ = '\n'; 9832159047fSniklas wrlen = dst - buffer; 9842159047fSniklas if (bfd_write ((PTR) buffer, 1, wrlen, abfd) != wrlen) 9852159047fSniklas return false; 9862159047fSniklas return true; 9872159047fSniklas } 9882159047fSniklas 9892159047fSniklas static boolean 9902159047fSniklas srec_write_header (abfd) 9912159047fSniklas bfd *abfd; 9922159047fSniklas { 9932159047fSniklas bfd_byte buffer[MAXCHUNK]; 9942159047fSniklas bfd_byte *dst = buffer; 9952159047fSniklas unsigned int i; 9962159047fSniklas 997*b55d4692Sfgsch /* I'll put an arbitary 40 char limit on header size. */ 9982159047fSniklas for (i = 0; i < 40 && abfd->filename[i]; i++) 9992159047fSniklas *dst++ = abfd->filename[i]; 1000*b55d4692Sfgsch 10012159047fSniklas return srec_write_record (abfd, 0, 0, buffer, dst); 10022159047fSniklas } 10032159047fSniklas 10042159047fSniklas static boolean 10052159047fSniklas srec_write_section (abfd, tdata, list) 10062159047fSniklas bfd *abfd; 10072159047fSniklas tdata_type *tdata; 10082159047fSniklas srec_data_list_type *list; 10092159047fSniklas { 1010b305b0f1Sespie unsigned int octets_written = 0; 10112159047fSniklas bfd_byte *location = list->data; 10122159047fSniklas 1013b305b0f1Sespie while (octets_written < list->size) 10142159047fSniklas { 10152159047fSniklas bfd_vma address; 1016b305b0f1Sespie unsigned int octets_this_chunk = list->size - octets_written; 10172159047fSniklas 1018*b55d4692Sfgsch if (octets_this_chunk > Chunk) 1019*b55d4692Sfgsch octets_this_chunk = Chunk; 10202159047fSniklas 1021b305b0f1Sespie address = list->where + octets_written / bfd_octets_per_byte (abfd); 10222159047fSniklas 10232159047fSniklas if (! srec_write_record (abfd, 10242159047fSniklas tdata->type, 10252159047fSniklas address, 10262159047fSniklas location, 1027b305b0f1Sespie location + octets_this_chunk)) 10282159047fSniklas return false; 10292159047fSniklas 1030b305b0f1Sespie octets_written += octets_this_chunk; 1031b305b0f1Sespie location += octets_this_chunk; 10322159047fSniklas } 10332159047fSniklas 10342159047fSniklas return true; 10352159047fSniklas } 10362159047fSniklas 10372159047fSniklas static boolean 10382159047fSniklas srec_write_terminator (abfd, tdata) 10392159047fSniklas bfd *abfd; 10402159047fSniklas tdata_type *tdata; 10412159047fSniklas { 10422159047fSniklas bfd_byte buffer[2]; 10432159047fSniklas 10442159047fSniklas return srec_write_record (abfd, 10 - tdata->type, 10452159047fSniklas abfd->start_address, buffer, buffer); 10462159047fSniklas } 10472159047fSniklas 10482159047fSniklas static boolean 10492159047fSniklas srec_write_symbols (abfd) 10502159047fSniklas bfd *abfd; 10512159047fSniklas { 10522159047fSniklas char buffer[MAXCHUNK]; 1053*b55d4692Sfgsch /* Dump out the symbols of a bfd. */ 10542159047fSniklas int i; 10552159047fSniklas int count = bfd_get_symcount (abfd); 10562159047fSniklas 10572159047fSniklas if (count) 10582159047fSniklas { 10592159047fSniklas size_t len; 10602159047fSniklas asymbol **table = bfd_get_outsymbols (abfd); 10612159047fSniklas sprintf (buffer, "$$ %s\r\n", abfd->filename); 10622159047fSniklas 10632159047fSniklas len = strlen (buffer); 10642159047fSniklas if (bfd_write (buffer, len, 1, abfd) != len) 10652159047fSniklas return false; 10662159047fSniklas 10672159047fSniklas for (i = 0; i < count; i++) 10682159047fSniklas { 10692159047fSniklas asymbol *s = table[i]; 1070b305b0f1Sespie if (! bfd_is_local_label (abfd, s) 1071b305b0f1Sespie && (s->flags & BSF_DEBUGGING) == 0) 10722159047fSniklas { 1073*b55d4692Sfgsch /* Just dump out non debug symbols. */ 10742159047fSniklas bfd_size_type l; 10752159047fSniklas char buf2[40], *p; 10762159047fSniklas 10772159047fSniklas sprintf_vma (buf2, 10782159047fSniklas s->value + s->section->output_section->lma 10792159047fSniklas + s->section->output_offset); 10802159047fSniklas p = buf2; 10812159047fSniklas while (p[0] == '0' && p[1] != 0) 10822159047fSniklas p++; 10832159047fSniklas sprintf (buffer, " %s $%s\r\n", s->name, p); 10842159047fSniklas l = strlen (buffer); 10852159047fSniklas if (bfd_write (buffer, l, 1, abfd) != l) 10862159047fSniklas return false; 10872159047fSniklas } 10882159047fSniklas } 10892159047fSniklas sprintf (buffer, "$$ \r\n"); 10902159047fSniklas len = strlen (buffer); 10912159047fSniklas if (bfd_write (buffer, len, 1, abfd) != len) 10922159047fSniklas return false; 10932159047fSniklas } 10942159047fSniklas 10952159047fSniklas return true; 10962159047fSniklas } 10972159047fSniklas 10982159047fSniklas static boolean 10992159047fSniklas internal_srec_write_object_contents (abfd, symbols) 11002159047fSniklas bfd *abfd; 11012159047fSniklas int symbols; 11022159047fSniklas { 11032159047fSniklas tdata_type *tdata = abfd->tdata.srec_data; 11042159047fSniklas srec_data_list_type *list; 11052159047fSniklas 11062159047fSniklas if (symbols) 11072159047fSniklas { 11082159047fSniklas if (! srec_write_symbols (abfd)) 11092159047fSniklas return false; 11102159047fSniklas } 11112159047fSniklas 11122159047fSniklas if (! srec_write_header (abfd)) 11132159047fSniklas return false; 11142159047fSniklas 1115*b55d4692Sfgsch /* Now wander though all the sections provided and output them. */ 11162159047fSniklas list = tdata->head; 11172159047fSniklas 11182159047fSniklas while (list != (srec_data_list_type *) NULL) 11192159047fSniklas { 11202159047fSniklas if (! srec_write_section (abfd, tdata, list)) 11212159047fSniklas return false; 11222159047fSniklas list = list->next; 11232159047fSniklas } 11242159047fSniklas return srec_write_terminator (abfd, tdata); 11252159047fSniklas } 11262159047fSniklas 11272159047fSniklas static boolean 11282159047fSniklas srec_write_object_contents (abfd) 11292159047fSniklas bfd *abfd; 11302159047fSniklas { 11312159047fSniklas return internal_srec_write_object_contents (abfd, 0); 11322159047fSniklas } 11332159047fSniklas 11342159047fSniklas static boolean 11352159047fSniklas symbolsrec_write_object_contents (abfd) 11362159047fSniklas bfd *abfd; 11372159047fSniklas { 11382159047fSniklas return internal_srec_write_object_contents (abfd, 1); 11392159047fSniklas } 11402159047fSniklas 11412159047fSniklas static int 11422159047fSniklas srec_sizeof_headers (abfd, exec) 1143b305b0f1Sespie bfd *abfd ATTRIBUTE_UNUSED; 1144b305b0f1Sespie boolean exec ATTRIBUTE_UNUSED; 11452159047fSniklas { 11462159047fSniklas return 0; 11472159047fSniklas } 11482159047fSniklas 11492159047fSniklas static asymbol * 11502159047fSniklas srec_make_empty_symbol (abfd) 11512159047fSniklas bfd *abfd; 11522159047fSniklas { 11532159047fSniklas asymbol *new = (asymbol *) bfd_zalloc (abfd, sizeof (asymbol)); 11542159047fSniklas if (new) 11552159047fSniklas new->the_bfd = abfd; 11562159047fSniklas return new; 11572159047fSniklas } 11582159047fSniklas 11592159047fSniklas /* Return the amount of memory needed to read the symbol table. */ 11602159047fSniklas 11612159047fSniklas static long 11622159047fSniklas srec_get_symtab_upper_bound (abfd) 11632159047fSniklas bfd *abfd; 11642159047fSniklas { 11652159047fSniklas return (bfd_get_symcount (abfd) + 1) * sizeof (asymbol *); 11662159047fSniklas } 11672159047fSniklas 11682159047fSniklas /* Return the symbol table. */ 11692159047fSniklas 11702159047fSniklas static long 11712159047fSniklas srec_get_symtab (abfd, alocation) 11722159047fSniklas bfd *abfd; 11732159047fSniklas asymbol **alocation; 11742159047fSniklas { 11752159047fSniklas unsigned int symcount = bfd_get_symcount (abfd); 11762159047fSniklas asymbol *csymbols; 11772159047fSniklas unsigned int i; 11782159047fSniklas 11792159047fSniklas csymbols = abfd->tdata.srec_data->csymbols; 11802159047fSniklas if (csymbols == NULL) 11812159047fSniklas { 11822159047fSniklas asymbol *c; 11832159047fSniklas struct srec_symbol *s; 11842159047fSniklas 11852159047fSniklas csymbols = (asymbol *) bfd_alloc (abfd, symcount * sizeof (asymbol)); 11862159047fSniklas if (csymbols == NULL && symcount != 0) 11872159047fSniklas return false; 11882159047fSniklas abfd->tdata.srec_data->csymbols = csymbols; 11892159047fSniklas 11902159047fSniklas for (s = abfd->tdata.srec_data->symbols, c = csymbols; 11912159047fSniklas s != NULL; 11922159047fSniklas s = s->next, ++c) 11932159047fSniklas { 11942159047fSniklas c->the_bfd = abfd; 11952159047fSniklas c->name = s->name; 11962159047fSniklas c->value = s->val; 11972159047fSniklas c->flags = BSF_GLOBAL; 11982159047fSniklas c->section = bfd_abs_section_ptr; 11992159047fSniklas c->udata.p = NULL; 12002159047fSniklas } 12012159047fSniklas } 12022159047fSniklas 12032159047fSniklas for (i = 0; i < symcount; i++) 12042159047fSniklas *alocation++ = csymbols++; 12052159047fSniklas *alocation = NULL; 12062159047fSniklas 12072159047fSniklas return symcount; 12082159047fSniklas } 12092159047fSniklas 1210b305b0f1Sespie static void 12112159047fSniklas srec_get_symbol_info (ignore_abfd, symbol, ret) 1212b305b0f1Sespie bfd *ignore_abfd ATTRIBUTE_UNUSED; 12132159047fSniklas asymbol *symbol; 12142159047fSniklas symbol_info *ret; 12152159047fSniklas { 12162159047fSniklas bfd_symbol_info (symbol, ret); 12172159047fSniklas } 12182159047fSniklas 1219e93f7393Sniklas static void 12202159047fSniklas srec_print_symbol (ignore_abfd, afile, symbol, how) 1221b305b0f1Sespie bfd *ignore_abfd ATTRIBUTE_UNUSED; 12222159047fSniklas PTR afile; 12232159047fSniklas asymbol *symbol; 12242159047fSniklas bfd_print_symbol_type how; 12252159047fSniklas { 12262159047fSniklas FILE *file = (FILE *) afile; 12272159047fSniklas switch (how) 12282159047fSniklas { 12292159047fSniklas case bfd_print_symbol_name: 12302159047fSniklas fprintf (file, "%s", symbol->name); 12312159047fSniklas break; 12322159047fSniklas default: 12332159047fSniklas bfd_print_symbol_vandf ((PTR) file, symbol); 12342159047fSniklas fprintf (file, " %-5s %s", 12352159047fSniklas symbol->section->name, 12362159047fSniklas symbol->name); 12372159047fSniklas 12382159047fSniklas } 12392159047fSniklas } 12402159047fSniklas 12412159047fSniklas #define srec_close_and_cleanup _bfd_generic_close_and_cleanup 12422159047fSniklas #define srec_bfd_free_cached_info _bfd_generic_bfd_free_cached_info 12432159047fSniklas #define srec_new_section_hook _bfd_generic_new_section_hook 12442159047fSniklas 1245b305b0f1Sespie #define srec_bfd_is_local_label_name bfd_generic_is_local_label_name 12462159047fSniklas #define srec_get_lineno _bfd_nosymbols_get_lineno 12472159047fSniklas #define srec_find_nearest_line _bfd_nosymbols_find_nearest_line 12482159047fSniklas #define srec_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol 12492159047fSniklas #define srec_read_minisymbols _bfd_generic_read_minisymbols 12502159047fSniklas #define srec_minisymbol_to_symbol _bfd_generic_minisymbol_to_symbol 12512159047fSniklas 12522159047fSniklas #define srec_get_reloc_upper_bound \ 12532159047fSniklas ((long (*) PARAMS ((bfd *, asection *))) bfd_0l) 12542159047fSniklas #define srec_canonicalize_reloc \ 12552159047fSniklas ((long (*) PARAMS ((bfd *, asection *, arelent **, asymbol **))) bfd_0l) 12562159047fSniklas #define srec_bfd_reloc_type_lookup _bfd_norelocs_bfd_reloc_type_lookup 12572159047fSniklas 12582159047fSniklas #define srec_get_section_contents_in_window \ 12592159047fSniklas _bfd_generic_get_section_contents_in_window 12602159047fSniklas 12612159047fSniklas #define srec_bfd_get_relocated_section_contents \ 12622159047fSniklas bfd_generic_get_relocated_section_contents 12632159047fSniklas #define srec_bfd_relax_section bfd_generic_relax_section 1264b305b0f1Sespie #define srec_bfd_gc_sections bfd_generic_gc_sections 12652159047fSniklas #define srec_bfd_link_hash_table_create _bfd_generic_link_hash_table_create 12662159047fSniklas #define srec_bfd_link_add_symbols _bfd_generic_link_add_symbols 12672159047fSniklas #define srec_bfd_final_link _bfd_generic_final_link 12682159047fSniklas #define srec_bfd_link_split_section _bfd_generic_link_split_section 12692159047fSniklas 12702159047fSniklas const bfd_target srec_vec = 12712159047fSniklas { 12722159047fSniklas "srec", /* name */ 12732159047fSniklas bfd_target_srec_flavour, 1274c88b1d6cSniklas BFD_ENDIAN_UNKNOWN, /* target byte order */ 1275c88b1d6cSniklas BFD_ENDIAN_UNKNOWN, /* target headers byte order */ 12762159047fSniklas (HAS_RELOC | EXEC_P | /* object flags */ 12772159047fSniklas HAS_LINENO | HAS_DEBUG | 12782159047fSniklas HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED), 12792159047fSniklas (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS 12802159047fSniklas | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */ 12812159047fSniklas 0, /* leading underscore */ 12822159047fSniklas ' ', /* ar_pad_char */ 12832159047fSniklas 16, /* ar_max_namelen */ 12842159047fSniklas bfd_getb64, bfd_getb_signed_64, bfd_putb64, 12852159047fSniklas bfd_getb32, bfd_getb_signed_32, bfd_putb32, 12862159047fSniklas bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* data */ 12872159047fSniklas bfd_getb64, bfd_getb_signed_64, bfd_putb64, 12882159047fSniklas bfd_getb32, bfd_getb_signed_32, bfd_putb32, 12892159047fSniklas bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* hdrs */ 12902159047fSniklas 12912159047fSniklas { 12922159047fSniklas _bfd_dummy_target, 12932159047fSniklas srec_object_p, /* bfd_check_format */ 12942159047fSniklas _bfd_dummy_target, 12952159047fSniklas _bfd_dummy_target, 12962159047fSniklas }, 12972159047fSniklas { 12982159047fSniklas bfd_false, 12992159047fSniklas srec_mkobject, 13002159047fSniklas _bfd_generic_mkarchive, 13012159047fSniklas bfd_false, 13022159047fSniklas }, 13032159047fSniklas { /* bfd_write_contents */ 13042159047fSniklas bfd_false, 13052159047fSniklas srec_write_object_contents, 13062159047fSniklas _bfd_write_archive_contents, 13072159047fSniklas bfd_false, 13082159047fSniklas }, 13092159047fSniklas 13102159047fSniklas BFD_JUMP_TABLE_GENERIC (srec), 13112159047fSniklas BFD_JUMP_TABLE_COPY (_bfd_generic), 13122159047fSniklas BFD_JUMP_TABLE_CORE (_bfd_nocore), 13132159047fSniklas BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive), 13142159047fSniklas BFD_JUMP_TABLE_SYMBOLS (srec), 13152159047fSniklas BFD_JUMP_TABLE_RELOCS (srec), 13162159047fSniklas BFD_JUMP_TABLE_WRITE (srec), 13172159047fSniklas BFD_JUMP_TABLE_LINK (srec), 13182159047fSniklas BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic), 13192159047fSniklas 1320b305b0f1Sespie NULL, 1321b305b0f1Sespie 13222159047fSniklas (PTR) 0 13232159047fSniklas }; 13242159047fSniklas 13252159047fSniklas const bfd_target symbolsrec_vec = 13262159047fSniklas { 13272159047fSniklas "symbolsrec", /* name */ 13282159047fSniklas bfd_target_srec_flavour, 1329c88b1d6cSniklas BFD_ENDIAN_UNKNOWN, /* target byte order */ 1330c88b1d6cSniklas BFD_ENDIAN_UNKNOWN, /* target headers byte order */ 13312159047fSniklas (HAS_RELOC | EXEC_P | /* object flags */ 13322159047fSniklas HAS_LINENO | HAS_DEBUG | 13332159047fSniklas HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED), 13342159047fSniklas (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS 13352159047fSniklas | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */ 13362159047fSniklas 0, /* leading underscore */ 13372159047fSniklas ' ', /* ar_pad_char */ 13382159047fSniklas 16, /* ar_max_namelen */ 13392159047fSniklas bfd_getb64, bfd_getb_signed_64, bfd_putb64, 13402159047fSniklas bfd_getb32, bfd_getb_signed_32, bfd_putb32, 13412159047fSniklas bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* data */ 13422159047fSniklas bfd_getb64, bfd_getb_signed_64, bfd_putb64, 13432159047fSniklas bfd_getb32, bfd_getb_signed_32, bfd_putb32, 13442159047fSniklas bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* hdrs */ 13452159047fSniklas 13462159047fSniklas { 13472159047fSniklas _bfd_dummy_target, 13482159047fSniklas symbolsrec_object_p, /* bfd_check_format */ 13492159047fSniklas _bfd_dummy_target, 13502159047fSniklas _bfd_dummy_target, 13512159047fSniklas }, 13522159047fSniklas { 13532159047fSniklas bfd_false, 13542159047fSniklas srec_mkobject, 13552159047fSniklas _bfd_generic_mkarchive, 13562159047fSniklas bfd_false, 13572159047fSniklas }, 13582159047fSniklas { /* bfd_write_contents */ 13592159047fSniklas bfd_false, 13602159047fSniklas symbolsrec_write_object_contents, 13612159047fSniklas _bfd_write_archive_contents, 13622159047fSniklas bfd_false, 13632159047fSniklas }, 13642159047fSniklas 13652159047fSniklas BFD_JUMP_TABLE_GENERIC (srec), 13662159047fSniklas BFD_JUMP_TABLE_COPY (_bfd_generic), 13672159047fSniklas BFD_JUMP_TABLE_CORE (_bfd_nocore), 13682159047fSniklas BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive), 13692159047fSniklas BFD_JUMP_TABLE_SYMBOLS (srec), 13702159047fSniklas BFD_JUMP_TABLE_RELOCS (srec), 13712159047fSniklas BFD_JUMP_TABLE_WRITE (srec), 13722159047fSniklas BFD_JUMP_TABLE_LINK (srec), 13732159047fSniklas BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic), 13742159047fSniklas 1375b305b0f1Sespie NULL, 1376b305b0f1Sespie 13772159047fSniklas (PTR) 0 13782159047fSniklas }; 1379