*** empty log message ***
[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
44 #include <sysdep.h>
45 #include "bfd.h"
46 #include "libbfd.h"
47
48
49 static 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
58 typedef 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 .. */
69 typedef 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
107
108 /*
109 called once per input srecord, used to work out vma and size of data.
110 */
111
112 static void
113 size_srec(abfd, section, address, raw, length)
114 bfd *abfd;
115 asection *section;
116 bfd_vma address;
117 byte_as_two_char_type *raw;
118 unsigned int length;
119 {
120 if (address < section->vma)
121 section->vma = address;
122
123 if (address + length > section->vma + section->size)
124 section->size = (address+length) - section->vma;
125 }
126
127 /*
128 called once per input srecord, copies data from input into bfd_alloc'd area
129 */
130
131 static void
132 fillup(abfd, section, address, raw, length)
133 bfd *abfd;
134 asection *section;
135 bfd_vma address;
136 byte_as_two_char_type *raw;
137 unsigned int length;
138 {
139 unsigned int i;
140 bfd_byte *dst = (bfd_byte *)(section->used_by_bfd) + address - section->vma;
141 for (i = 0; i < length; i++) {
142 *dst = HEX(raw);
143 dst++;
144 raw++;
145 }
146 }
147
148 /*
149 pass over an srecord file calling one of the above functions on each
150 record
151 */
152 static void
153 pass_over(abfd, func, section)
154 bfd *abfd;
155 void (*func)();
156 asection *section;
157 {
158 unsigned int bytes_on_line;
159 boolean eof = false;
160 bfd_vma address;
161 /* To the front of the file */
162 bfd_seek(abfd, (file_ptr)0, SEEK_SET);
163 while (eof == false)
164 {
165 srec_type buffer;
166
167 /* Find first 'S' */
168 eof = bfd_read(&buffer.S, 1, 1, abfd) != 1;
169 while (buffer.S != 'S' && !eof) {
170 eof = bfd_read(&buffer.S, 1, 1, abfd) != 1;
171 }
172 if (eof) break;
173
174 bfd_read(&buffer.type, 1, 3, abfd);
175
176 bytes_on_line = HEX(&buffer.size);
177
178 bfd_read((PTR)buffer.u.data, 1 , bytes_on_line * 2, abfd);
179
180 switch (buffer.type) {
181 case '6':
182 /* Prologue - ignore */
183 break;
184 case '3':
185 address = (HEX(buffer.u.type_3.address+0) << 24)
186 + (HEX(buffer.u.type_3.address+1) << 16)
187 + (HEX(buffer.u.type_3.address+2) << 8)
188 + (HEX(buffer.u.type_3.address+3));
189 func(abfd,section, address, buffer.u.type_2.data, bytes_on_line -1);
190
191 break;
192
193 case '2':
194 address = (HEX(buffer.u.type_2.address+0) << 16)+
195 (HEX(buffer.u.type_2.address+1) << 8) +
196 (HEX(buffer.u.type_2.address+2));
197 func(abfd,section, address, buffer.u.type_2.data, bytes_on_line -1);
198
199 break;
200 case '1':
201 address =
202 (HEX(buffer.u.type_1.address+0) << 8)
203 + (HEX(buffer.u.type_1.address+1));
204 func(abfd, section, address, buffer.u.type_1.data, bytes_on_line -1);
205 break;
206
207 }
208 }
209 }
210
211
212 bfd_target *
213 srec_object_p (abfd)
214 bfd *abfd;
215 {
216 char b;
217 asection *section;
218 bfd_seek(abfd, (file_ptr)0, SEEK_SET);
219 bfd_read(&b, 1,1,abfd);
220 if (b != 'S') return (bfd_target*)NULL;
221
222 /*
223 We create one section called data for all the contents,
224 and allocate enough room for the entire file
225 */
226
227
228 section = bfd_make_section(abfd, ".text");
229 section->size = 0;
230 section->vma = 0xffffffff;
231 pass_over(abfd, size_srec, section);
232
233 return abfd->xvec;
234 }
235
236
237
238
239
240
241
242
243 static boolean
244 srec_get_section_contents (abfd, section, location, offset, count)
245 bfd *abfd;
246 sec_ptr section;
247 void *location;
248 file_ptr offset;
249 unsigned int count;
250 {
251 if (section->used_by_bfd == (PTR)NULL) {
252 section->used_by_bfd = (PTR)bfd_alloc (abfd, section->size);
253 pass_over(abfd, fillup, section);
254 }
255 (void) memcpy(location, (bfd_byte *)(section->used_by_bfd) + offset, count);
256 return true;
257 }
258
259
260
261 boolean
262 srec_set_arch_mach (abfd, arch, machine)
263 bfd *abfd;
264 enum bfd_architecture arch;
265 unsigned long machine;
266 {
267 abfd->obj_arch = arch;
268 abfd->obj_machine = machine;
269 return true;
270 }
271
272
273
274 boolean
275 srec_set_section_contents (abfd, section, location, offset, bytes_to_do)
276 bfd *abfd;
277 sec_ptr section;
278 unsigned char *location;
279 file_ptr offset;
280 int bytes_to_do;
281 {
282 bfd_vma address;
283 int bytes_written;
284
285 int type;
286 unsigned int i;
287 srec_type buffer;
288 bytes_written = 0;
289 if (section->size <= 0xffff)
290 type = 1;
291 else if (section->size <= 0xffffff)
292 type = 2;
293 else
294 type = 3;
295
296 buffer.S = 'S';
297 buffer.type = '0' + type;
298
299 while (bytes_written < bytes_to_do) {
300 unsigned int size;
301 unsigned int check_sum;
302 byte_as_two_char_type *data;
303 unsigned int bytes_this_chunk = bytes_to_do - bytes_written;
304
305 if (bytes_this_chunk > CHUNK) {
306 bytes_this_chunk = CHUNK;
307 }
308
309 address = section->vma + offset + bytes_written;
310
311 switch (type) {
312 case 3:
313 check_sum = TOHEX(buffer.u.type_3.address, address >> 24);
314 check_sum += TOHEX(buffer.u.type_3.address+1, address >> 16);
315 check_sum += TOHEX(buffer.u.type_3.address+2, address >> 8);
316 check_sum += TOHEX(buffer.u.type_3.address+3, address >> 0);
317 size = bytes_this_chunk + 5;
318 data = buffer.u.type_3.data;
319
320 case 2:
321 check_sum = TOHEX(buffer.u.type_3.address, address >> 16);
322 check_sum += TOHEX(buffer.u.type_3.address+1, address >> 8);
323 check_sum += TOHEX(buffer.u.type_3.address+2, address >> 0);
324 size = bytes_this_chunk + 4;
325 data = buffer.u.type_2.data;
326 break;
327
328 case 1:
329 check_sum = TOHEX(buffer.u.type_3.address+0, address >> 8);
330 check_sum += TOHEX(buffer.u.type_3.address+1, address >> 0);
331 size = bytes_this_chunk + 3;
332 data = buffer.u.type_1.data;
333 }
334
335 for (i = 0; i < bytes_this_chunk; i++) {
336 check_sum += TOHEX(data, (location[i]));
337 data++;
338 }
339
340 check_sum += TOHEX(&(buffer.size), size );
341 (void) TOHEX(data, ~check_sum);
342 data++;
343
344 * ( (char *)(data)) = '\n';
345 bfd_write((PTR)&buffer, 1, (char *)data - (char *)&buffer + 1 , abfd);
346
347 bytes_written += bytes_this_chunk;
348 location += bytes_this_chunk;
349 }
350
351
352 return true;
353 }
354
355 boolean
356 srec_write_object_contents (abfd)
357 bfd *abfd;
358 {
359 bfd_write("S9030000FC\n", 1,11,abfd);
360 return true;
361 }
362
363 static int
364 DEFUN(srec_sizeof_headers,(abfd, exec),
365 bfd *abfd AND
366 boolean exec)
367 {
368 return 0;
369 }
370
371 /*SUPPRESS 460 */
372
373 #define srec_new_section_hook (PROTO(boolean, (*), (bfd *, asection *)))bfd_false
374 #define srec_get_symtab_upper_bound bfd_false
375 #define srec_get_symtab (PROTO(unsigned int, (*), (bfd *, asymbol **)))bfd_0
376 #define srec_get_reloc_upper_bound (PROTO(unsigned int, (*),(bfd*, asection *)))bfd_false
377 #define srec_canonicalize_reloc (PROTO(unsigned int, (*),(bfd*,asection *, arelent **, asymbol **))) bfd_0
378 #define srec_make_empty_symbol (PROTO(asymbol *,(*),(bfd*))) bfd_nullvoidptr
379 #define srec_print_symbol (PROTO(void,(*),(bfd *, PTR, asymbol *, bfd_print_symbol_enum_type))) bfd_void
380
381 #define srec_openr_next_archived_file (PROTO(bfd *, (*), (bfd*,bfd*))) bfd_nullvoidptr
382 #define srec_find_nearest_line (PROTO(boolean, (*),(bfd*,asection*,asymbol**,bfd_vma, CONST char**, CONST char**, unsigned int *))) bfd_false
383 #define srec_generic_stat_arch_elt (PROTO(int, (*), (bfd *,struct stat *))) bfd_0
384
385
386 #define srec_core_file_failing_command (char *(*)())(bfd_nullvoidptr)
387 #define srec_core_file_failing_signal (int (*)())bfd_0
388 #define srec_core_file_matches_executable_p (PROTO(boolean, (*),(bfd*, bfd*)))bfd_false
389 #define srec_slurp_armap bfd_true
390 #define srec_slurp_extended_name_table bfd_true
391 #define srec_truncate_arname (void (*)())bfd_nullvoidptr
392 #define srec_write_armap (PROTO( boolean, (*),(bfd *, unsigned int, struct orl *, int, int))) bfd_nullvoidptr
393 #define srec_get_lineno (struct lineno_cache_entry *(*)())bfd_nullvoidptr
394
395 #define srec_close_and_cleanup bfd_generic_close_and_cleanup
396
397
398 bfd_target srec_vec =
399 {
400 "srec", /* name */
401 bfd_target_srec_flavour_enum,
402 true, /* target byte order */
403 true, /* target headers byte order */
404 (HAS_RELOC | EXEC_P | /* object flags */
405 HAS_LINENO | HAS_DEBUG |
406 HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT | D_PAGED),
407 (SEC_CODE|SEC_DATA|SEC_ROM|SEC_HAS_CONTENTS
408 |SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
409 ' ', /* ar_pad_char */
410 16, /* ar_max_namelen */
411 _do_getb64, _do_putb64, _do_getb32, _do_putb32, _do_getb16, _do_putb16, /* data */
412 _do_getb64, _do_putb64, _do_getb32, _do_putb32, _do_getb16, _do_putb16, /* hdrs */
413
414 {_bfd_dummy_target,
415 srec_object_p, /* bfd_check_format */
416 (struct bfd_target *(*)()) bfd_nullvoidptr,
417 (struct bfd_target *(*)()) bfd_nullvoidptr,
418 },
419 {
420 bfd_false,
421 bfd_true, /* mkobject */
422 _bfd_generic_mkarchive,
423 bfd_false,
424 },
425 { /* bfd_write_contents */
426 bfd_false,
427 srec_write_object_contents,
428 _bfd_write_archive_contents,
429 bfd_false,
430 },
431 JUMP_TABLE(srec)
432 };