Initial revision
[deliverable/binutils-gdb.git] / bfd / srec.c
CommitLineData
4a81b561
DHW
1/* Copyright (C) 1990, 1991 Free Software Foundation, Inc.
2
3This file is part of BFD, the Binary File Diddler.
4
5BFD is free software; you can redistribute it and/or modify
6it under the terms of the GNU General Public License as published by
7the Free Software Foundation; either version 1, or (at your option)
8any later version.
9
10BFD is distributed in the hope that it will be useful,
11but WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with BFD; see the file COPYING. If not, write to
17the 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
2b1d8a50 32 this time the data is placed into a bfd_alloc'd area.
4a81b561
DHW
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
7ed4093a
SC
43
44#include <sysdep.h>
36773af5 45#include "bfd.h"
4a81b561
DHW
46#include "libbfd.h"
47
48
49static char digs[] = "0123456789ABCDEF";
50
51/* Macros for converting between hex and binary */
52
53#define NIBBLE(x) ((x >= '0' && x <= '9') ? (x - '0') : (x - 'A' + 10))
54#define HEX(buffer) ((NIBBLE((buffer)->high) <<4) + NIBBLE((buffer)->low))
55#define TOHEX(d,x) \
56 ((d)->low = digs[(x) & 0xf], (d)->high = digs[((x)>>4)&0xf], x)
57
58typedef struct {
59 char high;
60 char low;
61} byte_as_two_char_type;
62
63/* The maximum number of bytes on a line is FF */
64#define MAXCHUNK 0xff
65/* The number of bytes we fit onto a line on output */
66#define CHUNK 16
67
68/* The shape of an srecord .. */
69typedef struct
70{
71 char S;
72 char type;
73 byte_as_two_char_type size;
74 union {
75 struct {
76 byte_as_two_char_type address[4];
77 byte_as_two_char_type data[MAXCHUNK];
78 /* If there isn't MAXCHUNK bytes of data then the checksum will
79 appear earlier */
80 byte_as_two_char_type checksum;
81 char nl;
82 } type_3;
83 struct {
84 byte_as_two_char_type address[4];
85 byte_as_two_char_type data[MAXCHUNK];
86 byte_as_two_char_type checksum;
87 char nl;
88 } type_6;
89
90 struct {
91 byte_as_two_char_type address[3];
92 byte_as_two_char_type data[MAXCHUNK];
93 byte_as_two_char_type checksum;
94 char nl;
95 } type_2;
96
97 struct {
98 byte_as_two_char_type address[2];
99 byte_as_two_char_type data[MAXCHUNK];
100 byte_as_two_char_type checksum;
101 char nl;
102 } type_1;
103 byte_as_two_char_type data[MAXCHUNK];
104 } u;
105} srec_type;
106
357a1f38 107#define enda(x) (x->vma + x->size)
4a81b561
DHW
108/*
109 called once per input srecord, used to work out vma and size of data.
110 */
111
357a1f38 112static bfd_vma low,high;
4a81b561
DHW
113static void
114size_srec(abfd, section, address, raw, length)
115bfd *abfd;
116asection *section;
117bfd_vma address;
118byte_as_two_char_type *raw;
119unsigned int length;
120{
357a1f38
SC
121 if (address < low)
122 low = address;
123 if (address + length > high)
124 high = address + length;
4a81b561
DHW
125}
126
357a1f38 127
4a81b561 128/*
2b1d8a50 129 called once per input srecord, copies data from input into bfd_alloc'd area
4a81b561
DHW
130 */
131
132static void
133fillup(abfd, section, address, raw, length)
134bfd *abfd;
135asection *section;
136bfd_vma address;
137byte_as_two_char_type *raw;
138unsigned int length;
139{
140 unsigned int i;
141 bfd_byte *dst = (bfd_byte *)(section->used_by_bfd) + address - section->vma;
142 for (i = 0; i < length; i++) {
143 *dst = HEX(raw);
144 dst++;
145 raw++;
146 }
147}
148
149/*
150 pass over an srecord file calling one of the above functions on each
151 record
152 */
153static void
154pass_over(abfd, func, section)
155bfd *abfd;
156void (*func)();
157asection *section;
158{
159 unsigned int bytes_on_line;
160 boolean eof = false;
161 bfd_vma address;
162 /* To the front of the file */
163 bfd_seek(abfd, (file_ptr)0, SEEK_SET);
164 while (eof == false)
165 {
166 srec_type buffer;
167
168 /* Find first 'S' */
169 eof = bfd_read(&buffer.S, 1, 1, abfd) != 1;
170 while (buffer.S != 'S' && !eof) {
171 eof = bfd_read(&buffer.S, 1, 1, abfd) != 1;
172 }
173 if (eof) break;
174
175 bfd_read(&buffer.type, 1, 3, abfd);
176
177 bytes_on_line = HEX(&buffer.size);
178
d0ec7a8e 179 bfd_read((PTR)buffer.u.data, 1 , bytes_on_line * 2, abfd);
4a81b561
DHW
180
181 switch (buffer.type) {
182 case '6':
183 /* Prologue - ignore */
184 break;
185 case '3':
186 address = (HEX(buffer.u.type_3.address+0) << 24)
187 + (HEX(buffer.u.type_3.address+1) << 16)
188 + (HEX(buffer.u.type_3.address+2) << 8)
189 + (HEX(buffer.u.type_3.address+3));
190 func(abfd,section, address, buffer.u.type_2.data, bytes_on_line -1);
191
192 break;
193
194 case '2':
195 address = (HEX(buffer.u.type_2.address+0) << 16)+
196 (HEX(buffer.u.type_2.address+1) << 8) +
197 (HEX(buffer.u.type_2.address+2));
198 func(abfd,section, address, buffer.u.type_2.data, bytes_on_line -1);
199
200 break;
201 case '1':
202 address =
203 (HEX(buffer.u.type_1.address+0) << 8)
204 + (HEX(buffer.u.type_1.address+1));
205 func(abfd, section, address, buffer.u.type_1.data, bytes_on_line -1);
206 break;
207
208 }
209 }
210}
211
212
213bfd_target *
214srec_object_p (abfd)
215bfd *abfd;
216{
217 char b;
218 asection *section;
219 bfd_seek(abfd, (file_ptr)0, SEEK_SET);
220 bfd_read(&b, 1,1,abfd);
221 if (b != 'S') return (bfd_target*)NULL;
222
223 /*
224 We create one section called data for all the contents,
225 and allocate enough room for the entire file
226 */
227
228
229 section = bfd_make_section(abfd, ".text");
230 section->size = 0;
231 section->vma = 0xffffffff;
357a1f38
SC
232 low = 0xffffffff;
233 high = 0;
4a81b561 234 pass_over(abfd, size_srec, section);
357a1f38
SC
235 section->size = high - low;
236 section->vma = low;
4a81b561
DHW
237 return abfd->xvec;
238}
239
240
241
242
243
244
245
246
247static boolean
248srec_get_section_contents (abfd, section, location, offset, count)
249bfd *abfd;
250sec_ptr section;
251void *location;
252file_ptr offset;
253unsigned int count;
254{
a6ac0c59 255 if (section->used_by_bfd == (PTR)NULL) {
2b1d8a50 256 section->used_by_bfd = (PTR)bfd_alloc (abfd, section->size);
4a81b561
DHW
257 pass_over(abfd, fillup, section);
258 }
259 (void) memcpy(location, (bfd_byte *)(section->used_by_bfd) + offset, count);
260 return true;
261}
262
263
264
265boolean
266srec_set_arch_mach (abfd, arch, machine)
267bfd *abfd;
268enum bfd_architecture arch;
269unsigned long machine;
270{
271 abfd->obj_arch = arch;
272 abfd->obj_machine = machine;
273 return true;
274}
275
276
277
278boolean
279srec_set_section_contents (abfd, section, location, offset, bytes_to_do)
280bfd *abfd;
281sec_ptr section;
282unsigned char *location;
283file_ptr offset;
284int bytes_to_do;
285{
286 bfd_vma address;
287 int bytes_written;
288
289 int type;
290 unsigned int i;
291 srec_type buffer;
292 bytes_written = 0;
357a1f38 293 if (section->vma <= 0xffff)
4a81b561 294 type = 1;
357a1f38 295 else if (section->vma <= 0xffffff)
4a81b561
DHW
296 type = 2;
297 else
298 type = 3;
299
300 buffer.S = 'S';
301 buffer.type = '0' + type;
302
303 while (bytes_written < bytes_to_do) {
304 unsigned int size;
305 unsigned int check_sum;
306 byte_as_two_char_type *data;
36773af5 307 unsigned int bytes_this_chunk = bytes_to_do - bytes_written;
4a81b561
DHW
308
309 if (bytes_this_chunk > CHUNK) {
310 bytes_this_chunk = CHUNK;
311 }
312
313 address = section->vma + offset + bytes_written;
314
315 switch (type) {
316 case 3:
317 check_sum = TOHEX(buffer.u.type_3.address, address >> 24);
318 check_sum += TOHEX(buffer.u.type_3.address+1, address >> 16);
319 check_sum += TOHEX(buffer.u.type_3.address+2, address >> 8);
320 check_sum += TOHEX(buffer.u.type_3.address+3, address >> 0);
321 size = bytes_this_chunk + 5;
322 data = buffer.u.type_3.data;
323
324 case 2:
325 check_sum = TOHEX(buffer.u.type_3.address, address >> 16);
326 check_sum += TOHEX(buffer.u.type_3.address+1, address >> 8);
327 check_sum += TOHEX(buffer.u.type_3.address+2, address >> 0);
328 size = bytes_this_chunk + 4;
329 data = buffer.u.type_2.data;
330 break;
331
332 case 1:
333 check_sum = TOHEX(buffer.u.type_3.address+0, address >> 8);
334 check_sum += TOHEX(buffer.u.type_3.address+1, address >> 0);
335 size = bytes_this_chunk + 3;
336 data = buffer.u.type_1.data;
337 }
338
339 for (i = 0; i < bytes_this_chunk; i++) {
340 check_sum += TOHEX(data, (location[i]));
341 data++;
342 }
343
344 check_sum += TOHEX(&(buffer.size), size );
345 (void) TOHEX(data, ~check_sum);
346 data++;
347
348 * ( (char *)(data)) = '\n';
d0ec7a8e 349 bfd_write((PTR)&buffer, 1, (char *)data - (char *)&buffer + 1 , abfd);
4a81b561
DHW
350
351 bytes_written += bytes_this_chunk;
352 location += bytes_this_chunk;
353 }
354
355
356 return true;
357}
358
4a81b561 359boolean
2b1d8a50
JG
360srec_write_object_contents (abfd)
361 bfd *abfd;
4a81b561 362{
2b1d8a50 363 bfd_write("S9030000FC\n", 1,11,abfd);
7ed4093a 364 return true;
4a81b561
DHW
365}
366
39a2ce33 367static int
7ed4093a
SC
368DEFUN(srec_sizeof_headers,(abfd, exec),
369 bfd *abfd AND
370 boolean exec)
39a2ce33
SC
371{
372return 0;
373}
374
357a1f38
SC
375static asymbol *
376DEFUN(srec_make_empty_symbol, (abfd),
377 bfd*abfd)
378{
379 asymbol *new= (asymbol *)bfd_zalloc (abfd, sizeof (asymbol));
380 new->the_bfd = abfd;
381 return new;
382}
4a81b561 383/*SUPPRESS 460 */
d0ec7a8e 384
357a1f38 385#define srec_new_section_hook (PROTO(boolean, (*), (bfd *, asection *)))bfd_true
9872a49c 386#define srec_get_symtab_upper_bound bfd_false
7ed4093a
SC
387#define srec_get_symtab (PROTO(unsigned int, (*), (bfd *, asymbol **)))bfd_0
388#define srec_get_reloc_upper_bound (PROTO(unsigned int, (*),(bfd*, asection *)))bfd_false
389#define srec_canonicalize_reloc (PROTO(unsigned int, (*),(bfd*,asection *, arelent **, asymbol **))) bfd_0
357a1f38 390
7ed4093a 391#define srec_print_symbol (PROTO(void,(*),(bfd *, PTR, asymbol *, bfd_print_symbol_enum_type))) bfd_void
d0ec7a8e 392
7ed4093a
SC
393#define srec_openr_next_archived_file (PROTO(bfd *, (*), (bfd*,bfd*))) bfd_nullvoidptr
394#define srec_find_nearest_line (PROTO(boolean, (*),(bfd*,asection*,asymbol**,bfd_vma, CONST char**, CONST char**, unsigned int *))) bfd_false
395#define srec_generic_stat_arch_elt (PROTO(int, (*), (bfd *,struct stat *))) bfd_0
9872a49c 396
d0ec7a8e
SC
397
398#define srec_core_file_failing_command (char *(*)())(bfd_nullvoidptr)
399#define srec_core_file_failing_signal (int (*)())bfd_0
400#define srec_core_file_matches_executable_p (PROTO(boolean, (*),(bfd*, bfd*)))bfd_false
401#define srec_slurp_armap bfd_true
402#define srec_slurp_extended_name_table bfd_true
403#define srec_truncate_arname (void (*)())bfd_nullvoidptr
404#define srec_write_armap (PROTO( boolean, (*),(bfd *, unsigned int, struct orl *, int, int))) bfd_nullvoidptr
405#define srec_get_lineno (struct lineno_cache_entry *(*)())bfd_nullvoidptr
406
2b1d8a50
JG
407#define srec_close_and_cleanup bfd_generic_close_and_cleanup
408
d0ec7a8e 409
4a81b561
DHW
410bfd_target srec_vec =
411{
412 "srec", /* name */
413 bfd_target_srec_flavour_enum,
414 true, /* target byte order */
415 true, /* target headers byte order */
416 (HAS_RELOC | EXEC_P | /* object flags */
417 HAS_LINENO | HAS_DEBUG |
418 HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT | D_PAGED),
9872a49c 419 (SEC_CODE|SEC_DATA|SEC_ROM|SEC_HAS_CONTENTS
4a81b561 420 |SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
4a81b561
DHW
421 ' ', /* ar_pad_char */
422 16, /* ar_max_namelen */
7ed4093a
SC
423 _do_getb64, _do_putb64, _do_getb32, _do_putb32, _do_getb16, _do_putb16, /* data */
424 _do_getb64, _do_putb64, _do_getb32, _do_putb32, _do_getb16, _do_putb16, /* hdrs */
425
426 {_bfd_dummy_target,
427 srec_object_p, /* bfd_check_format */
428 (struct bfd_target *(*)()) bfd_nullvoidptr,
429 (struct bfd_target *(*)()) bfd_nullvoidptr,
430 },
431 {
432 bfd_false,
433 bfd_true, /* mkobject */
434 _bfd_generic_mkarchive,
435 bfd_false,
436 },
437 { /* bfd_write_contents */
438 bfd_false,
439 srec_write_object_contents,
440 _bfd_write_archive_contents,
441 bfd_false,
442 },
2b1d8a50 443 JUMP_TABLE(srec)
7ed4093a 444 };
This page took 0.049642 seconds and 4 git commands to generate.