/* Write resource file */ void write_res_file (const char *fn,const rc_res_directory *resdir) { asection *sec; rc_uint_type language; bfd *abfd; windres_bfd wrbfd; unsigned long sec_length = 0,sec_length_wrote; static const bfd_byte sign[] = {0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; filename = fn; abfd = windres_open_as_binary (filename, 0); sec = bfd_make_section (abfd, ".data"); if (sec == NULL) bfd_fatal ("bfd_make_section"); if (! bfd_set_section_flags (abfd, sec, (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_DATA))) bfd_fatal ("bfd_set_section_flags"); /* Requiring this is probably a bug in BFD. */ sec->output_section = sec; set_windres_bfd (&wrbfd, abfd, sec, (target_is_bigendian ? WR_KIND_BFD_BIN_B : WR_KIND_BFD_BIN_L)); language = -1; sec_length = write_res_directory ((windres_bfd *) NULL, 0x20UL, resdir, (const rc_res_id *) NULL, (const rc_res_id *) NULL, &language, 1); if (! bfd_set_section_size (abfd, sec, (sec_length + 3) & ~3)) bfd_fatal ("bfd_set_section_size"); if ((sec_length & 3) != 0) set_windres_bfd_content (&wrbfd, sign, sec_length, 4-(sec_length & 3)); set_windres_bfd_content (&wrbfd, sign, 0, sizeof (sign)); language = -1; sec_length_wrote = write_res_directory (&wrbfd, 0x20UL, resdir, (const rc_res_id *) NULL, (const rc_res_id *) NULL, &language, 1); if (sec_length != sec_length_wrote) fatal ("res write failed with different sizes (%lu/%lu).", (long) sec_length, (long) sec_length_wrote); bfd_close (abfd); return; }
static void mips_elf32_after_open() { /* Call the standard elf routine. */ gldelf32ltsmip_after_open (); #ifdef SUPPORT_EMBEDDED_RELOCS if (command_line.embedded_relocs && (! link_info.relocateable)) { bfd *abfd; /* In the embedded relocs mode we create a .rel.sdata section for each input file with a .sdata section which has has relocations. The BFD backend will fill in these sections with magic numbers which can be used to relocate the data section at run time. */ for (abfd = link_info.input_bfds; abfd != NULL; abfd = abfd->link_next) { asection *datasec; /* As first-order business, make sure that each input BFD is ELF. We need to call a special BFD backend function to generate the embedded relocs, and we have that function only for ELF */ if (bfd_get_flavour (abfd) != bfd_target_elf_flavour) einfo ("%F%B: all input objects must be ELF for --embedded-relocs\n"); if (bfd_get_arch_size (abfd) != 32) einfo ("%F%B: all input objects must be 32-bit ELF for --embedded-relocs\n"); datasec = bfd_get_section_by_name (abfd, ".sdata"); /* Note that we assume that the reloc_count field has already been set up. We could call bfd_get_reloc_upper_bound, but that returns the size of a memory buffer rather than a reloc count. We do not want to call bfd_canonicalize_reloc, because although it would always work it would force us to read in the relocs into BFD canonical form, which would waste a significant amount of time and memory. */ if (datasec != NULL && datasec->reloc_count > 0) { asection *relsec; relsec = bfd_make_section (abfd, ".rel.sdata"); if (relsec == NULL || ! bfd_set_section_flags (abfd, relsec, (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY)) || ! bfd_set_section_alignment (abfd, relsec, (32 == 32) ? 2 : 3) || ! bfd_set_section_size (abfd, relsec, datasec->reloc_count * ((32 / 8) + 8))) einfo ("%F%B: cannot create .rel.sdata section: %E\n"); } /* Double check that all other data sections have no relocs, as is required for embedded PIC code. */ bfd_map_over_sections (abfd, mips_elf32_check_sections, (PTR) datasec); } } #endif /* SUPPORT_EMBEDDED_RELOCS */ }
static void emit_so_bfd(const Chunk *base, uint64_t textOffs, uint64_t textLen, std::vector<MethBlock> &blocks, std::vector<DebugInfo> &debugInfos) { bfd_init(); bfd *abfd = bfd_openw("jit.o", #ifdef __MACH__ "mach-o-i386" #else "elf32-i386" #endif ) ; bfd_set_format(abfd, bfd_object); #ifdef __MACH__ bfd_set_arch_mach(abfd, bfd_arch_i386, bfd_mach_i386_i386); #else bfd_set_arch_mach(abfd, bfd_arch_i386, bfd_mach_i386_i386); #endif asection *textSection = bfd_make_section(abfd, ".text"); bfd_set_section_flags( abfd, textSection, SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE | SEC_HAS_CONTENTS); #ifdef __MACH__ bfd_set_section_size(abfd, textSection, textLen); // for mach-o, the .o we generate is linked into a .dylib // so just set the alignment to make sure things end up // in the right place after link textSection->alignment_power = l2(textOffs); static const uint64_t textAdj = 0; #else bfd_set_section_size(abfd, textSection, textLen + textOffs); // for linux (and oprofile) the generated object is used // directly, so just offset the symbols uint64_t textAdj = textOffs; #endif asymbol **symbols = (asymbol **) malloc( sizeof(asymbol *) * (6 + blocks.size())); uint64_t start = ((uint64_t *) base->data)[0] + textOffs; int n = 0; std::map<std::string, int> namesSeen; std::vector<MethBlock>::const_iterator i, e; symbols[n++] = make_glob_symbol(abfd, "__jitStart", textSection, textAdj); symbols[n++] = make_glob_symbol(abfd, "_jitStart", textSection, textAdj); for (i = blocks.begin(), e = blocks.end(); i != e; i++, n++) { std::string name = i->name(); int seen = namesSeen[name]++; if (seen) { char buf[16]; sprintf(buf, " (%d)", seen); name += buf; } symbols[n] = make_glob_symbol(abfd, name.c_str(), textSection, i->start() - start + textAdj); } symbols[n++] = make_glob_symbol(abfd, "__jitUnused", textSection, blocks.back().end() - start + textAdj); symbols[n++] = make_glob_symbol(abfd, "_jitUnused", textSection, blocks.back().end() - start + textAdj); symbols[n++] = make_glob_symbol(abfd, "__jitEnd", textSection, textLen + textAdj); symbols[n++] = make_glob_symbol(abfd, "_jitEnd", textSection, textLen + textAdj); bfd_set_symtab(abfd, symbols, n); for (i = blocks.begin(), e = blocks.end(); i != e; i++, n++) if (i->codeBytes()) bfd_set_section_contents(abfd, textSection, i->codeBytes(), i->start() - start, i->codeLen()); bfd_close(abfd); for (int n = 0; n < blocks.size(); n++) free((void *) symbols[n]->name); free(symbols); }
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; }
static const bfd_target * aout_adobe_callback (bfd *abfd) { struct internal_exec *execp = exec_hdr (abfd); asection *sect; struct external_segdesc ext[1]; char *section_name; char try_again[30]; /* Name and number. */ char *newname; int trynum; flagword flags; /* Architecture and machine type -- unknown in this format. */ bfd_set_arch_mach (abfd, bfd_arch_unknown, 0L); /* The positions of the string table and symbol table. */ obj_str_filepos (abfd) = N_STROFF (*execp); obj_sym_filepos (abfd) = N_SYMOFF (*execp); /* Suck up the section information from the file, one section at a time. */ for (;;) { bfd_size_type amt = sizeof (*ext); if (bfd_bread ( ext, amt, abfd) != amt) { if (bfd_get_error () != bfd_error_system_call) bfd_set_error (bfd_error_wrong_format); return NULL; } switch (ext->e_type[0]) { case N_TEXT: section_name = ".text"; flags = SEC_CODE | SEC_LOAD | SEC_ALLOC | SEC_HAS_CONTENTS; break; case N_DATA: section_name = ".data"; flags = SEC_DATA | SEC_LOAD | SEC_ALLOC | SEC_HAS_CONTENTS; break; case N_BSS: section_name = ".bss"; flags = SEC_DATA | SEC_HAS_CONTENTS; break; case 0: goto no_more_sections; default: (*_bfd_error_handler) (_("%B: Unknown section type in a.out.adobe file: %x\n"), abfd, ext->e_type[0]); goto no_more_sections; } /* First one is called ".text" or whatever; subsequent ones are ".text1", ".text2", ... */ bfd_set_error (bfd_error_no_error); sect = bfd_make_section (abfd, section_name); trynum = 0; while (!sect) { if (bfd_get_error () != bfd_error_no_error) /* Some other error -- slide into the sunset. */ return NULL; sprintf (try_again, "%s%d", section_name, ++trynum); sect = bfd_make_section (abfd, try_again); } /* Fix the name, if it is a sprintf'd name. */ if (sect->name == try_again) { amt = strlen (sect->name); newname = bfd_zalloc (abfd, amt); if (newname == NULL) return NULL; strcpy (newname, sect->name); sect->name = newname; } /* Now set the section's attributes. */ bfd_set_section_flags (abfd, sect, flags); /* Assumed big-endian. */ sect->size = ((ext->e_size[0] << 8) | ext->e_size[1] << 8 | ext->e_size[2]); sect->vma = H_GET_32 (abfd, ext->e_virtbase); sect->filepos = H_GET_32 (abfd, ext->e_filebase); /* FIXME XXX alignment? */ /* Set relocation information for first section of each type. */ if (trynum == 0) switch (ext->e_type[0]) { case N_TEXT: sect->rel_filepos = N_TRELOFF (*execp); sect->reloc_count = execp->a_trsize; break; case N_DATA: sect->rel_filepos = N_DRELOFF (*execp); sect->reloc_count = execp->a_drsize; break; default: break; } } no_more_sections: adata (abfd).reloc_entry_size = sizeof (struct reloc_std_external); adata (abfd).symbol_entry_size = sizeof (struct external_nlist); adata (abfd).page_size = 1; /* Not applicable. */ adata (abfd).segment_size = 1; /* Not applicable. */ adata (abfd).exec_bytes_size = EXEC_BYTES_SIZE; return abfd->xvec; }
/* 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; }