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