1/* vms-gsd.c -- BFD back-end for VAX (openVMS/VAX) and 2 EVAX (openVMS/Alpha) files. 3 Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 4 2007 Free Software Foundation, Inc. 5 6 go and read the openVMS linker manual (esp. appendix B) 7 if you don't know what's going on here :-) 8 9 Written by Klaus K"ampf (kkaempf@rmi.de) 10 11 This program is free software; you can redistribute it and/or modify 12 it under the terms of the GNU General Public License as published by 13 the Free Software Foundation; either version 3 of the License, or 14 (at your option) any later version. 15 16 This program is distributed in the hope that it will be useful, 17 but WITHOUT ANY WARRANTY; without even the implied warranty of 18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 GNU General Public License for more details. 20 21 You should have received a copy of the GNU General Public License 22 along with this program; if not, write to the Free Software 23 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, 24 MA 02110-1301, USA. */ 25 26#include "sysdep.h" 27#include "bfd.h" 28#include "bfdlink.h" 29#include "libbfd.h" 30 31#include "vms.h" 32 33/* Typical sections for vax object files. */ 34 35#define VAX_CODE_NAME "$CODE" 36#define VAX_DATA_NAME "$DATA" 37#define VAX_ADDRESS_DATA_NAME "$ADDRESS_DATA" 38 39/* Typical sections for evax object files. */ 40 41#define EVAX_ABS_NAME "$ABS$" 42#define EVAX_CODE_NAME "$CODE$" 43#define EVAX_LINK_NAME "$LINK$" 44#define EVAX_DATA_NAME "$DATA$" 45#define EVAX_BSS_NAME "$BSS$" 46#define EVAX_READONLYADDR_NAME "$READONLY_ADDR$" 47#define EVAX_READONLY_NAME "$READONLY$" 48#define EVAX_LITERAL_NAME "$LITERAL$" 49#define EVAX_COMMON_NAME "$COMMON$" 50#define EVAX_LOCAL_NAME "$LOCAL$" 51 52struct sec_flags_struct 53{ 54 char *name; /* Name of section. */ 55 int vflags_always; 56 flagword flags_always; /* Flags we set always. */ 57 int vflags_hassize; 58 flagword flags_hassize; /* Flags we set if the section has a size > 0. */ 59}; 60 61/* These flags are deccrtl/vaxcrtl (openVMS 6.2 VAX) compatible. */ 62 63static struct sec_flags_struct vax_section_flags[] = 64 { 65 { VAX_CODE_NAME, 66 (GPS_S_M_PIC | GPS_S_M_REL | GPS_S_M_SHR | GPS_S_M_EXE | GPS_S_M_RD), 67 (SEC_CODE), 68 (GPS_S_M_PIC | GPS_S_M_REL | GPS_S_M_SHR | GPS_S_M_EXE | GPS_S_M_RD), 69 (SEC_IN_MEMORY | SEC_CODE | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD) }, 70 { VAX_DATA_NAME, 71 (GPS_S_M_PIC | GPS_S_M_REL | GPS_S_M_RD | GPS_S_M_WRT), 72 (SEC_DATA), 73 (GPS_S_M_PIC | GPS_S_M_REL | GPS_S_M_RD | GPS_S_M_WRT), 74 (SEC_IN_MEMORY | SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD) }, 75 { VAX_ADDRESS_DATA_NAME, 76 (GPS_S_M_PIC | GPS_S_M_REL | GPS_S_M_RD), 77 (SEC_DATA | SEC_READONLY), 78 (GPS_S_M_PIC | GPS_S_M_REL | GPS_S_M_RD), 79 (SEC_IN_MEMORY | SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_READONLY | SEC_LOAD) }, 80 { NULL, 81 (GPS_S_M_PIC | GPS_S_M_OVR | GPS_S_M_REL | GPS_S_M_GBL | GPS_S_M_RD | GPS_S_M_WRT), 82 (SEC_DATA), 83 (GPS_S_M_PIC | GPS_S_M_OVR | GPS_S_M_REL | GPS_S_M_GBL | GPS_S_M_RD | GPS_S_M_WRT), 84 (SEC_IN_MEMORY | SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD) } 85 }; 86 87/* These flags are deccrtl/vaxcrtl (openVMS 6.2 Alpha) compatible. */ 88 89static struct sec_flags_struct evax_section_flags[] = 90 { 91 { EVAX_ABS_NAME, 92 (EGPS_S_V_SHR), 93 (SEC_DATA), 94 (EGPS_S_V_SHR), 95 (SEC_IN_MEMORY | SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD) }, 96 { EVAX_CODE_NAME, 97 (EGPS_S_V_PIC | EGPS_S_V_REL | EGPS_S_V_SHR | EGPS_S_V_EXE), 98 (SEC_CODE), 99 (EGPS_S_V_PIC | EGPS_S_V_REL | EGPS_S_V_SHR | EGPS_S_V_EXE), 100 (SEC_IN_MEMORY | SEC_CODE | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD) }, 101 { EVAX_LITERAL_NAME, 102 (EGPS_S_V_PIC | EGPS_S_V_REL | EGPS_S_V_SHR | EGPS_S_V_RD | EGPS_S_V_NOMOD), 103 (SEC_DATA | SEC_READONLY), 104 (EGPS_S_V_PIC | EGPS_S_V_REL | EGPS_S_V_SHR | EGPS_S_V_RD), 105 (SEC_IN_MEMORY | SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_READONLY | SEC_LOAD) }, 106 { EVAX_LINK_NAME, 107 (EGPS_S_V_REL | EGPS_S_V_RD), 108 (SEC_DATA | SEC_READONLY), 109 (EGPS_S_V_REL | EGPS_S_V_RD), 110 (SEC_IN_MEMORY | SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_READONLY | SEC_LOAD) }, 111 { EVAX_DATA_NAME, 112 (EGPS_S_V_REL | EGPS_S_V_RD | EGPS_S_V_WRT | EGPS_S_V_NOMOD), 113 (SEC_DATA), 114 (EGPS_S_V_REL | EGPS_S_V_RD | EGPS_S_V_WRT), 115 (SEC_IN_MEMORY | SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD) }, 116 { EVAX_BSS_NAME, 117 (EGPS_S_V_REL | EGPS_S_V_RD | EGPS_S_V_WRT | EGPS_S_V_NOMOD), 118 (SEC_NO_FLAGS), 119 (EGPS_S_V_REL | EGPS_S_V_RD | EGPS_S_V_WRT | EGPS_S_V_NOMOD), 120 (SEC_IN_MEMORY | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD) }, 121 { EVAX_READONLYADDR_NAME, 122 (EGPS_S_V_PIC | EGPS_S_V_REL | EGPS_S_V_RD), 123 (SEC_DATA | SEC_READONLY), 124 (EGPS_S_V_PIC | EGPS_S_V_REL | EGPS_S_V_RD), 125 (SEC_IN_MEMORY | SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_READONLY | SEC_LOAD) }, 126 { EVAX_READONLY_NAME, 127 (EGPS_S_V_PIC | EGPS_S_V_REL | EGPS_S_V_SHR | EGPS_S_V_RD | EGPS_S_V_NOMOD), 128 (SEC_DATA | SEC_READONLY), 129 (EGPS_S_V_PIC | EGPS_S_V_REL | EGPS_S_V_SHR | EGPS_S_V_RD), 130 (SEC_IN_MEMORY | SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_READONLY | SEC_LOAD) }, 131 { EVAX_LOCAL_NAME, 132 (EGPS_S_V_REL | EGPS_S_V_RD | EGPS_S_V_WRT), 133 (SEC_DATA), 134 (EGPS_S_V_REL | EGPS_S_V_RD | EGPS_S_V_WRT), 135 (SEC_IN_MEMORY | SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD) }, 136 { NULL, 137 (EGPS_S_V_REL | EGPS_S_V_RD | EGPS_S_V_WRT), 138 (SEC_DATA), 139 (EGPS_S_V_REL | EGPS_S_V_RD | EGPS_S_V_WRT), 140 (SEC_IN_MEMORY | SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD) } 141 }; 142 143/* Retrieve bfd section flags by name and size. */ 144 145static flagword 146vms_secflag_by_name (bfd *abfd, 147 struct sec_flags_struct *section_flags, 148 char *name, 149 int hassize) 150{ 151 int i = 0; 152 153 while (section_flags[i].name != NULL) 154 { 155 if ((PRIV (is_vax)? 156 strcasecmp (name, section_flags[i].name): 157 strcmp (name, section_flags[i].name)) == 0) 158 { 159 if (hassize) 160 return section_flags[i].flags_hassize; 161 else 162 return section_flags[i].flags_always; 163 } 164 i++; 165 } 166 if (hassize) 167 return section_flags[i].flags_hassize; 168 return section_flags[i].flags_always; 169} 170 171/* Retrieve vms section flags by name and size. */ 172 173static flagword 174vms_esecflag_by_name (struct sec_flags_struct *section_flags, 175 char *name, 176 int hassize) 177{ 178 int i = 0; 179 180 while (section_flags[i].name != NULL) 181 { 182 if (strcmp (name, section_flags[i].name) == 0) 183 { 184 if (hassize) 185 return section_flags[i].vflags_hassize; 186 else 187 return section_flags[i].vflags_always; 188 } 189 i++; 190 } 191 if (hassize) 192 return section_flags[i].vflags_hassize; 193 return section_flags[i].vflags_always; 194} 195 196#if VMS_DEBUG 197 198struct flagdescstruct { char *name; flagword value; }; 199 200/* Convert flag to printable string. */ 201 202static char * 203flag2str (struct flagdescstruct * flagdesc, flagword flags) 204{ 205 static char res[64]; 206 int next = 0; 207 208 res[0] = 0; 209 while (flagdesc->name != NULL) 210 { 211 if ((flags & flagdesc->value) != 0) 212 { 213 if (next) 214 strcat (res, ","); 215 else 216 next = 1; 217 strcat (res, flagdesc->name); 218 } 219 flagdesc++; 220 } 221 return res; 222} 223#endif 224 225/* Input routines. */ 226 227/* Process GSD/EGSD record 228 return 0 on success, -1 on error. */ 229 230int 231_bfd_vms_slurp_gsd (bfd * abfd, int objtype) 232{ 233#if VMS_DEBUG 234 static struct flagdescstruct gpsflagdesc[] = 235 { 236 { "PIC", 0x0001 }, 237 { "LIB", 0x0002 }, 238 { "OVR", 0x0004 }, 239 { "REL", 0x0008 }, 240 { "GBL", 0x0010 }, 241 { "SHR", 0x0020 }, 242 { "EXE", 0x0040 }, 243 { "RD", 0x0080 }, 244 { "WRT", 0x0100 }, 245 { "VEC", 0x0200 }, 246 { "NOMOD", 0x0400 }, 247 { "COM", 0x0800 }, 248 { NULL, 0 } 249 }; 250 251 static struct flagdescstruct gsyflagdesc[] = 252 { 253 { "WEAK", 0x0001 }, 254 { "DEF", 0x0002 }, 255 { "UNI", 0x0004 }, 256 { "REL", 0x0008 }, 257 { "COMM", 0x0010 }, 258 { "VECEP", 0x0020 }, 259 { "NORM", 0x0040 }, 260 { NULL, 0 } 261 }; 262#endif 263 264 int gsd_type, gsd_size; 265 asection *section; 266 unsigned char *vms_rec; 267 flagword new_flags, old_flags; 268 char *name; 269 asymbol *symbol; 270 vms_symbol_entry *entry; 271 unsigned long base_addr; 272 unsigned long align_addr; 273 static unsigned int psect_idx = 0; 274 275#if VMS_DEBUG 276 vms_debug (2, "GSD/EGSD (%d/%x)\n", objtype, objtype); 277#endif 278 279 switch (objtype) 280 { 281 case EOBJ_S_C_EGSD: 282 PRIV (vms_rec) += 8; /* Skip type, size, l_temp. */ 283 PRIV (rec_size) -= 8; 284 break; 285 case OBJ_S_C_GSD: 286 PRIV (vms_rec) += 1; 287 PRIV (rec_size) -= 1; 288 break; 289 default: 290 return -1; 291 } 292 293 /* Calculate base address for each section. */ 294 base_addr = 0L; 295 296 abfd->symcount = 0; 297 298 while (PRIV (rec_size) > 0) 299 { 300 vms_rec = PRIV (vms_rec); 301 302 if (objtype == OBJ_S_C_GSD) 303 gsd_type = *vms_rec; 304 else 305 { 306 _bfd_vms_get_header_values (abfd, vms_rec, &gsd_type, &gsd_size); 307 gsd_type += EVAX_OFFSET; 308 } 309 310#if VMS_DEBUG 311 vms_debug (3, "gsd_type %d\n", gsd_type); 312#endif 313 314 switch (gsd_type) 315 { 316 case GSD_S_C_PSC: 317 { 318 /* Program section definition. */ 319 asection *old_section = 0; 320 321#if VMS_DEBUG 322 vms_debug (4, "GSD_S_C_PSC\n"); 323#endif 324 /* If this section isn't a bfd section. */ 325 if (PRIV (is_vax) && (psect_idx < (abfd->section_count-1))) 326 { 327 /* Check for temporary section from TIR record. */ 328 if (psect_idx < PRIV (section_count)) 329 old_section = PRIV (sections)[psect_idx]; 330 else 331 old_section = 0; 332 } 333 334 name = _bfd_vms_save_counted_string (vms_rec + 8); 335 section = bfd_make_section (abfd, name); 336 if (!section) 337 { 338 (*_bfd_error_handler) (_("bfd_make_section (%s) failed"), 339 name); 340 return -1; 341 } 342 old_flags = bfd_getl16 (vms_rec + 2); 343 section->size = bfd_getl32 (vms_rec + 4); /* allocation */ 344 new_flags = vms_secflag_by_name (abfd, vax_section_flags, name, 345 section->size > 0); 346 if (old_flags & EGPS_S_V_REL) 347 new_flags |= SEC_RELOC; 348 if (old_flags & GPS_S_M_OVR) 349 new_flags |= SEC_IS_COMMON; 350 if (!bfd_set_section_flags (abfd, section, new_flags)) 351 { 352 (*_bfd_error_handler) 353 (_("bfd_set_section_flags (%s, %x) failed"), 354 name, new_flags); 355 return -1; 356 } 357 section->alignment_power = vms_rec[1]; 358 align_addr = (1 << section->alignment_power); 359 if ((base_addr % align_addr) != 0) 360 base_addr += (align_addr - (base_addr % align_addr)); 361 section->vma = (bfd_vma)base_addr; 362 base_addr += section->size; 363 364 /* Global section is common symbol. */ 365 366 if (old_flags & GPS_S_M_GBL) 367 { 368 entry = _bfd_vms_enter_symbol (abfd, name); 369 if (entry == NULL) 370 { 371 bfd_set_error (bfd_error_no_memory); 372 return -1; 373 } 374 symbol = entry->symbol; 375 376 symbol->value = 0; 377 symbol->section = section; 378 symbol->flags = (BSF_GLOBAL | BSF_SECTION_SYM | BSF_OLD_COMMON); 379 } 380 381 /* Copy saved contents if old_section set. */ 382 if (old_section != 0) 383 { 384 section->contents = old_section->contents; 385 if (section->size < old_section->size) 386 { 387 (*_bfd_error_handler) 388 (_("Size mismatch section %s=%lx, %s=%lx"), 389 old_section->name, 390 (unsigned long) old_section->size, 391 section->name, 392 (unsigned long) section->size); 393 return -1; 394 } 395 else if (section->size > old_section->size) 396 { 397 section->contents = bfd_realloc (old_section->contents, 398 section->size); 399 if (section->contents == NULL) 400 { 401 bfd_set_error (bfd_error_no_memory); 402 return -1; 403 } 404 } 405 } 406 else 407 { 408 section->contents = bfd_zmalloc (section->size); 409 if (section->contents == NULL) 410 { 411 bfd_set_error (bfd_error_no_memory); 412 return -1; 413 } 414 } 415#if VMS_DEBUG 416 vms_debug (4, "gsd psc %d (%s, flags %04x=%s) ", 417 section->index, name, old_flags, flag2str (gpsflagdesc, old_flags)); 418 vms_debug (4, "%d bytes at 0x%08lx (mem %p)\n", 419 section->size, section->vma, section->contents); 420#endif 421 422 gsd_size = vms_rec[8] + 9; 423 424 psect_idx++; 425 } 426 break; 427 428 case GSD_S_C_EPM: 429 case GSD_S_C_EPMW: 430#if VMS_DEBUG 431 vms_debug (4, "gsd epm\n"); 432#endif 433 /* Fall through. */ 434 case GSD_S_C_SYM: 435 case GSD_S_C_SYMW: 436 { 437 int name_offset = 0, value_offset = 0; 438 439 /* Symbol specification (definition or reference). */ 440#if VMS_DEBUG 441 vms_debug (4, "GSD_S_C_SYM(W)\n"); 442#endif 443 old_flags = bfd_getl16 (vms_rec + 2); 444 new_flags = BSF_NO_FLAGS; 445 446 if (old_flags & GSY_S_M_WEAK) 447 new_flags |= BSF_WEAK; 448 449 switch (gsd_type) 450 { 451 case GSD_S_C_EPM: 452 name_offset = 11; 453 value_offset = 5; 454 new_flags |= BSF_FUNCTION; 455 break; 456 case GSD_S_C_EPMW: 457 name_offset = 12; 458 value_offset = 6; 459 new_flags |= BSF_FUNCTION; 460 break; 461 case GSD_S_C_SYM: 462 if (old_flags & GSY_S_M_DEF) /* Symbol definition. */ 463 name_offset = 9; 464 else 465 name_offset = 4; 466 value_offset = 5; 467 break; 468 case GSD_S_C_SYMW: 469 if (old_flags & GSY_S_M_DEF) /* Symbol definition. */ 470 name_offset = 10; 471 else 472 name_offset = 5; 473 value_offset = 6; 474 break; 475 } 476 477 /* Save symbol in vms_symbol_table. */ 478 entry = _bfd_vms_enter_symbol 479 (abfd, _bfd_vms_save_counted_string (vms_rec + name_offset)); 480 if (entry == NULL) 481 { 482 bfd_set_error (bfd_error_no_memory); 483 return -1; 484 } 485 symbol = entry->symbol; 486 487 if (old_flags & GSY_S_M_DEF) 488 { 489 /* Symbol definition. */ 490 int psect; 491 492 symbol->value = bfd_getl32 (vms_rec + value_offset); 493 if ((gsd_type == GSD_S_C_SYMW) 494 || (gsd_type == GSD_S_C_EPMW)) 495 psect = bfd_getl16 (vms_rec + value_offset - 2); 496 else 497 psect = vms_rec[value_offset-1]; 498 499 symbol->section = (asection *) (size_t) psect; 500#if VMS_DEBUG 501 vms_debug (4, "gsd sym def #%d (%s, %d [%p], %04x=%s)\n", abfd->symcount, 502 symbol->name, (int)symbol->section, symbol->section, old_flags, flag2str (gsyflagdesc, old_flags)); 503#endif 504 } 505 else 506 { 507 /* Symbol reference. */ 508 symbol->section = bfd_make_section (abfd, BFD_UND_SECTION_NAME); 509#if VMS_DEBUG 510 vms_debug (4, "gsd sym ref #%d (%s, %s [%p], %04x=%s)\n", 511 abfd->symcount, symbol->name, symbol->section->name, 512 symbol->section, old_flags, flag2str (gsyflagdesc, old_flags)); 513#endif 514 } 515 516 gsd_size = vms_rec[name_offset] + name_offset + 1; 517 symbol->flags = new_flags; 518 } 519 520 break; 521 522 case GSD_S_C_PRO: 523 case GSD_S_C_PROW: 524#if VMS_DEBUG 525 vms_debug (4, "gsd pro\n"); 526#endif 527 break; 528 case GSD_S_C_IDC: 529#if VMS_DEBUG 530 vms_debug (4, "gsd idc\n"); 531#endif 532 break; 533 case GSD_S_C_ENV: 534#if VMS_DEBUG 535 vms_debug (4, "gsd env\n"); 536#endif 537 break; 538 case GSD_S_C_LSY: 539#if VMS_DEBUG 540 vms_debug (4, "gsd lsy\n"); 541#endif 542 break; 543 case GSD_S_C_LEPM: 544#if VMS_DEBUG 545 vms_debug (4, "gsd lepm\n"); 546#endif 547 break; 548 case GSD_S_C_LPRO: 549#if VMS_DEBUG 550 vms_debug (4, "gsd lpro\n"); 551#endif 552 break; 553 case GSD_S_C_SPSC: 554#if VMS_DEBUG 555 vms_debug (4, "gsd spsc\n"); 556#endif 557 break; 558 case GSD_S_C_SYMV: 559#if VMS_DEBUG 560 vms_debug (4, "gsd symv\n"); 561#endif 562 break; 563 case GSD_S_C_EPMV: 564#if VMS_DEBUG 565 vms_debug (4, "gsd epmv\n"); 566#endif 567 break; 568 case GSD_S_C_PROV: 569#if VMS_DEBUG 570 vms_debug (4, "gsd prov\n"); 571#endif 572 break; 573 574 case EGSD_S_C_PSC + EVAX_OFFSET: 575 { 576 /* Program section definition. */ 577 name = _bfd_vms_save_counted_string (vms_rec + 12); 578 section = bfd_make_section (abfd, name); 579 if (!section) 580 return -1; 581 old_flags = bfd_getl16 (vms_rec + 6); 582 section->size = bfd_getl32 (vms_rec + 8); /* Allocation. */ 583 new_flags = vms_secflag_by_name (abfd, evax_section_flags, name, 584 section->size > 0); 585 if (old_flags & EGPS_S_V_REL) 586 new_flags |= SEC_RELOC; 587 if (!bfd_set_section_flags (abfd, section, new_flags)) 588 return -1; 589 section->alignment_power = vms_rec[4]; 590 align_addr = (1 << section->alignment_power); 591 if ((base_addr % align_addr) != 0) 592 base_addr += (align_addr - (base_addr % align_addr)); 593 section->vma = (bfd_vma)base_addr; 594 base_addr += section->size; 595 section->contents = bfd_zmalloc (section->size); 596 if (section->contents == NULL) 597 return -1; 598#if VMS_DEBUG 599 vms_debug (4, "egsd psc %d (%s, flags %04x=%s) ", 600 section->index, name, old_flags, flag2str (gpsflagdesc, old_flags)); 601 vms_debug (4, "%d bytes at 0x%08lx (mem %p)\n", 602 section->size, section->vma, section->contents); 603#endif 604 } 605 break; 606 607 case EGSD_S_C_SYM + EVAX_OFFSET: 608 { 609 /* Symbol specification (definition or reference). */ 610 symbol = bfd_make_empty_symbol (abfd); 611 if (symbol == 0) 612 return -1; 613 614 old_flags = bfd_getl16 (vms_rec + 6); 615 new_flags = BSF_NO_FLAGS; 616 617 if (old_flags & EGSY_S_V_WEAK) 618 new_flags |= BSF_WEAK; 619 620 if (vms_rec[6] & EGSY_S_V_DEF) 621 { 622 /* Symbol definition. */ 623 symbol->name = _bfd_vms_save_counted_string (vms_rec + 32); 624 if (old_flags & EGSY_S_V_NORM) 625 /* Proc def. */ 626 new_flags |= BSF_FUNCTION; 627 628 symbol->value = bfd_getl64 (vms_rec + 8); 629 symbol->section = (asection *) ((unsigned long) bfd_getl32 (vms_rec + 28)); 630#if VMS_DEBUG 631 vms_debug (4, "egsd sym def #%d (%s, %d, %04x=%s)\n", abfd->symcount, 632 symbol->name, (int) symbol->section, old_flags, 633 flag2str (gsyflagdesc, old_flags)); 634#endif 635 } 636 else 637 { 638 /* Symbol reference. */ 639 symbol->name = _bfd_vms_save_counted_string (vms_rec + 8); 640#if VMS_DEBUG 641 vms_debug (4, "egsd sym ref #%d (%s, %04x=%s)\n", abfd->symcount, 642 symbol->name, old_flags, flag2str (gsyflagdesc, old_flags)); 643#endif 644 symbol->section = bfd_make_section (abfd, BFD_UND_SECTION_NAME); 645 } 646 647 symbol->flags = new_flags; 648 649 /* Save symbol in vms_symbol_table. */ 650 entry = (vms_symbol_entry *) bfd_hash_lookup (PRIV (vms_symbol_table), 651 symbol->name, 652 TRUE, FALSE); 653 if (entry == NULL) 654 { 655 bfd_set_error (bfd_error_no_memory); 656 return -1; 657 } 658 659 if (entry->symbol != NULL) 660 { 661 /* FIXME ?, DEC C generates this. */ 662#if VMS_DEBUG 663 vms_debug (4, "EGSD_S_C_SYM: duplicate \"%s\"\n", symbol->name); 664#endif 665 } 666 else 667 { 668 entry->symbol = symbol; 669 PRIV (gsd_sym_count)++; 670 abfd->symcount++; 671 } 672 } 673 break; 674 675 case EGSD_S_C_IDC + EVAX_OFFSET: 676 break; 677 678 default: 679 (*_bfd_error_handler) (_("unknown gsd/egsd subtype %d"), gsd_type); 680 bfd_set_error (bfd_error_bad_value); 681 return -1; 682 } 683 684 PRIV (rec_size) -= gsd_size; 685 PRIV (vms_rec) += gsd_size; 686 } 687 688 if (abfd->symcount > 0) 689 abfd->flags |= HAS_SYMS; 690 691 return 0; 692} 693 694/* Output routines. */ 695 696/* Write section and symbol directory of bfd abfd. */ 697 698int 699_bfd_vms_write_gsd (bfd *abfd, int objtype ATTRIBUTE_UNUSED) 700{ 701 asection *section; 702 asymbol *symbol; 703 unsigned int symnum; 704 int last_index = -1; 705 char dummy_name[10]; 706 char *sname; 707 flagword new_flags, old_flags; 708 709#if VMS_DEBUG 710 vms_debug (2, "vms_write_gsd (%p, %d)\n", abfd, objtype); 711#endif 712 713 /* Output sections. */ 714 section = abfd->sections; 715#if VMS_DEBUG 716 vms_debug (3, "%d sections found\n", abfd->section_count); 717#endif 718 719 /* Egsd is quadword aligned. */ 720 _bfd_vms_output_alignment (abfd, 8); 721 722 _bfd_vms_output_begin (abfd, EOBJ_S_C_EGSD, -1); 723 _bfd_vms_output_long (abfd, 0); 724 /* Prepare output for subrecords. */ 725 _bfd_vms_output_push (abfd); 726 727 while (section != 0) 728 { 729#if VMS_DEBUG 730 vms_debug (3, "Section #%d %s, %d bytes\n", section->index, section->name, (int)section->size); 731#endif 732 733 /* 13 bytes egsd, max 31 chars name -> should be 44 bytes. */ 734 if (_bfd_vms_output_check (abfd, 64) < 0) 735 { 736 _bfd_vms_output_pop (abfd); 737 _bfd_vms_output_end (abfd); 738 _bfd_vms_output_begin (abfd, EOBJ_S_C_EGSD, -1); 739 _bfd_vms_output_long (abfd, 0); 740 /* Prepare output for subrecords. */ 741 _bfd_vms_output_push (abfd); 742 } 743 744 /* Create dummy sections to keep consecutive indices. */ 745 while (section->index - last_index > 1) 746 { 747#if VMS_DEBUG 748 vms_debug (3, "index %d, last %d\n", section->index, last_index); 749#endif 750 _bfd_vms_output_begin (abfd, EGSD_S_C_PSC, -1); 751 _bfd_vms_output_short (abfd, 0); 752 _bfd_vms_output_short (abfd, 0); 753 _bfd_vms_output_long (abfd, 0); 754 sprintf (dummy_name, ".DUMMY%02d", last_index); 755 _bfd_vms_output_counted (abfd, dummy_name); 756 _bfd_vms_output_flush (abfd); 757 last_index++; 758 } 759 760 /* Don't know if this is necessary for the linker but for now it keeps 761 vms_slurp_gsd happy */ 762 sname = (char *)section->name; 763 if (*sname == '.') 764 { 765 sname++; 766 if ((*sname == 't') && (strcmp (sname, "text") == 0)) 767 sname = PRIV (is_vax)?VAX_CODE_NAME:EVAX_CODE_NAME; 768 else if ((*sname == 'd') && (strcmp (sname, "data") == 0)) 769 sname = PRIV (is_vax)?VAX_DATA_NAME:EVAX_DATA_NAME; 770 else if ((*sname == 'b') && (strcmp (sname, "bss") == 0)) 771 sname = EVAX_BSS_NAME; 772 else if ((*sname == 'l') && (strcmp (sname, "link") == 0)) 773 sname = EVAX_LINK_NAME; 774 else if ((*sname == 'r') && (strcmp (sname, "rdata") == 0)) 775 sname = EVAX_READONLY_NAME; 776 else if ((*sname == 'l') && (strcmp (sname, "literal") == 0)) 777 sname = EVAX_LITERAL_NAME; 778 else if ((*sname == 'c') && (strcmp (sname, "comm") == 0)) 779 sname = EVAX_COMMON_NAME; 780 else if ((*sname == 'l') && (strcmp (sname, "lcomm") == 0)) 781 sname = EVAX_LOCAL_NAME; 782 } 783 else 784 sname = _bfd_vms_length_hash_symbol (abfd, sname, EOBJ_S_C_SECSIZ); 785 786 _bfd_vms_output_begin (abfd, EGSD_S_C_PSC, -1); 787 _bfd_vms_output_short (abfd, section->alignment_power & 0xff); 788 if (bfd_is_com_section (section)) 789 new_flags = (EGPS_S_V_OVR | EGPS_S_V_REL | EGPS_S_V_GBL | EGPS_S_V_RD | EGPS_S_V_WRT | EGPS_S_V_NOMOD | EGPS_S_V_COM); 790 else 791 new_flags = vms_esecflag_by_name (evax_section_flags, sname, 792 section->size > 0); 793 794 _bfd_vms_output_short (abfd, new_flags); 795 _bfd_vms_output_long (abfd, (unsigned long) section->size); 796 _bfd_vms_output_counted (abfd, sname); 797 _bfd_vms_output_flush (abfd); 798 799 last_index = section->index; 800 section = section->next; 801 } 802 803 /* Output symbols. */ 804#if VMS_DEBUG 805 vms_debug (3, "%d symbols found\n", abfd->symcount); 806#endif 807 808 bfd_set_start_address (abfd, (bfd_vma) -1); 809 810 for (symnum = 0; symnum < abfd->symcount; symnum++) 811 { 812 char *hash; 813 814 symbol = abfd->outsymbols[symnum]; 815 if (*(symbol->name) == '_') 816 { 817 if (strcmp (symbol->name, "__main") == 0) 818 bfd_set_start_address (abfd, (bfd_vma)symbol->value); 819 } 820 old_flags = symbol->flags; 821 822 if (old_flags & BSF_FILE) 823 continue; 824 825 if (((old_flags & (BSF_GLOBAL | BSF_WEAK)) == 0) /* Not xdef... */ 826 && (!bfd_is_und_section (symbol->section))) /* ...and not xref. */ 827 continue; /* Dont output. */ 828 829 /* 13 bytes egsd, max 64 chars name -> should be 77 bytes. */ 830 if (_bfd_vms_output_check (abfd, 80) < 0) 831 { 832 _bfd_vms_output_pop (abfd); 833 _bfd_vms_output_end (abfd); 834 _bfd_vms_output_begin (abfd, EOBJ_S_C_EGSD, -1); 835 _bfd_vms_output_long (abfd, 0); 836 /* Prepare output for subrecords. */ 837 _bfd_vms_output_push (abfd); 838 } 839 840 _bfd_vms_output_begin (abfd, EGSD_S_C_SYM, -1); 841 842 /* Data type, alignment. */ 843 _bfd_vms_output_short (abfd, 0); 844 845 new_flags = 0; 846 847 if (old_flags & BSF_WEAK) 848 new_flags |= EGSY_S_V_WEAK; 849 if (bfd_is_com_section (symbol->section)) 850 new_flags |= (EGSY_S_V_WEAK | EGSY_S_V_COMM); 851 852 if (old_flags & BSF_FUNCTION) 853 { 854 new_flags |= EGSY_S_V_NORM; 855 new_flags |= EGSY_S_V_REL; 856 } 857 if (old_flags & (BSF_GLOBAL | BSF_WEAK)) 858 { 859 new_flags |= EGSY_S_V_DEF; 860 if (!bfd_is_abs_section (symbol->section)) 861 new_flags |= EGSY_S_V_REL; 862 } 863 _bfd_vms_output_short (abfd, new_flags); 864 865 if (old_flags & (BSF_GLOBAL | BSF_WEAK)) 866 { 867 /* Symbol definition. */ 868 uquad code_address = 0; 869 unsigned long ca_psindx = 0; 870 unsigned long psindx; 871 872 if ((old_flags & BSF_FUNCTION) && symbol->udata.p != NULL) 873 { 874 code_address = ((asymbol *) (symbol->udata.p))->value; 875 ca_psindx = ((asymbol *) (symbol->udata.p))->section->index; 876 } 877 psindx = symbol->section->index; 878 879 _bfd_vms_output_quad (abfd, symbol->value); 880 _bfd_vms_output_quad (abfd, code_address); 881 _bfd_vms_output_long (abfd, ca_psindx); 882 _bfd_vms_output_long (abfd, psindx); 883 } 884 hash = _bfd_vms_length_hash_symbol (abfd, symbol->name, EOBJ_S_C_SYMSIZ); 885 _bfd_vms_output_counted (abfd, hash); 886 887 _bfd_vms_output_flush (abfd); 888 889 } 890 891 _bfd_vms_output_alignment (abfd, 8); 892 _bfd_vms_output_pop (abfd); 893 _bfd_vms_output_end (abfd); 894 895 return 0; 896} 897