srec.c revision 38889
133965Sjdp/* BFD back-end for s-record objects. 238889Sjdp Copyright 1990, 91, 92, 93, 94, 95, 96, 97, 1998 338889Sjdp Free Software Foundation, Inc. 433965Sjdp Written by Steve Chamberlain of Cygnus Support <sac@cygnus.com>. 533965Sjdp 633965SjdpThis file is part of BFD, the Binary File Descriptor library. 733965Sjdp 833965SjdpThis program is free software; you can redistribute it and/or modify 933965Sjdpit under the terms of the GNU General Public License as published by 1033965Sjdpthe Free Software Foundation; either version 2 of the License, or 1133965Sjdp(at your option) any later version. 1233965Sjdp 1333965SjdpThis program is distributed in the hope that it will be useful, 1433965Sjdpbut WITHOUT ANY WARRANTY; without even the implied warranty of 1533965SjdpMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1633965SjdpGNU General Public License for more details. 1733965Sjdp 1833965SjdpYou should have received a copy of the GNU General Public License 1933965Sjdpalong with this program; if not, write to the Free Software 2033965SjdpFoundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 2133965Sjdp 2233965Sjdp/* 2333965SjdpSUBSECTION 2433965Sjdp S-Record handling 2533965Sjdp 2633965SjdpDESCRIPTION 2733965Sjdp 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: 4533965Sjdp 4633965SjdpEXAMPLE 4733965Sjdp S<type><length><address><data><checksum> 4833965Sjdp 4933965SjdpDESCRIPTION 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 6433965Sjdp 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 7433965Sjdp 7533965SjdpSUBSECTION 7633965Sjdp Symbol S-Record handling 7733965Sjdp 7833965SjdpDESCRIPTION 7933965Sjdp Some ICE equipment understands an addition to the standard 8033965Sjdp S-Record format; symbols and their addresses can be sent 8133965Sjdp before the data. 8233965Sjdp 8333965Sjdp The format of this is: 8433965Sjdp ($$ <modulename> 8533965Sjdp (<space> <symbol> <address>)*) 8633965Sjdp $$ 8733965Sjdp 8833965Sjdp so a short symbol table could look like: 8933965Sjdp 9033965SjdpEXAMPLE 9133965Sjdp $$ flash.x 9233965Sjdp $$ flash.c 9333965Sjdp _port6 $0 9433965Sjdp _delay $4 9533965Sjdp _start $14 9633965Sjdp _etext $8036 9733965Sjdp _edata $8036 9833965Sjdp _end $8036 9933965Sjdp $$ 10033965Sjdp 10133965SjdpDESCRIPTION 10233965Sjdp We allow symbols to be anywhere in the data stream - the module names 10333965Sjdp are always ignored. 10433965Sjdp 10533965Sjdp*/ 10633965Sjdp 10733965Sjdp#include "bfd.h" 10833965Sjdp#include "sysdep.h" 10933965Sjdp#include "libbfd.h" 11033965Sjdp#include "libiberty.h" 11133965Sjdp#include <ctype.h> 11233965Sjdp 11333965Sjdpstatic void srec_get_symbol_info PARAMS ((bfd *, asymbol *, symbol_info *)); 11433965Sjdpstatic void srec_print_symbol 11533965Sjdp PARAMS ((bfd *, PTR, asymbol *, bfd_print_symbol_type)); 11633965Sjdpstatic void srec_init PARAMS ((void)); 11733965Sjdpstatic boolean srec_mkobject PARAMS ((bfd *)); 11833965Sjdpstatic int srec_get_byte PARAMS ((bfd *, boolean *)); 11933965Sjdpstatic void srec_bad_byte PARAMS ((bfd *, unsigned int, int, boolean)); 12033965Sjdpstatic boolean srec_scan PARAMS ((bfd *)); 12133965Sjdpstatic const bfd_target *srec_object_p PARAMS ((bfd *)); 12233965Sjdpstatic const bfd_target *symbolsrec_object_p PARAMS ((bfd *)); 12333965Sjdpstatic boolean srec_read_section PARAMS ((bfd *, asection *, bfd_byte *)); 12433965Sjdp 12533965Sjdpstatic boolean srec_write_record PARAMS ((bfd *, int, bfd_vma, 12633965Sjdp const bfd_byte *, 12733965Sjdp const bfd_byte *)); 12833965Sjdpstatic boolean srec_write_header PARAMS ((bfd *)); 12933965Sjdpstatic boolean srec_write_symbols PARAMS ((bfd *)); 13033965Sjdpstatic boolean srec_new_symbol PARAMS ((bfd *, const char *, bfd_vma)); 13133965Sjdpstatic boolean srec_get_section_contents 13233965Sjdp PARAMS ((bfd *, asection *, PTR, file_ptr, bfd_size_type)); 13333965Sjdpstatic boolean srec_set_arch_mach 13433965Sjdp PARAMS ((bfd *, enum bfd_architecture, unsigned long)); 13533965Sjdpstatic boolean srec_set_section_contents 13633965Sjdp PARAMS ((bfd *, sec_ptr, PTR, file_ptr, bfd_size_type)); 13733965Sjdpstatic boolean internal_srec_write_object_contents PARAMS ((bfd *, int)); 13833965Sjdpstatic boolean srec_write_object_contents PARAMS ((bfd *)); 13933965Sjdpstatic boolean symbolsrec_write_object_contents PARAMS ((bfd *)); 14033965Sjdpstatic int srec_sizeof_headers PARAMS ((bfd *, boolean)); 14133965Sjdpstatic asymbol *srec_make_empty_symbol PARAMS ((bfd *)); 14233965Sjdpstatic long srec_get_symtab_upper_bound PARAMS ((bfd *)); 14333965Sjdpstatic long srec_get_symtab PARAMS ((bfd *, asymbol **)); 14433965Sjdp 14533965Sjdp/* Macros for converting between hex and binary. */ 14633965Sjdp 14733965Sjdpstatic CONST char digs[] = "0123456789ABCDEF"; 14833965Sjdp 14933965Sjdp#define NIBBLE(x) hex_value(x) 15033965Sjdp#define HEX(buffer) ((NIBBLE((buffer)[0])<<4) + NIBBLE((buffer)[1])) 15133965Sjdp#define TOHEX(d, x, ch) \ 15233965Sjdp d[1] = digs[(x) & 0xf]; \ 15333965Sjdp d[0] = digs[((x)>>4)&0xf]; \ 15433965Sjdp ch += ((x) & 0xff); 15533965Sjdp#define ISHEX(x) hex_p(x) 15633965Sjdp 15733965Sjdp/* Initialize by filling in the hex conversion array. */ 15833965Sjdp 15933965Sjdpstatic void 16033965Sjdpsrec_init () 16133965Sjdp{ 16233965Sjdp static boolean inited = false; 16333965Sjdp 16433965Sjdp if (inited == false) 16533965Sjdp { 16633965Sjdp inited = true; 16733965Sjdp hex_init (); 16833965Sjdp } 16933965Sjdp} 17033965Sjdp 17133965Sjdp/* The maximum number of bytes on a line is FF */ 17233965Sjdp#define MAXCHUNK 0xff 17333965Sjdp/* The number of bytes we fit onto a line on output */ 17433965Sjdp#define CHUNK 21 17533965Sjdp 17633965Sjdp/* When writing an S-record file, the S-records can not be output as 17733965Sjdp they are seen. This structure is used to hold them in memory. */ 17833965Sjdp 17933965Sjdpstruct srec_data_list_struct 18033965Sjdp{ 18133965Sjdp struct srec_data_list_struct *next; 18233965Sjdp bfd_byte *data; 18333965Sjdp bfd_vma where; 18433965Sjdp bfd_size_type size; 18533965Sjdp}; 18633965Sjdp 18733965Sjdptypedef struct srec_data_list_struct srec_data_list_type; 18833965Sjdp 18933965Sjdp/* When scanning the S-record file, a linked list of srec_symbol 19033965Sjdp structures is built to represent the symbol table (if there is 19133965Sjdp one). */ 19233965Sjdp 19333965Sjdpstruct srec_symbol 19433965Sjdp{ 19533965Sjdp struct srec_symbol *next; 19633965Sjdp const char *name; 19733965Sjdp bfd_vma val; 19833965Sjdp}; 19933965Sjdp 20033965Sjdp/* The S-record tdata information. */ 20133965Sjdp 20233965Sjdptypedef struct srec_data_struct 20333965Sjdp { 20433965Sjdp srec_data_list_type *head; 20533965Sjdp srec_data_list_type *tail; 20633965Sjdp unsigned int type; 20733965Sjdp struct srec_symbol *symbols; 20833965Sjdp struct srec_symbol *symtail; 20933965Sjdp asymbol *csymbols; 21033965Sjdp } 21133965Sjdptdata_type; 21233965Sjdp 21333965Sjdpstatic boolean srec_write_section PARAMS ((bfd *, tdata_type *, 21433965Sjdp srec_data_list_type *)); 21533965Sjdpstatic boolean srec_write_terminator PARAMS ((bfd *, tdata_type *)); 21633965Sjdp 21733965Sjdp/* Set up the S-record tdata information. */ 21833965Sjdp 21933965Sjdpstatic boolean 22033965Sjdpsrec_mkobject (abfd) 22133965Sjdp bfd *abfd; 22233965Sjdp{ 22333965Sjdp srec_init (); 22433965Sjdp 22533965Sjdp if (abfd->tdata.srec_data == NULL) 22633965Sjdp { 22733965Sjdp tdata_type *tdata = (tdata_type *) bfd_alloc (abfd, sizeof (tdata_type)); 22833965Sjdp if (tdata == NULL) 22933965Sjdp return false; 23033965Sjdp abfd->tdata.srec_data = tdata; 23133965Sjdp tdata->type = 1; 23233965Sjdp tdata->head = NULL; 23333965Sjdp tdata->tail = NULL; 23433965Sjdp tdata->symbols = NULL; 23533965Sjdp tdata->symtail = NULL; 23633965Sjdp tdata->csymbols = NULL; 23733965Sjdp } 23833965Sjdp 23933965Sjdp return true; 24033965Sjdp} 24133965Sjdp 24233965Sjdp/* Read a byte from an S record file. Set *ERRORPTR if an error 24333965Sjdp occurred. Return EOF on error or end of file. */ 24433965Sjdp 24533965Sjdpstatic int 24633965Sjdpsrec_get_byte (abfd, errorptr) 24733965Sjdp bfd *abfd; 24833965Sjdp boolean *errorptr; 24933965Sjdp{ 25033965Sjdp bfd_byte c; 25133965Sjdp 25233965Sjdp if (bfd_read (&c, 1, 1, abfd) != 1) 25333965Sjdp { 25433965Sjdp if (bfd_get_error () != bfd_error_file_truncated) 25533965Sjdp *errorptr = true; 25633965Sjdp return EOF; 25733965Sjdp } 25833965Sjdp 25933965Sjdp return (int) (c & 0xff); 26033965Sjdp} 26133965Sjdp 26233965Sjdp/* Report a problem in an S record file. FIXME: This probably should 26333965Sjdp not call fprintf, but we really do need some mechanism for printing 26433965Sjdp error messages. */ 26533965Sjdp 26633965Sjdpstatic void 26733965Sjdpsrec_bad_byte (abfd, lineno, c, error) 26833965Sjdp bfd *abfd; 26933965Sjdp unsigned int lineno; 27033965Sjdp int c; 27133965Sjdp boolean error; 27233965Sjdp{ 27333965Sjdp if (c == EOF) 27433965Sjdp { 27533965Sjdp if (! error) 27633965Sjdp bfd_set_error (bfd_error_file_truncated); 27733965Sjdp } 27833965Sjdp else 27933965Sjdp { 28033965Sjdp char buf[10]; 28133965Sjdp 28233965Sjdp if (! isprint (c)) 28333965Sjdp sprintf (buf, "\\%03o", (unsigned int) c); 28433965Sjdp else 28533965Sjdp { 28633965Sjdp buf[0] = c; 28733965Sjdp buf[1] = '\0'; 28833965Sjdp } 28933965Sjdp (*_bfd_error_handler) 29033965Sjdp ("%s:%d: Unexpected character `%s' in S-record file\n", 29133965Sjdp bfd_get_filename (abfd), lineno, buf); 29233965Sjdp bfd_set_error (bfd_error_bad_value); 29333965Sjdp } 29433965Sjdp} 29533965Sjdp 29633965Sjdp/* Add a new symbol found in an S-record file. */ 29733965Sjdp 29833965Sjdpstatic boolean 29933965Sjdpsrec_new_symbol (abfd, name, val) 30033965Sjdp bfd *abfd; 30133965Sjdp const char *name; 30233965Sjdp bfd_vma val; 30333965Sjdp{ 30433965Sjdp struct srec_symbol *n; 30533965Sjdp 30633965Sjdp n = (struct srec_symbol *) bfd_alloc (abfd, sizeof (struct srec_symbol)); 30733965Sjdp if (n == NULL) 30833965Sjdp return false; 30933965Sjdp 31033965Sjdp n->name = name; 31133965Sjdp n->val = val; 31233965Sjdp 31333965Sjdp if (abfd->tdata.srec_data->symbols == NULL) 31433965Sjdp abfd->tdata.srec_data->symbols = n; 31533965Sjdp else 31633965Sjdp abfd->tdata.srec_data->symtail->next = n; 31733965Sjdp abfd->tdata.srec_data->symtail = n; 31833965Sjdp n->next = NULL; 31933965Sjdp 32033965Sjdp ++abfd->symcount; 32133965Sjdp 32233965Sjdp return true; 32333965Sjdp} 32433965Sjdp 32533965Sjdp/* Read the S record file and turn it into sections. We create a new 32633965Sjdp section for each contiguous set of bytes. */ 32733965Sjdp 32833965Sjdpstatic boolean 32933965Sjdpsrec_scan (abfd) 33033965Sjdp bfd *abfd; 33133965Sjdp{ 33233965Sjdp int c; 33333965Sjdp unsigned int lineno = 1; 33433965Sjdp boolean error = false; 33533965Sjdp bfd_byte *buf = NULL; 33633965Sjdp size_t bufsize = 0; 33733965Sjdp asection *sec = NULL; 33833965Sjdp char *symbuf = NULL; 33933965Sjdp 34033965Sjdp if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0) 34133965Sjdp goto error_return; 34233965Sjdp 34333965Sjdp while ((c = srec_get_byte (abfd, &error)) != EOF) 34433965Sjdp { 34533965Sjdp /* We only build sections from contiguous S-records, so if this 34633965Sjdp is not an S-record, then stop building a section. */ 34733965Sjdp if (c != 'S' && c != '\r' && c != '\n') 34833965Sjdp sec = NULL; 34933965Sjdp 35033965Sjdp switch (c) 35133965Sjdp { 35233965Sjdp default: 35333965Sjdp srec_bad_byte (abfd, lineno, c, error); 35433965Sjdp goto error_return; 35533965Sjdp 35633965Sjdp case '\n': 35733965Sjdp ++lineno; 35833965Sjdp break; 35933965Sjdp 36033965Sjdp case '\r': 36133965Sjdp break; 36233965Sjdp 36333965Sjdp case '$': 36433965Sjdp /* Starting a module name, which we ignore. */ 36533965Sjdp while ((c = srec_get_byte (abfd, &error)) != '\n' 36633965Sjdp && c != EOF) 36733965Sjdp ; 36833965Sjdp if (c == EOF) 36933965Sjdp { 37033965Sjdp srec_bad_byte (abfd, lineno, c, error); 37133965Sjdp goto error_return; 37233965Sjdp } 37333965Sjdp 37433965Sjdp ++lineno; 37533965Sjdp 37633965Sjdp break; 37733965Sjdp 37833965Sjdp case ' ': 37933965Sjdp do 38033965Sjdp { 38133965Sjdp unsigned int alc; 38233965Sjdp char *p, *symname; 38333965Sjdp bfd_vma symval; 38433965Sjdp 38533965Sjdp /* Starting a symbol definition. */ 38633965Sjdp while ((c = srec_get_byte (abfd, &error)) != EOF 38733965Sjdp && (c == ' ' || c == '\t')) 38833965Sjdp ; 38933965Sjdp 39033965Sjdp if (c == '\n') 39133965Sjdp break; 39233965Sjdp 39333965Sjdp if (c == EOF) 39433965Sjdp { 39533965Sjdp srec_bad_byte (abfd, lineno, c, error); 39633965Sjdp goto error_return; 39733965Sjdp } 39833965Sjdp 39933965Sjdp alc = 10; 40033965Sjdp symbuf = (char *) bfd_malloc (alc + 1); 40133965Sjdp if (symbuf == NULL) 40233965Sjdp goto error_return; 40333965Sjdp 40433965Sjdp p = symbuf; 40533965Sjdp 40633965Sjdp *p++ = c; 40733965Sjdp while ((c = srec_get_byte (abfd, &error)) != EOF 40833965Sjdp && ! isspace (c)) 40933965Sjdp { 41038889Sjdp if ((unsigned int) (p - symbuf) >= alc) 41133965Sjdp { 41233965Sjdp char *n; 41333965Sjdp 41433965Sjdp alc *= 2; 41533965Sjdp n = (char *) bfd_realloc (symbuf, alc + 1); 41633965Sjdp if (n == NULL) 41733965Sjdp goto error_return; 41833965Sjdp p = n + (p - symbuf); 41933965Sjdp symbuf = n; 42033965Sjdp } 42133965Sjdp 42233965Sjdp *p++ = c; 42333965Sjdp } 42433965Sjdp 42533965Sjdp if (c == EOF) 42633965Sjdp { 42733965Sjdp srec_bad_byte (abfd, lineno, c, error); 42833965Sjdp goto error_return; 42933965Sjdp } 43033965Sjdp 43133965Sjdp *p++ = '\0'; 43233965Sjdp symname = bfd_alloc (abfd, p - symbuf); 43333965Sjdp if (symname == NULL) 43433965Sjdp goto error_return; 43533965Sjdp strcpy (symname, symbuf); 43633965Sjdp free (symbuf); 43733965Sjdp symbuf = NULL; 43833965Sjdp 43933965Sjdp while ((c = srec_get_byte (abfd, &error)) != EOF 44033965Sjdp && (c == ' ' || c == '\t')) 44133965Sjdp ; 44233965Sjdp if (c == EOF) 44333965Sjdp { 44433965Sjdp srec_bad_byte (abfd, lineno, c, error); 44533965Sjdp goto error_return; 44633965Sjdp } 44733965Sjdp 44833965Sjdp /* Skip a dollar sign before the hex value. */ 44933965Sjdp if (c == '$') 45033965Sjdp { 45133965Sjdp c = srec_get_byte (abfd, &error); 45233965Sjdp if (c == EOF) 45333965Sjdp { 45433965Sjdp srec_bad_byte (abfd, lineno, c, error); 45533965Sjdp goto error_return; 45633965Sjdp } 45733965Sjdp } 45833965Sjdp 45933965Sjdp symval = 0; 46033965Sjdp while (ISHEX (c)) 46133965Sjdp { 46233965Sjdp symval <<= 4; 46333965Sjdp symval += NIBBLE (c); 46433965Sjdp c = srec_get_byte (abfd, &error); 46533965Sjdp } 46633965Sjdp 46733965Sjdp if (! srec_new_symbol (abfd, symname, symval)) 46833965Sjdp goto error_return; 46933965Sjdp } 47033965Sjdp while (c == ' ' || c == '\t'); 47133965Sjdp 47233965Sjdp if (c != '\n') 47333965Sjdp { 47433965Sjdp srec_bad_byte (abfd, lineno, c, error); 47533965Sjdp goto error_return; 47633965Sjdp } 47733965Sjdp 47833965Sjdp ++lineno; 47933965Sjdp 48033965Sjdp break; 48133965Sjdp 48233965Sjdp case 'S': 48333965Sjdp { 48433965Sjdp file_ptr pos; 48533965Sjdp char hdr[3]; 48633965Sjdp unsigned int bytes; 48733965Sjdp bfd_vma address; 48833965Sjdp bfd_byte *data; 48933965Sjdp 49033965Sjdp /* Starting an S-record. */ 49133965Sjdp 49233965Sjdp pos = bfd_tell (abfd) - 1; 49333965Sjdp 49433965Sjdp if (bfd_read (hdr, 1, 3, abfd) != 3) 49533965Sjdp goto error_return; 49633965Sjdp 49733965Sjdp if (! ISHEX (hdr[1]) || ! ISHEX (hdr[2])) 49833965Sjdp { 49933965Sjdp if (! ISHEX (hdr[1])) 50033965Sjdp c = hdr[1]; 50133965Sjdp else 50233965Sjdp c = hdr[2]; 50333965Sjdp srec_bad_byte (abfd, lineno, c, error); 50433965Sjdp goto error_return; 50533965Sjdp } 50633965Sjdp 50733965Sjdp bytes = HEX (hdr + 1); 50833965Sjdp if (bytes * 2 > bufsize) 50933965Sjdp { 51033965Sjdp if (buf != NULL) 51133965Sjdp free (buf); 51233965Sjdp buf = (bfd_byte *) bfd_malloc (bytes * 2); 51333965Sjdp if (buf == NULL) 51433965Sjdp goto error_return; 51533965Sjdp bufsize = bytes * 2; 51633965Sjdp } 51733965Sjdp 51833965Sjdp if (bfd_read (buf, 1, bytes * 2, abfd) != bytes * 2) 51933965Sjdp goto error_return; 52033965Sjdp 52133965Sjdp /* Ignore the checksum byte. */ 52233965Sjdp --bytes; 52333965Sjdp 52433965Sjdp address = 0; 52533965Sjdp data = buf; 52633965Sjdp switch (hdr[0]) 52733965Sjdp { 52833965Sjdp case '0': 52933965Sjdp case '5': 53033965Sjdp /* Prologue--ignore the file name, but stop building a 53133965Sjdp section at this point. */ 53233965Sjdp sec = NULL; 53333965Sjdp break; 53433965Sjdp 53533965Sjdp case '3': 53633965Sjdp address = HEX (data); 53733965Sjdp data += 2; 53833965Sjdp --bytes; 53933965Sjdp /* Fall through. */ 54033965Sjdp case '2': 54133965Sjdp address = (address << 8) | HEX (data); 54233965Sjdp data += 2; 54333965Sjdp --bytes; 54433965Sjdp /* Fall through. */ 54533965Sjdp case '1': 54633965Sjdp address = (address << 8) | HEX (data); 54733965Sjdp data += 2; 54833965Sjdp address = (address << 8) | HEX (data); 54933965Sjdp data += 2; 55033965Sjdp bytes -= 2; 55133965Sjdp 55233965Sjdp if (sec != NULL 55333965Sjdp && sec->vma + sec->_raw_size == address) 55433965Sjdp { 55533965Sjdp /* This data goes at the end of the section we are 55633965Sjdp currently building. */ 55733965Sjdp sec->_raw_size += bytes; 55833965Sjdp } 55933965Sjdp else 56033965Sjdp { 56133965Sjdp char secbuf[20]; 56233965Sjdp char *secname; 56333965Sjdp 56433965Sjdp sprintf (secbuf, ".sec%d", bfd_count_sections (abfd) + 1); 56533965Sjdp secname = (char *) bfd_alloc (abfd, strlen (secbuf) + 1); 56633965Sjdp strcpy (secname, secbuf); 56733965Sjdp sec = bfd_make_section (abfd, secname); 56833965Sjdp if (sec == NULL) 56933965Sjdp goto error_return; 57033965Sjdp sec->flags = SEC_HAS_CONTENTS | SEC_LOAD | SEC_ALLOC; 57133965Sjdp sec->vma = address; 57233965Sjdp sec->lma = address; 57333965Sjdp sec->_raw_size = bytes; 57433965Sjdp sec->filepos = pos; 57533965Sjdp } 57633965Sjdp 57733965Sjdp break; 57833965Sjdp 57933965Sjdp case '7': 58033965Sjdp address = HEX (data); 58133965Sjdp data += 2; 58233965Sjdp /* Fall through. */ 58333965Sjdp case '8': 58433965Sjdp address = (address << 8) | HEX (data); 58533965Sjdp data += 2; 58633965Sjdp /* Fall through. */ 58733965Sjdp case '9': 58833965Sjdp address = (address << 8) | HEX (data); 58933965Sjdp data += 2; 59033965Sjdp address = (address << 8) | HEX (data); 59133965Sjdp data += 2; 59233965Sjdp 59333965Sjdp /* This is a termination record. */ 59433965Sjdp abfd->start_address = address; 59533965Sjdp 59633965Sjdp if (buf != NULL) 59733965Sjdp free (buf); 59833965Sjdp 59933965Sjdp return true; 60033965Sjdp } 60133965Sjdp } 60233965Sjdp break; 60333965Sjdp } 60433965Sjdp } 60533965Sjdp 60633965Sjdp if (error) 60733965Sjdp goto error_return; 60833965Sjdp 60933965Sjdp if (buf != NULL) 61033965Sjdp free (buf); 61133965Sjdp 61233965Sjdp return true; 61333965Sjdp 61433965Sjdp error_return: 61533965Sjdp if (symbuf != NULL) 61633965Sjdp free (symbuf); 61733965Sjdp if (buf != NULL) 61833965Sjdp free (buf); 61933965Sjdp return false; 62033965Sjdp} 62133965Sjdp 62233965Sjdp/* Check whether an existing file is an S-record file. */ 62333965Sjdp 62433965Sjdpstatic const bfd_target * 62533965Sjdpsrec_object_p (abfd) 62633965Sjdp bfd *abfd; 62733965Sjdp{ 62833965Sjdp bfd_byte b[4]; 62933965Sjdp 63033965Sjdp srec_init (); 63133965Sjdp 63233965Sjdp if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0 63333965Sjdp || bfd_read (b, 1, 4, abfd) != 4) 63433965Sjdp return NULL; 63533965Sjdp 63633965Sjdp if (b[0] != 'S' || !ISHEX (b[1]) || !ISHEX (b[2]) || !ISHEX (b[3])) 63733965Sjdp { 63833965Sjdp bfd_set_error (bfd_error_wrong_format); 63933965Sjdp return NULL; 64033965Sjdp } 64133965Sjdp 64233965Sjdp if (! srec_mkobject (abfd) 64333965Sjdp || ! srec_scan (abfd)) 64433965Sjdp return NULL; 64533965Sjdp 64633965Sjdp return abfd->xvec; 64733965Sjdp} 64833965Sjdp 64933965Sjdp/* Check whether an existing file is an S-record file with symbols. */ 65033965Sjdp 65133965Sjdpstatic const bfd_target * 65233965Sjdpsymbolsrec_object_p (abfd) 65333965Sjdp bfd *abfd; 65433965Sjdp{ 65533965Sjdp char b[2]; 65633965Sjdp 65733965Sjdp srec_init (); 65833965Sjdp 65933965Sjdp if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0 66033965Sjdp || bfd_read (b, 1, 2, abfd) != 2) 66133965Sjdp return NULL; 66233965Sjdp 66333965Sjdp if (b[0] != '$' || b[1] != '$') 66433965Sjdp { 66533965Sjdp bfd_set_error (bfd_error_wrong_format); 66633965Sjdp return NULL; 66733965Sjdp } 66833965Sjdp 66933965Sjdp if (! srec_mkobject (abfd) 67033965Sjdp || ! srec_scan (abfd)) 67133965Sjdp return NULL; 67233965Sjdp 67333965Sjdp return abfd->xvec; 67433965Sjdp} 67533965Sjdp 67633965Sjdp/* Read in the contents of a section in an S-record file. */ 67733965Sjdp 67833965Sjdpstatic boolean 67933965Sjdpsrec_read_section (abfd, section, contents) 68033965Sjdp bfd *abfd; 68133965Sjdp asection *section; 68233965Sjdp bfd_byte *contents; 68333965Sjdp{ 68433965Sjdp int c; 68533965Sjdp bfd_size_type sofar = 0; 68633965Sjdp boolean error = false; 68733965Sjdp bfd_byte *buf = NULL; 68833965Sjdp size_t bufsize = 0; 68933965Sjdp 69033965Sjdp if (bfd_seek (abfd, section->filepos, SEEK_SET) != 0) 69133965Sjdp goto error_return; 69233965Sjdp 69333965Sjdp while ((c = srec_get_byte (abfd, &error)) != EOF) 69433965Sjdp { 69533965Sjdp bfd_byte hdr[3]; 69633965Sjdp unsigned int bytes; 69733965Sjdp bfd_vma address; 69833965Sjdp bfd_byte *data; 69933965Sjdp 70033965Sjdp if (c == '\r' || c == '\n') 70133965Sjdp continue; 70233965Sjdp 70333965Sjdp /* This is called after srec_scan has already been called, so we 70433965Sjdp ought to know the exact format. */ 70533965Sjdp BFD_ASSERT (c == 'S'); 70633965Sjdp 70733965Sjdp if (bfd_read (hdr, 1, 3, abfd) != 3) 70833965Sjdp goto error_return; 70933965Sjdp 71033965Sjdp BFD_ASSERT (ISHEX (hdr[1]) && ISHEX (hdr[2])); 71133965Sjdp 71233965Sjdp bytes = HEX (hdr + 1); 71333965Sjdp 71433965Sjdp if (bytes * 2 > bufsize) 71533965Sjdp { 71633965Sjdp if (buf != NULL) 71733965Sjdp free (buf); 71833965Sjdp buf = (bfd_byte *) bfd_malloc (bytes * 2); 71933965Sjdp if (buf == NULL) 72033965Sjdp goto error_return; 72133965Sjdp bufsize = bytes * 2; 72233965Sjdp } 72333965Sjdp 72433965Sjdp if (bfd_read (buf, 1, bytes * 2, abfd) != bytes * 2) 72533965Sjdp goto error_return; 72633965Sjdp 72733965Sjdp address = 0; 72833965Sjdp data = buf; 72933965Sjdp switch (hdr[0]) 73033965Sjdp { 73133965Sjdp default: 73233965Sjdp BFD_ASSERT (sofar == section->_raw_size); 73333965Sjdp if (buf != NULL) 73433965Sjdp free (buf); 73533965Sjdp return true; 73633965Sjdp 73733965Sjdp case '3': 73833965Sjdp address = HEX (data); 73933965Sjdp data += 2; 74033965Sjdp --bytes; 74133965Sjdp /* Fall through. */ 74233965Sjdp case '2': 74333965Sjdp address = (address << 8) | HEX (data); 74433965Sjdp data += 2; 74533965Sjdp --bytes; 74633965Sjdp /* Fall through. */ 74733965Sjdp case '1': 74833965Sjdp address = (address << 8) | HEX (data); 74933965Sjdp data += 2; 75033965Sjdp address = (address << 8) | HEX (data); 75133965Sjdp data += 2; 75233965Sjdp bytes -= 2; 75333965Sjdp 75433965Sjdp if (address != section->vma + sofar) 75533965Sjdp { 75633965Sjdp /* We've come to the end of this section. */ 75733965Sjdp BFD_ASSERT (sofar == section->_raw_size); 75833965Sjdp if (buf != NULL) 75933965Sjdp free (buf); 76033965Sjdp return true; 76133965Sjdp } 76233965Sjdp 76333965Sjdp /* Don't consider checksum. */ 76433965Sjdp --bytes; 76533965Sjdp 76633965Sjdp while (bytes-- != 0) 76733965Sjdp { 76833965Sjdp contents[sofar] = HEX (data); 76933965Sjdp data += 2; 77033965Sjdp ++sofar; 77133965Sjdp } 77233965Sjdp 77333965Sjdp break; 77433965Sjdp } 77533965Sjdp } 77633965Sjdp 77733965Sjdp if (error) 77833965Sjdp goto error_return; 77933965Sjdp 78033965Sjdp BFD_ASSERT (sofar == section->_raw_size); 78133965Sjdp 78233965Sjdp if (buf != NULL) 78333965Sjdp free (buf); 78433965Sjdp 78533965Sjdp return true; 78633965Sjdp 78733965Sjdp error_return: 78833965Sjdp if (buf != NULL) 78933965Sjdp free (buf); 79033965Sjdp return false; 79133965Sjdp} 79233965Sjdp 79333965Sjdp/* Get the contents of a section in an S-record file. */ 79433965Sjdp 79533965Sjdpstatic boolean 79633965Sjdpsrec_get_section_contents (abfd, section, location, offset, count) 79733965Sjdp bfd *abfd; 79833965Sjdp asection *section; 79933965Sjdp PTR location; 80033965Sjdp file_ptr offset; 80133965Sjdp bfd_size_type count; 80233965Sjdp{ 80333965Sjdp if (section->used_by_bfd == NULL) 80433965Sjdp { 80533965Sjdp section->used_by_bfd = bfd_alloc (abfd, section->_raw_size); 80633965Sjdp if (section->used_by_bfd == NULL 80733965Sjdp && section->_raw_size != 0) 80833965Sjdp return false; 80933965Sjdp 81033965Sjdp if (! srec_read_section (abfd, section, section->used_by_bfd)) 81133965Sjdp return false; 81233965Sjdp } 81333965Sjdp 81433965Sjdp memcpy (location, (bfd_byte *) section->used_by_bfd + offset, 81533965Sjdp (size_t) count); 81633965Sjdp 81733965Sjdp return true; 81833965Sjdp} 81933965Sjdp 82033965Sjdp/* Set the architecture. We accept an unknown architecture here. */ 82133965Sjdp 82233965Sjdpstatic boolean 82333965Sjdpsrec_set_arch_mach (abfd, arch, mach) 82433965Sjdp bfd *abfd; 82533965Sjdp enum bfd_architecture arch; 82633965Sjdp unsigned long mach; 82733965Sjdp{ 82833965Sjdp if (arch == bfd_arch_unknown) 82933965Sjdp { 83033965Sjdp abfd->arch_info = &bfd_default_arch_struct; 83133965Sjdp return true; 83233965Sjdp } 83333965Sjdp return bfd_default_set_arch_mach (abfd, arch, mach); 83433965Sjdp} 83533965Sjdp 83633965Sjdp/* we have to save up all the Srecords for a splurge before output */ 83733965Sjdp 83833965Sjdpstatic boolean 83933965Sjdpsrec_set_section_contents (abfd, section, location, offset, bytes_to_do) 84033965Sjdp bfd *abfd; 84133965Sjdp sec_ptr section; 84233965Sjdp PTR location; 84333965Sjdp file_ptr offset; 84433965Sjdp bfd_size_type bytes_to_do; 84533965Sjdp{ 84633965Sjdp tdata_type *tdata = abfd->tdata.srec_data; 84733965Sjdp register srec_data_list_type *entry; 84833965Sjdp 84933965Sjdp entry = ((srec_data_list_type *) 85033965Sjdp bfd_alloc (abfd, sizeof (srec_data_list_type))); 85133965Sjdp if (entry == NULL) 85233965Sjdp return false; 85333965Sjdp 85433965Sjdp if (bytes_to_do 85533965Sjdp && (section->flags & SEC_ALLOC) 85633965Sjdp && (section->flags & SEC_LOAD)) 85733965Sjdp { 85833965Sjdp bfd_byte *data = (bfd_byte *) bfd_alloc (abfd, bytes_to_do); 85933965Sjdp if (data == NULL) 86033965Sjdp return false; 86133965Sjdp memcpy ((PTR) data, location, (size_t) bytes_to_do); 86233965Sjdp 86333965Sjdp if ((section->lma + offset + bytes_to_do - 1) <= 0xffff) 86433965Sjdp { 86533965Sjdp 86633965Sjdp } 86733965Sjdp else if ((section->lma + offset + bytes_to_do - 1) <= 0xffffff 86833965Sjdp && tdata->type < 2) 86933965Sjdp { 87033965Sjdp tdata->type = 2; 87133965Sjdp } 87233965Sjdp else 87333965Sjdp { 87433965Sjdp tdata->type = 3; 87533965Sjdp } 87633965Sjdp 87733965Sjdp entry->data = data; 87833965Sjdp entry->where = section->lma + offset; 87933965Sjdp entry->size = bytes_to_do; 88033965Sjdp 88133965Sjdp /* Sort the records by address. Optimize for the common case of 88233965Sjdp adding a record to the end of the list. */ 88333965Sjdp if (tdata->tail != NULL 88433965Sjdp && entry->where >= tdata->tail->where) 88533965Sjdp { 88633965Sjdp tdata->tail->next = entry; 88733965Sjdp entry->next = NULL; 88833965Sjdp tdata->tail = entry; 88933965Sjdp } 89033965Sjdp else 89133965Sjdp { 89233965Sjdp register srec_data_list_type **look; 89333965Sjdp 89433965Sjdp for (look = &tdata->head; 89533965Sjdp *look != NULL && (*look)->where < entry->where; 89633965Sjdp look = &(*look)->next) 89733965Sjdp ; 89833965Sjdp entry->next = *look; 89933965Sjdp *look = entry; 90033965Sjdp if (entry->next == NULL) 90133965Sjdp tdata->tail = entry; 90233965Sjdp } 90333965Sjdp } 90433965Sjdp return true; 90533965Sjdp} 90633965Sjdp 90733965Sjdp/* Write a record of type, of the supplied number of bytes. The 90833965Sjdp supplied bytes and length don't have a checksum. That's worked out 90933965Sjdp here 91033965Sjdp*/ 91133965Sjdpstatic boolean 91233965Sjdpsrec_write_record (abfd, type, address, data, end) 91333965Sjdp bfd *abfd; 91433965Sjdp int type; 91533965Sjdp bfd_vma address; 91633965Sjdp const bfd_byte *data; 91733965Sjdp const bfd_byte *end; 91833965Sjdp{ 91933965Sjdp char buffer[MAXCHUNK]; 92033965Sjdp unsigned int check_sum = 0; 92133965Sjdp CONST bfd_byte *src = data; 92233965Sjdp char *dst = buffer; 92333965Sjdp char *length; 92433965Sjdp bfd_size_type wrlen; 92533965Sjdp 92633965Sjdp *dst++ = 'S'; 92733965Sjdp *dst++ = '0' + type; 92833965Sjdp 92933965Sjdp length = dst; 93033965Sjdp dst += 2; /* leave room for dst*/ 93133965Sjdp 93233965Sjdp switch (type) 93333965Sjdp { 93433965Sjdp case 3: 93533965Sjdp case 7: 93633965Sjdp TOHEX (dst, (address >> 24), check_sum); 93733965Sjdp dst += 2; 93833965Sjdp case 8: 93933965Sjdp case 2: 94033965Sjdp TOHEX (dst, (address >> 16), check_sum); 94133965Sjdp dst += 2; 94233965Sjdp case 9: 94333965Sjdp case 1: 94433965Sjdp case 0: 94533965Sjdp TOHEX (dst, (address >> 8), check_sum); 94633965Sjdp dst += 2; 94733965Sjdp TOHEX (dst, (address), check_sum); 94833965Sjdp dst += 2; 94933965Sjdp break; 95033965Sjdp 95133965Sjdp } 95233965Sjdp for (src = data; src < end; src++) 95333965Sjdp { 95433965Sjdp TOHEX (dst, *src, check_sum); 95533965Sjdp dst += 2; 95633965Sjdp } 95733965Sjdp 95833965Sjdp /* Fill in the length */ 95933965Sjdp TOHEX (length, (dst - length) / 2, check_sum); 96033965Sjdp check_sum &= 0xff; 96133965Sjdp check_sum = 255 - check_sum; 96233965Sjdp TOHEX (dst, check_sum, check_sum); 96333965Sjdp dst += 2; 96433965Sjdp 96533965Sjdp *dst++ = '\r'; 96633965Sjdp *dst++ = '\n'; 96733965Sjdp wrlen = dst - buffer; 96833965Sjdp if (bfd_write ((PTR) buffer, 1, wrlen, abfd) != wrlen) 96933965Sjdp return false; 97033965Sjdp return true; 97133965Sjdp} 97233965Sjdp 97333965Sjdp 97433965Sjdp 97533965Sjdpstatic boolean 97633965Sjdpsrec_write_header (abfd) 97733965Sjdp bfd *abfd; 97833965Sjdp{ 97933965Sjdp bfd_byte buffer[MAXCHUNK]; 98033965Sjdp bfd_byte *dst = buffer; 98133965Sjdp unsigned int i; 98233965Sjdp 98333965Sjdp /* I'll put an arbitary 40 char limit on header size */ 98433965Sjdp for (i = 0; i < 40 && abfd->filename[i]; i++) 98533965Sjdp { 98633965Sjdp *dst++ = abfd->filename[i]; 98733965Sjdp } 98833965Sjdp return srec_write_record (abfd, 0, 0, buffer, dst); 98933965Sjdp} 99033965Sjdp 99133965Sjdpstatic boolean 99233965Sjdpsrec_write_section (abfd, tdata, list) 99333965Sjdp bfd *abfd; 99433965Sjdp tdata_type *tdata; 99533965Sjdp srec_data_list_type *list; 99633965Sjdp{ 99733965Sjdp unsigned int bytes_written = 0; 99833965Sjdp bfd_byte *location = list->data; 99933965Sjdp 100033965Sjdp while (bytes_written < list->size) 100133965Sjdp { 100233965Sjdp bfd_vma address; 100333965Sjdp 100433965Sjdp unsigned int bytes_this_chunk = list->size - bytes_written; 100533965Sjdp 100633965Sjdp if (bytes_this_chunk > CHUNK) 100733965Sjdp { 100833965Sjdp bytes_this_chunk = CHUNK; 100933965Sjdp } 101033965Sjdp 101133965Sjdp address = list->where + bytes_written; 101233965Sjdp 101333965Sjdp if (! srec_write_record (abfd, 101433965Sjdp tdata->type, 101533965Sjdp address, 101633965Sjdp location, 101733965Sjdp location + bytes_this_chunk)) 101833965Sjdp return false; 101933965Sjdp 102033965Sjdp bytes_written += bytes_this_chunk; 102133965Sjdp location += bytes_this_chunk; 102233965Sjdp } 102333965Sjdp 102433965Sjdp return true; 102533965Sjdp} 102633965Sjdp 102733965Sjdpstatic boolean 102833965Sjdpsrec_write_terminator (abfd, tdata) 102933965Sjdp bfd *abfd; 103033965Sjdp tdata_type *tdata; 103133965Sjdp{ 103233965Sjdp bfd_byte buffer[2]; 103333965Sjdp 103433965Sjdp return srec_write_record (abfd, 10 - tdata->type, 103533965Sjdp abfd->start_address, buffer, buffer); 103633965Sjdp} 103733965Sjdp 103833965Sjdp 103933965Sjdp 104033965Sjdpstatic boolean 104133965Sjdpsrec_write_symbols (abfd) 104233965Sjdp bfd *abfd; 104333965Sjdp{ 104433965Sjdp char buffer[MAXCHUNK]; 104533965Sjdp /* Dump out the symbols of a bfd */ 104633965Sjdp int i; 104733965Sjdp int count = bfd_get_symcount (abfd); 104833965Sjdp 104933965Sjdp if (count) 105033965Sjdp { 105133965Sjdp size_t len; 105233965Sjdp asymbol **table = bfd_get_outsymbols (abfd); 105333965Sjdp sprintf (buffer, "$$ %s\r\n", abfd->filename); 105433965Sjdp 105533965Sjdp len = strlen (buffer); 105633965Sjdp if (bfd_write (buffer, len, 1, abfd) != len) 105733965Sjdp return false; 105833965Sjdp 105933965Sjdp for (i = 0; i < count; i++) 106033965Sjdp { 106133965Sjdp asymbol *s = table[i]; 106233965Sjdp#if 0 106333965Sjdp int len = strlen (s->name); 106433965Sjdp 106533965Sjdp /* If this symbol has a .[ocs] in it, it's probably a file name 106633965Sjdp and we'll output that as the module name */ 106733965Sjdp 106833965Sjdp if (len > 3 && s->name[len - 2] == '.') 106933965Sjdp { 107033965Sjdp int l; 107133965Sjdp sprintf (buffer, "$$ %s\r\n", s->name); 107233965Sjdp l = strlen (buffer); 107333965Sjdp if (bfd_write (buffer, l, 1, abfd) != l) 107433965Sjdp return false; 107533965Sjdp } 107633965Sjdp else 107733965Sjdp#endif 107833965Sjdp if (s->flags & (BSF_GLOBAL | BSF_LOCAL) 107933965Sjdp && (s->flags & BSF_DEBUGGING) == 0 108033965Sjdp && s->name[0] != '.' 108133965Sjdp && s->name[0] != 't') 108233965Sjdp { 108333965Sjdp /* Just dump out non debug symbols */ 108433965Sjdp bfd_size_type l; 108533965Sjdp char buf2[40], *p; 108633965Sjdp 108733965Sjdp sprintf_vma (buf2, 108833965Sjdp s->value + s->section->output_section->lma 108933965Sjdp + s->section->output_offset); 109033965Sjdp p = buf2; 109133965Sjdp while (p[0] == '0' && p[1] != 0) 109233965Sjdp p++; 109333965Sjdp sprintf (buffer, " %s $%s\r\n", s->name, p); 109433965Sjdp l = strlen (buffer); 109533965Sjdp if (bfd_write (buffer, l, 1, abfd) != l) 109633965Sjdp return false; 109733965Sjdp } 109833965Sjdp } 109933965Sjdp sprintf (buffer, "$$ \r\n"); 110033965Sjdp len = strlen (buffer); 110133965Sjdp if (bfd_write (buffer, len, 1, abfd) != len) 110233965Sjdp return false; 110333965Sjdp } 110433965Sjdp 110533965Sjdp return true; 110633965Sjdp} 110733965Sjdp 110833965Sjdpstatic boolean 110933965Sjdpinternal_srec_write_object_contents (abfd, symbols) 111033965Sjdp bfd *abfd; 111133965Sjdp int symbols; 111233965Sjdp{ 111333965Sjdp tdata_type *tdata = abfd->tdata.srec_data; 111433965Sjdp srec_data_list_type *list; 111533965Sjdp 111633965Sjdp if (symbols) 111733965Sjdp { 111833965Sjdp if (! srec_write_symbols (abfd)) 111933965Sjdp return false; 112033965Sjdp } 112133965Sjdp 112233965Sjdp if (! srec_write_header (abfd)) 112333965Sjdp return false; 112433965Sjdp 112533965Sjdp /* Now wander though all the sections provided and output them */ 112633965Sjdp list = tdata->head; 112733965Sjdp 112833965Sjdp while (list != (srec_data_list_type *) NULL) 112933965Sjdp { 113033965Sjdp if (! srec_write_section (abfd, tdata, list)) 113133965Sjdp return false; 113233965Sjdp list = list->next; 113333965Sjdp } 113433965Sjdp return srec_write_terminator (abfd, tdata); 113533965Sjdp} 113633965Sjdp 113733965Sjdpstatic boolean 113833965Sjdpsrec_write_object_contents (abfd) 113933965Sjdp bfd *abfd; 114033965Sjdp{ 114133965Sjdp return internal_srec_write_object_contents (abfd, 0); 114233965Sjdp} 114333965Sjdp 114433965Sjdpstatic boolean 114533965Sjdpsymbolsrec_write_object_contents (abfd) 114633965Sjdp bfd *abfd; 114733965Sjdp{ 114833965Sjdp return internal_srec_write_object_contents (abfd, 1); 114933965Sjdp} 115033965Sjdp 115133965Sjdp/*ARGSUSED*/ 115233965Sjdpstatic int 115333965Sjdpsrec_sizeof_headers (abfd, exec) 115433965Sjdp bfd *abfd; 115533965Sjdp boolean exec; 115633965Sjdp{ 115733965Sjdp return 0; 115833965Sjdp} 115933965Sjdp 116033965Sjdpstatic asymbol * 116133965Sjdpsrec_make_empty_symbol (abfd) 116233965Sjdp bfd *abfd; 116333965Sjdp{ 116433965Sjdp asymbol *new = (asymbol *) bfd_zalloc (abfd, sizeof (asymbol)); 116533965Sjdp if (new) 116633965Sjdp new->the_bfd = abfd; 116733965Sjdp return new; 116833965Sjdp} 116933965Sjdp 117033965Sjdp/* Return the amount of memory needed to read the symbol table. */ 117133965Sjdp 117233965Sjdpstatic long 117333965Sjdpsrec_get_symtab_upper_bound (abfd) 117433965Sjdp bfd *abfd; 117533965Sjdp{ 117633965Sjdp return (bfd_get_symcount (abfd) + 1) * sizeof (asymbol *); 117733965Sjdp} 117833965Sjdp 117933965Sjdp/* Return the symbol table. */ 118033965Sjdp 118133965Sjdpstatic long 118233965Sjdpsrec_get_symtab (abfd, alocation) 118333965Sjdp bfd *abfd; 118433965Sjdp asymbol **alocation; 118533965Sjdp{ 118633965Sjdp unsigned int symcount = bfd_get_symcount (abfd); 118733965Sjdp asymbol *csymbols; 118833965Sjdp unsigned int i; 118933965Sjdp 119033965Sjdp csymbols = abfd->tdata.srec_data->csymbols; 119133965Sjdp if (csymbols == NULL) 119233965Sjdp { 119333965Sjdp asymbol *c; 119433965Sjdp struct srec_symbol *s; 119533965Sjdp 119633965Sjdp csymbols = (asymbol *) bfd_alloc (abfd, symcount * sizeof (asymbol)); 119733965Sjdp if (csymbols == NULL && symcount != 0) 119833965Sjdp return false; 119933965Sjdp abfd->tdata.srec_data->csymbols = csymbols; 120033965Sjdp 120133965Sjdp for (s = abfd->tdata.srec_data->symbols, c = csymbols; 120233965Sjdp s != NULL; 120333965Sjdp s = s->next, ++c) 120433965Sjdp { 120533965Sjdp c->the_bfd = abfd; 120633965Sjdp c->name = s->name; 120733965Sjdp c->value = s->val; 120833965Sjdp c->flags = BSF_GLOBAL; 120933965Sjdp c->section = bfd_abs_section_ptr; 121033965Sjdp c->udata.p = NULL; 121133965Sjdp } 121233965Sjdp } 121333965Sjdp 121433965Sjdp for (i = 0; i < symcount; i++) 121533965Sjdp *alocation++ = csymbols++; 121633965Sjdp *alocation = NULL; 121733965Sjdp 121833965Sjdp return symcount; 121933965Sjdp} 122033965Sjdp 122133965Sjdp/*ARGSUSED*/ 122233965Sjdpstatic void 122333965Sjdpsrec_get_symbol_info (ignore_abfd, symbol, ret) 122433965Sjdp bfd *ignore_abfd; 122533965Sjdp asymbol *symbol; 122633965Sjdp symbol_info *ret; 122733965Sjdp{ 122833965Sjdp bfd_symbol_info (symbol, ret); 122933965Sjdp} 123033965Sjdp 123133965Sjdp/*ARGSUSED*/ 123233965Sjdpstatic void 123333965Sjdpsrec_print_symbol (ignore_abfd, afile, symbol, how) 123433965Sjdp bfd *ignore_abfd; 123533965Sjdp PTR afile; 123633965Sjdp asymbol *symbol; 123733965Sjdp bfd_print_symbol_type how; 123833965Sjdp{ 123933965Sjdp FILE *file = (FILE *) afile; 124033965Sjdp switch (how) 124133965Sjdp { 124233965Sjdp case bfd_print_symbol_name: 124333965Sjdp fprintf (file, "%s", symbol->name); 124433965Sjdp break; 124533965Sjdp default: 124633965Sjdp bfd_print_symbol_vandf ((PTR) file, symbol); 124733965Sjdp fprintf (file, " %-5s %s", 124833965Sjdp symbol->section->name, 124933965Sjdp symbol->name); 125033965Sjdp 125133965Sjdp } 125233965Sjdp} 125333965Sjdp 125433965Sjdp#define srec_close_and_cleanup _bfd_generic_close_and_cleanup 125533965Sjdp#define srec_bfd_free_cached_info _bfd_generic_bfd_free_cached_info 125633965Sjdp#define srec_new_section_hook _bfd_generic_new_section_hook 125733965Sjdp 125833965Sjdp#define srec_bfd_is_local_label_name bfd_generic_is_local_label_name 125933965Sjdp#define srec_get_lineno _bfd_nosymbols_get_lineno 126033965Sjdp#define srec_find_nearest_line _bfd_nosymbols_find_nearest_line 126133965Sjdp#define srec_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol 126233965Sjdp#define srec_read_minisymbols _bfd_generic_read_minisymbols 126333965Sjdp#define srec_minisymbol_to_symbol _bfd_generic_minisymbol_to_symbol 126433965Sjdp 126533965Sjdp#define srec_get_reloc_upper_bound \ 126633965Sjdp ((long (*) PARAMS ((bfd *, asection *))) bfd_0l) 126733965Sjdp#define srec_canonicalize_reloc \ 126833965Sjdp ((long (*) PARAMS ((bfd *, asection *, arelent **, asymbol **))) bfd_0l) 126933965Sjdp#define srec_bfd_reloc_type_lookup _bfd_norelocs_bfd_reloc_type_lookup 127033965Sjdp 127133965Sjdp#define srec_get_section_contents_in_window \ 127233965Sjdp _bfd_generic_get_section_contents_in_window 127333965Sjdp 127433965Sjdp#define srec_bfd_get_relocated_section_contents \ 127533965Sjdp bfd_generic_get_relocated_section_contents 127633965Sjdp#define srec_bfd_relax_section bfd_generic_relax_section 127733965Sjdp#define srec_bfd_link_hash_table_create _bfd_generic_link_hash_table_create 127833965Sjdp#define srec_bfd_link_add_symbols _bfd_generic_link_add_symbols 127933965Sjdp#define srec_bfd_final_link _bfd_generic_final_link 128033965Sjdp#define srec_bfd_link_split_section _bfd_generic_link_split_section 128133965Sjdp 128233965Sjdpconst bfd_target srec_vec = 128333965Sjdp{ 128433965Sjdp "srec", /* name */ 128533965Sjdp bfd_target_srec_flavour, 128633965Sjdp BFD_ENDIAN_UNKNOWN, /* target byte order */ 128733965Sjdp BFD_ENDIAN_UNKNOWN, /* target headers byte order */ 128833965Sjdp (HAS_RELOC | EXEC_P | /* object flags */ 128933965Sjdp HAS_LINENO | HAS_DEBUG | 129033965Sjdp HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED), 129133965Sjdp (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS 129233965Sjdp | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */ 129333965Sjdp 0, /* leading underscore */ 129433965Sjdp ' ', /* ar_pad_char */ 129533965Sjdp 16, /* ar_max_namelen */ 129633965Sjdp bfd_getb64, bfd_getb_signed_64, bfd_putb64, 129733965Sjdp bfd_getb32, bfd_getb_signed_32, bfd_putb32, 129833965Sjdp bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* data */ 129933965Sjdp bfd_getb64, bfd_getb_signed_64, bfd_putb64, 130033965Sjdp bfd_getb32, bfd_getb_signed_32, bfd_putb32, 130133965Sjdp bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* hdrs */ 130233965Sjdp 130333965Sjdp { 130433965Sjdp _bfd_dummy_target, 130533965Sjdp srec_object_p, /* bfd_check_format */ 130633965Sjdp _bfd_dummy_target, 130733965Sjdp _bfd_dummy_target, 130833965Sjdp }, 130933965Sjdp { 131033965Sjdp bfd_false, 131133965Sjdp srec_mkobject, 131233965Sjdp _bfd_generic_mkarchive, 131333965Sjdp bfd_false, 131433965Sjdp }, 131533965Sjdp { /* bfd_write_contents */ 131633965Sjdp bfd_false, 131733965Sjdp srec_write_object_contents, 131833965Sjdp _bfd_write_archive_contents, 131933965Sjdp bfd_false, 132033965Sjdp }, 132133965Sjdp 132233965Sjdp BFD_JUMP_TABLE_GENERIC (srec), 132333965Sjdp BFD_JUMP_TABLE_COPY (_bfd_generic), 132433965Sjdp BFD_JUMP_TABLE_CORE (_bfd_nocore), 132533965Sjdp BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive), 132633965Sjdp BFD_JUMP_TABLE_SYMBOLS (srec), 132733965Sjdp BFD_JUMP_TABLE_RELOCS (srec), 132833965Sjdp BFD_JUMP_TABLE_WRITE (srec), 132933965Sjdp BFD_JUMP_TABLE_LINK (srec), 133033965Sjdp BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic), 133133965Sjdp 133233965Sjdp (PTR) 0 133333965Sjdp}; 133433965Sjdp 133533965Sjdp 133633965Sjdp 133733965Sjdpconst bfd_target symbolsrec_vec = 133833965Sjdp{ 133933965Sjdp "symbolsrec", /* name */ 134033965Sjdp bfd_target_srec_flavour, 134133965Sjdp BFD_ENDIAN_UNKNOWN, /* target byte order */ 134233965Sjdp BFD_ENDIAN_UNKNOWN, /* target headers byte order */ 134333965Sjdp (HAS_RELOC | EXEC_P | /* object flags */ 134433965Sjdp HAS_LINENO | HAS_DEBUG | 134533965Sjdp HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED), 134633965Sjdp (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS 134733965Sjdp | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */ 134833965Sjdp 0, /* leading underscore */ 134933965Sjdp ' ', /* ar_pad_char */ 135033965Sjdp 16, /* ar_max_namelen */ 135133965Sjdp bfd_getb64, bfd_getb_signed_64, bfd_putb64, 135233965Sjdp bfd_getb32, bfd_getb_signed_32, bfd_putb32, 135333965Sjdp bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* data */ 135433965Sjdp bfd_getb64, bfd_getb_signed_64, bfd_putb64, 135533965Sjdp bfd_getb32, bfd_getb_signed_32, bfd_putb32, 135633965Sjdp bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* hdrs */ 135733965Sjdp 135833965Sjdp { 135933965Sjdp _bfd_dummy_target, 136033965Sjdp symbolsrec_object_p, /* bfd_check_format */ 136133965Sjdp _bfd_dummy_target, 136233965Sjdp _bfd_dummy_target, 136333965Sjdp }, 136433965Sjdp { 136533965Sjdp bfd_false, 136633965Sjdp srec_mkobject, 136733965Sjdp _bfd_generic_mkarchive, 136833965Sjdp bfd_false, 136933965Sjdp }, 137033965Sjdp { /* bfd_write_contents */ 137133965Sjdp bfd_false, 137233965Sjdp symbolsrec_write_object_contents, 137333965Sjdp _bfd_write_archive_contents, 137433965Sjdp bfd_false, 137533965Sjdp }, 137633965Sjdp 137733965Sjdp BFD_JUMP_TABLE_GENERIC (srec), 137833965Sjdp BFD_JUMP_TABLE_COPY (_bfd_generic), 137933965Sjdp BFD_JUMP_TABLE_CORE (_bfd_nocore), 138033965Sjdp BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive), 138133965Sjdp BFD_JUMP_TABLE_SYMBOLS (srec), 138233965Sjdp BFD_JUMP_TABLE_RELOCS (srec), 138333965Sjdp BFD_JUMP_TABLE_WRITE (srec), 138433965Sjdp BFD_JUMP_TABLE_LINK (srec), 138533965Sjdp BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic), 138633965Sjdp 138733965Sjdp (PTR) 0 138833965Sjdp}; 1389