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