* ser-tcp.c (tcp_open): Cast to struct sockaddr when passing to
[deliverable/binutils-gdb.git] / bfd / srec.c
CommitLineData
4a8db330 1/* BFD back-end for s-record objects.
9783e04a 2 Copyright 1990, 1991, 1992, 1993, 1994 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
8f8fefcc 23 S-Record handling
4a81b561 24
9898b929
JG
25DESCRIPTION
26
8f8fefcc
JG
27 Ordinary S-Records cannot hold anything but addresses and
28 data, so that's all that we implement.
9783e04a 29
8f8fefcc 30 The only interesting thing is that S-Records may come out of
9898b929
JG
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
9783e04a 34 arbitrarily call this section ".text".
9898b929
JG
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.
8f8fefcc
JG
72
73
74SUBSECTION
75 Symbol S-Record handling
76
77DESCRIPTION
78 Some ICE equipment understands an addition to the standard
79 S-Record format; symbols and their addresses can be sent
80 before the data.
81
82 The format of this is:
83 ($$ <modulename>
84 (<space> <symbol> <address>)*)
85 $$
86
87 so a short symbol table could look like:
88
89EXAMPLE
90 $$ flash.x
91 $$ flash.c
92 _port6 $0
93 _delay $4
94 _start $14
95 _etext $8036
96 _edata $8036
97 _end $8036
9783e04a 98 $$
8f8fefcc
JG
99
100DESCRIPTION
101 We allow symbols to be anywhere in the data stream - the module names
102 are always ignored.
103
9898b929 104*/
7ed4093a 105
36773af5 106#include "bfd.h"
9898b929 107#include "sysdep.h"
4a81b561
DHW
108#include "libbfd.h"
109
6d4f7715
ILT
110static boolean srec_write_record PARAMS ((bfd *, int, bfd_vma,
111 const unsigned char *,
112 const unsigned char *));
113static boolean srec_write_header PARAMS ((bfd *));
114static boolean srec_write_symbols PARAMS ((bfd *));
115
4c8d6c9f 116/* Macros for converting between hex and binary. */
4a81b561 117
3039e8ee 118static CONST char digs[] = "0123456789ABCDEF";
5f9ca960 119
4c8d6c9f
SS
120/* Table that gets filled in with numbers corresponding to hex chars. */
121
122static char hex_value[256];
9898b929 123
9898b929 124#define NOT_HEX 20
5f9ca960 125#define NIBBLE(x) hex_value[(unsigned char)(x)]
9898b929 126#define HEX(buffer) ((NIBBLE((buffer)[0])<<4) + NIBBLE((buffer)[1]))
5f9ca960
JG
127#define TOHEX(d, x, ch) \
128 d[1] = digs[(x) & 0xf]; \
129 d[0] = digs[((x)>>4)&0xf]; \
130 ch += ((x) & 0xff);
131#define ISHEX(x) (hex_value[(unsigned char)(x)] != NOT_HEX)
4a81b561 132
4c8d6c9f 133/* Initialize by filling in the hex conversion array. */
9898b929 134
e98e6ec1 135static void
57a1867e 136srec_init ()
9898b929 137{
9783e04a
DM
138 unsigned int i;
139 static boolean inited = false;
140
141 if (inited == false)
9898b929 142 {
9783e04a
DM
143 inited = true;
144
145 for (i = 0; i < sizeof (hex_value); i++)
9898b929 146 {
9783e04a 147 hex_value[i] = NOT_HEX;
9898b929 148 }
9783e04a 149 for (i = 0; i < 10; i++)
9898b929 150 {
9783e04a 151 hex_value[i + '0'] = i;
9898b929 152 }
9783e04a 153 for (i = 0; i < 6; i++)
9898b929 154 {
9783e04a
DM
155 hex_value[i + 'a'] = i + 10;
156 hex_value[i + 'A'] = i + 10;
9898b929 157 }
9783e04a 158 }
9898b929
JG
159}
160
4a81b561
DHW
161
162/* The maximum number of bytes on a line is FF */
9783e04a 163#define MAXCHUNK 0xff
4a81b561 164/* The number of bytes we fit onto a line on output */
9898b929
JG
165#define CHUNK 21
166
167/* We cannot output our srecords as we see them, we have to glue them
168 together, this is done in this structure : */
169
170struct srec_data_list_struct
171{
9783e04a
DM
172 unsigned char *data;
173 bfd_vma where;
174 bfd_size_type size;
175 struct srec_data_list_struct *next;
176
8f8fefcc 177
9783e04a 178};
9898b929
JG
179typedef struct srec_data_list_struct srec_data_list_type;
180
4a81b561 181
9783e04a
DM
182typedef struct srec_data_struct
183 {
184 srec_data_list_type *head;
d4d16683 185 srec_data_list_type *tail;
9898b929 186 unsigned int type;
9783e04a 187
8f8fefcc
JG
188 int done_symbol_read;
189 int count;
190 asymbol *symbols;
191 char *strings;
192 int symbol_idx;
193 int string_size;
194 int string_idx;
9783e04a
DM
195 }
196tdata_type;
9898b929 197
6d4f7715
ILT
198static boolean srec_write_section PARAMS ((bfd *, tdata_type *,
199 srec_data_list_type *));
200static boolean srec_write_terminator PARAMS ((bfd *, tdata_type *));
9898b929 201
9783e04a 202/*
8f8fefcc 203 called once per input S-Record, used to work out vma and size of data.
4a81b561
DHW
204 */
205
9783e04a 206static bfd_vma low, high;
9898b929 207
9783e04a 208/*ARGSUSED*/
8f8fefcc 209static void
9783e04a
DM
210size_symbols (abfd, buf, len, val)
211 bfd *abfd;
212 char *buf;
213 int len;
214 int val;
215{
216 abfd->symcount++;
217 abfd->tdata.srec_data->string_size += len + 1;
8f8fefcc
JG
218}
219
220static void
9783e04a
DM
221fillup_symbols (abfd, buf, len, val)
222 bfd *abfd;
223 char *buf;
224 int len;
225 int val;
8f8fefcc
JG
226{
227 if (!abfd->tdata.srec_data->done_symbol_read)
8f8fefcc 228 {
9783e04a
DM
229 asymbol *p;
230 if (abfd->tdata.srec_data->symbols == 0)
231 {
232 abfd->tdata.srec_data->symbols = (asymbol *) bfd_alloc (abfd, abfd->symcount * sizeof (asymbol));
233 abfd->tdata.srec_data->strings = (char *) bfd_alloc (abfd, abfd->tdata.srec_data->string_size);
234 if (!abfd->tdata.srec_data->symbols || !abfd->tdata.srec_data->strings)
235 {
5e808126 236 bfd_set_error (bfd_error_no_memory);
9783e04a
DM
237 abort (); /* FIXME */
238 }
239 abfd->tdata.srec_data->symbol_idx = 0;
240 abfd->tdata.srec_data->string_idx = 0;
241 }
8f8fefcc 242
9783e04a
DM
243 p = abfd->tdata.srec_data->symbols + abfd->tdata.srec_data->symbol_idx++;
244 p->the_bfd = abfd;
245 p->name = abfd->tdata.srec_data->strings + abfd->tdata.srec_data->string_idx;
246 memcpy ((char *) (p->name), buf, len + 1);
247 abfd->tdata.srec_data->string_idx += len + 1;
248 p->value = val;
249 p->flags = BSF_EXPORT | BSF_GLOBAL;
5e643795 250 p->section = bfd_abs_section_ptr;
d4d16683 251 p->udata.p = NULL;
9783e04a 252 }
8f8fefcc 253}
9783e04a 254/*ARGSUSED*/
4a81b561 255static void
57a1867e
DM
256size_srec (abfd, section, address, raw, length)
257 bfd *abfd;
258 asection *section;
259 bfd_vma address;
260 bfd_byte *raw;
261 unsigned int length;
4a81b561 262{
357a1f38
SC
263 if (address < low)
264 low = address;
9783e04a
DM
265 if (address + length > high)
266 high = address + length - 1;
4a81b561
DHW
267}
268
357a1f38 269
4a81b561 270/*
8f8fefcc 271 called once per input S-Record, copies data from input into bfd_alloc'd area
4a81b561
DHW
272 */
273
9783e04a 274/*ARGSUSED*/
4a81b561 275static void
57a1867e
DM
276fillup (abfd, section, address, raw, length)
277 bfd *abfd;
278 asection *section;
279 bfd_vma address;
280 bfd_byte *raw;
281 unsigned int length;
9783e04a
DM
282{
283 unsigned int i;
284 bfd_byte *dst =
285 (bfd_byte *) (section->used_by_bfd) + address - section->vma;
286 /* length -1 because we don't read in the checksum */
287 for (i = 0; i < length - 1; i++)
288 {
289 *dst = HEX (raw);
290 dst++;
291 raw += 2;
292 }
4a81b561
DHW
293}
294
8f8fefcc 295/* Pass over an S-Record file, calling one of the above functions on each
387cbb2b
JG
296 record. */
297
57a1867e 298static int
9783e04a
DM
299white (x)
300 char x;
8f8fefcc 301{
9783e04a 302 return (x == ' ' || x == '\t' || x == '\n' || x == '\r');
8f8fefcc
JG
303}
304static int
9783e04a
DM
305skipwhite (src, abfd)
306 char *src;
307 bfd *abfd;
8f8fefcc
JG
308{
309 int eof = 0;
9783e04a
DM
310 while (white (*src) && !eof)
311 {
312 eof = (boolean) (bfd_read (src, 1, 1, abfd) != 1);
313 }
8f8fefcc
JG
314 return eof;
315}
316
317static boolean
57a1867e
DM
318srec_mkobject (abfd)
319 bfd *abfd;
8f8fefcc 320{
9783e04a
DM
321 if (abfd->tdata.srec_data == 0)
322 {
323 tdata_type *tdata = (tdata_type *) bfd_alloc (abfd, sizeof (tdata_type));
324 if (!tdata)
325 {
5e808126 326 bfd_set_error (bfd_error_no_memory);
9783e04a
DM
327 return false;
328 }
329 abfd->tdata.srec_data = tdata;
330 tdata->type = 1;
d4d16683
ILT
331 tdata->head = NULL;
332 tdata->tail = NULL;
9783e04a 333 }
8f8fefcc 334 return true;
9783e04a 335
8f8fefcc
JG
336}
337
57a1867e 338static void
9783e04a 339pass_over (abfd, func, symbolfunc, section)
4c3721d5 340 bfd *abfd;
9783e04a
DM
341 void (*func) ();
342 void (*symbolfunc) ();
4c3721d5 343 asection *section;
4a81b561 344{
8f8fefcc
JG
345 unsigned int bytes_on_line;
346 boolean eof = false;
e98e6ec1 347
9783e04a 348 srec_mkobject (abfd);
8f8fefcc 349 /* To the front of the file */
6d4f7715
ILT
350 if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
351 abort ();
8f8fefcc 352 while (eof == false)
4a81b561 353 {
9783e04a
DM
354 char buffer[MAXCHUNK];
355 char *src = buffer;
356 char type;
357 bfd_vma address = 0;
358
359 /* Find first 'S' or $ */
360 eof = (boolean) (bfd_read (src, 1, 1, abfd) != 1);
361 switch (*src)
8f8fefcc 362 {
9783e04a 363 default:
9783e04a
DM
364 if (eof)
365 return;
366 break;
367
368 case '$':
369 /* Inside a symbol definition - just ignore the module name */
370 while (*src != '\n' && !eof)
371 {
372 eof = (boolean) (bfd_read (src, 1, 1, abfd) != 1);
373 }
374 break;
375
376 case ' ':
377 /* spaces - maybe just before a symbol */
378 while (*src != '\n' && *src != '\r' && white (*src))
379 {
380 eof = skipwhite (src, abfd);
4c3721d5 381
4c3721d5 382 {
9783e04a
DM
383 int val = 0;
384 int slen = 0;
385 char symbol[MAXCHUNK];
386
387 /* get the symbol part */
388 while (!eof && !white (*src) && slen < MAXCHUNK)
389 {
390 symbol[slen++] = *src;
391 eof = (boolean) (bfd_read (src, 1, 1, abfd) != 1);
392 }
393 symbol[slen] = 0;
394 eof = skipwhite (src, abfd);
395 /* skip the $ for the hex value */
396 if (*src == '$')
397 {
398 eof = (boolean) (bfd_read (src, 1, 1, abfd) != 1);
399 }
400
401 /* Scan off the hex number */
402 while (isxdigit (*src))
403 {
404 val *= 16;
405 if (isdigit (*src))
406 val += *src - '0';
407 else if (isupper (*src))
408 {
409 val += *src - 'A' + 10;
410 }
411 else
412 {
413 val += *src - 'a' + 10;
414 }
415 eof = (boolean) (bfd_read (src, 1, 1, abfd) != 1);
416 }
417 symbolfunc (abfd, symbol, slen, val);
4c3721d5 418 }
9783e04a
DM
419 }
420 break;
421 case 'S':
422 src++;
423
424 /* Fetch the type and the length */
6d4f7715
ILT
425 if (bfd_read (src, 1, 3, abfd) != 3)
426 abort (); /* FIXME */
9783e04a
DM
427
428 type = *src++;
429
430 if (!ISHEX (src[0]) || !ISHEX (src[1]))
431 break;
432
433 bytes_on_line = HEX (src);
434
435 if (bytes_on_line > MAXCHUNK / 2)
436 break;
437 src += 2;
438
6d4f7715
ILT
439 if (bfd_read (src, 1, bytes_on_line * 2, abfd) != bytes_on_line * 2)
440 abort (); /* FIXME */
9783e04a
DM
441
442 switch (type)
443 {
444 case '0':
445 case '5':
446 /* Prologue - ignore */
447 break;
448 case '3':
449 address = HEX (src);
450 src += 2;
451 bytes_on_line--;
452
453 case '2':
454 address = HEX (src) | (address << 8);
455 src += 2;
456 bytes_on_line--;
457 case '1':
458 address = HEX (src) | (address << 8);
459 src += 2;
460 address = HEX (src) | (address << 8);
461 src += 2;
462 bytes_on_line -= 2;
463 func (abfd, section, address, src, bytes_on_line);
464 break;
5e643795
ILT
465
466 case '7':
467 address = HEX (src);
468 src += 2;
469 bytes_on_line--;
470 case '8':
471 address = HEX (src) | (address << 8);
472 src += 2;
473 bytes_on_line--;
474 case '9':
475 address = HEX (src) | (address << 8);
476 src += 2;
477 address = HEX (src) | (address << 8);
478 src += 2;
479 bytes_on_line -= 2;
480 abfd->start_address = address;
481 return;
482
9783e04a
DM
483 default:
484 return;
485 }
8f8fefcc 486 }
4a81b561 487 }
9898b929 488
4a81b561
DHW
489}
490
2f3508ad 491static const bfd_target *
9783e04a
DM
492object_p (abfd)
493 bfd *abfd;
8f8fefcc
JG
494{
495 asection *section;
9783e04a 496 /* We create one section called .text for all the contents,
8f8fefcc 497 and allocate enough room for the entire file. */
9783e04a
DM
498
499 section = bfd_make_section (abfd, ".text");
8f8fefcc
JG
500 section->_raw_size = 0;
501 section->vma = 0xffffffff;
502 low = 0xffffffff;
503 high = 0;
9783e04a 504 pass_over (abfd, size_srec, size_symbols, section);
8f8fefcc
JG
505 section->_raw_size = high - low;
506 section->vma = low;
507 section->flags = SEC_HAS_CONTENTS | SEC_LOAD | SEC_ALLOC;
4a81b561 508
8f8fefcc 509 if (abfd->symcount)
9783e04a 510 abfd->flags |= HAS_SYMS;
8f8fefcc
JG
511 return abfd->xvec;
512}
9898b929 513
2f3508ad 514static const bfd_target *
57a1867e
DM
515srec_object_p (abfd)
516 bfd *abfd;
4a81b561 517{
387cbb2b 518 char b[4];
8f8fefcc 519
9783e04a 520 srec_init ();
9898b929 521
6d4f7715
ILT
522 if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0
523 || bfd_read (b, 1, 4, abfd) != 4)
524 return NULL;
9783e04a
DM
525
526 if (b[0] != 'S' || !ISHEX (b[1]) || !ISHEX (b[2]) || !ISHEX (b[3]))
2f3508ad 527 return (const bfd_target *) NULL;
9783e04a
DM
528
529 /* We create one section called .text for all the contents,
387cbb2b 530 and allocate enough room for the entire file. */
4a81b561 531
9783e04a 532 return object_p (abfd);
8f8fefcc
JG
533}
534
535
2f3508ad 536static const bfd_target *
57a1867e
DM
537symbolsrec_object_p (abfd)
538 bfd *abfd;
8f8fefcc
JG
539{
540 char b[4];
541
9783e04a
DM
542 srec_init ();
543
6d4f7715
ILT
544 if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0
545 || bfd_read (b, 1, 4, abfd) != 4)
546 return NULL;
8f8fefcc
JG
547
548 if (b[0] != '$' || b[1] != '$')
2f3508ad 549 return (const bfd_target *) NULL;
8f8fefcc 550
9783e04a 551 return object_p (abfd);
4a81b561
DHW
552}
553
554
4a81b561 555static boolean
57a1867e
DM
556srec_get_section_contents (abfd, section, location, offset, count)
557 bfd *abfd;
558 asection *section;
559 PTR location;
560 file_ptr offset;
561 bfd_size_type count;
9783e04a
DM
562{
563 if (section->used_by_bfd == (PTR) NULL)
9898b929 564 {
9783e04a
DM
565 section->used_by_bfd = (PTR) bfd_alloc (abfd, section->_raw_size);
566 if (!section->used_by_bfd)
567 {
5e808126 568 bfd_set_error (bfd_error_no_memory);
9783e04a
DM
569 return false;
570 }
571
572 pass_over (abfd, fillup, fillup_symbols, section);
9898b929 573 }
9783e04a 574 memcpy ((PTR) location,
57a1867e
DM
575 (PTR) ((char *) (section->used_by_bfd) + offset),
576 count);
9783e04a 577 return true;
4a81b561 578}
9783e04a 579
4a81b561
DHW
580
581
582boolean
57a1867e
DM
583srec_set_arch_mach (abfd, arch, machine)
584 bfd *abfd;
585 enum bfd_architecture arch;
586 unsigned long machine;
4a81b561 587{
9783e04a 588 return bfd_default_set_arch_mach (abfd, arch, machine);
4a81b561
DHW
589}
590
591
9898b929
JG
592/* we have to save up all the Srecords for a splurge before output,
593 also remember */
4a81b561 594
9898b929 595static boolean
57a1867e
DM
596srec_set_section_contents (abfd, section, location, offset, bytes_to_do)
597 bfd *abfd;
598 sec_ptr section;
599 PTR location;
600 file_ptr offset;
601 bfd_size_type bytes_to_do;
9783e04a
DM
602{
603 tdata_type *tdata = abfd->tdata.srec_data;
d4d16683 604 register srec_data_list_type *entry;
9783e04a 605
d4d16683
ILT
606 entry = ((srec_data_list_type *)
607 bfd_alloc (abfd, sizeof (srec_data_list_type)));
608 if (entry == NULL)
9783e04a 609 {
5e808126 610 bfd_set_error (bfd_error_no_memory);
9783e04a
DM
611 return false;
612 }
8f8fefcc 613
294eaca4 614 if ((section->flags & SEC_ALLOC)
9783e04a 615 && (section->flags & SEC_LOAD))
9898b929 616 {
9783e04a 617 unsigned char *data = (unsigned char *) bfd_alloc (abfd, bytes_to_do);
d4d16683 618 if (data == NULL)
9783e04a 619 {
5e808126 620 bfd_set_error (bfd_error_no_memory);
9783e04a
DM
621 return false;
622 }
68241b2b 623 memcpy ((PTR) data, location, bytes_to_do);
9898b929 624
9783e04a 625 if ((section->lma + offset + bytes_to_do) <= 0xffff)
8f8fefcc 626 {
9898b929 627
8f8fefcc 628 }
9783e04a
DM
629 else if ((section->lma + offset + bytes_to_do) <= 0xffffff
630 && tdata->type < 2)
8f8fefcc
JG
631 {
632 tdata->type = 2;
633 }
9783e04a 634 else
8f8fefcc
JG
635 {
636 tdata->type = 3;
637 }
638
639 entry->data = data;
640 entry->where = section->lma + offset;
641 entry->size = bytes_to_do;
d4d16683
ILT
642
643 /* Sort the records by address. Optimize for the common case of
644 adding a record to the end of the list. */
645 if (tdata->tail != NULL
646 && entry->where >= tdata->tail->where)
647 {
648 tdata->tail->next = entry;
649 entry->next = NULL;
650 tdata->tail = entry;
651 }
652 else
653 {
654 register srec_data_list_type **look;
655
656 for (look = &tdata->head;
657 *look != NULL && (*look)->where < entry->where;
658 look = &(*look)->next)
659 ;
660 entry->next = *look;
661 *look = entry;
662 if (entry->next == NULL)
663 tdata->tail = entry;
664 }
8f8fefcc 665 }
9783e04a 666 return true;
9898b929
JG
667}
668
669/* Write a record of type, of the supplied number of bytes. The
670 supplied bytes and length don't have a checksum. That's worked out
671 here
672*/
6d4f7715 673static boolean
57a1867e
DM
674srec_write_record (abfd, type, address, data, end)
675 bfd *abfd;
6d4f7715 676 int type;
57a1867e 677 bfd_vma address;
6d4f7715
ILT
678 const unsigned char *data;
679 const unsigned char *end;
9783e04a
DM
680{
681 char buffer[MAXCHUNK];
682
683 unsigned int check_sum = 0;
684 CONST unsigned char *src = data;
685 char *dst = buffer;
686 char *length;
687
688
689 *dst++ = 'S';
690 *dst++ = '0' + type;
691
692 length = dst;
693 dst += 2; /* leave room for dst*/
694
695 switch (type)
9898b929 696 {
9783e04a
DM
697 case 3:
698 case 7:
699 TOHEX (dst, (address >> 24), check_sum);
700 dst += 2;
701 case 8:
702 case 2:
703 TOHEX (dst, (address >> 16), check_sum);
704 dst += 2;
705 case 9:
706 case 1:
707 case 0:
708 TOHEX (dst, (address >> 8), check_sum);
709 dst += 2;
710 TOHEX (dst, (address), check_sum);
711 dst += 2;
712 break;
4a81b561 713
4a81b561 714 }
9783e04a 715 for (src = data; src < end; src++)
9898b929 716 {
9783e04a
DM
717 TOHEX (dst, *src, check_sum);
718 dst += 2;
4a81b561
DHW
719 }
720
9783e04a
DM
721 /* Fill in the length */
722 TOHEX (length, (dst - length) / 2, check_sum);
723 check_sum &= 0xff;
724 check_sum = 255 - check_sum;
725 TOHEX (dst, check_sum, check_sum);
726 dst += 2;
727
728 *dst++ = '\r';
729 *dst++ = '\n';
6d4f7715
ILT
730 if (bfd_write ((PTR) buffer, 1, dst - buffer, abfd) != dst - buffer)
731 return false;
732 return true;
9898b929 733}
4a81b561 734
4a81b561 735
4a81b561 736
6d4f7715 737static boolean
57a1867e
DM
738srec_write_header (abfd)
739 bfd *abfd;
9898b929 740{
9783e04a
DM
741 unsigned char buffer[MAXCHUNK];
742 unsigned char *dst = buffer;
743 unsigned int i;
4a81b561 744
9783e04a
DM
745 /* I'll put an arbitary 40 char limit on header size */
746 for (i = 0; i < 40 && abfd->filename[i]; i++)
9898b929 747 {
9783e04a 748 *dst++ = abfd->filename[i];
9898b929 749 }
6d4f7715 750 return srec_write_record (abfd, 0, 0, buffer, dst);
4a81b561
DHW
751}
752
6d4f7715 753static boolean
57a1867e
DM
754srec_write_section (abfd, tdata, list)
755 bfd *abfd;
756 tdata_type *tdata;
757 srec_data_list_type *list;
9898b929 758{
9783e04a
DM
759 unsigned int bytes_written = 0;
760 unsigned char *location = list->data;
9898b929 761
9783e04a 762 while (bytes_written < list->size)
9898b929 763 {
9783e04a
DM
764 bfd_vma address;
765
766 unsigned int bytes_this_chunk = list->size - bytes_written;
9898b929 767
9783e04a 768 if (bytes_this_chunk > CHUNK)
9898b929 769 {
9783e04a 770 bytes_this_chunk = CHUNK;
9898b929
JG
771 }
772
9783e04a 773 address = list->where + bytes_written;
9898b929 774
6d4f7715
ILT
775 if (! srec_write_record (abfd,
776 tdata->type,
777 address,
778 location,
779 location + bytes_this_chunk))
780 return false;
9898b929 781
9783e04a
DM
782 bytes_written += bytes_this_chunk;
783 location += bytes_this_chunk;
9898b929
JG
784 }
785
6d4f7715 786 return true;
9898b929
JG
787}
788
6d4f7715 789static boolean
57a1867e
DM
790srec_write_terminator (abfd, tdata)
791 bfd *abfd;
792 tdata_type *tdata;
9783e04a
DM
793{
794 unsigned char buffer[2];
795
6d4f7715
ILT
796 return srec_write_record (abfd, 10 - tdata->type,
797 abfd->start_address, buffer, buffer);
9898b929 798}
3039e8ee 799
8f8fefcc 800
9783e04a 801
6d4f7715 802static boolean
9783e04a 803srec_write_symbols (abfd)
2c3b9e47 804 bfd *abfd;
9898b929 805{
8f8fefcc
JG
806 char buffer[MAXCHUNK];
807 /* Dump out the symbols of a bfd */
808 int i;
2f3508ad 809 int count = bfd_get_symcount (abfd);
8f8fefcc 810
2f3508ad 811 if (count)
9783e04a 812 {
6d4f7715 813 size_t len;
9783e04a
DM
814 asymbol **table = bfd_get_outsymbols (abfd);
815 sprintf (buffer, "$$ %s\r\n", abfd->filename);
8f8fefcc 816
2f3508ad 817 len = strlen (buffer);
6d4f7715
ILT
818 if (bfd_write (buffer, len, 1, abfd) != len)
819 return false;
8f8fefcc 820
2f3508ad 821 for (i = 0; i < count; i++)
9783e04a
DM
822 {
823 asymbol *s = table[i];
8f8fefcc 824#if 0
9783e04a 825 int len = strlen (s->name);
8f8fefcc 826
9783e04a 827 /* If this symbol has a .[ocs] in it, it's probably a file name
8f8fefcc
JG
828 and we'll output that as the module name */
829
9783e04a
DM
830 if (len > 3 && s->name[len - 2] == '.')
831 {
832 int l;
833 sprintf (buffer, "$$ %s\r\n", s->name);
834 l = strlen (buffer);
6d4f7715
ILT
835 if (bfd_write (buffer, l, 1, abfd) != l)
836 return false;
9783e04a
DM
837 }
838 else
8f8fefcc 839#endif
9783e04a
DM
840 if (s->flags & (BSF_GLOBAL | BSF_LOCAL)
841 && (s->flags & BSF_DEBUGGING) == 0
842 && s->name[0] != '.'
843 && s->name[0] != 't')
844 {
845 /* Just dump out non debug symbols */
846
847 int l;
848 char buf2[40], *p;
849
850 sprintf_vma (buf2,
851 s->value + s->section->output_section->lma
852 + s->section->output_offset);
853 p = buf2;
854 while (p[0] == '0' && p[1] != 0)
855 p++;
856 sprintf (buffer, " %s $%s\r\n", s->name, p);
857 l = strlen (buffer);
6d4f7715
ILT
858 if (bfd_write (buffer, l, 1, abfd) != l)
859 return false;
9783e04a
DM
860 }
861 }
862 sprintf (buffer, "$$ \r\n");
2f3508ad 863 len = strlen (buffer);
6d4f7715
ILT
864 if (bfd_write (buffer, len, 1, abfd) != len)
865 return false;
8f8fefcc 866 }
6d4f7715
ILT
867
868 return true;
9898b929
JG
869}
870
9898b929 871static boolean
9783e04a 872internal_srec_write_object_contents (abfd, symbols)
8f8fefcc
JG
873 bfd *abfd;
874 int symbols;
4a81b561 875{
9783e04a
DM
876 tdata_type *tdata = abfd->tdata.srec_data;
877 srec_data_list_type *list;
9898b929 878
9783e04a 879 if (symbols)
6d4f7715
ILT
880 {
881 if (! srec_write_symbols (abfd))
882 return false;
883 }
8f8fefcc 884
6d4f7715
ILT
885 if (! srec_write_header (abfd))
886 return false;
8f8fefcc 887
9783e04a
DM
888 /* Now wander though all the sections provided and output them */
889 list = tdata->head;
9898b929 890
9783e04a 891 while (list != (srec_data_list_type *) NULL)
9898b929 892 {
6d4f7715
ILT
893 if (! srec_write_section (abfd, tdata, list))
894 return false;
9783e04a 895 list = list->next;
9898b929 896 }
6d4f7715 897 return srec_write_terminator (abfd, tdata);
4a81b561
DHW
898}
899
8f8fefcc 900static boolean
9783e04a 901srec_write_object_contents (abfd)
8f8fefcc
JG
902 bfd *abfd;
903{
9783e04a 904 return internal_srec_write_object_contents (abfd, 0);
8f8fefcc
JG
905}
906
907static boolean
9783e04a 908symbolsrec_write_object_contents (abfd)
8f8fefcc
JG
909 bfd *abfd;
910{
9783e04a 911 return internal_srec_write_object_contents (abfd, 1);
8f8fefcc
JG
912}
913
9783e04a
DM
914/*ARGSUSED*/
915static int
57a1867e
DM
916srec_sizeof_headers (abfd, exec)
917 bfd *abfd;
918 boolean exec;
39a2ce33 919{
9783e04a 920 return 0;
39a2ce33
SC
921}
922
357a1f38 923static asymbol *
57a1867e
DM
924srec_make_empty_symbol (abfd)
925 bfd *abfd;
357a1f38 926{
9783e04a
DM
927 asymbol *new = (asymbol *) bfd_zalloc (abfd, sizeof (asymbol));
928 if (new)
929 new->the_bfd = abfd;
357a1f38
SC
930 return new;
931}
8f8fefcc 932
326e32d7 933static long
9783e04a
DM
934srec_get_symtab_upper_bound (abfd)
935 bfd *abfd;
8f8fefcc
JG
936{
937 /* Read in all the info */
326e32d7
ILT
938 if (! srec_get_section_contents (abfd, abfd->sections, 0, 0, 0))
939 return -1;
9783e04a 940 return (bfd_get_symcount (abfd) + 1) * (sizeof (asymbol *));
8f8fefcc
JG
941}
942
326e32d7 943static long
57a1867e
DM
944srec_get_symtab (abfd, alocation)
945 bfd *abfd;
946 asymbol **alocation;
8f8fefcc
JG
947{
948 int lim = abfd->symcount;
949 int i;
9783e04a
DM
950 for (i = 0; i < lim; i++)
951 {
952 alocation[i] = abfd->tdata.srec_data->symbols + i;
953 }
8f8fefcc
JG
954 alocation[i] = 0;
955 return lim;
956}
957
9783e04a
DM
958/*ARGSUSED*/
959void
57a1867e
DM
960srec_get_symbol_info (ignore_abfd, symbol, ret)
961 bfd *ignore_abfd;
962 asymbol *symbol;
963 symbol_info *ret;
2c3b9e47
KR
964{
965 bfd_symbol_info (symbol, ret);
966}
967
9783e04a
DM
968/*ARGSUSED*/
969void
57a1867e
DM
970srec_print_symbol (ignore_abfd, afile, symbol, how)
971 bfd *ignore_abfd;
972 PTR afile;
973 asymbol *symbol;
974 bfd_print_symbol_type how;
9783e04a
DM
975{
976 FILE *file = (FILE *) afile;
977 switch (how)
978 {
979 case bfd_print_symbol_name:
980 fprintf (file, "%s", symbol->name);
981 break;
982 default:
983 bfd_print_symbol_vandf ((PTR) file, symbol);
984 fprintf (file, " %-5s %s",
985 symbol->section->name,
986 symbol->name);
8f8fefcc 987
9783e04a 988 }
8f8fefcc
JG
989}
990
6812b607
ILT
991#define srec_close_and_cleanup _bfd_generic_close_and_cleanup
992#define srec_bfd_free_cached_info _bfd_generic_bfd_free_cached_info
993#define srec_new_section_hook _bfd_generic_new_section_hook
9872a49c 994
6812b607
ILT
995#define srec_bfd_is_local_label bfd_generic_is_local_label
996#define srec_get_lineno _bfd_nosymbols_get_lineno
997#define srec_find_nearest_line _bfd_nosymbols_find_nearest_line
998#define srec_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol
d0ec7a8e 999
6812b607
ILT
1000#define srec_bfd_get_relocated_section_contents \
1001 bfd_generic_get_relocated_section_contents
294eaca4 1002#define srec_bfd_relax_section bfd_generic_relax_section
4c3721d5
ILT
1003#define srec_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
1004#define srec_bfd_link_add_symbols _bfd_generic_link_add_symbols
1005#define srec_bfd_final_link _bfd_generic_final_link
3039e8ee 1006
2f3508ad 1007const bfd_target srec_vec =
4a81b561 1008{
9783e04a
DM
1009 "srec", /* name */
1010 bfd_target_srec_flavour,
1011 true, /* target byte order */
1012 true, /* target headers byte order */
1013 (HAS_RELOC | EXEC_P | /* object flags */
1014 HAS_LINENO | HAS_DEBUG |
1015 HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
1016 (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS
1017 | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
1018 0, /* leading underscore */
1019 ' ', /* ar_pad_char */
1020 16, /* ar_max_namelen */
1021 1, /* minimum alignment */
1022 bfd_getb64, bfd_getb_signed_64, bfd_putb64,
1023 bfd_getb32, bfd_getb_signed_32, bfd_putb32,
1024 bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* data */
1025 bfd_getb64, bfd_getb_signed_64, bfd_putb64,
1026 bfd_getb32, bfd_getb_signed_32, bfd_putb32,
1027 bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* hdrs */
9898b929
JG
1028
1029 {
9783e04a
DM
1030 _bfd_dummy_target,
1031 srec_object_p, /* bfd_check_format */
2f3508ad
ILT
1032 _bfd_dummy_target,
1033 _bfd_dummy_target,
9898b929
JG
1034 },
1035 {
9783e04a
DM
1036 bfd_false,
1037 srec_mkobject,
1038 _bfd_generic_mkarchive,
1039 bfd_false,
9898b929
JG
1040 },
1041 { /* bfd_write_contents */
9783e04a
DM
1042 bfd_false,
1043 srec_write_object_contents,
1044 _bfd_write_archive_contents,
1045 bfd_false,
9898b929 1046 },
6812b607
ILT
1047
1048 BFD_JUMP_TABLE_GENERIC (srec),
1049 BFD_JUMP_TABLE_COPY (_bfd_generic),
1050 BFD_JUMP_TABLE_CORE (_bfd_nocore),
1051 BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
1052 BFD_JUMP_TABLE_SYMBOLS (srec),
1053 BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
1054 BFD_JUMP_TABLE_WRITE (srec),
1055 BFD_JUMP_TABLE_LINK (srec),
dfc1c006 1056 BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
6812b607
ILT
1057
1058 (PTR) 0
9783e04a 1059};
9898b929 1060
8f8fefcc
JG
1061
1062
2f3508ad 1063const bfd_target symbolsrec_vec =
8f8fefcc 1064{
9783e04a
DM
1065 "symbolsrec", /* name */
1066 bfd_target_srec_flavour,
1067 true, /* target byte order */
1068 true, /* target headers byte order */
1069 (HAS_RELOC | EXEC_P | /* object flags */
1070 HAS_LINENO | HAS_DEBUG |
1071 HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
1072 (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS
1073 | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
1074 0, /* leading underscore */
1075 ' ', /* ar_pad_char */
1076 16, /* ar_max_namelen */
1077 1, /* minimum alignment */
1078 bfd_getb64, bfd_getb_signed_64, bfd_putb64,
1079 bfd_getb32, bfd_getb_signed_32, bfd_putb32,
1080 bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* data */
1081 bfd_getb64, bfd_getb_signed_64, bfd_putb64,
1082 bfd_getb32, bfd_getb_signed_32, bfd_putb32,
1083 bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* hdrs */
8f8fefcc
JG
1084
1085 {
9783e04a
DM
1086 _bfd_dummy_target,
1087 symbolsrec_object_p, /* bfd_check_format */
2f3508ad
ILT
1088 _bfd_dummy_target,
1089 _bfd_dummy_target,
8f8fefcc
JG
1090 },
1091 {
9783e04a
DM
1092 bfd_false,
1093 srec_mkobject,
1094 _bfd_generic_mkarchive,
1095 bfd_false,
8f8fefcc
JG
1096 },
1097 { /* bfd_write_contents */
9783e04a
DM
1098 bfd_false,
1099 symbolsrec_write_object_contents,
1100 _bfd_write_archive_contents,
1101 bfd_false,
8f8fefcc 1102 },
6812b607
ILT
1103
1104 BFD_JUMP_TABLE_GENERIC (srec),
1105 BFD_JUMP_TABLE_COPY (_bfd_generic),
1106 BFD_JUMP_TABLE_CORE (_bfd_nocore),
1107 BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
1108 BFD_JUMP_TABLE_SYMBOLS (srec),
1109 BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
1110 BFD_JUMP_TABLE_WRITE (srec),
1111 BFD_JUMP_TABLE_LINK (srec),
dfc1c006 1112 BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
6812b607 1113
9783e04a
DM
1114 (PTR) 0
1115};
This page took 0.183253 seconds and 4 git commands to generate.