📄 vms-gsd.c
字号:
/* vms-gsd.c -- BFD back-end for VAX (openVMS/VAX) and EVAX (openVMS/Alpha) files. Copyright 1996, 1997, 1998, 1999, 2000 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 modifyit under the terms of the GNU General Public License as published bythe 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 ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with this program; if not, write to the Free SoftwareFoundation, 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 flagwordvms_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 flagwordvms_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");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -