/* vms-gsd.c -- BFD back-end for VAX (openVMS/VAX) and EVAX (openVMS/Alpha) files. Copyright 1996, 1997, 1998, 1999 Free Software Foundation Inc. go and read the openVMS linker manual (esp. appendix B) if you don't know what's going on here :-) Written by Klaus K"ampf (kkaempf@rmi.de) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include <ctype.h> #include "bfd.h" #include "sysdep.h" #include "bfdlink.h" #include "libbfd.h" #include "vms.h" /*-----------------------------------------------------------------------------*/ /* typical sections for vax object files */ #define VAX_CODE_NAME "$CODE" #define VAX_DATA_NAME "$DATA" #define VAX_ADDRESS_DATA_NAME "$ADDRESS_DATA" /* typical sections for evax object files */ #define EVAX_ABS_NAME "$ABS$" #define EVAX_CODE_NAME "$CODE$" #define EVAX_LINK_NAME "$LINK$" #define EVAX_DATA_NAME "$DATA$" #define EVAX_BSS_NAME "$BSS$" #define EVAX_READONLYADDR_NAME "$READONLY_ADDR$" #define EVAX_READONLY_NAME "$READONLY$" #define EVAX_LITERAL_NAME "$LITERAL$" #define EVAX_COMMON_NAME "$COMMON$" #define EVAX_LOCAL_NAME "$LOCAL$" struct sec_flags_struct { char *name; /* name of section */ int vflags_always; flagword flags_always; /* flags we set always */ int vflags_hassize; flagword flags_hassize; /* flags we set if the section has a size > 0 */ }; /* These flags are deccrtl/vaxcrtl (openVMS 6.2 VAX) compatible */ static struct sec_flags_struct vax_section_flags[] = { { VAX_CODE_NAME, (GPS_S_M_PIC|GPS_S_M_REL|GPS_S_M_SHR|GPS_S_M_EXE|GPS_S_M_RD), (SEC_CODE), (GPS_S_M_PIC|GPS_S_M_REL|GPS_S_M_SHR|GPS_S_M_EXE|GPS_S_M_RD), (SEC_IN_MEMORY|SEC_CODE|SEC_HAS_CONTENTS|SEC_ALLOC|SEC_LOAD) }, { VAX_DATA_NAME, (GPS_S_M_PIC|GPS_S_M_REL|GPS_S_M_RD|GPS_S_M_WRT), (SEC_DATA), (GPS_S_M_PIC|GPS_S_M_REL|GPS_S_M_RD|GPS_S_M_WRT), (SEC_IN_MEMORY|SEC_DATA|SEC_HAS_CONTENTS|SEC_ALLOC|SEC_LOAD) }, { VAX_ADDRESS_DATA_NAME, (GPS_S_M_PIC|GPS_S_M_REL|GPS_S_M_RD), (SEC_DATA|SEC_READONLY), (GPS_S_M_PIC|GPS_S_M_REL|GPS_S_M_RD), (SEC_IN_MEMORY|SEC_DATA|SEC_HAS_CONTENTS|SEC_ALLOC|SEC_READONLY|SEC_LOAD) }, { NULL, (GPS_S_M_PIC|GPS_S_M_OVR|GPS_S_M_REL|GPS_S_M_GBL|GPS_S_M_RD|GPS_S_M_WRT), (SEC_DATA), (GPS_S_M_PIC|GPS_S_M_OVR|GPS_S_M_REL|GPS_S_M_GBL|GPS_S_M_RD|GPS_S_M_WRT), (SEC_IN_MEMORY|SEC_DATA|SEC_HAS_CONTENTS|SEC_ALLOC|SEC_LOAD) } }; /* These flags are deccrtl/vaxcrtl (openVMS 6.2 Alpha) compatible */ static struct sec_flags_struct evax_section_flags[] = { { EVAX_ABS_NAME, (EGPS_S_V_SHR), (SEC_DATA), (EGPS_S_V_SHR), (SEC_IN_MEMORY|SEC_DATA|SEC_HAS_CONTENTS|SEC_ALLOC|SEC_LOAD) }, { EVAX_CODE_NAME, (EGPS_S_V_PIC|EGPS_S_V_REL|EGPS_S_V_SHR|EGPS_S_V_EXE), (SEC_CODE), (EGPS_S_V_PIC|EGPS_S_V_REL|EGPS_S_V_SHR|EGPS_S_V_EXE), (SEC_IN_MEMORY|SEC_CODE|SEC_HAS_CONTENTS|SEC_ALLOC|SEC_LOAD) }, { EVAX_LITERAL_NAME, (EGPS_S_V_PIC|EGPS_S_V_REL|EGPS_S_V_SHR|EGPS_S_V_RD|EGPS_S_V_NOMOD), (SEC_DATA|SEC_READONLY), (EGPS_S_V_PIC|EGPS_S_V_REL|EGPS_S_V_SHR|EGPS_S_V_RD), (SEC_IN_MEMORY|SEC_DATA|SEC_HAS_CONTENTS|SEC_ALLOC|SEC_READONLY|SEC_LOAD) }, { EVAX_LINK_NAME, (EGPS_S_V_REL|EGPS_S_V_RD), (SEC_DATA|SEC_READONLY), (EGPS_S_V_REL|EGPS_S_V_RD), (SEC_IN_MEMORY|SEC_DATA|SEC_HAS_CONTENTS|SEC_ALLOC|SEC_READONLY|SEC_LOAD) }, { EVAX_DATA_NAME, (EGPS_S_V_REL|EGPS_S_V_RD|EGPS_S_V_WRT|EGPS_S_V_NOMOD), (SEC_DATA), (EGPS_S_V_REL|EGPS_S_V_RD|EGPS_S_V_WRT), (SEC_IN_MEMORY|SEC_DATA|SEC_HAS_CONTENTS|SEC_ALLOC|SEC_LOAD) }, { EVAX_BSS_NAME, (EGPS_S_V_REL|EGPS_S_V_RD|EGPS_S_V_WRT|EGPS_S_V_NOMOD), (SEC_NO_FLAGS), (EGPS_S_V_REL|EGPS_S_V_RD|EGPS_S_V_WRT|EGPS_S_V_NOMOD), (SEC_IN_MEMORY|SEC_HAS_CONTENTS|SEC_ALLOC|SEC_LOAD) }, { EVAX_READONLYADDR_NAME, (EGPS_S_V_PIC|EGPS_S_V_REL|EGPS_S_V_RD), (SEC_DATA|SEC_READONLY), (EGPS_S_V_PIC|EGPS_S_V_REL|EGPS_S_V_RD), (SEC_IN_MEMORY|SEC_DATA|SEC_HAS_CONTENTS|SEC_ALLOC|SEC_READONLY|SEC_LOAD) }, { EVAX_READONLY_NAME, (EGPS_S_V_PIC|EGPS_S_V_REL|EGPS_S_V_SHR|EGPS_S_V_RD|EGPS_S_V_NOMOD), (SEC_DATA|SEC_READONLY), (EGPS_S_V_PIC|EGPS_S_V_REL|EGPS_S_V_SHR|EGPS_S_V_RD), (SEC_IN_MEMORY|SEC_DATA|SEC_HAS_CONTENTS|SEC_ALLOC|SEC_READONLY|SEC_LOAD) }, { EVAX_LOCAL_NAME, (EGPS_S_V_REL|EGPS_S_V_RD|EGPS_S_V_WRT), (SEC_DATA), (EGPS_S_V_REL|EGPS_S_V_RD|EGPS_S_V_WRT), (SEC_IN_MEMORY|SEC_DATA|SEC_HAS_CONTENTS|SEC_ALLOC|SEC_LOAD) }, { NULL, (EGPS_S_V_REL|EGPS_S_V_RD|EGPS_S_V_WRT), (SEC_DATA), (EGPS_S_V_REL|EGPS_S_V_RD|EGPS_S_V_WRT), (SEC_IN_MEMORY|SEC_DATA|SEC_HAS_CONTENTS|SEC_ALLOC|SEC_LOAD) } }; /* Retrieve bfd section flags by name and size */ static flagword vms_secflag_by_name (abfd, section_flags, name, size) bfd *abfd; struct sec_flags_struct *section_flags; char *name; int size; { int i = 0; while (section_flags[i].name != NULL) { if ((PRIV(is_vax)? strcasecmp (name, section_flags[i].name): strcmp (name, section_flags[i].name)) == 0) { if (size > 0) return section_flags[i].flags_hassize; else return section_flags[i].flags_always; } i++; } if (size > 0) return section_flags[i].flags_hassize; return section_flags[i].flags_always; } /* Retrieve vms section flags by name and size */ static flagword vms_esecflag_by_name (section_flags, name, size) struct sec_flags_struct *section_flags; char *name; int size; { int i = 0; while (section_flags[i].name != NULL) { if (strcmp (name, section_flags[i].name) == 0) { if (size > 0) return section_flags[i].vflags_hassize; else return section_flags[i].vflags_always; } i++; } if (size > 0) return section_flags[i].vflags_hassize; return section_flags[i].vflags_always; } /*-----------------------------------------------------------------------------*/ #if VMS_DEBUG /* debug */ struct flagdescstruct { char *name; flagword value; }; /* Convert flag to printable string */ static char * flag2str(flagdesc, flags) struct flagdescstruct *flagdesc; flagword flags; { static char res[64]; int next = 0; res[0] = 0; while (flagdesc->name != NULL) { if ((flags & flagdesc->value) != 0) { if (next) strcat(res, ","); else next = 1; strcat (res, flagdesc->name); } flagdesc++; } return res; } #endif /*-----------------------------------------------------------------------------*/ /* input routines */ /* Process GSD/EGSD record return 0 on success, -1 on error */ int _bfd_vms_slurp_gsd (abfd, objtype) bfd *abfd; int objtype; { #if VMS_DEBUG static struct flagdescstruct gpsflagdesc[] = { { "PIC", 0x0001 }, { "LIB", 0x0002 }, { "OVR", 0x0004 }, { "REL", 0x0008 }, { "GBL", 0x0010 }, { "SHR", 0x0020 }, { "EXE", 0x0040 }, { "RD", 0x0080 }, { "WRT", 0x0100 }, { "VEC", 0x0200 }, { "NOMOD", 0x0400 }, { "COM", 0x0800 }, { NULL, 0 } }; static struct flagdescstruct gsyflagdesc[] = { { "WEAK", 0x0001 }, { "DEF", 0x0002 }, { "UNI", 0x0004 }, { "REL", 0x0008 }, { "COMM", 0x0010 }, { "VECEP", 0x0020 }, { "NORM", 0x0040 }, { NULL, 0 } }; #endif int gsd_type, gsd_size; asection *section; unsigned char *vms_rec; flagword new_flags, old_flags; char *name; asymbol *symbol; vms_symbol_entry *entry; unsigned long base_addr; unsigned long align_addr; static unsigned int psect_idx = 0; #if VMS_DEBUG vms_debug (2, "GSD/EGSD (%d/%x)\n", objtype, objtype); #endif switch (objtype) { case EOBJ_S_C_EGSD: PRIV(vms_rec) += 8; /* skip type, size, l_temp */ PRIV(rec_size) -= 8; break; case OBJ_S_C_GSD: PRIV(vms_rec) += 1; PRIV(rec_size) -= 1; break; default: return -1; } /* calculate base address for each section */ base_addr = 0L; abfd->symcount = 0; while (PRIV(rec_size) > 0) { vms_rec = PRIV(vms_rec); if (objtype == OBJ_S_C_GSD) { gsd_type = *vms_rec; } else { _bfd_vms_get_header_values (abfd, vms_rec, &gsd_type, &gsd_size); gsd_type += EVAX_OFFSET; } #if VMS_DEBUG vms_debug (3, "gsd_type %d\n", gsd_type); #endif switch (gsd_type) { case GSD_S_C_PSC: { /* * program section definition */ asection *old_section = 0; #if VMS_DEBUG vms_debug (4, "GSD_S_C_PSC\n"); #endif /* If this section isn't a bfd section. */ if (PRIV(is_vax) && (psect_idx < (abfd->section_count-1))) { /* check for temporary section from TIR record. */ if (psect_idx < PRIV(section_count)) old_section = PRIV(sections)[psect_idx]; else old_section = 0; } name = _bfd_vms_save_counted_string (vms_rec + 8); section = bfd_make_section (abfd, name); if (!section) { (*_bfd_error_handler) (_("bfd_make_section (%s) failed"), name); return -1; } old_flags = bfd_getl16 (vms_rec + 2); section->_raw_size = bfd_getl32(vms_rec + 4); /* allocation */ new_flags = vms_secflag_by_name (abfd, vax_section_flags, name, section->_raw_size); if (old_flags & EGPS_S_V_REL) new_flags |= SEC_RELOC; if (old_flags & GPS_S_M_OVR) new_flags |= SEC_IS_COMMON; if (!bfd_set_section_flags (abfd, section, new_flags)) { (*_bfd_error_handler) (_("bfd_set_section_flags (%s, %x) failed"), name, new_flags); return -1; } section->alignment_power = vms_rec[1]; align_addr = (1 << section->alignment_power); if ((base_addr % align_addr) != 0) base_addr += (align_addr - (base_addr % align_addr)); section->vma = (bfd_vma)base_addr; base_addr += section->_raw_size; /* global section is common symbol */ if (old_flags & GPS_S_M_GBL) { entry = _bfd_vms_enter_symbol (abfd, name); if (entry == (vms_symbol_entry *)NULL) { bfd_set_error (bfd_error_no_memory); return -1; } symbol = entry->symbol; symbol->value = 0; symbol->section = section; symbol->flags = (BSF_GLOBAL|BSF_SECTION_SYM|BSF_OLD_COMMON); } /* copy saved contents if old_section set */ if (old_section != 0) { section->contents = old_section->contents; if (section->_raw_size < old_section->_raw_size) { (*_bfd_error_handler) (_("Size mismatch section %s=%lx, %s=%lx"), old_section->name, (unsigned long) old_section->_raw_size, section->name, (unsigned long) section->_raw_size); return -1; } else if (section->_raw_size > old_section->_raw_size) { section->contents = ((unsigned char *) bfd_realloc (old_section->contents, section->_raw_size)); if (section->contents == NULL) { bfd_set_error (bfd_error_no_memory); return -1; } } } else { section->contents = ((unsigned char *) bfd_malloc (section->_raw_size)); if (section->contents == NULL) { bfd_set_error (bfd_error_no_memory); return -1; } memset (section->contents, 0, (size_t)section->_raw_size); } section->_cooked_size = section->_raw_size; #if VMS_DEBUG vms_debug (4, "gsd psc %d (%s, flags %04x=%s) ", section->index, name, old_flags, flag2str (gpsflagdesc, old_flags)); vms_debug (4, "%d bytes at 0x%08lx (mem %p)\n", section->_raw_size, section->vma, section->contents); #endif gsd_size = vms_rec[8] + 9; psect_idx++; } break; case GSD_S_C_EPM: case GSD_S_C_EPMW: #if VMS_DEBUG vms_debug(4, "gsd epm\n"); #endif /*FALLTHRU*/ case GSD_S_C_SYM: case GSD_S_C_SYMW: { int name_offset, value_offset; /* * symbol specification (definition or reference) */ #if VMS_DEBUG vms_debug (4, "GSD_S_C_SYM(W)\n"); #endif old_flags = bfd_getl16 (vms_rec + 2); new_flags = BSF_NO_FLAGS; if (old_flags & GSY_S_M_WEAK) new_flags |= BSF_WEAK; switch (gsd_type) { case GSD_S_C_EPM: name_offset = 11; value_offset = 5; new_flags |= BSF_FUNCTION; break; case GSD_S_C_EPMW: name_offset = 12; value_offset = 6; new_flags |= BSF_FUNCTION; break; case GSD_S_C_SYM: if (old_flags & GSY_S_M_DEF) /* symbol definition */ name_offset = 9; else name_offset = 4; value_offset = 5; break; case GSD_S_C_SYMW: if (old_flags & GSY_S_M_DEF) /* symbol definition */ name_offset = 10; else name_offset = 5; value_offset = 6; break; } /* save symbol in vms_symbol_table */ entry = _bfd_vms_enter_symbol (abfd, _bfd_vms_save_counted_string (vms_rec + name_offset)); if (entry == (vms_symbol_entry *)NULL) { bfd_set_error (bfd_error_no_memory); return -1; } symbol = entry->symbol; if (old_flags & GSY_S_M_DEF) /* symbol definition */ { int psect; symbol->value = bfd_getl32 (vms_rec+value_offset); if ((gsd_type == GSD_S_C_SYMW) || (gsd_type == GSD_S_C_EPMW)) psect = bfd_getl16 (vms_rec + value_offset - 2); else psect = vms_rec[value_offset-1]; symbol->section = (asection *)psect; #if VMS_DEBUG vms_debug(4, "gsd sym def #%d (%s, %d [%p], %04x=%s)\n", abfd->symcount, symbol->name, (int)symbol->section, symbol->section, old_flags, flag2str(gsyflagdesc, old_flags)); #endif } else /* symbol reference */ { symbol->section = bfd_make_section (abfd, BFD_UND_SECTION_NAME); #if VMS_DEBUG vms_debug (4, "gsd sym ref #%d (%s, %s [%p], %04x=%s)\n", abfd->symcount, symbol->name, symbol->section->name, symbol->section, old_flags, flag2str (gsyflagdesc, old_flags)); #endif } gsd_size = vms_rec[name_offset] + name_offset + 1; symbol->flags = new_flags; } break; case GSD_S_C_PRO: case GSD_S_C_PROW: #if VMS_DEBUG vms_debug(4, "gsd pro\n"); #endif break; case GSD_S_C_IDC: #if VMS_DEBUG vms_debug(4, "gsd idc\n"); #endif break; case GSD_S_C_ENV: #if VMS_DEBUG vms_debug(4, "gsd env\n"); #endif break; case GSD_S_C_LSY: #if VMS_DEBUG vms_debug(4, "gsd lsy\n"); #endif break; case GSD_S_C_LEPM: #if VMS_DEBUG vms_debug(4, "gsd lepm\n"); #endif break; case GSD_S_C_LPRO: #if VMS_DEBUG vms_debug(4, "gsd lpro\n"); #endif break; case GSD_S_C_SPSC: #if VMS_DEBUG vms_debug(4, "gsd spsc\n"); #endif break; case GSD_S_C_SYMV: #if VMS_DEBUG vms_debug(4, "gsd symv\n"); #endif break; case GSD_S_C_EPMV: #if VMS_DEBUG vms_debug(4, "gsd epmv\n"); #endif break; case GSD_S_C_PROV: #if VMS_DEBUG vms_debug(4, "gsd prov\n"); #endif break; case EGSD_S_C_PSC + EVAX_OFFSET: { /* program section definition */ name = _bfd_vms_save_counted_string (vms_rec+12); section = bfd_make_section (abfd, name); if (!section) return -1; old_flags = bfd_getl16 (vms_rec + 6); section->_raw_size = bfd_getl32 (vms_rec + 8); /* allocation */ new_flags = vms_secflag_by_name (abfd, evax_section_flags, name, (int) section->_raw_size); if (old_flags & EGPS_S_V_REL) new_flags |= SEC_RELOC; if (!bfd_set_section_flags (abfd, section, new_flags)) return -1; section->alignment_power = vms_rec[4]; align_addr = (1 << section->alignment_power); if ((base_addr % align_addr) != 0) base_addr += (align_addr - (base_addr % align_addr)); section->vma = (bfd_vma)base_addr; base_addr += section->_raw_size; section->contents = ((unsigned char *) bfd_malloc (section->_raw_size)); if (section->contents == NULL) return -1; memset (section->contents, 0, (size_t) section->_raw_size); section->_cooked_size = section->_raw_size; #if VMS_DEBUG vms_debug(4, "egsd psc %d (%s, flags %04x=%s) ", section->index, name, old_flags, flag2str(gpsflagdesc, old_flags)); vms_debug(4, "%d bytes at 0x%08lx (mem %p)\n", section->_raw_size, section->vma, section->contents); #endif } break; case EGSD_S_C_SYM + EVAX_OFFSET: { /* symbol specification (definition or reference) */ symbol = _bfd_vms_make_empty_symbol (abfd); if (symbol == 0) return -1; old_flags = bfd_getl16 (vms_rec + 6); new_flags = BSF_NO_FLAGS; if (old_flags & EGSY_S_V_WEAK) new_flags |= BSF_WEAK; if (vms_rec[6] & EGSY_S_V_DEF) /* symbol definition */ { symbol->name = _bfd_vms_save_counted_string (vms_rec+32); if (old_flags & EGSY_S_V_NORM) { /* proc def */ new_flags |= BSF_FUNCTION; } symbol->value = bfd_getl64 (vms_rec+8); symbol->section = (asection *)((unsigned long) bfd_getl32 (vms_rec+28)); #if VMS_DEBUG vms_debug(4, "egsd sym def #%d (%s, %d, %04x=%s)\n", abfd->symcount, symbol->name, (int)symbol->section, old_flags, flag2str(gsyflagdesc, old_flags)); #endif } else /* symbol reference */ { symbol->name = _bfd_vms_save_counted_string (vms_rec+8); #if VMS_DEBUG vms_debug(4, "egsd sym ref #%d (%s, %04x=%s)\n", abfd->symcount, symbol->name, old_flags, flag2str(gsyflagdesc, old_flags)); #endif symbol->section = bfd_make_section (abfd, BFD_UND_SECTION_NAME); } symbol->flags = new_flags; /* save symbol in vms_symbol_table */ entry = (vms_symbol_entry *) bfd_hash_lookup (PRIV(vms_symbol_table), symbol->name, true, false); if (entry == (vms_symbol_entry *)NULL) { bfd_set_error (bfd_error_no_memory); return -1; } if (entry->symbol != (asymbol *)NULL) { /* FIXME ?, DEC C generates this */ #if VMS_DEBUG vms_debug(4, "EGSD_S_C_SYM: duplicate \"%s\"\n", symbol->name); #endif } else { entry->symbol = symbol; PRIV(gsd_sym_count)++; abfd->symcount++; } } break; case EGSD_S_C_IDC + EVAX_OFFSET: break; default: (*_bfd_error_handler) (_("unknown gsd/egsd subtype %d"), gsd_type); bfd_set_error (bfd_error_bad_value); return -1; } /* switch */ PRIV(rec_size) -= gsd_size; PRIV(vms_rec) += gsd_size; } /* while (recsize > 0) */ if (abfd->symcount > 0) abfd->flags |= HAS_SYMS; return 0; } /*-----------------------------------------------------------------------------*/ /* output routines */ /* Write section and symbol directory of bfd abfd */ int _bfd_vms_write_gsd (abfd, objtype) bfd *abfd; int objtype ATTRIBUTE_UNUSED; { asection *section; asymbol *symbol; unsigned int symnum; int last_index = -1; char dummy_name[10]; char *sname; flagword new_flags, old_flags; #if VMS_DEBUG vms_debug (2, "vms_write_gsd (%p, %d)\n", abfd, objtype); #endif /* output sections */ section = abfd->sections; #if VMS_DEBUG vms_debug (3, "%d sections found\n", abfd->section_count); #endif /* egsd is quadword aligned */ _bfd_vms_output_alignment (abfd, 8); _bfd_vms_output_begin (abfd, EOBJ_S_C_EGSD, -1); _bfd_vms_output_long (abfd, 0); _bfd_vms_output_push (abfd); /* prepare output for subrecords */ while (section != 0) { #if VMS_DEBUG vms_debug (3, "Section #%d %s, %d bytes\n", section->index, section->name, (int)section->_raw_size); #endif /* 13 bytes egsd, max 31 chars name -> should be 44 bytes */ if (_bfd_vms_output_check (abfd, 64) < 0) { _bfd_vms_output_pop (abfd); _bfd_vms_output_end (abfd); _bfd_vms_output_begin (abfd, EOBJ_S_C_EGSD, -1); _bfd_vms_output_long (abfd, 0); _bfd_vms_output_push (abfd); /* prepare output for subrecords */ } /* Create dummy sections to keep consecutive indices */ while (section->index - last_index > 1) { #if VMS_DEBUG vms_debug (3, "index %d, last %d\n", section->index, last_index); #endif _bfd_vms_output_begin (abfd, EGSD_S_C_PSC, -1); _bfd_vms_output_short (abfd, 0); _bfd_vms_output_short (abfd, 0); _bfd_vms_output_long (abfd, 0); sprintf (dummy_name, ".DUMMY%02d", last_index); _bfd_vms_output_counted (abfd, dummy_name); _bfd_vms_output_flush (abfd); last_index++; } /* Don't know if this is neccesary for the linker but for now it keeps vms_slurp_gsd happy */ sname = (char *)section->name; if (*sname == '.') { sname++; if ((*sname == 't') && (strcmp (sname, "text") == 0)) sname = PRIV(is_vax)?VAX_CODE_NAME:EVAX_CODE_NAME; else if ((*sname == 'd') && (strcmp (sname, "data") == 0)) sname = PRIV(is_vax)?VAX_DATA_NAME:EVAX_DATA_NAME; else if ((*sname == 'b') && (strcmp (sname, "bss") == 0)) sname = EVAX_BSS_NAME; else if ((*sname == 'l') && (strcmp (sname, "link") == 0)) sname = EVAX_LINK_NAME; else if ((*sname == 'r') && (strcmp (sname, "rdata") == 0)) sname = EVAX_READONLY_NAME; else if ((*sname == 'l') && (strcmp (sname, "literal") == 0)) sname = EVAX_LITERAL_NAME; else if ((*sname == 'c') && (strcmp (sname, "comm") == 0)) sname = EVAX_COMMON_NAME; else if ((*sname == 'l') && (strcmp (sname, "lcomm") == 0)) sname = EVAX_LOCAL_NAME; } else sname = _bfd_vms_length_hash_symbol (abfd, sname, EOBJ_S_C_SECSIZ); _bfd_vms_output_begin (abfd, EGSD_S_C_PSC, -1); _bfd_vms_output_short (abfd, section->alignment_power & 0xff); if (bfd_is_com_section (section)) { 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); } else { new_flags = vms_esecflag_by_name (evax_section_flags, sname, section->_raw_size); } _bfd_vms_output_short (abfd, new_flags); _bfd_vms_output_long (abfd, section->_raw_size); _bfd_vms_output_counted (abfd, sname); _bfd_vms_output_flush (abfd); last_index = section->index; section = section->next; } /* output symbols */ #if VMS_DEBUG vms_debug (3, "%d symbols found\n", abfd->symcount); #endif bfd_set_start_address (abfd, (bfd_vma)-1); for (symnum = 0; symnum < abfd->symcount; symnum++) { symbol = abfd->outsymbols[symnum]; if (*(symbol->name) == '_') { if (strcmp (symbol->name, "__main") == 0) bfd_set_start_address (abfd, (bfd_vma)symbol->value); } old_flags = symbol->flags; if (old_flags & BSF_FILE) continue; if (((old_flags & (BSF_GLOBAL|BSF_WEAK)) == 0) /* not xdef */ && (!bfd_is_und_section (symbol->section))) /* and not xref */ continue; /* dont output */ /* 13 bytes egsd, max 64 chars name -> should be 77 bytes */ if (_bfd_vms_output_check (abfd, 80) < 0) { _bfd_vms_output_pop (abfd); _bfd_vms_output_end (abfd); _bfd_vms_output_begin (abfd, EOBJ_S_C_EGSD, -1); _bfd_vms_output_long (abfd, 0); _bfd_vms_output_push (abfd); /* prepare output for subrecords */ } _bfd_vms_output_begin (abfd, EGSD_S_C_SYM, -1); _bfd_vms_output_short (abfd, 0); /* data type, alignment */ new_flags = 0; if (old_flags & BSF_WEAK) new_flags |= EGSY_S_V_WEAK; if (bfd_is_com_section (symbol->section)) /* .comm */ new_flags |= (EGSY_S_V_WEAK|EGSY_S_V_COMM); if (old_flags & BSF_FUNCTION) { new_flags |= EGSY_S_V_NORM; new_flags |= EGSY_S_V_REL; } if (old_flags & (BSF_GLOBAL|BSF_WEAK)) { new_flags |= EGSY_S_V_DEF; if (!bfd_is_abs_section (symbol->section)) new_flags |= EGSY_S_V_REL; } _bfd_vms_output_short (abfd, new_flags); if (old_flags & (BSF_GLOBAL|BSF_WEAK)) /* symbol definition */ { if (old_flags & BSF_FUNCTION) { _bfd_vms_output_quad (abfd, symbol->value); _bfd_vms_output_quad (abfd, ((asymbol *)(symbol->udata.p))->value); _bfd_vms_output_long (abfd, (((asymbol *)(symbol->udata.p)) ->section->index)); _bfd_vms_output_long (abfd, symbol->section->index); } else { _bfd_vms_output_quad (abfd, symbol->value); /* L_VALUE */ _bfd_vms_output_quad (abfd, 0); /* L_CODE_ADDRESS */ _bfd_vms_output_long (abfd, 0); /* L_CA_PSINDX */ _bfd_vms_output_long (abfd, symbol->section->index);/* L_PSINDX */ } } _bfd_vms_output_counted (abfd, _bfd_vms_length_hash_symbol (abfd, symbol->name, EOBJ_S_C_SYMSIZ)); _bfd_vms_output_flush (abfd); } _bfd_vms_output_alignment (abfd, 8); _bfd_vms_output_pop (abfd); _bfd_vms_output_end (abfd); return 0; }