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