Cleanups of interface, including close_and_cleanup and write_contents
[deliverable/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 bfd_alloc'd 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.8 1991/05/11 00:38:46 gnu
46 * Cleanups of interface, including close_and_cleanup and write_contents
47 * transfer vector changes. See ChangeLog.
48 *
49 * Revision 1.7 1991/05/08 19:21:47 steve
50 * Various portability lints.
51 * Fixed reloc bug in ieee and oasys.
52 *
53 * Revision 1.6 1991/04/25 04:06:21 gnu
54 * Fix minor pointer type problems that "cc" complains about.
55 *
56 * Revision 1.5 1991/04/23 22:44:14 steve
57 * *** empty log message ***
58 *
59 * Revision 1.4 1991/04/23 16:01:02 steve
60 * *** empty log message ***
61 *
62 * Revision 1.3 1991/04/08 23:22:31 steve
63 * *** empty log message ***
64 *
65 * Revision 1.2 1991/04/03 22:10:51 steve
66 * Fixed typo
67 *
68 * Revision 1.1.1.1 1991/03/21 21:11:22 gumby
69 * Back from Intel with Steve
70 *
71 * Revision 1.1 1991/03/21 21:11:20 gumby
72 * Initial revision
73 *
74 * Revision 1.1 1991/03/13 00:22:29 chrisb
75 * Initial revision
76 *
77 * Revision 1.3 1991/03/10 19:11:40 rich
78 * Modified Files:
79 * bfd.c coff-code.h libbfd.c libbfd.h srec.c sunos.c
80 *
81 * Working bugs out of coff support.
82 *
83 * Revision 1.2 1991/03/07 02:26:18 sac
84 * Tidied up xfer table
85 *
86 * Revision 1.1 1991/03/05 16:28:12 sac
87 * Initial revision
88 *
89 */
90 #include "sysdep.h"
91 #include "bfd.h"
92 #include "libbfd.h"
93
94
95 static char digs[] = "0123456789ABCDEF";
96
97 /* Macros for converting between hex and binary */
98
99 #define NIBBLE(x) ((x >= '0' && x <= '9') ? (x - '0') : (x - 'A' + 10))
100 #define HEX(buffer) ((NIBBLE((buffer)->high) <<4) + NIBBLE((buffer)->low))
101 #define TOHEX(d,x) \
102 ((d)->low = digs[(x) & 0xf], (d)->high = digs[((x)>>4)&0xf], x)
103
104 typedef struct {
105 char high;
106 char low;
107 } byte_as_two_char_type;
108
109 /* The maximum number of bytes on a line is FF */
110 #define MAXCHUNK 0xff
111 /* The number of bytes we fit onto a line on output */
112 #define CHUNK 16
113
114 /* The shape of an srecord .. */
115 typedef struct
116 {
117 char S;
118 char type;
119 byte_as_two_char_type size;
120 union {
121 struct {
122 byte_as_two_char_type address[4];
123 byte_as_two_char_type data[MAXCHUNK];
124 /* If there isn't MAXCHUNK bytes of data then the checksum will
125 appear earlier */
126 byte_as_two_char_type checksum;
127 char nl;
128 } type_3;
129 struct {
130 byte_as_two_char_type address[4];
131 byte_as_two_char_type data[MAXCHUNK];
132 byte_as_two_char_type checksum;
133 char nl;
134 } type_6;
135
136 struct {
137 byte_as_two_char_type address[3];
138 byte_as_two_char_type data[MAXCHUNK];
139 byte_as_two_char_type checksum;
140 char nl;
141 } type_2;
142
143 struct {
144 byte_as_two_char_type address[2];
145 byte_as_two_char_type data[MAXCHUNK];
146 byte_as_two_char_type checksum;
147 char nl;
148 } type_1;
149 byte_as_two_char_type data[MAXCHUNK];
150 } u;
151 } srec_type;
152
153
154 /*
155 called once per input srecord, used to work out vma and size of data.
156 */
157
158 static void
159 size_srec(abfd, section, address, raw, length)
160 bfd *abfd;
161 asection *section;
162 bfd_vma address;
163 byte_as_two_char_type *raw;
164 unsigned int length;
165 {
166 if (address < section->vma)
167 section->vma = address;
168
169 if (address + length > section->vma + section->size)
170 section->size = (address+length) - section->vma;
171 }
172
173 /*
174 called once per input srecord, copies data from input into bfd_alloc'd area
175 */
176
177 static void
178 fillup(abfd, section, address, raw, length)
179 bfd *abfd;
180 asection *section;
181 bfd_vma address;
182 byte_as_two_char_type *raw;
183 unsigned int length;
184 {
185 unsigned int i;
186 bfd_byte *dst = (bfd_byte *)(section->used_by_bfd) + address - section->vma;
187 for (i = 0; i < length; i++) {
188 *dst = HEX(raw);
189 dst++;
190 raw++;
191 }
192 }
193
194 /*
195 pass over an srecord file calling one of the above functions on each
196 record
197 */
198 static void
199 pass_over(abfd, func, section)
200 bfd *abfd;
201 void (*func)();
202 asection *section;
203 {
204 unsigned int bytes_on_line;
205 boolean eof = false;
206 bfd_vma address;
207 /* To the front of the file */
208 bfd_seek(abfd, (file_ptr)0, SEEK_SET);
209 while (eof == false)
210 {
211 srec_type buffer;
212
213 /* Find first 'S' */
214 eof = bfd_read(&buffer.S, 1, 1, abfd) != 1;
215 while (buffer.S != 'S' && !eof) {
216 eof = bfd_read(&buffer.S, 1, 1, abfd) != 1;
217 }
218 if (eof) break;
219
220 bfd_read(&buffer.type, 1, 3, abfd);
221
222 bytes_on_line = HEX(&buffer.size);
223
224 bfd_read((PTR)buffer.u.data, 1 , bytes_on_line * 2, abfd);
225
226 switch (buffer.type) {
227 case '6':
228 /* Prologue - ignore */
229 break;
230 case '3':
231 address = (HEX(buffer.u.type_3.address+0) << 24)
232 + (HEX(buffer.u.type_3.address+1) << 16)
233 + (HEX(buffer.u.type_3.address+2) << 8)
234 + (HEX(buffer.u.type_3.address+3));
235 func(abfd,section, address, buffer.u.type_2.data, bytes_on_line -1);
236
237 break;
238
239 case '2':
240 address = (HEX(buffer.u.type_2.address+0) << 16)+
241 (HEX(buffer.u.type_2.address+1) << 8) +
242 (HEX(buffer.u.type_2.address+2));
243 func(abfd,section, address, buffer.u.type_2.data, bytes_on_line -1);
244
245 break;
246 case '1':
247 address =
248 (HEX(buffer.u.type_1.address+0) << 8)
249 + (HEX(buffer.u.type_1.address+1));
250 func(abfd, section, address, buffer.u.type_1.data, bytes_on_line -1);
251 break;
252
253 }
254 }
255 }
256
257
258 bfd_target *
259 srec_object_p (abfd)
260 bfd *abfd;
261 {
262 char b;
263 asection *section;
264 bfd_seek(abfd, (file_ptr)0, SEEK_SET);
265 bfd_read(&b, 1,1,abfd);
266 if (b != 'S') return (bfd_target*)NULL;
267
268 /*
269 We create one section called data for all the contents,
270 and allocate enough room for the entire file
271 */
272
273
274 section = bfd_make_section(abfd, ".text");
275 section->size = 0;
276 section->vma = 0xffffffff;
277 pass_over(abfd, size_srec, section);
278
279 return abfd->xvec;
280 }
281
282
283
284
285
286
287
288
289 static boolean
290 srec_get_section_contents (abfd, section, location, offset, count)
291 bfd *abfd;
292 sec_ptr section;
293 void *location;
294 file_ptr offset;
295 unsigned int count;
296 {
297 if (section->used_by_bfd == (PTR)NULL) {
298 section->used_by_bfd = (PTR)bfd_alloc (abfd, section->size);
299 pass_over(abfd, fillup, section);
300 }
301 (void) memcpy(location, (bfd_byte *)(section->used_by_bfd) + offset, count);
302 return true;
303 }
304
305
306
307 boolean
308 srec_set_arch_mach (abfd, arch, machine)
309 bfd *abfd;
310 enum bfd_architecture arch;
311 unsigned long machine;
312 {
313 abfd->obj_arch = arch;
314 abfd->obj_machine = machine;
315 return true;
316 }
317
318
319
320 boolean
321 srec_set_section_contents (abfd, section, location, offset, bytes_to_do)
322 bfd *abfd;
323 sec_ptr section;
324 unsigned char *location;
325 file_ptr offset;
326 int bytes_to_do;
327 {
328 bfd_vma address;
329 int bytes_written;
330
331 int type;
332 unsigned int i;
333 srec_type buffer;
334 bytes_written = 0;
335 if (section->size <= 0xffff)
336 type = 1;
337 else if (section->size <= 0xffffff)
338 type = 2;
339 else
340 type = 3;
341
342 buffer.S = 'S';
343 buffer.type = '0' + type;
344
345 while (bytes_written < bytes_to_do) {
346 unsigned int size;
347 unsigned int check_sum;
348 byte_as_two_char_type *data;
349 unsigned int bytes_this_chunk = bytes_to_do - bytes_written;
350
351 if (bytes_this_chunk > CHUNK) {
352 bytes_this_chunk = CHUNK;
353 }
354
355 address = section->vma + offset + bytes_written;
356
357 switch (type) {
358 case 3:
359 check_sum = TOHEX(buffer.u.type_3.address, address >> 24);
360 check_sum += TOHEX(buffer.u.type_3.address+1, address >> 16);
361 check_sum += TOHEX(buffer.u.type_3.address+2, address >> 8);
362 check_sum += TOHEX(buffer.u.type_3.address+3, address >> 0);
363 size = bytes_this_chunk + 5;
364 data = buffer.u.type_3.data;
365
366 case 2:
367 check_sum = TOHEX(buffer.u.type_3.address, address >> 16);
368 check_sum += TOHEX(buffer.u.type_3.address+1, address >> 8);
369 check_sum += TOHEX(buffer.u.type_3.address+2, address >> 0);
370 size = bytes_this_chunk + 4;
371 data = buffer.u.type_2.data;
372 break;
373
374 case 1:
375 check_sum = TOHEX(buffer.u.type_3.address+0, address >> 8);
376 check_sum += TOHEX(buffer.u.type_3.address+1, address >> 0);
377 size = bytes_this_chunk + 3;
378 data = buffer.u.type_1.data;
379 }
380
381 for (i = 0; i < bytes_this_chunk; i++) {
382 check_sum += TOHEX(data, (location[i]));
383 data++;
384 }
385
386 check_sum += TOHEX(&(buffer.size), size );
387 (void) TOHEX(data, ~check_sum);
388 data++;
389
390 * ( (char *)(data)) = '\n';
391 bfd_write((PTR)&buffer, 1, (char *)data - (char *)&buffer + 1 , abfd);
392
393 bytes_written += bytes_this_chunk;
394 location += bytes_this_chunk;
395 }
396
397
398 return true;
399 }
400
401 boolean
402 srec_write_object_contents (abfd)
403 bfd *abfd;
404 {
405 bfd_write("S9030000FC\n", 1,11,abfd);
406 }
407
408 static int
409 DEFUN(srec_sizeof_headers,(abfd),
410 bfd *abfd)
411 {
412 return 0;
413 }
414
415 /*SUPPRESS 460 */
416
417 #define srec_new_section_hook bfd_false
418 #define srec_get_symtab_upper_bound bfd_false
419 #define srec_get_symtab bfd_false
420 #define srec_get_reloc_upper_bound bfd_false
421 #define srec_canonicalize_reloc bfd_false
422 #define srec_make_empty_symbol bfd_false
423 #define srec_print_symbol bfd_false
424
425 #define srec_openr_next_archived_file bfd_false
426 #define srec_find_nearest_line bfd_false
427 #define srec_generic_stat_arch_elt bfd_false
428
429
430 #define srec_core_file_failing_command (char *(*)())(bfd_nullvoidptr)
431 #define srec_core_file_failing_signal (int (*)())bfd_0
432 #define srec_core_file_matches_executable_p (PROTO(boolean, (*),(bfd*, bfd*)))bfd_false
433 #define srec_slurp_armap bfd_true
434 #define srec_slurp_extended_name_table bfd_true
435 #define srec_truncate_arname (void (*)())bfd_nullvoidptr
436 #define srec_write_armap (PROTO( boolean, (*),(bfd *, unsigned int, struct orl *, int, int))) bfd_nullvoidptr
437 #define srec_get_lineno (struct lineno_cache_entry *(*)())bfd_nullvoidptr
438
439 #define srec_close_and_cleanup bfd_generic_close_and_cleanup
440
441
442 bfd_target srec_vec =
443 {
444 "srec", /* name */
445 bfd_target_srec_flavour_enum,
446 true, /* target byte order */
447 true, /* target headers byte order */
448 (HAS_RELOC | EXEC_P | /* object flags */
449 HAS_LINENO | HAS_DEBUG |
450 HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT | D_PAGED),
451 (SEC_CODE|SEC_DATA|SEC_ROM|SEC_HAS_CONTENTS
452 |SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
453 ' ', /* ar_pad_char */
454 16, /* ar_max_namelen */
455 _do_getblong, _do_putblong, _do_getbshort, _do_putbshort, /* data */
456 _do_getblong, _do_putblong, _do_getbshort, _do_putbshort, /* hdrs */
457
458 {_bfd_dummy_target,
459 srec_object_p, /* bfd_check_format */
460 (struct bfd_target *(*)()) bfd_nullvoidptr,
461 (struct bfd_target *(*)()) bfd_nullvoidptr,
462 },
463 {
464 bfd_false,
465 bfd_true, /* mkobject */
466 _bfd_generic_mkarchive,
467 bfd_false,
468 },
469 { /* bfd_write_contents */
470 bfd_false,
471 srec_write_object_contents,
472 _bfd_write_archive_contents,
473 bfd_false,
474 },
475 JUMP_TABLE(srec)
476 };
This page took 0.056543 seconds and 5 git commands to generate.