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