* oasys.c (oasys_write_object_contents): Lint.
[deliverable/binutils-gdb.git] / bfd / srec.c
CommitLineData
4a8db330
JG
1/* BFD back-end for s-record objects.
2 Copyright 1990, 1991, 1992 Free Software Foundation, Inc.
9898b929 3 Written by Steve Chamberlain of Cygnus Support <sac@cygnus.com>.
4a81b561 4
387cbb2b 5This file is part of BFD, the Binary File Descriptor library.
4a81b561 6
387cbb2b 7This program is free software; you can redistribute it and/or modify
4a81b561 8it under the terms of the GNU General Public License as published by
387cbb2b
JG
9the Free Software Foundation; either version 2 of the License, or
10(at your option) any later version.
4a81b561 11
387cbb2b 12This program is distributed in the hope that it will be useful,
4a81b561
DHW
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
387cbb2b
JG
18along with this program; if not, write to the Free Software
19Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
4a81b561 20
9898b929
JG
21/*
22SUBSECTION
23 S-record handling
4a81b561 24
9898b929
JG
25DESCRIPTION
26
27 S-records cannot hold anything but addresses and data, so
28 that's all that we implement.
29
30 The only interesting thing is that s-records may come out of
31 order and there is no header, so an initial scan is required
32 to discover the minimum and maximum addresses used to create
33 the vma and size of the only section we create. We
34 arbitrarily call this section ".text".
35
36 When bfd_get_section_contents is called the file is read
37 again, and this time the data is placed into a bfd_alloc'd
38 area.
39
40 Any number of sections may be created for output, we save them
41 up and output them when it's time to close the bfd.
42
43 An s record looks like:
44
45EXAMPLE
294eaca4 46 S<type><length><address><data><checksum>
9898b929
JG
47
48DESCRIPTION
49 Where
50 o length
51 is the number of bytes following upto the checksum. Note that
52 this is not the number of chars following, since it takes two
53 chars to represent a byte.
54 o type
55 is one of:
56 0) header record
57 1) two byte address data record
58 2) three byte address data record
59 3) four byte address data record
60 7) four byte address termination record
61 8) three byte address termination record
62 9) two byte address termination record
63
64 o address
65 is the start address of the data following, or in the case of
66 a termination record, the start address of the image
67 o data
68 is the data.
69 o checksum
70 is the sum of all the raw byte data in the record, from the length
71 upwards, modulo 256 and subtracted from 255.
72
73*/
7ed4093a 74
36773af5 75#include "bfd.h"
9898b929 76#include "sysdep.h"
4a81b561
DHW
77#include "libbfd.h"
78
5f9ca960 79/* Macros for converting between hex and binary */
4a81b561 80
3039e8ee 81static CONST char digs[] = "0123456789ABCDEF";
5f9ca960
JG
82
83static char hex_value[1 + (unsigned char)~0];
9898b929 84
9898b929 85#define NOT_HEX 20
5f9ca960 86#define NIBBLE(x) hex_value[(unsigned char)(x)]
9898b929 87#define HEX(buffer) ((NIBBLE((buffer)[0])<<4) + NIBBLE((buffer)[1]))
5f9ca960
JG
88#define TOHEX(d, x, ch) \
89 d[1] = digs[(x) & 0xf]; \
90 d[0] = digs[((x)>>4)&0xf]; \
91 ch += ((x) & 0xff);
92#define ISHEX(x) (hex_value[(unsigned char)(x)] != NOT_HEX)
4a81b561 93
4a81b561 94
9898b929 95
e98e6ec1 96static void
9898b929
JG
97DEFUN_VOID(srec_init)
98{
99 unsigned int i;
100 static boolean inited = false;
101
102 if (inited == false)
103 {
104
105 inited = true;
106
5f9ca960 107 for (i = 0; i < sizeof (hex_value); i++)
9898b929
JG
108 {
109 hex_value[i] = NOT_HEX;
110 }
111
112 for (i = 0; i < 10; i++)
113 {
114 hex_value[i + '0'] = i;
115
116 }
117 for (i = 0; i < 6; i++)
118 {
119 hex_value[i + 'a'] = i+10;
120 hex_value[i + 'A'] = i+10;
121 }
122 }
123}
124
4a81b561
DHW
125
126/* The maximum number of bytes on a line is FF */
127#define MAXCHUNK 0xff
128/* The number of bytes we fit onto a line on output */
9898b929
JG
129#define CHUNK 21
130
131/* We cannot output our srecords as we see them, we have to glue them
132 together, this is done in this structure : */
133
134struct srec_data_list_struct
135{
136 unsigned char *data;
137 bfd_vma where;
138 bfd_size_type size;
139 struct srec_data_list_struct *next;
140
141} ;
142typedef struct srec_data_list_struct srec_data_list_type;
143
4a81b561 144
e98e6ec1 145typedef struct srec_data_struct
4a81b561 146{
9898b929
JG
147 srec_data_list_type *head;
148 unsigned int type;
149
150} tdata_type;
151
152
4a81b561 153
357a1f38 154#define enda(x) (x->vma + x->size)
4a81b561 155/*
387cbb2b 156 called once per input s-record, used to work out vma and size of data.
4a81b561
DHW
157 */
158
357a1f38 159static bfd_vma low,high;
9898b929 160
4a81b561 161static void
9898b929
JG
162DEFUN(size_srec,(abfd, section, address, raw, length),
163 bfd *abfd AND
164 asection *section AND
165 bfd_vma address AND
166 bfd_byte *raw AND
167 unsigned int length)
4a81b561 168{
357a1f38
SC
169 if (address < low)
170 low = address;
171 if (address + length > high)
9898b929 172 high = address + length -1;
4a81b561
DHW
173}
174
357a1f38 175
4a81b561 176/*
387cbb2b 177 called once per input s-record, copies data from input into bfd_alloc'd area
4a81b561
DHW
178 */
179
180static void
9898b929
JG
181DEFUN(fillup,(abfd, section, address, raw, length),
182bfd *abfd AND
183asection *section AND
184bfd_vma address AND
185bfd_byte *raw AND
186unsigned int length)
4a81b561 187{
9898b929
JG
188 unsigned int i;
189 bfd_byte *dst =
190 (bfd_byte *)(section->used_by_bfd) +
191 address - section->vma;
192 /* length -1 because we don't read in the checksum */
193 for (i = 0; i < length -1 ; i++) {
194 *dst = HEX(raw);
195 dst++;
196 raw+=2;
197 }
4a81b561
DHW
198}
199
387cbb2b
JG
200/* Pass over an s-record file, calling one of the above functions on each
201 record. */
202
4a81b561 203static void
9898b929
JG
204DEFUN(pass_over,(abfd, func, section),
205 bfd *abfd AND
206 void (*func)() AND
207 asection *section)
4a81b561 208{
9898b929
JG
209 unsigned int bytes_on_line;
210 boolean eof = false;
e98e6ec1 211
9898b929
JG
212 /* To the front of the file */
213 bfd_seek(abfd, (file_ptr)0, SEEK_SET);
214 while (eof == false)
4a81b561 215 {
9898b929
JG
216 char buffer[MAXCHUNK];
217 char *src = buffer;
218 char type;
219 bfd_vma address = 0;
220
221 /* Find first 'S' */
222 eof = (boolean)(bfd_read(src, 1, 1, abfd) != 1);
223 while (*src!= 'S' && !eof) {
224 eof = (boolean)(bfd_read(src, 1, 1, abfd) != 1);
225 }
226 if (eof) break;
227 src++;
228
229 /* Fetch the type and the length */
230 bfd_read(src, 1, 3, abfd);
231
232 type = *src++;
233
234 if (!ISHEX (src[0]) || !ISHEX (src[1]))
235 break;
236
237 bytes_on_line = HEX(src);
238
239 if (bytes_on_line > MAXCHUNK/2)
240 break;
241 src+=2 ;
242
243 bfd_read(src, 1 , bytes_on_line * 2, abfd);
244
245 switch (type) {
246 case '0':
247 case '5':
248 /* Prologue - ignore */
249 break;
250 case '3':
251 address = HEX(src);
252 src+=2;
253 bytes_on_line--;
254
255 case '2':
256 address = HEX(src) | (address<<8) ;
257 src+=2;
258 bytes_on_line--;
259 case '1':
260 address = HEX(src) | (address<<8) ;
261 src+=2;
262 address = HEX(src) | (address<<8) ;
263 src+=2;
264 bytes_on_line-=2;
265 func(abfd,section, address, src, bytes_on_line);
266 break;
267 default:
268 return;
269 }
4a81b561 270 }
9898b929 271
4a81b561
DHW
272}
273
274
9898b929
JG
275
276static bfd_target *
277DEFUN(srec_object_p, (abfd),
278 bfd *abfd)
4a81b561 279{
387cbb2b 280 char b[4];
4a81b561 281 asection *section;
9898b929
JG
282 srec_init();
283
4a81b561 284 bfd_seek(abfd, (file_ptr)0, SEEK_SET);
387cbb2b 285 bfd_read(b, 1, 4, abfd);
9898b929 286
387cbb2b
JG
287 if (b[0] != 'S' || !ISHEX(b[1]) || !ISHEX(b[2]) || !ISHEX(b[3]))
288 return (bfd_target*) NULL;
289
290 /* We create one section called .text for all the contents,
291 and allocate enough room for the entire file. */
4a81b561
DHW
292
293 section = bfd_make_section(abfd, ".text");
e98e6ec1 294 section->_raw_size = 0;
4a81b561 295 section->vma = 0xffffffff;
357a1f38
SC
296 low = 0xffffffff;
297 high = 0;
4a81b561 298 pass_over(abfd, size_srec, section);
e98e6ec1 299 section->_raw_size = high - low;
357a1f38 300 section->vma = low;
9898b929
JG
301 section->flags = SEC_HAS_CONTENTS | SEC_LOAD | SEC_ALLOC;
302
4a81b561
DHW
303 return abfd->xvec;
304}
305
306
4a81b561 307static boolean
9898b929
JG
308DEFUN(srec_get_section_contents,(abfd, section, location, offset, count),
309 bfd *abfd AND
310 asection *section AND
311 PTR location AND
312 file_ptr offset AND
313 bfd_size_type count)
4a81b561 314{
9898b929
JG
315 if (section->used_by_bfd == (PTR)NULL)
316 {
e98e6ec1 317 section->used_by_bfd = (PTR)bfd_alloc (abfd, section->_raw_size);
9898b929
JG
318 pass_over(abfd, fillup, section);
319 }
320 (void) memcpy((PTR)location,
321 (PTR)((char *)(section->used_by_bfd) + offset),
322 count);
323 return true;
4a81b561
DHW
324}
325
326
327
328boolean
9898b929
JG
329DEFUN(srec_set_arch_mach,(abfd, arch, machine),
330 bfd *abfd AND
331 enum bfd_architecture arch AND
332 unsigned long machine)
4a81b561 333{
9898b929 334 return bfd_default_set_arch_mach(abfd, arch, machine);
4a81b561
DHW
335}
336
337
9898b929
JG
338/* we have to save up all the Srecords for a splurge before output,
339 also remember */
4a81b561 340
9898b929
JG
341static boolean
342DEFUN(srec_set_section_contents,(abfd, section, location, offset, bytes_to_do),
343 bfd *abfd AND
344 sec_ptr section AND
345 PTR location AND
346 file_ptr offset AND
347 bfd_size_type bytes_to_do)
4a81b561 348{
294eaca4
SC
349 tdata_type *tdata = abfd->tdata.srec_data;
350 srec_data_list_type *entry = (srec_data_list_type *)
351 bfd_alloc(abfd, sizeof(srec_data_list_type));
352 if ((section->flags & SEC_ALLOC)
353 && (section->flags & SEC_LOAD))
354 {
9898b929
JG
355 unsigned char *data = (unsigned char *) bfd_alloc(abfd, bytes_to_do);
356 memcpy(data, location, bytes_to_do);
357
358 if ((section->vma + offset + bytes_to_do) <= 0xffff)
359 {
360
361 }
362 else if ((section->vma + offset + bytes_to_do) <= 0xffffff
363 && tdata->type < 2)
364 {
294eaca4 365 tdata->type = 2;
4a81b561 366 }
9898b929
JG
367 else
368 {
294eaca4 369 tdata->type = 3;
9898b929
JG
370 }
371
372 entry->data = data;
373 entry->where = section->vma + offset;
374 entry->size = bytes_to_do;
375 entry->next = tdata->head;
376 tdata->head = entry;
294eaca4
SC
377 }
378 return true;
9898b929
JG
379}
380
381/* Write a record of type, of the supplied number of bytes. The
382 supplied bytes and length don't have a checksum. That's worked out
383 here
384*/
385static
386void DEFUN(srec_write_record,(abfd, type, address, data, end),
387 bfd *abfd AND
388 char type AND
389 bfd_vma address AND
390 CONST unsigned char *data AND
391 CONST unsigned char *end)
392
393{
394 char buffer[MAXCHUNK];
395
396 unsigned int check_sum = 0;
397 unsigned CONST char *src = data;
398 char *dst =buffer;
399 char *length;
400
401
402 *dst++ = 'S';
403 *dst++ = '0' + type;
404
405 length = dst;
406 dst+=2; /* leave room for dst*/
407
408 switch (type)
409 {
410 case 3:
411 case 7:
412 TOHEX(dst, (address >> 24), check_sum);
413 dst+=2;
414 case 8:
415 case 2:
416 TOHEX(dst, (address >> 16), check_sum);
417 dst+=2;
418 case 9:
419 case 1:
420 case 0:
421 TOHEX(dst, (address >> 8), check_sum);
422 dst+=2;
423 TOHEX(dst, (address), check_sum);
424 dst+=2;
425 break;
4a81b561 426
4a81b561 427 }
9898b929
JG
428 for (src = data; src < end; src++)
429 {
430 TOHEX(dst, *src, check_sum);
431 dst+=2;
4a81b561
DHW
432 }
433
9898b929
JG
434 /* Fill in the length */
435 TOHEX(length, (dst - length)/2, check_sum);
436 check_sum &= 0xff;
437 check_sum = 255 - check_sum;
438 TOHEX(dst, check_sum, check_sum);
439 dst+=2;
440
3039e8ee 441 *dst ++ = '\r';
9898b929
JG
442 *dst ++ = '\n';
443 bfd_write((PTR)buffer, 1, dst - buffer , abfd);
444}
4a81b561 445
4a81b561 446
4a81b561 447
9898b929
JG
448static void
449DEFUN(srec_write_header,(abfd),
450 bfd *abfd)
451{
452 unsigned char buffer[MAXCHUNK];
453 unsigned char *dst = buffer;
454 unsigned int i;
4a81b561 455
9898b929
JG
456 /* I'll put an arbitary 40 char limit on header size */
457 for (i = 0; i < 40 && abfd->filename[i]; i++)
458 {
459 *dst++ = abfd->filename[i];
460 }
461 srec_write_record(abfd,0, 0, buffer, dst);
4a81b561
DHW
462}
463
9898b929
JG
464static void
465DEFUN(srec_write_section,(abfd, tdata, list),
466 bfd *abfd AND
467 tdata_type *tdata AND
468 srec_data_list_type *list)
469{
470 unsigned int bytes_written = 0;
471 unsigned char *location = list->data;
472
473 while (bytes_written < list->size)
474 {
9898b929 475 bfd_vma address;
9898b929
JG
476
477 unsigned int bytes_this_chunk = list->size - bytes_written;
478
479 if (bytes_this_chunk > CHUNK)
480 {
481 bytes_this_chunk = CHUNK;
482 }
483
484 address = list->where + bytes_written;
485
486 srec_write_record(abfd,
487 tdata->type,
488 address,
489 location,
490 location + bytes_this_chunk);
491
492 bytes_written += bytes_this_chunk;
493 location += bytes_this_chunk;
494 }
495
496}
497
498static void
499DEFUN(srec_write_terminator,(abfd, tdata),
500 bfd *abfd AND
501 tdata_type *tdata)
502{
503 unsigned char buffer[2];
504
505 srec_write_record(abfd, 10 - tdata->type,
506 abfd->start_address, buffer, buffer);
9898b929 507}
3039e8ee 508
9898b929
JG
509static boolean
510DEFUN(srec_mkobject, (abfd),
511 bfd *abfd)
512{
513 tdata_type *tdata = (tdata_type *)bfd_alloc(abfd, sizeof(tdata_type));
e98e6ec1 514 abfd->tdata.srec_data = tdata;
9898b929
JG
515 tdata->type = 1;
516 tdata->head = (srec_data_list_type *)NULL;
517 return true;
518
519}
520
521
522static boolean
523DEFUN(srec_write_object_contents,(abfd),
524 bfd *abfd)
4a81b561 525{
9898b929 526 int bytes_written;
e98e6ec1 527 tdata_type *tdata = abfd->tdata.srec_data;
9898b929
JG
528 srec_data_list_type *list;
529
530 bytes_written = 0;
531
532
533
534 srec_write_header(abfd);
535
536 /* Now wander though all the sections provided and output them */
537 list = tdata->head;
538
539 while (list != (srec_data_list_type*)NULL)
540 {
541 srec_write_section(abfd, tdata, list);
542 list = list->next;
543 }
544 srec_write_terminator(abfd, tdata);
545 return true;
4a81b561
DHW
546}
547
39a2ce33 548static int
7ed4093a
SC
549DEFUN(srec_sizeof_headers,(abfd, exec),
550 bfd *abfd AND
551 boolean exec)
39a2ce33
SC
552{
553return 0;
554}
555
357a1f38
SC
556static asymbol *
557DEFUN(srec_make_empty_symbol, (abfd),
558 bfd*abfd)
559{
560 asymbol *new= (asymbol *)bfd_zalloc (abfd, sizeof (asymbol));
561 new->the_bfd = abfd;
562 return new;
563}
6f715d66
SC
564#define FOO PROTO
565#define srec_new_section_hook (FOO(boolean, (*), (bfd *, asection *)))bfd_true
387cbb2b 566#define srec_get_symtab_upper_bound (PROTO(unsigned int, (*),(bfd *)))bfd_false
6f715d66
SC
567#define srec_get_symtab (FOO(unsigned int, (*), (bfd *, asymbol **)))bfd_0
568#define srec_get_reloc_upper_bound (FOO(unsigned int, (*),(bfd*, asection *)))bfd_false
569#define srec_canonicalize_reloc (FOO(unsigned int, (*),(bfd*,asection *, arelent **, asymbol **))) bfd_0
357a1f38 570
9898b929 571#define srec_print_symbol (FOO(void,(*),(bfd *, PTR, asymbol *, bfd_print_symbol_type))) bfd_void
d0ec7a8e 572
6f715d66
SC
573#define srec_openr_next_archived_file (FOO(bfd *, (*), (bfd*,bfd*))) bfd_nullvoidptr
574#define srec_find_nearest_line (FOO(boolean, (*),(bfd*,asection*,asymbol**,bfd_vma, CONST char**, CONST char**, unsigned int *))) bfd_false
575#define srec_generic_stat_arch_elt (FOO(int, (*), (bfd *,struct stat *))) bfd_0
9872a49c 576
d0ec7a8e
SC
577
578#define srec_core_file_failing_command (char *(*)())(bfd_nullvoidptr)
579#define srec_core_file_failing_signal (int (*)())bfd_0
6f715d66 580#define srec_core_file_matches_executable_p (FOO(boolean, (*),(bfd*, bfd*)))bfd_false
d0ec7a8e
SC
581#define srec_slurp_armap bfd_true
582#define srec_slurp_extended_name_table bfd_true
583#define srec_truncate_arname (void (*)())bfd_nullvoidptr
9898b929 584#define srec_write_armap (FOO( boolean, (*),(bfd *, unsigned int, struct orl *, unsigned int, int))) bfd_nullvoidptr
d0ec7a8e 585#define srec_get_lineno (struct lineno_cache_entry *(*)())bfd_nullvoidptr
2b1d8a50 586#define srec_close_and_cleanup bfd_generic_close_and_cleanup
6f715d66
SC
587#define srec_bfd_debug_info_start bfd_void
588#define srec_bfd_debug_info_end bfd_void
589#define srec_bfd_debug_info_accumulate (FOO(void, (*), (bfd *, asection *))) bfd_void
e98e6ec1 590#define srec_bfd_get_relocated_section_contents bfd_generic_get_relocated_section_contents
294eaca4 591#define srec_bfd_relax_section bfd_generic_relax_section
3039e8ee
JG
592#define srec_bfd_seclet_link bfd_generic_seclet_link
593
4a81b561
DHW
594bfd_target srec_vec =
595{
9898b929
JG
596 "srec", /* name */
597 bfd_target_srec_flavour,
598 true, /* target byte order */
599 true, /* target headers byte order */
600 (HAS_RELOC | EXEC_P | /* object flags */
601 HAS_LINENO | HAS_DEBUG |
602 HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT | D_PAGED),
603 (SEC_CODE|SEC_DATA|SEC_ROM|SEC_HAS_CONTENTS
604 |SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
294eaca4 605 0, /* leading underscore */
9898b929
JG
606 ' ', /* ar_pad_char */
607 16, /* ar_max_namelen */
6f715d66 608 1, /* minimum alignment */
9898b929
JG
609 _do_getb64, _do_putb64, _do_getb32,
610 _do_putb32, _do_getb16, _do_putb16, /* data */
611 _do_getb64, _do_putb64, _do_getb32,
612 _do_putb32, _do_getb16, _do_putb16, /* hdrs */
613
614 {
615 _bfd_dummy_target,
616 srec_object_p, /* bfd_check_format */
617 (struct bfd_target *(*)()) bfd_nullvoidptr,
618 (struct bfd_target *(*)()) bfd_nullvoidptr,
619 },
620 {
7ed4093a 621 bfd_false,
9898b929 622 srec_mkobject,
7ed4093a
SC
623 _bfd_generic_mkarchive,
624 bfd_false,
9898b929
JG
625 },
626 { /* bfd_write_contents */
7ed4093a
SC
627 bfd_false,
628 srec_write_object_contents,
629 _bfd_write_archive_contents,
630 bfd_false,
9898b929
JG
631 },
632 JUMP_TABLE(srec)
633 };
634
This page took 0.089021 seconds and 4 git commands to generate.