1 /* srconv.c -- Sysroff conversion program 2 Copyright (C) 1994-2022 Free Software Foundation, Inc. 3 4 This file is part of GNU Binutils. 5 6 This program is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 3 of the License, or 9 (at your option) any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program; if not, write to the Free Software 18 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 19 02110-1301, USA. */ 20 21 /* Written by Steve Chamberlain (sac@cygnus.com) 22 23 This program can be used to convert a coff object file 24 into a Hitachi OM/LM (Sysroff) format. 25 26 All debugging information is preserved */ 27 28 #include "sysdep.h" 29 #include "bfd.h" 30 #include "bucomm.h" 31 #include "sysroff.h" 32 #include "coffgrok.h" 33 #include "libiberty.h" 34 #include "filenames.h" 35 #include "getopt.h" 36 37 #include "coff/internal.h" 38 #include "../bfd/libcoff.h" 39 40 /*#define FOOP1 1 */ 41 42 static int addrsize; 43 static char *toolname; 44 static char **rnames; 45 46 static void walk_tree_symbol 47 (struct coff_sfile *, struct coff_section *, struct coff_symbol *, int); 48 static void walk_tree_scope 49 (struct coff_section *, struct coff_sfile *, struct coff_scope *, int, int); 50 static int find_base (struct coff_sfile *, struct coff_section *); 51 static void wr_globals (struct coff_ofile *, struct coff_sfile *, int); 52 53 static FILE *file; 54 static bfd *abfd; 55 static int debug = 0; 56 static int quick = 0; 57 static int noprescan = 0; 58 static struct coff_ofile *tree; 59 /* Obsolete ?? 60 static int absolute_p; 61 */ 62 63 static int segmented_p; 64 static int code; 65 66 static int ids1[20000]; 67 static int ids2[20000]; 68 69 static int base1 = 0x18; 70 static int base2 = 0x2018; 71 72 static int 73 get_member_id (int x) 74 { 75 if (ids2[x]) 76 return ids2[x]; 77 78 ids2[x] = base2++; 79 return ids2[x]; 80 } 81 82 static int 83 get_ordinary_id (int x) 84 { 85 if (ids1[x]) 86 return ids1[x]; 87 88 ids1[x] = base1++; 89 return ids1[x]; 90 } 91 static char * 92 section_translate (char *n) 93 { 94 if (strcmp (n, ".text") == 0) 95 return "P"; 96 if (strcmp (n, ".data") == 0) 97 return "D"; 98 if (strcmp (n, ".bss") == 0) 99 return "B"; 100 return n; 101 } 102 103 #define DATE "940201073000"; /* Just a time on my birthday */ 104 105 static char * 106 strip_suffix (const char *name) 107 { 108 int i; 109 char *res; 110 111 for (i = 0; name[i] != 0 && name[i] != '.'; i++) 112 ; 113 res = (char *) xmalloc (i + 1); 114 memcpy (res, name, i); 115 res[i] = 0; 116 return res; 117 } 118 119 /* IT LEN stuff CS */ 120 static void 121 checksum (FILE *ffile, unsigned char *ptr, int size, int ccode) 122 { 123 int j; 124 int last; 125 int sum = 0; 126 int bytes = size / 8; 127 128 last = !(ccode & 0xff00); 129 if (size & 0x7) 130 fatal (_("Checksum failure")); 131 132 ptr[0] = ccode | (last ? 0x80 : 0); 133 ptr[1] = bytes + 1; 134 135 for (j = 0; j < bytes; j++) 136 sum += ptr[j]; 137 138 /* Glue on a checksum too. */ 139 ptr[bytes] = ~sum; 140 if (fwrite (ptr, bytes + 1, 1, ffile) != 1) 141 /* FIXME: Return error status. */ 142 fatal (_("Failed to write checksum")); 143 } 144 145 146 static void 147 writeINT (int n, unsigned char *ptr, int *idx, int size, FILE *ffile) 148 { 149 int byte = *idx / 8; 150 151 if (size == -2) 152 size = addrsize; 153 else if (size == -1) 154 size = 0; 155 156 if (byte > 240) 157 { 158 /* Lets write out that record and do another one. */ 159 checksum (ffile, ptr, *idx, code | 0x1000); 160 *idx = 16; 161 byte = *idx / 8; 162 } 163 164 switch (size) 165 { 166 case 0: 167 break; 168 case 1: 169 ptr[byte] = n; 170 break; 171 case 2: 172 ptr[byte + 0] = n >> 8; 173 ptr[byte + 1] = n; 174 break; 175 case 4: 176 ptr[byte + 0] = n >> 24; 177 ptr[byte + 1] = n >> 16; 178 ptr[byte + 2] = n >> 8; 179 ptr[byte + 3] = n >> 0; 180 break; 181 default: 182 fatal (_("Unsupported integer write size: %d"), size); 183 } 184 *idx += size * 8; 185 } 186 187 static void 188 writeBITS (int val, unsigned char *ptr, int *idx, int size) 189 { 190 int byte = *idx / 8; 191 int bit = *idx % 8; 192 int old; 193 194 *idx += size; 195 196 old = ptr[byte]; 197 /* Turn off all about to change bits. */ 198 old &= ~((~0 >> (8 - bit - size)) & ((1 << size) - 1)); 199 /* Turn on the bits we want. */ 200 old |= (val & ((1 << size) - 1)) << (8 - bit - size); 201 ptr[byte] = old; 202 } 203 204 static void 205 writeBARRAY (barray data, unsigned char *ptr, int *idx, 206 int size ATTRIBUTE_UNUSED, FILE *ffile) 207 { 208 int i; 209 210 writeINT (data.len, ptr, idx, 1, ffile); 211 for (i = 0; i < data.len; i++) 212 writeINT (data.data[i], ptr, idx, 1, ffile); 213 } 214 215 static void 216 writeCHARS (char *string, unsigned char *ptr, int *idx, int size, FILE *ffile) 217 { 218 int i = *idx / 8; 219 220 if (i > 240) 221 { 222 /* Lets write out that record and do another one. */ 223 checksum (ffile, ptr, *idx, code | 0x1000); 224 *idx = 16; 225 i = *idx / 8; 226 } 227 228 if (size == 0) 229 { 230 /* Variable length string. */ 231 size = strlen (string); 232 ptr[i++] = size; 233 } 234 235 /* BUG WAITING TO HAPPEN. */ 236 memcpy (ptr + i, string, size); 237 i += size; 238 *idx = i * 8; 239 } 240 241 #define SYSROFF_SWAP_OUT 242 #include "sysroff.c" 243 244 static char *rname_sh[] = 245 { 246 "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7", "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15" 247 }; 248 249 static char *rname_h8300[] = 250 { 251 "ER0", "ER1", "ER2", "ER3", "ER4", "ER5", "ER6", "ER7", "PC", "CCR" 252 }; 253 254 static void 255 wr_tr (void) 256 { 257 /* The TR block is not normal - it doesn't have any contents. */ 258 259 static char b[] = 260 { 261 0xff, /* IT */ 262 0x03, /* RL */ 263 0xfd, /* CS */ 264 }; 265 266 if (fwrite (b, sizeof (b), 1, file) != 1) 267 /* FIXME: Return error status. */ 268 fatal (_("Failed to write TR block")); 269 } 270 271 static void 272 wr_un (struct coff_ofile *ptr, struct coff_sfile *sfile, int first, 273 int nsecs ATTRIBUTE_UNUSED) 274 { 275 struct IT_un un; 276 struct coff_symbol *s; 277 278 un.spare1 = 0; 279 280 if (bfd_get_file_flags (abfd) & EXEC_P) 281 un.format = FORMAT_LM; 282 else 283 un.format = FORMAT_OM; 284 un.spare1 = 0; 285 286 /* Don't count the abs section. */ 287 un.nsections = ptr->nsections - 1; 288 289 un.nextdefs = 0; 290 un.nextrefs = 0; 291 /* Count all the undefined and defined variables with global scope. */ 292 293 if (first) 294 { 295 for (s = ptr->symbol_list_head; s; s = s->next_in_ofile_list) 296 { 297 if (s->visible->type == coff_vis_ext_def 298 || s->visible->type == coff_vis_common) 299 un.nextdefs++; 300 301 if (s->visible->type == coff_vis_ext_ref) 302 un.nextrefs++; 303 } 304 } 305 un.tool = toolname; 306 un.tcd = DATE; 307 un.linker = "L_GX00"; 308 un.lcd = DATE; 309 un.name = sfile->name; 310 sysroff_swap_un_out (file, &un); 311 } 312 313 static void 314 wr_hd (struct coff_ofile *p) 315 { 316 struct IT_hd hd; 317 318 hd.spare1 = 0; 319 hd.spare2 = 0; 320 if (bfd_get_file_flags (abfd) & EXEC_P) 321 hd.mt = MTYPE_ABS_LM; 322 else 323 hd.mt = MTYPE_OMS_OR_LMS; 324 325 hd.cd = DATE; 326 327 hd.nu = p->nsources; /* Always one unit */ 328 hd.code = 0; /* Always ASCII */ 329 hd.ver = "0200"; /* Version 2.00 */ 330 331 switch (bfd_get_arch (abfd)) 332 { 333 case bfd_arch_h8300: 334 hd.au = 8; 335 hd.si = 0; 336 hd.spcsz = 32; 337 hd.segsz = 0; 338 hd.segsh = 0; 339 switch (bfd_get_mach (abfd)) 340 { 341 case bfd_mach_h8300: 342 hd.cpu = "H8300"; 343 hd.afl = 2; 344 addrsize = 2; 345 toolname = "C_H8/300"; 346 break; 347 case bfd_mach_h8300h: 348 hd.cpu = "H8300H"; 349 hd.afl = 4; 350 addrsize = 4; 351 toolname = "C_H8/300H"; 352 break; 353 case bfd_mach_h8300s: 354 hd.cpu = "H8300S"; 355 hd.afl = 4; 356 addrsize = 4; 357 toolname = "C_H8/300S"; 358 break; 359 default: 360 fatal (_("Unrecognized H8300 sub-architecture: %ld"), 361 bfd_get_mach (abfd)); 362 } 363 rnames = rname_h8300; 364 break; 365 case bfd_arch_sh: 366 hd.au = 8; 367 hd.si = 0; 368 hd.afl = 4; 369 hd.spcsz = 32; 370 hd.segsz = 0; 371 hd.segsh = 0; 372 hd.cpu = "SH"; 373 addrsize = 4; 374 toolname = "C_SH"; 375 rnames = rname_sh; 376 break; 377 default: 378 fatal (_("Unsupported architecture: %d"), bfd_get_arch (abfd)); 379 } 380 381 if (! (bfd_get_file_flags(abfd) & EXEC_P)) 382 { 383 hd.ep = 0; 384 } 385 else 386 { 387 hd.ep = 1; 388 hd.uan = 0; 389 hd.sa = 0; 390 hd.sad = 0; 391 hd.address = bfd_get_start_address (abfd); 392 } 393 394 hd.os = ""; 395 hd.sys = ""; 396 hd.mn = strip_suffix (bfd_get_filename (abfd)); 397 398 sysroff_swap_hd_out (file, &hd); 399 } 400 401 402 static void 403 wr_sh (struct coff_ofile *p ATTRIBUTE_UNUSED, struct coff_section *sec) 404 { 405 struct IT_sh sh; 406 sh.unit = 0; 407 sh.section = sec->number; 408 #ifdef FOOP1 409 sh.section = 0; 410 #endif 411 sysroff_swap_sh_out (file, &sh); 412 } 413 414 415 static void 416 wr_ob (struct coff_ofile *p ATTRIBUTE_UNUSED, struct coff_section *section) 417 { 418 bfd_size_type i; 419 int first = 1; 420 unsigned char stuff[200]; 421 422 i = 0; 423 while (i < bfd_section_size (section->bfd_section)) 424 { 425 struct IT_ob ob; 426 int todo = 200; /* Copy in 200 byte lumps. */ 427 428 ob.spare = 0; 429 if (i + todo > bfd_section_size (section->bfd_section)) 430 todo = bfd_section_size (section->bfd_section) - i; 431 432 if (first) 433 { 434 ob.saf = 1; 435 if (bfd_get_file_flags (abfd) & EXEC_P) 436 ob.address = section->address; 437 else 438 ob.address = 0; 439 440 first = 0; 441 } 442 else 443 { 444 ob.saf = 0; 445 } 446 447 ob.cpf = 0; /* Never compress. */ 448 ob.data.len = todo; 449 bfd_get_section_contents (abfd, section->bfd_section, stuff, i, todo); 450 ob.data.data = stuff; 451 sysroff_swap_ob_out (file, &ob /*, i + todo < section->size */ ); 452 i += todo; 453 } 454 455 /* Now fill the rest with blanks. */ 456 while (i < (bfd_size_type) section->size) 457 { 458 struct IT_ob ob; 459 int todo = 200; /* Copy in 200 byte lumps. */ 460 461 ob.spare = 0; 462 if (i + todo > (bfd_size_type) section->size) 463 todo = section->size - i; 464 ob.saf = 0; 465 466 ob.cpf = 0; /* Never compress. */ 467 ob.data.len = todo; 468 memset (stuff, 0, todo); 469 ob.data.data = stuff; 470 sysroff_swap_ob_out (file, &ob); 471 i += todo; 472 } 473 /* Now fill the rest with blanks. */ 474 } 475 476 static void 477 wr_rl (struct coff_ofile *ptr ATTRIBUTE_UNUSED, struct coff_section *sec) 478 { 479 int nr = sec->nrelocs; 480 int i; 481 482 for (i = 0; i < nr; i++) 483 { 484 struct coff_reloc *r = sec->relocs + i; 485 struct coff_symbol *ref; 486 struct IT_rl rl; 487 488 rl.apol = 0; 489 rl.boundary = 0; 490 rl.segment = 1; 491 rl.sign = 0; 492 rl.check = 0; 493 rl.addr = r->offset; 494 rl.bitloc = 0; 495 rl.flen = 32; /* SH Specific. */ 496 497 /* What sort of reloc ? Look in the section to find out. */ 498 ref = r->symbol; 499 if (ref->visible->type == coff_vis_ext_ref) 500 { 501 rl.bcount = 4; /* Always 4 for us. */ 502 rl.op = OP_EXT_REF; 503 rl.symn = ref->er_number; 504 } 505 else if (ref->visible->type == coff_vis_common) 506 { 507 rl.bcount = 11; /* Always 11 for us. */ 508 rl.op = OP_SEC_REF; 509 rl.secn = ref->where->section->number; 510 rl.copcode_is_3 = 3; 511 rl.alength_is_4 = 4; 512 rl.addend = ref->where->offset - ref->where->section->address; 513 rl.aopcode_is_0x20 = 0x20; 514 } 515 else 516 { 517 rl.bcount = 11; /* Always 11 for us. */ 518 rl.op = OP_SEC_REF; 519 rl.secn = ref->where->section->number; 520 rl.copcode_is_3 = 3; 521 rl.alength_is_4 = 4; 522 rl.addend = -ref->where->section->address; 523 rl.aopcode_is_0x20 = 0x20; 524 } 525 526 rl.end = 0xff; 527 528 if ( rl.op == OP_SEC_REF 529 || rl.op == OP_EXT_REF) 530 sysroff_swap_rl_out (file, &rl); 531 } 532 } 533 534 static void 535 wr_object_body (struct coff_ofile *p) 536 { 537 int i; 538 539 for (i = 1; i < p->nsections; i++) 540 { 541 wr_sh (p, p->sections + i); 542 wr_ob (p, p->sections + i); 543 wr_rl (p, p->sections + i); 544 } 545 } 546 547 static void 548 wr_dps_start (struct coff_sfile *sfile, 549 struct coff_section *section ATTRIBUTE_UNUSED, 550 struct coff_scope *scope, int type, int nest) 551 { 552 struct IT_dps dps; 553 554 dps.end = 0; 555 dps.opt = 0; 556 dps.type = type; 557 558 if (scope->sec) 559 { 560 dps.san = scope->sec->number; 561 dps.address = scope->offset - find_base (sfile, scope->sec); 562 dps.block_size = scope->size; 563 564 if (debug) 565 { 566 printf ("DPS %s %d %x\n", 567 sfile->name, 568 nest, 569 dps.address); 570 } 571 } 572 else 573 { 574 dps.san = 0; 575 dps.address = 0; 576 dps.block_size = 0; 577 } 578 579 dps.nesting = nest; 580 dps.neg = 0x1001; 581 sysroff_swap_dps_out (file, &dps); 582 } 583 584 static void 585 wr_dps_end (struct coff_section *section ATTRIBUTE_UNUSED, 586 struct coff_scope *scope ATTRIBUTE_UNUSED, int type) 587 { 588 struct IT_dps dps; 589 590 dps.end = 1; 591 dps.type = type; 592 sysroff_swap_dps_out (file, &dps); 593 } 594 595 static int * 596 nints (int x) 597 { 598 return (int *) (xcalloc (sizeof (int), x)); 599 } 600 601 static void 602 walk_tree_type_1 (struct coff_sfile *sfile, struct coff_symbol *symbol, 603 struct coff_type *type, int nest) 604 { 605 switch (type->type) 606 { 607 case coff_secdef_type: 608 case coff_basic_type: 609 { 610 struct IT_dbt dbt; 611 612 switch (type->u.basic) 613 { 614 case T_NULL: 615 case T_VOID: 616 dbt.btype = BTYPE_VOID; 617 dbt.sign = BTYPE_UNSPEC; 618 dbt.fptype = FPTYPE_NOTSPEC; 619 break; 620 621 case T_CHAR: 622 dbt.btype = BTYPE_CHAR; 623 dbt.sign = BTYPE_UNSPEC; 624 dbt.fptype = FPTYPE_NOTSPEC; 625 break; 626 627 case T_SHORT: 628 case T_INT: 629 case T_LONG: 630 dbt.btype = BTYPE_INT; 631 dbt.sign = SIGN_SIGNED; 632 dbt.fptype = FPTYPE_NOTSPEC; 633 break; 634 635 case T_FLOAT: 636 dbt.btype = BTYPE_FLOAT; 637 dbt.fptype = FPTYPE_SINGLE; 638 break; 639 640 case T_DOUBLE: 641 dbt.btype = BTYPE_FLOAT; 642 dbt.fptype = FPTYPE_DOUBLE; 643 break; 644 645 case T_LNGDBL: 646 dbt.btype = BTYPE_FLOAT; 647 dbt.fptype = FPTYPE_EXTENDED; 648 break; 649 650 case T_UCHAR: 651 dbt.btype = BTYPE_CHAR; 652 dbt.sign = SIGN_UNSIGNED; 653 dbt.fptype = FPTYPE_NOTSPEC; 654 break; 655 656 case T_USHORT: 657 case T_UINT: 658 case T_ULONG: 659 dbt.btype = BTYPE_INT; 660 dbt.sign = SIGN_UNSIGNED; 661 dbt.fptype = FPTYPE_NOTSPEC; 662 break; 663 } 664 665 dbt.bitsize = type->size; 666 dbt.neg = 0x1001; 667 sysroff_swap_dbt_out (file, &dbt); 668 break; 669 } 670 671 case coff_pointer_type: 672 { 673 struct IT_dpt dpt; 674 675 dpt.dunno = 0; 676 walk_tree_type_1 (sfile, symbol, type->u.pointer.points_to, nest + 1); 677 dpt.neg = 0x1001; 678 sysroff_swap_dpt_out (file, &dpt); 679 break; 680 } 681 682 case coff_function_type: 683 { 684 struct IT_dfp dfp; 685 struct coff_symbol *param; 686 687 dfp.end = 0; 688 dfp.spare = 0; 689 dfp.nparams = type->u.function.parameters->nvars; 690 dfp.neg = 0x1001; 691 692 walk_tree_type_1 (sfile, symbol, type->u.function.function_returns, nest + 1); 693 694 sysroff_swap_dfp_out (file, &dfp); 695 696 for (param = type->u.function.parameters->vars_head; 697 param; 698 param = param->next) 699 walk_tree_symbol (sfile, 0, param, nest); 700 701 dfp.end = 1; 702 sysroff_swap_dfp_out (file, &dfp); 703 break; 704 } 705 706 case coff_structdef_type: 707 { 708 struct IT_dbt dbt; 709 struct IT_dds dds; 710 struct coff_symbol *member; 711 712 dds.spare = 0; 713 dbt.btype = BTYPE_STRUCT; 714 dbt.bitsize = type->size; 715 dbt.sign = SIGN_UNSPEC; 716 dbt.fptype = FPTYPE_NOTSPEC; 717 dbt.sid = get_member_id (type->u.astructdef.idx); 718 dbt.neg = 0x1001; 719 sysroff_swap_dbt_out (file, &dbt); 720 dds.end = 0; 721 dds.neg = 0x1001; 722 sysroff_swap_dds_out (file, &dds); 723 724 for (member = type->u.astructdef.elements->vars_head; 725 member; 726 member = member->next) 727 walk_tree_symbol (sfile, 0, member, nest + 1); 728 729 dds.end = 1; 730 sysroff_swap_dds_out (file, &dds); 731 732 } 733 break; 734 735 case coff_structref_type: 736 { 737 struct IT_dbt dbt; 738 739 dbt.btype = BTYPE_TAG; 740 dbt.bitsize = type->size; 741 dbt.sign = SIGN_UNSPEC; 742 dbt.fptype = FPTYPE_NOTSPEC; 743 744 if (type->u.astructref.ref) 745 dbt.sid = get_member_id (type->u.astructref.ref->number); 746 else 747 dbt.sid = 0; 748 749 dbt.neg = 0x1001; 750 sysroff_swap_dbt_out (file, &dbt); 751 } 752 break; 753 754 case coff_array_type: 755 { 756 struct IT_dar dar; 757 int j; 758 int dims = 1; /* Only output one dimension at a time. */ 759 760 dar.dims = dims; 761 dar.variable = nints (dims); 762 dar.subtype = nints (dims); 763 dar.spare = nints (dims); 764 dar.max_variable = nints (dims); 765 dar.maxspare = nints (dims); 766 dar.max = nints (dims); 767 dar.min_variable = nints (dims); 768 dar.min = nints (dims); 769 dar.minspare = nints (dims); 770 dar.neg = 0x1001; 771 dar.length = type->size / type->u.array.dim; 772 773 for (j = 0; j < dims; j++) 774 { 775 dar.variable[j] = VARIABLE_FIXED; 776 dar.subtype[j] = SUB_INTEGER; 777 dar.spare[j] = 0; 778 dar.max_variable[j] = 0; 779 dar.max[j] = type->u.array.dim; 780 dar.min_variable[j] = 0; 781 dar.min[j] = 1; /* Why isn't this 0 ? */ 782 } 783 walk_tree_type_1 (sfile, symbol, type->u.array.array_of, nest + 1); 784 sysroff_swap_dar_out (file, &dar); 785 } 786 break; 787 788 case coff_enumdef_type: 789 { 790 struct IT_dbt dbt; 791 struct IT_den den; 792 struct coff_symbol *member; 793 794 dbt.btype = BTYPE_ENUM; 795 dbt.bitsize = type->size; 796 dbt.sign = SIGN_UNSPEC; 797 dbt.fptype = FPTYPE_NOTSPEC; 798 dbt.sid = get_member_id (type->u.aenumdef.idx); 799 dbt.neg = 0x1001; 800 sysroff_swap_dbt_out (file, &dbt); 801 802 den.end = 0; 803 den.neg = 0x1001; 804 den.spare = 0; 805 sysroff_swap_den_out (file, &den); 806 807 for (member = type->u.aenumdef.elements->vars_head; 808 member; 809 member = member->next) 810 walk_tree_symbol (sfile, 0, member, nest + 1); 811 812 den.end = 1; 813 sysroff_swap_den_out (file, &den); 814 } 815 break; 816 817 case coff_enumref_type: 818 { 819 struct IT_dbt dbt; 820 821 dbt.btype = BTYPE_TAG; 822 dbt.bitsize = type->size; 823 dbt.sign = SIGN_UNSPEC; 824 dbt.fptype = FPTYPE_NOTSPEC; 825 dbt.sid = get_member_id (type->u.aenumref.ref->number); 826 dbt.neg = 0x1001; 827 sysroff_swap_dbt_out (file, &dbt); 828 } 829 break; 830 831 default: 832 fatal (_("Unrecognised type: %d"), type->type); 833 } 834 } 835 836 /* Obsolete ? 837 static void 838 dty_start () 839 { 840 struct IT_dty dty; 841 dty.end = 0; 842 dty.neg = 0x1001; 843 dty.spare = 0; 844 sysroff_swap_dty_out (file, &dty); 845 } 846 847 static void 848 dty_stop () 849 { 850 struct IT_dty dty; 851 dty.end = 0; 852 dty.neg = 0x1001; 853 dty.end = 1; 854 sysroff_swap_dty_out (file, &dty); 855 } 856 857 858 static void 859 dump_tree_structure (sfile, symbol, type, nest) 860 struct coff_sfile *sfile; 861 struct coff_symbol *symbol; 862 struct coff_type *type; 863 int nest; 864 { 865 if (symbol->type->type == coff_function_type) 866 { 867 868 869 } 870 871 } 872 */ 873 874 static void 875 walk_tree_type (struct coff_sfile *sfile, struct coff_symbol *symbol, 876 struct coff_type *type, int nest) 877 { 878 struct IT_dty dty; 879 880 dty.spare = 0; 881 dty.end = 0; 882 dty.neg = 0x1001; 883 884 if (symbol->type->type == coff_function_type) 885 { 886 sysroff_swap_dty_out (file, &dty); 887 walk_tree_type_1 (sfile, symbol, type, nest); 888 dty.end = 1; 889 sysroff_swap_dty_out (file, &dty); 890 891 wr_dps_start (sfile, 892 symbol->where->section, 893 symbol->type->u.function.code, 894 BLOCK_TYPE_FUNCTION, nest); 895 wr_dps_start (sfile, symbol->where->section, 896 symbol->type->u.function.code, 897 BLOCK_TYPE_BLOCK, nest); 898 walk_tree_scope (symbol->where->section, 899 sfile, 900 symbol->type->u.function.code, 901 nest + 1, BLOCK_TYPE_BLOCK); 902 903 wr_dps_end (symbol->where->section, 904 symbol->type->u.function.code, 905 BLOCK_TYPE_BLOCK); 906 wr_dps_end (symbol->where->section, 907 symbol->type->u.function.code, BLOCK_TYPE_FUNCTION); 908 } 909 else 910 { 911 sysroff_swap_dty_out (file, &dty); 912 walk_tree_type_1 (sfile, symbol, type, nest); 913 dty.end = 1; 914 sysroff_swap_dty_out (file, &dty); 915 } 916 } 917 918 static void 919 walk_tree_symbol (struct coff_sfile *sfile, struct coff_section *section ATTRIBUTE_UNUSED, struct coff_symbol *symbol, int nest) 920 { 921 struct IT_dsy dsy; 922 923 memset (&dsy, 0, sizeof(dsy)); 924 dsy.nesting = nest; 925 926 switch (symbol->type->type) 927 { 928 case coff_function_type: 929 dsy.type = STYPE_FUNC; 930 dsy.assign = 1; 931 break; 932 933 case coff_structref_type: 934 case coff_pointer_type: 935 case coff_array_type: 936 case coff_basic_type: 937 case coff_enumref_type: 938 dsy.type = STYPE_VAR; 939 dsy.assign = 1; 940 break; 941 942 case coff_enumdef_type: 943 dsy.type = STYPE_TAG; 944 dsy.assign = 0; 945 dsy.magic = 2; 946 break; 947 948 case coff_structdef_type: 949 dsy.type = STYPE_TAG; 950 dsy.assign = 0; 951 dsy.magic = symbol->type->u.astructdef.isstruct ? 0 : 1; 952 break; 953 954 case coff_secdef_type: 955 return; 956 957 default: 958 fatal (_("Unrecognised coff symbol type: %d"), symbol->type->type); 959 } 960 961 if (symbol->where->where == coff_where_member_of_struct) 962 { 963 dsy.assign = 0; 964 dsy.type = STYPE_MEMBER; 965 } 966 967 if (symbol->where->where == coff_where_member_of_enum) 968 { 969 dsy.type = STYPE_ENUM; 970 dsy.assign = 0; 971 dsy.evallen = 4; 972 dsy.evalue = symbol->where->offset; 973 } 974 975 if (symbol->type->type == coff_structdef_type 976 || symbol->where->where == coff_where_entag 977 || symbol->where->where == coff_where_strtag) 978 { 979 dsy.snumber = get_member_id (symbol->number); 980 } 981 else 982 { 983 dsy.snumber = get_ordinary_id (symbol->number); 984 } 985 986 dsy.sname = symbol->name[0] == '_' ? symbol->name + 1 : symbol->name; 987 988 switch (symbol->visible->type) 989 { 990 case coff_vis_common: 991 case coff_vis_ext_def: 992 dsy.ainfo = AINFO_STATIC_EXT_DEF; 993 break; 994 995 case coff_vis_ext_ref: 996 dsy.ainfo = AINFO_STATIC_EXT_REF; 997 break; 998 999 case coff_vis_int_def: 1000 dsy.ainfo = AINFO_STATIC_INT; 1001 break; 1002 1003 case coff_vis_auto: 1004 case coff_vis_autoparam: 1005 dsy.ainfo = AINFO_AUTO; 1006 break; 1007 1008 case coff_vis_register: 1009 case coff_vis_regparam: 1010 dsy.ainfo = AINFO_REG; 1011 break; 1012 break; 1013 1014 case coff_vis_tag: 1015 case coff_vis_member_of_struct: 1016 case coff_vis_member_of_enum: 1017 break; 1018 1019 default: 1020 fatal (_("Unrecognised coff symbol visibility: %d"), symbol->visible->type); 1021 } 1022 1023 dsy.dlength = symbol->type->size; 1024 1025 switch (symbol->where->where) 1026 { 1027 case coff_where_memory: 1028 1029 dsy.section = symbol->where->section->number; 1030 #ifdef FOOP 1031 dsy.section = 0; 1032 #endif 1033 break; 1034 1035 case coff_where_member_of_struct: 1036 case coff_where_member_of_enum: 1037 case coff_where_stack: 1038 case coff_where_register: 1039 case coff_where_unknown: 1040 case coff_where_strtag: 1041 case coff_where_entag: 1042 case coff_where_typedef: 1043 break; 1044 1045 default: 1046 fatal (_("Unrecognised coff symbol location: %d"), symbol->where->where); 1047 } 1048 1049 switch (symbol->where->where) 1050 { 1051 case coff_where_memory: 1052 dsy.address = symbol->where->offset - find_base (sfile, symbol->where->section); 1053 break; 1054 1055 case coff_where_stack: 1056 dsy.address = symbol->where->offset; 1057 break; 1058 1059 case coff_where_member_of_struct: 1060 if (symbol->where->bitsize) 1061 { 1062 int bits = (symbol->where->offset * 8 + symbol->where->bitoffset); 1063 dsy.bitunit = 1; 1064 dsy.field_len = symbol->where->bitsize; 1065 dsy.field_off = (bits / 32) * 4; 1066 dsy.field_bitoff = bits % 32; 1067 } 1068 else 1069 { 1070 dsy.bitunit = 0; 1071 1072 dsy.field_len = symbol->type->size; 1073 dsy.field_off = symbol->where->offset; 1074 } 1075 break; 1076 1077 case coff_where_member_of_enum: 1078 /* dsy.bitunit = 0; 1079 dsy.field_len = symbol->type->size; 1080 dsy.field_off = symbol->where->offset; */ 1081 break; 1082 1083 case coff_where_register: 1084 case coff_where_unknown: 1085 case coff_where_strtag: 1086 case coff_where_entag: 1087 case coff_where_typedef: 1088 break; 1089 1090 default: 1091 fatal (_("Unrecognised coff symbol location: %d"), symbol->where->where); 1092 } 1093 1094 if (symbol->where->where == coff_where_register) 1095 dsy.reg = rnames[symbol->where->offset]; 1096 1097 switch (symbol->visible->type) 1098 { 1099 case coff_vis_common: 1100 /* We do this 'cause common C symbols are treated as extdefs. */ 1101 case coff_vis_ext_def: 1102 case coff_vis_ext_ref: 1103 dsy.ename = symbol->name; 1104 break; 1105 1106 case coff_vis_regparam: 1107 case coff_vis_autoparam: 1108 dsy.type = STYPE_PARAMETER; 1109 break; 1110 1111 case coff_vis_int_def: 1112 case coff_vis_auto: 1113 case coff_vis_register: 1114 case coff_vis_tag: 1115 case coff_vis_member_of_struct: 1116 case coff_vis_member_of_enum: 1117 break; 1118 1119 default: 1120 fatal (_("Unrecognised coff symbol visibility: %d"), symbol->visible->type); 1121 } 1122 1123 dsy.sfn = 0; 1124 dsy.sln = 2; 1125 dsy.neg = 0x1001; 1126 1127 sysroff_swap_dsy_out (file, &dsy); 1128 1129 walk_tree_type (sfile, symbol, symbol->type, nest); 1130 } 1131 1132 static void 1133 walk_tree_scope (struct coff_section *section, struct coff_sfile *sfile, struct coff_scope *scope, int nest, int type) 1134 { 1135 struct coff_symbol *vars; 1136 struct coff_scope *child; 1137 1138 if (scope->vars_head 1139 || (scope->list_head && scope->list_head->vars_head)) 1140 { 1141 wr_dps_start (sfile, section, scope, type, nest); 1142 1143 if (nest == 0) 1144 wr_globals (tree, sfile, nest + 1); 1145 1146 for (vars = scope->vars_head; vars; vars = vars->next) 1147 walk_tree_symbol (sfile, section, vars, nest); 1148 1149 for (child = scope->list_head; child; child = child->next) 1150 walk_tree_scope (section, sfile, child, nest + 1, BLOCK_TYPE_BLOCK); 1151 1152 wr_dps_end (section, scope, type); 1153 } 1154 } 1155 1156 static void 1157 walk_tree_sfile (struct coff_section *section, struct coff_sfile *sfile) 1158 { 1159 walk_tree_scope (section, sfile, sfile->scope, 0, BLOCK_TYPE_COMPUNIT); 1160 } 1161 1162 static void 1163 wr_program_structure (struct coff_ofile *p, struct coff_sfile *sfile) 1164 { 1165 if (p->nsections < 4) 1166 return; 1167 walk_tree_sfile (p->sections + 4, sfile); 1168 } 1169 1170 static void 1171 wr_du (struct coff_ofile *p, struct coff_sfile *sfile, int n) 1172 { 1173 struct IT_du du; 1174 int lim; 1175 int i; 1176 int j; 1177 unsigned int *lowest = (unsigned *) nints (p->nsections); 1178 unsigned int *highest = (unsigned *) nints (p->nsections); 1179 1180 du.format = bfd_get_file_flags (abfd) & EXEC_P ? 0 : 1; 1181 du.optimized = 0; 1182 du.stackfrmt = 0; 1183 du.spare = 0; 1184 du.unit = n; 1185 du.sections = p->nsections - 1; 1186 du.san = (int *) xcalloc (sizeof (int), du.sections); 1187 du.address = nints (du.sections); 1188 du.length = nints (du.sections); 1189 1190 for (i = 0; i < du.sections; i++) 1191 { 1192 lowest[i] = ~0; 1193 highest[i] = 0; 1194 } 1195 1196 lim = du.sections; 1197 for (j = 0; j < lim; j++) 1198 { 1199 int src = j; 1200 int dst = j; 1201 1202 du.san[dst] = dst; 1203 1204 if (sfile->section[src].init) 1205 { 1206 du.length[dst] 1207 = sfile->section[src].high - sfile->section[src].low + 1; 1208 du.address[dst] 1209 = sfile->section[src].low; 1210 } 1211 else 1212 { 1213 du.length[dst] = 0; 1214 du.address[dst] = 0; 1215 } 1216 1217 if (debug) 1218 { 1219 if (sfile->section[src].parent) 1220 { 1221 printf (" section %6s 0x%08x..0x%08x\n", 1222 sfile->section[src].parent->name, 1223 du.address[dst], 1224 du.address[dst] + du.length[dst] - 1); 1225 } 1226 } 1227 1228 du.sections = dst + 1; 1229 } 1230 1231 du.tool = "c_gcc"; 1232 du.date = DATE; 1233 1234 sysroff_swap_du_out (file, &du); 1235 } 1236 1237 static void 1238 wr_dus (struct coff_ofile *p ATTRIBUTE_UNUSED, struct coff_sfile *sfile) 1239 { 1240 struct IT_dus dus; 1241 1242 dus.efn = 0x1001; 1243 dus.ns = 1; /* p->nsources; sac 14 jul 94 */ 1244 dus.drb = nints (dus.ns); 1245 dus.fname = (char **) xcalloc (sizeof (char *), dus.ns); 1246 dus.spare = nints (dus.ns); 1247 dus.ndir = 0; 1248 /* Find the filenames. */ 1249 dus.drb[0] = 0; 1250 dus.fname[0] = sfile->name; 1251 1252 sysroff_swap_dus_out (file, &dus); 1253 1254 } 1255 1256 /* Find the offset of the .text section for this sfile in the 1257 .text section for the output file. */ 1258 1259 static int 1260 find_base (struct coff_sfile *sfile, struct coff_section *section) 1261 { 1262 return sfile->section[section->number].low; 1263 } 1264 1265 static void 1266 wr_dln (struct coff_ofile *p ATTRIBUTE_UNUSED, struct coff_sfile *sfile, 1267 int n ATTRIBUTE_UNUSED) 1268 { 1269 /* Count up all the linenumbers */ 1270 1271 struct coff_symbol *sy; 1272 int lc = 0; 1273 struct IT_dln dln; 1274 1275 int idx; 1276 1277 for (sy = sfile->scope->vars_head; 1278 sy; 1279 sy = sy->next) 1280 { 1281 struct coff_type *t = sy->type; 1282 if (t->type == coff_function_type) 1283 { 1284 struct coff_line *l = t->u.function.lines; 1285 if (l) 1286 lc += l->nlines; 1287 } 1288 } 1289 1290 dln.sfn = nints (lc); 1291 dln.sln = nints (lc); 1292 dln.cc = nints (lc); 1293 dln.section = nints (lc); 1294 1295 dln.from_address = nints (lc); 1296 dln.to_address = nints (lc); 1297 1298 1299 dln.neg = 0x1001; 1300 1301 dln.nln = lc; 1302 1303 /* Run through once more and fill up the structure */ 1304 idx = 0; 1305 for (sy = sfile->scope->vars_head; 1306 sy; 1307 sy = sy->next) 1308 { 1309 if (sy->type->type == coff_function_type) 1310 { 1311 int i; 1312 struct coff_line *l = sy->type->u.function.lines; 1313 if (l) 1314 { 1315 int base = find_base (sfile, sy->where->section); 1316 for (i = 0; i < l->nlines; i++) 1317 { 1318 dln.section[idx] = sy->where->section->number; 1319 dln.sfn[idx] = 0; 1320 dln.sln[idx] = l->lines[i]; 1321 dln.from_address[idx] = 1322 l->addresses[i] + sy->where->section->address - base; 1323 dln.cc[idx] = 0; 1324 if (idx) 1325 dln.to_address[idx - 1] = dln.from_address[idx]; 1326 idx++; 1327 1328 } 1329 dln.to_address[idx - 1] = dln.from_address[idx - 1] + 2; 1330 } 1331 } 1332 } 1333 if (lc) 1334 sysroff_swap_dln_out (file, &dln); 1335 } 1336 1337 /* Write the global symbols out to the debug info. */ 1338 1339 static void 1340 wr_globals (struct coff_ofile *p, struct coff_sfile *sfile, 1341 int n ATTRIBUTE_UNUSED) 1342 { 1343 struct coff_symbol *sy; 1344 1345 for (sy = p->symbol_list_head; 1346 sy; 1347 sy = sy->next_in_ofile_list) 1348 { 1349 if (sy->visible->type == coff_vis_ext_def 1350 || sy->visible->type == coff_vis_ext_ref) 1351 { 1352 /* Only write out symbols if they belong to 1353 the current source file. */ 1354 if (sy->sfile == sfile) 1355 walk_tree_symbol (sfile, 0, sy, 0); 1356 } 1357 } 1358 } 1359 1360 static void 1361 wr_debug (struct coff_ofile *p) 1362 { 1363 struct coff_sfile *sfile; 1364 int n = 0; 1365 1366 for (sfile = p->source_head; 1367 sfile; 1368 sfile = sfile->next) 1369 { 1370 if (debug) 1371 printf ("%s\n", sfile->name); 1372 1373 wr_du (p, sfile, n); 1374 wr_dus (p, sfile); 1375 wr_program_structure (p, sfile); 1376 wr_dln (p, sfile, n); 1377 n++; 1378 } 1379 } 1380 1381 static void 1382 wr_cs (void) 1383 { 1384 /* It seems that the CS struct is not normal - the size is wrong 1385 heres one I prepared earlier. */ 1386 static char b[] = 1387 { 1388 0x80, /* IT */ 1389 0x21, /* RL */ 1390 0x00, /* number of chars in variable length part */ 1391 0x80, /* hd */ 1392 0x00, /* hs */ 1393 0x80, /* un */ 1394 0x00, /* us */ 1395 0x80, /* sc */ 1396 0x00, /* ss */ 1397 0x80, /* er */ 1398 0x80, /* ed */ 1399 0x80, /* sh */ 1400 0x80, /* ob */ 1401 0x80, /* rl */ 1402 0x80, /* du */ 1403 0x80, /* dps */ 1404 0x80, /* dsy */ 1405 0x80, /* dty */ 1406 0x80, /* dln */ 1407 0x80, /* dso */ 1408 0x80, /* dus */ 1409 0x00, /* dss */ 1410 0x80, /* dbt */ 1411 0x00, /* dpp */ 1412 0x80, /* dfp */ 1413 0x80, /* den */ 1414 0x80, /* dds */ 1415 0x80, /* dar */ 1416 0x80, /* dpt */ 1417 0x00, /* dul */ 1418 0x00, /* dse */ 1419 0x00, /* dot */ 1420 0xDE /* CS */ 1421 }; 1422 1423 if (fwrite (b, sizeof (b), 1, file) != 1) 1424 /* FIXME: Return error status. */ 1425 fatal (_("Failed to write CS struct")); 1426 } 1427 1428 /* Write out the SC records for a unit. Create an SC 1429 for all the sections which appear in the output file, even 1430 if there isn't an equivalent one on the input. */ 1431 1432 static int 1433 wr_sc (struct coff_ofile *ptr, struct coff_sfile *sfile) 1434 { 1435 int i; 1436 int scount = 0; 1437 /* First work out the total number of sections. */ 1438 int total_sec = ptr->nsections; 1439 struct myinfo 1440 { 1441 struct coff_section *sec; 1442 struct coff_symbol *symbol; 1443 }; 1444 struct coff_symbol *symbol; 1445 struct myinfo *info 1446 = (struct myinfo *) calloc (total_sec, sizeof (struct myinfo)); 1447 1448 1449 for (i = 0; i < total_sec; i++) 1450 { 1451 info[i].sec = ptr->sections + i; 1452 info[i].symbol = 0; 1453 } 1454 1455 for (symbol = sfile->scope->vars_head; 1456 symbol; 1457 symbol = symbol->next) 1458 { 1459 1460 if (symbol->type->type == coff_secdef_type) 1461 { 1462 for (i = 0; i < total_sec; i++) 1463 { 1464 if (symbol->where->section == info[i].sec) 1465 { 1466 info[i].symbol = symbol; 1467 break; 1468 } 1469 } 1470 } 1471 } 1472 1473 /* Now output all the section info, and fake up some stuff for sections 1474 we don't have. */ 1475 for (i = 1; i < total_sec; i++) 1476 { 1477 struct IT_sc sc; 1478 char *name; 1479 1480 symbol = info[i].symbol; 1481 sc.spare = 0; 1482 sc.spare1 = 0; 1483 1484 if (!symbol) 1485 { 1486 /* Don't have a symbol set aside for this section, which means 1487 that nothing in this file does anything for the section. */ 1488 sc.format = !(bfd_get_file_flags (abfd) & EXEC_P); 1489 sc.addr = 0; 1490 sc.length = 0; 1491 name = info[i].sec->name; 1492 } 1493 else 1494 { 1495 if (bfd_get_file_flags (abfd) & EXEC_P) 1496 { 1497 sc.format = 0; 1498 sc.addr = symbol->where->offset; 1499 } 1500 else 1501 { 1502 sc.format = 1; 1503 sc.addr = 0; 1504 } 1505 sc.length = symbol->type->size; 1506 name = symbol->name; 1507 } 1508 1509 sc.align = 4; 1510 sc.concat = CONCAT_SIMPLE; 1511 sc.read = 3; 1512 sc.write = 3; 1513 sc.exec = 3; 1514 sc.init = 3; 1515 sc.mode = 3; 1516 sc.spare = 0; 1517 sc.segadd = 0; 1518 sc.spare1 = 0; /* If not zero, then it doesn't work. */ 1519 sc.name = section_translate (name); 1520 1521 if (strlen (sc.name) == 1) 1522 { 1523 switch (sc.name[0]) 1524 { 1525 case 'D': 1526 case 'B': 1527 sc.contents = CONTENTS_DATA; 1528 break; 1529 1530 default: 1531 sc.contents = CONTENTS_CODE; 1532 } 1533 } 1534 else 1535 { 1536 sc.contents = CONTENTS_CODE; 1537 } 1538 1539 sysroff_swap_sc_out (file, &sc); 1540 scount++; 1541 } 1542 free (info); 1543 return scount; 1544 } 1545 1546 /* Write out the ER records for a unit. */ 1547 1548 static void 1549 wr_er (struct coff_ofile *ptr, struct coff_sfile *sfile ATTRIBUTE_UNUSED, 1550 int first) 1551 { 1552 int idx = 0; 1553 struct coff_symbol *sym; 1554 1555 if (first) 1556 { 1557 for (sym = ptr->symbol_list_head; sym; sym = sym->next_in_ofile_list) 1558 { 1559 if (sym->visible->type == coff_vis_ext_ref) 1560 { 1561 struct IT_er er; 1562 1563 er.spare = 0; 1564 er.type = ER_NOTSPEC; 1565 er.name = sym->name; 1566 sysroff_swap_er_out (file, &er); 1567 sym->er_number = idx++; 1568 } 1569 } 1570 } 1571 } 1572 1573 /* Write out the ED records for a unit. */ 1574 1575 static void 1576 wr_ed (struct coff_ofile *ptr, struct coff_sfile *sfile ATTRIBUTE_UNUSED, 1577 int first) 1578 { 1579 struct coff_symbol *s; 1580 1581 if (first) 1582 { 1583 for (s = ptr->symbol_list_head; s; s = s->next_in_ofile_list) 1584 { 1585 if (s->visible->type == coff_vis_ext_def 1586 || s->visible->type == coff_vis_common) 1587 { 1588 struct IT_ed ed; 1589 1590 ed.section = s->where->section->number; 1591 ed.spare = 0; 1592 1593 if (s->where->section->data) 1594 { 1595 ed.type = ED_TYPE_DATA; 1596 } 1597 else if (s->where->section->code & SEC_CODE) 1598 { 1599 ed.type = ED_TYPE_ENTRY; 1600 } 1601 else 1602 { 1603 ed.type = ED_TYPE_NOTSPEC; 1604 ed.type = ED_TYPE_DATA; 1605 } 1606 1607 ed.address = s->where->offset - s->where->section->address; 1608 ed.name = s->name; 1609 sysroff_swap_ed_out (file, &ed); 1610 } 1611 } 1612 } 1613 } 1614 1615 static void 1616 wr_unit_info (struct coff_ofile *ptr) 1617 { 1618 struct coff_sfile *sfile; 1619 int first = 1; 1620 1621 for (sfile = ptr->source_head; 1622 sfile; 1623 sfile = sfile->next) 1624 { 1625 long p1; 1626 long p2; 1627 int nsecs; 1628 1629 p1 = ftell (file); 1630 wr_un (ptr, sfile, first, 0); 1631 nsecs = wr_sc (ptr, sfile); 1632 p2 = ftell (file); 1633 fseek (file, p1, SEEK_SET); 1634 wr_un (ptr, sfile, first, nsecs); 1635 fseek (file, p2, SEEK_SET); 1636 wr_er (ptr, sfile, first); 1637 wr_ed (ptr, sfile, first); 1638 first = 0; 1639 } 1640 } 1641 1642 static void 1643 wr_module (struct coff_ofile *p) 1644 { 1645 wr_cs (); 1646 wr_hd (p); 1647 wr_unit_info (p); 1648 wr_object_body (p); 1649 wr_debug (p); 1650 wr_tr (); 1651 } 1652 1653 static int 1654 align (int x) 1655 { 1656 return (x + 3) & ~3; 1657 } 1658 1659 /* Find all the common variables and turn them into 1660 ordinary defs - dunno why, but thats what hitachi does with 'em. */ 1661 1662 static void 1663 prescan (struct coff_ofile *otree) 1664 { 1665 struct coff_symbol *s; 1666 struct coff_section *common_section; 1667 1668 if (otree->nsections < 3) 1669 return; 1670 1671 /* Find the common section - always section 3. */ 1672 common_section = otree->sections + 3; 1673 1674 for (s = otree->symbol_list_head; 1675 s; 1676 s = s->next_in_ofile_list) 1677 { 1678 if (s->visible->type == coff_vis_common) 1679 { 1680 struct coff_where *w = s->where; 1681 /* s->visible->type = coff_vis_ext_def; leave it as common */ 1682 common_section->size = align (common_section->size); 1683 w->offset = common_section->size + common_section->address; 1684 w->section = common_section; 1685 common_section->size += s->type->size; 1686 common_section->size = align (common_section->size); 1687 } 1688 } 1689 } 1690 1691 ATTRIBUTE_NORETURN static void 1692 show_usage (FILE *ffile, int status) 1693 { 1694 fprintf (ffile, _("Usage: %s [option(s)] in-file [out-file]\n"), program_name); 1695 fprintf (ffile, _("Convert a COFF object file into a SYSROFF object file\n")); 1696 fprintf (ffile, _(" The options are:\n\ 1697 -q --quick (Obsolete - ignored)\n\ 1698 -n --noprescan Do not perform a scan to convert commons into defs\n\ 1699 -d --debug Display information about what is being done\n\ 1700 @<file> Read options from <file>\n\ 1701 -h --help Display this information\n\ 1702 -v --version Print the program's version number\n")); 1703 1704 if (REPORT_BUGS_TO[0] && status == 0) 1705 fprintf (ffile, _("Report bugs to %s\n"), REPORT_BUGS_TO); 1706 exit (status); 1707 } 1708 1709 int 1710 main (int ac, char **av) 1711 { 1712 int opt; 1713 static struct option long_options[] = 1714 { 1715 {"debug", no_argument, 0, 'd'}, 1716 {"quick", no_argument, 0, 'q'}, 1717 {"noprescan", no_argument, 0, 'n'}, 1718 {"help", no_argument, 0, 'h'}, 1719 {"version", no_argument, 0, 'V'}, 1720 {NULL, no_argument, 0, 0} 1721 }; 1722 char **matching; 1723 char *input_file; 1724 char *output_file; 1725 1726 #ifdef HAVE_LC_MESSAGES 1727 setlocale (LC_MESSAGES, ""); 1728 #endif 1729 setlocale (LC_CTYPE, ""); 1730 bindtextdomain (PACKAGE, LOCALEDIR); 1731 textdomain (PACKAGE); 1732 1733 program_name = av[0]; 1734 xmalloc_set_program_name (program_name); 1735 bfd_set_error_program_name (program_name); 1736 1737 expandargv (&ac, &av); 1738 1739 while ((opt = getopt_long (ac, av, "dHhVvqn", long_options, 1740 (int *) NULL)) 1741 != EOF) 1742 { 1743 switch (opt) 1744 { 1745 case 'q': 1746 quick = 1; 1747 break; 1748 case 'n': 1749 noprescan = 1; 1750 break; 1751 case 'd': 1752 debug = 1; 1753 break; 1754 case 'H': 1755 case 'h': 1756 show_usage (stdout, 0); 1757 /*NOTREACHED */ 1758 case 'v': 1759 case 'V': 1760 print_version ("srconv"); 1761 exit (0); 1762 /*NOTREACHED */ 1763 case 0: 1764 break; 1765 default: 1766 show_usage (stderr, 1); 1767 /*NOTREACHED */ 1768 } 1769 } 1770 1771 /* The input and output files may be named on the command line. */ 1772 output_file = NULL; 1773 if (optind < ac) 1774 { 1775 input_file = av[optind]; 1776 ++optind; 1777 if (optind < ac) 1778 { 1779 output_file = av[optind]; 1780 ++optind; 1781 if (optind < ac) 1782 show_usage (stderr, 1); 1783 if (filename_cmp (input_file, output_file) == 0) 1784 { 1785 fatal (_("input and output files must be different")); 1786 } 1787 } 1788 } 1789 else 1790 input_file = 0; 1791 1792 if (!input_file) 1793 { 1794 fatal (_("no input file specified")); 1795 } 1796 1797 if (!output_file) 1798 { 1799 /* Take a .o off the input file and stick on a .obj. If 1800 it doesn't end in .o, then stick a .obj on anyway */ 1801 1802 int len = strlen (input_file); 1803 1804 output_file = xmalloc (len + 5); 1805 strcpy (output_file, input_file); 1806 1807 if (len > 3 1808 && output_file[len - 2] == '.' 1809 && output_file[len - 1] == 'o') 1810 { 1811 output_file[len] = 'b'; 1812 output_file[len + 1] = 'j'; 1813 output_file[len + 2] = 0; 1814 } 1815 else 1816 { 1817 strcat (output_file, ".obj"); 1818 } 1819 } 1820 1821 abfd = bfd_openr (input_file, 0); 1822 1823 if (!abfd) 1824 bfd_fatal (input_file); 1825 1826 if (!bfd_check_format_matches (abfd, bfd_object, &matching)) 1827 { 1828 bfd_nonfatal (input_file); 1829 1830 if (bfd_get_error () == bfd_error_file_ambiguously_recognized) 1831 list_matching_formats (matching); 1832 exit (1); 1833 } 1834 1835 file = fopen (output_file, FOPEN_WB); 1836 1837 if (!file) 1838 fatal (_("unable to open output file %s"), output_file); 1839 1840 if (debug) 1841 printf ("ids %d %d\n", base1, base2); 1842 1843 tree = coff_grok (abfd); 1844 if (tree) 1845 { 1846 if (!noprescan) 1847 prescan (tree); 1848 1849 wr_module (tree); 1850 } 1851 return 0; 1852 } 1853