xref: /dragonfly/contrib/binutils-2.34/bfd/srec.c (revision fae548d3)
1*fae548d3Szrj /* BFD back-end for s-record objects.
2*fae548d3Szrj    Copyright (C) 1990-2020 Free Software Foundation, Inc.
3*fae548d3Szrj    Written by Steve Chamberlain of Cygnus Support <sac@cygnus.com>.
4*fae548d3Szrj 
5*fae548d3Szrj    This file is part of BFD, the Binary File Descriptor library.
6*fae548d3Szrj 
7*fae548d3Szrj    This program is free software; you can redistribute it and/or modify
8*fae548d3Szrj    it under the terms of the GNU General Public License as published by
9*fae548d3Szrj    the Free Software Foundation; either version 3 of the License, or
10*fae548d3Szrj    (at your option) any later version.
11*fae548d3Szrj 
12*fae548d3Szrj    This program is distributed in the hope that it will be useful,
13*fae548d3Szrj    but WITHOUT ANY WARRANTY; without even the implied warranty of
14*fae548d3Szrj    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15*fae548d3Szrj    GNU General Public License for more details.
16*fae548d3Szrj 
17*fae548d3Szrj    You should have received a copy of the GNU General Public License
18*fae548d3Szrj    along with this program; if not, write to the Free Software
19*fae548d3Szrj    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
20*fae548d3Szrj    MA 02110-1301, USA.  */
21*fae548d3Szrj 
22*fae548d3Szrj 
23*fae548d3Szrj /* SUBSECTION
24*fae548d3Szrj 	S-Record handling
25*fae548d3Szrj 
26*fae548d3Szrj    DESCRIPTION
27*fae548d3Szrj 
28*fae548d3Szrj 	Ordinary S-Records cannot hold anything but addresses and
29*fae548d3Szrj 	data, so that's all that we implement.
30*fae548d3Szrj 
31*fae548d3Szrj 	The only interesting thing is that S-Records may come out of
32*fae548d3Szrj 	order and there is no header, so an initial scan is required
33*fae548d3Szrj 	to discover the minimum and maximum addresses used to create
34*fae548d3Szrj 	the vma and size of the only section we create.  We
35*fae548d3Szrj 	arbitrarily call this section ".text".
36*fae548d3Szrj 
37*fae548d3Szrj 	When bfd_get_section_contents is called the file is read
38*fae548d3Szrj 	again, and this time the data is placed into a bfd_alloc'd
39*fae548d3Szrj 	area.
40*fae548d3Szrj 
41*fae548d3Szrj 	Any number of sections may be created for output, we save them
42*fae548d3Szrj 	up and output them when it's time to close the bfd.
43*fae548d3Szrj 
44*fae548d3Szrj 	An s record looks like:
45*fae548d3Szrj 
46*fae548d3Szrj    EXAMPLE
47*fae548d3Szrj 	S<type><length><address><data><checksum>
48*fae548d3Szrj 
49*fae548d3Szrj    DESCRIPTION
50*fae548d3Szrj 	Where
51*fae548d3Szrj 	o length
52*fae548d3Szrj 	is the number of bytes following upto the checksum. Note that
53*fae548d3Szrj 	this is not the number of chars following, since it takes two
54*fae548d3Szrj 	chars to represent a byte.
55*fae548d3Szrj 	o type
56*fae548d3Szrj 	is one of:
57*fae548d3Szrj 	0) header record
58*fae548d3Szrj 	1) two byte address data record
59*fae548d3Szrj 	2) three byte address data record
60*fae548d3Szrj 	3) four byte address data record
61*fae548d3Szrj 	7) four byte address termination record
62*fae548d3Szrj 	8) three byte address termination record
63*fae548d3Szrj 	9) two byte address termination record
64*fae548d3Szrj 
65*fae548d3Szrj 	o address
66*fae548d3Szrj 	is the start address of the data following, or in the case of
67*fae548d3Szrj 	a termination record, the start address of the image
68*fae548d3Szrj 	o data
69*fae548d3Szrj 	is the data.
70*fae548d3Szrj 	o checksum
71*fae548d3Szrj 	is the sum of all the raw byte data in the record, from the length
72*fae548d3Szrj 	upwards, modulo 256 and subtracted from 255.
73*fae548d3Szrj 
74*fae548d3Szrj    SUBSECTION
75*fae548d3Szrj 	Symbol S-Record handling
76*fae548d3Szrj 
77*fae548d3Szrj    DESCRIPTION
78*fae548d3Szrj 	Some ICE equipment understands an addition to the standard
79*fae548d3Szrj 	S-Record format; symbols and their addresses can be sent
80*fae548d3Szrj 	before the data.
81*fae548d3Szrj 
82*fae548d3Szrj 	The format of this is:
83*fae548d3Szrj 	($$ <modulename>
84*fae548d3Szrj 		(<space> <symbol> <address>)*)
85*fae548d3Szrj 	$$
86*fae548d3Szrj 
87*fae548d3Szrj 	so a short symbol table could look like:
88*fae548d3Szrj 
89*fae548d3Szrj    EXAMPLE
90*fae548d3Szrj 	$$ flash.x
91*fae548d3Szrj 	$$ flash.c
92*fae548d3Szrj 	  _port6 $0
93*fae548d3Szrj 	  _delay $4
94*fae548d3Szrj 	  _start $14
95*fae548d3Szrj 	  _etext $8036
96*fae548d3Szrj 	  _edata $8036
97*fae548d3Szrj 	  _end $8036
98*fae548d3Szrj 	$$
99*fae548d3Szrj 
100*fae548d3Szrj    DESCRIPTION
101*fae548d3Szrj 	We allow symbols to be anywhere in the data stream - the module names
102*fae548d3Szrj 	are always ignored.  */
103*fae548d3Szrj 
104*fae548d3Szrj #include "sysdep.h"
105*fae548d3Szrj #include "bfd.h"
106*fae548d3Szrj #include "libbfd.h"
107*fae548d3Szrj #include "libiberty.h"
108*fae548d3Szrj #include "safe-ctype.h"
109*fae548d3Szrj 
110*fae548d3Szrj 
111*fae548d3Szrj /* Macros for converting between hex and binary.  */
112*fae548d3Szrj 
113*fae548d3Szrj static const char digs[] = "0123456789ABCDEF";
114*fae548d3Szrj 
115*fae548d3Szrj #define NIBBLE(x)    hex_value(x)
116*fae548d3Szrj #define HEX(buffer) ((NIBBLE ((buffer)[0])<<4) + NIBBLE ((buffer)[1]))
117*fae548d3Szrj #define TOHEX(d, x, ch) \
118*fae548d3Szrj 	d[1] = digs[(x) & 0xf]; \
119*fae548d3Szrj 	d[0] = digs[((x)>>4)&0xf]; \
120*fae548d3Szrj 	ch += ((x) & 0xff);
121*fae548d3Szrj #define	ISHEX(x)    hex_p(x)
122*fae548d3Szrj 
123*fae548d3Szrj /* The maximum number of address+data+crc bytes on a line is FF.  */
124*fae548d3Szrj #define MAXCHUNK 0xff
125*fae548d3Szrj 
126*fae548d3Szrj /* Default size for a CHUNK.  */
127*fae548d3Szrj #define DEFAULT_CHUNK 16
128*fae548d3Szrj 
129*fae548d3Szrj /* The number of data bytes we actually fit onto a line on output.
130*fae548d3Szrj    This variable can be modified by objcopy's --srec-len parameter.
131*fae548d3Szrj    For a 0x75 byte record you should set --srec-len=0x70.  */
132*fae548d3Szrj unsigned int _bfd_srec_len = DEFAULT_CHUNK;
133*fae548d3Szrj 
134*fae548d3Szrj /* The type of srec output (free or forced to S3).
135*fae548d3Szrj    This variable can be modified by objcopy's --srec-forceS3
136*fae548d3Szrj    parameter.  */
137*fae548d3Szrj bfd_boolean _bfd_srec_forceS3 = FALSE;
138*fae548d3Szrj 
139*fae548d3Szrj /* When writing an S-record file, the S-records can not be output as
140*fae548d3Szrj    they are seen.  This structure is used to hold them in memory.  */
141*fae548d3Szrj 
142*fae548d3Szrj struct srec_data_list_struct
143*fae548d3Szrj {
144*fae548d3Szrj   struct srec_data_list_struct *next;
145*fae548d3Szrj   bfd_byte *data;
146*fae548d3Szrj   bfd_vma where;
147*fae548d3Szrj   bfd_size_type size;
148*fae548d3Szrj };
149*fae548d3Szrj 
150*fae548d3Szrj typedef struct srec_data_list_struct srec_data_list_type;
151*fae548d3Szrj 
152*fae548d3Szrj /* When scanning the S-record file, a linked list of srec_symbol
153*fae548d3Szrj    structures is built to represent the symbol table (if there is
154*fae548d3Szrj    one).  */
155*fae548d3Szrj 
156*fae548d3Szrj struct srec_symbol
157*fae548d3Szrj {
158*fae548d3Szrj   struct srec_symbol *next;
159*fae548d3Szrj   const char *name;
160*fae548d3Szrj   bfd_vma val;
161*fae548d3Szrj };
162*fae548d3Szrj 
163*fae548d3Szrj /* The S-record tdata information.  */
164*fae548d3Szrj 
165*fae548d3Szrj typedef struct srec_data_struct
166*fae548d3Szrj   {
167*fae548d3Szrj     srec_data_list_type *head;
168*fae548d3Szrj     srec_data_list_type *tail;
169*fae548d3Szrj     unsigned int type;
170*fae548d3Szrj     struct srec_symbol *symbols;
171*fae548d3Szrj     struct srec_symbol *symtail;
172*fae548d3Szrj     asymbol *csymbols;
173*fae548d3Szrj   }
174*fae548d3Szrj tdata_type;
175*fae548d3Szrj 
176*fae548d3Szrj /* Initialize by filling in the hex conversion array.  */
177*fae548d3Szrj 
178*fae548d3Szrj static void
srec_init(void)179*fae548d3Szrj srec_init (void)
180*fae548d3Szrj {
181*fae548d3Szrj   static bfd_boolean inited = FALSE;
182*fae548d3Szrj 
183*fae548d3Szrj   if (! inited)
184*fae548d3Szrj     {
185*fae548d3Szrj       inited = TRUE;
186*fae548d3Szrj       hex_init ();
187*fae548d3Szrj     }
188*fae548d3Szrj }
189*fae548d3Szrj 
190*fae548d3Szrj /* Set up the S-record tdata information.  */
191*fae548d3Szrj 
192*fae548d3Szrj static bfd_boolean
srec_mkobject(bfd * abfd)193*fae548d3Szrj srec_mkobject (bfd *abfd)
194*fae548d3Szrj {
195*fae548d3Szrj   tdata_type *tdata;
196*fae548d3Szrj 
197*fae548d3Szrj   srec_init ();
198*fae548d3Szrj 
199*fae548d3Szrj   tdata = (tdata_type *) bfd_alloc (abfd, sizeof (tdata_type));
200*fae548d3Szrj   if (tdata == NULL)
201*fae548d3Szrj     return FALSE;
202*fae548d3Szrj 
203*fae548d3Szrj   abfd->tdata.srec_data = tdata;
204*fae548d3Szrj   tdata->type = 1;
205*fae548d3Szrj   tdata->head = NULL;
206*fae548d3Szrj   tdata->tail = NULL;
207*fae548d3Szrj   tdata->symbols = NULL;
208*fae548d3Szrj   tdata->symtail = NULL;
209*fae548d3Szrj   tdata->csymbols = NULL;
210*fae548d3Szrj 
211*fae548d3Szrj   return TRUE;
212*fae548d3Szrj }
213*fae548d3Szrj 
214*fae548d3Szrj /* Read a byte from an S record file.  Set *ERRORPTR if an error
215*fae548d3Szrj    occurred.  Return EOF on error or end of file.  */
216*fae548d3Szrj 
217*fae548d3Szrj static int
srec_get_byte(bfd * abfd,bfd_boolean * errorptr)218*fae548d3Szrj srec_get_byte (bfd *abfd, bfd_boolean *errorptr)
219*fae548d3Szrj {
220*fae548d3Szrj   bfd_byte c;
221*fae548d3Szrj 
222*fae548d3Szrj   if (bfd_bread (&c, (bfd_size_type) 1, abfd) != 1)
223*fae548d3Szrj     {
224*fae548d3Szrj       if (bfd_get_error () != bfd_error_file_truncated)
225*fae548d3Szrj 	*errorptr = TRUE;
226*fae548d3Szrj       return EOF;
227*fae548d3Szrj     }
228*fae548d3Szrj 
229*fae548d3Szrj   return (int) (c & 0xff);
230*fae548d3Szrj }
231*fae548d3Szrj 
232*fae548d3Szrj /* Report a problem in an S record file.  FIXME: This probably should
233*fae548d3Szrj    not call fprintf, but we really do need some mechanism for printing
234*fae548d3Szrj    error messages.  */
235*fae548d3Szrj 
236*fae548d3Szrj static void
srec_bad_byte(bfd * abfd,unsigned int lineno,int c,bfd_boolean error)237*fae548d3Szrj srec_bad_byte (bfd *abfd,
238*fae548d3Szrj 	       unsigned int lineno,
239*fae548d3Szrj 	       int c,
240*fae548d3Szrj 	       bfd_boolean error)
241*fae548d3Szrj {
242*fae548d3Szrj   if (c == EOF)
243*fae548d3Szrj     {
244*fae548d3Szrj       if (! error)
245*fae548d3Szrj 	bfd_set_error (bfd_error_file_truncated);
246*fae548d3Szrj     }
247*fae548d3Szrj   else
248*fae548d3Szrj     {
249*fae548d3Szrj       char buf[40];
250*fae548d3Szrj 
251*fae548d3Szrj       if (! ISPRINT (c))
252*fae548d3Szrj 	sprintf (buf, "\\%03o", (unsigned int) c & 0xff);
253*fae548d3Szrj       else
254*fae548d3Szrj 	{
255*fae548d3Szrj 	  buf[0] = c;
256*fae548d3Szrj 	  buf[1] = '\0';
257*fae548d3Szrj 	}
258*fae548d3Szrj       _bfd_error_handler
259*fae548d3Szrj 	/* xgettext:c-format */
260*fae548d3Szrj 	(_("%pB:%d: unexpected character `%s' in S-record file"),
261*fae548d3Szrj 	 abfd, lineno, buf);
262*fae548d3Szrj       bfd_set_error (bfd_error_bad_value);
263*fae548d3Szrj     }
264*fae548d3Szrj }
265*fae548d3Szrj 
266*fae548d3Szrj /* Add a new symbol found in an S-record file.  */
267*fae548d3Szrj 
268*fae548d3Szrj static bfd_boolean
srec_new_symbol(bfd * abfd,const char * name,bfd_vma val)269*fae548d3Szrj srec_new_symbol (bfd *abfd, const char *name, bfd_vma val)
270*fae548d3Szrj {
271*fae548d3Szrj   struct srec_symbol *n;
272*fae548d3Szrj 
273*fae548d3Szrj   n = (struct srec_symbol *) bfd_alloc (abfd, sizeof (* n));
274*fae548d3Szrj   if (n == NULL)
275*fae548d3Szrj     return FALSE;
276*fae548d3Szrj 
277*fae548d3Szrj   n->name = name;
278*fae548d3Szrj   n->val = val;
279*fae548d3Szrj 
280*fae548d3Szrj   if (abfd->tdata.srec_data->symbols == NULL)
281*fae548d3Szrj     abfd->tdata.srec_data->symbols = n;
282*fae548d3Szrj   else
283*fae548d3Szrj     abfd->tdata.srec_data->symtail->next = n;
284*fae548d3Szrj   abfd->tdata.srec_data->symtail = n;
285*fae548d3Szrj   n->next = NULL;
286*fae548d3Szrj 
287*fae548d3Szrj   ++abfd->symcount;
288*fae548d3Szrj 
289*fae548d3Szrj   return TRUE;
290*fae548d3Szrj }
291*fae548d3Szrj 
292*fae548d3Szrj /* Read the S record file and turn it into sections.  We create a new
293*fae548d3Szrj    section for each contiguous set of bytes.  */
294*fae548d3Szrj 
295*fae548d3Szrj static bfd_boolean
srec_scan(bfd * abfd)296*fae548d3Szrj srec_scan (bfd *abfd)
297*fae548d3Szrj {
298*fae548d3Szrj   int c;
299*fae548d3Szrj   unsigned int lineno = 1;
300*fae548d3Szrj   bfd_boolean error = FALSE;
301*fae548d3Szrj   bfd_byte *buf = NULL;
302*fae548d3Szrj   size_t bufsize = 0;
303*fae548d3Szrj   asection *sec = NULL;
304*fae548d3Szrj   char *symbuf = NULL;
305*fae548d3Szrj 
306*fae548d3Szrj   if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
307*fae548d3Szrj     goto error_return;
308*fae548d3Szrj 
309*fae548d3Szrj   while ((c = srec_get_byte (abfd, &error)) != EOF)
310*fae548d3Szrj     {
311*fae548d3Szrj       /* We only build sections from contiguous S-records, so if this
312*fae548d3Szrj 	 is not an S-record, then stop building a section.  */
313*fae548d3Szrj       if (c != 'S' && c != '\r' && c != '\n')
314*fae548d3Szrj 	sec = NULL;
315*fae548d3Szrj 
316*fae548d3Szrj       switch (c)
317*fae548d3Szrj 	{
318*fae548d3Szrj 	default:
319*fae548d3Szrj 	  srec_bad_byte (abfd, lineno, c, error);
320*fae548d3Szrj 	  goto error_return;
321*fae548d3Szrj 
322*fae548d3Szrj 	case '\n':
323*fae548d3Szrj 	  ++lineno;
324*fae548d3Szrj 	  break;
325*fae548d3Szrj 
326*fae548d3Szrj 	case '\r':
327*fae548d3Szrj 	  break;
328*fae548d3Szrj 
329*fae548d3Szrj 	case '$':
330*fae548d3Szrj 	  /* Starting a module name, which we ignore.  */
331*fae548d3Szrj 	  while ((c = srec_get_byte (abfd, &error)) != '\n'
332*fae548d3Szrj 		 && c != EOF)
333*fae548d3Szrj 	    ;
334*fae548d3Szrj 	  if (c == EOF)
335*fae548d3Szrj 	    {
336*fae548d3Szrj 	      srec_bad_byte (abfd, lineno, c, error);
337*fae548d3Szrj 	      goto error_return;
338*fae548d3Szrj 	    }
339*fae548d3Szrj 
340*fae548d3Szrj 	  ++lineno;
341*fae548d3Szrj 	  break;
342*fae548d3Szrj 
343*fae548d3Szrj 	case ' ':
344*fae548d3Szrj 	  do
345*fae548d3Szrj 	    {
346*fae548d3Szrj 	      bfd_size_type alc;
347*fae548d3Szrj 	      char *p, *symname;
348*fae548d3Szrj 	      bfd_vma symval;
349*fae548d3Szrj 
350*fae548d3Szrj 	      /* Starting a symbol definition.  */
351*fae548d3Szrj 	      while ((c = srec_get_byte (abfd, &error)) != EOF
352*fae548d3Szrj 		     && (c == ' ' || c == '\t'))
353*fae548d3Szrj 		;
354*fae548d3Szrj 
355*fae548d3Szrj 	      if (c == '\n' || c == '\r')
356*fae548d3Szrj 		break;
357*fae548d3Szrj 
358*fae548d3Szrj 	      if (c == EOF)
359*fae548d3Szrj 		{
360*fae548d3Szrj 		  srec_bad_byte (abfd, lineno, c, error);
361*fae548d3Szrj 		  goto error_return;
362*fae548d3Szrj 		}
363*fae548d3Szrj 
364*fae548d3Szrj 	      alc = 10;
365*fae548d3Szrj 	      symbuf = (char *) bfd_malloc (alc + 1);
366*fae548d3Szrj 	      if (symbuf == NULL)
367*fae548d3Szrj 		goto error_return;
368*fae548d3Szrj 
369*fae548d3Szrj 	      p = symbuf;
370*fae548d3Szrj 
371*fae548d3Szrj 	      *p++ = c;
372*fae548d3Szrj 	      while ((c = srec_get_byte (abfd, &error)) != EOF
373*fae548d3Szrj 		     && ! ISSPACE (c))
374*fae548d3Szrj 		{
375*fae548d3Szrj 		  if ((bfd_size_type) (p - symbuf) >= alc)
376*fae548d3Szrj 		    {
377*fae548d3Szrj 		      char *n;
378*fae548d3Szrj 
379*fae548d3Szrj 		      alc *= 2;
380*fae548d3Szrj 		      n = (char *) bfd_realloc (symbuf, alc + 1);
381*fae548d3Szrj 		      if (n == NULL)
382*fae548d3Szrj 			goto error_return;
383*fae548d3Szrj 		      p = n + (p - symbuf);
384*fae548d3Szrj 		      symbuf = n;
385*fae548d3Szrj 		    }
386*fae548d3Szrj 
387*fae548d3Szrj 		  *p++ = c;
388*fae548d3Szrj 		}
389*fae548d3Szrj 
390*fae548d3Szrj 	      if (c == EOF)
391*fae548d3Szrj 		{
392*fae548d3Szrj 		  srec_bad_byte (abfd, lineno, c, error);
393*fae548d3Szrj 		  goto error_return;
394*fae548d3Szrj 		}
395*fae548d3Szrj 
396*fae548d3Szrj 	      *p++ = '\0';
397*fae548d3Szrj 	      symname = (char *) bfd_alloc (abfd, (bfd_size_type) (p - symbuf));
398*fae548d3Szrj 	      if (symname == NULL)
399*fae548d3Szrj 		goto error_return;
400*fae548d3Szrj 	      strcpy (symname, symbuf);
401*fae548d3Szrj 	      free (symbuf);
402*fae548d3Szrj 	      symbuf = NULL;
403*fae548d3Szrj 
404*fae548d3Szrj 	      while ((c = srec_get_byte (abfd, &error)) != EOF
405*fae548d3Szrj 		     && (c == ' ' || c == '\t'))
406*fae548d3Szrj 		;
407*fae548d3Szrj 	      if (c == EOF)
408*fae548d3Szrj 		{
409*fae548d3Szrj 		  srec_bad_byte (abfd, lineno, c, error);
410*fae548d3Szrj 		  goto error_return;
411*fae548d3Szrj 		}
412*fae548d3Szrj 
413*fae548d3Szrj 	      /* Skip a dollar sign before the hex value.  */
414*fae548d3Szrj 	      if (c == '$')
415*fae548d3Szrj 		{
416*fae548d3Szrj 		  c = srec_get_byte (abfd, &error);
417*fae548d3Szrj 		  if (c == EOF)
418*fae548d3Szrj 		    {
419*fae548d3Szrj 		      srec_bad_byte (abfd, lineno, c, error);
420*fae548d3Szrj 		      goto error_return;
421*fae548d3Szrj 		    }
422*fae548d3Szrj 		}
423*fae548d3Szrj 
424*fae548d3Szrj 	      symval = 0;
425*fae548d3Szrj 	      while (ISHEX (c))
426*fae548d3Szrj 		{
427*fae548d3Szrj 		  symval <<= 4;
428*fae548d3Szrj 		  symval += NIBBLE (c);
429*fae548d3Szrj 		  c = srec_get_byte (abfd, &error);
430*fae548d3Szrj 		  if (c == EOF)
431*fae548d3Szrj 		    {
432*fae548d3Szrj 		      srec_bad_byte (abfd, lineno, c, error);
433*fae548d3Szrj 		      goto error_return;
434*fae548d3Szrj 		    }
435*fae548d3Szrj 		}
436*fae548d3Szrj 
437*fae548d3Szrj 	      if (! srec_new_symbol (abfd, symname, symval))
438*fae548d3Szrj 		goto error_return;
439*fae548d3Szrj 	    }
440*fae548d3Szrj 	  while (c == ' ' || c == '\t')
441*fae548d3Szrj 	    ;
442*fae548d3Szrj 
443*fae548d3Szrj 	  if (c == '\n')
444*fae548d3Szrj 	    ++lineno;
445*fae548d3Szrj 	  else if (c != '\r')
446*fae548d3Szrj 	    {
447*fae548d3Szrj 	      srec_bad_byte (abfd, lineno, c, error);
448*fae548d3Szrj 	      goto error_return;
449*fae548d3Szrj 	    }
450*fae548d3Szrj 
451*fae548d3Szrj 	  break;
452*fae548d3Szrj 
453*fae548d3Szrj 	case 'S':
454*fae548d3Szrj 	  {
455*fae548d3Szrj 	    file_ptr pos;
456*fae548d3Szrj 	    unsigned char hdr[3];
457*fae548d3Szrj 	    unsigned int bytes, min_bytes;
458*fae548d3Szrj 	    bfd_vma address;
459*fae548d3Szrj 	    bfd_byte *data;
460*fae548d3Szrj 	    unsigned char check_sum;
461*fae548d3Szrj 
462*fae548d3Szrj 	    /* Starting an S-record.  */
463*fae548d3Szrj 
464*fae548d3Szrj 	    pos = bfd_tell (abfd) - 1;
465*fae548d3Szrj 
466*fae548d3Szrj 	    if (bfd_bread (hdr, (bfd_size_type) 3, abfd) != 3)
467*fae548d3Szrj 	      goto error_return;
468*fae548d3Szrj 
469*fae548d3Szrj 	    if (! ISHEX (hdr[1]) || ! ISHEX (hdr[2]))
470*fae548d3Szrj 	      {
471*fae548d3Szrj 		if (! ISHEX (hdr[1]))
472*fae548d3Szrj 		  c = hdr[1];
473*fae548d3Szrj 		else
474*fae548d3Szrj 		  c = hdr[2];
475*fae548d3Szrj 		srec_bad_byte (abfd, lineno, c, error);
476*fae548d3Szrj 		goto error_return;
477*fae548d3Szrj 	      }
478*fae548d3Szrj 
479*fae548d3Szrj 	    check_sum = bytes = HEX (hdr + 1);
480*fae548d3Szrj 	    min_bytes = 3;
481*fae548d3Szrj 	    if (hdr[0] == '2' || hdr[0] == '8')
482*fae548d3Szrj 	      min_bytes = 4;
483*fae548d3Szrj 	    else if (hdr[0] == '3' || hdr[0] == '7')
484*fae548d3Szrj 	      min_bytes = 5;
485*fae548d3Szrj 	    if (bytes < min_bytes)
486*fae548d3Szrj 	      {
487*fae548d3Szrj 		/* xgettext:c-format */
488*fae548d3Szrj 		_bfd_error_handler (_("%pB:%d: byte count %d too small"),
489*fae548d3Szrj 				    abfd, lineno, bytes);
490*fae548d3Szrj 		bfd_set_error (bfd_error_bad_value);
491*fae548d3Szrj 		goto error_return;
492*fae548d3Szrj 	      }
493*fae548d3Szrj 
494*fae548d3Szrj 	    if (bytes * 2 > bufsize)
495*fae548d3Szrj 	      {
496*fae548d3Szrj 		if (buf != NULL)
497*fae548d3Szrj 		  free (buf);
498*fae548d3Szrj 		buf = (bfd_byte *) bfd_malloc ((bfd_size_type) bytes * 2);
499*fae548d3Szrj 		if (buf == NULL)
500*fae548d3Szrj 		  goto error_return;
501*fae548d3Szrj 		bufsize = bytes * 2;
502*fae548d3Szrj 	      }
503*fae548d3Szrj 
504*fae548d3Szrj 	    if (bfd_bread (buf, (bfd_size_type) bytes * 2, abfd) != bytes * 2)
505*fae548d3Szrj 	      goto error_return;
506*fae548d3Szrj 
507*fae548d3Szrj 	    /* Ignore the checksum byte.  */
508*fae548d3Szrj 	    --bytes;
509*fae548d3Szrj 
510*fae548d3Szrj 	    address = 0;
511*fae548d3Szrj 	    data = buf;
512*fae548d3Szrj 	    switch (hdr[0])
513*fae548d3Szrj 	      {
514*fae548d3Szrj 	      case '0':
515*fae548d3Szrj 	      case '5':
516*fae548d3Szrj 		/* Prologue--ignore the file name, but stop building a
517*fae548d3Szrj 		   section at this point.  */
518*fae548d3Szrj 		sec = NULL;
519*fae548d3Szrj 		break;
520*fae548d3Szrj 
521*fae548d3Szrj 	      case '3':
522*fae548d3Szrj 		check_sum += HEX (data);
523*fae548d3Szrj 		address = HEX (data);
524*fae548d3Szrj 		data += 2;
525*fae548d3Szrj 		--bytes;
526*fae548d3Szrj 		/* Fall through.  */
527*fae548d3Szrj 	      case '2':
528*fae548d3Szrj 		check_sum += HEX (data);
529*fae548d3Szrj 		address = (address << 8) | HEX (data);
530*fae548d3Szrj 		data += 2;
531*fae548d3Szrj 		--bytes;
532*fae548d3Szrj 		/* Fall through.  */
533*fae548d3Szrj 	      case '1':
534*fae548d3Szrj 		check_sum += HEX (data);
535*fae548d3Szrj 		address = (address << 8) | HEX (data);
536*fae548d3Szrj 		data += 2;
537*fae548d3Szrj 		check_sum += HEX (data);
538*fae548d3Szrj 		address = (address << 8) | HEX (data);
539*fae548d3Szrj 		data += 2;
540*fae548d3Szrj 		bytes -= 2;
541*fae548d3Szrj 
542*fae548d3Szrj 		if (sec != NULL
543*fae548d3Szrj 		    && sec->vma + sec->size == address)
544*fae548d3Szrj 		  {
545*fae548d3Szrj 		    /* This data goes at the end of the section we are
546*fae548d3Szrj 		       currently building.  */
547*fae548d3Szrj 		    sec->size += bytes;
548*fae548d3Szrj 		  }
549*fae548d3Szrj 		else
550*fae548d3Szrj 		  {
551*fae548d3Szrj 		    char secbuf[20];
552*fae548d3Szrj 		    char *secname;
553*fae548d3Szrj 		    bfd_size_type amt;
554*fae548d3Szrj 		    flagword flags;
555*fae548d3Szrj 
556*fae548d3Szrj 		    sprintf (secbuf, ".sec%d", bfd_count_sections (abfd) + 1);
557*fae548d3Szrj 		    amt = strlen (secbuf) + 1;
558*fae548d3Szrj 		    secname = (char *) bfd_alloc (abfd, amt);
559*fae548d3Szrj 		    strcpy (secname, secbuf);
560*fae548d3Szrj 		    flags = SEC_HAS_CONTENTS | SEC_LOAD | SEC_ALLOC;
561*fae548d3Szrj 		    sec = bfd_make_section_with_flags (abfd, secname, flags);
562*fae548d3Szrj 		    if (sec == NULL)
563*fae548d3Szrj 		      goto error_return;
564*fae548d3Szrj 		    sec->vma = address;
565*fae548d3Szrj 		    sec->lma = address;
566*fae548d3Szrj 		    sec->size = bytes;
567*fae548d3Szrj 		    sec->filepos = pos;
568*fae548d3Szrj 		  }
569*fae548d3Szrj 
570*fae548d3Szrj 		while (bytes > 0)
571*fae548d3Szrj 		  {
572*fae548d3Szrj 		    check_sum += HEX (data);
573*fae548d3Szrj 		    data += 2;
574*fae548d3Szrj 		    bytes--;
575*fae548d3Szrj 		  }
576*fae548d3Szrj 		check_sum = 255 - (check_sum & 0xff);
577*fae548d3Szrj 		if (check_sum != HEX (data))
578*fae548d3Szrj 		  {
579*fae548d3Szrj 		    _bfd_error_handler
580*fae548d3Szrj 		      /* xgettext:c-format */
581*fae548d3Szrj 		      (_("%pB:%d: bad checksum in S-record file"),
582*fae548d3Szrj 		       abfd, lineno);
583*fae548d3Szrj 		    bfd_set_error (bfd_error_bad_value);
584*fae548d3Szrj 		    goto error_return;
585*fae548d3Szrj 		  }
586*fae548d3Szrj 
587*fae548d3Szrj 		break;
588*fae548d3Szrj 
589*fae548d3Szrj 	      case '7':
590*fae548d3Szrj 		check_sum += HEX (data);
591*fae548d3Szrj 		address = HEX (data);
592*fae548d3Szrj 		data += 2;
593*fae548d3Szrj 		/* Fall through.  */
594*fae548d3Szrj 	      case '8':
595*fae548d3Szrj 		check_sum += HEX (data);
596*fae548d3Szrj 		address = (address << 8) | HEX (data);
597*fae548d3Szrj 		data += 2;
598*fae548d3Szrj 		/* Fall through.  */
599*fae548d3Szrj 	      case '9':
600*fae548d3Szrj 		check_sum += HEX (data);
601*fae548d3Szrj 		address = (address << 8) | HEX (data);
602*fae548d3Szrj 		data += 2;
603*fae548d3Szrj 		check_sum += HEX (data);
604*fae548d3Szrj 		address = (address << 8) | HEX (data);
605*fae548d3Szrj 		data += 2;
606*fae548d3Szrj 
607*fae548d3Szrj 		/* This is a termination record.  */
608*fae548d3Szrj 		abfd->start_address = address;
609*fae548d3Szrj 
610*fae548d3Szrj 		check_sum = 255 - (check_sum & 0xff);
611*fae548d3Szrj 		if (check_sum != HEX (data))
612*fae548d3Szrj 		  {
613*fae548d3Szrj 		    _bfd_error_handler
614*fae548d3Szrj 		      /* xgettext:c-format */
615*fae548d3Szrj 		      (_("%pB:%d: bad checksum in S-record file"),
616*fae548d3Szrj 		       abfd, lineno);
617*fae548d3Szrj 		    bfd_set_error (bfd_error_bad_value);
618*fae548d3Szrj 		    goto error_return;
619*fae548d3Szrj 		  }
620*fae548d3Szrj 
621*fae548d3Szrj 		if (buf != NULL)
622*fae548d3Szrj 		  free (buf);
623*fae548d3Szrj 
624*fae548d3Szrj 		return TRUE;
625*fae548d3Szrj 	      }
626*fae548d3Szrj 	  }
627*fae548d3Szrj 	  break;
628*fae548d3Szrj 	}
629*fae548d3Szrj     }
630*fae548d3Szrj 
631*fae548d3Szrj   if (error)
632*fae548d3Szrj     goto error_return;
633*fae548d3Szrj 
634*fae548d3Szrj   if (buf != NULL)
635*fae548d3Szrj     free (buf);
636*fae548d3Szrj 
637*fae548d3Szrj   return TRUE;
638*fae548d3Szrj 
639*fae548d3Szrj  error_return:
640*fae548d3Szrj   if (symbuf != NULL)
641*fae548d3Szrj     free (symbuf);
642*fae548d3Szrj   if (buf != NULL)
643*fae548d3Szrj     free (buf);
644*fae548d3Szrj   return FALSE;
645*fae548d3Szrj }
646*fae548d3Szrj 
647*fae548d3Szrj /* Check whether an existing file is an S-record file.  */
648*fae548d3Szrj 
649*fae548d3Szrj static const bfd_target *
srec_object_p(bfd * abfd)650*fae548d3Szrj srec_object_p (bfd *abfd)
651*fae548d3Szrj {
652*fae548d3Szrj   void * tdata_save;
653*fae548d3Szrj   bfd_byte b[4];
654*fae548d3Szrj 
655*fae548d3Szrj   srec_init ();
656*fae548d3Szrj 
657*fae548d3Szrj   if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0
658*fae548d3Szrj       || bfd_bread (b, (bfd_size_type) 4, abfd) != 4)
659*fae548d3Szrj     return NULL;
660*fae548d3Szrj 
661*fae548d3Szrj   if (b[0] != 'S' || !ISHEX (b[1]) || !ISHEX (b[2]) || !ISHEX (b[3]))
662*fae548d3Szrj     {
663*fae548d3Szrj       bfd_set_error (bfd_error_wrong_format);
664*fae548d3Szrj       return NULL;
665*fae548d3Szrj     }
666*fae548d3Szrj 
667*fae548d3Szrj   tdata_save = abfd->tdata.any;
668*fae548d3Szrj   if (! srec_mkobject (abfd) || ! srec_scan (abfd))
669*fae548d3Szrj     {
670*fae548d3Szrj       if (abfd->tdata.any != tdata_save && abfd->tdata.any != NULL)
671*fae548d3Szrj 	bfd_release (abfd, abfd->tdata.any);
672*fae548d3Szrj       abfd->tdata.any = tdata_save;
673*fae548d3Szrj       return NULL;
674*fae548d3Szrj     }
675*fae548d3Szrj 
676*fae548d3Szrj   if (abfd->symcount > 0)
677*fae548d3Szrj     abfd->flags |= HAS_SYMS;
678*fae548d3Szrj 
679*fae548d3Szrj   return abfd->xvec;
680*fae548d3Szrj }
681*fae548d3Szrj 
682*fae548d3Szrj /* Check whether an existing file is an S-record file with symbols.  */
683*fae548d3Szrj 
684*fae548d3Szrj static const bfd_target *
symbolsrec_object_p(bfd * abfd)685*fae548d3Szrj symbolsrec_object_p (bfd *abfd)
686*fae548d3Szrj {
687*fae548d3Szrj   void * tdata_save;
688*fae548d3Szrj   char b[2];
689*fae548d3Szrj 
690*fae548d3Szrj   srec_init ();
691*fae548d3Szrj 
692*fae548d3Szrj   if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0
693*fae548d3Szrj       || bfd_bread (b, (bfd_size_type) 2, abfd) != 2)
694*fae548d3Szrj     return NULL;
695*fae548d3Szrj 
696*fae548d3Szrj   if (b[0] != '$' || b[1] != '$')
697*fae548d3Szrj     {
698*fae548d3Szrj       bfd_set_error (bfd_error_wrong_format);
699*fae548d3Szrj       return NULL;
700*fae548d3Szrj     }
701*fae548d3Szrj 
702*fae548d3Szrj   tdata_save = abfd->tdata.any;
703*fae548d3Szrj   if (! srec_mkobject (abfd) || ! srec_scan (abfd))
704*fae548d3Szrj     {
705*fae548d3Szrj       if (abfd->tdata.any != tdata_save && abfd->tdata.any != NULL)
706*fae548d3Szrj 	bfd_release (abfd, abfd->tdata.any);
707*fae548d3Szrj       abfd->tdata.any = tdata_save;
708*fae548d3Szrj       return NULL;
709*fae548d3Szrj     }
710*fae548d3Szrj 
711*fae548d3Szrj   if (abfd->symcount > 0)
712*fae548d3Szrj     abfd->flags |= HAS_SYMS;
713*fae548d3Szrj 
714*fae548d3Szrj   return abfd->xvec;
715*fae548d3Szrj }
716*fae548d3Szrj 
717*fae548d3Szrj /* Read in the contents of a section in an S-record file.  */
718*fae548d3Szrj 
719*fae548d3Szrj static bfd_boolean
srec_read_section(bfd * abfd,asection * section,bfd_byte * contents)720*fae548d3Szrj srec_read_section (bfd *abfd, asection *section, bfd_byte *contents)
721*fae548d3Szrj {
722*fae548d3Szrj   int c;
723*fae548d3Szrj   bfd_size_type sofar = 0;
724*fae548d3Szrj   bfd_boolean error = FALSE;
725*fae548d3Szrj   bfd_byte *buf = NULL;
726*fae548d3Szrj   size_t bufsize = 0;
727*fae548d3Szrj 
728*fae548d3Szrj   if (bfd_seek (abfd, section->filepos, SEEK_SET) != 0)
729*fae548d3Szrj     goto error_return;
730*fae548d3Szrj 
731*fae548d3Szrj   while ((c = srec_get_byte (abfd, &error)) != EOF)
732*fae548d3Szrj     {
733*fae548d3Szrj       bfd_byte hdr[3];
734*fae548d3Szrj       unsigned int bytes;
735*fae548d3Szrj       bfd_vma address;
736*fae548d3Szrj       bfd_byte *data;
737*fae548d3Szrj 
738*fae548d3Szrj       if (c == '\r' || c == '\n')
739*fae548d3Szrj 	continue;
740*fae548d3Szrj 
741*fae548d3Szrj       /* This is called after srec_scan has already been called, so we
742*fae548d3Szrj 	 ought to know the exact format.  */
743*fae548d3Szrj       BFD_ASSERT (c == 'S');
744*fae548d3Szrj 
745*fae548d3Szrj       if (bfd_bread (hdr, (bfd_size_type) 3, abfd) != 3)
746*fae548d3Szrj 	goto error_return;
747*fae548d3Szrj 
748*fae548d3Szrj       BFD_ASSERT (ISHEX (hdr[1]) && ISHEX (hdr[2]));
749*fae548d3Szrj 
750*fae548d3Szrj       bytes = HEX (hdr + 1);
751*fae548d3Szrj 
752*fae548d3Szrj       if (bytes * 2 > bufsize)
753*fae548d3Szrj 	{
754*fae548d3Szrj 	  if (buf != NULL)
755*fae548d3Szrj 	    free (buf);
756*fae548d3Szrj 	  buf = (bfd_byte *) bfd_malloc ((bfd_size_type) bytes * 2);
757*fae548d3Szrj 	  if (buf == NULL)
758*fae548d3Szrj 	    goto error_return;
759*fae548d3Szrj 	  bufsize = bytes * 2;
760*fae548d3Szrj 	}
761*fae548d3Szrj 
762*fae548d3Szrj       if (bfd_bread (buf, (bfd_size_type) bytes * 2, abfd) != bytes * 2)
763*fae548d3Szrj 	goto error_return;
764*fae548d3Szrj 
765*fae548d3Szrj       address = 0;
766*fae548d3Szrj       data = buf;
767*fae548d3Szrj       switch (hdr[0])
768*fae548d3Szrj 	{
769*fae548d3Szrj 	default:
770*fae548d3Szrj 	  BFD_ASSERT (sofar == section->size);
771*fae548d3Szrj 	  if (buf != NULL)
772*fae548d3Szrj 	    free (buf);
773*fae548d3Szrj 	  return TRUE;
774*fae548d3Szrj 
775*fae548d3Szrj 	case '3':
776*fae548d3Szrj 	  address = HEX (data);
777*fae548d3Szrj 	  data += 2;
778*fae548d3Szrj 	  --bytes;
779*fae548d3Szrj 	  /* Fall through.  */
780*fae548d3Szrj 	case '2':
781*fae548d3Szrj 	  address = (address << 8) | HEX (data);
782*fae548d3Szrj 	  data += 2;
783*fae548d3Szrj 	  --bytes;
784*fae548d3Szrj 	  /* Fall through.  */
785*fae548d3Szrj 	case '1':
786*fae548d3Szrj 	  address = (address << 8) | HEX (data);
787*fae548d3Szrj 	  data += 2;
788*fae548d3Szrj 	  address = (address << 8) | HEX (data);
789*fae548d3Szrj 	  data += 2;
790*fae548d3Szrj 	  bytes -= 2;
791*fae548d3Szrj 
792*fae548d3Szrj 	  if (address != section->vma + sofar)
793*fae548d3Szrj 	    {
794*fae548d3Szrj 	      /* We've come to the end of this section.  */
795*fae548d3Szrj 	      BFD_ASSERT (sofar == section->size);
796*fae548d3Szrj 	      if (buf != NULL)
797*fae548d3Szrj 		free (buf);
798*fae548d3Szrj 	      return TRUE;
799*fae548d3Szrj 	    }
800*fae548d3Szrj 
801*fae548d3Szrj 	  /* Don't consider checksum.  */
802*fae548d3Szrj 	  --bytes;
803*fae548d3Szrj 
804*fae548d3Szrj 	  while (bytes-- != 0)
805*fae548d3Szrj 	    {
806*fae548d3Szrj 	      contents[sofar] = HEX (data);
807*fae548d3Szrj 	      data += 2;
808*fae548d3Szrj 	      ++sofar;
809*fae548d3Szrj 	    }
810*fae548d3Szrj 
811*fae548d3Szrj 	  break;
812*fae548d3Szrj 	}
813*fae548d3Szrj     }
814*fae548d3Szrj 
815*fae548d3Szrj   if (error)
816*fae548d3Szrj     goto error_return;
817*fae548d3Szrj 
818*fae548d3Szrj   BFD_ASSERT (sofar == section->size);
819*fae548d3Szrj 
820*fae548d3Szrj   if (buf != NULL)
821*fae548d3Szrj     free (buf);
822*fae548d3Szrj 
823*fae548d3Szrj   return TRUE;
824*fae548d3Szrj 
825*fae548d3Szrj  error_return:
826*fae548d3Szrj   if (buf != NULL)
827*fae548d3Szrj     free (buf);
828*fae548d3Szrj   return FALSE;
829*fae548d3Szrj }
830*fae548d3Szrj 
831*fae548d3Szrj /* Get the contents of a section in an S-record file.  */
832*fae548d3Szrj 
833*fae548d3Szrj static bfd_boolean
srec_get_section_contents(bfd * abfd,asection * section,void * location,file_ptr offset,bfd_size_type count)834*fae548d3Szrj srec_get_section_contents (bfd *abfd,
835*fae548d3Szrj 			   asection *section,
836*fae548d3Szrj 			   void * location,
837*fae548d3Szrj 			   file_ptr offset,
838*fae548d3Szrj 			   bfd_size_type count)
839*fae548d3Szrj {
840*fae548d3Szrj   if (count == 0)
841*fae548d3Szrj     return TRUE;
842*fae548d3Szrj 
843*fae548d3Szrj   if (offset + count < count
844*fae548d3Szrj       || offset + count > section->size)
845*fae548d3Szrj     {
846*fae548d3Szrj       bfd_set_error (bfd_error_invalid_operation);
847*fae548d3Szrj       return FALSE;
848*fae548d3Szrj     }
849*fae548d3Szrj 
850*fae548d3Szrj   if (section->used_by_bfd == NULL)
851*fae548d3Szrj     {
852*fae548d3Szrj       section->used_by_bfd = bfd_alloc (abfd, section->size);
853*fae548d3Szrj       if (section->used_by_bfd == NULL)
854*fae548d3Szrj 	return FALSE;
855*fae548d3Szrj 
856*fae548d3Szrj       if (! srec_read_section (abfd, section,
857*fae548d3Szrj 			       (bfd_byte *) section->used_by_bfd))
858*fae548d3Szrj 	return FALSE;
859*fae548d3Szrj     }
860*fae548d3Szrj 
861*fae548d3Szrj   memcpy (location, (bfd_byte *) section->used_by_bfd + offset,
862*fae548d3Szrj 	  (size_t) count);
863*fae548d3Szrj 
864*fae548d3Szrj   return TRUE;
865*fae548d3Szrj }
866*fae548d3Szrj 
867*fae548d3Szrj /* Set the architecture.  We accept an unknown architecture here.  */
868*fae548d3Szrj 
869*fae548d3Szrj static bfd_boolean
srec_set_arch_mach(bfd * abfd,enum bfd_architecture arch,unsigned long mach)870*fae548d3Szrj srec_set_arch_mach (bfd *abfd, enum bfd_architecture arch, unsigned long mach)
871*fae548d3Szrj {
872*fae548d3Szrj   if (arch != bfd_arch_unknown)
873*fae548d3Szrj     return bfd_default_set_arch_mach (abfd, arch, mach);
874*fae548d3Szrj 
875*fae548d3Szrj   abfd->arch_info = & bfd_default_arch_struct;
876*fae548d3Szrj   return TRUE;
877*fae548d3Szrj }
878*fae548d3Szrj 
879*fae548d3Szrj /* We have to save up all the Srecords for a splurge before output.  */
880*fae548d3Szrj 
881*fae548d3Szrj static bfd_boolean
srec_set_section_contents(bfd * abfd,sec_ptr section,const void * location,file_ptr offset,bfd_size_type bytes_to_do)882*fae548d3Szrj srec_set_section_contents (bfd *abfd,
883*fae548d3Szrj 			   sec_ptr section,
884*fae548d3Szrj 			   const void * location,
885*fae548d3Szrj 			   file_ptr offset,
886*fae548d3Szrj 			   bfd_size_type bytes_to_do)
887*fae548d3Szrj {
888*fae548d3Szrj   int opb = bfd_octets_per_byte (abfd, NULL);
889*fae548d3Szrj   tdata_type *tdata = abfd->tdata.srec_data;
890*fae548d3Szrj   srec_data_list_type *entry;
891*fae548d3Szrj 
892*fae548d3Szrj   entry = (srec_data_list_type *) bfd_alloc (abfd, sizeof (* entry));
893*fae548d3Szrj   if (entry == NULL)
894*fae548d3Szrj     return FALSE;
895*fae548d3Szrj 
896*fae548d3Szrj   if (bytes_to_do
897*fae548d3Szrj       && (section->flags & SEC_ALLOC)
898*fae548d3Szrj       && (section->flags & SEC_LOAD))
899*fae548d3Szrj     {
900*fae548d3Szrj       bfd_byte *data;
901*fae548d3Szrj 
902*fae548d3Szrj       data = (bfd_byte *) bfd_alloc (abfd, bytes_to_do);
903*fae548d3Szrj       if (data == NULL)
904*fae548d3Szrj 	return FALSE;
905*fae548d3Szrj       memcpy ((void *) data, location, (size_t) bytes_to_do);
906*fae548d3Szrj 
907*fae548d3Szrj       /* If _bfd_srec_forceS3 is TRUE then always select S3 records,
908*fae548d3Szrj 	 regardless of the size of the addresses.  */
909*fae548d3Szrj       if (_bfd_srec_forceS3)
910*fae548d3Szrj 	tdata->type = 3;
911*fae548d3Szrj       else if ((section->lma + (offset + bytes_to_do) / opb - 1) <= 0xffff)
912*fae548d3Szrj 	;  /* The default, S1, is OK.  */
913*fae548d3Szrj       else if ((section->lma + (offset + bytes_to_do) / opb - 1) <= 0xffffff
914*fae548d3Szrj 	       && tdata->type <= 2)
915*fae548d3Szrj 	tdata->type = 2;
916*fae548d3Szrj       else
917*fae548d3Szrj 	tdata->type = 3;
918*fae548d3Szrj 
919*fae548d3Szrj       entry->data = data;
920*fae548d3Szrj       entry->where = section->lma + offset / opb;
921*fae548d3Szrj       entry->size = bytes_to_do;
922*fae548d3Szrj 
923*fae548d3Szrj       /* Sort the records by address.  Optimize for the common case of
924*fae548d3Szrj 	 adding a record to the end of the list.  */
925*fae548d3Szrj       if (tdata->tail != NULL
926*fae548d3Szrj 	  && entry->where >= tdata->tail->where)
927*fae548d3Szrj 	{
928*fae548d3Szrj 	  tdata->tail->next = entry;
929*fae548d3Szrj 	  entry->next = NULL;
930*fae548d3Szrj 	  tdata->tail = entry;
931*fae548d3Szrj 	}
932*fae548d3Szrj       else
933*fae548d3Szrj 	{
934*fae548d3Szrj 	  srec_data_list_type **look;
935*fae548d3Szrj 
936*fae548d3Szrj 	  for (look = &tdata->head;
937*fae548d3Szrj 	       *look != NULL && (*look)->where < entry->where;
938*fae548d3Szrj 	       look = &(*look)->next)
939*fae548d3Szrj 	    ;
940*fae548d3Szrj 	  entry->next = *look;
941*fae548d3Szrj 	  *look = entry;
942*fae548d3Szrj 	  if (entry->next == NULL)
943*fae548d3Szrj 	    tdata->tail = entry;
944*fae548d3Szrj 	}
945*fae548d3Szrj     }
946*fae548d3Szrj   return TRUE;
947*fae548d3Szrj }
948*fae548d3Szrj 
949*fae548d3Szrj /* Write a record of type, of the supplied number of bytes. The
950*fae548d3Szrj    supplied bytes and length don't have a checksum. That's worked out
951*fae548d3Szrj    here.  */
952*fae548d3Szrj 
953*fae548d3Szrj static bfd_boolean
srec_write_record(bfd * abfd,unsigned int type,bfd_vma address,const bfd_byte * data,const bfd_byte * end)954*fae548d3Szrj srec_write_record (bfd *abfd,
955*fae548d3Szrj 		   unsigned int type,
956*fae548d3Szrj 		   bfd_vma address,
957*fae548d3Szrj 		   const bfd_byte *data,
958*fae548d3Szrj 		   const bfd_byte *end)
959*fae548d3Szrj {
960*fae548d3Szrj   char buffer[2 * MAXCHUNK + 6];
961*fae548d3Szrj   unsigned int check_sum = 0;
962*fae548d3Szrj   const bfd_byte *src = data;
963*fae548d3Szrj   char *dst = buffer;
964*fae548d3Szrj   char *length;
965*fae548d3Szrj   bfd_size_type wrlen;
966*fae548d3Szrj 
967*fae548d3Szrj   *dst++ = 'S';
968*fae548d3Szrj   *dst++ = '0' + type;
969*fae548d3Szrj 
970*fae548d3Szrj   length = dst;
971*fae548d3Szrj   dst += 2;			/* Leave room for dst.  */
972*fae548d3Szrj 
973*fae548d3Szrj   switch (type)
974*fae548d3Szrj     {
975*fae548d3Szrj     case 3:
976*fae548d3Szrj     case 7:
977*fae548d3Szrj       TOHEX (dst, (address >> 24), check_sum);
978*fae548d3Szrj       dst += 2;
979*fae548d3Szrj       /* Fall through.  */
980*fae548d3Szrj     case 8:
981*fae548d3Szrj     case 2:
982*fae548d3Szrj       TOHEX (dst, (address >> 16), check_sum);
983*fae548d3Szrj       dst += 2;
984*fae548d3Szrj       /* Fall through.  */
985*fae548d3Szrj     case 9:
986*fae548d3Szrj     case 1:
987*fae548d3Szrj     case 0:
988*fae548d3Szrj       TOHEX (dst, (address >> 8), check_sum);
989*fae548d3Szrj       dst += 2;
990*fae548d3Szrj       TOHEX (dst, (address), check_sum);
991*fae548d3Szrj       dst += 2;
992*fae548d3Szrj       break;
993*fae548d3Szrj 
994*fae548d3Szrj     }
995*fae548d3Szrj   for (src = data; src < end; src++)
996*fae548d3Szrj     {
997*fae548d3Szrj       TOHEX (dst, *src, check_sum);
998*fae548d3Szrj       dst += 2;
999*fae548d3Szrj     }
1000*fae548d3Szrj 
1001*fae548d3Szrj   /* Fill in the length.  */
1002*fae548d3Szrj   TOHEX (length, (dst - length) / 2, check_sum);
1003*fae548d3Szrj   check_sum &= 0xff;
1004*fae548d3Szrj   check_sum = 255 - check_sum;
1005*fae548d3Szrj   TOHEX (dst, check_sum, check_sum);
1006*fae548d3Szrj   dst += 2;
1007*fae548d3Szrj 
1008*fae548d3Szrj   *dst++ = '\r';
1009*fae548d3Szrj   *dst++ = '\n';
1010*fae548d3Szrj   wrlen = dst - buffer;
1011*fae548d3Szrj 
1012*fae548d3Szrj   return bfd_bwrite ((void *) buffer, wrlen, abfd) == wrlen;
1013*fae548d3Szrj }
1014*fae548d3Szrj 
1015*fae548d3Szrj static bfd_boolean
srec_write_header(bfd * abfd)1016*fae548d3Szrj srec_write_header (bfd *abfd)
1017*fae548d3Szrj {
1018*fae548d3Szrj   unsigned int len = strlen (abfd->filename);
1019*fae548d3Szrj 
1020*fae548d3Szrj   /* I'll put an arbitrary 40 char limit on header size.  */
1021*fae548d3Szrj   if (len > 40)
1022*fae548d3Szrj     len = 40;
1023*fae548d3Szrj 
1024*fae548d3Szrj   return srec_write_record (abfd, 0, (bfd_vma) 0,
1025*fae548d3Szrj 			    (bfd_byte *) abfd->filename,
1026*fae548d3Szrj 			    (bfd_byte *) abfd->filename + len);
1027*fae548d3Szrj }
1028*fae548d3Szrj 
1029*fae548d3Szrj static bfd_boolean
srec_write_section(bfd * abfd,tdata_type * tdata,srec_data_list_type * list)1030*fae548d3Szrj srec_write_section (bfd *abfd,
1031*fae548d3Szrj 		    tdata_type *tdata,
1032*fae548d3Szrj 		    srec_data_list_type *list)
1033*fae548d3Szrj {
1034*fae548d3Szrj   unsigned int octets_written = 0;
1035*fae548d3Szrj   bfd_byte *location = list->data;
1036*fae548d3Szrj 
1037*fae548d3Szrj   /* Validate number of data bytes to write.  The srec length byte
1038*fae548d3Szrj      counts the address, data and crc bytes.  S1 (tdata->type == 1)
1039*fae548d3Szrj      records have two address bytes, S2 (tdata->type == 2) records
1040*fae548d3Szrj      have three, and S3 (tdata->type == 3) records have four.
1041*fae548d3Szrj      The total length can't exceed 255, and a zero data length will
1042*fae548d3Szrj      spin for a long time.  */
1043*fae548d3Szrj   if (_bfd_srec_len == 0)
1044*fae548d3Szrj     _bfd_srec_len = 1;
1045*fae548d3Szrj   else if (_bfd_srec_len > MAXCHUNK - tdata->type - 2)
1046*fae548d3Szrj     _bfd_srec_len = MAXCHUNK - tdata->type - 2;
1047*fae548d3Szrj 
1048*fae548d3Szrj   while (octets_written < list->size)
1049*fae548d3Szrj     {
1050*fae548d3Szrj       bfd_vma address;
1051*fae548d3Szrj       unsigned int octets_this_chunk = list->size - octets_written;
1052*fae548d3Szrj 
1053*fae548d3Szrj       if (octets_this_chunk > _bfd_srec_len)
1054*fae548d3Szrj 	octets_this_chunk = _bfd_srec_len;
1055*fae548d3Szrj 
1056*fae548d3Szrj       address = list->where + (octets_written
1057*fae548d3Szrj 			       / bfd_octets_per_byte (abfd, NULL));
1058*fae548d3Szrj 
1059*fae548d3Szrj       if (! srec_write_record (abfd,
1060*fae548d3Szrj 			       tdata->type,
1061*fae548d3Szrj 			       address,
1062*fae548d3Szrj 			       location,
1063*fae548d3Szrj 			       location + octets_this_chunk))
1064*fae548d3Szrj 	return FALSE;
1065*fae548d3Szrj 
1066*fae548d3Szrj       octets_written += octets_this_chunk;
1067*fae548d3Szrj       location += octets_this_chunk;
1068*fae548d3Szrj     }
1069*fae548d3Szrj 
1070*fae548d3Szrj   return TRUE;
1071*fae548d3Szrj }
1072*fae548d3Szrj 
1073*fae548d3Szrj static bfd_boolean
srec_write_terminator(bfd * abfd,tdata_type * tdata)1074*fae548d3Szrj srec_write_terminator (bfd *abfd, tdata_type *tdata)
1075*fae548d3Szrj {
1076*fae548d3Szrj   return srec_write_record (abfd, 10 - tdata->type,
1077*fae548d3Szrj 			    abfd->start_address, NULL, NULL);
1078*fae548d3Szrj }
1079*fae548d3Szrj 
1080*fae548d3Szrj static bfd_boolean
srec_write_symbols(bfd * abfd)1081*fae548d3Szrj srec_write_symbols (bfd *abfd)
1082*fae548d3Szrj {
1083*fae548d3Szrj   /* Dump out the symbols of a bfd.  */
1084*fae548d3Szrj   int i;
1085*fae548d3Szrj   int count = bfd_get_symcount (abfd);
1086*fae548d3Szrj 
1087*fae548d3Szrj   if (count)
1088*fae548d3Szrj     {
1089*fae548d3Szrj       bfd_size_type len;
1090*fae548d3Szrj       asymbol **table = bfd_get_outsymbols (abfd);
1091*fae548d3Szrj 
1092*fae548d3Szrj       len = strlen (abfd->filename);
1093*fae548d3Szrj       if (bfd_bwrite ("$$ ", (bfd_size_type) 3, abfd) != 3
1094*fae548d3Szrj 	  || bfd_bwrite (abfd->filename, len, abfd) != len
1095*fae548d3Szrj 	  || bfd_bwrite ("\r\n", (bfd_size_type) 2, abfd) != 2)
1096*fae548d3Szrj 	return FALSE;
1097*fae548d3Szrj 
1098*fae548d3Szrj       for (i = 0; i < count; i++)
1099*fae548d3Szrj 	{
1100*fae548d3Szrj 	  asymbol *s = table[i];
1101*fae548d3Szrj 	  if (! bfd_is_local_label (abfd, s)
1102*fae548d3Szrj 	      && (s->flags & BSF_DEBUGGING) == 0)
1103*fae548d3Szrj 	    {
1104*fae548d3Szrj 	      /* Just dump out non debug symbols.  */
1105*fae548d3Szrj 	      char buf[43], *p;
1106*fae548d3Szrj 
1107*fae548d3Szrj 	      len = strlen (s->name);
1108*fae548d3Szrj 	      if (bfd_bwrite ("  ", (bfd_size_type) 2, abfd) != 2
1109*fae548d3Szrj 		  || bfd_bwrite (s->name, len, abfd) != len)
1110*fae548d3Szrj 		return FALSE;
1111*fae548d3Szrj 
1112*fae548d3Szrj 	      sprintf_vma (buf + 2, (s->value
1113*fae548d3Szrj 				     + s->section->output_section->lma
1114*fae548d3Szrj 				     + s->section->output_offset));
1115*fae548d3Szrj 	      p = buf + 2;
1116*fae548d3Szrj 	      while (p[0] == '0' && p[1] != 0)
1117*fae548d3Szrj 		p++;
1118*fae548d3Szrj 	      len = strlen (p);
1119*fae548d3Szrj 	      p[len] = '\r';
1120*fae548d3Szrj 	      p[len + 1] = '\n';
1121*fae548d3Szrj 	      *--p = '$';
1122*fae548d3Szrj 	      *--p = ' ';
1123*fae548d3Szrj 	      len += 4;
1124*fae548d3Szrj 	      if (bfd_bwrite (p, len, abfd) != len)
1125*fae548d3Szrj 		return FALSE;
1126*fae548d3Szrj 	    }
1127*fae548d3Szrj 	}
1128*fae548d3Szrj       if (bfd_bwrite ("$$ \r\n", (bfd_size_type) 5, abfd) != 5)
1129*fae548d3Szrj 	return FALSE;
1130*fae548d3Szrj     }
1131*fae548d3Szrj 
1132*fae548d3Szrj   return TRUE;
1133*fae548d3Szrj }
1134*fae548d3Szrj 
1135*fae548d3Szrj static bfd_boolean
internal_srec_write_object_contents(bfd * abfd,int symbols)1136*fae548d3Szrj internal_srec_write_object_contents (bfd *abfd, int symbols)
1137*fae548d3Szrj {
1138*fae548d3Szrj   tdata_type *tdata = abfd->tdata.srec_data;
1139*fae548d3Szrj   srec_data_list_type *list;
1140*fae548d3Szrj 
1141*fae548d3Szrj   if (symbols)
1142*fae548d3Szrj     {
1143*fae548d3Szrj       if (! srec_write_symbols (abfd))
1144*fae548d3Szrj 	return FALSE;
1145*fae548d3Szrj     }
1146*fae548d3Szrj 
1147*fae548d3Szrj   if (! srec_write_header (abfd))
1148*fae548d3Szrj     return FALSE;
1149*fae548d3Szrj 
1150*fae548d3Szrj   /* Now wander though all the sections provided and output them.  */
1151*fae548d3Szrj   list = tdata->head;
1152*fae548d3Szrj 
1153*fae548d3Szrj   while (list != (srec_data_list_type *) NULL)
1154*fae548d3Szrj     {
1155*fae548d3Szrj       if (! srec_write_section (abfd, tdata, list))
1156*fae548d3Szrj 	return FALSE;
1157*fae548d3Szrj       list = list->next;
1158*fae548d3Szrj     }
1159*fae548d3Szrj   return srec_write_terminator (abfd, tdata);
1160*fae548d3Szrj }
1161*fae548d3Szrj 
1162*fae548d3Szrj static bfd_boolean
srec_write_object_contents(bfd * abfd)1163*fae548d3Szrj srec_write_object_contents (bfd *abfd)
1164*fae548d3Szrj {
1165*fae548d3Szrj   return internal_srec_write_object_contents (abfd, 0);
1166*fae548d3Szrj }
1167*fae548d3Szrj 
1168*fae548d3Szrj static bfd_boolean
symbolsrec_write_object_contents(bfd * abfd)1169*fae548d3Szrj symbolsrec_write_object_contents (bfd *abfd)
1170*fae548d3Szrj {
1171*fae548d3Szrj   return internal_srec_write_object_contents (abfd, 1);
1172*fae548d3Szrj }
1173*fae548d3Szrj 
1174*fae548d3Szrj static int
srec_sizeof_headers(bfd * abfd ATTRIBUTE_UNUSED,struct bfd_link_info * info ATTRIBUTE_UNUSED)1175*fae548d3Szrj srec_sizeof_headers (bfd *abfd ATTRIBUTE_UNUSED,
1176*fae548d3Szrj 		     struct bfd_link_info *info ATTRIBUTE_UNUSED)
1177*fae548d3Szrj {
1178*fae548d3Szrj   return 0;
1179*fae548d3Szrj }
1180*fae548d3Szrj 
1181*fae548d3Szrj /* Return the amount of memory needed to read the symbol table.  */
1182*fae548d3Szrj 
1183*fae548d3Szrj static long
srec_get_symtab_upper_bound(bfd * abfd)1184*fae548d3Szrj srec_get_symtab_upper_bound (bfd *abfd)
1185*fae548d3Szrj {
1186*fae548d3Szrj   return (bfd_get_symcount (abfd) + 1) * sizeof (asymbol *);
1187*fae548d3Szrj }
1188*fae548d3Szrj 
1189*fae548d3Szrj /* Return the symbol table.  */
1190*fae548d3Szrj 
1191*fae548d3Szrj static long
srec_canonicalize_symtab(bfd * abfd,asymbol ** alocation)1192*fae548d3Szrj srec_canonicalize_symtab (bfd *abfd, asymbol **alocation)
1193*fae548d3Szrj {
1194*fae548d3Szrj   bfd_size_type symcount = bfd_get_symcount (abfd);
1195*fae548d3Szrj   asymbol *csymbols;
1196*fae548d3Szrj   unsigned int i;
1197*fae548d3Szrj 
1198*fae548d3Szrj   csymbols = abfd->tdata.srec_data->csymbols;
1199*fae548d3Szrj   if (csymbols == NULL && symcount != 0)
1200*fae548d3Szrj     {
1201*fae548d3Szrj       asymbol *c;
1202*fae548d3Szrj       struct srec_symbol *s;
1203*fae548d3Szrj 
1204*fae548d3Szrj       csymbols = (asymbol *) bfd_alloc (abfd, symcount * sizeof (asymbol));
1205*fae548d3Szrj       if (csymbols == NULL)
1206*fae548d3Szrj 	return -1;
1207*fae548d3Szrj       abfd->tdata.srec_data->csymbols = csymbols;
1208*fae548d3Szrj 
1209*fae548d3Szrj       for (s = abfd->tdata.srec_data->symbols, c = csymbols;
1210*fae548d3Szrj 	   s != NULL;
1211*fae548d3Szrj 	   s = s->next, ++c)
1212*fae548d3Szrj 	{
1213*fae548d3Szrj 	  c->the_bfd = abfd;
1214*fae548d3Szrj 	  c->name = s->name;
1215*fae548d3Szrj 	  c->value = s->val;
1216*fae548d3Szrj 	  c->flags = BSF_GLOBAL;
1217*fae548d3Szrj 	  c->section = bfd_abs_section_ptr;
1218*fae548d3Szrj 	  c->udata.p = NULL;
1219*fae548d3Szrj 	}
1220*fae548d3Szrj     }
1221*fae548d3Szrj 
1222*fae548d3Szrj   for (i = 0; i < symcount; i++)
1223*fae548d3Szrj     *alocation++ = csymbols++;
1224*fae548d3Szrj   *alocation = NULL;
1225*fae548d3Szrj 
1226*fae548d3Szrj   return symcount;
1227*fae548d3Szrj }
1228*fae548d3Szrj 
1229*fae548d3Szrj static void
srec_get_symbol_info(bfd * ignore_abfd ATTRIBUTE_UNUSED,asymbol * symbol,symbol_info * ret)1230*fae548d3Szrj srec_get_symbol_info (bfd *ignore_abfd ATTRIBUTE_UNUSED,
1231*fae548d3Szrj 		      asymbol *symbol,
1232*fae548d3Szrj 		      symbol_info *ret)
1233*fae548d3Szrj {
1234*fae548d3Szrj   bfd_symbol_info (symbol, ret);
1235*fae548d3Szrj }
1236*fae548d3Szrj 
1237*fae548d3Szrj static void
srec_print_symbol(bfd * abfd,void * afile,asymbol * symbol,bfd_print_symbol_type how)1238*fae548d3Szrj srec_print_symbol (bfd *abfd,
1239*fae548d3Szrj 		   void * afile,
1240*fae548d3Szrj 		   asymbol *symbol,
1241*fae548d3Szrj 		   bfd_print_symbol_type how)
1242*fae548d3Szrj {
1243*fae548d3Szrj   FILE *file = (FILE *) afile;
1244*fae548d3Szrj 
1245*fae548d3Szrj   switch (how)
1246*fae548d3Szrj     {
1247*fae548d3Szrj     case bfd_print_symbol_name:
1248*fae548d3Szrj       fprintf (file, "%s", symbol->name);
1249*fae548d3Szrj       break;
1250*fae548d3Szrj     default:
1251*fae548d3Szrj       bfd_print_symbol_vandf (abfd, (void *) file, symbol);
1252*fae548d3Szrj       fprintf (file, " %-5s %s",
1253*fae548d3Szrj 	       symbol->section->name,
1254*fae548d3Szrj 	       symbol->name);
1255*fae548d3Szrj     }
1256*fae548d3Szrj }
1257*fae548d3Szrj 
1258*fae548d3Szrj #define	srec_close_and_cleanup			  _bfd_generic_close_and_cleanup
1259*fae548d3Szrj #define srec_bfd_free_cached_info		  _bfd_generic_bfd_free_cached_info
1260*fae548d3Szrj #define srec_new_section_hook			  _bfd_generic_new_section_hook
1261*fae548d3Szrj #define srec_bfd_is_target_special_symbol	  _bfd_bool_bfd_asymbol_false
1262*fae548d3Szrj #define srec_bfd_is_local_label_name		  bfd_generic_is_local_label_name
1263*fae548d3Szrj #define srec_get_lineno				  _bfd_nosymbols_get_lineno
1264*fae548d3Szrj #define srec_find_nearest_line			  _bfd_nosymbols_find_nearest_line
1265*fae548d3Szrj #define srec_find_line				  _bfd_nosymbols_find_line
1266*fae548d3Szrj #define srec_find_inliner_info			  _bfd_nosymbols_find_inliner_info
1267*fae548d3Szrj #define srec_make_empty_symbol			  _bfd_generic_make_empty_symbol
1268*fae548d3Szrj #define srec_get_symbol_version_string		  _bfd_nosymbols_get_symbol_version_string
1269*fae548d3Szrj #define srec_bfd_make_debug_symbol		  _bfd_nosymbols_bfd_make_debug_symbol
1270*fae548d3Szrj #define srec_read_minisymbols			  _bfd_generic_read_minisymbols
1271*fae548d3Szrj #define srec_minisymbol_to_symbol		  _bfd_generic_minisymbol_to_symbol
1272*fae548d3Szrj #define srec_get_section_contents_in_window	  _bfd_generic_get_section_contents_in_window
1273*fae548d3Szrj #define srec_bfd_get_relocated_section_contents	  bfd_generic_get_relocated_section_contents
1274*fae548d3Szrj #define srec_bfd_relax_section			  bfd_generic_relax_section
1275*fae548d3Szrj #define srec_bfd_gc_sections			  bfd_generic_gc_sections
1276*fae548d3Szrj #define srec_bfd_lookup_section_flags		  bfd_generic_lookup_section_flags
1277*fae548d3Szrj #define srec_bfd_merge_sections			  bfd_generic_merge_sections
1278*fae548d3Szrj #define srec_bfd_is_group_section		  bfd_generic_is_group_section
1279*fae548d3Szrj #define srec_bfd_group_name			  bfd_generic_group_name
1280*fae548d3Szrj #define srec_bfd_discard_group			  bfd_generic_discard_group
1281*fae548d3Szrj #define srec_section_already_linked		  _bfd_generic_section_already_linked
1282*fae548d3Szrj #define srec_bfd_define_common_symbol		  bfd_generic_define_common_symbol
1283*fae548d3Szrj #define srec_bfd_link_hide_symbol		  _bfd_generic_link_hide_symbol
1284*fae548d3Szrj #define srec_bfd_define_start_stop		  bfd_generic_define_start_stop
1285*fae548d3Szrj #define srec_bfd_link_hash_table_create		  _bfd_generic_link_hash_table_create
1286*fae548d3Szrj #define srec_bfd_link_add_symbols		  _bfd_generic_link_add_symbols
1287*fae548d3Szrj #define srec_bfd_link_just_syms			  _bfd_generic_link_just_syms
1288*fae548d3Szrj #define srec_bfd_copy_link_hash_symbol_type	  _bfd_generic_copy_link_hash_symbol_type
1289*fae548d3Szrj #define srec_bfd_final_link			  _bfd_generic_final_link
1290*fae548d3Szrj #define srec_bfd_link_split_section		  _bfd_generic_link_split_section
1291*fae548d3Szrj #define srec_bfd_link_check_relocs		  _bfd_generic_link_check_relocs
1292*fae548d3Szrj 
1293*fae548d3Szrj const bfd_target srec_vec =
1294*fae548d3Szrj {
1295*fae548d3Szrj   "srec",			/* Name.  */
1296*fae548d3Szrj   bfd_target_srec_flavour,
1297*fae548d3Szrj   BFD_ENDIAN_UNKNOWN,		/* Target byte order.  */
1298*fae548d3Szrj   BFD_ENDIAN_UNKNOWN,		/* Target headers byte order.  */
1299*fae548d3Szrj   (HAS_RELOC | EXEC_P |		/* Object flags.  */
1300*fae548d3Szrj    HAS_LINENO | HAS_DEBUG |
1301*fae548d3Szrj    HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
1302*fae548d3Szrj   (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS
1303*fae548d3Szrj    | SEC_ALLOC | SEC_LOAD | SEC_RELOC),	/* Section flags.  */
1304*fae548d3Szrj   0,				/* Leading underscore.  */
1305*fae548d3Szrj   ' ',				/* AR_pad_char.  */
1306*fae548d3Szrj   16,				/* AR_max_namelen.  */
1307*fae548d3Szrj   0,				/* match priority.  */
1308*fae548d3Szrj   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
1309*fae548d3Szrj   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
1310*fae548d3Szrj   bfd_getb16, bfd_getb_signed_16, bfd_putb16,	/* Data.  */
1311*fae548d3Szrj   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
1312*fae548d3Szrj   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
1313*fae548d3Szrj   bfd_getb16, bfd_getb_signed_16, bfd_putb16,	/* Hdrs.  */
1314*fae548d3Szrj 
1315*fae548d3Szrj   {
1316*fae548d3Szrj     _bfd_dummy_target,
1317*fae548d3Szrj     srec_object_p,		/* bfd_check_format.  */
1318*fae548d3Szrj     _bfd_dummy_target,
1319*fae548d3Szrj     _bfd_dummy_target,
1320*fae548d3Szrj   },
1321*fae548d3Szrj   {
1322*fae548d3Szrj     _bfd_bool_bfd_false_error,
1323*fae548d3Szrj     srec_mkobject,
1324*fae548d3Szrj     _bfd_generic_mkarchive,
1325*fae548d3Szrj     _bfd_bool_bfd_false_error,
1326*fae548d3Szrj   },
1327*fae548d3Szrj   {				/* bfd_write_contents.  */
1328*fae548d3Szrj     _bfd_bool_bfd_false_error,
1329*fae548d3Szrj     srec_write_object_contents,
1330*fae548d3Szrj     _bfd_write_archive_contents,
1331*fae548d3Szrj     _bfd_bool_bfd_false_error,
1332*fae548d3Szrj   },
1333*fae548d3Szrj 
1334*fae548d3Szrj   BFD_JUMP_TABLE_GENERIC (srec),
1335*fae548d3Szrj   BFD_JUMP_TABLE_COPY (_bfd_generic),
1336*fae548d3Szrj   BFD_JUMP_TABLE_CORE (_bfd_nocore),
1337*fae548d3Szrj   BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
1338*fae548d3Szrj   BFD_JUMP_TABLE_SYMBOLS (srec),
1339*fae548d3Szrj   BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
1340*fae548d3Szrj   BFD_JUMP_TABLE_WRITE (srec),
1341*fae548d3Szrj   BFD_JUMP_TABLE_LINK (srec),
1342*fae548d3Szrj   BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
1343*fae548d3Szrj 
1344*fae548d3Szrj   NULL,
1345*fae548d3Szrj 
1346*fae548d3Szrj   NULL
1347*fae548d3Szrj };
1348*fae548d3Szrj 
1349*fae548d3Szrj const bfd_target symbolsrec_vec =
1350*fae548d3Szrj {
1351*fae548d3Szrj   "symbolsrec",			/* Name.  */
1352*fae548d3Szrj   bfd_target_srec_flavour,
1353*fae548d3Szrj   BFD_ENDIAN_UNKNOWN,		/* Target byte order.  */
1354*fae548d3Szrj   BFD_ENDIAN_UNKNOWN,		/* Target headers byte order.  */
1355*fae548d3Szrj   (HAS_RELOC | EXEC_P |		/* Object flags.  */
1356*fae548d3Szrj    HAS_LINENO | HAS_DEBUG |
1357*fae548d3Szrj    HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
1358*fae548d3Szrj   (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS
1359*fae548d3Szrj    | SEC_ALLOC | SEC_LOAD | SEC_RELOC),	/* Section flags.  */
1360*fae548d3Szrj   0,				/* Leading underscore.  */
1361*fae548d3Szrj   ' ',				/* AR_pad_char.  */
1362*fae548d3Szrj   16,				/* AR_max_namelen.  */
1363*fae548d3Szrj   0,				/* match priority.  */
1364*fae548d3Szrj   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
1365*fae548d3Szrj   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
1366*fae548d3Szrj   bfd_getb16, bfd_getb_signed_16, bfd_putb16,	/* Data.  */
1367*fae548d3Szrj   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
1368*fae548d3Szrj   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
1369*fae548d3Szrj   bfd_getb16, bfd_getb_signed_16, bfd_putb16,	/* Headers.  */
1370*fae548d3Szrj 
1371*fae548d3Szrj   {
1372*fae548d3Szrj     _bfd_dummy_target,
1373*fae548d3Szrj     symbolsrec_object_p,	/* bfd_check_format.  */
1374*fae548d3Szrj     _bfd_dummy_target,
1375*fae548d3Szrj     _bfd_dummy_target,
1376*fae548d3Szrj   },
1377*fae548d3Szrj   {
1378*fae548d3Szrj     _bfd_bool_bfd_false_error,
1379*fae548d3Szrj     srec_mkobject,
1380*fae548d3Szrj     _bfd_generic_mkarchive,
1381*fae548d3Szrj     _bfd_bool_bfd_false_error,
1382*fae548d3Szrj   },
1383*fae548d3Szrj   {				/* bfd_write_contents.  */
1384*fae548d3Szrj     _bfd_bool_bfd_false_error,
1385*fae548d3Szrj     symbolsrec_write_object_contents,
1386*fae548d3Szrj     _bfd_write_archive_contents,
1387*fae548d3Szrj     _bfd_bool_bfd_false_error,
1388*fae548d3Szrj   },
1389*fae548d3Szrj 
1390*fae548d3Szrj   BFD_JUMP_TABLE_GENERIC (srec),
1391*fae548d3Szrj   BFD_JUMP_TABLE_COPY (_bfd_generic),
1392*fae548d3Szrj   BFD_JUMP_TABLE_CORE (_bfd_nocore),
1393*fae548d3Szrj   BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
1394*fae548d3Szrj   BFD_JUMP_TABLE_SYMBOLS (srec),
1395*fae548d3Szrj   BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
1396*fae548d3Szrj   BFD_JUMP_TABLE_WRITE (srec),
1397*fae548d3Szrj   BFD_JUMP_TABLE_LINK (srec),
1398*fae548d3Szrj   BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
1399*fae548d3Szrj 
1400*fae548d3Szrj   NULL,
1401*fae548d3Szrj 
1402*fae548d3Szrj   NULL
1403*fae548d3Szrj };
1404