1 /* Copyright (C) 1990, 1991 Free Software Foundation, Inc.
3 This file is part of BFD, the Binary File Diddler.
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)
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.
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. */
21 bfd backend for srecord objects.
23 Srecords cannot hold anything but addresses and data, so that's all
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".
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.
34 Any number of sections may be created for output, we just output them
35 in the order provided to bfd_set_section_contents.
38 Steve Chamberlain steve@cygnus.com
45 * Revision 1.1 1991/03/21 21:11:20 gumby
48 * Revision 1.1 1991/03/13 00:22:29 chrisb
51 * Revision 1.3 1991/03/10 19:11:40 rich
53 * bfd.c coff-code.h libbfd.c libbfd.h srec.c sunos.c
55 * Working bugs out of coff support.
57 * Revision 1.2 1991/03/07 02:26:18 sac
58 * Tidied up xfer table
60 * Revision 1.1 1991/03/05 16:28:12 sac
68 static char digs
[] = "0123456789ABCDEF";
70 /* Macros for converting between hex and binary */
72 #define NIBBLE(x) ((x >= '0' && x <= '9') ? (x - '0') : (x - 'A' + 10))
73 #define HEX(buffer) ((NIBBLE((buffer)->high) <<4) + NIBBLE((buffer)->low))
75 ((d)->low = digs[(x) & 0xf], (d)->high = digs[((x)>>4)&0xf], x)
80 } byte_as_two_char_type
;
82 /* The maximum number of bytes on a line is FF */
84 /* The number of bytes we fit onto a line on output */
87 /* The shape of an srecord .. */
92 byte_as_two_char_type size
;
95 byte_as_two_char_type address
[4];
96 byte_as_two_char_type data
[MAXCHUNK
];
97 /* If there isn't MAXCHUNK bytes of data then the checksum will
99 byte_as_two_char_type checksum
;
103 byte_as_two_char_type address
[4];
104 byte_as_two_char_type data
[MAXCHUNK
];
105 byte_as_two_char_type checksum
;
110 byte_as_two_char_type address
[3];
111 byte_as_two_char_type data
[MAXCHUNK
];
112 byte_as_two_char_type checksum
;
117 byte_as_two_char_type address
[2];
118 byte_as_two_char_type data
[MAXCHUNK
];
119 byte_as_two_char_type checksum
;
122 byte_as_two_char_type data
[MAXCHUNK
];
128 called once per input srecord, used to work out vma and size of data.
132 size_srec(abfd
, section
, address
, raw
, length
)
136 byte_as_two_char_type
*raw
;
139 if (address
< section
->vma
)
140 section
->vma
= address
;
142 if (address
+ length
> section
->vma
+ section
->size
)
143 section
->size
= (address
+length
) - section
->vma
;
147 called once per input srecord, copies data from input into malloced area
151 fillup(abfd
, section
, address
, raw
, length
)
155 byte_as_two_char_type
*raw
;
159 bfd_byte
*dst
= (bfd_byte
*)(section
->used_by_bfd
) + address
- section
->vma
;
160 for (i
= 0; i
< length
; i
++) {
168 pass over an srecord file calling one of the above functions on each
172 pass_over(abfd
, func
, section
)
177 unsigned int bytes_on_line
;
180 /* To the front of the file */
181 bfd_seek(abfd
, (file_ptr
)0, SEEK_SET
);
187 eof
= bfd_read(&buffer
.S
, 1, 1, abfd
) != 1;
188 while (buffer
.S
!= 'S' && !eof
) {
189 eof
= bfd_read(&buffer
.S
, 1, 1, abfd
) != 1;
193 bfd_read(&buffer
.type
, 1, 3, abfd
);
195 bytes_on_line
= HEX(&buffer
.size
);
197 bfd_read(buffer
.u
.data
, 1 , bytes_on_line
* 2, abfd
);
199 switch (buffer
.type
) {
201 /* Prologue - ignore */
204 address
= (HEX(buffer
.u
.type_3
.address
+0) << 24)
205 + (HEX(buffer
.u
.type_3
.address
+1) << 16)
206 + (HEX(buffer
.u
.type_3
.address
+2) << 8)
207 + (HEX(buffer
.u
.type_3
.address
+3));
208 func(abfd
,section
, address
, buffer
.u
.type_2
.data
, bytes_on_line
-1);
213 address
= (HEX(buffer
.u
.type_2
.address
+0) << 16)+
214 (HEX(buffer
.u
.type_2
.address
+1) << 8) +
215 (HEX(buffer
.u
.type_2
.address
+2));
216 func(abfd
,section
, address
, buffer
.u
.type_2
.data
, bytes_on_line
-1);
221 (HEX(buffer
.u
.type_1
.address
+0) << 8)
222 + (HEX(buffer
.u
.type_1
.address
+1));
223 func(abfd
, section
, address
, buffer
.u
.type_1
.data
, bytes_on_line
-1);
237 bfd_seek(abfd
, (file_ptr
)0, SEEK_SET
);
238 bfd_read(&b
, 1,1,abfd
);
239 if (b
!= 'S') return (bfd_target
*)NULL
;
242 We create one section called data for all the contents,
243 and allocate enough room for the entire file
247 section
= bfd_make_section(abfd
, ".text");
249 section
->vma
= 0xffffffff;
250 pass_over(abfd
, size_srec
, section
);
263 srec_get_section_contents (abfd
, section
, location
, offset
, count
)
270 if (section
->used_by_bfd
== (bfd_byte
*)NULL
) {
271 section
->used_by_bfd
= (bfd_byte
*)malloc(section
->size
);
272 pass_over(abfd
, fillup
, section
);
274 (void) memcpy(location
, (bfd_byte
*)(section
->used_by_bfd
) + offset
, count
);
281 srec_set_arch_mach (abfd
, arch
, machine
)
283 enum bfd_architecture arch
;
284 unsigned long machine
;
286 abfd
->obj_arch
= arch
;
287 abfd
->obj_machine
= machine
;
294 srec_set_section_contents (abfd
, section
, location
, offset
, bytes_to_do
)
297 unsigned char *location
;
308 if (section
->size
<= 0xffff)
310 else if (section
->size
<= 0xffffff)
316 buffer
.type
= '0' + type
;
318 while (bytes_written
< bytes_to_do
) {
320 unsigned int check_sum
;
321 byte_as_two_char_type
*data
;
322 int bytes_this_chunk
= bytes_to_do
- bytes_written
;
324 if (bytes_this_chunk
> CHUNK
) {
325 bytes_this_chunk
= CHUNK
;
328 address
= section
->vma
+ offset
+ bytes_written
;
332 check_sum
= TOHEX(buffer
.u
.type_3
.address
, address
>> 24);
333 check_sum
+= TOHEX(buffer
.u
.type_3
.address
+1, address
>> 16);
334 check_sum
+= TOHEX(buffer
.u
.type_3
.address
+2, address
>> 8);
335 check_sum
+= TOHEX(buffer
.u
.type_3
.address
+3, address
>> 0);
336 size
= bytes_this_chunk
+ 5;
337 data
= buffer
.u
.type_3
.data
;
340 check_sum
= TOHEX(buffer
.u
.type_3
.address
, address
>> 16);
341 check_sum
+= TOHEX(buffer
.u
.type_3
.address
+1, address
>> 8);
342 check_sum
+= TOHEX(buffer
.u
.type_3
.address
+2, address
>> 0);
343 size
= bytes_this_chunk
+ 4;
344 data
= buffer
.u
.type_2
.data
;
348 check_sum
= TOHEX(buffer
.u
.type_3
.address
+0, address
>> 8);
349 check_sum
+= TOHEX(buffer
.u
.type_3
.address
+1, address
>> 0);
350 size
= bytes_this_chunk
+ 3;
351 data
= buffer
.u
.type_1
.data
;
354 for (i
= 0; i
< bytes_this_chunk
; i
++) {
355 check_sum
+= TOHEX(data
, (location
[i
]));
359 check_sum
+= TOHEX(&(buffer
.size
), size
);
360 (void) TOHEX(data
, ~check_sum
);
363 * ( (char *)(data
)) = '\n';
364 bfd_write(&buffer
, 1, (char *)data
- (char *)&buffer
+ 1 , abfd
);
366 bytes_written
+= bytes_this_chunk
;
367 location
+= bytes_this_chunk
;
376 srec_close_and_cleanup (abfd
)
380 if (bfd_read_p (abfd
) == false) {
381 switch (abfd
->format
) {
383 if (!_bfd_write_archive_contents (abfd
)) {
388 bfd_write("S9030000FC\n", 1,11,abfd
);
391 bfd_error
= invalid_operation
;
395 for (s
= abfd
->sections
; s
!= (asection
*)NULL
;s
= s
->next
) {
396 if (s
->used_by_bfd
!= (void *)NULL
) {
397 free(s
->used_by_bfd
);
404 bfd_target srec_vec
=
407 bfd_target_srec_flavour_enum
,
408 true, /* target byte order */
409 true, /* target headers byte order */
410 (HAS_RELOC
| EXEC_P
| /* object flags */
411 HAS_LINENO
| HAS_DEBUG
|
412 HAS_SYMS
| HAS_LOCALS
| DYNAMIC
| WP_TEXT
| D_PAGED
),
413 (SEC_CODE
|SEC_DATA
|SEC_ROM
414 |SEC_ALLOC
| SEC_LOAD
| SEC_RELOC
), /* section flags */
415 0, /* valid reloc types */
416 ' ', /* ar_pad_char */
417 16, /* ar_max_namelen */
418 srec_close_and_cleanup
, /* _close_and_cleanup */
419 srec_set_section_contents
, /* bfd_set_section_contents */
420 srec_get_section_contents
,
421 bfd_true
, /* new_section_hook */
422 0, /* _core_file_failing_command */
423 0, /* _core_file_failing_signal */
424 0, /* _core_file_matches_ex...p */
426 bfd_false
, /* bfd_slurp_armap */
427 bfd_false
, /* bfd_slurp_extended_name_table */
428 bfd_void
, /* bfd_truncate_arname */
429 bfd_0u
, /* get_symtab_upper_bound */
430 bfd_0u
, /* canonicalize_symtab */
431 bfd_void
, /* bfd_reclaim_symbol_table */
432 bfd_0u
, /* get_reloc_upper_bound */
433 bfd_0u
, /* bfd_canonicalize_reloc */
434 bfd_void
, /* bfd_reclaim_reloc */
435 bfd_0
, /* bfd_get_symcount_upper_bound */
436 (symindex (*)())bfd_0
, /* bfd_get_first_symbol */
437 (symindex (*)())bfd_0
, /* bfd_get_next_symbol */
438 bfd_false
, /* bfd_classify_symbol */
439 bfd_false
, /* bfd_symbol_hasclass */
440 (char* (*)())bfd_0
, /* bfd_symbol_name */
441 bfd_0
, /* bfd_symbol_value */
443 _do_getblong
, _do_putblong
, _do_getbshort
, _do_putbshort
, /* data */
444 _do_getblong
, _do_putblong
, _do_getbshort
, _do_putbshort
, /* hdrs */
447 srec_object_p
, /* bfd_check_format */
448 (struct bfd_target
*(*)()) bfd_nullvoidptr
,
449 (struct bfd_target
*(*)()) bfd_nullvoidptr
,
453 bfd_true
, /* mkobject */
454 _bfd_generic_mkarchive
,
457 (asymbol
* (*)()) bfd_nullvoidptr
, /* bfd_make_empty_symbol */
458 bfd_void
, /* bfd_prit_symbol */
459 (alent
*(*)())bfd_nullvoidptr
, /* srec_get_lineno,*/
460 srec_set_arch_mach
, /* bfd_set_arch_mach,*/
461 bfd_false
, /* write_armap*/
462 (bfd
*(*)())bfd_nullvoidptr
, /* openr_next_archived_file */
463 bfd_false
, /* bfd_find_nearest_line */