static bfd_boolean fill_section_ptr (struct bfd_hash_entry * entry, void * sections) { asection *sec; asymbol *sym; sym = ((vms_symbol_entry *) entry)->symbol; sec = sym->section; #if defined(VMS_DEBUG) && VMS_DEBUG vms_debug(6, "fill_section_ptr: sym %p, sec %p\n", (void *)sym, (void *)sec); #endif /* Fill forward references (these contain section number, not section ptr). */ if ((unsigned int) (size_t) sec < priv_section_count) sec = ((vms_symbol_entry *) entry)->symbol->section = ((asection **) sections)[(unsigned int) (size_t) sec]; if (strcmp (sym->name, sec->name) == 0) sym->flags |= BSF_SECTION_SYM; return TRUE; }
static const struct bfd_target * vms_object_p (bfd * abfd) { int err = 0; int prev_type; const struct bfd_target *target_vector = NULL; const bfd_arch_info_type *arch = NULL; void * tdata_save = abfd->tdata.any; bfd_vma saddr_save = bfd_get_start_address (abfd); #if defined(VMS_DEBUG) && VMS_DEBUG vms_debug(1, "vms_object_p (%p)\n", (void *)abfd); #endif if (!vms_initialize (abfd)) goto error_ret; if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET)) goto err_wrong_format; prev_type = -1; do { #if defined(VMS_DEBUG) && VMS_DEBUG vms_debug(7, "reading at %08lx\n", (unsigned long)bfd_tell(abfd)); #endif if (_bfd_vms_next_record (abfd) < 0) { #if defined(VMS_DEBUG) && VMS_DEBUG vms_debug (2, "next_record failed\n"); #endif goto err_wrong_format; } if ((prev_type == EOBJ_S_C_EGSD) && (PRIV (rec_type) != EOBJ_S_C_EGSD)) { if (! vms_fixup_sections (abfd)) { #if defined(VMS_DEBUG) && VMS_DEBUG vms_debug (2, "vms_fixup_sections failed\n"); #endif goto err_wrong_format; } } prev_type = PRIV (rec_type); if (target_vector == NULL) { if (prev_type <= OBJ_S_C_MAXRECTYP) target_vector = &vms_vax_vec; else target_vector = &vms_alpha_vec; } switch (prev_type) { case OBJ_S_C_HDR: case EOBJ_S_C_EMH: err = _bfd_vms_slurp_hdr (abfd, prev_type); break; case OBJ_S_C_EOM: case OBJ_S_C_EOMW: case EOBJ_S_C_EEOM: err = _bfd_vms_slurp_eom (abfd, prev_type); break; case OBJ_S_C_GSD: case EOBJ_S_C_EGSD: err = _bfd_vms_slurp_gsd (abfd, prev_type); break; case OBJ_S_C_TIR: case EOBJ_S_C_ETIR: err = _bfd_vms_slurp_tir (abfd, prev_type); break; case OBJ_S_C_DBG: case EOBJ_S_C_EDBG: err = _bfd_vms_slurp_dbg (abfd, prev_type); break; case OBJ_S_C_TBT: case EOBJ_S_C_ETBT: err = _bfd_vms_slurp_tbt (abfd, prev_type); break; case OBJ_S_C_LNK: err = _bfd_vms_slurp_lnk (abfd, prev_type); break; default: err = -1; } if (err != 0) { #if defined(VMS_DEBUG) && VMS_DEBUG vms_debug (2, "slurp type %d failed with %d\n", prev_type, err); #endif goto err_wrong_format; } } while ((prev_type != EOBJ_S_C_EEOM) && (prev_type != OBJ_S_C_EOM) && (prev_type != OBJ_S_C_EOMW)); if (target_vector == & vms_vax_vec) { if (! vms_fixup_sections (abfd)) { #if defined(VMS_DEBUG) && VMS_DEBUG vms_debug (2, "vms_fixup_sections failed\n"); #endif goto err_wrong_format; } /* Set arch_info to vax. */ arch = bfd_scan_arch ("vax"); PRIV (is_vax) = TRUE; #if defined(VMS_DEBUG) && VMS_DEBUG vms_debug (2, "arch is vax\n"); #endif } else if (target_vector == &vms_alpha_vec) { /* Set arch_info to alpha: */ const char *alphastr = "alpha"; arch = bfd_scan_arch(alphastr); PRIV (is_vax) = FALSE; #if defined(VMS_DEBUG) && VMS_DEBUG vms_debug(2, "arch is %s\n", alphastr); #endif /* VMS_DEBUG */ } if (arch == NULL) { #if defined(VMS_DEBUG) && VMS_DEBUG vms_debug (2, "arch not found\n"); #endif goto err_wrong_format; } abfd->arch_info = arch; return target_vector; err_wrong_format: bfd_set_error (bfd_error_wrong_format); error_ret: if (abfd->tdata.any != tdata_save && abfd->tdata.any != NULL) bfd_release (abfd, abfd->tdata.any); abfd->tdata.any = tdata_save; bfd_set_start_address (abfd, saddr_save); return NULL; }
static int register_universal_symbol (bfd *abfd, asymbol *symbol, int vms_flags) { bfd_vma sbase = 0; asection *s, *sec = NULL; vms_symbol_entry *entry; /* A universal symbol is by definition global... */ symbol->flags |= BSF_GLOBAL; /* ...and dynamic in shared libraries. */ if (abfd->flags & DYNAMIC) symbol->flags |= BSF_DYNAMIC; /* Find containing section. */ for (s = abfd->sections; s; s = s->next) { if (symbol->value >= s->vma && s->vma > sbase && !(s->flags & SEC_COFF_SHARED_LIBRARY) && (s->size > 0 || !(vms_flags & EGSY_S_V_REL))) { sbase = s->vma; sec = s; } } symbol->value -= sbase; symbol->section = sec; #if VMS_DEBUG vms_debug (4, "EGST sym def #%d (%s, 0x%llx => 0x%llx, %04x=%s)\n", abfd->symcount, symbol->name, symbol->value + sbase, symbol->value, vms_flags, flag2str(gsyflagdesc, vms_flags)); #endif entry = (vms_symbol_entry *) bfd_hash_lookup (PRIV (vms_symbol_table), symbol->name, TRUE, FALSE); if (entry == NULL) { bfd_set_error (bfd_error_no_memory); return -1; } if (entry->symbol) /* FIXME: DEC C generates this */ { #if VMS_DEBUG vms_debug (4, "EGSD_S_C_SYMG: duplicate \"%s\"\n", symbol->name); #endif } else { entry->symbol = symbol; PRIV (gsd_sym_count)++; abfd->symcount++; } return 0; }
int _bfd_vms_slurp_gsd (bfd * abfd, int objtype) { 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[0]; 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->size = bfd_getl32 (vms_rec + 4); /* allocation */ new_flags = vms_secflag_by_name (abfd, vax_section_flags, name, section->size > 0); 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->size; /* Global section is common symbol. */ if (old_flags & GPS_S_M_GBL) { entry = _bfd_vms_enter_symbol (abfd, name); if (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->size < old_section->size) { (*_bfd_error_handler) (_("Size mismatch section %s=%lx, %s=%lx"), old_section->name, (unsigned long) old_section->size, section->name, (unsigned long) section->size); return -1; } else if (section->size > old_section->size) { section->contents = bfd_realloc (old_section->contents, section->size); if (section->contents == NULL) { bfd_set_error (bfd_error_no_memory); return -1; } } } else { section->contents = bfd_zmalloc (section->size); if (section->contents == NULL) { bfd_set_error (bfd_error_no_memory); return -1; } } #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->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 /* Fall through. */ case GSD_S_C_SYM: case GSD_S_C_SYMW: { int name_offset = 0, value_offset = 0; /* 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 == 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 *)(unsigned long)psect; #if VMS_DEBUG vms_debug (4, "gsd sym def #%d (%s, %ld, %04x=%s)\n", abfd->symcount, symbol->name, (long)symbol->section, old_flags, flag2str(gsyflagdesc, old_flags)); #endif } else { /* Symbol reference. */ #if VMS_DEBUG vms_debug (4, "gsd sym ref #%d (%s, %04x=%s)\n", abfd->symcount, symbol->name, old_flags, flag2str (gsyflagdesc, old_flags)); #endif symbol->section = (asection *)(unsigned long)-1; } 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 + EGPS_S_B_NAMLNG); section = bfd_make_section (abfd, name); if (!section) return -1; old_flags = bfd_getl16 (vms_rec + EGPS_S_W_FLAGS); section->size = bfd_getl32 (vms_rec + EGPS_S_L_ALLOC); new_flags = vms_secflag_by_name (abfd, evax_section_flags, name, section->size > 0); 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[EGPS_S_B_ALIGN]; 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->size; section->contents = bfd_zmalloc (section->size); if (section->contents == NULL) return -1; section->filepos = (unsigned int)-1; #if VMS_DEBUG vms_debug (4, "EGSD P-section %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->size, section->vma, section->contents); #endif } break; case EGSD_S_C_SYM + EVAX_OFFSET: { /* Global symbol specification (definition or reference). */ symbol = bfd_make_empty_symbol (abfd); if (symbol == 0) return -1; old_flags = bfd_getl16 (vms_rec + EGSY_S_W_FLAGS); new_flags = BSF_NO_FLAGS; if (old_flags & EGSY_S_V_WEAK) new_flags |= BSF_WEAK; if (old_flags & EGSY_S_V_DEF) { /* Symbol definition. */ if (old_flags & EGSY_S_V_NORM) new_flags |= BSF_FUNCTION; symbol->name = _bfd_vms_save_counted_string (vms_rec + ESDF_S_B_NAMLNG); symbol->value = bfd_getl64 (vms_rec + ESDF_S_L_VALUE); symbol->section = (asection *)(unsigned long) bfd_getl32 (vms_rec + ESDF_S_L_PSINDX); #if VMS_DEBUG vms_debug (4, "EGSD sym def #%d (%s, %ld, %04x=%s)\n", abfd->symcount, symbol->name, (long)symbol->section, old_flags, flag2str (gsyflagdesc, old_flags)); #endif } else { /* Symbol reference. */ symbol->name = _bfd_vms_save_counted_string (vms_rec + ESRF_S_B_NAMLNG); #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 = (asection *)(unsigned long)-1; } symbol->flags = new_flags; /* Register symbol in VMS symbol table. */ entry = (vms_symbol_entry *) bfd_hash_lookup (PRIV (vms_symbol_table), symbol->name, TRUE, FALSE); if (entry == NULL) { bfd_set_error (bfd_error_no_memory); return -1; } if (entry->symbol != 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_SYMG + EVAX_OFFSET: { /* Universal symbol specification (definition). */ symbol = bfd_make_empty_symbol (abfd); if (symbol == 0) return -1; old_flags = bfd_getl16 (vms_rec + EGST_S_W_FLAGS); new_flags = BSF_NO_FLAGS; if (old_flags & EGSY_S_V_WEAK) new_flags |= BSF_WEAK; if (old_flags & EGSY_S_V_DEF) /* symbol definition */ { if (old_flags & EGSY_S_V_NORM) new_flags |= BSF_FUNCTION; symbol->name = _bfd_vms_save_counted_string (vms_rec + EGST_S_B_NAMLNG); /* For BSF_FUNCTION symbols, the entry point is in LP_1 and the descriptor in LP_2. For other symbols, the unique value is in LP_2. */ symbol->value = bfd_getl64 (vms_rec + EGST_S_Q_LP_2); /* Adding this offset is necessary in order for GDB to read the DWARF-2 debug info from shared libraries. */ if (abfd->flags & DYNAMIC && strstr (symbol->name, "$DWARF2.DEBUG") != 0) symbol->value += PRIV (symvva); } else /* symbol reference */ (*_bfd_error_handler) ("Invalid EGST reference"); symbol->flags = new_flags; if (register_universal_symbol (abfd, symbol, old_flags) < 0) return -1; /* Make a second symbol for the entry point. */ if (symbol->flags & BSF_FUNCTION) { asymbol *en_sym; char *name = bfd_alloc (abfd, strlen (symbol->name) + 5); en_sym = bfd_make_empty_symbol (abfd); if (en_sym == 0) return -1; strcpy (name, symbol->name); strcat (name, "..en"); en_sym->name = name; en_sym->value = bfd_getl64 (vms_rec + EGST_S_Q_LP_1); if (register_universal_symbol (abfd, en_sym, old_flags) < 0) return -1; } } 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; } PRIV (rec_size) -= gsd_size; PRIV (vms_rec) += gsd_size; } if (abfd->symcount > 0) abfd->flags |= HAS_SYMS; return 0; }
int _bfd_vms_write_gsd (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 defined(VMS_DEBUG) && VMS_DEBUG vms_debug (2, "vms_write_gsd (%p, %d)\n", abfd, objtype); #endif /* Output sections. */ section = abfd->sections; #if defined(VMS_DEBUG) && 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); /* Prepare output for subrecords. */ _bfd_vms_output_push (abfd); while (section != 0) { #if defined(VMS_DEBUG) && VMS_DEBUG vms_debug (3, "Section #%d %s, %d bytes\n", section->index, section->name, (int)section->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); /* Prepare output for subrecords. */ _bfd_vms_output_push (abfd); } /* Create dummy sections to keep consecutive indices. */ while (section->index - last_index > 1) { #if defined(VMS_DEBUG) && 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 necessary 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->size > 0); _bfd_vms_output_short (abfd, new_flags); _bfd_vms_output_long (abfd, (unsigned long) section->size); _bfd_vms_output_counted (abfd, sname); _bfd_vms_output_flush (abfd); last_index = section->index; section = section->next; } /* Output symbols. */ #if defined(VMS_DEBUG) && 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++) { char *hash; 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); /* Prepare output for subrecords. */ _bfd_vms_output_push (abfd); } _bfd_vms_output_begin (abfd, EGSD_S_C_SYM, -1); /* Data type, alignment. */ _bfd_vms_output_short (abfd, 0); new_flags = 0; if (old_flags & BSF_WEAK) new_flags |= EGSY_S_V_WEAK; if (bfd_is_com_section (symbol->section)) 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. */ uquad code_address = 0; unsigned long ca_psindx = 0; unsigned long psindx; if ((old_flags & BSF_FUNCTION) && symbol->udata.p != NULL) { code_address = ((asymbol *) (symbol->udata.p))->value; ca_psindx = ((asymbol *) (symbol->udata.p))->section->index; } psindx = symbol->section->index; _bfd_vms_output_quad (abfd, symbol->value); _bfd_vms_output_quad (abfd, code_address); _bfd_vms_output_long (abfd, ca_psindx); _bfd_vms_output_long (abfd, psindx); } hash = _bfd_vms_length_hash_symbol (abfd, symbol->name, EOBJ_S_C_SYMSIZ); _bfd_vms_output_counted (abfd, hash); _bfd_vms_output_flush (abfd); } _bfd_vms_output_alignment (abfd, 8); _bfd_vms_output_pop (abfd); _bfd_vms_output_end (abfd); return 0; }
/* Process GSD/EGSD record. * Return 0 on success, -1 on error. */ int _bfd_vms_slurp_gsd(bfd * abfd, int objtype) { #if defined(VMS_DEBUG) && 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 /* VMS_DEBUG */ 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; gsd_size = 0; #if defined(VMS_DEBUG) && VMS_DEBUG vms_debug(2, "GSD/EGSD (%d/%x)\n", objtype, objtype); #endif /* VMS_DEBUG */ 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 defined(VMS_DEBUG) && 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 defined(VMS_DEBUG) && 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->size = bfd_getl32 (vms_rec + 4); /* allocation */ new_flags = vms_secflag_by_name (abfd, vax_section_flags, name, section->size > 0); 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->size; /* Global section is common symbol. */ if (old_flags & GPS_S_M_GBL) { entry = _bfd_vms_enter_symbol (abfd, name); if (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->size < old_section->size) { (*_bfd_error_handler) (_("Size mismatch section %s=%lx, %s=%lx"), old_section->name, (unsigned long) old_section->size, section->name, (unsigned long) section->size); return -1; } else if (section->size > old_section->size) { section->contents = (unsigned char *)bfd_realloc(old_section->contents, section->size); if (section->contents == NULL) { bfd_set_error (bfd_error_no_memory); return -1; } } } else { section->contents = (unsigned char *)bfd_zmalloc(section->size); if (section->contents == NULL) { bfd_set_error (bfd_error_no_memory); return -1; } } #if defined(VMS_DEBUG) && 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->size, section->vma, section->contents); #endif /* VMS_DEBUG */ gsd_size = vms_rec[8] + 9; psect_idx++; } break; case GSD_S_C_EPM: case GSD_S_C_EPMW: #if defined(VMS_DEBUG) && VMS_DEBUG vms_debug (4, "gsd epm\n"); #endif /* Fall through. */ case GSD_S_C_SYM: case GSD_S_C_SYMW: { int name_offset = 0, value_offset = 0; /* Symbol specification (definition or reference). */ #if defined(VMS_DEBUG) && 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; default: break; } /* end "switch (gsd_type)" */ /* Save symbol in vms_symbol_table: */ entry = _bfd_vms_enter_symbol(abfd, _bfd_vms_save_counted_string(vms_rec + name_offset)); if (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 *) (size_t) psect; #if defined(VMS_DEBUG) && 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 defined(VMS_DEBUG) && 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 defined(VMS_DEBUG) && VMS_DEBUG vms_debug (4, "gsd pro\n"); #endif break; case GSD_S_C_IDC: #if defined(VMS_DEBUG) && VMS_DEBUG vms_debug (4, "gsd idc\n"); #endif break; case GSD_S_C_ENV: #if defined(VMS_DEBUG) && VMS_DEBUG vms_debug (4, "gsd env\n"); #endif break; case GSD_S_C_LSY: #if defined(VMS_DEBUG) && VMS_DEBUG vms_debug (4, "gsd lsy\n"); #endif break; case GSD_S_C_LEPM: #if defined(VMS_DEBUG) && VMS_DEBUG vms_debug (4, "gsd lepm\n"); #endif break; case GSD_S_C_LPRO: #if defined(VMS_DEBUG) && VMS_DEBUG vms_debug (4, "gsd lpro\n"); #endif break; case GSD_S_C_SPSC: #if defined(VMS_DEBUG) && VMS_DEBUG vms_debug (4, "gsd spsc\n"); #endif break; case GSD_S_C_SYMV: #if defined(VMS_DEBUG) && VMS_DEBUG vms_debug (4, "gsd symv\n"); #endif break; case GSD_S_C_EPMV: #if defined(VMS_DEBUG) && VMS_DEBUG vms_debug (4, "gsd epmv\n"); #endif break; case GSD_S_C_PROV: #if defined(VMS_DEBUG) && 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->size = bfd_getl32 (vms_rec + 8); /* Allocation. */ new_flags = vms_secflag_by_name (abfd, evax_section_flags, name, section->size > 0); 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->size; section->contents = (unsigned char *)bfd_zmalloc(section->size); if (section->contents == NULL) return -1; #if defined(VMS_DEBUG) && 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->size, section->vma, section->contents); #endif } break; case EGSD_S_C_SYM + EVAX_OFFSET: { /* Symbol specification (definition or reference). */ symbol = bfd_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 defined(VMS_DEBUG) && 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 defined(VMS_DEBUG) && 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 == NULL) { bfd_set_error(bfd_error_no_memory); return -1; } if (entry->symbol != NULL) { /* FIXME ?, DEC C generates this. */ #if defined(VMS_DEBUG) && VMS_DEBUG vms_debug(4, "EGSD_S_C_SYM: duplicate \"%s\"\n", symbol->name); #endif /* VMS_DEBUG */ } 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; } PRIV(rec_size) -= gsd_size; PRIV(vms_rec) += gsd_size; } if (abfd->symcount > 0) abfd->flags |= HAS_SYMS; return 0; }