133965Sjdp/* BFD back-end for s-record objects. 278828Sobrien Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 3218822Sdim 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 438889Sjdp Free Software Foundation, Inc. 533965Sjdp Written by Steve Chamberlain of Cygnus Support <sac@cygnus.com>. 633965Sjdp 7218822Sdim This file is part of BFD, the Binary File Descriptor library. 833965Sjdp 9218822Sdim This program is free software; you can redistribute it and/or modify 10218822Sdim it under the terms of the GNU General Public License as published by 11218822Sdim the Free Software Foundation; either version 2 of the License, or 12218822Sdim (at your option) any later version. 1333965Sjdp 14218822Sdim This program is distributed in the hope that it will be useful, 15218822Sdim but WITHOUT ANY WARRANTY; without even the implied warranty of 16218822Sdim MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17218822Sdim GNU General Public License for more details. 1833965Sjdp 19218822Sdim You should have received a copy of the GNU General Public License 20218822Sdim along with this program; if not, write to the Free Software 21218822Sdim Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ 2233965Sjdp 23218822Sdim/* SUBSECTION 2433965Sjdp S-Record handling 2533965Sjdp 26218822Sdim DESCRIPTION 2777298Sobrien 2833965Sjdp Ordinary S-Records cannot hold anything but addresses and 2933965Sjdp data, so that's all that we implement. 3033965Sjdp 3133965Sjdp The only interesting thing is that S-Records may come out of 3233965Sjdp order and there is no header, so an initial scan is required 3333965Sjdp to discover the minimum and maximum addresses used to create 3433965Sjdp the vma and size of the only section we create. We 3533965Sjdp arbitrarily call this section ".text". 3633965Sjdp 3733965Sjdp When bfd_get_section_contents is called the file is read 3833965Sjdp again, and this time the data is placed into a bfd_alloc'd 3933965Sjdp area. 4033965Sjdp 4133965Sjdp Any number of sections may be created for output, we save them 4233965Sjdp up and output them when it's time to close the bfd. 4333965Sjdp 4433965Sjdp An s record looks like: 4577298Sobrien 46218822Sdim EXAMPLE 4733965Sjdp S<type><length><address><data><checksum> 4877298Sobrien 49218822Sdim DESCRIPTION 5033965Sjdp Where 5133965Sjdp o length 5233965Sjdp is the number of bytes following upto the checksum. Note that 5333965Sjdp this is not the number of chars following, since it takes two 5433965Sjdp chars to represent a byte. 5533965Sjdp o type 5633965Sjdp is one of: 5733965Sjdp 0) header record 5833965Sjdp 1) two byte address data record 5933965Sjdp 2) three byte address data record 6033965Sjdp 3) four byte address data record 6133965Sjdp 7) four byte address termination record 6233965Sjdp 8) three byte address termination record 6333965Sjdp 9) two byte address termination record 6477298Sobrien 6533965Sjdp o address 6633965Sjdp is the start address of the data following, or in the case of 6733965Sjdp a termination record, the start address of the image 6833965Sjdp o data 6933965Sjdp is the data. 7033965Sjdp o checksum 7133965Sjdp is the sum of all the raw byte data in the record, from the length 7233965Sjdp upwards, modulo 256 and subtracted from 255. 7333965Sjdp 74218822Sdim SUBSECTION 7533965Sjdp Symbol S-Record handling 7633965Sjdp 77218822Sdim DESCRIPTION 7833965Sjdp Some ICE equipment understands an addition to the standard 7933965Sjdp S-Record format; symbols and their addresses can be sent 8033965Sjdp before the data. 8133965Sjdp 8233965Sjdp The format of this is: 8333965Sjdp ($$ <modulename> 8433965Sjdp (<space> <symbol> <address>)*) 8533965Sjdp $$ 8633965Sjdp 8733965Sjdp so a short symbol table could look like: 8833965Sjdp 89218822Sdim EXAMPLE 9033965Sjdp $$ flash.x 9133965Sjdp $$ flash.c 9233965Sjdp _port6 $0 9333965Sjdp _delay $4 9433965Sjdp _start $14 9533965Sjdp _etext $8036 9633965Sjdp _edata $8036 9733965Sjdp _end $8036 9833965Sjdp $$ 9933965Sjdp 100218822Sdim DESCRIPTION 10133965Sjdp We allow symbols to be anywhere in the data stream - the module names 102218822Sdim are always ignored. */ 10377298Sobrien 104218822Sdim#include "sysdep.h" 10533965Sjdp#include "bfd.h" 10633965Sjdp#include "libbfd.h" 10733965Sjdp#include "libiberty.h" 10889857Sobrien#include "safe-ctype.h" 10933965Sjdp 11033965Sjdp 11177298Sobrien/* Macros for converting between hex and binary. */ 11233965Sjdp 11389857Sobrienstatic const char digs[] = "0123456789ABCDEF"; 11433965Sjdp 115218822Sdim#define NIBBLE(x) hex_value(x) 116218822Sdim#define HEX(buffer) ((NIBBLE ((buffer)[0])<<4) + NIBBLE ((buffer)[1])) 11733965Sjdp#define TOHEX(d, x, ch) \ 11833965Sjdp d[1] = digs[(x) & 0xf]; \ 11933965Sjdp d[0] = digs[((x)>>4)&0xf]; \ 12033965Sjdp ch += ((x) & 0xff); 121218822Sdim#define ISHEX(x) hex_p(x) 12233965Sjdp 12394536Sobrien/* The maximum number of address+data+crc bytes on a line is FF. */ 12433965Sjdp#define MAXCHUNK 0xff 12533965Sjdp 12677298Sobrien/* Default size for a CHUNK. */ 12777298Sobrien#define DEFAULT_CHUNK 16 12877298Sobrien 12994536Sobrien/* The number of data bytes we actually fit onto a line on output. 13077298Sobrien This variable can be modified by objcopy's --srec-len parameter. 13177298Sobrien For a 0x75 byte record you should set --srec-len=0x70. */ 13277298Sobrienunsigned int Chunk = DEFAULT_CHUNK; 13377298Sobrien 13477298Sobrien/* The type of srec output (free or forced to S3). 13577298Sobrien This variable can be modified by objcopy's --srec-forceS3 13677298Sobrien parameter. */ 137130561Sobrienbfd_boolean S3Forced = FALSE; 13877298Sobrien 13933965Sjdp/* When writing an S-record file, the S-records can not be output as 14033965Sjdp they are seen. This structure is used to hold them in memory. */ 14133965Sjdp 14233965Sjdpstruct srec_data_list_struct 14333965Sjdp{ 14433965Sjdp struct srec_data_list_struct *next; 14533965Sjdp bfd_byte *data; 14633965Sjdp bfd_vma where; 14733965Sjdp bfd_size_type size; 14833965Sjdp}; 14933965Sjdp 15033965Sjdptypedef struct srec_data_list_struct srec_data_list_type; 15133965Sjdp 15233965Sjdp/* When scanning the S-record file, a linked list of srec_symbol 15333965Sjdp structures is built to represent the symbol table (if there is 15433965Sjdp one). */ 15533965Sjdp 15633965Sjdpstruct srec_symbol 15733965Sjdp{ 15833965Sjdp struct srec_symbol *next; 15933965Sjdp const char *name; 16033965Sjdp bfd_vma val; 16133965Sjdp}; 16233965Sjdp 16333965Sjdp/* The S-record tdata information. */ 16433965Sjdp 16533965Sjdptypedef struct srec_data_struct 16633965Sjdp { 16733965Sjdp srec_data_list_type *head; 16833965Sjdp srec_data_list_type *tail; 16933965Sjdp unsigned int type; 17033965Sjdp struct srec_symbol *symbols; 17133965Sjdp struct srec_symbol *symtail; 17233965Sjdp asymbol *csymbols; 17333965Sjdp } 17433965Sjdptdata_type; 17533965Sjdp 176218822Sdim/* Initialize by filling in the hex conversion array. */ 17733965Sjdp 178218822Sdimstatic void 179218822Sdimsrec_init (void) 180218822Sdim{ 181218822Sdim static bfd_boolean inited = FALSE; 182218822Sdim 183218822Sdim if (! inited) 184218822Sdim { 185218822Sdim inited = TRUE; 186218822Sdim hex_init (); 187218822Sdim } 188218822Sdim} 189218822Sdim 19033965Sjdp/* Set up the S-record tdata information. */ 19133965Sjdp 192130561Sobrienstatic bfd_boolean 193218822Sdimsrec_mkobject (bfd *abfd) 19433965Sjdp{ 195104834Sobrien tdata_type *tdata; 196104834Sobrien 19733965Sjdp srec_init (); 19833965Sjdp 199218822Sdim tdata = bfd_alloc (abfd, sizeof (tdata_type)); 200104834Sobrien if (tdata == NULL) 201130561Sobrien return FALSE; 202130561Sobrien 203104834Sobrien abfd->tdata.srec_data = tdata; 204104834Sobrien tdata->type = 1; 205104834Sobrien tdata->head = NULL; 206104834Sobrien tdata->tail = NULL; 207104834Sobrien tdata->symbols = NULL; 208104834Sobrien tdata->symtail = NULL; 209104834Sobrien tdata->csymbols = NULL; 21033965Sjdp 211130561Sobrien return TRUE; 21233965Sjdp} 21333965Sjdp 21433965Sjdp/* Read a byte from an S record file. Set *ERRORPTR if an error 21533965Sjdp occurred. Return EOF on error or end of file. */ 21633965Sjdp 21733965Sjdpstatic int 218218822Sdimsrec_get_byte (bfd *abfd, bfd_boolean *errorptr) 21933965Sjdp{ 22033965Sjdp bfd_byte c; 22133965Sjdp 22289857Sobrien if (bfd_bread (&c, (bfd_size_type) 1, abfd) != 1) 22333965Sjdp { 22433965Sjdp if (bfd_get_error () != bfd_error_file_truncated) 225130561Sobrien *errorptr = TRUE; 22633965Sjdp return EOF; 22733965Sjdp } 22833965Sjdp 22933965Sjdp return (int) (c & 0xff); 23033965Sjdp} 23133965Sjdp 23233965Sjdp/* Report a problem in an S record file. FIXME: This probably should 23333965Sjdp not call fprintf, but we really do need some mechanism for printing 23433965Sjdp error messages. */ 23533965Sjdp 23633965Sjdpstatic void 237218822Sdimsrec_bad_byte (bfd *abfd, 238218822Sdim unsigned int lineno, 239218822Sdim int c, 240218822Sdim bfd_boolean error) 24133965Sjdp{ 24233965Sjdp if (c == EOF) 24333965Sjdp { 24433965Sjdp if (! error) 24533965Sjdp bfd_set_error (bfd_error_file_truncated); 24633965Sjdp } 24733965Sjdp else 24833965Sjdp { 24933965Sjdp char buf[10]; 25033965Sjdp 25189857Sobrien if (! ISPRINT (c)) 25233965Sjdp sprintf (buf, "\\%03o", (unsigned int) c); 25333965Sjdp else 25433965Sjdp { 25533965Sjdp buf[0] = c; 25633965Sjdp buf[1] = '\0'; 25733965Sjdp } 25833965Sjdp (*_bfd_error_handler) 259218822Sdim (_("%B:%d: Unexpected character `%s' in S-record file\n"), 260218822Sdim abfd, lineno, buf); 26133965Sjdp bfd_set_error (bfd_error_bad_value); 26233965Sjdp } 26333965Sjdp} 26433965Sjdp 26533965Sjdp/* Add a new symbol found in an S-record file. */ 26633965Sjdp 267130561Sobrienstatic bfd_boolean 268218822Sdimsrec_new_symbol (bfd *abfd, const char *name, bfd_vma val) 26933965Sjdp{ 27033965Sjdp struct srec_symbol *n; 27133965Sjdp 272218822Sdim n = bfd_alloc (abfd, sizeof (* n)); 27333965Sjdp if (n == NULL) 274130561Sobrien return FALSE; 27533965Sjdp 27633965Sjdp n->name = name; 27733965Sjdp n->val = val; 27833965Sjdp 27933965Sjdp if (abfd->tdata.srec_data->symbols == NULL) 28033965Sjdp abfd->tdata.srec_data->symbols = n; 28133965Sjdp else 28233965Sjdp abfd->tdata.srec_data->symtail->next = n; 28333965Sjdp abfd->tdata.srec_data->symtail = n; 28433965Sjdp n->next = NULL; 28533965Sjdp 28633965Sjdp ++abfd->symcount; 28733965Sjdp 288130561Sobrien return TRUE; 28933965Sjdp} 29033965Sjdp 29133965Sjdp/* Read the S record file and turn it into sections. We create a new 29233965Sjdp section for each contiguous set of bytes. */ 29333965Sjdp 294130561Sobrienstatic bfd_boolean 295218822Sdimsrec_scan (bfd *abfd) 29633965Sjdp{ 29733965Sjdp int c; 29833965Sjdp unsigned int lineno = 1; 299130561Sobrien bfd_boolean error = FALSE; 30033965Sjdp bfd_byte *buf = NULL; 30133965Sjdp size_t bufsize = 0; 30233965Sjdp asection *sec = NULL; 30333965Sjdp char *symbuf = NULL; 30433965Sjdp 30533965Sjdp if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0) 30633965Sjdp goto error_return; 30733965Sjdp 30833965Sjdp while ((c = srec_get_byte (abfd, &error)) != EOF) 30933965Sjdp { 31033965Sjdp /* We only build sections from contiguous S-records, so if this 311130561Sobrien is not an S-record, then stop building a section. */ 31233965Sjdp if (c != 'S' && c != '\r' && c != '\n') 31333965Sjdp sec = NULL; 31433965Sjdp 31533965Sjdp switch (c) 31633965Sjdp { 31733965Sjdp default: 31833965Sjdp srec_bad_byte (abfd, lineno, c, error); 31933965Sjdp goto error_return; 32033965Sjdp 32133965Sjdp case '\n': 32233965Sjdp ++lineno; 32333965Sjdp break; 32433965Sjdp 32533965Sjdp case '\r': 32633965Sjdp break; 32733965Sjdp 32833965Sjdp case '$': 32933965Sjdp /* Starting a module name, which we ignore. */ 33033965Sjdp while ((c = srec_get_byte (abfd, &error)) != '\n' 33133965Sjdp && c != EOF) 33233965Sjdp ; 33333965Sjdp if (c == EOF) 33433965Sjdp { 33533965Sjdp srec_bad_byte (abfd, lineno, c, error); 33633965Sjdp goto error_return; 33733965Sjdp } 33833965Sjdp 33933965Sjdp ++lineno; 34033965Sjdp break; 34133965Sjdp 34233965Sjdp case ' ': 34333965Sjdp do 34433965Sjdp { 34589857Sobrien bfd_size_type alc; 34633965Sjdp char *p, *symname; 34733965Sjdp bfd_vma symval; 34833965Sjdp 34933965Sjdp /* Starting a symbol definition. */ 35033965Sjdp while ((c = srec_get_byte (abfd, &error)) != EOF 35133965Sjdp && (c == ' ' || c == '\t')) 35233965Sjdp ; 35333965Sjdp 35460484Sobrien if (c == '\n' || c == '\r') 35533965Sjdp break; 35633965Sjdp 35733965Sjdp if (c == EOF) 35833965Sjdp { 35933965Sjdp srec_bad_byte (abfd, lineno, c, error); 36033965Sjdp goto error_return; 36133965Sjdp } 36233965Sjdp 36333965Sjdp alc = 10; 364218822Sdim symbuf = bfd_malloc (alc + 1); 36533965Sjdp if (symbuf == NULL) 36633965Sjdp goto error_return; 36733965Sjdp 36833965Sjdp p = symbuf; 36933965Sjdp 37033965Sjdp *p++ = c; 37133965Sjdp while ((c = srec_get_byte (abfd, &error)) != EOF 37289857Sobrien && ! ISSPACE (c)) 37333965Sjdp { 37489857Sobrien if ((bfd_size_type) (p - symbuf) >= alc) 37533965Sjdp { 37633965Sjdp char *n; 37733965Sjdp 37833965Sjdp alc *= 2; 379218822Sdim n = bfd_realloc (symbuf, alc + 1); 38033965Sjdp if (n == NULL) 38133965Sjdp goto error_return; 38233965Sjdp p = n + (p - symbuf); 38333965Sjdp symbuf = n; 38433965Sjdp } 38533965Sjdp 38633965Sjdp *p++ = c; 38733965Sjdp } 38833965Sjdp 38933965Sjdp if (c == EOF) 39033965Sjdp { 39133965Sjdp srec_bad_byte (abfd, lineno, c, error); 39233965Sjdp goto error_return; 39333965Sjdp } 39433965Sjdp 39533965Sjdp *p++ = '\0'; 39689857Sobrien symname = bfd_alloc (abfd, (bfd_size_type) (p - symbuf)); 39733965Sjdp if (symname == NULL) 39833965Sjdp goto error_return; 39933965Sjdp strcpy (symname, symbuf); 40033965Sjdp free (symbuf); 40133965Sjdp symbuf = NULL; 40233965Sjdp 40333965Sjdp while ((c = srec_get_byte (abfd, &error)) != EOF 40433965Sjdp && (c == ' ' || c == '\t')) 40533965Sjdp ; 40633965Sjdp if (c == EOF) 40733965Sjdp { 40833965Sjdp srec_bad_byte (abfd, lineno, c, error); 40933965Sjdp goto error_return; 41033965Sjdp } 41133965Sjdp 41233965Sjdp /* Skip a dollar sign before the hex value. */ 41333965Sjdp if (c == '$') 41433965Sjdp { 41533965Sjdp c = srec_get_byte (abfd, &error); 41633965Sjdp if (c == EOF) 41733965Sjdp { 41833965Sjdp srec_bad_byte (abfd, lineno, c, error); 41933965Sjdp goto error_return; 42033965Sjdp } 42133965Sjdp } 42233965Sjdp 42333965Sjdp symval = 0; 42433965Sjdp while (ISHEX (c)) 42533965Sjdp { 42633965Sjdp symval <<= 4; 42733965Sjdp symval += NIBBLE (c); 42833965Sjdp c = srec_get_byte (abfd, &error); 42933965Sjdp } 43033965Sjdp 43133965Sjdp if (! srec_new_symbol (abfd, symname, symval)) 43233965Sjdp goto error_return; 43333965Sjdp } 43477298Sobrien while (c == ' ' || c == '\t') 43577298Sobrien ; 43633965Sjdp 43760484Sobrien if (c == '\n') 43860484Sobrien ++lineno; 43960484Sobrien else if (c != '\r') 44033965Sjdp { 44133965Sjdp srec_bad_byte (abfd, lineno, c, error); 44233965Sjdp goto error_return; 44333965Sjdp } 44433965Sjdp 44533965Sjdp break; 44677298Sobrien 44733965Sjdp case 'S': 44833965Sjdp { 44933965Sjdp file_ptr pos; 45033965Sjdp char hdr[3]; 45133965Sjdp unsigned int bytes; 45233965Sjdp bfd_vma address; 45333965Sjdp bfd_byte *data; 45433965Sjdp 45533965Sjdp /* Starting an S-record. */ 45633965Sjdp 45733965Sjdp pos = bfd_tell (abfd) - 1; 45833965Sjdp 45989857Sobrien if (bfd_bread (hdr, (bfd_size_type) 3, abfd) != 3) 46033965Sjdp goto error_return; 46133965Sjdp 46233965Sjdp if (! ISHEX (hdr[1]) || ! ISHEX (hdr[2])) 46333965Sjdp { 46433965Sjdp if (! ISHEX (hdr[1])) 46533965Sjdp c = hdr[1]; 46633965Sjdp else 46733965Sjdp c = hdr[2]; 46833965Sjdp srec_bad_byte (abfd, lineno, c, error); 46933965Sjdp goto error_return; 47033965Sjdp } 47133965Sjdp 47233965Sjdp bytes = HEX (hdr + 1); 47333965Sjdp if (bytes * 2 > bufsize) 47433965Sjdp { 47533965Sjdp if (buf != NULL) 47633965Sjdp free (buf); 477218822Sdim buf = bfd_malloc ((bfd_size_type) bytes * 2); 47833965Sjdp if (buf == NULL) 47933965Sjdp goto error_return; 48033965Sjdp bufsize = bytes * 2; 48133965Sjdp } 48233965Sjdp 48389857Sobrien if (bfd_bread (buf, (bfd_size_type) bytes * 2, abfd) != bytes * 2) 48433965Sjdp goto error_return; 48533965Sjdp 48633965Sjdp /* Ignore the checksum byte. */ 48733965Sjdp --bytes; 48833965Sjdp 48933965Sjdp address = 0; 49033965Sjdp data = buf; 49133965Sjdp switch (hdr[0]) 49233965Sjdp { 49333965Sjdp case '0': 49433965Sjdp case '5': 49533965Sjdp /* Prologue--ignore the file name, but stop building a 496130561Sobrien section at this point. */ 49733965Sjdp sec = NULL; 49833965Sjdp break; 49933965Sjdp 50033965Sjdp case '3': 50133965Sjdp address = HEX (data); 50233965Sjdp data += 2; 50333965Sjdp --bytes; 50433965Sjdp /* Fall through. */ 50533965Sjdp case '2': 50633965Sjdp address = (address << 8) | HEX (data); 50733965Sjdp data += 2; 50833965Sjdp --bytes; 50933965Sjdp /* Fall through. */ 51033965Sjdp case '1': 51133965Sjdp address = (address << 8) | HEX (data); 51233965Sjdp data += 2; 51333965Sjdp address = (address << 8) | HEX (data); 51433965Sjdp data += 2; 51533965Sjdp bytes -= 2; 51633965Sjdp 51733965Sjdp if (sec != NULL 518218822Sdim && sec->vma + sec->size == address) 51933965Sjdp { 52033965Sjdp /* This data goes at the end of the section we are 521130561Sobrien currently building. */ 522218822Sdim sec->size += bytes; 52333965Sjdp } 52433965Sjdp else 52533965Sjdp { 52633965Sjdp char secbuf[20]; 52733965Sjdp char *secname; 52889857Sobrien bfd_size_type amt; 529218822Sdim flagword flags; 53033965Sjdp 53133965Sjdp sprintf (secbuf, ".sec%d", bfd_count_sections (abfd) + 1); 53289857Sobrien amt = strlen (secbuf) + 1; 533218822Sdim secname = bfd_alloc (abfd, amt); 53433965Sjdp strcpy (secname, secbuf); 535218822Sdim flags = SEC_HAS_CONTENTS | SEC_LOAD | SEC_ALLOC; 536218822Sdim sec = bfd_make_section_with_flags (abfd, secname, flags); 53733965Sjdp if (sec == NULL) 53833965Sjdp goto error_return; 53933965Sjdp sec->vma = address; 54033965Sjdp sec->lma = address; 541218822Sdim sec->size = bytes; 54233965Sjdp sec->filepos = pos; 54333965Sjdp } 54433965Sjdp break; 54533965Sjdp 54633965Sjdp case '7': 54733965Sjdp address = HEX (data); 54833965Sjdp data += 2; 54933965Sjdp /* Fall through. */ 55033965Sjdp case '8': 55133965Sjdp address = (address << 8) | HEX (data); 55233965Sjdp data += 2; 55333965Sjdp /* Fall through. */ 55433965Sjdp case '9': 55533965Sjdp address = (address << 8) | HEX (data); 55633965Sjdp data += 2; 55733965Sjdp address = (address << 8) | HEX (data); 55833965Sjdp data += 2; 55933965Sjdp 56033965Sjdp /* This is a termination record. */ 56133965Sjdp abfd->start_address = address; 56233965Sjdp 56333965Sjdp if (buf != NULL) 56433965Sjdp free (buf); 56533965Sjdp 566130561Sobrien return TRUE; 56733965Sjdp } 56833965Sjdp } 56933965Sjdp break; 57033965Sjdp } 57133965Sjdp } 57233965Sjdp 57333965Sjdp if (error) 57433965Sjdp goto error_return; 57533965Sjdp 57633965Sjdp if (buf != NULL) 57733965Sjdp free (buf); 57833965Sjdp 579130561Sobrien return TRUE; 58033965Sjdp 58133965Sjdp error_return: 58233965Sjdp if (symbuf != NULL) 58333965Sjdp free (symbuf); 58433965Sjdp if (buf != NULL) 58533965Sjdp free (buf); 586130561Sobrien return FALSE; 58733965Sjdp} 58833965Sjdp 58933965Sjdp/* Check whether an existing file is an S-record file. */ 59033965Sjdp 59133965Sjdpstatic const bfd_target * 592218822Sdimsrec_object_p (bfd *abfd) 59333965Sjdp{ 594218822Sdim void * tdata_save; 59533965Sjdp bfd_byte b[4]; 59633965Sjdp 59733965Sjdp srec_init (); 59833965Sjdp 59933965Sjdp if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0 60089857Sobrien || bfd_bread (b, (bfd_size_type) 4, abfd) != 4) 60133965Sjdp return NULL; 60233965Sjdp 60333965Sjdp if (b[0] != 'S' || !ISHEX (b[1]) || !ISHEX (b[2]) || !ISHEX (b[3])) 60433965Sjdp { 60533965Sjdp bfd_set_error (bfd_error_wrong_format); 60633965Sjdp return NULL; 60733965Sjdp } 60833965Sjdp 609104834Sobrien tdata_save = abfd->tdata.any; 610104834Sobrien if (! srec_mkobject (abfd) || ! srec_scan (abfd)) 611104834Sobrien { 612104834Sobrien if (abfd->tdata.any != tdata_save && abfd->tdata.any != NULL) 613104834Sobrien bfd_release (abfd, abfd->tdata.any); 614104834Sobrien abfd->tdata.any = tdata_save; 615104834Sobrien return NULL; 616104834Sobrien } 61733965Sjdp 61860484Sobrien if (abfd->symcount > 0) 61960484Sobrien abfd->flags |= HAS_SYMS; 62060484Sobrien 62133965Sjdp return abfd->xvec; 62233965Sjdp} 62333965Sjdp 62433965Sjdp/* Check whether an existing file is an S-record file with symbols. */ 62533965Sjdp 62633965Sjdpstatic const bfd_target * 627218822Sdimsymbolsrec_object_p (bfd *abfd) 62833965Sjdp{ 629218822Sdim void * tdata_save; 63033965Sjdp char b[2]; 63133965Sjdp 63233965Sjdp srec_init (); 63333965Sjdp 63433965Sjdp if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0 63589857Sobrien || bfd_bread (b, (bfd_size_type) 2, abfd) != 2) 63633965Sjdp return NULL; 63733965Sjdp 63833965Sjdp if (b[0] != '$' || b[1] != '$') 63933965Sjdp { 64033965Sjdp bfd_set_error (bfd_error_wrong_format); 64133965Sjdp return NULL; 64233965Sjdp } 64333965Sjdp 644104834Sobrien tdata_save = abfd->tdata.any; 645104834Sobrien if (! srec_mkobject (abfd) || ! srec_scan (abfd)) 646104834Sobrien { 647104834Sobrien if (abfd->tdata.any != tdata_save && abfd->tdata.any != NULL) 648104834Sobrien bfd_release (abfd, abfd->tdata.any); 649104834Sobrien abfd->tdata.any = tdata_save; 650104834Sobrien return NULL; 651104834Sobrien } 65233965Sjdp 65360484Sobrien if (abfd->symcount > 0) 65460484Sobrien abfd->flags |= HAS_SYMS; 65560484Sobrien 65633965Sjdp return abfd->xvec; 65733965Sjdp} 65833965Sjdp 65933965Sjdp/* Read in the contents of a section in an S-record file. */ 66033965Sjdp 661130561Sobrienstatic bfd_boolean 662218822Sdimsrec_read_section (bfd *abfd, asection *section, bfd_byte *contents) 66333965Sjdp{ 66433965Sjdp int c; 66533965Sjdp bfd_size_type sofar = 0; 666130561Sobrien bfd_boolean error = FALSE; 66733965Sjdp bfd_byte *buf = NULL; 66833965Sjdp size_t bufsize = 0; 66933965Sjdp 67033965Sjdp if (bfd_seek (abfd, section->filepos, SEEK_SET) != 0) 67133965Sjdp goto error_return; 67233965Sjdp 67333965Sjdp while ((c = srec_get_byte (abfd, &error)) != EOF) 67433965Sjdp { 67533965Sjdp bfd_byte hdr[3]; 67633965Sjdp unsigned int bytes; 67733965Sjdp bfd_vma address; 67833965Sjdp bfd_byte *data; 67933965Sjdp 68033965Sjdp if (c == '\r' || c == '\n') 68133965Sjdp continue; 68233965Sjdp 68333965Sjdp /* This is called after srec_scan has already been called, so we 684130561Sobrien ought to know the exact format. */ 68533965Sjdp BFD_ASSERT (c == 'S'); 68633965Sjdp 68789857Sobrien if (bfd_bread (hdr, (bfd_size_type) 3, abfd) != 3) 68833965Sjdp goto error_return; 68933965Sjdp 69033965Sjdp BFD_ASSERT (ISHEX (hdr[1]) && ISHEX (hdr[2])); 69133965Sjdp 69233965Sjdp bytes = HEX (hdr + 1); 69333965Sjdp 69433965Sjdp if (bytes * 2 > bufsize) 69533965Sjdp { 69633965Sjdp if (buf != NULL) 69733965Sjdp free (buf); 698218822Sdim buf = bfd_malloc ((bfd_size_type) bytes * 2); 69933965Sjdp if (buf == NULL) 70033965Sjdp goto error_return; 70133965Sjdp bufsize = bytes * 2; 70233965Sjdp } 70333965Sjdp 70489857Sobrien if (bfd_bread (buf, (bfd_size_type) bytes * 2, abfd) != bytes * 2) 70533965Sjdp goto error_return; 70633965Sjdp 70733965Sjdp address = 0; 70833965Sjdp data = buf; 70933965Sjdp switch (hdr[0]) 71033965Sjdp { 71133965Sjdp default: 712218822Sdim BFD_ASSERT (sofar == section->size); 71333965Sjdp if (buf != NULL) 71433965Sjdp free (buf); 715130561Sobrien return TRUE; 71633965Sjdp 71733965Sjdp case '3': 71833965Sjdp address = HEX (data); 71933965Sjdp data += 2; 72033965Sjdp --bytes; 72133965Sjdp /* Fall through. */ 72233965Sjdp case '2': 72333965Sjdp address = (address << 8) | HEX (data); 72433965Sjdp data += 2; 72533965Sjdp --bytes; 72633965Sjdp /* Fall through. */ 72733965Sjdp case '1': 72833965Sjdp address = (address << 8) | HEX (data); 72933965Sjdp data += 2; 73033965Sjdp address = (address << 8) | HEX (data); 73133965Sjdp data += 2; 73233965Sjdp bytes -= 2; 73333965Sjdp 73433965Sjdp if (address != section->vma + sofar) 73533965Sjdp { 73633965Sjdp /* We've come to the end of this section. */ 737218822Sdim BFD_ASSERT (sofar == section->size); 73833965Sjdp if (buf != NULL) 73933965Sjdp free (buf); 740130561Sobrien return TRUE; 74133965Sjdp } 74233965Sjdp 74333965Sjdp /* Don't consider checksum. */ 74433965Sjdp --bytes; 74533965Sjdp 74633965Sjdp while (bytes-- != 0) 74733965Sjdp { 74833965Sjdp contents[sofar] = HEX (data); 74933965Sjdp data += 2; 75033965Sjdp ++sofar; 75133965Sjdp } 75233965Sjdp 75333965Sjdp break; 75433965Sjdp } 75533965Sjdp } 75633965Sjdp 75733965Sjdp if (error) 75833965Sjdp goto error_return; 75933965Sjdp 760218822Sdim BFD_ASSERT (sofar == section->size); 76133965Sjdp 76233965Sjdp if (buf != NULL) 76333965Sjdp free (buf); 76433965Sjdp 765130561Sobrien return TRUE; 76633965Sjdp 76733965Sjdp error_return: 76833965Sjdp if (buf != NULL) 76933965Sjdp free (buf); 770130561Sobrien return FALSE; 77133965Sjdp} 77233965Sjdp 77333965Sjdp/* Get the contents of a section in an S-record file. */ 77433965Sjdp 775130561Sobrienstatic bfd_boolean 776218822Sdimsrec_get_section_contents (bfd *abfd, 777218822Sdim asection *section, 778218822Sdim void * location, 779218822Sdim file_ptr offset, 780218822Sdim bfd_size_type count) 78133965Sjdp{ 78233965Sjdp if (section->used_by_bfd == NULL) 78333965Sjdp { 784218822Sdim section->used_by_bfd = bfd_alloc (abfd, section->size); 785218822Sdim if (section->used_by_bfd == NULL && section->size != 0) 786130561Sobrien return FALSE; 78733965Sjdp 78833965Sjdp if (! srec_read_section (abfd, section, section->used_by_bfd)) 789130561Sobrien return FALSE; 79033965Sjdp } 79133965Sjdp 79233965Sjdp memcpy (location, (bfd_byte *) section->used_by_bfd + offset, 79333965Sjdp (size_t) count); 79433965Sjdp 795130561Sobrien return TRUE; 79633965Sjdp} 79733965Sjdp 79833965Sjdp/* Set the architecture. We accept an unknown architecture here. */ 79933965Sjdp 800130561Sobrienstatic bfd_boolean 801218822Sdimsrec_set_arch_mach (bfd *abfd, enum bfd_architecture arch, unsigned long mach) 80233965Sjdp{ 803218822Sdim if (arch != bfd_arch_unknown) 804218822Sdim return bfd_default_set_arch_mach (abfd, arch, mach); 805218822Sdim 806218822Sdim abfd->arch_info = & bfd_default_arch_struct; 807218822Sdim return TRUE; 80833965Sjdp} 80933965Sjdp 81077298Sobrien/* We have to save up all the Srecords for a splurge before output. */ 81133965Sjdp 812130561Sobrienstatic bfd_boolean 813218822Sdimsrec_set_section_contents (bfd *abfd, 814218822Sdim sec_ptr section, 815218822Sdim const void * location, 816218822Sdim file_ptr offset, 817218822Sdim bfd_size_type bytes_to_do) 81833965Sjdp{ 81933965Sjdp tdata_type *tdata = abfd->tdata.srec_data; 820218822Sdim srec_data_list_type *entry; 82133965Sjdp 822218822Sdim entry = bfd_alloc (abfd, sizeof (* entry)); 82333965Sjdp if (entry == NULL) 824130561Sobrien return FALSE; 82533965Sjdp 82633965Sjdp if (bytes_to_do 82733965Sjdp && (section->flags & SEC_ALLOC) 82833965Sjdp && (section->flags & SEC_LOAD)) 82933965Sjdp { 83089857Sobrien bfd_byte *data; 83189857Sobrien 832218822Sdim data = bfd_alloc (abfd, bytes_to_do); 83333965Sjdp if (data == NULL) 834130561Sobrien return FALSE; 835218822Sdim memcpy ((void *) data, location, (size_t) bytes_to_do); 83633965Sjdp 837130561Sobrien /* Ff S3Forced is TRUE then always select S3 records, 83877298Sobrien regardless of the siez of the addresses. */ 83977298Sobrien if (S3Forced) 84077298Sobrien tdata->type = 3; 84177298Sobrien else if ((section->lma + offset + bytes_to_do - 1) <= 0xffff) 84277298Sobrien ; /* The default, S1, is OK. */ 84333965Sjdp else if ((section->lma + offset + bytes_to_do - 1) <= 0xffffff 84460484Sobrien && tdata->type <= 2) 84577298Sobrien tdata->type = 2; 84633965Sjdp else 84777298Sobrien tdata->type = 3; 84833965Sjdp 84933965Sjdp entry->data = data; 85033965Sjdp entry->where = section->lma + offset; 85133965Sjdp entry->size = bytes_to_do; 85233965Sjdp 85333965Sjdp /* Sort the records by address. Optimize for the common case of 854130561Sobrien adding a record to the end of the list. */ 85533965Sjdp if (tdata->tail != NULL 85633965Sjdp && entry->where >= tdata->tail->where) 85733965Sjdp { 85833965Sjdp tdata->tail->next = entry; 85933965Sjdp entry->next = NULL; 86033965Sjdp tdata->tail = entry; 86133965Sjdp } 86233965Sjdp else 86333965Sjdp { 864218822Sdim srec_data_list_type **look; 86533965Sjdp 86633965Sjdp for (look = &tdata->head; 86733965Sjdp *look != NULL && (*look)->where < entry->where; 86833965Sjdp look = &(*look)->next) 86933965Sjdp ; 87033965Sjdp entry->next = *look; 87133965Sjdp *look = entry; 87233965Sjdp if (entry->next == NULL) 87333965Sjdp tdata->tail = entry; 87433965Sjdp } 87533965Sjdp } 876130561Sobrien return TRUE; 87733965Sjdp} 87833965Sjdp 87933965Sjdp/* Write a record of type, of the supplied number of bytes. The 88033965Sjdp supplied bytes and length don't have a checksum. That's worked out 88177298Sobrien here. */ 88277298Sobrien 883130561Sobrienstatic bfd_boolean 884218822Sdimsrec_write_record (bfd *abfd, 885218822Sdim unsigned int type, 886218822Sdim bfd_vma address, 887218822Sdim const bfd_byte *data, 888218822Sdim const bfd_byte *end) 88933965Sjdp{ 89094536Sobrien char buffer[2 * MAXCHUNK + 6]; 89133965Sjdp unsigned int check_sum = 0; 89289857Sobrien const bfd_byte *src = data; 89333965Sjdp char *dst = buffer; 89433965Sjdp char *length; 89533965Sjdp bfd_size_type wrlen; 89633965Sjdp 89733965Sjdp *dst++ = 'S'; 89833965Sjdp *dst++ = '0' + type; 89933965Sjdp 90033965Sjdp length = dst; 90177298Sobrien dst += 2; /* Leave room for dst. */ 90233965Sjdp 90333965Sjdp switch (type) 90433965Sjdp { 90533965Sjdp case 3: 90633965Sjdp case 7: 90733965Sjdp TOHEX (dst, (address >> 24), check_sum); 90833965Sjdp dst += 2; 90933965Sjdp case 8: 91033965Sjdp case 2: 91133965Sjdp TOHEX (dst, (address >> 16), check_sum); 91233965Sjdp dst += 2; 91333965Sjdp case 9: 91433965Sjdp case 1: 91533965Sjdp case 0: 91633965Sjdp TOHEX (dst, (address >> 8), check_sum); 91733965Sjdp dst += 2; 91833965Sjdp TOHEX (dst, (address), check_sum); 91933965Sjdp dst += 2; 92033965Sjdp break; 92133965Sjdp 92233965Sjdp } 92333965Sjdp for (src = data; src < end; src++) 92433965Sjdp { 92533965Sjdp TOHEX (dst, *src, check_sum); 92633965Sjdp dst += 2; 92733965Sjdp } 92833965Sjdp 92977298Sobrien /* Fill in the length. */ 93033965Sjdp TOHEX (length, (dst - length) / 2, check_sum); 93133965Sjdp check_sum &= 0xff; 93233965Sjdp check_sum = 255 - check_sum; 93333965Sjdp TOHEX (dst, check_sum, check_sum); 93433965Sjdp dst += 2; 93533965Sjdp 93633965Sjdp *dst++ = '\r'; 93733965Sjdp *dst++ = '\n'; 93833965Sjdp wrlen = dst - buffer; 939218822Sdim 940218822Sdim return bfd_bwrite ((void *) buffer, wrlen, abfd) == wrlen; 94133965Sjdp} 94233965Sjdp 943130561Sobrienstatic bfd_boolean 944218822Sdimsrec_write_header (bfd *abfd) 94533965Sjdp{ 94694536Sobrien unsigned int len = strlen (abfd->filename); 94733965Sjdp 948130561Sobrien /* I'll put an arbitrary 40 char limit on header size. */ 94994536Sobrien if (len > 40) 95094536Sobrien len = 40; 95177298Sobrien 95294536Sobrien return srec_write_record (abfd, 0, (bfd_vma) 0, 953218822Sdim (bfd_byte *) abfd->filename, 954218822Sdim (bfd_byte *) abfd->filename + len); 95533965Sjdp} 95633965Sjdp 957130561Sobrienstatic bfd_boolean 958218822Sdimsrec_write_section (bfd *abfd, 959218822Sdim tdata_type *tdata, 960218822Sdim srec_data_list_type *list) 96133965Sjdp{ 96260484Sobrien unsigned int octets_written = 0; 96333965Sjdp bfd_byte *location = list->data; 96433965Sjdp 96594536Sobrien /* Validate number of data bytes to write. The srec length byte 96694536Sobrien counts the address, data and crc bytes. S1 (tdata->type == 1) 96794536Sobrien records have two address bytes, S2 (tdata->type == 2) records 96894536Sobrien have three, and S3 (tdata->type == 3) records have four. 96994536Sobrien The total length can't exceed 255, and a zero data length will 97094536Sobrien spin for a long time. */ 97194536Sobrien if (Chunk == 0) 97294536Sobrien Chunk = 1; 97394536Sobrien else if (Chunk > MAXCHUNK - tdata->type - 2) 97494536Sobrien Chunk = MAXCHUNK - tdata->type - 2; 97594536Sobrien 97660484Sobrien while (octets_written < list->size) 97733965Sjdp { 97833965Sjdp bfd_vma address; 97960484Sobrien unsigned int octets_this_chunk = list->size - octets_written; 98033965Sjdp 98177298Sobrien if (octets_this_chunk > Chunk) 98277298Sobrien octets_this_chunk = Chunk; 98333965Sjdp 98460484Sobrien address = list->where + octets_written / bfd_octets_per_byte (abfd); 98533965Sjdp 98633965Sjdp if (! srec_write_record (abfd, 98733965Sjdp tdata->type, 98833965Sjdp address, 98933965Sjdp location, 99060484Sobrien location + octets_this_chunk)) 991130561Sobrien return FALSE; 99233965Sjdp 99360484Sobrien octets_written += octets_this_chunk; 99460484Sobrien location += octets_this_chunk; 99533965Sjdp } 99633965Sjdp 997130561Sobrien return TRUE; 99833965Sjdp} 99933965Sjdp 1000130561Sobrienstatic bfd_boolean 1001218822Sdimsrec_write_terminator (bfd *abfd, tdata_type *tdata) 100233965Sjdp{ 100333965Sjdp return srec_write_record (abfd, 10 - tdata->type, 100494536Sobrien abfd->start_address, NULL, NULL); 100533965Sjdp} 100633965Sjdp 1007130561Sobrienstatic bfd_boolean 1008218822Sdimsrec_write_symbols (bfd *abfd) 100933965Sjdp{ 101077298Sobrien /* Dump out the symbols of a bfd. */ 101133965Sjdp int i; 101233965Sjdp int count = bfd_get_symcount (abfd); 101333965Sjdp 101433965Sjdp if (count) 101533965Sjdp { 101689857Sobrien bfd_size_type len; 101733965Sjdp asymbol **table = bfd_get_outsymbols (abfd); 1018218822Sdim 101994536Sobrien len = strlen (abfd->filename); 102094536Sobrien if (bfd_bwrite ("$$ ", (bfd_size_type) 3, abfd) != 3 102194536Sobrien || bfd_bwrite (abfd->filename, len, abfd) != len 102294536Sobrien || bfd_bwrite ("\r\n", (bfd_size_type) 2, abfd) != 2) 1023130561Sobrien return FALSE; 102433965Sjdp 102533965Sjdp for (i = 0; i < count; i++) 102633965Sjdp { 102733965Sjdp asymbol *s = table[i]; 102860484Sobrien if (! bfd_is_local_label (abfd, s) 102960484Sobrien && (s->flags & BSF_DEBUGGING) == 0) 103033965Sjdp { 103177298Sobrien /* Just dump out non debug symbols. */ 1032130561Sobrien char buf[43], *p; 103333965Sjdp 103494536Sobrien len = strlen (s->name); 103594536Sobrien if (bfd_bwrite (" ", (bfd_size_type) 2, abfd) != 2 103694536Sobrien || bfd_bwrite (s->name, len, abfd) != len) 1037130561Sobrien return FALSE; 103894536Sobrien 1039130561Sobrien sprintf_vma (buf + 2, (s->value 104094536Sobrien + s->section->output_section->lma 104194536Sobrien + s->section->output_offset)); 1042130561Sobrien p = buf + 2; 104333965Sjdp while (p[0] == '0' && p[1] != 0) 104433965Sjdp p++; 104594536Sobrien len = strlen (p); 104694536Sobrien p[len] = '\r'; 104794536Sobrien p[len + 1] = '\n'; 1048130561Sobrien *--p = '$'; 104994536Sobrien *--p = ' '; 1050130561Sobrien len += 4; 105194536Sobrien if (bfd_bwrite (p, len, abfd) != len) 1052130561Sobrien return FALSE; 105333965Sjdp } 105433965Sjdp } 105594536Sobrien if (bfd_bwrite ("$$ \r\n", (bfd_size_type) 5, abfd) != 5) 1056130561Sobrien return FALSE; 105733965Sjdp } 105833965Sjdp 1059130561Sobrien return TRUE; 106033965Sjdp} 106133965Sjdp 1062130561Sobrienstatic bfd_boolean 1063218822Sdiminternal_srec_write_object_contents (bfd *abfd, int symbols) 106433965Sjdp{ 106533965Sjdp tdata_type *tdata = abfd->tdata.srec_data; 106633965Sjdp srec_data_list_type *list; 106733965Sjdp 106833965Sjdp if (symbols) 106933965Sjdp { 107033965Sjdp if (! srec_write_symbols (abfd)) 1071130561Sobrien return FALSE; 107233965Sjdp } 107333965Sjdp 107433965Sjdp if (! srec_write_header (abfd)) 1075130561Sobrien return FALSE; 107633965Sjdp 107777298Sobrien /* Now wander though all the sections provided and output them. */ 107833965Sjdp list = tdata->head; 107933965Sjdp 108033965Sjdp while (list != (srec_data_list_type *) NULL) 108133965Sjdp { 108233965Sjdp if (! srec_write_section (abfd, tdata, list)) 1083130561Sobrien return FALSE; 108433965Sjdp list = list->next; 108533965Sjdp } 108633965Sjdp return srec_write_terminator (abfd, tdata); 108733965Sjdp} 108833965Sjdp 1089130561Sobrienstatic bfd_boolean 1090218822Sdimsrec_write_object_contents (bfd *abfd) 109133965Sjdp{ 109233965Sjdp return internal_srec_write_object_contents (abfd, 0); 109333965Sjdp} 109433965Sjdp 1095130561Sobrienstatic bfd_boolean 1096218822Sdimsymbolsrec_write_object_contents (bfd *abfd) 109733965Sjdp{ 109833965Sjdp return internal_srec_write_object_contents (abfd, 1); 109933965Sjdp} 110033965Sjdp 110133965Sjdpstatic int 1102218822Sdimsrec_sizeof_headers (bfd *abfd ATTRIBUTE_UNUSED, 1103218822Sdim struct bfd_link_info *info ATTRIBUTE_UNUSED) 110433965Sjdp{ 110533965Sjdp return 0; 110633965Sjdp} 110733965Sjdp 110833965Sjdp/* Return the amount of memory needed to read the symbol table. */ 110933965Sjdp 111033965Sjdpstatic long 1111218822Sdimsrec_get_symtab_upper_bound (bfd *abfd) 111233965Sjdp{ 111333965Sjdp return (bfd_get_symcount (abfd) + 1) * sizeof (asymbol *); 111433965Sjdp} 111533965Sjdp 111633965Sjdp/* Return the symbol table. */ 111733965Sjdp 111833965Sjdpstatic long 1119218822Sdimsrec_canonicalize_symtab (bfd *abfd, asymbol **alocation) 112033965Sjdp{ 112189857Sobrien bfd_size_type symcount = bfd_get_symcount (abfd); 112233965Sjdp asymbol *csymbols; 112333965Sjdp unsigned int i; 112433965Sjdp 112533965Sjdp csymbols = abfd->tdata.srec_data->csymbols; 112633965Sjdp if (csymbols == NULL) 112733965Sjdp { 112833965Sjdp asymbol *c; 112933965Sjdp struct srec_symbol *s; 113033965Sjdp 1131218822Sdim csymbols = bfd_alloc (abfd, symcount * sizeof (asymbol)); 113233965Sjdp if (csymbols == NULL && symcount != 0) 1133130561Sobrien return 0; 113433965Sjdp abfd->tdata.srec_data->csymbols = csymbols; 113533965Sjdp 113633965Sjdp for (s = abfd->tdata.srec_data->symbols, c = csymbols; 113733965Sjdp s != NULL; 113833965Sjdp s = s->next, ++c) 113933965Sjdp { 114033965Sjdp c->the_bfd = abfd; 114133965Sjdp c->name = s->name; 114233965Sjdp c->value = s->val; 114333965Sjdp c->flags = BSF_GLOBAL; 114433965Sjdp c->section = bfd_abs_section_ptr; 114533965Sjdp c->udata.p = NULL; 114633965Sjdp } 114733965Sjdp } 114877298Sobrien 114933965Sjdp for (i = 0; i < symcount; i++) 115033965Sjdp *alocation++ = csymbols++; 115133965Sjdp *alocation = NULL; 115233965Sjdp 115333965Sjdp return symcount; 115433965Sjdp} 115533965Sjdp 115633965Sjdpstatic void 1157218822Sdimsrec_get_symbol_info (bfd *ignore_abfd ATTRIBUTE_UNUSED, 1158218822Sdim asymbol *symbol, 1159218822Sdim symbol_info *ret) 116033965Sjdp{ 116133965Sjdp bfd_symbol_info (symbol, ret); 116233965Sjdp} 116333965Sjdp 116433965Sjdpstatic void 1165218822Sdimsrec_print_symbol (bfd *abfd, 1166218822Sdim void * afile, 1167218822Sdim asymbol *symbol, 1168218822Sdim bfd_print_symbol_type how) 116933965Sjdp{ 117033965Sjdp FILE *file = (FILE *) afile; 1171218822Sdim 117233965Sjdp switch (how) 117333965Sjdp { 117433965Sjdp case bfd_print_symbol_name: 117533965Sjdp fprintf (file, "%s", symbol->name); 117633965Sjdp break; 117733965Sjdp default: 1178218822Sdim bfd_print_symbol_vandf (abfd, (void *) file, symbol); 117933965Sjdp fprintf (file, " %-5s %s", 118033965Sjdp symbol->section->name, 118133965Sjdp symbol->name); 118233965Sjdp } 118333965Sjdp} 118433965Sjdp 1185218822Sdim#define srec_close_and_cleanup _bfd_generic_close_and_cleanup 1186218822Sdim#define srec_bfd_free_cached_info _bfd_generic_bfd_free_cached_info 1187218822Sdim#define srec_new_section_hook _bfd_generic_new_section_hook 1188218822Sdim#define srec_bfd_is_target_special_symbol ((bfd_boolean (*) (bfd *, asymbol *)) bfd_false) 1189218822Sdim#define srec_bfd_is_local_label_name bfd_generic_is_local_label_name 1190218822Sdim#define srec_get_lineno _bfd_nosymbols_get_lineno 1191218822Sdim#define srec_find_nearest_line _bfd_nosymbols_find_nearest_line 1192218822Sdim#define srec_find_inliner_info _bfd_nosymbols_find_inliner_info 1193218822Sdim#define srec_make_empty_symbol _bfd_generic_make_empty_symbol 1194218822Sdim#define srec_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol 1195218822Sdim#define srec_read_minisymbols _bfd_generic_read_minisymbols 1196218822Sdim#define srec_minisymbol_to_symbol _bfd_generic_minisymbol_to_symbol 1197218822Sdim#define srec_get_section_contents_in_window _bfd_generic_get_section_contents_in_window 1198218822Sdim#define srec_bfd_get_relocated_section_contents bfd_generic_get_relocated_section_contents 1199218822Sdim#define srec_bfd_relax_section bfd_generic_relax_section 1200218822Sdim#define srec_bfd_gc_sections bfd_generic_gc_sections 1201218822Sdim#define srec_bfd_merge_sections bfd_generic_merge_sections 1202218822Sdim#define srec_bfd_is_group_section bfd_generic_is_group_section 1203218822Sdim#define srec_bfd_discard_group bfd_generic_discard_group 1204218822Sdim#define srec_section_already_linked _bfd_generic_section_already_linked 1205218822Sdim#define srec_bfd_link_hash_table_create _bfd_generic_link_hash_table_create 1206218822Sdim#define srec_bfd_link_hash_table_free _bfd_generic_link_hash_table_free 1207218822Sdim#define srec_bfd_link_add_symbols _bfd_generic_link_add_symbols 1208218822Sdim#define srec_bfd_link_just_syms _bfd_generic_link_just_syms 1209218822Sdim#define srec_bfd_final_link _bfd_generic_final_link 1210218822Sdim#define srec_bfd_link_split_section _bfd_generic_link_split_section 121133965Sjdp 121233965Sjdpconst bfd_target srec_vec = 121333965Sjdp{ 1214218822Sdim "srec", /* Name. */ 121533965Sjdp bfd_target_srec_flavour, 1216218822Sdim BFD_ENDIAN_UNKNOWN, /* Target byte order. */ 1217218822Sdim BFD_ENDIAN_UNKNOWN, /* Target headers byte order. */ 1218218822Sdim (HAS_RELOC | EXEC_P | /* Object flags. */ 121933965Sjdp HAS_LINENO | HAS_DEBUG | 122033965Sjdp HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED), 122133965Sjdp (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS 1222218822Sdim | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* Section flags. */ 1223218822Sdim 0, /* Leading underscore. */ 1224218822Sdim ' ', /* AR_pad_char. */ 1225218822Sdim 16, /* AR_max_namelen. */ 122633965Sjdp bfd_getb64, bfd_getb_signed_64, bfd_putb64, 122733965Sjdp bfd_getb32, bfd_getb_signed_32, bfd_putb32, 1228218822Sdim bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* Data. */ 122933965Sjdp bfd_getb64, bfd_getb_signed_64, bfd_putb64, 123033965Sjdp bfd_getb32, bfd_getb_signed_32, bfd_putb32, 1231218822Sdim bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* Hdrs. */ 123233965Sjdp 123333965Sjdp { 123433965Sjdp _bfd_dummy_target, 1235218822Sdim srec_object_p, /* bfd_check_format. */ 123633965Sjdp _bfd_dummy_target, 123733965Sjdp _bfd_dummy_target, 123833965Sjdp }, 123933965Sjdp { 124033965Sjdp bfd_false, 124133965Sjdp srec_mkobject, 124233965Sjdp _bfd_generic_mkarchive, 124333965Sjdp bfd_false, 124433965Sjdp }, 1245218822Sdim { /* bfd_write_contents. */ 124633965Sjdp bfd_false, 124733965Sjdp srec_write_object_contents, 124833965Sjdp _bfd_write_archive_contents, 124933965Sjdp bfd_false, 125033965Sjdp }, 125133965Sjdp 125233965Sjdp BFD_JUMP_TABLE_GENERIC (srec), 125333965Sjdp BFD_JUMP_TABLE_COPY (_bfd_generic), 125433965Sjdp BFD_JUMP_TABLE_CORE (_bfd_nocore), 125533965Sjdp BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive), 125633965Sjdp BFD_JUMP_TABLE_SYMBOLS (srec), 1257218822Sdim BFD_JUMP_TABLE_RELOCS (_bfd_norelocs), 125833965Sjdp BFD_JUMP_TABLE_WRITE (srec), 125933965Sjdp BFD_JUMP_TABLE_LINK (srec), 126033965Sjdp BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic), 126133965Sjdp 126260484Sobrien NULL, 126377298Sobrien 1264218822Sdim NULL 126533965Sjdp}; 126633965Sjdp 126733965Sjdpconst bfd_target symbolsrec_vec = 126833965Sjdp{ 1269218822Sdim "symbolsrec", /* Name. */ 127033965Sjdp bfd_target_srec_flavour, 1271218822Sdim BFD_ENDIAN_UNKNOWN, /* Target byte order. */ 1272218822Sdim BFD_ENDIAN_UNKNOWN, /* Target headers byte order. */ 1273218822Sdim (HAS_RELOC | EXEC_P | /* Object flags. */ 127433965Sjdp HAS_LINENO | HAS_DEBUG | 127533965Sjdp HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED), 127633965Sjdp (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS 1277218822Sdim | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* Section flags. */ 1278218822Sdim 0, /* Leading underscore. */ 1279218822Sdim ' ', /* AR_pad_char. */ 1280218822Sdim 16, /* AR_max_namelen. */ 128133965Sjdp bfd_getb64, bfd_getb_signed_64, bfd_putb64, 128233965Sjdp bfd_getb32, bfd_getb_signed_32, bfd_putb32, 1283218822Sdim bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* Data. */ 128433965Sjdp bfd_getb64, bfd_getb_signed_64, bfd_putb64, 128533965Sjdp bfd_getb32, bfd_getb_signed_32, bfd_putb32, 1286218822Sdim bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* Headers. */ 128733965Sjdp 128833965Sjdp { 128933965Sjdp _bfd_dummy_target, 1290218822Sdim symbolsrec_object_p, /* bfd_check_format. */ 129133965Sjdp _bfd_dummy_target, 129233965Sjdp _bfd_dummy_target, 129333965Sjdp }, 129433965Sjdp { 129533965Sjdp bfd_false, 129633965Sjdp srec_mkobject, 129733965Sjdp _bfd_generic_mkarchive, 129833965Sjdp bfd_false, 129933965Sjdp }, 1300218822Sdim { /* bfd_write_contents. */ 130133965Sjdp bfd_false, 130233965Sjdp symbolsrec_write_object_contents, 130333965Sjdp _bfd_write_archive_contents, 130433965Sjdp bfd_false, 130533965Sjdp }, 130633965Sjdp 130733965Sjdp BFD_JUMP_TABLE_GENERIC (srec), 130833965Sjdp BFD_JUMP_TABLE_COPY (_bfd_generic), 130933965Sjdp BFD_JUMP_TABLE_CORE (_bfd_nocore), 131033965Sjdp BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive), 131133965Sjdp BFD_JUMP_TABLE_SYMBOLS (srec), 1312218822Sdim BFD_JUMP_TABLE_RELOCS (_bfd_norelocs), 131333965Sjdp BFD_JUMP_TABLE_WRITE (srec), 131433965Sjdp BFD_JUMP_TABLE_LINK (srec), 131533965Sjdp BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic), 131633965Sjdp 131760484Sobrien NULL, 131877298Sobrien 1319218822Sdim NULL 132033965Sjdp}; 1321