]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - bfd/srec.c
*** empty log message ***
[thirdparty/binutils-gdb.git] / bfd / srec.c
1 /* Copyright (C) 1990, 1991 Free Software Foundation, Inc.
2
3 This file is part of BFD, the Binary File Diddler.
4
5 BFD is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 1, or (at your option)
8 any later version.
9
10 BFD is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with BFD; see the file COPYING. If not, write to
17 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
18
19 /*
20
21 bfd backend for srecord objects.
22
23 Srecords cannot hold anything but addresses and data, so that's all
24 that we impliment.
25
26 The only interesting thing is that srecords may come out of order and
27 there is no header, so an initial scan is required to discover the
28 minimum and maximum addresses used to create the vma and size of the
29 only section we create. We arbitarily call this section ".text".
30
31 When bfd_get_section_contents is called the file is read again, and
32 this time the data is placed into a malloced area.
33
34 Any number of sections may be created for output, we just output them
35 in the order provided to bfd_set_section_contents.
36
37
38 Steve Chamberlain steve@cygnus.com
39
40 */
41
42
43 /* $Id$
44 * $Log$
45 * Revision 1.4 1991/04/23 16:01:02 steve
46 * *** empty log message ***
47 *
48 * Revision 1.3 1991/04/08 23:22:31 steve
49 * *** empty log message ***
50 *
51 * Revision 1.2 1991/04/03 22:10:51 steve
52 * Fixed typo
53 *
54 * Revision 1.1.1.1 1991/03/21 21:11:22 gumby
55 * Back from Intel with Steve
56 *
57 * Revision 1.1 1991/03/21 21:11:20 gumby
58 * Initial revision
59 *
60 * Revision 1.1 1991/03/13 00:22:29 chrisb
61 * Initial revision
62 *
63 * Revision 1.3 1991/03/10 19:11:40 rich
64 * Modified Files:
65 * bfd.c coff-code.h libbfd.c libbfd.h srec.c sunos.c
66 *
67 * Working bugs out of coff support.
68 *
69 * Revision 1.2 1991/03/07 02:26:18 sac
70 * Tidied up xfer table
71 *
72 * Revision 1.1 1991/03/05 16:28:12 sac
73 * Initial revision
74 *
75 */
76 #include "sysdep.h"
77 #include "bfd.h"
78 #include "libbfd.h"
79
80
81 static char digs[] = "0123456789ABCDEF";
82
83 /* Macros for converting between hex and binary */
84
85 #define NIBBLE(x) ((x >= '0' && x <= '9') ? (x - '0') : (x - 'A' + 10))
86 #define HEX(buffer) ((NIBBLE((buffer)->high) <<4) + NIBBLE((buffer)->low))
87 #define TOHEX(d,x) \
88 ((d)->low = digs[(x) & 0xf], (d)->high = digs[((x)>>4)&0xf], x)
89
90 typedef struct {
91 char high;
92 char low;
93 } byte_as_two_char_type;
94
95 /* The maximum number of bytes on a line is FF */
96 #define MAXCHUNK 0xff
97 /* The number of bytes we fit onto a line on output */
98 #define CHUNK 16
99
100 /* The shape of an srecord .. */
101 typedef struct
102 {
103 char S;
104 char type;
105 byte_as_two_char_type size;
106 union {
107 struct {
108 byte_as_two_char_type address[4];
109 byte_as_two_char_type data[MAXCHUNK];
110 /* If there isn't MAXCHUNK bytes of data then the checksum will
111 appear earlier */
112 byte_as_two_char_type checksum;
113 char nl;
114 } type_3;
115 struct {
116 byte_as_two_char_type address[4];
117 byte_as_two_char_type data[MAXCHUNK];
118 byte_as_two_char_type checksum;
119 char nl;
120 } type_6;
121
122 struct {
123 byte_as_two_char_type address[3];
124 byte_as_two_char_type data[MAXCHUNK];
125 byte_as_two_char_type checksum;
126 char nl;
127 } type_2;
128
129 struct {
130 byte_as_two_char_type address[2];
131 byte_as_two_char_type data[MAXCHUNK];
132 byte_as_two_char_type checksum;
133 char nl;
134 } type_1;
135 byte_as_two_char_type data[MAXCHUNK];
136 } u;
137 } srec_type;
138
139
140 /*
141 called once per input srecord, used to work out vma and size of data.
142 */
143
144 static void
145 size_srec(abfd, section, address, raw, length)
146 bfd *abfd;
147 asection *section;
148 bfd_vma address;
149 byte_as_two_char_type *raw;
150 unsigned int length;
151 {
152 if (address < section->vma)
153 section->vma = address;
154
155 if (address + length > section->vma + section->size)
156 section->size = (address+length) - section->vma;
157 }
158
159 /*
160 called once per input srecord, copies data from input into malloced area
161 */
162
163 static void
164 fillup(abfd, section, address, raw, length)
165 bfd *abfd;
166 asection *section;
167 bfd_vma address;
168 byte_as_two_char_type *raw;
169 unsigned int length;
170 {
171 unsigned int i;
172 bfd_byte *dst = (bfd_byte *)(section->used_by_bfd) + address - section->vma;
173 for (i = 0; i < length; i++) {
174 *dst = HEX(raw);
175 dst++;
176 raw++;
177 }
178 }
179
180 /*
181 pass over an srecord file calling one of the above functions on each
182 record
183 */
184 static void
185 pass_over(abfd, func, section)
186 bfd *abfd;
187 void (*func)();
188 asection *section;
189 {
190 unsigned int bytes_on_line;
191 boolean eof = false;
192 bfd_vma address;
193 /* To the front of the file */
194 bfd_seek(abfd, (file_ptr)0, SEEK_SET);
195 while (eof == false)
196 {
197 srec_type buffer;
198
199 /* Find first 'S' */
200 eof = bfd_read(&buffer.S, 1, 1, abfd) != 1;
201 while (buffer.S != 'S' && !eof) {
202 eof = bfd_read(&buffer.S, 1, 1, abfd) != 1;
203 }
204 if (eof) break;
205
206 bfd_read(&buffer.type, 1, 3, abfd);
207
208 bytes_on_line = HEX(&buffer.size);
209
210 bfd_read(buffer.u.data, 1 , bytes_on_line * 2, abfd);
211
212 switch (buffer.type) {
213 case '6':
214 /* Prologue - ignore */
215 break;
216 case '3':
217 address = (HEX(buffer.u.type_3.address+0) << 24)
218 + (HEX(buffer.u.type_3.address+1) << 16)
219 + (HEX(buffer.u.type_3.address+2) << 8)
220 + (HEX(buffer.u.type_3.address+3));
221 func(abfd,section, address, buffer.u.type_2.data, bytes_on_line -1);
222
223 break;
224
225 case '2':
226 address = (HEX(buffer.u.type_2.address+0) << 16)+
227 (HEX(buffer.u.type_2.address+1) << 8) +
228 (HEX(buffer.u.type_2.address+2));
229 func(abfd,section, address, buffer.u.type_2.data, bytes_on_line -1);
230
231 break;
232 case '1':
233 address =
234 (HEX(buffer.u.type_1.address+0) << 8)
235 + (HEX(buffer.u.type_1.address+1));
236 func(abfd, section, address, buffer.u.type_1.data, bytes_on_line -1);
237 break;
238
239 }
240 }
241 }
242
243
244 bfd_target *
245 srec_object_p (abfd)
246 bfd *abfd;
247 {
248 char b;
249 asection *section;
250 bfd_seek(abfd, (file_ptr)0, SEEK_SET);
251 bfd_read(&b, 1,1,abfd);
252 if (b != 'S') return (bfd_target*)NULL;
253
254 /*
255 We create one section called data for all the contents,
256 and allocate enough room for the entire file
257 */
258
259
260 section = bfd_make_section(abfd, ".text");
261 section->size = 0;
262 section->vma = 0xffffffff;
263 pass_over(abfd, size_srec, section);
264
265 return abfd->xvec;
266 }
267
268
269
270
271
272
273
274
275 static boolean
276 srec_get_section_contents (abfd, section, location, offset, count)
277 bfd *abfd;
278 sec_ptr section;
279 void *location;
280 file_ptr offset;
281 unsigned int count;
282 {
283 if (section->used_by_bfd == (bfd_byte *)NULL) {
284 section->used_by_bfd = (bfd_byte *)malloc(section->size);
285 pass_over(abfd, fillup, section);
286 }
287 (void) memcpy(location, (bfd_byte *)(section->used_by_bfd) + offset, count);
288 return true;
289 }
290
291
292
293 boolean
294 srec_set_arch_mach (abfd, arch, machine)
295 bfd *abfd;
296 enum bfd_architecture arch;
297 unsigned long machine;
298 {
299 abfd->obj_arch = arch;
300 abfd->obj_machine = machine;
301 return true;
302 }
303
304
305
306 boolean
307 srec_set_section_contents (abfd, section, location, offset, bytes_to_do)
308 bfd *abfd;
309 sec_ptr section;
310 unsigned char *location;
311 file_ptr offset;
312 int bytes_to_do;
313 {
314 bfd_vma address;
315 int bytes_written;
316
317 int type;
318 unsigned int i;
319 srec_type buffer;
320 bytes_written = 0;
321 if (section->size <= 0xffff)
322 type = 1;
323 else if (section->size <= 0xffffff)
324 type = 2;
325 else
326 type = 3;
327
328 buffer.S = 'S';
329 buffer.type = '0' + type;
330
331 while (bytes_written < bytes_to_do) {
332 unsigned int size;
333 unsigned int check_sum;
334 byte_as_two_char_type *data;
335 unsigned int bytes_this_chunk = bytes_to_do - bytes_written;
336
337 if (bytes_this_chunk > CHUNK) {
338 bytes_this_chunk = CHUNK;
339 }
340
341 address = section->vma + offset + bytes_written;
342
343 switch (type) {
344 case 3:
345 check_sum = TOHEX(buffer.u.type_3.address, address >> 24);
346 check_sum += TOHEX(buffer.u.type_3.address+1, address >> 16);
347 check_sum += TOHEX(buffer.u.type_3.address+2, address >> 8);
348 check_sum += TOHEX(buffer.u.type_3.address+3, address >> 0);
349 size = bytes_this_chunk + 5;
350 data = buffer.u.type_3.data;
351
352 case 2:
353 check_sum = TOHEX(buffer.u.type_3.address, address >> 16);
354 check_sum += TOHEX(buffer.u.type_3.address+1, address >> 8);
355 check_sum += TOHEX(buffer.u.type_3.address+2, address >> 0);
356 size = bytes_this_chunk + 4;
357 data = buffer.u.type_2.data;
358 break;
359
360 case 1:
361 check_sum = TOHEX(buffer.u.type_3.address+0, address >> 8);
362 check_sum += TOHEX(buffer.u.type_3.address+1, address >> 0);
363 size = bytes_this_chunk + 3;
364 data = buffer.u.type_1.data;
365 }
366
367 for (i = 0; i < bytes_this_chunk; i++) {
368 check_sum += TOHEX(data, (location[i]));
369 data++;
370 }
371
372 check_sum += TOHEX(&(buffer.size), size );
373 (void) TOHEX(data, ~check_sum);
374 data++;
375
376 * ( (char *)(data)) = '\n';
377 bfd_write(&buffer, 1, (char *)data - (char *)&buffer + 1 , abfd);
378
379 bytes_written += bytes_this_chunk;
380 location += bytes_this_chunk;
381 }
382
383
384 return true;
385 }
386
387
388 boolean
389 srec_close_and_cleanup (abfd)
390 bfd *abfd;
391 {
392 asection *s;
393 if (bfd_read_p (abfd) == false) {
394 switch (abfd->format) {
395 case bfd_archive:
396 if (!_bfd_write_archive_contents (abfd)) {
397 return false;
398 }
399 break;
400 case bfd_object:
401 bfd_write("S9030000FC\n", 1,11,abfd);
402 break;
403 default:
404 bfd_error = invalid_operation;
405 return false;
406 }
407 }
408 for (s = abfd->sections; s != (asection *)NULL;s = s->next) {
409 if (s->used_by_bfd != (void *)NULL) {
410 free(s->used_by_bfd);
411 }
412 }
413 return true;
414 }
415
416 /*SUPPRESS 460 */
417 #define srec_core_file_failing_command bfd_false
418 #define srec_core_file_failing_signal bfd_false
419 #define srec_core_file_matches_executable_p bfd_false
420 #define srec_slurp_armap bfd_false
421 #define srec_slurp_extended_name_table bfd_false
422 #define srec_truncate_arname bfd_false
423 #define srec_write_armap bfd_false
424 #define srec_new_section_hook bfd_false
425 #define srec_get_symtab_upper_bound bfd_false
426 #define srec_get_symtab bfd_false
427 #define srec_get_reloc_upper_bound bfd_false
428 #define srec_canonicalize_reloc bfd_false
429 #define srec_make_empty_symbol bfd_false
430 #define srec_print_symbol bfd_false
431 #define srec_get_lineno bfd_false
432 #define srec_openr_next_archived_file bfd_false
433 #define srec_find_nearest_line bfd_false
434 #define srec_generic_stat_arch_elt bfd_false
435
436 bfd_target srec_vec =
437 {
438 "srec", /* name */
439 bfd_target_srec_flavour_enum,
440 true, /* target byte order */
441 true, /* target headers byte order */
442 (HAS_RELOC | EXEC_P | /* object flags */
443 HAS_LINENO | HAS_DEBUG |
444 HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT | D_PAGED),
445 (SEC_CODE|SEC_DATA|SEC_ROM|SEC_HAS_CONTENTS
446 |SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
447 ' ', /* ar_pad_char */
448 16, /* ar_max_namelen */
449 _do_getblong, _do_putblong, _do_getbshort, _do_putbshort, /* data */
450 _do_getblong, _do_putblong, _do_getbshort, _do_putbshort, /* hdrs */
451
452 {_bfd_dummy_target,
453 srec_object_p, /* bfd_check_format */
454 (struct bfd_target *(*)()) bfd_nullvoidptr,
455 (struct bfd_target *(*)()) bfd_nullvoidptr,
456 },
457 {
458 bfd_false,
459 bfd_true, /* mkobject */
460 _bfd_generic_mkarchive,
461 bfd_false,
462 },
463 JUMP_TABLE(srec)
464 };