00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111 #include "bfd.h"
00112 #include "sysdep.h"
00113 #include "libbfd.h"
00114 #include "libiberty.h"
00115 #include "safe-ctype.h"
00116
00117 static void srec_get_symbol_info PARAMS ((bfd *, asymbol *, symbol_info *));
00118 static void srec_print_symbol
00119 PARAMS ((bfd *, PTR, asymbol *, bfd_print_symbol_type));
00120 static void srec_init PARAMS ((void));
00121 static bfd_boolean srec_mkobject PARAMS ((bfd *));
00122 static int srec_get_byte PARAMS ((bfd *, bfd_boolean *));
00123 static void srec_bad_byte PARAMS ((bfd *, unsigned int, int, bfd_boolean));
00124 static bfd_boolean srec_scan PARAMS ((bfd *));
00125 static const bfd_target *srec_object_p PARAMS ((bfd *));
00126 static const bfd_target *symbolsrec_object_p PARAMS ((bfd *));
00127 static bfd_boolean srec_read_section PARAMS ((bfd *, asection *, bfd_byte *));
00128
00129 static bfd_boolean srec_write_record
00130 PARAMS ((bfd *, unsigned int, bfd_vma, const bfd_byte *, const bfd_byte *));
00131 static bfd_boolean srec_write_header PARAMS ((bfd *));
00132 static bfd_boolean srec_write_symbols PARAMS ((bfd *));
00133 static bfd_boolean srec_new_symbol PARAMS ((bfd *, const char *, bfd_vma));
00134 static bfd_boolean srec_get_section_contents
00135 PARAMS ((bfd *, asection *, PTR, file_ptr, bfd_size_type));
00136 static bfd_boolean srec_set_arch_mach
00137 PARAMS ((bfd *, enum bfd_architecture, unsigned long));
00138 static bfd_boolean srec_set_section_contents
00139 PARAMS ((bfd *, sec_ptr, const PTR, file_ptr, bfd_size_type));
00140 static bfd_boolean internal_srec_write_object_contents PARAMS ((bfd *, int));
00141 static bfd_boolean srec_write_object_contents PARAMS ((bfd *));
00142 static bfd_boolean symbolsrec_write_object_contents PARAMS ((bfd *));
00143 static int srec_sizeof_headers PARAMS ((bfd *, bfd_boolean));
00144 static long srec_get_symtab_upper_bound PARAMS ((bfd *));
00145 static long srec_canonicalize_symtab PARAMS ((bfd *, asymbol **));
00146
00147
00148
00149 static const char digs[] = "0123456789ABCDEF";
00150
00151 #define NIBBLE(x) hex_value(x)
00152 #define HEX(buffer) ((NIBBLE((buffer)[0])<<4) + NIBBLE((buffer)[1]))
00153 #define TOHEX(d, x, ch) \
00154 d[1] = digs[(x) & 0xf]; \
00155 d[0] = digs[((x)>>4)&0xf]; \
00156 ch += ((x) & 0xff);
00157 #define ISHEX(x) hex_p(x)
00158
00159
00160
00161 static void
00162 srec_init ()
00163 {
00164 static bfd_boolean inited = FALSE;
00165
00166 if (! inited)
00167 {
00168 inited = TRUE;
00169 hex_init ();
00170 }
00171 }
00172
00173
00174 #define MAXCHUNK 0xff
00175
00176
00177 #define DEFAULT_CHUNK 16
00178
00179
00180
00181
00182 unsigned int Chunk = DEFAULT_CHUNK;
00183
00184
00185
00186
00187 bfd_boolean S3Forced = FALSE;
00188
00189
00190
00191
00192 struct srec_data_list_struct
00193 {
00194 struct srec_data_list_struct *next;
00195 bfd_byte *data;
00196 bfd_vma where;
00197 bfd_size_type size;
00198 };
00199
00200 typedef struct srec_data_list_struct srec_data_list_type;
00201
00202
00203
00204
00205
00206 struct srec_symbol
00207 {
00208 struct srec_symbol *next;
00209 const char *name;
00210 bfd_vma val;
00211 };
00212
00213
00214
00215 typedef struct srec_data_struct
00216 {
00217 srec_data_list_type *head;
00218 srec_data_list_type *tail;
00219 unsigned int type;
00220 struct srec_symbol *symbols;
00221 struct srec_symbol *symtail;
00222 asymbol *csymbols;
00223 }
00224 tdata_type;
00225
00226 static bfd_boolean srec_write_section
00227 PARAMS ((bfd *, tdata_type *, srec_data_list_type *));
00228 static bfd_boolean srec_write_terminator
00229 PARAMS ((bfd *, tdata_type *));
00230
00231
00232
00233 static bfd_boolean
00234 srec_mkobject (abfd)
00235 bfd *abfd;
00236 {
00237 bfd_size_type amt;
00238 tdata_type *tdata;
00239
00240 srec_init ();
00241
00242 amt = sizeof (tdata_type);
00243 tdata = (tdata_type *) bfd_alloc (abfd, amt);
00244 if (tdata == NULL)
00245 return FALSE;
00246
00247 abfd->tdata.srec_data = tdata;
00248 tdata->type = 1;
00249 tdata->head = NULL;
00250 tdata->tail = NULL;
00251 tdata->symbols = NULL;
00252 tdata->symtail = NULL;
00253 tdata->csymbols = NULL;
00254
00255 return TRUE;
00256 }
00257
00258
00259
00260
00261 static int
00262 srec_get_byte (abfd, errorptr)
00263 bfd *abfd;
00264 bfd_boolean *errorptr;
00265 {
00266 bfd_byte c;
00267
00268 if (bfd_bread (&c, (bfd_size_type) 1, abfd) != 1)
00269 {
00270 if (bfd_get_error () != bfd_error_file_truncated)
00271 *errorptr = TRUE;
00272 return EOF;
00273 }
00274
00275 return (int) (c & 0xff);
00276 }
00277
00278
00279
00280
00281
00282 static void
00283 srec_bad_byte (abfd, lineno, c, error)
00284 bfd *abfd;
00285 unsigned int lineno;
00286 int c;
00287 bfd_boolean error;
00288 {
00289 if (c == EOF)
00290 {
00291 if (! error)
00292 bfd_set_error (bfd_error_file_truncated);
00293 }
00294 else
00295 {
00296 char buf[10];
00297
00298 if (! ISPRINT (c))
00299 sprintf (buf, "\\%03o", (unsigned int) c);
00300 else
00301 {
00302 buf[0] = c;
00303 buf[1] = '\0';
00304 }
00305 (*_bfd_error_handler)
00306 (_("%B:%d: Unexpected character `%s' in S-record file\n"),
00307 abfd, lineno, buf);
00308 bfd_set_error (bfd_error_bad_value);
00309 }
00310 }
00311
00312
00313
00314 static bfd_boolean
00315 srec_new_symbol (abfd, name, val)
00316 bfd *abfd;
00317 const char *name;
00318 bfd_vma val;
00319 {
00320 struct srec_symbol *n;
00321 bfd_size_type amt = sizeof (struct srec_symbol);
00322
00323 n = (struct srec_symbol *) bfd_alloc (abfd, amt);
00324 if (n == NULL)
00325 return FALSE;
00326
00327 n->name = name;
00328 n->val = val;
00329
00330 if (abfd->tdata.srec_data->symbols == NULL)
00331 abfd->tdata.srec_data->symbols = n;
00332 else
00333 abfd->tdata.srec_data->symtail->next = n;
00334 abfd->tdata.srec_data->symtail = n;
00335 n->next = NULL;
00336
00337 ++abfd->symcount;
00338
00339 return TRUE;
00340 }
00341
00342
00343
00344
00345 static bfd_boolean
00346 srec_scan (abfd)
00347 bfd *abfd;
00348 {
00349 int c;
00350 unsigned int lineno = 1;
00351 bfd_boolean error = FALSE;
00352 bfd_byte *buf = NULL;
00353 size_t bufsize = 0;
00354 asection *sec = NULL;
00355 char *symbuf = NULL;
00356
00357 if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
00358 goto error_return;
00359
00360 while ((c = srec_get_byte (abfd, &error)) != EOF)
00361 {
00362
00363
00364 if (c != 'S' && c != '\r' && c != '\n')
00365 sec = NULL;
00366
00367 switch (c)
00368 {
00369 default:
00370 srec_bad_byte (abfd, lineno, c, error);
00371 goto error_return;
00372
00373 case '\n':
00374 ++lineno;
00375 break;
00376
00377 case '\r':
00378 break;
00379
00380 case '$':
00381
00382 while ((c = srec_get_byte (abfd, &error)) != '\n'
00383 && c != EOF)
00384 ;
00385 if (c == EOF)
00386 {
00387 srec_bad_byte (abfd, lineno, c, error);
00388 goto error_return;
00389 }
00390
00391 ++lineno;
00392
00393 break;
00394
00395 case ' ':
00396 do
00397 {
00398 bfd_size_type alc;
00399 char *p, *symname;
00400 bfd_vma symval;
00401
00402
00403 while ((c = srec_get_byte (abfd, &error)) != EOF
00404 && (c == ' ' || c == '\t'))
00405 ;
00406
00407 if (c == '\n' || c == '\r')
00408 break;
00409
00410 if (c == EOF)
00411 {
00412 srec_bad_byte (abfd, lineno, c, error);
00413 goto error_return;
00414 }
00415
00416 alc = 10;
00417 symbuf = (char *) bfd_malloc (alc + 1);
00418 if (symbuf == NULL)
00419 goto error_return;
00420
00421 p = symbuf;
00422
00423 *p++ = c;
00424 while ((c = srec_get_byte (abfd, &error)) != EOF
00425 && ! ISSPACE (c))
00426 {
00427 if ((bfd_size_type) (p - symbuf) >= alc)
00428 {
00429 char *n;
00430
00431 alc *= 2;
00432 n = (char *) bfd_realloc (symbuf, alc + 1);
00433 if (n == NULL)
00434 goto error_return;
00435 p = n + (p - symbuf);
00436 symbuf = n;
00437 }
00438
00439 *p++ = c;
00440 }
00441
00442 if (c == EOF)
00443 {
00444 srec_bad_byte (abfd, lineno, c, error);
00445 goto error_return;
00446 }
00447
00448 *p++ = '\0';
00449 symname = bfd_alloc (abfd, (bfd_size_type) (p - symbuf));
00450 if (symname == NULL)
00451 goto error_return;
00452 strcpy (symname, symbuf);
00453 free (symbuf);
00454 symbuf = NULL;
00455
00456 while ((c = srec_get_byte (abfd, &error)) != EOF
00457 && (c == ' ' || c == '\t'))
00458 ;
00459 if (c == EOF)
00460 {
00461 srec_bad_byte (abfd, lineno, c, error);
00462 goto error_return;
00463 }
00464
00465
00466 if (c == '$')
00467 {
00468 c = srec_get_byte (abfd, &error);
00469 if (c == EOF)
00470 {
00471 srec_bad_byte (abfd, lineno, c, error);
00472 goto error_return;
00473 }
00474 }
00475
00476 symval = 0;
00477 while (ISHEX (c))
00478 {
00479 symval <<= 4;
00480 symval += NIBBLE (c);
00481 c = srec_get_byte (abfd, &error);
00482 }
00483
00484 if (! srec_new_symbol (abfd, symname, symval))
00485 goto error_return;
00486 }
00487 while (c == ' ' || c == '\t')
00488 ;
00489
00490 if (c == '\n')
00491 ++lineno;
00492 else if (c != '\r')
00493 {
00494 srec_bad_byte (abfd, lineno, c, error);
00495 goto error_return;
00496 }
00497
00498 break;
00499
00500 case 'S':
00501 {
00502 file_ptr pos;
00503 char hdr[3];
00504 unsigned int bytes;
00505 bfd_vma address;
00506 bfd_byte *data;
00507
00508
00509
00510 pos = bfd_tell (abfd) - 1;
00511
00512 if (bfd_bread (hdr, (bfd_size_type) 3, abfd) != 3)
00513 goto error_return;
00514
00515 if (! ISHEX (hdr[1]) || ! ISHEX (hdr[2]))
00516 {
00517 if (! ISHEX (hdr[1]))
00518 c = hdr[1];
00519 else
00520 c = hdr[2];
00521 srec_bad_byte (abfd, lineno, c, error);
00522 goto error_return;
00523 }
00524
00525 bytes = HEX (hdr + 1);
00526 if (bytes * 2 > bufsize)
00527 {
00528 if (buf != NULL)
00529 free (buf);
00530 buf = (bfd_byte *) bfd_malloc ((bfd_size_type) bytes * 2);
00531 if (buf == NULL)
00532 goto error_return;
00533 bufsize = bytes * 2;
00534 }
00535
00536 if (bfd_bread (buf, (bfd_size_type) bytes * 2, abfd) != bytes * 2)
00537 goto error_return;
00538
00539
00540 --bytes;
00541
00542 address = 0;
00543 data = buf;
00544 switch (hdr[0])
00545 {
00546 case '0':
00547 case '5':
00548
00549
00550 sec = NULL;
00551 break;
00552
00553 case '3':
00554 address = HEX (data);
00555 data += 2;
00556 --bytes;
00557
00558 case '2':
00559 address = (address << 8) | HEX (data);
00560 data += 2;
00561 --bytes;
00562
00563 case '1':
00564 address = (address << 8) | HEX (data);
00565 data += 2;
00566 address = (address << 8) | HEX (data);
00567 data += 2;
00568 bytes -= 2;
00569
00570 if (sec != NULL
00571 && sec->vma + sec->size == address)
00572 {
00573
00574
00575 sec->size += bytes;
00576 }
00577 else
00578 {
00579 char secbuf[20];
00580 char *secname;
00581 bfd_size_type amt;
00582
00583 sprintf (secbuf, ".sec%d", bfd_count_sections (abfd) + 1);
00584 amt = strlen (secbuf) + 1;
00585 secname = (char *) bfd_alloc (abfd, amt);
00586 strcpy (secname, secbuf);
00587 sec = bfd_make_section (abfd, secname);
00588 if (sec == NULL)
00589 goto error_return;
00590 sec->flags = SEC_HAS_CONTENTS | SEC_LOAD | SEC_ALLOC;
00591 sec->vma = address;
00592 sec->lma = address;
00593 sec->size = bytes;
00594 sec->filepos = pos;
00595 }
00596
00597 break;
00598
00599 case '7':
00600 address = HEX (data);
00601 data += 2;
00602
00603 case '8':
00604 address = (address << 8) | HEX (data);
00605 data += 2;
00606
00607 case '9':
00608 address = (address << 8) | HEX (data);
00609 data += 2;
00610 address = (address << 8) | HEX (data);
00611 data += 2;
00612
00613
00614 abfd->start_address = address;
00615
00616 if (buf != NULL)
00617 free (buf);
00618
00619 return TRUE;
00620 }
00621 }
00622 break;
00623 }
00624 }
00625
00626 if (error)
00627 goto error_return;
00628
00629 if (buf != NULL)
00630 free (buf);
00631
00632 return TRUE;
00633
00634 error_return:
00635 if (symbuf != NULL)
00636 free (symbuf);
00637 if (buf != NULL)
00638 free (buf);
00639 return FALSE;
00640 }
00641
00642
00643
00644 static const bfd_target *
00645 srec_object_p (abfd)
00646 bfd *abfd;
00647 {
00648 PTR tdata_save;
00649 bfd_byte b[4];
00650
00651 srec_init ();
00652
00653 if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0
00654 || bfd_bread (b, (bfd_size_type) 4, abfd) != 4)
00655 return NULL;
00656
00657 if (b[0] != 'S' || !ISHEX (b[1]) || !ISHEX (b[2]) || !ISHEX (b[3]))
00658 {
00659 bfd_set_error (bfd_error_wrong_format);
00660 return NULL;
00661 }
00662
00663 tdata_save = abfd->tdata.any;
00664 if (! srec_mkobject (abfd) || ! srec_scan (abfd))
00665 {
00666 if (abfd->tdata.any != tdata_save && abfd->tdata.any != NULL)
00667 bfd_release (abfd, abfd->tdata.any);
00668 abfd->tdata.any = tdata_save;
00669 return NULL;
00670 }
00671
00672 if (abfd->symcount > 0)
00673 abfd->flags |= HAS_SYMS;
00674
00675 return abfd->xvec;
00676 }
00677
00678
00679
00680 static const bfd_target *
00681 symbolsrec_object_p (abfd)
00682 bfd *abfd;
00683 {
00684 PTR tdata_save;
00685 char b[2];
00686
00687 srec_init ();
00688
00689 if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0
00690 || bfd_bread (b, (bfd_size_type) 2, abfd) != 2)
00691 return NULL;
00692
00693 if (b[0] != '$' || b[1] != '$')
00694 {
00695 bfd_set_error (bfd_error_wrong_format);
00696 return NULL;
00697 }
00698
00699 tdata_save = abfd->tdata.any;
00700 if (! srec_mkobject (abfd) || ! srec_scan (abfd))
00701 {
00702 if (abfd->tdata.any != tdata_save && abfd->tdata.any != NULL)
00703 bfd_release (abfd, abfd->tdata.any);
00704 abfd->tdata.any = tdata_save;
00705 return NULL;
00706 }
00707
00708 if (abfd->symcount > 0)
00709 abfd->flags |= HAS_SYMS;
00710
00711 return abfd->xvec;
00712 }
00713
00714
00715
00716 static bfd_boolean
00717 srec_read_section (abfd, section, contents)
00718 bfd *abfd;
00719 asection *section;
00720 bfd_byte *contents;
00721 {
00722 int c;
00723 bfd_size_type sofar = 0;
00724 bfd_boolean error = FALSE;
00725 bfd_byte *buf = NULL;
00726 size_t bufsize = 0;
00727
00728 if (bfd_seek (abfd, section->filepos, SEEK_SET) != 0)
00729 goto error_return;
00730
00731 while ((c = srec_get_byte (abfd, &error)) != EOF)
00732 {
00733 bfd_byte hdr[3];
00734 unsigned int bytes;
00735 bfd_vma address;
00736 bfd_byte *data;
00737
00738 if (c == '\r' || c == '\n')
00739 continue;
00740
00741
00742
00743 BFD_ASSERT (c == 'S');
00744
00745 if (bfd_bread (hdr, (bfd_size_type) 3, abfd) != 3)
00746 goto error_return;
00747
00748 BFD_ASSERT (ISHEX (hdr[1]) && ISHEX (hdr[2]));
00749
00750 bytes = HEX (hdr + 1);
00751
00752 if (bytes * 2 > bufsize)
00753 {
00754 if (buf != NULL)
00755 free (buf);
00756 buf = (bfd_byte *) bfd_malloc ((bfd_size_type) bytes * 2);
00757 if (buf == NULL)
00758 goto error_return;
00759 bufsize = bytes * 2;
00760 }
00761
00762 if (bfd_bread (buf, (bfd_size_type) bytes * 2, abfd) != bytes * 2)
00763 goto error_return;
00764
00765 address = 0;
00766 data = buf;
00767 switch (hdr[0])
00768 {
00769 default:
00770 BFD_ASSERT (sofar == section->size);
00771 if (buf != NULL)
00772 free (buf);
00773 return TRUE;
00774
00775 case '3':
00776 address = HEX (data);
00777 data += 2;
00778 --bytes;
00779
00780 case '2':
00781 address = (address << 8) | HEX (data);
00782 data += 2;
00783 --bytes;
00784
00785 case '1':
00786 address = (address << 8) | HEX (data);
00787 data += 2;
00788 address = (address << 8) | HEX (data);
00789 data += 2;
00790 bytes -= 2;
00791
00792 if (address != section->vma + sofar)
00793 {
00794
00795 BFD_ASSERT (sofar == section->size);
00796 if (buf != NULL)
00797 free (buf);
00798 return TRUE;
00799 }
00800
00801
00802 --bytes;
00803
00804 while (bytes-- != 0)
00805 {
00806 contents[sofar] = HEX (data);
00807 data += 2;
00808 ++sofar;
00809 }
00810
00811 break;
00812 }
00813 }
00814
00815 if (error)
00816 goto error_return;
00817
00818 BFD_ASSERT (sofar == section->size);
00819
00820 if (buf != NULL)
00821 free (buf);
00822
00823 return TRUE;
00824
00825 error_return:
00826 if (buf != NULL)
00827 free (buf);
00828 return FALSE;
00829 }
00830
00831
00832
00833 static bfd_boolean
00834 srec_get_section_contents (abfd, section, location, offset, count)
00835 bfd *abfd;
00836 asection *section;
00837 PTR location;
00838 file_ptr offset;
00839 bfd_size_type count;
00840 {
00841 if (section->used_by_bfd == NULL)
00842 {
00843 section->used_by_bfd = bfd_alloc (abfd, section->size);
00844 if (section->used_by_bfd == NULL && section->size != 0)
00845 return FALSE;
00846
00847 if (! srec_read_section (abfd, section, section->used_by_bfd))
00848 return FALSE;
00849 }
00850
00851 memcpy (location, (bfd_byte *) section->used_by_bfd + offset,
00852 (size_t) count);
00853
00854 return TRUE;
00855 }
00856
00857
00858
00859 static bfd_boolean
00860 srec_set_arch_mach (abfd, arch, mach)
00861 bfd *abfd;
00862 enum bfd_architecture arch;
00863 unsigned long mach;
00864 {
00865 if (arch == bfd_arch_unknown)
00866 {
00867 abfd->arch_info = &bfd_default_arch_struct;
00868 return TRUE;
00869 }
00870 return bfd_default_set_arch_mach (abfd, arch, mach);
00871 }
00872
00873
00874
00875 static bfd_boolean
00876 srec_set_section_contents (abfd, section, location, offset, bytes_to_do)
00877 bfd *abfd;
00878 sec_ptr section;
00879 const PTR location;
00880 file_ptr offset;
00881 bfd_size_type bytes_to_do;
00882 {
00883 tdata_type *tdata = abfd->tdata.srec_data;
00884 register srec_data_list_type *entry;
00885
00886 entry = ((srec_data_list_type *)
00887 bfd_alloc (abfd, (bfd_size_type) sizeof (srec_data_list_type)));
00888 if (entry == NULL)
00889 return FALSE;
00890
00891 if (bytes_to_do
00892 && (section->flags & SEC_ALLOC)
00893 && (section->flags & SEC_LOAD))
00894 {
00895 bfd_byte *data;
00896
00897 data = (bfd_byte *) bfd_alloc (abfd, bytes_to_do);
00898 if (data == NULL)
00899 return FALSE;
00900 memcpy ((PTR) data, location, (size_t) bytes_to_do);
00901
00902
00903
00904 if (S3Forced)
00905 tdata->type = 3;
00906 else if ((section->lma + offset + bytes_to_do - 1) <= 0xffff)
00907 ;
00908 else if ((section->lma + offset + bytes_to_do - 1) <= 0xffffff
00909 && tdata->type <= 2)
00910 tdata->type = 2;
00911 else
00912 tdata->type = 3;
00913
00914 entry->data = data;
00915 entry->where = section->lma + offset;
00916 entry->size = bytes_to_do;
00917
00918
00919
00920 if (tdata->tail != NULL
00921 && entry->where >= tdata->tail->where)
00922 {
00923 tdata->tail->next = entry;
00924 entry->next = NULL;
00925 tdata->tail = entry;
00926 }
00927 else
00928 {
00929 register srec_data_list_type **look;
00930
00931 for (look = &tdata->head;
00932 *look != NULL && (*look)->where < entry->where;
00933 look = &(*look)->next)
00934 ;
00935 entry->next = *look;
00936 *look = entry;
00937 if (entry->next == NULL)
00938 tdata->tail = entry;
00939 }
00940 }
00941 return TRUE;
00942 }
00943
00944
00945
00946
00947
00948 static bfd_boolean
00949 srec_write_record (abfd, type, address, data, end)
00950 bfd *abfd;
00951 unsigned int type;
00952 bfd_vma address;
00953 const bfd_byte *data;
00954 const bfd_byte *end;
00955 {
00956 char buffer[2 * MAXCHUNK + 6];
00957 unsigned int check_sum = 0;
00958 const bfd_byte *src = data;
00959 char *dst = buffer;
00960 char *length;
00961 bfd_size_type wrlen;
00962
00963 *dst++ = 'S';
00964 *dst++ = '0' + type;
00965
00966 length = dst;
00967 dst += 2;
00968
00969 switch (type)
00970 {
00971 case 3:
00972 case 7:
00973 TOHEX (dst, (address >> 24), check_sum);
00974 dst += 2;
00975 case 8:
00976 case 2:
00977 TOHEX (dst, (address >> 16), check_sum);
00978 dst += 2;
00979 case 9:
00980 case 1:
00981 case 0:
00982 TOHEX (dst, (address >> 8), check_sum);
00983 dst += 2;
00984 TOHEX (dst, (address), check_sum);
00985 dst += 2;
00986 break;
00987
00988 }
00989 for (src = data; src < end; src++)
00990 {
00991 TOHEX (dst, *src, check_sum);
00992 dst += 2;
00993 }
00994
00995
00996 TOHEX (length, (dst - length) / 2, check_sum);
00997 check_sum &= 0xff;
00998 check_sum = 255 - check_sum;
00999 TOHEX (dst, check_sum, check_sum);
01000 dst += 2;
01001
01002 *dst++ = '\r';
01003 *dst++ = '\n';
01004 wrlen = dst - buffer;
01005 if (bfd_bwrite ((PTR) buffer, wrlen, abfd) != wrlen)
01006 return FALSE;
01007 return TRUE;
01008 }
01009
01010 static bfd_boolean
01011 srec_write_header (abfd)
01012 bfd *abfd;
01013 {
01014 unsigned int len = strlen (abfd->filename);
01015
01016
01017 if (len > 40)
01018 len = 40;
01019
01020 return srec_write_record (abfd, 0, (bfd_vma) 0,
01021 (bfd_byte *) abfd->filename,
01022 (bfd_byte *) abfd->filename + len);
01023 }
01024
01025 static bfd_boolean
01026 srec_write_section (abfd, tdata, list)
01027 bfd *abfd;
01028 tdata_type *tdata;
01029 srec_data_list_type *list;
01030 {
01031 unsigned int octets_written = 0;
01032 bfd_byte *location = list->data;
01033
01034
01035
01036
01037
01038
01039
01040 if (Chunk == 0)
01041 Chunk = 1;
01042 else if (Chunk > MAXCHUNK - tdata->type - 2)
01043 Chunk = MAXCHUNK - tdata->type - 2;
01044
01045 while (octets_written < list->size)
01046 {
01047 bfd_vma address;
01048 unsigned int octets_this_chunk = list->size - octets_written;
01049
01050 if (octets_this_chunk > Chunk)
01051 octets_this_chunk = Chunk;
01052
01053 address = list->where + octets_written / bfd_octets_per_byte (abfd);
01054
01055 if (! srec_write_record (abfd,
01056 tdata->type,
01057 address,
01058 location,
01059 location + octets_this_chunk))
01060 return FALSE;
01061
01062 octets_written += octets_this_chunk;
01063 location += octets_this_chunk;
01064 }
01065
01066 return TRUE;
01067 }
01068
01069 static bfd_boolean
01070 srec_write_terminator (abfd, tdata)
01071 bfd *abfd;
01072 tdata_type *tdata;
01073 {
01074 return srec_write_record (abfd, 10 - tdata->type,
01075 abfd->start_address, NULL, NULL);
01076 }
01077
01078 static bfd_boolean
01079 srec_write_symbols (abfd)
01080 bfd *abfd;
01081 {
01082
01083 int i;
01084 int count = bfd_get_symcount (abfd);
01085
01086 if (count)
01087 {
01088 bfd_size_type len;
01089 asymbol **table = bfd_get_outsymbols (abfd);
01090 len = strlen (abfd->filename);
01091 if (bfd_bwrite ("$$ ", (bfd_size_type) 3, abfd) != 3
01092 || bfd_bwrite (abfd->filename, len, abfd) != len
01093 || bfd_bwrite ("\r\n", (bfd_size_type) 2, abfd) != 2)
01094 return FALSE;
01095
01096 for (i = 0; i < count; i++)
01097 {
01098 asymbol *s = table[i];
01099 if (! bfd_is_local_label (abfd, s)
01100 && (s->flags & BSF_DEBUGGING) == 0)
01101 {
01102
01103 char buf[43], *p;
01104
01105 len = strlen (s->name);
01106 if (bfd_bwrite (" ", (bfd_size_type) 2, abfd) != 2
01107 || bfd_bwrite (s->name, len, abfd) != len)
01108 return FALSE;
01109
01110 sprintf_vma (buf + 2, (s->value
01111 + s->section->output_section->lma
01112 + s->section->output_offset));
01113 p = buf + 2;
01114 while (p[0] == '0' && p[1] != 0)
01115 p++;
01116 len = strlen (p);
01117 p[len] = '\r';
01118 p[len + 1] = '\n';
01119 *--p = '$';
01120 *--p = ' ';
01121 len += 4;
01122 if (bfd_bwrite (p, len, abfd) != len)
01123 return FALSE;
01124 }
01125 }
01126 if (bfd_bwrite ("$$ \r\n", (bfd_size_type) 5, abfd) != 5)
01127 return FALSE;
01128 }
01129
01130 return TRUE;
01131 }
01132
01133 static bfd_boolean
01134 internal_srec_write_object_contents (abfd, symbols)
01135 bfd *abfd;
01136 int symbols;
01137 {
01138 tdata_type *tdata = abfd->tdata.srec_data;
01139 srec_data_list_type *list;
01140
01141 if (symbols)
01142 {
01143 if (! srec_write_symbols (abfd))
01144 return FALSE;
01145 }
01146
01147 if (! srec_write_header (abfd))
01148 return FALSE;
01149
01150
01151 list = tdata->head;
01152
01153 while (list != (srec_data_list_type *) NULL)
01154 {
01155 if (! srec_write_section (abfd, tdata, list))
01156 return FALSE;
01157 list = list->next;
01158 }
01159 return srec_write_terminator (abfd, tdata);
01160 }
01161
01162 static bfd_boolean
01163 srec_write_object_contents (abfd)
01164 bfd *abfd;
01165 {
01166 return internal_srec_write_object_contents (abfd, 0);
01167 }
01168
01169 static bfd_boolean
01170 symbolsrec_write_object_contents (abfd)
01171 bfd *abfd;
01172 {
01173 return internal_srec_write_object_contents (abfd, 1);
01174 }
01175
01176 static int
01177 srec_sizeof_headers (abfd, exec)
01178 bfd *abfd ATTRIBUTE_UNUSED;
01179 bfd_boolean exec ATTRIBUTE_UNUSED;
01180 {
01181 return 0;
01182 }
01183
01184
01185
01186 static long
01187 srec_get_symtab_upper_bound (abfd)
01188 bfd *abfd;
01189 {
01190 return (bfd_get_symcount (abfd) + 1) * sizeof (asymbol *);
01191 }
01192
01193
01194
01195 static long
01196 srec_canonicalize_symtab (abfd, alocation)
01197 bfd *abfd;
01198 asymbol **alocation;
01199 {
01200 bfd_size_type symcount = bfd_get_symcount (abfd);
01201 asymbol *csymbols;
01202 unsigned int i;
01203
01204 csymbols = abfd->tdata.srec_data->csymbols;
01205 if (csymbols == NULL)
01206 {
01207 asymbol *c;
01208 struct srec_symbol *s;
01209
01210 csymbols = (asymbol *) bfd_alloc (abfd, symcount * sizeof (asymbol));
01211 if (csymbols == NULL && symcount != 0)
01212 return 0;
01213 abfd->tdata.srec_data->csymbols = csymbols;
01214
01215 for (s = abfd->tdata.srec_data->symbols, c = csymbols;
01216 s != NULL;
01217 s = s->next, ++c)
01218 {
01219 c->the_bfd = abfd;
01220 c->name = s->name;
01221 c->value = s->val;
01222 c->flags = BSF_GLOBAL;
01223 c->section = bfd_abs_section_ptr;
01224 c->udata.p = NULL;
01225 }
01226 }
01227
01228 for (i = 0; i < symcount; i++)
01229 *alocation++ = csymbols++;
01230 *alocation = NULL;
01231
01232 return symcount;
01233 }
01234
01235 static void
01236 srec_get_symbol_info (ignore_abfd, symbol, ret)
01237 bfd *ignore_abfd ATTRIBUTE_UNUSED;
01238 asymbol *symbol;
01239 symbol_info *ret;
01240 {
01241 bfd_symbol_info (symbol, ret);
01242 }
01243
01244 static void
01245 srec_print_symbol (abfd, afile, symbol, how)
01246 bfd *abfd;
01247 PTR afile;
01248 asymbol *symbol;
01249 bfd_print_symbol_type how;
01250 {
01251 FILE *file = (FILE *) afile;
01252 switch (how)
01253 {
01254 case bfd_print_symbol_name:
01255 fprintf (file, "%s", symbol->name);
01256 break;
01257 default:
01258 bfd_print_symbol_vandf (abfd, (PTR) file, symbol);
01259 fprintf (file, " %-5s %s",
01260 symbol->section->name,
01261 symbol->name);
01262
01263 }
01264 }
01265
01266 #define srec_close_and_cleanup _bfd_generic_close_and_cleanup
01267 #define srec_bfd_free_cached_info _bfd_generic_bfd_free_cached_info
01268 #define srec_new_section_hook _bfd_generic_new_section_hook
01269
01270 #define srec_bfd_is_target_special_symbol ((bfd_boolean (*) (bfd *, asymbol *)) bfd_false)
01271 #define srec_bfd_is_local_label_name bfd_generic_is_local_label_name
01272 #define srec_get_lineno _bfd_nosymbols_get_lineno
01273 #define srec_find_nearest_line _bfd_nosymbols_find_nearest_line
01274 #define srec_make_empty_symbol _bfd_generic_make_empty_symbol
01275 #define srec_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol
01276 #define srec_read_minisymbols _bfd_generic_read_minisymbols
01277 #define srec_minisymbol_to_symbol _bfd_generic_minisymbol_to_symbol
01278
01279 #define srec_get_reloc_upper_bound \
01280 ((long (*) PARAMS ((bfd *, asection *))) bfd_0l)
01281 #define srec_canonicalize_reloc \
01282 ((long (*) PARAMS ((bfd *, asection *, arelent **, asymbol **))) bfd_0l)
01283 #define srec_bfd_reloc_type_lookup _bfd_norelocs_bfd_reloc_type_lookup
01284
01285 #define srec_get_section_contents_in_window \
01286 _bfd_generic_get_section_contents_in_window
01287
01288 #define srec_bfd_get_relocated_section_contents \
01289 bfd_generic_get_relocated_section_contents
01290 #define srec_bfd_relax_section bfd_generic_relax_section
01291 #define srec_bfd_gc_sections bfd_generic_gc_sections
01292 #define srec_bfd_merge_sections bfd_generic_merge_sections
01293 #define srec_bfd_is_group_section bfd_generic_is_group_section
01294 #define srec_bfd_discard_group bfd_generic_discard_group
01295 #define srec_section_already_linked \
01296 _bfd_generic_section_already_linked
01297 #define srec_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
01298 #define srec_bfd_link_hash_table_free _bfd_generic_link_hash_table_free
01299 #define srec_bfd_link_add_symbols _bfd_generic_link_add_symbols
01300 #define srec_bfd_link_just_syms _bfd_generic_link_just_syms
01301 #define srec_bfd_final_link _bfd_generic_final_link
01302 #define srec_bfd_link_split_section _bfd_generic_link_split_section
01303
01304 const bfd_target srec_vec =
01305 {
01306 "srec",
01307 bfd_target_srec_flavour,
01308 BFD_ENDIAN_UNKNOWN,
01309 BFD_ENDIAN_UNKNOWN,
01310 (HAS_RELOC | EXEC_P |
01311 HAS_LINENO | HAS_DEBUG |
01312 HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
01313 (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS
01314 | SEC_ALLOC | SEC_LOAD | SEC_RELOC),
01315 0,
01316 ' ',
01317 16,
01318 bfd_getb64, bfd_getb_signed_64, bfd_putb64,
01319 bfd_getb32, bfd_getb_signed_32, bfd_putb32,
01320 bfd_getb16, bfd_getb_signed_16, bfd_putb16,
01321 bfd_getb64, bfd_getb_signed_64, bfd_putb64,
01322 bfd_getb32, bfd_getb_signed_32, bfd_putb32,
01323 bfd_getb16, bfd_getb_signed_16, bfd_putb16,
01324
01325 {
01326 _bfd_dummy_target,
01327 srec_object_p,
01328 _bfd_dummy_target,
01329 _bfd_dummy_target,
01330 },
01331 {
01332 bfd_false,
01333 srec_mkobject,
01334 _bfd_generic_mkarchive,
01335 bfd_false,
01336 },
01337 {
01338 bfd_false,
01339 srec_write_object_contents,
01340 _bfd_write_archive_contents,
01341 bfd_false,
01342 },
01343
01344 BFD_JUMP_TABLE_GENERIC (srec),
01345 BFD_JUMP_TABLE_COPY (_bfd_generic),
01346 BFD_JUMP_TABLE_CORE (_bfd_nocore),
01347 BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
01348 BFD_JUMP_TABLE_SYMBOLS (srec),
01349 BFD_JUMP_TABLE_RELOCS (srec),
01350 BFD_JUMP_TABLE_WRITE (srec),
01351 BFD_JUMP_TABLE_LINK (srec),
01352 BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
01353
01354 NULL,
01355
01356 (PTR) 0
01357 };
01358
01359 const bfd_target symbolsrec_vec =
01360 {
01361 "symbolsrec",
01362 bfd_target_srec_flavour,
01363 BFD_ENDIAN_UNKNOWN,
01364 BFD_ENDIAN_UNKNOWN,
01365 (HAS_RELOC | EXEC_P |
01366 HAS_LINENO | HAS_DEBUG |
01367 HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
01368 (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS
01369 | SEC_ALLOC | SEC_LOAD | SEC_RELOC),
01370 0,
01371 ' ',
01372 16,
01373 bfd_getb64, bfd_getb_signed_64, bfd_putb64,
01374 bfd_getb32, bfd_getb_signed_32, bfd_putb32,
01375 bfd_getb16, bfd_getb_signed_16, bfd_putb16,
01376 bfd_getb64, bfd_getb_signed_64, bfd_putb64,
01377 bfd_getb32, bfd_getb_signed_32, bfd_putb32,
01378 bfd_getb16, bfd_getb_signed_16, bfd_putb16,
01379
01380 {
01381 _bfd_dummy_target,
01382 symbolsrec_object_p,
01383 _bfd_dummy_target,
01384 _bfd_dummy_target,
01385 },
01386 {
01387 bfd_false,
01388 srec_mkobject,
01389 _bfd_generic_mkarchive,
01390 bfd_false,
01391 },
01392 {
01393 bfd_false,
01394 symbolsrec_write_object_contents,
01395 _bfd_write_archive_contents,
01396 bfd_false,
01397 },
01398
01399 BFD_JUMP_TABLE_GENERIC (srec),
01400 BFD_JUMP_TABLE_COPY (_bfd_generic),
01401 BFD_JUMP_TABLE_CORE (_bfd_nocore),
01402 BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
01403 BFD_JUMP_TABLE_SYMBOLS (srec),
01404 BFD_JUMP_TABLE_RELOCS (srec),
01405 BFD_JUMP_TABLE_WRITE (srec),
01406 BFD_JUMP_TABLE_LINK (srec),
01407 BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
01408
01409 NULL,
01410
01411 (PTR) 0
01412 };