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