diff options
-rw-r--r-- | bfd/ChangeLog | 212 | ||||
-rw-r--r-- | bfd/bfd-in2.h | 16 | ||||
-rw-r--r-- | bfd/bfdio.c | 22 | ||||
-rw-r--r-- | bfd/libbfd.h | 4 | ||||
-rw-r--r-- | bfd/makefile.vms | 10 | ||||
-rw-r--r-- | bfd/reloc.c | 24 | ||||
-rw-r--r-- | bfd/vms-gsd.c | 347 | ||||
-rw-r--r-- | bfd/vms-hdr.c | 1090 | ||||
-rw-r--r-- | bfd/vms-misc.c | 520 | ||||
-rw-r--r-- | bfd/vms-tir.c | 1559 | ||||
-rw-r--r-- | bfd/vms.c | 823 | ||||
-rw-r--r-- | bfd/vms.h | 635 |
12 files changed, 4026 insertions, 1236 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 32ae0d89..17a23d7 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,215 @@ +2009-02-23 Tristan Gingold <gingold@adacore.com> + + * vms.h: Update copyright year, fix comments, reorder declarations. + (_bfd_save_vms_section): Remove the prototype. + (EGPS_S_V_NO_SHIFT): New constant. + (bfd_vms_set_section_flags): New prototype. + (EGPS_S_B_ALIGN, EGPS_S_W_FLAGS, EGPS_S_L_ALLOC, EGPS_S_B_NAMLNG): New + constants. + (EGSY_S_W_FLAGS): Ditto. + (EGSY_S_V_QUAD_VAL): Ditto. + (ESDF_S_L_VALUE, ESDF_S_L_PSINDX, ESDF_S_B_NAMLNG): Ditto. + (EGST_S_W_FLAGS, EGST_S_Q_LP_1, EGST_S_Q_LP_2, EGST_S_L_PSINDX, + EGST_S_B_NAMLNG): Ditto. + (ESRF_S_B_NAMLNG): Ditto. + (ETIR_S_C_HEADER_SIZE): Ditto. + (EGPS_S_V_ALLOC_64BIT): Ditto. + (DST_S_C_EPILOG): Ditto. + (DST_S_C_SRC_SETLNUM_L, DST_S_C_SRC_SETLNUM_W) : Ditto. + (DST_S_C_SRC_INCRLNUM_B): Ditto. + (DST_S_B_PCLINE_UNSBYTE, DST_S_W_PCLINE_UNSWORD): Ditto. + (DST_S_L_PCLINE_UNSLONG): Ditto. + (DST_S_B_MODBEG_NAME, DST_S_L_RTNBEG_ADDRESS) : Ditto + (DST_S_B_RTNBEG_NAME, DST_S_L_RTNEND_SIZE): Ditto + (DST_S_C_SOURCE_HEADER_SIZE): Ditto. + (DST_S_B_SRC_DF_LENGTH, DST_S_W_SRC_DF_FILEID): Ditto. + (DST_S_B_SRC_DF_FILENAME, DST_S_B_SRC_UNSBYTE): Ditto. + (DST_S_B_SRC_UNSBYTE): Ditto. + (DST_S_W_SRC_UNSWORD, DST_S_L_SRC_UNSLONG): Ditto. + Add prototypes. + (vms_section, vms_reloc): Remove types. + (hdr_struc): Replaced by ... + (hdr_struct): ... new type. + (EMH_S_W_HDRTYP, EMH_S_B_STRLVL, EMH_S_L_ARCH1): New constants. + (EMH_S_L_ARCH2, EMH_S_L_RECSIZ, EMH_S_B_NAMLNG): Ditto. + (EMH_DATE_LENGTH): Ditto. + (eom_struc): Replaced by ... + (eom_struct): ... new type. + (EEOM_S_L_TOTAL_LPS, EEOM_S_W_COMCOD, EEOM_S_B_TFRFLG): New constants. + (EEOM_S_L_PSINDX, EEOM_S_L_TFRADR): Ditto. + (EIHD_S_K_MAJORID, EIHD_S_K_MINORID, EIHD_S_K_EXE): Ditto. + (EIHD_S_L_SIZE, EIHD_S_L_ISDOFF, EIHD_S_L_SYMDBGOFF): Ditto. + (EIHD_S_Q_SYMVVA, EIHD_S_L_IMGTYPE): Ditto. + (EISD_S_L_EISDSIZE, EISD_S_L_SECSIZE, EISD_S_Q_VIR_ADDR): Ditto. + (EISD_S_L_FLAGS, EISD_S_L_VBN, EISD_S_R_CONTROL): Ditto. + (EISD_S_L_IDENT, EISD_S_T_GBLNAM): Ditto. + (EISD_S_M_GBL, EISD_S_M_CRF, EISD_S_M_DZRO, EISD_S_M_WRT): Ditto. + (EISD_S_M_INITALCODE, EISD_S_M_BASED, EISD_S_M_FIXUPVEC): Ditto. + (EISD_S_M_RESIDENT, EISD_S_M_VECTOR, EISD_S_M_PROTECT): Ditto. + (EISD_S_M_LASTCLU, EISD_S_M_EXE, EISD_S_M_NONSHRADR): Ditto. + (EISD_S_M_QUAD_LENGTH, EISD_S_M_ALLOC_64BIT): Ditto. + (EIHS_S_L_DSTVBN, EIHS_S_L_DSTSIZE, EIHS_S_L_GSTVBN): Ditto. + (EIHS_S_L_GSTSIZE, EIHS_S_L_DMTVBN, EIHS_S_L_DMTBYTES): Ditto. + (DBG_S_L_DMT_MODBEG, DBG_S_L_DST_SIZE): Ditto. + (DBG_S_W_DMT_PSECT_COUNT, DBG_S_C_DMT_HEADER_SIZE): Ditto. + (DBG_S_L_DMT_PSECT_START, DBG_S_L_DMT_PSECT_LENGTH) + (DBG_S_C_DMT_PSECT_SIZE): Ditto. + (enum file_type_enum): New type. + (struct location_struct): Removed. + (struct fileinfo, struct srecinfo, struct lineinfo): New types. + (struct funcinfo, struct module): Ditto. + (struct vms_private_data_struct): Update fields. + (struct vms_section_data_struct): New type. + + * vms.c: Update copyright year, fix comments, + Fix includes for DECC, add prototypes. + (vms_initialize): Use bfd_alloc instead of bfd_zalloc and remove + some initializers. + Use flavour to set is_vax, location_stack is removed. + (struct pair): Declare. + (fill_section_ptr): Initialize variables at declaration. + Add guard to set SECTION_SYM flag, handlde und section. + (vms_fixup_sections): Use struct pair for fill_section_ptr argument. + (_bfd_vms_slurp_object_records): New function, replaces previous + vms_object_p. + (vms_slurp_module): New function. + (vms_slurp_image): Ditto. + (vms_object_p): Complete rewrite. + (vms_mkobject): Use is_vax field to slect architecture. + (free_reloc_stream): New function. + (vms_convert_to_var): Ditto. + (vms_convert_to_var_1): Ditto. + (vms_convert_to_var_unix_filename): Ditto. + (vms_close_and_cleanup): Call free_reloc_stream, convert file to + VAR format on VMS. + (vms_new_section_hook): Set alignment to 0, allocate private data. + (vms_get_section_contents): Load content. + (vms_get_symbol_info): Handle undefined section. + (vms_find_nearest_line): Handle. + (alloc_reloc_stream): New function. + (vms_slurp_reloc_table): Ditto. + (vms_get_reloc_upper_bound): Make it real. + (vms_canonicalize_reloc): Do the real work. + (alpha_howto_table): Add ALPHA_R_NOP, ALPHA_R_BSR, ALPHA_R_LDA, + ALPHA_R_BOH. + (vms_bfd_reloc_type_lookup): Handle NOP, BSR, LDA and BOH. + (vms_set_arch_mach): Check arch. + (vms_set_section_contents): Copy the content after allocation. + (vms_alpha_vec): Update object flags. + + * vms-tir.c: Update copyright year, fix comments, + add prototypes for new functions. + (dst_define_location): New function. + (dst_restore_location): New function. + (dst_retrieve_location): New function. + (dst_check_allocation): New function. + (image_dump): Call dst_check_allocation. + (image_write_b): Ditto. + (image_write_w): Ditto. + (image_write_l): Ditto. + (image_write_q): Ditto. + (cmd_name): Handle STA_LW, STA_QW, STO_OFF, STO_IMM, STO_IMMR, STO_LW, + STO_QW, OPR_ADD, CTL_SETRB, STC_LP_PSB, CTL_DFLOC, CTL_STLOC, + CTL_STKDL. + Call error handler instead of abort if name is not known. + (etir_sta): Add quarter_relocs argument and set it. + Fix cast. + (etir_sto): Ditto. + (etir_opr): Ditto, return FALSE in case of error. + (etir_ctl): Add quarter_relocs argument and set it, fix cast. + Fix CTL_DFLOC, CTL_STLOC, CTL_STKDL. + (etir_stc): Add quarter_relocs argument and set it, fix cast. + Fix STC_LP, STC_LP_PSB, STC_GBL and STC_CGA. + Handle STC_LP_PSB, STC_BSR_GBL, STC_LDA_GBL, STC_BOH_GBL. + Move STC_NOP_PS, STC_BSR_PS, STC_LDA_PS, STC_BOH_PS, STC_NBH_PS. + Return FALSE in case of error. + (tir_sta): Change sign of psect. + (tir_ctl): Ditto. + (tir_cmd): Fix cast. Makes tir_table static const. + (etir_cmd): Add quarter_relocs argument, makes etir_table const, + add argument to explain. + (analyze_etir): Initialize maxptr, add quarter_relocs + declaration, move some declarations into inner scopes. + Handle quarter_relocs and STO_IMM. + (_bfd_vms_slurp_tir): Use constant instead of hard-coded values. + (_bfd_vms_slurp_relocs): New function. + (_bfd_vms_decode_relocs): New function. + (sto_imm): Rewritten. + (start_first_etbt_record): New function. + (start_another_etbt_record): Ditto. + (etir_output_check): Ditto. + (defer_reloc_p): Ditto. + (_bfd_vms_write_tir): Remove nextoffset, convert a while-loop to + a for-loop. Correctly deals with contents, deals with .vmsdebug, + rewritte relocations handling. + (_bfd_vms_write_tbt): Removed. + (_bfd_vms_write_dbg): Ditto. + + * vms-misc.c: Update copyright year, Fix comments. + (_bfd_vms_get_header_values): Use 'size' instead of 'length'. + (maybe_adjust_record_pointer_for_object): New function. + (_bfd_vms_get_first_record): New function, replaces ... + (_bfd_vms_get_record): .. removed. + (_bfd_vms_get_object_record): New function. + (_bfd_vms_get_object_record): New function. + (vms_get_remaining_object_record): New function, replaces ... + (_bfd_vms_get_next_record): ... removed. + (add_new_contents): Removed. + (_bfd_save_vms_section): Removed. + (_bfd_get_vms_section): Removed. + (_bfd_vms_output_flush): Write in VAR format. + (new_symbol): Don't make UND section. + + * vms-hdr.c: Update copyright year, update list of record handled. + (_bfd_vms_slurp_hdr): rec_length renamed to rec_size. + (_bfd_vms_write_hdr): Strip vms and unix patches, + add comments, truncate module name at 31 characters, + use constants instead of hard-coded value, + write BFD version instead of a fixed string. + (_bfd_vms_slurp_ihd): New function. + (_bfd_vms_slurp_isd): Ditto. + (_bfd_vms_slurp_ihs): Ditto. + (new_module): Ditto. + (parse_module): Ditto + (build_module_list): Ditto. + (module_find_nearest_line): Ditto. + (_bfd_vms_find_nearest_dst_line): Ditto. + (vms_slurp_debug): Ditto. + (_bfd_vms_slurp_dbg): Ditto. + (_bfd_vms_slurp_tbt): Ditto. + (_bfd_vms_write_dbg): Ditto. + (_bfd_vms_write_tbt): Ditto. + + * vms-gsd.c: Update copyright year, update list of records handled. + (EVAX_LITERALS_NAME): New macro. + (evax_section_flags): Add an entry for EVAX_LITERALS_NAME. + (gpsflagdesc, gsyflagdesc): Moved out of _bfd_vms_slurp_gsd. + (register_universal_symbol): New function and prototype. + (_bfd_vms_slurp_gsd): Fix indentations and casts, + improve debug messages, + use constants instead of hard-coded value, + fix missing endianness conversion, + handle global symbol (SYMG). + (bfd_vms_set_section_flags): New function. + (_bfd_vms_write_gsd): Don't write .vmsdebug section, + handle section literals, + fix indentation, + handle section bfd and vms flags, + don't output LIB$INITIALIZE symbol, + fix handling of weak symbols, + fix evax vs vax procedure descriptor, + handle absolute symbols. + + * reloc.c (BFD_RELOC_ALPHA_NOP, BFD_RELOC_ALPHA_BSR, + BFD_RELOC_ALPHA_LDA, BFD_RELOC_ALPHA_BOH): New relocations. + + * makefile.vms (DEFS): Fix flags for VMS. + + * bfdio.c (real_fopen): Handle multiple VMS fopen attributes. + + * bfd-in2.h: Regenerated. + * libbfd.h: Regenerated. + 2009-02-20 Cary Coutant <ccoutant@google.com> * vmsutil.c (vms_file_stats_name): Fix incorrect use of st_mtime diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index 994759d..7870962 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -2586,6 +2586,22 @@ share a common GP, and the target address is adjusted for STO_ALPHA_STD_GPLOAD. */ BFD_RELOC_ALPHA_BRSGP, +/* The NOP relocation outputs a NOP if the longword displacement +between two procedure entry points is < 2^21. */ + BFD_RELOC_ALPHA_NOP, + +/* The BSR relocation outputs a BSR if the longword displacement +between two procedure entry points is < 2^21. */ + BFD_RELOC_ALPHA_BSR, + +/* The LDA relocation outputs a LDA if the longword displacement +between two procedure entry points is < 2^16. */ + BFD_RELOC_ALPHA_LDA, + +/* The BOH relocation outputs a BSR if the longword displacement +between two procedure entry points is < 2^21, or else a hint. */ + BFD_RELOC_ALPHA_BOH, + /* Alpha thread-local storage relocations. */ BFD_RELOC_ALPHA_TLSGD, BFD_RELOC_ALPHA_TLSLDM, diff --git a/bfd/bfdio.c b/bfd/bfdio.c index 7cba51f..d3a295c 100644 --- a/bfd/bfdio.c +++ b/bfd/bfdio.c @@ -102,13 +102,21 @@ real_fopen (const char *filename, const char *modes) } else { - /* Attribute found - rebuild modes. */ - size_t modes_len = vms_attr - modes; - - BFD_ASSERT (modes_len < sizeof (vms_modes)); - memcpy (vms_modes, modes, modes_len); - vms_modes[modes_len] = 0; - return close_on_exec (fopen (filename, vms_modes, vms_attr + 1)); + /* Attributes found. Split. */ + size_t modes_len = strlen (modes) + 1; + char attrs[modes_len + 1]; + char *at[3]; + int i; + + memcpy (attrs, modes, modes_len); + at[0] = attrs; + for (i = 0; i < 2; i++) + { + at[i + 1] = strchr (at[i], ','); + BFD_ASSERT (at[i + 1] != NULL); + *(at[i + 1]++) = 0; /* Replace ',' with a nul, and skip it. */ + } + return close_on_exec (fopen (filename, at[0], at[1], at[2])); } #else /* !VMS */ #if defined (HAVE_FOPEN64) diff --git a/bfd/libbfd.h b/bfd/libbfd.h index 26238b5..2ba7fc8 100644 --- a/bfd/libbfd.h +++ b/bfd/libbfd.h @@ -957,6 +957,10 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@", "BFD_RELOC_ALPHA_GPREL_HI16", "BFD_RELOC_ALPHA_GPREL_LO16", "BFD_RELOC_ALPHA_BRSGP", + "BFD_RELOC_ALPHA_NOP", + "BFD_RELOC_ALPHA_BSR", + "BFD_RELOC_ALPHA_LDA", + "BFD_RELOC_ALPHA_BOH", "BFD_RELOC_ALPHA_TLSGD", "BFD_RELOC_ALPHA_TLSLDM", "BFD_RELOC_ALPHA_DTPMOD64", diff --git a/bfd/makefile.vms b/bfd/makefile.vms index 963441a..2e2d2a1 100644 --- a/bfd/makefile.vms +++ b/bfd/makefile.vms @@ -36,13 +36,15 @@ endif CFLAGS=/include=([],[-.include])$(DEFS) else ifeq ($(ARCH),ALPHA) -DEFS=/define=(SELECT_VECS="&vms_alpha_vec",SELECT_ARCHITECTURES="&bfd_alpha_arch",\ -"HAVE_vms_alpha_vec=1","unlink=remove","DEBUGDIR=NULL") +DEFS=/define=(SELECT_VECS="&vms_alpha_vec",\ + SELECT_ARCHITECTURES="&bfd_alpha_arch",\ + "HAVE_vms_alpha_vec=1","unlink=remove","DEBUGDIR=NULL") else DEFS=/define=(SELECT_VECS="&vms_vax_vec",SELECT_ARCHITECTURES="&bfd_vax_arch",\ -"HAVE_vms_vax_vec=1","unlink=remove","const=") + "HAVE_vms_vax_vec=1","unlink=remove") endif -CFLAGS=/noopt/debug/show=incl/name=(as_is,shortened)/include=([],[-.include])$(DEFS)/warnings=disable=(missingreturn,longextern) +OPT=/noopt/debug +CFLAGS=/name=(as_is,shortened)/include=([],[-.include])$(DEFS)$(OPT) endif diff --git a/bfd/reloc.c b/bfd/reloc.c index 0c0fb1d3..781147e 100644 --- a/bfd/reloc.c +++ b/bfd/reloc.c @@ -2110,6 +2110,30 @@ ENUMDOC STO_ALPHA_STD_GPLOAD. ENUM + BFD_RELOC_ALPHA_NOP +ENUMDOC + The NOP relocation outputs a NOP if the longword displacement + between two procedure entry points is < 2^21. + +ENUM + BFD_RELOC_ALPHA_BSR +ENUMDOC + The BSR relocation outputs a BSR if the longword displacement + between two procedure entry points is < 2^21. + +ENUM + BFD_RELOC_ALPHA_LDA +ENUMDOC + The LDA relocation outputs a LDA if the longword displacement + between two procedure entry points is < 2^16. + +ENUM + BFD_RELOC_ALPHA_BOH +ENUMDOC + The BOH relocation outputs a BSR if the longword displacement + between two procedure entry points is < 2^21, or else a hint. + +ENUM BFD_RELOC_ALPHA_TLSGD ENUMX BFD_RELOC_ALPHA_TLSLDM diff --git a/bfd/vms-gsd.c b/bfd/vms-gsd.c index 4bdc27c..e641d0d 100644 --- a/bfd/vms-gsd.c +++ b/bfd/vms-gsd.c @@ -1,9 +1,12 @@ /* vms-gsd.c -- BFD back-end for VAX (openVMS/VAX) and EVAX (openVMS/Alpha) files. Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, - 2007 Free Software Foundation, Inc. + 2007, 2009 Free Software Foundation, Inc. - go and read the openVMS linker manual (esp. appendix B) + GSD record handling functions + EGSD record handling functions + + 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) @@ -46,6 +49,7 @@ #define EVAX_READONLYADDR_NAME "$READONLY_ADDR$" #define EVAX_READONLY_NAME "$READONLY$" #define EVAX_LITERAL_NAME "$LITERAL$" +#define EVAX_LITERALS_NAME "$LITERALS" #define EVAX_COMMON_NAME "$COMMON$" #define EVAX_LOCAL_NAME "$LOCAL$" @@ -133,6 +137,11 @@ static struct sec_flags_struct evax_section_flags[] = (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_LITERALS_NAME, + (EGPS_S_V_PIC | EGPS_S_V_OVR), + (SEC_DATA | SEC_READONLY), + (EGPS_S_V_PIC | EGPS_S_V_OVR), + (SEC_IN_MEMORY | SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_READONLY | SEC_LOAD) }, { NULL, (EGPS_S_V_REL | EGPS_S_V_RD | EGPS_S_V_WRT), (SEC_DATA), @@ -197,6 +206,37 @@ vms_esecflag_by_name (struct sec_flags_struct *section_flags, struct flagdescstruct { char *name; flagword value; }; +static const struct flagdescstruct gpsflagdesc[] = +{ + { "PIC", GPS_S_M_PIC }, + { "LIB", GPS_S_M_LIB }, + { "OVR", GPS_S_M_OVR }, + { "REL", GPS_S_M_REL }, + { "GBL", GPS_S_M_GBL }, + { "SHR", GPS_S_M_SHR }, + { "EXE", GPS_S_M_EXE }, + { "RD", GPS_S_M_RD }, + { "WRT", GPS_S_M_WRT }, + { "VEC", GPS_S_M_VEC }, + { "NOMOD", EGPS_S_V_NOMOD }, + { "COM", EGPS_S_V_COM }, + { NULL, 0 } +}; + +static const struct flagdescstruct gsyflagdesc[] = +{ + { "WEAK", GSY_S_M_WEAK }, + { "DEF", GSY_S_M_DEF }, + { "UNI", GSY_S_M_UNI }, + { "REL", GSY_S_M_REL }, + { "COMM", EGSY_S_V_COMM }, + { "VECEP", EGSY_S_V_VECEP }, + { "NORM", EGCY_S_V_NORM }, + { NULL, 0 } +}; + +static char *flag2str (struct flagdescstruct *, flagword); + /* Convert flag to printable string. */ static char * @@ -224,43 +264,15 @@ flag2str (struct flagdescstruct * flagdesc, flagword flags) /* Input routines. */ +static int register_universal_symbol (bfd *abfd, asymbol *symbol, + int vms_flags); + /* Process GSD/EGSD record return 0 on success, -1 on error. */ int _bfd_vms_slurp_gsd (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; @@ -300,7 +312,7 @@ _bfd_vms_slurp_gsd (bfd * abfd, int objtype) vms_rec = PRIV (vms_rec); if (objtype == OBJ_S_C_GSD) - gsd_type = *vms_rec; + gsd_type = vms_rec[0]; else { _bfd_vms_get_header_values (abfd, vms_rec, &gsd_type, &gsd_size); @@ -322,7 +334,7 @@ _bfd_vms_slurp_gsd (bfd * abfd, int objtype) 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))) + if (PRIV (is_vax) && (psect_idx < (abfd->section_count - 1))) { /* Check for temporary section from TIR record. */ if (psect_idx < PRIV (section_count)) @@ -362,7 +374,6 @@ _bfd_vms_slurp_gsd (bfd * abfd, int objtype) base_addr += section->size; /* Global section is common symbol. */ - if (old_flags & GPS_S_M_GBL) { entry = _bfd_vms_enter_symbol (abfd, name); @@ -496,21 +507,20 @@ _bfd_vms_slurp_gsd (bfd * abfd, int objtype) else psect = vms_rec[value_offset-1]; - symbol->section = (asection *) (size_t) psect; + symbol->section = (asection *)(unsigned long)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)); + 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. */ - 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)); + 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; @@ -574,19 +584,19 @@ _bfd_vms_slurp_gsd (bfd * abfd, int objtype) case EGSD_S_C_PSC + EVAX_OFFSET: { /* Program section definition. */ - name = _bfd_vms_save_counted_string (vms_rec + 12); + 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 + 6); - section->size = bfd_getl32 (vms_rec + 8); /* Allocation. */ + 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[4]; + 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)); @@ -595,9 +605,10 @@ _bfd_vms_slurp_gsd (bfd * abfd, int objtype) section->contents = bfd_zmalloc (section->size); if (section->contents == NULL) return -1; + section->filepos = (unsigned int)-1; #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, "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 @@ -606,50 +617,52 @@ _bfd_vms_slurp_gsd (bfd * abfd, int objtype) case EGSD_S_C_SYM + EVAX_OFFSET: { - /* Symbol specification (definition or reference). */ + /* Global symbol specification (definition or reference). */ symbol = bfd_make_empty_symbol (abfd); if (symbol == 0) return -1; - old_flags = bfd_getl16 (vms_rec + 6); + 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 (vms_rec[6] & EGSY_S_V_DEF) + if (old_flags & 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)); + 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, %d, %04x=%s)\n", abfd->symcount, - symbol->name, (int) symbol->section, old_flags, - flag2str (gsyflagdesc, old_flags)); + 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 + 8); + 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)); + 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->section = (asection *)(unsigned long)-1; } 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); + /* 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); @@ -672,11 +685,73 @@ _bfd_vms_slurp_gsd (bfd * abfd, int objtype) } break; - case EGSD_S_C_IDC + EVAX_OFFSET: + 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_error_handler) (_("Unknown GSD/EGSD subtype %d"), gsd_type); bfd_set_error (bfd_error_bad_value); return -1; } @@ -691,7 +766,79 @@ _bfd_vms_slurp_gsd (bfd * abfd, int objtype) return 0; } -/* Output routines. */ +/* Register a universal symbol in the VMS symbol table. */ + +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; +} + +/* Set section VMS flags. */ + +void +bfd_vms_set_section_flags (bfd *abfd ATTRIBUTE_UNUSED, + asection *sec, flagword flags) +{ + vms_section_data (sec)->vflags = flags; +} /* Write section and symbol directory of bfd abfd. */ @@ -705,6 +852,7 @@ _bfd_vms_write_gsd (bfd *abfd, int objtype ATTRIBUTE_UNUSED) char dummy_name[10]; char *sname; flagword new_flags, old_flags; + int abs_section_index = 0; #if VMS_DEBUG vms_debug (2, "vms_write_gsd (%p, %d)\n", abfd, objtype); @@ -730,6 +878,11 @@ _bfd_vms_write_gsd (bfd *abfd, int objtype ATTRIBUTE_UNUSED) vms_debug (3, "Section #%d %s, %d bytes\n", section->index, section->name, (int)section->size); #endif + /* Don't write out the VMS debug info section since it is in the + ETBT and EDBG sections in etir. */ + if (!strcmp (section->name, ".vmsdebug")) + goto done; + /* 13 bytes egsd, max 31 chars name -> should be 44 bytes. */ if (_bfd_vms_output_check (abfd, 64) < 0) { @@ -775,6 +928,11 @@ _bfd_vms_write_gsd (bfd *abfd, int objtype ATTRIBUTE_UNUSED) sname = EVAX_READONLY_NAME; else if ((*sname == 'l') && (strcmp (sname, "literal") == 0)) sname = EVAX_LITERAL_NAME; + else if ((*sname == 'l') && (strcmp (sname, "literals") == 0)) + { + sname = EVAX_LITERALS_NAME; + abs_section_index = section->index; + } else if ((*sname == 'c') && (strcmp (sname, "comm") == 0)) sname = EVAX_COMMON_NAME; else if ((*sname == 'l') && (strcmp (sname, "lcomm") == 0)) @@ -785,18 +943,34 @@ _bfd_vms_write_gsd (bfd *abfd, int objtype ATTRIBUTE_UNUSED) _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); + 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); + /* Modify them as directed. */ + if (section->flags & SEC_READONLY) + new_flags &= ~EGPS_S_V_WRT; + + new_flags |= vms_section_data (section)->vflags & 0xffff; + new_flags &= + ~((vms_section_data (section)->vflags >> EGPS_S_V_NO_SHIFT) & 0xffff); + +#if VMS_DEBUG + vms_debug (3, "sec flags %x\n", section->flags); + vms_debug (3, "new_flags %x, _raw_size %d\n", new_flags, section->size); +#endif + _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; +done: section = section->next; } @@ -822,9 +996,11 @@ _bfd_vms_write_gsd (bfd *abfd, int objtype ATTRIBUTE_UNUSED) 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. */ + if ((old_flags & BSF_GLOBAL) == 0 /* Not xdef... */ + && !bfd_is_und_section (symbol->section) /* and not xref... */ + && !((old_flags & BSF_SECTION_SYM) != 0 /* and not LIB$INITIALIZE. */ + && strcmp (symbol->section->name, "LIB$INITIALIZE") == 0)) + continue; /* 13 bytes egsd, max 64 chars name -> should be 77 bytes. */ if (_bfd_vms_output_check (abfd, 80) < 0) @@ -846,7 +1022,7 @@ _bfd_vms_write_gsd (bfd *abfd, int objtype ATTRIBUTE_UNUSED) if (old_flags & BSF_WEAK) new_flags |= EGSY_S_V_WEAK; - if (bfd_is_com_section (symbol->section)) + if (bfd_is_com_section (symbol->section)) /* .comm */ new_flags |= (EGSY_S_V_WEAK | EGSY_S_V_COMM); if (old_flags & BSF_FUNCTION) @@ -854,7 +1030,7 @@ _bfd_vms_write_gsd (bfd *abfd, int objtype ATTRIBUTE_UNUSED) new_flags |= EGSY_S_V_NORM; new_flags |= EGSY_S_V_REL; } - if (old_flags & (BSF_GLOBAL | BSF_WEAK)) + if (old_flags & BSF_GLOBAL) { new_flags |= EGSY_S_V_DEF; if (!bfd_is_abs_section (symbol->section)) @@ -862,7 +1038,7 @@ _bfd_vms_write_gsd (bfd *abfd, int objtype ATTRIBUTE_UNUSED) } _bfd_vms_output_short (abfd, new_flags); - if (old_flags & (BSF_GLOBAL | BSF_WEAK)) + if (old_flags & BSF_GLOBAL) { /* Symbol definition. */ uquad code_address = 0; @@ -871,10 +1047,19 @@ _bfd_vms_write_gsd (bfd *abfd, int objtype ATTRIBUTE_UNUSED) if ((old_flags & BSF_FUNCTION) && symbol->udata.p != NULL) { - code_address = ((asymbol *) (symbol->udata.p))->value; - ca_psindx = ((asymbol *) (symbol->udata.p))->section->index; + asymbol *sym; + + if (bfd_get_flavour (abfd) == bfd_target_evax_flavour) + sym = ((struct evax_private_udata_struct *)symbol->udata.p)->enbsym; + else + sym = (asymbol *)symbol->udata.p; + code_address = sym->value; + ca_psindx = sym->section->index; } - psindx = symbol->section->index; + if (bfd_is_abs_section (symbol->section)) + psindx = abs_section_index; + else + psindx = symbol->section->index; _bfd_vms_output_quad (abfd, symbol->value); _bfd_vms_output_quad (abfd, code_address); diff --git a/bfd/vms-hdr.c b/bfd/vms-hdr.c index 11e1af6..6ad84dd 100644 --- a/bfd/vms-hdr.c +++ b/bfd/vms-hdr.c @@ -1,14 +1,31 @@ /* vms-hdr.c -- BFD back-end for VMS/VAX (openVMS/VAX) and EVAX (openVMS/Alpha) files. Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2005, 2006, - 2007 Free Software Foundation, Inc. + 2007, 2008, 2009 Free Software Foundation, Inc. HDR record handling functions EMH record handling functions - and + EOM record handling functions EEOM record handling functions + IHD record handling functions + EIHD record handling functions + + ISD record handling functions + EISD record handling functions + + IHS record handling functions + EIHS record handling functions + + DBG record handling functions + EDBG record handling functions + + TBT record handling functions + ETBT record handling functions + + DST/DMT section handling functions + Written by Klaus K"ampf (kkaempf@rmi.de) This program is free software; you can redistribute it and/or modify @@ -39,6 +56,20 @@ #include <alloca.h> #endif +static struct module *new_module (bfd *); +static void parse_module + (bfd *, struct module *, unsigned char *, unsigned int); +static struct module *build_module_list (bfd *); +static bfd_boolean module_find_nearest_line + (bfd *, struct module *, bfd_vma, const char **, const char **, + unsigned int *); +static int vms_slurp_debug (bfd *); + +#define SET_MODULE_PARSED(m) \ + do { if ((m)->name == NULL) (m)->name = ""; } while (0) +#define IS_MODULE_PARSED(m) ((m)->name != NULL) + + /* Read & process emh record return 0 on success, -1 on error. */ @@ -85,15 +116,15 @@ _bfd_vms_slurp_hdr (bfd *abfd, int objtype) break; case MHD_S_C_LNM: - PRIV (hdr_data).hdr_c_lnm = _bfd_vms_save_sized_string (vms_rec, PRIV (rec_length - 2)); + PRIV (hdr_data).hdr_c_lnm = _bfd_vms_save_sized_string (vms_rec, PRIV (rec_size - 2)); break; case MHD_S_C_SRC: - PRIV (hdr_data).hdr_c_src = _bfd_vms_save_sized_string (vms_rec, PRIV (rec_length - 2)); + PRIV (hdr_data).hdr_c_src = _bfd_vms_save_sized_string (vms_rec, PRIV (rec_size - 2)); break; case MHD_S_C_TTL: - PRIV (hdr_data).hdr_c_ttl = _bfd_vms_save_sized_string (vms_rec, PRIV (rec_length - 2)); + PRIV (hdr_data).hdr_c_ttl = _bfd_vms_save_sized_string (vms_rec, PRIV (rec_size - 2)); break; case EMH_S_C_MHD + EVAX_OFFSET: @@ -110,15 +141,15 @@ _bfd_vms_slurp_hdr (bfd *abfd, int objtype) break; case EMH_S_C_LNM + EVAX_OFFSET: - PRIV (hdr_data).hdr_c_lnm = _bfd_vms_save_sized_string (vms_rec, PRIV (rec_length - 6)); + PRIV (hdr_data).hdr_c_lnm = _bfd_vms_save_sized_string (vms_rec, PRIV (rec_size - 6)); break; case EMH_S_C_SRC + EVAX_OFFSET: - PRIV (hdr_data).hdr_c_src = _bfd_vms_save_sized_string (vms_rec, PRIV (rec_length - 6)); + PRIV (hdr_data).hdr_c_src = _bfd_vms_save_sized_string (vms_rec, PRIV (rec_size - 6)); break; case EMH_S_C_TTL + EVAX_OFFSET: - PRIV (hdr_data).hdr_c_ttl = _bfd_vms_save_sized_string (vms_rec, PRIV (rec_length - 6)); + PRIV (hdr_data).hdr_c_ttl = _bfd_vms_save_sized_string (vms_rec, PRIV (rec_size - 6)); break; case MHD_S_C_CPR: @@ -189,6 +220,7 @@ _bfd_vms_write_hdr (bfd *abfd, int objtype) unsigned int symnum; int had_case = 0; int had_file = 0; + char version [256]; #if VMS_DEBUG vms_debug (2, "vms_write_hdr (%p)\n", abfd); @@ -213,27 +245,34 @@ _bfd_vms_write_hdr (bfd *abfd, int objtype) fptr = bfd_get_filename (abfd); fname = strdup (fptr); + + /* Strip VMS path. */ fout = strrchr (fname, ']'); - if (fout == 0) + if (fout == NULL) fout = strchr (fname, ':'); - if (fout != 0) + if (fout != NULL) fout++; else fout = fname; + /* Strip UNIX path. */ + fptr = strrchr (fout, '/'); + if (fptr != NULL) + fout = fptr + 1; + /* Strip .obj suffix. */ - fptr = strrchr (fname, '.'); - if ((fptr != 0) - && (strcasecmp (fptr, ".OBJ") == 0)) + fptr = strrchr (fout, '.'); + if (fptr != 0 && strcasecmp (fptr, ".OBJ") == 0) *fptr = 0; + /* Convert to upper case and truncate at 31 characters. + (VMS object file format restricts module name length to 31). */ fptr = fout; while (*fptr != 0) { *fptr = TOUPPER (*fptr); fptr++; - if ((*fptr == ';') - || ((fptr - fout) > 31)) + if (*fptr == ';' || (fptr - fout) >= 31) *fptr = 0; } _bfd_vms_output_counted (abfd, fout); @@ -243,13 +282,14 @@ _bfd_vms_write_hdr (bfd *abfd, int objtype) _bfd_vms_output_counted (abfd, "NONAME"); _bfd_vms_output_counted (abfd, BFD_VERSION_STRING); - _bfd_vms_output_dump (abfd, get_vms_time_string (), 17); - _bfd_vms_output_fill (abfd, 0, 17); + _bfd_vms_output_dump (abfd, get_vms_time_string (), EMH_DATE_LENGTH); + _bfd_vms_output_fill (abfd, 0, EMH_DATE_LENGTH); _bfd_vms_output_flush (abfd); /* LMN. */ _bfd_vms_output_begin (abfd, EOBJ_S_C_EMH, EMH_S_C_LNM); - _bfd_vms_output_dump (abfd, (unsigned char *) STRING_COMMA_LEN ("GAS proGIS")); + snprintf (version, sizeof (version), "GAS BFD v%s", BFD_VERSION_STRING); + _bfd_vms_output_dump (abfd, (unsigned char *)version, strlen (version)); _bfd_vms_output_flush (abfd); /* SRC. */ @@ -320,10 +360,10 @@ _bfd_vms_slurp_eom (bfd *abfd, int objtype) } else { - PRIV (eom_data).eom_l_total_lps = bfd_getl32 (vms_rec + 4); - PRIV (eom_data).eom_b_comcod = *(vms_rec + 8); - - if (PRIV (eom_data).eom_b_comcod > 1) + PRIV (eom_data).eom_l_total_lps + = bfd_getl32 (vms_rec + EEOM_S_L_TOTAL_LPS); + PRIV (eom_data).eom_w_comcod = bfd_getl16 (vms_rec + EEOM_S_W_COMCOD); + if (PRIV (eom_data).eom_w_comcod > 1) { (*_bfd_error_handler) (_("Object module NOT error-free !\n")); bfd_set_error (bfd_error_bad_value); @@ -333,9 +373,11 @@ _bfd_vms_slurp_eom (bfd *abfd, int objtype) if (PRIV (rec_size) > 10) { PRIV (eom_data).eom_has_transfer = TRUE; - PRIV (eom_data).eom_b_tfrflg = *(vms_rec + 9); - PRIV (eom_data).eom_l_psindx = bfd_getl32 (vms_rec + 12); - PRIV (eom_data).eom_l_tfradr = bfd_getl32 (vms_rec + 16); + PRIV (eom_data).eom_b_tfrflg = vms_rec[EEOM_S_B_TFRFLG]; + PRIV (eom_data).eom_l_psindx + = bfd_getl32 (vms_rec + EEOM_S_L_PSINDX); + PRIV (eom_data).eom_l_tfradr + = bfd_getl32 (vms_rec + EEOM_S_L_TFRADR); abfd->start_address = PRIV (eom_data).eom_l_tfradr; } @@ -377,3 +419,1001 @@ _bfd_vms_write_eom (bfd *abfd, int objtype) _bfd_vms_output_end (abfd); return 0; } + +/* Read & process IHD/EIHD record. + Return 0 on success, -1 on error */ +int +_bfd_vms_slurp_ihd (bfd *abfd, unsigned int *isd_offset, + unsigned int *ihs_offset) +{ + unsigned int imgtype, size; + bfd_vma symvva; + +#if VMS_DEBUG + vms_debug (8, "_bfd_vms_slurp_ihd\n"); +#endif + + size = bfd_getl32 (PRIV (vms_rec) + EIHD_S_L_SIZE); + imgtype = bfd_getl32 (PRIV (vms_rec) + EIHD_S_L_IMGTYPE); + + if (imgtype == EIHD_S_K_EXE) + abfd->flags |= EXEC_P; + + symvva = bfd_getl64 (PRIV (vms_rec) + EIHD_S_Q_SYMVVA); + if (symvva != 0) + { + PRIV (symvva) = symvva; + abfd->flags |= DYNAMIC; + } + + *isd_offset = bfd_getl32 (PRIV (vms_rec) + EIHD_S_L_ISDOFF); + *ihs_offset = bfd_getl32 (PRIV (vms_rec) + EIHD_S_L_SYMDBGOFF); + +#if VMS_DEBUG + vms_debug (4, "EIHD record size %d imgtype %d symvva 0x%llx isd %d ihs %d\n", + size, imgtype, symvva, *isd_offset, *ihs_offset); +#endif + + return 0; +} + +/* Read & process ISD/EISD record + return 0 on success, -1 on error */ + +int +_bfd_vms_slurp_isd (bfd *abfd, unsigned int offset) +{ + int section_count = 0; + unsigned char *p; + unsigned int rec_size; + +#if VMS_DEBUG + vms_debug (8, "_bfd_vms_slurp_isd\n"); +#endif + + for (p = PRIV (vms_rec) + offset; + (rec_size = bfd_getl32 (p + EISD_S_L_EISDSIZE)) != 0; + p += rec_size) + { + unsigned long long vaddr = bfd_getl64 (p + EISD_S_Q_VIR_ADDR); + unsigned int size = bfd_getl32 (p + EISD_S_L_SECSIZE); + unsigned int flags = bfd_getl32 (p + EISD_S_L_FLAGS); + unsigned int vbn = bfd_getl32 (p + EISD_S_L_VBN); + char *name = NULL; + asection *section; + flagword bfd_flags; + +#if VMS_DEBUG + vms_debug (4, "EISD record at 0x%x size 0x%x addr 0x%x bfd_flags 0x%x block %d\n", + p - PRIV (vms_rec), size, vaddr, flags, vbn); +#endif + + /* VMS combines psects from .obj files into isects in the .exe. This + process doesn't preserve enough information to reliably determine + what's in each section without examining the data. This is + especially true of DWARF debug sections. */ + bfd_flags = SEC_ALLOC; + + if (flags & EISD_S_M_EXE) + bfd_flags |= SEC_CODE | SEC_HAS_CONTENTS | SEC_LOAD; + + if (flags & EISD_S_M_NONSHRADR) + bfd_flags |= SEC_DATA | SEC_HAS_CONTENTS | SEC_LOAD; + + if (!(flags & EISD_S_M_WRT)) + bfd_flags |= SEC_READONLY; + + if (flags & EISD_S_M_DZRO) + bfd_flags |= SEC_DATA; + + if (flags & EISD_S_M_FIXUPVEC) + bfd_flags |= SEC_DATA | SEC_HAS_CONTENTS | SEC_LOAD; + + if (flags & EISD_S_M_CRF) + bfd_flags |= SEC_HAS_CONTENTS | SEC_LOAD; + + if (flags & EISD_S_M_GBL) + { + name = _bfd_vms_save_counted_string (p + EISD_S_T_GBLNAM); + bfd_flags |= SEC_COFF_SHARED_LIBRARY; + bfd_flags &= ~(SEC_ALLOC | SEC_LOAD); + } + else + { + name = (char*) bfd_alloc (abfd, 32); + sprintf (name, "$LOCAL_%03d$", section_count++); + } + + section = bfd_make_section (abfd, name); + + if (!section) + return -1; + + section->filepos = vbn ? VMS_BLOCK_SIZE * (vbn - 1) : (unsigned int)-1; + section->size = size; + section->vma = vaddr; + + if (!bfd_set_section_flags (abfd, section, bfd_flags)) + return -1; + } + + return 0; +} + +/* Read & process IHS/EIHS record + return 0 on success, -1 on error */ +int +_bfd_vms_slurp_ihs (bfd *abfd, unsigned int offset) +{ + unsigned char *p = PRIV (vms_rec) + offset; + unsigned int gstvbn = bfd_getl32 (p + EIHS_S_L_GSTVBN); + unsigned int gstsize ATTRIBUTE_UNUSED = bfd_getl32 (p + EIHS_S_L_GSTSIZE); + unsigned int dstvbn = bfd_getl32 (p + EIHS_S_L_DSTVBN); + unsigned int dstsize = bfd_getl32 (p + EIHS_S_L_DSTSIZE); + unsigned int dmtvbn = bfd_getl32 (p + EIHS_S_L_DMTVBN); + unsigned int dmtbytes = bfd_getl32 (p + EIHS_S_L_DMTBYTES); + asection *section; + +#if VMS_DEBUG + vms_debug (8, "_bfd_vms_slurp_ihs\n"); + vms_debug (4, "EIHS record gstvbn %d gstsize %d dstvbn %d dstsize %d dmtvbn %d dmtbytes %d\n", + gstvbn, gstsize, dstvbn, dstsize, dmtvbn, dmtbytes); +#endif + + if (dstvbn) + { + flagword bfd_flags = SEC_HAS_CONTENTS | SEC_DEBUGGING; + + section = bfd_make_section (abfd, "$DST$"); + if (!section) + return -1; + + section->size = dstsize; + section->filepos = VMS_BLOCK_SIZE * (dstvbn - 1); + + if (!bfd_set_section_flags (abfd, section, bfd_flags)) + return -1; + + PRIV (dst_section) = section; + abfd->flags |= (HAS_DEBUG | HAS_LINENO); + } + + if (dmtvbn) + { + flagword bfd_flags = SEC_HAS_CONTENTS | SEC_DEBUGGING; + + section = bfd_make_section (abfd, "$DMT$"); + if (!section) + return -1; + + section->size = dmtbytes; + section->filepos = VMS_BLOCK_SIZE * (dmtvbn - 1); + + if (!bfd_set_section_flags (abfd, section, bfd_flags)) + return -1; + } + + if (gstvbn) + { + flagword bfd_flags = SEC_HAS_CONTENTS; + + section = bfd_make_section (abfd, "$GST$"); + if (!section) + return -1; + + if (bfd_seek (abfd, VMS_BLOCK_SIZE * (gstvbn - 1), SEEK_SET)) + { + bfd_set_error (bfd_error_file_truncated); + return -1; + } + + if (_bfd_vms_slurp_object_records (abfd) != 0) + return -1; + + section->filepos = VMS_BLOCK_SIZE * (gstvbn - 1); + section->size = bfd_tell (abfd) - section->filepos; + + if (!bfd_set_section_flags (abfd, section, bfd_flags)) + return -1; + + abfd->flags |= HAS_SYMS; + } + + return 0; +} + +/* Build a new module for the specified BFD. */ + +static struct module * +new_module (bfd *abfd) +{ + struct module *module + = (struct module *) bfd_zalloc (abfd, sizeof (struct module)); + module->file_table_count = 16; /* Arbitrary. */ + module->file_table + = bfd_malloc (module->file_table_count * sizeof (struct fileinfo)); + return module; +} + +/* Parse debug info for a module and internalize it. */ + +static void +parse_module (bfd *abfd, struct module *module, unsigned char *ptr, + unsigned int length) +{ + unsigned char *maxptr = ptr + length, *src_ptr, *pcl_ptr; + unsigned int prev_linum = 0, curr_linenum = 0; + bfd_vma prev_pc = 0, curr_pc = 0; + struct srecinfo *curr_srec, *srec; + struct lineinfo *curr_line, *line; + struct funcinfo *funcinfo; + + /* Initialize tables with zero element. */ + curr_srec = (struct srecinfo *) bfd_zalloc (abfd, sizeof (struct srecinfo)); + module->srec_table = curr_srec; + + curr_line = (struct lineinfo *) bfd_zalloc (abfd, sizeof (struct lineinfo)); + module->line_table = curr_line; + + while (ptr < maxptr) + { + /* The first byte is not counted in the recorded length. */ + int rec_length = bfd_getl16 (ptr) + 1; + int rec_type = bfd_getl16 (ptr + 2); + +#if VMS_DEBUG + _bfd_vms_debug (2, "DST record: length %d, type %d\n", + rec_length, rec_type); +#endif + + switch (rec_type) + { + case DST_S_C_MODBEG: + module->name + = _bfd_vms_save_counted_string (ptr + DST_S_B_MODBEG_NAME); + + curr_pc = 0; + prev_pc = 0; + curr_linenum = 0; + prev_linum = 0; + +#if VMS_DEBUG + _bfd_vms_debug (3, "module: %s\n", module->name); +#endif + break; + + case DST_S_C_MODEND: +#if VMS_DEBUG + _bfd_vms_debug (3, "end module\n"); +#endif + break; + + case DST_S_C_RTNBEG: + funcinfo = (struct funcinfo *) + bfd_zalloc (abfd, sizeof (struct funcinfo)); + funcinfo->name + = _bfd_vms_save_counted_string (ptr + DST_S_B_RTNBEG_NAME); + funcinfo->low = bfd_getl32 (ptr + DST_S_L_RTNBEG_ADDRESS); + funcinfo->next = module->func_table; + module->func_table = funcinfo; + +#if VMS_DEBUG + _bfd_vms_debug (3, "routine: %s at 0x%x\n", + funcinfo->name, funcinfo->low); +#endif + break; + + case DST_S_C_RTNEND: + module->func_table->high = module->func_table->low + + bfd_getl32 (ptr + DST_S_L_RTNEND_SIZE) - 1; + + if (module->func_table->high > module->high) + module->high = module->func_table->high; + +#if VMS_DEBUG + _bfd_vms_debug (3, "end routine\n"); +#endif + break; + + case DST_S_C_PROLOG: +#if VMS_DEBUG + _bfd_vms_debug (3, "prologue\n"); +#endif + break; + + case DST_S_C_EPILOG: +#if VMS_DEBUG + _bfd_vms_debug (3, "epilog\n"); +#endif + break; + + case DST_S_C_BLKBEG: +#if VMS_DEBUG + _bfd_vms_debug (3, "block\n"); +#endif + break; + + case DST_S_C_BLKEND: +#if VMS_DEBUG + _bfd_vms_debug (3, "end block\n"); +#endif + break; + + case DST_S_C_SOURCE: + src_ptr = ptr + DST_S_C_SOURCE_HEADER_SIZE; + +#if VMS_DEBUG + _bfd_vms_debug (3, "source info\n"); +#endif + + while (src_ptr < ptr + rec_length) + { + int cmd = src_ptr[0], cmd_length, data; + + switch (cmd) + { + case DST_S_C_SRC_DECLFILE: + { + unsigned int fileid + = bfd_getl16 (src_ptr + DST_S_W_SRC_DF_FILEID); + char *filename + = _bfd_vms_save_counted_string (src_ptr + + DST_S_B_SRC_DF_FILENAME); + + while (fileid >= module->file_table_count) + { + module->file_table_count *= 2; + module->file_table + = bfd_realloc (module->file_table, + module->file_table_count + * sizeof (struct fileinfo)); + } + + module->file_table [fileid].name = filename; + module->file_table [fileid].srec = 1; + cmd_length = src_ptr[DST_S_B_SRC_DF_LENGTH] + 2; +#if VMS_DEBUG + _bfd_vms_debug (4, "DST_S_C_SRC_DECLFILE: %d, %s\n", + fileid, + module->file_table [fileid].name); +#endif + } + break; + + case DST_S_C_SRC_DEFLINES_B: + /* Perform the association and set the next higher index + to the limit. */ + data = src_ptr[DST_S_B_SRC_UNSBYTE]; + srec = (struct srecinfo *) + bfd_zalloc (abfd, sizeof (struct srecinfo)); + srec->line = curr_srec->line + data; + srec->srec = curr_srec->srec + data; + srec->sfile = curr_srec->sfile; + curr_srec->next = srec; + curr_srec = srec; + cmd_length = 2; +#if VMS_DEBUG + _bfd_vms_debug (4, "DST_S_C_SRC_DEFLINES_B: %d\n", data); +#endif + break; + + case DST_S_C_SRC_DEFLINES_W: + /* Perform the association and set the next higher index + to the limit. */ + data = bfd_getl16 (src_ptr + DST_S_W_SRC_UNSWORD); + srec = (struct srecinfo *) + bfd_zalloc (abfd, sizeof (struct srecinfo)); + srec->line = curr_srec->line + data; + srec->srec = curr_srec->srec + data, + srec->sfile = curr_srec->sfile; + curr_srec->next = srec; + curr_srec = srec; + cmd_length = 3; +#if VMS_DEBUG + _bfd_vms_debug (4, "DST_S_C_SRC_DEFLINES_W: %d\n", data); +#endif + break; + + case DST_S_C_SRC_INCRLNUM_B: + data = src_ptr[DST_S_B_SRC_UNSBYTE]; + curr_srec->line += data; + cmd_length = 2; +#if VMS_DEBUG + _bfd_vms_debug (4, "DST_S_C_SRC_INCRLNUM_B: %d\n", data); +#endif + break; + + case DST_S_C_SRC_SETFILE: + data = bfd_getl16 (src_ptr + DST_S_W_SRC_UNSWORD); + curr_srec->sfile = data; + curr_srec->srec = module->file_table[data].srec; + cmd_length = 3; +#if VMS_DEBUG + _bfd_vms_debug (4, "DST_S_C_SRC_SETFILE: %d\n", data); +#endif + break; + + case DST_S_C_SRC_SETLNUM_L: + data = bfd_getl32 (src_ptr + DST_S_L_SRC_UNSLONG); + curr_srec->line = data; + cmd_length = 5; +#if VMS_DEBUG + _bfd_vms_debug (4, "DST_S_C_SRC_SETLNUM_L: %d\n", data); +#endif + break; + + case DST_S_C_SRC_SETLNUM_W: + data = bfd_getl16 (src_ptr + DST_S_W_SRC_UNSWORD); + curr_srec->line = data; + cmd_length = 3; +#if VMS_DEBUG + _bfd_vms_debug (4, "DST_S_C_SRC_SETLNUM_W: %d\n", data); +#endif + break; + + case DST_S_C_SRC_SETREC_L: + data = bfd_getl32 (src_ptr + DST_S_L_SRC_UNSLONG); + curr_srec->srec = data; + module->file_table[curr_srec->sfile].srec = data; + cmd_length = 5; +#if VMS_DEBUG + _bfd_vms_debug (4, "DST_S_C_SRC_SETREC_L: %d\n", data); +#endif + break; + + case DST_S_C_SRC_SETREC_W: + data = bfd_getl16 (src_ptr + DST_S_W_SRC_UNSWORD); + curr_srec->srec = data; + module->file_table[curr_srec->sfile].srec = data; + cmd_length = 3; +#if VMS_DEBUG + _bfd_vms_debug (4, "DST_S_C_SRC_SETREC_W: %d\n", data); +#endif + break; + + case DST_S_C_SRC_FORMFEED: + cmd_length = 1; +#if VMS_DEBUG + _bfd_vms_debug (4, "DST_S_C_SRC_FORMFEED\n"); +#endif + break; + + default: + (*_bfd_error_handler) (_("unknown source command %d"), + cmd); + cmd_length = 2; + break; + } + + src_ptr += cmd_length; + } + break; + + case DST_S_C_LINE_NUM: + pcl_ptr = ptr + DST_S_C_LINE_NUM_HEADER_SIZE; + +#if VMS_DEBUG + _bfd_vms_debug (3, "line info\n"); +#endif + + while (pcl_ptr < ptr + rec_length) + { + /* The command byte is signed so we must sign-extend it. */ + int cmd = ((signed char *)pcl_ptr)[0], cmd_length, data; + + switch (cmd) + { + case DST_S_C_DELTA_PC_W: + data = bfd_getl16 (pcl_ptr + DST_S_W_PCLINE_UNSWORD); + curr_pc += data; + curr_linenum += 1; + cmd_length = 3; +#if VMS_DEBUG + _bfd_vms_debug (4, "DST_S_C_DELTA_PC_W: %d\n", data); +#endif + break; + + case DST_S_C_DELTA_PC_L: + data = bfd_getl32 (pcl_ptr + DST_S_L_PCLINE_UNSLONG); + curr_pc += data; + curr_linenum += 1; + cmd_length = 5; +#if VMS_DEBUG + _bfd_vms_debug (4, "DST_S_C_DELTA_PC_L: %d\n", data); +#endif + break; + + case DST_S_C_INCR_LINUM: + data = pcl_ptr[DST_S_B_PCLINE_UNSBYTE]; + curr_linenum += data; + cmd_length = 2; +#if VMS_DEBUG + _bfd_vms_debug (4, "DST_S_C_INCR_LINUM: %d\n", data); +#endif + break; + + case DST_S_C_INCR_LINUM_W: + data = bfd_getl16 (pcl_ptr + DST_S_W_PCLINE_UNSWORD); + curr_linenum += data; + cmd_length = 3; +#if VMS_DEBUG + _bfd_vms_debug (4, "DST_S_C_INCR_LINUM_W: %d\n", data); +#endif + break; + + case DST_S_C_INCR_LINUM_L: + data = bfd_getl32 (pcl_ptr + DST_S_L_PCLINE_UNSLONG); + curr_linenum += data; + cmd_length = 5; +#if VMS_DEBUG + _bfd_vms_debug (4, "DST_S_C_INCR_LINUM_L: %d\n", data); +#endif + break; + + case DST_S_C_SET_LINUM_INCR: + (*_bfd_error_handler) + (_("DST_S_C_SET_LINUM_INCR not implemented")); + cmd_length = 2; + break; + + case DST_S_C_SET_LINUM_INCR_W: + (*_bfd_error_handler) + (_("DST_S_C_SET_LINUM_INCR_W not implemented")); + cmd_length = 3; + break; + + case DST_S_C_RESET_LINUM_INCR: + (*_bfd_error_handler) + (_("DST_S_C_RESET_LINUM_INCR not implemented")); + cmd_length = 1; + break; + + case DST_S_C_BEG_STMT_MODE: + (*_bfd_error_handler) + (_("DST_S_C_BEG_STMT_MODE not implemented")); + cmd_length = 1; + break; + + case DST_S_C_END_STMT_MODE: + (*_bfd_error_handler) + (_("DST_S_C_END_STMT_MODE not implemented")); + cmd_length = 1; + break; + + case DST_S_C_SET_LINUM_B: + data = pcl_ptr[DST_S_B_PCLINE_UNSBYTE]; + curr_linenum = data; + cmd_length = 2; +#if VMS_DEBUG + _bfd_vms_debug (4, "DST_S_C_SET_LINUM_B: %d\n", data); +#endif + break; + + case DST_S_C_SET_LINE_NUM: + data = bfd_getl16 (pcl_ptr + DST_S_W_PCLINE_UNSWORD); + curr_linenum = data; + cmd_length = 3; +#if VMS_DEBUG + _bfd_vms_debug (4, "DST_S_C_SET_LINE_NUM: %d\n", data); +#endif + break; + + case DST_S_C_SET_LINUM_L: + data = bfd_getl32 (pcl_ptr + DST_S_L_PCLINE_UNSLONG); + curr_linenum = data; + cmd_length = 5; +#if VMS_DEBUG + _bfd_vms_debug (4, "DST_S_C_SET_LINUM_L: %d\n", data); +#endif + break; + + case DST_S_C_SET_PC: + (*_bfd_error_handler) + (_("DST_S_C_SET_PC not implemented")); + cmd_length = 2; + break; + + case DST_S_C_SET_PC_W: + (*_bfd_error_handler) + (_("DST_S_C_SET_PC_W not implemented")); + cmd_length = 3; + break; + + case DST_S_C_SET_PC_L: + (*_bfd_error_handler) + (_("DST_S_C_SET_PC_L not implemented")); + cmd_length = 5; + break; + + case DST_S_C_SET_STMTNUM: + (*_bfd_error_handler) + (_("DST_S_C_SET_STMTNUM not implemented")); + cmd_length = 2; + break; + + case DST_S_C_TERM: + data = pcl_ptr[DST_S_B_PCLINE_UNSBYTE]; + curr_pc += data; + cmd_length = 2; +#if VMS_DEBUG + _bfd_vms_debug (4, "DST_S_C_TERM: %d\n", data); +#endif + break; + + case DST_S_C_TERM_W: + data = bfd_getl16 (pcl_ptr + DST_S_W_PCLINE_UNSWORD); + curr_pc += data; + cmd_length = 3; +#if VMS_DEBUG + _bfd_vms_debug (4, "DST_S_C_TERM_W: %d\n", data); +#endif + break; + + case DST_S_C_TERM_L: + data = bfd_getl32 (pcl_ptr + DST_S_L_PCLINE_UNSLONG); + curr_pc += data; + cmd_length = 5; +#if VMS_DEBUG + _bfd_vms_debug (4, "DST_S_C_TERM_L: %d\n", data); +#endif + break; + + case DST_S_C_SET_ABS_PC: + data = bfd_getl32 (pcl_ptr + DST_S_L_PCLINE_UNSLONG); + curr_pc = data; + cmd_length = 5; +#if VMS_DEBUG + _bfd_vms_debug (4, "DST_S_C_SET_ABS_PC: 0x%x\n", data); +#endif + break; + + default: + if (cmd <= 0) + { + curr_pc -= cmd; + curr_linenum += 1; + cmd_length = 1; +#if VMS_DEBUG + _bfd_vms_debug (4, "bump pc to 0x%llx and line to %d\n", + curr_pc, curr_linenum); +#endif + } + else + { + (*_bfd_error_handler) (_("unknown line command %d"), + cmd); + cmd_length = 2; + } + break; + } + + if ((curr_linenum != prev_linum && curr_pc != prev_pc) + || cmd <= 0 + || cmd == DST_S_C_DELTA_PC_L + || cmd == DST_S_C_DELTA_PC_W) + { + line = (struct lineinfo *) + bfd_zalloc (abfd, sizeof (struct lineinfo)); + line->address = curr_pc; + line->line = curr_linenum; + + curr_line->next = line; + curr_line = line; + + prev_linum = curr_linenum; + prev_pc = curr_pc; +#if VMS_DEBUG + _bfd_vms_debug (4, "-> correlate pc 0x%llx with line %d\n", + curr_pc, curr_linenum); +#endif + } + + pcl_ptr += cmd_length; + } + break; + + case 0x17: /* Undocumented type used by DEC C to declare equates. */ +#if VMS_DEBUG + _bfd_vms_debug (3, "undocumented type 0x17\n"); +#endif + break; + + default: +#if VMS_DEBUG + _bfd_vms_debug (3, "ignoring record\n"); +#endif + break; + + } + + ptr += rec_length; + } + + /* Finalize tables with EOL marker. */ + srec = (struct srecinfo *) bfd_zalloc (abfd, sizeof (struct srecinfo)); + srec->line = (unsigned int) -1; + srec->srec = (unsigned int) -1; + curr_srec->next = srec; + + line = (struct lineinfo *) bfd_zalloc (abfd, sizeof (struct lineinfo)); + line->line = (unsigned int) -1; + line->address = (bfd_vma) -1; + curr_line->next = line; + + /* Advertise that this module has been parsed. This is needed + because parsing can be either performed at module creation + or deferred until debug info is consumed. */ + SET_MODULE_PARSED (module); +} + +/* Build the list of modules for the specified BFD. */ + +static struct module * +build_module_list (bfd *abfd) +{ + struct module *module, *list = NULL; + asection *dmt; + + if ((dmt = bfd_get_section_by_name (abfd, "$DMT$"))) + { + /* We have a DMT section so this must be an image. Parse the + section and build the list of modules. This is sufficient + since we can compute the start address and the end address + of every module from the section contents. */ + bfd_size_type size = bfd_get_section_size (dmt); + unsigned char *ptr, *end; + + ptr = (unsigned char *) bfd_alloc (abfd, size); + if (! ptr) + return NULL; + + if (! bfd_get_section_contents (abfd, dmt, ptr, 0, size)) + return NULL; + +#if VMS_DEBUG + _bfd_vms_debug (2, "DMT\n"); +#endif + + end = ptr + size; + + while (ptr < end) + { + /* Each header declares a module with its start offset and size + of debug info in the DST section, as well as the count of + program sections (i.e. address spans) it contains. */ + int modbeg = bfd_getl32 (ptr + DBG_S_L_DMT_MODBEG); + int size = bfd_getl32 (ptr + DBG_S_L_DST_SIZE); + int count = bfd_getl16 (ptr + DBG_S_W_DMT_PSECT_COUNT); + ptr += DBG_S_C_DMT_HEADER_SIZE; + +#if VMS_DEBUG + _bfd_vms_debug (3, "module: modbeg = %d, size = %d, count = %d\n", + modbeg, size, count); +#endif + + /* We create a 'module' structure for each program section since + we only support contiguous addresses in a 'module' structure. + As a consequence, the actual debug info in the DST section is + shared and can be parsed multiple times; that doesn't seem to + cause problems in practice. */ + while (count-- > 0) + { + int start = bfd_getl32 (ptr + DBG_S_L_DMT_PSECT_START); + int length = bfd_getl32 (ptr + DBG_S_L_DMT_PSECT_LENGTH); + module = new_module (abfd); + module->modbeg = modbeg; + module->size = size; + module->low = start; + module->high = start + length; + module->next = list; + list = module; + ptr += DBG_S_C_DMT_PSECT_SIZE; + +#if VMS_DEBUG + _bfd_vms_debug (4, "section: start = 0x%x, length = %d\n", + start, length); +#endif + } + } + } + else + { + /* We don't have a DMT section so this must be an object. Parse + the module right now in order to compute its start address and + end address. */ + module = new_module (abfd); + parse_module (abfd, module, PRIV (dst_section)->contents, + PRIV (dst_ptr_end) - PRIV (dst_section)->contents); + list = module; + } + + return list; +} + +/* Calculate and return the name of the source file and the line nearest + to the wanted location in the specified module. */ + +static bfd_boolean +module_find_nearest_line (bfd *abfd, struct module *module, bfd_vma addr, + const char **file, const char **func, + unsigned int *line) +{ + struct funcinfo *funcinfo; + struct lineinfo *lineinfo; + struct srecinfo *srecinfo; + bfd_boolean ret = FALSE; + + /* Parse this module if that was not done at module creation. */ + if (! IS_MODULE_PARSED (module)) + { + unsigned int size = module->size; + unsigned int modbeg = PRIV (dst_section)->filepos + module->modbeg; + unsigned char *buffer = (unsigned char *) bfd_malloc (module->size); + + if (bfd_seek (abfd, modbeg, SEEK_SET) != 0 + || bfd_bread (buffer, size, abfd) != size) + { + bfd_set_error (bfd_error_no_debug_section); + return FALSE; + } + + parse_module (abfd, module, buffer, size); + free (buffer); + } + + /* Find out the function (if any) that contains the address. */ + for (funcinfo = module->func_table; funcinfo; funcinfo = funcinfo->next) + if (addr >= funcinfo->low && addr <= funcinfo->high) + { + *func = funcinfo->name; + ret = TRUE; + break; + } + + /* Find out the source file and the line nearest to the address. */ + for (lineinfo = module->line_table; lineinfo; lineinfo = lineinfo->next) + if (lineinfo->next && addr < lineinfo->next->address) + { + for (srecinfo = module->srec_table; srecinfo; srecinfo = srecinfo->next) + if (srecinfo->next && lineinfo->line < srecinfo->next->line) + { + if (srecinfo->sfile > 0) + { + *file = module->file_table[srecinfo->sfile].name; + *line = srecinfo->srec + lineinfo->line - srecinfo->line; + } + else + { + *file = module->name; + *line = lineinfo->line; + } + return TRUE; + } + + break; + } + + return ret; +} + +/* Provided a BFD, a section and an offset into the section, calculate and + return the name of the source file and the line nearest to the wanted + location. */ + +bfd_boolean +_bfd_vms_find_nearest_dst_line (bfd *abfd, asection *section, + asymbol **symbols ATTRIBUTE_UNUSED, + bfd_vma offset, const char **file, + const char **func, unsigned int *line) +{ + struct module *module; + + /* What address are we looking for? */ + bfd_vma addr = section->vma + offset; + + *file = NULL; + *func = NULL; + *line = 0; + + if (PRIV (dst_section) == NULL) + return FALSE; + + if (PRIV (modules) == NULL) + { + PRIV (modules) = build_module_list (abfd); + if (PRIV (modules) == NULL) + return FALSE; + } + + for (module = PRIV (modules); module; module = module->next) + if (addr >= module->low && addr <= module->high) + return module_find_nearest_line (abfd, module, addr, file, func, line); + + return FALSE; +} + +/* Process EDBG/ETBT record. + Return 0 on success, -1 on error */ + +static int +vms_slurp_debug (bfd *abfd) +{ + if (PRIV (dst_section) == NULL) + { + /* We have no way to find out beforehand how much debug info there + is in an object file, so pick an initial amount and grow it as + needed later. */ + flagword flags = SEC_HAS_CONTENTS | SEC_DEBUGGING | SEC_RELOC; + asection *section = bfd_make_section (abfd, "$DST$"); + if (!section) + return -1; + section->size = 1024; + if (!bfd_set_section_flags (abfd, section, flags)) + return -1; + section->contents = ((unsigned char *) + bfd_zmalloc (section->size)); + if (section->contents == NULL) + return -1; + section->filepos = (unsigned int)-1; + PRIV (dst_section) = section; + } + + PRIV (image_section) = PRIV (dst_section); + PRIV (image_ptr) = PRIV (dst_section)->contents; + + return _bfd_vms_slurp_tir (abfd, EOBJ_S_C_ETIR); +} + +/* Process DBG/EDBG record. + Return 0 on success, -1 on error. */ + +int +_bfd_vms_slurp_dbg (bfd *abfd, int objtype ATTRIBUTE_UNUSED) +{ +#if VMS_DEBUG + _bfd_vms_debug (2, "DBG/EDBG\n"); +#endif + + abfd->flags |= (HAS_DEBUG | HAS_LINENO); + + return vms_slurp_debug (abfd); +} + +/* Process TBT/ETBT record. + Return 0 on success, -1 on error. */ + +int +_bfd_vms_slurp_tbt (bfd *abfd, int objtype ATTRIBUTE_UNUSED) +{ +#if VMS_DEBUG + _bfd_vms_debug (2, "TBT/ETBT\n"); +#endif + + abfd->flags |= HAS_LINENO; + + return vms_slurp_debug (abfd); +} + +/* Write DBG/EDBG record. */ + +int +_bfd_vms_write_dbg (bfd *abfd ATTRIBUTE_UNUSED, int objtype ATTRIBUTE_UNUSED) +{ +#if VMS_DEBUG + _bfd_vms_debug (2, "vms_write_dbg (%p, objtype)\n", abfd, objtype); +#endif + + return 0; +} + +/* Write TBT/ETBT record. */ + +int +_bfd_vms_write_tbt (bfd *abfd ATTRIBUTE_UNUSED, int objtype ATTRIBUTE_UNUSED) +{ +#if VMS_DEBUG + _bfd_vms_debug (2, "vms_write_tbt (%p, %d)\n", abfd, objtype); +#endif + + return 0; +} diff --git a/bfd/vms-misc.c b/bfd/vms-misc.c index 9d0ffdb..2181658 100644 --- a/bfd/vms-misc.c +++ b/bfd/vms-misc.c @@ -1,7 +1,9 @@ -/* vms-misc.c -- Miscellaneous functions for VAX (openVMS/VAX) and +/* vms-misc.c -- BFD back-end for VMS/VAX (openVMS/VAX) and EVAX (openVMS/Alpha) files. Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, - 2007, 2008 Free Software Foundation, Inc. + 2007, 2008, 2009 Free Software Foundation, Inc. + + Miscellaneous functions. Written by Klaus K"ampf (kkaempf@rmi.de) @@ -30,22 +32,29 @@ #include "libbfd.h" #include "vms.h" - + +#define MIN(a,b) ((a) < (b) ? (a) : (b)) + +static int hash_string PARAMS ((const char *)); +static asymbol *new_symbol PARAMS ((bfd *, char *)); +static void maybe_adjust_record_pointer_for_object PARAMS ((bfd *)); +static int vms_get_remaining_object_record PARAMS ((bfd *, int )); +static int vms_get_remaining_image_record PARAMS ((bfd *, int )); + #if VMS_DEBUG /* Debug functions. */ -/* Debug function for all vms extensions - evaluates environment variable VMS_DEBUG for a - numerical value on the first call - all error levels below this value are printed +/* Debug function for all vms extensions evaluates environment + variable VMS_DEBUG for a numerical value on the first call all + error levels below this value are printed: - levels: + Levels: 1 toplevel bfd calls (functions from the bfd vector) 2 functions called by bfd calls ... 9 almost everything - level is also indentation level. Indentation is performed + Level is also indentation level. Indentation is performed if level > 0. */ void @@ -167,22 +176,23 @@ _bfd_vms_hash_newfunc (struct bfd_hash_entry *entry, /* Object file input functions. */ -/* Return type and length from record header (buf) on Alpha. */ +/* Return type and size from record header (buf) on Alpha. */ void _bfd_vms_get_header_values (bfd * abfd ATTRIBUTE_UNUSED, unsigned char *buf, int *type, - int *length) + int *size) { - if (type != 0) + if (type) *type = bfd_getl16 (buf); - buf += 2; - if (length != 0) - *length = bfd_getl16 (buf); + + if (size) + *size = bfd_getl16 (buf+2); #if VMS_DEBUG - vms_debug (10, "_bfd_vms_get_header_values type %x, length %x\n", (type?*type:0), (length?*length:0)); + vms_debug (10, "_bfd_vms_get_header_values type %x, size %x\n", + type ? *type : 0, size ? *size : 0); #endif } @@ -193,237 +203,341 @@ _bfd_vms_get_header_values (bfd * abfd ATTRIBUTE_UNUSED, The openVMS object file has 'variable length' which means that read() returns data in chunks of (hopefully) correct and expected - size. The linker (and other tools on vms) depend on that. Unix doesn't - know about 'formatted' files, so reading and writing such an object - file in a unix environment is not trivial. + size. The linker (and other tools on VMS) depend on that. Unix + doesn't know about 'formatted' files, so reading and writing such + an object file in a Unix environment is not trivial. - With the tool 'file' (available on all vms ftp sites), one - can view and change the attributes of a file. Changing from + With the tool 'file' (available on all VMS FTP sites), one + can view and change the attributes of a file. Changing from 'variable length' to 'fixed length, 512 bytes' reveals the - record length at the first 2 bytes of every record. The same - happens during the transfer of object files from vms to unix, - at least with ucx, dec's implementation of tcp/ip. + record size at the first 2 bytes of every record. The same + happens during the transfer of object files from VMS to Unix, + at least with UCX, the DEC implementation of TCP/IP. - The vms format repeats the length at bytes 2 & 3 of every record. + The VMS format repeats the size at bytes 2 & 3 of every record. On the first call (file_format == FF_UNKNOWN) we check if the first and the third byte pair (!) of the record match. - If they do it's an object file in an unix environment or with - wrong attributes (FF_FOREIGN), else we should be in a vms + If they do it's an object file in an Unix environment or with + wrong attributes (FF_FOREIGN), else we should be in a VMS environment where read() returns the record size (FF_NATIVE). - Reading is always done in 2 steps. - First just the record header is read and the length extracted - by get_header_values, - then the read buffer is adjusted and the remaining bytes are - read in. + Reading is always done in 2 steps: + 1. first just the record header is read and the size extracted, + 2. then the read buffer is adjusted and the remaining bytes are + read in. + + All file I/O is done on even file positions. */ - All file i/o is always done on even file positions. */ +#define VMS_OBJECT_ADJUSTMENT 2 + +static void +maybe_adjust_record_pointer_for_object (bfd *abfd) +{ + /* Set the file format once for all on the first invocation. */ + if (PRIV (file_format) == FF_UNKNOWN) + { + if (PRIV (vms_rec)[0] == PRIV (vms_rec)[4] + && PRIV (vms_rec)[1] == PRIV (vms_rec)[5]) + PRIV (file_format) = FF_FOREIGN; + else + PRIV (file_format) = FF_NATIVE; + } + + /* The adjustment is needed only in an Unix environment. */ + if (PRIV (file_format) == FF_FOREIGN) + PRIV (vms_rec) += VMS_OBJECT_ADJUSTMENT; +} + +/* Get first record from file and return the file type. */ int -_bfd_vms_get_record (bfd * abfd) +_bfd_vms_get_first_record (bfd *abfd) { - int test_len, test_start, remaining; - unsigned char *vms_buf; + unsigned int test_len; #if VMS_DEBUG - vms_debug (8, "_bfd_vms_get_record\n"); + vms_debug (8, "_bfd_vms_get_first_record\n"); #endif - /* Minimum is 6 bytes on Alpha - (2 bytes length, 2 bytes record id, 2 bytes length repeated) - - On the VAX there's no length information in the record - so start with OBJ_S_C_MAXRECSIZ. */ + if (PRIV (is_vax)) + test_len = 0; + else + /* Minimum is 6 bytes for objects (2 bytes size, 2 bytes record id, + 2 bytes size repeated) and 12 bytes for images (4 bytes major id, + 4 bytes minor id, 4 bytes length). */ + test_len = 12; + /* Size the main buffer. */ if (PRIV (buf_size) == 0) { - bfd_size_type amt; - - if (PRIV (is_vax)) - { - amt = OBJ_S_C_MAXRECSIZ; - PRIV (file_format) = FF_VAX; - } - else - amt = 6; - PRIV (vms_buf) = bfd_malloc (amt); + /* On VAX there's no size information in the record, so + start with OBJ_S_C_MAXRECSIZ. */ + bfd_size_type amt = (test_len ? test_len : OBJ_S_C_MAXRECSIZ); + PRIV (vms_buf) = (unsigned char *) bfd_malloc (amt); PRIV (buf_size) = amt; } - vms_buf = PRIV (vms_buf); + /* Initialize the record pointer. */ + PRIV (vms_rec) = PRIV (vms_buf); - if (vms_buf == 0) - return -1; - - switch (PRIV (file_format)) + /* We only support modules on VAX. */ + if (PRIV (is_vax)) { - case FF_UNKNOWN: - case FF_FOREIGN: - test_len = 6; /* Probe 6 bytes. */ - test_start = 2; /* Where the record starts. */ - break; - - case FF_NATIVE: - test_len = 4; - test_start = 0; - break; - - default: - case FF_VAX: - test_len = 0; - test_start = 0; - break; + if (vms_get_remaining_object_record (abfd, test_len) <= 0) + return FT_UNKNOWN; + +#if VMS_DEBUG + vms_debug (2, "file type is VAX module\n"); +#endif + + return FT_MODULE; } - /* Skip odd alignment byte. */ + if (bfd_bread (PRIV (vms_buf), test_len, abfd) != test_len) + { + bfd_set_error (bfd_error_file_truncated); + return FT_UNKNOWN; + } - if (bfd_tell (abfd) & 1) + /* Is it an image? */ + if ((bfd_getl32 (PRIV (vms_rec)) == EIHD_S_K_MAJORID) + && (bfd_getl32 (PRIV (vms_rec) + 4) == EIHD_S_K_MINORID)) { - if (bfd_bread (PRIV (vms_buf), (bfd_size_type) 1, abfd) != 1) - { - bfd_set_error (bfd_error_file_truncated); - return 0; - } + if (vms_get_remaining_image_record (abfd, test_len) <= 0) + return FT_UNKNOWN; + +#if VMS_DEBUG + vms_debug (2, "file type is image\n"); +#endif + + return FT_IMAGE; } - /* Read the record header on Alpha. */ - if ((test_len != 0) - && (bfd_bread (PRIV (vms_buf), (bfd_size_type) test_len, abfd) - != (bfd_size_type) test_len)) + /* Assume it's a module and adjust record pointer if necessary. */ + maybe_adjust_record_pointer_for_object (abfd); + + /* But is it really a module? */ + if (bfd_getl16 (PRIV (vms_rec)) <= EOBJ_S_C_MAXRECTYP + && bfd_getl16 (PRIV (vms_rec) + 2) <= EOBJ_S_C_MAXRECSIZ) { - bfd_set_error (bfd_error_file_truncated); - return 0; + if (vms_get_remaining_object_record (abfd, test_len) <= 0) + return FT_UNKNOWN; + +#if VMS_DEBUG + vms_debug (2, "file type is module\n"); +#endif + + return FT_MODULE; } - /* Check file format on first call. */ - if (PRIV (file_format) == FF_UNKNOWN) - { /* Record length repeats ? */ - if (vms_buf[0] == vms_buf[4] - && vms_buf[1] == vms_buf[5]) +#if VMS_DEBUG + vms_debug (2, "file type is unknown\n"); +#endif + + return FT_UNKNOWN; +} + +/* Implement step #1 of the object record reading procedure. + Return the record type or -1 on failure. */ + +int +_bfd_vms_get_object_record (bfd *abfd) +{ + unsigned int test_len; + int type; + +#if VMS_DEBUG + vms_debug (8, "_bfd_vms_get_obj_record\n"); +#endif + + if (PRIV (is_vax)) + test_len = 0; + else + { + /* See _bfd_vms_get_first_record. */ + test_len = 6; + + /* Skip odd alignment byte. */ + if (bfd_tell (abfd) & 1) { - PRIV (file_format) = FF_FOREIGN; /* Y: foreign environment. */ - test_start = 2; + if (bfd_bread (PRIV (vms_buf), 1, abfd) != 1) + { + bfd_set_error (bfd_error_file_truncated); + return -1; + } } - else + + /* Read the record header */ + if (bfd_bread (PRIV (vms_buf), test_len, abfd) != test_len) { - PRIV (file_format) = FF_NATIVE; /* N: native environment. */ - test_start = 0; + bfd_set_error (bfd_error_file_truncated); + return -1; } + + /* Reset the record pointer. */ + PRIV (vms_rec) = PRIV (vms_buf); + maybe_adjust_record_pointer_for_object (abfd); } + if (vms_get_remaining_object_record (abfd, test_len) <= 0) + return -1; + + if (PRIV (is_vax)) + type = PRIV (vms_rec) [0]; + else + type = bfd_getl16 (PRIV (vms_rec)); + +#if VMS_DEBUG + vms_debug (8, "_bfd_vms_get_obj_record: rec %p, size %d, type %d\n", + PRIV (vms_rec), PRIV (rec_size), type); +#endif + + return type; +} + +/* Implement step #2 of the object record reading procedure. + Return the size of the record or 0 on failure. */ + +static int +vms_get_remaining_object_record (bfd *abfd, int read_so_far) +{ +#if VMS_DEBUG + vms_debug (8, "vms_get_remaining_obj_record\n"); +#endif + if (PRIV (is_vax)) { - PRIV (rec_length) = bfd_bread (vms_buf, (bfd_size_type) PRIV (buf_size), - abfd); - if (PRIV (rec_length) <= 0) + if (read_so_far != 0) + abort (); + + PRIV (rec_size) = bfd_bread (PRIV (vms_buf), PRIV (buf_size), abfd); + + if (PRIV (rec_size) <= 0) { bfd_set_error (bfd_error_file_truncated); return 0; } - PRIV (vms_rec) = vms_buf; + + /* Reset the record pointer. */ + PRIV (vms_rec) = PRIV (vms_buf); } else { - /* Alpha. */ - /* Extract vms record length. */ + unsigned int to_read; - _bfd_vms_get_header_values (abfd, vms_buf + test_start, NULL, - & PRIV (rec_length)); + /* Extract record size. */ + PRIV (rec_size) = bfd_getl16 (PRIV (vms_rec) + 2); - if (PRIV (rec_length) <= 0) + if (PRIV (rec_size) <= 0) { bfd_set_error (bfd_error_file_truncated); return 0; } /* That's what the linker manual says. */ - - if (PRIV (rec_length) > EOBJ_S_C_MAXRECSIZ) + if (PRIV (rec_size) > EOBJ_S_C_MAXRECSIZ) { bfd_set_error (bfd_error_file_truncated); return 0; } - /* Adjust the buffer. */ + /* Take into account object adjustment. */ + to_read = PRIV (rec_size); + if (PRIV (file_format) == FF_FOREIGN) + to_read += VMS_OBJECT_ADJUSTMENT; - if (PRIV (rec_length) > PRIV (buf_size)) + /* Adjust the buffer. */ + if (to_read > PRIV (buf_size)) { - PRIV (vms_buf) = bfd_realloc_or_free (vms_buf, - (bfd_size_type) PRIV (rec_length)); - vms_buf = PRIV (vms_buf); - if (vms_buf == 0) - return -1; - PRIV (buf_size) = PRIV (rec_length); + PRIV (vms_buf) + = (unsigned char *) bfd_realloc (PRIV (vms_buf), to_read); + if (PRIV (vms_buf) == NULL) + return 0; + PRIV (buf_size) = to_read; } /* Read the remaining record. */ - remaining = PRIV (rec_length) - test_len + test_start; + to_read -= read_so_far; #if VMS_DEBUG - vms_debug (10, "bfd_bread remaining %d\n", remaining); + vms_debug (8, "vms_get_remaining_obj_record: to_read %d\n", to_read); #endif - if (bfd_bread (vms_buf + test_len, (bfd_size_type) remaining, abfd) != - (bfd_size_type) remaining) + + if (bfd_bread (PRIV (vms_buf) + read_so_far, to_read, abfd) != to_read) { bfd_set_error (bfd_error_file_truncated); return 0; } - PRIV (vms_rec) = vms_buf + test_start; + + /* Reset the record pointer. */ + PRIV (vms_rec) = PRIV (vms_buf); + maybe_adjust_record_pointer_for_object (abfd); } #if VMS_DEBUG - vms_debug (11, "bfd_bread rec_length %d\n", PRIV (rec_length)); + vms_debug (8, "vms_get_remaining_obj_record: size %d\n", PRIV (rec_size)); #endif - return PRIV (rec_length); + return PRIV (rec_size); } -/* Get next vms record from file - update vms_rec and rec_length to new (remaining) values. */ +/* Implement step #2 of the record reading procedure for images. + Return the size of the record or 0 on failure. */ -int -_bfd_vms_next_record (bfd * abfd) +static int +vms_get_remaining_image_record (bfd *abfd, int read_so_far) { -#if VMS_DEBUG - vms_debug (8, "_bfd_vms_next_record (len %d, size %d)\n", - PRIV (rec_length), PRIV (rec_size)); -#endif + unsigned int to_read; + int remaining; - if (PRIV (rec_length) > 0) - PRIV (vms_rec) += PRIV (rec_size); - else + /* Extract record size. */ + PRIV (rec_size) = bfd_getl32 (PRIV (vms_rec) + EIHD_S_L_SIZE); + + if (PRIV (rec_size) > PRIV (buf_size)) { - if (_bfd_vms_get_record (abfd) <= 0) - return -1; + PRIV (vms_buf) = bfd_realloc (PRIV (vms_buf), PRIV (rec_size)); + + if (PRIV (vms_buf) == NULL) + { + bfd_set_error (bfd_error_no_memory); + return 0; + } + + PRIV (buf_size) = PRIV (rec_size); } - if (!PRIV (vms_rec) || !PRIV (vms_buf) - || PRIV (vms_rec) >= (PRIV (vms_buf) + PRIV (buf_size))) - return -1; + /* Read the remaining record. */ + remaining = PRIV (rec_size) - read_so_far; + to_read = MIN (VMS_BLOCK_SIZE - read_so_far, remaining); - if (PRIV (is_vax)) + while (remaining > 0) { - PRIV (rec_type) = *(PRIV (vms_rec)); - PRIV (rec_size) = PRIV (rec_length); - } - else - _bfd_vms_get_header_values (abfd, PRIV (vms_rec), &PRIV (rec_type), - &PRIV (rec_size)); + if (bfd_bread (PRIV (vms_buf) + read_so_far, to_read, abfd) != to_read) + { + bfd_set_error (bfd_error_file_truncated); + return 0; + } - PRIV (rec_length) -= PRIV (rec_size); + read_so_far += to_read; + remaining -= to_read; -#if VMS_DEBUG - vms_debug (8, "_bfd_vms_next_record: rec %p, size %d, length %d, type %d\n", - PRIV (vms_rec), PRIV (rec_size), PRIV (rec_length), - PRIV (rec_type)); -#endif + /* Eat trailing 0xff's. */ + if (remaining > 0) + while (PRIV (vms_buf) [read_so_far - 1] == 0xff) + read_so_far--; + + to_read = MIN (VMS_BLOCK_SIZE, remaining); + } - return PRIV (rec_type); + /* Reset the record pointer. */ + PRIV (vms_rec) = PRIV (vms_buf); + + return PRIV (rec_size); } - -/* Copy sized string (string with fixed length) to new allocated area - size is string length (size of record) */ + +/* Copy sized string (string with fixed size) to new allocated area + size is string size (size of record) */ char * _bfd_vms_save_sized_string (unsigned char *str, int size) @@ -438,8 +552,8 @@ _bfd_vms_save_sized_string (unsigned char *str, int size) return newstr; } -/* Copy counted string (string with length at first byte) to new allocated area - ptr points to length byte on entry */ +/* Copy counted string (string with size at first byte) to new allocated area + ptr points to size byte on entry */ char * _bfd_vms_save_counted_string (unsigned char *ptr) @@ -501,83 +615,12 @@ _bfd_vms_pop (bfd * abfd, int *psect) return value; } -/* Object file output functions. */ - -/* GAS tends to write sections in little chunks (bfd_set_section_contents) - which we can't use directly. So we save the little chunks in linked - lists (one per section) and write them later. */ - -/* Add a new vms_section structure to vms_section_table - - forward chaining -. */ - -static vms_section * -add_new_contents (bfd * abfd, sec_ptr section) -{ - vms_section *sptr, *newptr; - - sptr = PRIV (vms_section_table)[section->index]; - if (sptr != NULL) - return sptr; - - newptr = bfd_alloc (abfd, (bfd_size_type) sizeof (vms_section)); - if (newptr == NULL) - return NULL; - newptr->contents = bfd_alloc (abfd, section->size); - if (newptr->contents == NULL) - return NULL; - newptr->offset = 0; - newptr->size = section->size; - newptr->next = 0; - PRIV (vms_section_table)[section->index] = newptr; - return newptr; -} - -/* Save section data & offset to a vms_section structure - vms_section_table[] holds the vms_section chain. */ - -bfd_boolean -_bfd_save_vms_section (bfd * abfd, - sec_ptr section, - const void * data, - file_ptr offset, - bfd_size_type count) -{ - vms_section *sptr; - - if (section->index >= VMS_SECTION_COUNT) - { - bfd_set_error (bfd_error_nonrepresentable_section); - return FALSE; - } - if (count == (bfd_size_type)0) - return TRUE; - sptr = add_new_contents (abfd, section); - if (sptr == NULL) - return FALSE; - memcpy (sptr->contents + offset, data, (size_t) count); - - return TRUE; -} - -/* Get vms_section pointer to saved contents for section # index */ - -vms_section * -_bfd_get_vms_section (bfd * abfd, int index) -{ - if (index >= VMS_SECTION_COUNT) - { - bfd_set_error (bfd_error_nonrepresentable_section); - return NULL; - } - return PRIV (vms_section_table)[index]; -} - /* Object output routines. */ /* Begin new record or record header write 2 bytes rectype write 2 bytes record length (filled in at flush) - write 2 bytes header type (ommitted if rechead == -1). */ + write 2 bytes header type (ommitted if rechead == -1). */ void _bfd_vms_output_begin (bfd * abfd, int rectype, int rechead) @@ -691,18 +734,11 @@ _bfd_vms_output_flush (bfd * abfd) if (PRIV (push_level) == 0) { - if (0 -#ifndef VMS - /* Write length first, see FF_FOREIGN in the input routines. */ - || fwrite (PRIV (output_buf) + 2, 2, 1, - (FILE *) abfd->iostream) != 1 -#endif - || (real_size != 0 - && fwrite (PRIV (output_buf), (size_t) real_size, 1, - (FILE *) abfd->iostream) != 1)) - /* FIXME: Return error status. */ - abort (); - + /* File is open in undefined (UDF) format on VMS, but ultimately will be + converted to variable length (VAR) format. VAR format has a length + word first which must be explicitly output in UDF format. */ + bfd_bwrite (PRIV (output_buf) + 2, 2, abfd); + bfd_bwrite (PRIV (output_buf), (size_t) real_size, abfd); PRIV (output_size) = 0; } else @@ -948,7 +984,7 @@ new_symbol (bfd * abfd, char *name) if (symbol == 0) return symbol; symbol->name = name; - symbol->section = bfd_make_section (abfd, BFD_UND_SECTION_NAME); + symbol->section = (asection *)(unsigned long)-1; return symbol; } diff --git a/bfd/vms-tir.c b/bfd/vms-tir.c index e6ec6eb..5bc61da 100644 --- a/bfd/vms-tir.c +++ b/bfd/vms-tir.c @@ -1,12 +1,12 @@ /* vms-tir.c -- BFD back-end for VAX (openVMS/VAX) and EVAX (openVMS/Alpha) files. - Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2004, 2005, 2007, 2008 - Free Software Foundation, Inc. + Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2004, 2005, 2007, + 2008, 2009 Free Software Foundation, Inc. TIR record handling functions ETIR record handling functions - go and read the openVMS linker manual (esp. appendix B) + 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) @@ -26,7 +26,6 @@ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ - /* The following type abbreviations are used: cs counted string (ascii string with length byte) @@ -41,6 +40,33 @@ #include "bfdlink.h" #include "libbfd.h" #include "vms.h" + +static int check_section (bfd *, int); +static void image_set_ptr (bfd *abfd, int psect, uquad offset); +static void image_inc_ptr (bfd *abfd, uquad offset); +static void dst_define_location (bfd *abfd, uquad loc); +static void dst_restore_location (bfd *abfd, uquad loc); +static unsigned int dst_retrieve_location (bfd *abfd, uquad loc); +static void dst_check_allocation (bfd *abfd, unsigned int size); +static void image_dump (bfd *abfd, unsigned char *ptr, int size, int offset); +static void image_write_b (bfd *abfd, unsigned int value); +static void image_write_w (bfd *abfd, unsigned int value); +static void image_write_l (bfd *abfd, unsigned long value); +static void image_write_q (bfd *abfd, uquad value); +static bfd_boolean etir_sta (bfd *, int, unsigned char *, int *); +static bfd_boolean etir_sto (bfd *, int, unsigned char *, int *); +static bfd_boolean etir_opr (bfd *, int, unsigned char *, int *); +static bfd_boolean etir_ctl (bfd *, int, unsigned char *, int *); +static bfd_boolean etir_stc (bfd *, int, unsigned char *, int *); +static asection *new_section (bfd *, int); +static int alloc_section (bfd *, unsigned int); +static int etir_cmd (bfd *, int, unsigned char *, int *); +static int analyze_tir (bfd *, unsigned char *, unsigned int); +static int analyze_etir (bfd *, unsigned char *, unsigned int); +static unsigned char *tir_opr (bfd *, unsigned char *); +static const char *tir_cmd_name (int); +static const char *cmd_name (int); + static int check_section (bfd * abfd, int size) @@ -92,6 +118,77 @@ image_inc_ptr (bfd * abfd, uquad offset) PRIV (image_ptr) += offset; } +/* Save current DST location counter under specified index. */ + +static void +dst_define_location (bfd *abfd, uquad loc) +{ + asection *dst_section = PRIV (dst_section); + +#if VMS_DEBUG + _bfd_vms_debug (4, "dst_define_location (%d)\n", (int)loc); +#endif + + /* Grow the ptr offset table if necessary. */ + if (loc + 1 > PRIV (dst_ptr_offsets_count)) + { + PRIV (dst_ptr_offsets) = bfd_realloc (PRIV (dst_ptr_offsets), + (loc + 1) * sizeof (unsigned int)); + PRIV (dst_ptr_offsets_count) = loc + 1; + } + + PRIV (dst_ptr_offsets)[loc] = PRIV (image_ptr) - dst_section->contents; +} + +/* Restore saved DST location counter from specified index. */ + +static void +dst_restore_location (bfd *abfd, uquad loc) +{ + asection *dst_section = PRIV (dst_section); + +#if VMS_DEBUG + _bfd_vms_debug (4, "dst_restore_location (%d)\n", (int)loc); +#endif + + PRIV (image_ptr) = dst_section->contents + PRIV (dst_ptr_offsets)[loc]; +} + +/* Retrieve saved DST location counter from specified index. */ + +static unsigned int +dst_retrieve_location (bfd *abfd, uquad loc) +{ +#if VMS_DEBUG + _bfd_vms_debug (4, "dst_retrieve_location (%d)\n", (int)loc); +#endif + + return PRIV (dst_ptr_offsets)[loc]; +} + +/* Check that the DST section is big enough for the specified + amount of bytes. */ + +static void +dst_check_allocation (bfd *abfd, unsigned int size) +{ + asection *dst_section = PRIV (dst_section); + + bfd_size_type used = PRIV (image_ptr) - dst_section->contents; + bfd_size_type left = dst_section->size - used; + + /* Grow the DST section as necessary */ + if (size > left) + { + dst_section->size *= 2; + dst_section->contents + = bfd_realloc (dst_section->contents, dst_section->size); + PRIV (image_ptr) = dst_section->contents + used; + + dst_check_allocation (abfd, size); + } +} + /* Dump multiple bytes to section image. */ static void @@ -109,6 +206,9 @@ image_dump (bfd * abfd, if (PRIV (is_vax) && check_section (abfd, size)) return; + if (PRIV (dst_section)) + dst_check_allocation (abfd, size); + while (size-- > 0) *PRIV (image_ptr)++ = *ptr++; } @@ -125,6 +225,9 @@ image_write_b (bfd * abfd, unsigned int value) if (PRIV (is_vax) && check_section (abfd, 1)) return; + if (PRIV (dst_section)) + dst_check_allocation (abfd, 1); + *PRIV (image_ptr)++ = (value & 0xff); } @@ -140,6 +243,9 @@ image_write_w (bfd * abfd, unsigned int value) if (PRIV (is_vax) && check_section (abfd, 2)) return; + if (PRIV (dst_section)) + dst_check_allocation (abfd, 2); + bfd_putl16 ((bfd_vma) value, PRIV (image_ptr)); PRIV (image_ptr) += 2; } @@ -156,6 +262,9 @@ image_write_l (bfd * abfd, unsigned long value) if (PRIV (is_vax) && check_section (abfd, 4)) return; + if (PRIV (dst_section)) + dst_check_allocation (abfd, 4); + bfd_putl32 ((bfd_vma) value, PRIV (image_ptr)); PRIV (image_ptr) += 4; } @@ -172,6 +281,9 @@ image_write_q (bfd * abfd, uquad value) if (PRIV (is_vax) && check_section (abfd, 8)) return; + if (PRIV (dst_section)) + dst_check_allocation (abfd, 8); + bfd_putl64 (value, PRIV (image_ptr)); PRIV (image_ptr) += 8; } @@ -182,6 +294,8 @@ cmd_name (int cmd) switch (cmd) { case ETIR_S_C_STA_GBL: return "ETIR_S_C_STA_GBL"; + case ETIR_S_C_STA_LW: return "ETIR_S_C_STA_LW"; + case ETIR_S_C_STA_QW: return "ETIR_S_C_STA_QW"; case ETIR_S_C_STA_PQ: return "ETIR_S_C_STA_PQ"; case ETIR_S_C_STA_LI: return "ETIR_S_C_STA_LI"; case ETIR_S_C_STA_MOD: return "ETIR_S_C_STA_MOD"; @@ -192,10 +306,16 @@ cmd_name (int cmd) case ETIR_S_C_STO_CA: return "ETIR_S_C_STO_CA"; case ETIR_S_C_STO_RB: return "ETIR_S_C_STO_RB"; case ETIR_S_C_STO_AB: return "ETIR_S_C_STO_AB"; + case ETIR_S_C_STO_OFF: return "ETIR_S_C_STO_OFF"; + case ETIR_S_C_STO_IMM: return "ETIR_S_C_STO_IMM"; + case ETIR_S_C_STO_IMMR: return "ETIR_S_C_STO_IMMR"; + case ETIR_S_C_STO_LW: return "ETIR_S_C_STO_LW"; + case ETIR_S_C_STO_QW: return "ETIR_S_C_STO_QW"; case ETIR_S_C_STO_GBL_LW: return "ETIR_S_C_STO_GBL_LW"; case ETIR_S_C_STO_LP_PSB: return "ETIR_S_C_STO_LP_PSB"; case ETIR_S_C_STO_HINT_GBL: return "ETIR_S_C_STO_HINT_GBL"; case ETIR_S_C_STO_HINT_PS: return "ETIR_S_C_STO_HINT_PS"; + case ETIR_S_C_OPR_ADD: return "ETIR_S_C_OPR_ADD"; case ETIR_S_C_OPR_INSV: return "ETIR_S_C_OPR_INSV"; case ETIR_S_C_OPR_USH: return "ETIR_S_C_OPR_USH"; case ETIR_S_C_OPR_ROT: return "ETIR_S_C_OPR_ROT"; @@ -215,34 +335,41 @@ cmd_name (int cmd) case ETIR_S_C_STC_BOH_GBL: return "ETIR_S_C_STC_BOH_GBL"; case ETIR_S_C_STC_BOH_PS: return "ETIR_S_C_STC_BOH_PS"; case ETIR_S_C_STC_NBH_GBL: return "ETIR_S_C_STC_NBH_GBL"; + case ETIR_S_C_CTL_SETRB: return "ETIR_S_C_CTL_SETRB"; + case ETIR_S_C_STC_LP_PSB: return "ETIR_S_C_STC_LP_PSB"; + case ETIR_S_C_CTL_DFLOC: return "ETIR_S_C_CTL_DFLOC"; + case ETIR_S_C_CTL_STLOC: return "ETIR_S_C_CTL_STLOC"; + case ETIR_S_C_CTL_STKDL: return "ETIR_S_C_CTL_STKDL"; default: /* These names have not yet been added to this switch statement. */ - abort (); + (*_bfd_error_handler) (_("unknown ETIR command %d"), cmd); } + + return NULL; } #define HIGHBIT(op) ((op & 0x80000000L) == 0x80000000L) /* etir_sta - vms stack commands + Vms stack commands. - handle sta_xxx commands in etir section - ptr points to data area in record + Handle sta_xxx commands in etir section, + ptr points to data area in record. - see table B-8 of the openVMS linker manual. */ + See table B-8 of the openVMS linker manual. */ static bfd_boolean -etir_sta (bfd * abfd, int cmd, unsigned char *ptr) +etir_sta (bfd *abfd, int cmd, unsigned char *ptr, int *quarter_relocs) { #if VMS_DEBUG _bfd_vms_debug (5, "etir_sta %d/%x\n", cmd, cmd); - _bfd_hexdump (8, ptr, 16, (int) ptr); + _bfd_hexdump (8, ptr, 16, (long) ptr); #endif switch (cmd) { - /* stack global + /* Stack global arg: cs symbol name stack 32 bit value of symbol (high bits set to 0). */ @@ -265,37 +392,50 @@ etir_sta (bfd * abfd, int cmd, unsigned char *ptr) else _bfd_vms_push (abfd, (uquad) (entry->symbol->value), -1); } + *quarter_relocs = 1; break; - /* stack longword + /* Stack longword arg: lw value stack 32 bit value, sign extend to 64 bit. */ case ETIR_S_C_STA_LW: _bfd_vms_push (abfd, (uquad) bfd_getl32 (ptr), -1); + /* This one is special as it is both part of the section header + and of the ALPHA_R_REFLONG relocation. */ + if (bfd_getl16 (ptr - 4 + bfd_getl16 (ptr - 2)) == ETIR_S_C_CTL_DFLOC) + *quarter_relocs = 0; + else if (*quarter_relocs) + *quarter_relocs += 1; + else + *quarter_relocs = 2; break; - /* stack global + /* Stack quadword arg: qw value stack 64 bit value of symbol. */ case ETIR_S_C_STA_QW: _bfd_vms_push (abfd, (uquad) bfd_getl64 (ptr), -1); + if (*quarter_relocs) + *quarter_relocs += 1; + else + *quarter_relocs = 2; break; - /* stack psect base plus quadword offset + /* Stack psect base plus quadword offset arg: lw section index qw signed quadword offset (low 32 bits) - stack qw argument and section index + Stack qw argument and section index (see ETIR_S_C_STO_OFF, ETIR_S_C_CTL_SETRB). */ case ETIR_S_C_STA_PQ: { uquad dummy; - unsigned int psect; + int psect; psect = bfd_getl32 (ptr); - if (psect >= PRIV (section_count)) + if ((unsigned int) psect >= PRIV (section_count)) { (*_bfd_error_handler) (_("bad section index in %s"), cmd_name (cmd)); @@ -305,23 +445,31 @@ etir_sta (bfd * abfd, int cmd, unsigned char *ptr) dummy = bfd_getl64 (ptr + 4); _bfd_vms_push (abfd, dummy, (int) psect); } + /* This one is special as it is both part of the section header + and of the ALPHA_R_REFLONG and ALPHA_R_REFQUAD relocations. */ + if (bfd_getl16 (ptr - 4 + bfd_getl16 (ptr - 2)) == ETIR_S_C_CTL_SETRB) + *quarter_relocs = 0; + else + *quarter_relocs = 2; break; case ETIR_S_C_STA_LI: case ETIR_S_C_STA_MOD: case ETIR_S_C_STA_CKARG: (*_bfd_error_handler) (_("unsupported STA cmd %s"), cmd_name (cmd)); + *quarter_relocs = 0; return FALSE; - break; default: (*_bfd_error_handler) (_("reserved STA cmd %d"), cmd); + *quarter_relocs = 0; return FALSE; - break; } + #if VMS_DEBUG _bfd_vms_debug (5, "etir_sta true\n"); #endif + return TRUE; } @@ -335,14 +483,14 @@ etir_sta (bfd * abfd, int cmd, unsigned char *ptr) see table B-9 of the openVMS linker manual. */ static bfd_boolean -etir_sto (bfd * abfd, int cmd, unsigned char *ptr) +etir_sto (bfd *abfd, int cmd, unsigned char *ptr, int *quarter_relocs) { uquad dummy; int psect; #if VMS_DEBUG _bfd_vms_debug (5, "etir_sto %d/%x\n", cmd, cmd); - _bfd_hexdump (8, ptr, 16, (int) ptr); + _bfd_hexdump (8, ptr, 16, (long) ptr); #endif switch (cmd) @@ -353,6 +501,7 @@ etir_sto (bfd * abfd, int cmd, unsigned char *ptr) dummy = _bfd_vms_pop (abfd, &psect); /* FIXME: check top bits. */ image_write_b (abfd, (unsigned int) dummy & 0xff); + *quarter_relocs = 0; break; /* Store word: pop stack, write word @@ -361,6 +510,7 @@ etir_sto (bfd * abfd, int cmd, unsigned char *ptr) dummy = _bfd_vms_pop (abfd, &psect); /* FIXME: check top bits */ image_write_w (abfd, (unsigned int) dummy & 0xffff); + *quarter_relocs = 0; break; /* Store longword: pop stack, write longword @@ -370,6 +520,10 @@ etir_sto (bfd * abfd, int cmd, unsigned char *ptr) dummy += (PRIV (sections)[psect])->vma; /* FIXME: check top bits. */ image_write_l (abfd, (unsigned int) dummy & 0xffffffff); + if (*quarter_relocs == 2) + *quarter_relocs = 4; + else + *quarter_relocs += 1; break; /* Store quadword: pop stack, write quadword @@ -379,6 +533,10 @@ etir_sto (bfd * abfd, int cmd, unsigned char *ptr) dummy += (PRIV (sections)[psect])->vma; /* FIXME: check top bits. */ image_write_q (abfd, dummy); + if (*quarter_relocs == 2) + *quarter_relocs = 4; + else + *quarter_relocs += 1; break; /* Store immediate repeated: pop stack for repeat count @@ -393,6 +551,7 @@ etir_sto (bfd * abfd, int cmd, unsigned char *ptr) while (dummy-- > 0) image_dump (abfd, ptr+4, size, 0); } + *quarter_relocs = 0; break; /* Store global: write symbol value @@ -406,15 +565,13 @@ etir_sto (bfd * abfd, int cmd, unsigned char *ptr) entry = (vms_symbol_entry *) bfd_hash_lookup (PRIV (vms_symbol_table), name, FALSE, FALSE); if (entry == NULL) - { - (*_bfd_error_handler) (_("%s: no symbol \"%s\""), - cmd_name (cmd), name); - return FALSE; - } + /* FIXME, reloc. */ + image_write_q (abfd, (uquad) (0)); else /* FIXME, reloc. */ image_write_q (abfd, (uquad) (entry->symbol->value)); } + *quarter_relocs = 4; break; /* Store code address: write address of entry point @@ -428,15 +585,13 @@ etir_sto (bfd * abfd, int cmd, unsigned char *ptr) entry = (vms_symbol_entry *) bfd_hash_lookup (PRIV (vms_symbol_table), name, FALSE, FALSE); if (entry == NULL) - { - (*_bfd_error_handler) (_("%s: no symbol \"%s\""), - cmd_name (cmd), name); - return FALSE; - } + /* FIXME, reloc. */ + image_write_q (abfd, (uquad) (0)); else /* FIXME, reloc. */ image_write_q (abfd, (uquad) (entry->symbol->value)); } + *quarter_relocs = 4; break; /* Store offset to psect: pop stack, add low 32 bits to base of psect @@ -450,6 +605,7 @@ etir_sto (bfd * abfd, int cmd, unsigned char *ptr) q += (PRIV (sections)[psect1])->vma; image_write_q (abfd, q); } + *quarter_relocs += 2; break; /* Store immediate @@ -462,6 +618,7 @@ etir_sto (bfd * abfd, int cmd, unsigned char *ptr) size = bfd_getl32 (ptr); image_dump (abfd, ptr+4, size, 0); } + *quarter_relocs = 0; break; /* This code is 'reserved to digital' according to the openVMS @@ -489,22 +646,26 @@ etir_sto (bfd * abfd, int cmd, unsigned char *ptr) /* FIXME, reloc. */ image_write_l (abfd, (unsigned long) (entry->symbol->value)); } + *quarter_relocs = 4; break; case ETIR_S_C_STO_RB: case ETIR_S_C_STO_AB: case ETIR_S_C_STO_LP_PSB: (*_bfd_error_handler) (_("%s: not supported"), cmd_name (cmd)); - break; + *quarter_relocs = 0; + return FALSE; case ETIR_S_C_STO_HINT_GBL: case ETIR_S_C_STO_HINT_PS: (*_bfd_error_handler) (_("%s: not implemented"), cmd_name (cmd)); - break; + *quarter_relocs = 0; + return FALSE; default: (*_bfd_error_handler) (_("reserved STO cmd %d"), cmd); - break; + *quarter_relocs = 0; + return FALSE; } return TRUE; @@ -518,15 +679,22 @@ etir_sto (bfd * abfd, int cmd, unsigned char *ptr) see table B-10 of the openVMS linker manual. */ static bfd_boolean -etir_opr (bfd * abfd, int cmd, unsigned char *ptr ATTRIBUTE_UNUSED) +etir_opr (bfd *abfd, int cmd, unsigned char *ptr ATTRIBUTE_UNUSED, + int *quarter_relocs) { long op1, op2; #if VMS_DEBUG _bfd_vms_debug (5, "etir_opr %d/%x\n", cmd, cmd); - _bfd_hexdump (8, ptr, 16, (int) ptr); + _bfd_hexdump (8, ptr, 16, (long) ptr); #endif + /* No relocation uses OPR commands except ETIR_S_C_OPR_ADD. */ + if (cmd == ETIR_S_C_OPR_ADD) + *quarter_relocs += 1; + else + *quarter_relocs = 0; + switch (cmd) { case ETIR_S_C_OPR_NOP: /* No-op. */ @@ -604,7 +772,7 @@ etir_opr (bfd * abfd, int cmd, unsigned char *ptr ATTRIBUTE_UNUSED) case ETIR_S_C_OPR_REDEF: /* Redefine symbol to current location. */ case ETIR_S_C_OPR_DFLIT: /* Define a literal. */ (*_bfd_error_handler) (_("%s: not supported"), cmd_name (cmd)); - break; + return FALSE; case ETIR_S_C_OPR_SEL: /* Select. */ if ((long) _bfd_vms_pop (abfd, NULL) & 0x01L) @@ -619,7 +787,7 @@ etir_opr (bfd * abfd, int cmd, unsigned char *ptr ATTRIBUTE_UNUSED) default: (*_bfd_error_handler) (_("reserved OPR cmd %d"), cmd); - break; + return FALSE; } return TRUE; @@ -630,16 +798,19 @@ etir_opr (bfd * abfd, int cmd, unsigned char *ptr ATTRIBUTE_UNUSED) See table B-11 of the openVMS linker manual. */ static bfd_boolean -etir_ctl (bfd * abfd, int cmd, unsigned char *ptr) +etir_ctl (bfd *abfd, int cmd, unsigned char *ptr, int *quarter_relocs) { - uquad dummy; + uquad dummy; int psect; #if VMS_DEBUG _bfd_vms_debug (5, "etir_ctl %d/%x\n", cmd, cmd); - _bfd_hexdump (8, ptr, 16, (int) ptr); + _bfd_hexdump (8, ptr, 16, (long) ptr); #endif + /* No relocation uses CTL commands. */ + *quarter_relocs = 0; + switch (cmd) { /* Det relocation base: pop stack, set image location counter @@ -660,27 +831,28 @@ etir_ctl (bfd * abfd, int cmd, unsigned char *ptr) arg: none. */ case ETIR_S_C_CTL_DFLOC: dummy = _bfd_vms_pop (abfd, NULL); - /* FIXME */ + dst_define_location (abfd, dummy); break; /* Set location: pop index, restore location counter from index arg: none. */ case ETIR_S_C_CTL_STLOC: - dummy = _bfd_vms_pop (abfd, &psect); - /* FIXME */ + dummy = _bfd_vms_pop (abfd, NULL); + dst_restore_location (abfd, dummy); break; /* Stack defined location: pop index, push location counter from index arg: none. */ case ETIR_S_C_CTL_STKDL: - dummy = _bfd_vms_pop (abfd, &psect); - /* FIXME. */ + dummy = _bfd_vms_pop (abfd, NULL); + _bfd_vms_push (abfd, dst_retrieve_location (abfd, dummy), -1); break; default: (*_bfd_error_handler) (_("reserved CTL cmd %d"), cmd); - break; + return FALSE; } + return TRUE; } @@ -689,11 +861,12 @@ etir_ctl (bfd * abfd, int cmd, unsigned char *ptr) See table B-12 and B-13 of the openVMS linker manual. */ static bfd_boolean -etir_stc (bfd * abfd, int cmd, unsigned char *ptr ATTRIBUTE_UNUSED) +etir_stc (bfd *abfd, int cmd, unsigned char *ptr ATTRIBUTE_UNUSED, + int *quarter_relocs) { #if VMS_DEBUG _bfd_vms_debug (5, "etir_stc %d/%x\n", cmd, cmd); - _bfd_hexdump (8, ptr, 16, (int) ptr); + _bfd_hexdump (8, ptr, 16, (long) ptr); #endif switch (cmd) @@ -701,32 +874,17 @@ etir_stc (bfd * abfd, int cmd, unsigned char *ptr ATTRIBUTE_UNUSED) /* 200 Store-conditional Linkage Pair arg: none. */ case ETIR_S_C_STC_LP: - (*_bfd_error_handler) (_("%s: not supported"), cmd_name (cmd)); - break; - - /* 201 Store-conditional Linkage Pair with Procedure Signature - arg: lw linkage index - cs procedure name - by signature length - da signature. */ - case ETIR_S_C_STC_LP_PSB: - image_inc_ptr (abfd, (uquad) 16); /* skip entry,procval */ - break; /* 202 Store-conditional Address at global address arg: lw linkage index cs global name. */ case ETIR_S_C_STC_GBL: - (*_bfd_error_handler) (_("%s: not supported"), cmd_name (cmd)); - break; /* 203 Store-conditional Code Address at global address arg: lw linkage index cs procedure name. */ case ETIR_S_C_STC_GCA: - (*_bfd_error_handler) (_("%s: not supported"), cmd_name (cmd)); - break; /* 204 Store-conditional Address at psect + offset arg: lw linkage index @@ -734,56 +892,82 @@ etir_stc (bfd * abfd, int cmd, unsigned char *ptr ATTRIBUTE_UNUSED) qw offset. */ case ETIR_S_C_STC_PS: (*_bfd_error_handler) (_("%s: not supported"), cmd_name (cmd)); + *quarter_relocs = 0; + return FALSE; + + /* 201 Store-conditional Linkage Pair with Procedure Signature + arg: lw linkage index + cs procedure name + by signature length + da signature. */ + + case ETIR_S_C_STC_LP_PSB: + image_inc_ptr (abfd, (uquad) 16); /* skip entry,procval */ + *quarter_relocs = 4; break; /* 205 Store-conditional NOP at address of global arg: none. */ case ETIR_S_C_STC_NOP_GBL: - - /* 206 Store-conditional NOP at pect + offset - arg: none. */ - case ETIR_S_C_STC_NOP_PS: + /* ALPHA_R_NOP */ /* 207 Store-conditional BSR at global address arg: none. */ - case ETIR_S_C_STC_BSR_GBL: - /* 208 Store-conditional BSR at pect + offset - arg: none. */ - case ETIR_S_C_STC_BSR_PS: + case ETIR_S_C_STC_BSR_GBL: + /* ALPHA_R_BSR */ /* 209 Store-conditional LDA at global address arg: none. */ - case ETIR_S_C_STC_LDA_GBL: - /* 210 Store-conditional LDA at psect + offset - arg: none. */ - case ETIR_S_C_STC_LDA_PS: + case ETIR_S_C_STC_LDA_GBL: + /* ALPHA_R_LDA */ /* 211 Store-conditional BSR or Hint at global address arg: none. */ - case ETIR_S_C_STC_BOH_GBL: - /* 212 Store-conditional BSR or Hint at pect + offset - arg: none. */ - case ETIR_S_C_STC_BOH_PS: + case ETIR_S_C_STC_BOH_GBL: + *quarter_relocs = 4; + break; /* 213 Store-conditional NOP,BSR or HINT at global address arg: none. */ + case ETIR_S_C_STC_NBH_GBL: - /* 214 Store-conditional NOP,BSR or HINT at psect + offset + /* 206 Store-conditional NOP at pect + offset + arg: none. */ + + case ETIR_S_C_STC_NOP_PS: + + /* 208 Store-conditional BSR at pect + offset + arg: none. */ + + case ETIR_S_C_STC_BSR_PS: + + /* 210 Store-conditional LDA at psect + offset + arg: none. */ + + case ETIR_S_C_STC_LDA_PS: + + /* 212 Store-conditional BSR or Hint at pect + offset + arg: none. */ + + case ETIR_S_C_STC_BOH_PS: + + /* 214 Store-conditional NOP, BSR or HINT at psect + offset arg: none. */ case ETIR_S_C_STC_NBH_PS: - /* FIXME */ - break; + (*_bfd_error_handler) ("%s: not supported", cmd_name (cmd)); + *quarter_relocs = 0; + return FALSE; default: -#if VMS_DEBUG - _bfd_vms_debug (3, "reserved STC cmd %d", cmd); -#endif - break; + (*_bfd_error_handler) (_("reserved STC cmd %d"), cmd); + *quarter_relocs = 0; + return FALSE; } + return TRUE; } @@ -851,10 +1035,10 @@ alloc_section (bfd * abfd, unsigned int idx) /* tir_sta - vax stack commands + Vax stack commands. - Handle sta_xxx commands in tir section - ptr points to data area in record + Handle sta_xxx commands in tir section, + ptr points to data area in record. See table 7-3 of the VAX/VMS linker manual. */ @@ -924,7 +1108,7 @@ tir_sta (bfd * abfd, unsigned char *ptr) by signed byte offset. */ { unsigned long dummy; - unsigned int psect; + int psect; if (cmd == TIR_S_C_STA_PB) psect = *ptr++; @@ -934,12 +1118,12 @@ tir_sta (bfd * abfd, unsigned char *ptr) ptr += 2; } - if (psect >= PRIV (section_count)) + if ((unsigned int) psect >= PRIV (section_count)) alloc_section (abfd, psect); dummy = (long) *ptr++; dummy += (PRIV (sections)[psect])->vma; - _bfd_vms_push (abfd, (uquad) dummy, (int) psect); + _bfd_vms_push (abfd, (uquad) dummy, psect); } break; @@ -951,7 +1135,7 @@ tir_sta (bfd * abfd, unsigned char *ptr) sh signed short offset. */ { unsigned long dummy; - unsigned int psect; + int psect; if (cmd == TIR_S_C_STA_PW) psect = *ptr++; @@ -961,12 +1145,12 @@ tir_sta (bfd * abfd, unsigned char *ptr) ptr += 2; } - if (psect >= PRIV (section_count)) + if ((unsigned int) psect >= PRIV (section_count)) alloc_section (abfd, psect); dummy = bfd_getl16 (ptr); ptr+=2; dummy += (PRIV (sections)[psect])->vma; - _bfd_vms_push (abfd, (uquad) dummy, (int) psect); + _bfd_vms_push (abfd, (uquad) dummy, psect); } break; @@ -978,7 +1162,7 @@ tir_sta (bfd * abfd, unsigned char *ptr) lw signed longword offset. */ { unsigned long dummy; - unsigned int psect; + int psect; if (cmd == TIR_S_C_STA_PL) psect = *ptr++; @@ -988,12 +1172,12 @@ tir_sta (bfd * abfd, unsigned char *ptr) ptr += 2; } - if (psect >= PRIV (section_count)) + if ((unsigned int) psect >= PRIV (section_count)) alloc_section (abfd, psect); dummy = bfd_getl32 (ptr); ptr += 4; dummy += (PRIV (sections)[psect])->vma; - _bfd_vms_push (abfd, (uquad) dummy, (int) psect); + _bfd_vms_push (abfd, (uquad) dummy, psect); } break; @@ -1457,7 +1641,7 @@ static unsigned char * tir_ctl (bfd * abfd, unsigned char *ptr) { unsigned long dummy; - unsigned int psect; + int psect; #if VMS_DEBUG _bfd_vms_debug (5, "tir_ctl %d\n", *ptr); @@ -1468,10 +1652,10 @@ tir_ctl (bfd * abfd, unsigned char *ptr) case TIR_S_C_CTL_SETRB: /* Set relocation base: pop stack, set image location counter arg: none. */ - dummy = _bfd_vms_pop (abfd, (int *) &psect); - if (psect >= PRIV (section_count)) + dummy = _bfd_vms_pop (abfd, &psect); + if ((unsigned int) psect >= PRIV (section_count)) alloc_section (abfd, psect); - image_set_ptr (abfd, (int) psect, (uquad) dummy); + image_set_ptr (abfd, psect, (uquad) dummy); break; case TIR_S_C_CTL_AUGRB: @@ -1492,7 +1676,7 @@ tir_ctl (bfd * abfd, unsigned char *ptr) case TIR_S_C_CTL_STLOC: /* Set location: pop index, restore location counter from index arg: none. */ - dummy = _bfd_vms_pop (abfd, (int *) &psect); + dummy = _bfd_vms_pop (abfd, &psect); (*_bfd_error_handler) (_("%s: not fully implemented"), tir_cmd_name (ptr[-1])); break; @@ -1500,7 +1684,7 @@ tir_ctl (bfd * abfd, unsigned char *ptr) case TIR_S_C_CTL_STKDL: /* Stack defined location: pop index, push location counter from index arg: none. */ - dummy = _bfd_vms_pop (abfd, (int *) &psect); + dummy = _bfd_vms_pop (abfd, &psect); (*_bfd_error_handler) (_("%s: not fully implemented"), tir_cmd_name (ptr[-1])); break; @@ -1517,7 +1701,7 @@ tir_ctl (bfd * abfd, unsigned char *ptr) static unsigned char * tir_cmd (bfd * abfd, unsigned char *ptr) { - struct + static const struct { int mincod; int maxcod; @@ -1535,7 +1719,7 @@ tir_cmd (bfd * abfd, unsigned char *ptr) #if VMS_DEBUG _bfd_vms_debug (4, "tir_cmd %d/%x\n", *ptr, *ptr); - _bfd_hexdump (8, ptr, 16, (int) ptr); + _bfd_hexdump (8, ptr, 16, (long) ptr); #endif if (*ptr & 0x80) @@ -1570,13 +1754,13 @@ tir_cmd (bfd * abfd, unsigned char *ptr) /* Handle command from ETIR section. */ static int -etir_cmd (bfd * abfd, int cmd, unsigned char *ptr) +etir_cmd (bfd *abfd, int cmd, unsigned char *ptr, int *quarter_relocs) { - static struct + static const struct { int mincod; int maxcod; - bfd_boolean (*explain) (bfd *, int, unsigned char *); + bfd_boolean (*explain) (bfd *, int, unsigned char *, int *); } etir_table[] = { @@ -1591,8 +1775,8 @@ etir_cmd (bfd * abfd, int cmd, unsigned char *ptr) int i = 0; #if VMS_DEBUG - _bfd_vms_debug (4, "etir_cmd %d/%x\n", cmd, cmd); - _bfd_hexdump (8, ptr, 16, (int) ptr); + _bfd_vms_debug (4, "etir_cmd: %s(%d)\n", cmd_name (cmd), cmd); + _bfd_hexdump (8, ptr, 16, (long) ptr); #endif while (etir_table[i].mincod >= 0) @@ -1600,7 +1784,7 @@ etir_cmd (bfd * abfd, int cmd, unsigned char *ptr) if ( (etir_table[i].mincod <= cmd) && (cmd <= etir_table[i].maxcod)) { - if (!etir_table[i].explain (abfd, cmd, ptr)) + if (!etir_table[i].explain (abfd, cmd, ptr, quarter_relocs)) return -1; break; } @@ -1608,7 +1792,7 @@ etir_cmd (bfd * abfd, int cmd, unsigned char *ptr) } #if VMS_DEBUG - _bfd_vms_debug (4, "etir_cmd: = 0\n"); + _bfd_vms_debug (4, "etir_cmd: result = 0\n"); #endif return 0; } @@ -1643,28 +1827,67 @@ analyze_tir (bfd * abfd, unsigned char *ptr, unsigned int length) static int analyze_etir (bfd * abfd, unsigned char *ptr, unsigned int length) { - int cmd; - unsigned char *maxptr; + unsigned char *maxptr = ptr + length; + /* Relocations are made of 1, 2 or 4 ETIR commands. + We therefore count them using quarters. */ + int quarter_relocs = 0; int result = 0; #if VMS_DEBUG _bfd_vms_debug (3, "analyze_etir: %d bytes\n", length); #endif - maxptr = ptr + length; - while (ptr < maxptr) { - cmd = bfd_getl16 (ptr); - length = bfd_getl16 (ptr + 2); - result = etir_cmd (abfd, cmd, ptr+4); + int cmd = bfd_getl16 (ptr); + int cmd_length = bfd_getl16 (ptr + 2); + result = etir_cmd (abfd, cmd, ptr + 4, &quarter_relocs); if (result != 0) break; - ptr += length; + + /* If we have a relocation, we record its length to size + future buffers and bump the reloc count of the section. */ + if (quarter_relocs) + { + vms_section_data (PRIV (image_section))->reloc_size += cmd_length; + abfd->flags |= HAS_RELOC; + + if (quarter_relocs == 4) + { + PRIV (image_section)->reloc_count++; + +#if VMS_DEBUG + _bfd_vms_debug (4, "-> reloc %d at 0x%x\n", + PRIV (image_section)->reloc_count-1, + ptr - (maxptr - length)); +#endif + + quarter_relocs = 0; + } + else if (quarter_relocs > 4) + { + +#if VMS_DEBUG + _bfd_vms_debug (4, "Reloc count error (%d) in section %s\n", + PRIV (image_section)->reloc_count, + PRIV (image_section)->name); +#endif + + quarter_relocs = 0; + } + } + + /* If we have a Store Immediate, we reserve space for the + count argument. */ + else if (cmd == ETIR_S_C_STO_IMM) + vms_section_data (PRIV (image_section))->reloc_size + += ETIR_S_C_HEADER_SIZE + 4; + + ptr += cmd_length; } #if VMS_DEBUG - _bfd_vms_debug (3, "analyze_etir: = %d\n", result); + _bfd_vms_debug (3, "analyze_etir: result = %d\n", result); #endif return result; @@ -1685,8 +1908,8 @@ _bfd_vms_slurp_tir (bfd * abfd, int objtype) switch (objtype) { case EOBJ_S_C_ETIR: - PRIV (vms_rec) += 4; /* Skip type, size. */ - PRIV (rec_size) -= 4; + PRIV (vms_rec) += ETIR_S_C_HEADER_SIZE; + PRIV (rec_size) -= ETIR_S_C_HEADER_SIZE; result = analyze_etir (abfd, PRIV (vms_rec), (unsigned) PRIV (rec_size)); break; case OBJ_S_C_TIR: @@ -1702,33 +1925,361 @@ _bfd_vms_slurp_tir (bfd * abfd, int objtype) return result; } -/* Process EDBG record - Return 0 on success, -1 on error - - Not implemented yet. */ + /* Slurp relocs from ETIR sections and (temporarily) save them + in the per-section reloc buffer. */ int -_bfd_vms_slurp_dbg (bfd * abfd, int objtype ATTRIBUTE_UNUSED) +_bfd_vms_slurp_relocs (bfd *abfd) { + struct vms_section_data_struct *vsd; + unsigned char *begin = PRIV (vms_rec) + 4; + unsigned char *end = PRIV (vms_rec) + PRIV (rec_size); + unsigned char *ptr; + int cmd, length, slurped_length; + #if VMS_DEBUG - _bfd_vms_debug (2, "DBG/EDBG\n"); + _bfd_vms_debug (3, "_bfd_vms_slurp_relocs: %d bytes\n", PRIV (rec_size)); +#endif + + for (ptr = begin; ptr < end; ptr += length) + { + cmd = bfd_getl16 (ptr); + length = bfd_getl16 (ptr + 2); + slurped_length = length; + + switch (cmd) + { + case ETIR_S_C_STA_PQ: /* ALPHA_R_REF{LONG|QUAD}, others part 1 */ + /* This one is special as it is both part of the section header + and of the ALPHA_R_REFLONG and ALPHA_R_REFQUAD relocations. */ + if (bfd_getl16 (ptr + length) == ETIR_S_C_CTL_SETRB) + { + int psect = bfd_getl32 (ptr + ETIR_S_C_HEADER_SIZE); + PRIV (image_section) = PRIV (sections)[psect]; + continue; + } + + case ETIR_S_C_STA_GBL: /* ALPHA_R_REFLONG und_section, step 1 */ + /* ALPHA_R_REFQUAD und_section, step 1 */ + break; + + case ETIR_S_C_STA_LW: /* ALPHA_R_REFLONG und_section, step 2 */ + /* ALPHA_R_REFLONG abs_section, step 1 */ + /* This one is special as it is both part of the section header + and of the ALPHA_R_REFLONG relocation. */ + if (bfd_getl16 (ptr + length) == ETIR_S_C_CTL_DFLOC) + { + PRIV (image_section) = PRIV (dst_section); + continue; + } + + case ETIR_S_C_STA_QW: /* ALPHA_R_REFQUAD und_section, step 2 */ + /* ALPHA_R_REFQUAD abs_section, step 1 */ + + case ETIR_S_C_STO_LW: /* ALPHA_R_REFLONG und_section, step 4 */ + /* ALPHA_R_REFLONG abs_section, step 2 */ + /* ALPHA_R_REFLONG others, step 2 */ + + case ETIR_S_C_STO_QW: /* ALPHA_R_REFQUAD und_section, step 4 */ + /* ALPHA_R_REFQUAD abs_section, step 2 */ + + case ETIR_S_C_STO_OFF: /* ALPHA_R_REFQUAD others, step 2 */ + + case ETIR_S_C_OPR_ADD: /* ALPHA_R_REFLONG und_section, step 3 */ + /* ALPHA_R_REFQUAD und_section, step 3 */ + + case ETIR_S_C_STO_CA: /* ALPHA_R_CODEADDR */ + case ETIR_S_C_STO_GBL: /* ALPHA_R_REFQUAD und_section */ + case ETIR_S_C_STO_GBL_LW: /* ALPHA_R_REFLONG und_section */ + case ETIR_S_C_STC_LP_PSB: /* ALPHA_R_LINKAGE */ + case ETIR_S_C_STC_NOP_GBL: /* ALPHA_R_NOP */ + case ETIR_S_C_STC_BSR_GBL: /* ALPHA_R_BSR */ + case ETIR_S_C_STC_LDA_GBL: /* ALPHA_R_LDA */ + case ETIR_S_C_STC_BOH_GBL: /* ALPHA_R_BOH */ + break; + + case ETIR_S_C_STO_IMM: + if (PRIV (image_section)->reloc_count == 0) + continue; + /* This is not a relocation, but we nevertheless slurp the + count argument. We'll use it to compute the addresses + of the relocations. */ + slurped_length = ETIR_S_C_HEADER_SIZE + 4; + break; + + default: + continue; + } + + vsd = vms_section_data (PRIV (image_section)); + memcpy (vsd->reloc_stream + vsd->reloc_offset, ptr, slurped_length); + vsd->reloc_offset += slurped_length; + if (vsd->reloc_offset > vsd->reloc_size) + { + (*_bfd_error_handler) (_("Reloc size error in section %s"), + PRIV (image_section)->name); + return -1; + } + } + +#if VMS_DEBUG + _bfd_vms_debug (3, "_bfd_vms_slurp_relocs: result = 0\n"); #endif - abfd->flags |= (HAS_DEBUG | HAS_LINENO); return 0; } -/* Process ETBT record - Return 0 on success, -1 on error - - Not implemented yet. */ +/* Decode relocs from the reloc buffer of the specified section + and internalize them in the specified buffer. */ int -_bfd_vms_slurp_tbt (bfd * abfd ATTRIBUTE_UNUSED, - int objtype ATTRIBUTE_UNUSED) +_bfd_vms_decode_relocs (bfd *abfd, arelent *relocs, asection *section, + asymbol **symbols ATTRIBUTE_UNUSED) { + int saved_cmd, saved_sym_offset, saved_sec_offset, saved_addend_offset; + int cmd, sym_offset, sec_offset, address_offset, addend_offset; + struct vms_section_data_struct *vsd = vms_section_data (section); + bfd_reloc_code_real_type reloc_code; + vms_symbol_entry *entry; + bfd_vma vaddr = 0; + unsigned char *begin = vsd->reloc_stream; + unsigned char *end = vsd->reloc_stream + vsd->reloc_size; + unsigned char *ptr, *arg_ptr; + const char *name; + int length; + #if VMS_DEBUG - _bfd_vms_debug (2, "TBT/ETBT\n"); + _bfd_vms_debug (3, "_bfd_vms_decode_relocs: %d bytes\n", vsd->reloc_size); +#endif + + #define PUSH_CMD() \ + { \ + saved_cmd = cmd; \ + saved_sym_offset = sym_offset - length; \ + saved_sec_offset = sec_offset - length; \ + saved_addend_offset = addend_offset - length; \ + continue; \ + } + + #define POP_CMD() \ + { \ + cmd = saved_cmd; \ + saved_cmd = ETIR_S_C_MAXSTCCOD + 1; \ + sym_offset = saved_sym_offset; \ + sec_offset = saved_sec_offset; \ + addend_offset= saved_addend_offset; \ + } + + #define CMD_PUSHED (saved_cmd != ETIR_S_C_MAXSTCCOD + 1) + + #define NO_OFFSET -128 + + saved_cmd = ETIR_S_C_MAXSTCCOD + 1; + saved_sym_offset = NO_OFFSET; + saved_sec_offset = NO_OFFSET; + saved_addend_offset = NO_OFFSET; + + for (ptr = begin; ptr < end; ptr += length) + { + cmd = bfd_getl16 (ptr); + length = bfd_getl16 (ptr + 2); + + arg_ptr = ptr + ETIR_S_C_HEADER_SIZE; + sym_offset = NO_OFFSET; + sec_offset = NO_OFFSET; + address_offset = NO_OFFSET; + addend_offset = NO_OFFSET; + + switch (cmd) + { + case ETIR_S_C_STA_GBL: /* ALPHA_R_REFLONG und_section, step 1 */ + /* ALPHA_R_REFQUAD und_section, step 1 */ + sym_offset = 0; + PUSH_CMD () + + case ETIR_S_C_STA_PQ: /* ALPHA_R_REF{LONG|QUAD}, others part 1 */ + sec_offset = 0; + addend_offset = 4; + PUSH_CMD () + + case ETIR_S_C_STA_LW: /* ALPHA_R_REFLONG abs_section, step 1 */ + /* ALPHA_R_REFLONG und_section, step 2 */ + if (CMD_PUSHED) + { + POP_CMD () + if (cmd != ETIR_S_C_STA_GBL) + { + (*_bfd_error_handler) (_("Unknown reloc %s + %s"), + cmd_name (cmd), + cmd_name (ETIR_S_C_STA_LW)); + return 0; + } + cmd = ETIR_S_C_STA_LW; + } + addend_offset = 0; + PUSH_CMD () + + case ETIR_S_C_STA_QW: /* ALPHA_R_REFQUAD abs_section, step 1 */ + /* ALPHA_R_REFQUAD und_section, step 2 */ + if (CMD_PUSHED) + { + POP_CMD () + if (cmd != ETIR_S_C_STA_GBL) + { + (*_bfd_error_handler) (_("Unknown reloc %s + %s"), + cmd_name (cmd), + cmd_name (ETIR_S_C_STA_QW)); + return 0; + } + cmd = ETIR_S_C_STA_QW; + } + addend_offset = 0; + PUSH_CMD () + + case ETIR_S_C_STO_LW: /* ALPHA_R_REFLONG und_section, step 4 */ + /* ALPHA_R_REFLONG abs_section, step 2 */ + /* ALPHA_R_REFLONG others, step 2 */ + POP_CMD () + if (cmd != ETIR_S_C_OPR_ADD + && cmd != ETIR_S_C_STA_LW + && cmd != ETIR_S_C_STA_PQ) + { + (*_bfd_error_handler) (_("Unknown reloc %s + %s"), + cmd_name (cmd), cmd_name (ETIR_S_C_STO_LW)); + return 0; + } + reloc_code = BFD_RELOC_32; + break; + + case ETIR_S_C_STO_QW: /* ALPHA_R_REFQUAD und_section, step 4 */ + /* ALPHA_R_REFQUAD abs_section, step 2 */ + POP_CMD () + if (cmd != ETIR_S_C_OPR_ADD && cmd != ETIR_S_C_STA_QW) + { + (*_bfd_error_handler) (_("Unknown reloc %s + %s"), + cmd_name (cmd), cmd_name (ETIR_S_C_STO_QW)); + return 0; + } + reloc_code = BFD_RELOC_64; + break; + + case ETIR_S_C_STO_OFF: /* ALPHA_R_REFQUAD others, step 2 */ + POP_CMD () + if (cmd != ETIR_S_C_STA_PQ) + { + (*_bfd_error_handler) (_("Unknown reloc %s + %s"), + cmd_name (cmd), cmd_name (ETIR_S_C_STO_OFF)); + return 0; + } + reloc_code = BFD_RELOC_64; + break; + + case ETIR_S_C_OPR_ADD: /* ALPHA_R_REFLONG und_section, step 3 */ + /* ALPHA_R_REFQUAD und_section, step 3 */ + POP_CMD () + if (cmd != ETIR_S_C_STA_LW && cmd != ETIR_S_C_STA_QW) + { + (*_bfd_error_handler) (_("Unknown reloc %s + %s"), + cmd_name (cmd), cmd_name (ETIR_S_C_OPR_ADD)); + return 0; + } + cmd = ETIR_S_C_OPR_ADD; + PUSH_CMD () + + case ETIR_S_C_STO_CA: /* ALPHA_R_CODEADDR */ + reloc_code = BFD_RELOC_ALPHA_CODEADDR; + sym_offset = 0; + break; + + case ETIR_S_C_STO_GBL: /* ALPHA_R_REFQUAD und_section */ + reloc_code = BFD_RELOC_64; + sym_offset = 0; + break; + + case ETIR_S_C_STO_GBL_LW: /* ALPHA_R_REFLONG und_section */ + reloc_code = BFD_RELOC_32; + sym_offset = 0; + break; + + case ETIR_S_C_STC_LP_PSB: /* ALPHA_R_LINKAGE */ + reloc_code = BFD_RELOC_ALPHA_LINKAGE; + sym_offset = 4; + break; + + case ETIR_S_C_STC_NOP_GBL: /* ALPHA_R_NOP */ + reloc_code = BFD_RELOC_ALPHA_NOP; + goto call_reloc; + + case ETIR_S_C_STC_BSR_GBL: /* ALPHA_R_BSR */ + reloc_code = BFD_RELOC_ALPHA_BSR; + goto call_reloc; + + case ETIR_S_C_STC_LDA_GBL: /* ALPHA_R_LDA */ + reloc_code = BFD_RELOC_ALPHA_LDA; + goto call_reloc; + + case ETIR_S_C_STC_BOH_GBL: /* ALPHA_R_BOH */ + reloc_code = BFD_RELOC_ALPHA_BOH; + goto call_reloc; + + call_reloc: + sym_offset = 32; + address_offset = 8; + addend_offset = 24; + break; + + case ETIR_S_C_STO_IMM: + vaddr += bfd_getl32 (arg_ptr); + length = ETIR_S_C_HEADER_SIZE + 4; + continue; + + default: + continue; + } + + relocs->howto = bfd_reloc_type_lookup (abfd, reloc_code); + + if (sym_offset > NO_OFFSET) + { + name = _bfd_vms_save_counted_string (arg_ptr + sym_offset); + entry = (vms_symbol_entry *) + bfd_hash_lookup (PRIV (vms_symbol_table), name, FALSE, FALSE); + if (entry == NULL) + { + (*_bfd_error_handler) (_("Unknown symbol %s in command %s"), + name, cmd_name (cmd)); + relocs->sym_ptr_ptr = NULL; + } + else + /* ??? This is a hack. We should point in 'symbols'. */ + relocs->sym_ptr_ptr = &entry->symbol; + } + else if (sec_offset > NO_OFFSET) + relocs->sym_ptr_ptr + = PRIV (sections)[bfd_getl32 (arg_ptr + sec_offset)]->symbol_ptr_ptr; + else + relocs->sym_ptr_ptr = NULL; + + if (address_offset > NO_OFFSET) + relocs->address = bfd_getl64 (arg_ptr + address_offset); + else + relocs->address = vaddr; + + if (addend_offset > NO_OFFSET) + relocs->addend = bfd_getl64 (arg_ptr + addend_offset); + else + relocs->addend = 0; + + vaddr += bfd_get_reloc_size (relocs->howto); + relocs++; + } + + #undef PUSH_CMD + #undef POP_CMD + #undef NO_OFFSET + +#if VMS_DEBUG + _bfd_vms_debug (3, "_bfd_vms_decode_relocs: result = 0\n"); #endif return 0; @@ -1750,6 +2301,20 @@ _bfd_vms_slurp_lnk (bfd * abfd ATTRIBUTE_UNUSED, return 0; } +/* WRITE ETIR SECTION + + This is still under construction and therefore not documented. */ + +static void start_etir_record (bfd *abfd, int index, uquad offset, + bfd_boolean justoffset); +static void start_first_etbt_record (bfd *abfd); +static void start_another_etbt_record (bfd *abfd); +static void sto_imm (bfd *abfd, bfd_size_type, unsigned char *, bfd_vma vaddr, + int index, const char *name); +static void end_etir_record (bfd *abfd); +static void etir_output_check (bfd *abfd, asection *section, bfd_vma vaddr, + int checklen); + /* Start ETIR record for section #index at virtual addr offset. */ static void @@ -1780,25 +2345,20 @@ end_etir_record (bfd * abfd) _bfd_vms_output_end (abfd); } -/* WRITE ETIR SECTION - - This is still under construction and therefore not documented. */ +/* Output a STO_IMM command for SSIZE bytes of data from CPR at virtual + address VADDR in section specified by INDEX and NAME. */ static void -sto_imm (bfd * abfd, vms_section *sptr, bfd_vma vaddr, int index) +sto_imm (bfd *abfd, bfd_size_type ssize, unsigned char *cptr, bfd_vma vaddr, + int index, const char *name) { - int size; - int ssize; - unsigned char *cptr; + bfd_size_type size; #if VMS_DEBUG - _bfd_vms_debug (8, "sto_imm %d bytes\n", sptr->size); - _bfd_hexdump (9, sptr->contents, (int) sptr->size, (int) vaddr); + _bfd_vms_debug (8, "sto_imm %d bytes\n", ssize); + _bfd_hexdump (9, cptr, (int) ssize, (int) vaddr); #endif - ssize = sptr->size; - cptr = sptr->contents; - while (ssize > 0) { /* Try all the rest. */ @@ -1808,11 +2368,14 @@ sto_imm (bfd * abfd, vms_section *sptr, bfd_vma vaddr, int index) { /* Doesn't fit, split ! */ end_etir_record (abfd); - start_etir_record (abfd, index, vaddr, FALSE); - /* Get max size. */ - size = _bfd_vms_output_check (abfd, 0); - /* More than what's left ? */ - if (size > ssize) + + if (name [0] && name[1] == 'v' && !strcmp (name, ".vmsdebug")) + start_another_etbt_record (abfd); + else + start_etir_record (abfd, index, vaddr, FALSE); + + size = _bfd_vms_output_check (abfd, 0); /* get max size */ + if (size > ssize) /* more than what's left ? */ size = ssize; } @@ -1827,8 +2390,63 @@ sto_imm (bfd * abfd, vms_section *sptr, bfd_vma vaddr, int index) #endif vaddr += size; - ssize -= size; cptr += size; + ssize -= size; + } +} + +/* Start ETBT record for section #index at virtual addr offset. */ + +static void +start_first_etbt_record (bfd *abfd) +{ + _bfd_vms_output_begin (abfd, EOBJ_S_C_ETBT, -1); + _bfd_vms_output_push (abfd); + + _bfd_vms_output_begin (abfd, ETIR_S_C_STA_LW, -1); /* push start offset */ + _bfd_vms_output_long (abfd, (unsigned long) 0); + _bfd_vms_output_flush (abfd); + + _bfd_vms_output_begin (abfd, ETIR_S_C_CTL_DFLOC, -1); /* start = pop() */ + _bfd_vms_output_flush (abfd); +} + +static void +start_another_etbt_record (bfd *abfd) +{ + _bfd_vms_output_begin (abfd, EOBJ_S_C_ETBT, -1); + _bfd_vms_output_push (abfd); +} + +static void +etir_output_check (bfd *abfd, asection *section, bfd_vma vaddr, int checklen) +{ + if (_bfd_vms_output_check (abfd, checklen) < 0) + { + end_etir_record (abfd); + if (section->name[0] && section->name[1] == 'v' + && !strcmp (section->name, ".vmsdebug")) + start_another_etbt_record (abfd); + else + start_etir_record (abfd, section->index, vaddr, FALSE); + } +} + +/* Return whether RELOC must be deferred till the end. */ + +static int +defer_reloc_p (arelent *reloc) +{ + switch (reloc->howto->type) + { + case ALPHA_R_NOP: + case ALPHA_R_LDA: + case ALPHA_R_BSR: + case ALPHA_R_BOH: + return 1; + + default: + return 0; } } @@ -1838,8 +2456,6 @@ int _bfd_vms_write_tir (bfd * abfd, int objtype ATTRIBUTE_UNUSED) { asection *section; - vms_section *sptr; - int nextoffset; #if VMS_DEBUG _bfd_vms_debug (2, "vms_write_tir (%p, %d)\n", abfd, objtype); @@ -1847,391 +2463,346 @@ _bfd_vms_write_tir (bfd * abfd, int objtype ATTRIBUTE_UNUSED) _bfd_vms_output_alignment (abfd, 4); - nextoffset = 0; PRIV (vms_linkage_index) = 1; - /* Dump all other sections. */ - section = abfd->sections; - - while (section != NULL) + for (section = abfd->sections; section; section = section->next) { - #if VMS_DEBUG _bfd_vms_debug (4, "writing %d. section '%s' (%d bytes)\n", section->index, section->name, (int) (section->size)); #endif + if (!(section->flags & SEC_HAS_CONTENTS) + || bfd_is_com_section (section)) + continue; + + if (!section->contents) + { + bfd_set_error (bfd_error_no_contents); + return -1; + } + + if (section->name[0] + && section->name[1] == 'v' + && !strcmp (section->name, ".vmsdebug")) + start_first_etbt_record (abfd); + else + start_etir_record (abfd, section->index, 0, FALSE); + if (section->flags & SEC_RELOC) { - int i; + bfd_vma curr_addr = 0; + unsigned char *curr_data = section->contents; + bfd_size_type size; + int pass2_needed = 0; + int pass2_in_progress = 0; + unsigned int irel; + + if (section->reloc_count <= 0) + (*_bfd_error_handler) + (_("SEC_RELOC with no relocs in section %s"), section->name); - if ((i = section->reloc_count) <= 0) - (*_bfd_error_handler) (_("SEC_RELOC with no relocs in section %s"), - section->name); #if VMS_DEBUG else { - arelent **rptr; + int i = section->reloc_count; + arelent **rptr = section->orelocation; _bfd_vms_debug (4, "%d relocations:\n", i); - rptr = section->orelocation; while (i-- > 0) { - _bfd_vms_debug (4, "sym %s in sec %s, value %08lx, addr %08lx, off %08lx, len %d: %s\n", + _bfd_vms_debug (4, "sym %s in sec %s, value %08lx, " + "addr %08lx, off %08lx, len %d: %s\n", (*(*rptr)->sym_ptr_ptr)->name, (*(*rptr)->sym_ptr_ptr)->section->name, (long) (*(*rptr)->sym_ptr_ptr)->value, (*rptr)->address, (*rptr)->addend, bfd_get_reloc_size ((*rptr)->howto), - (*rptr)->howto->name); + ( *rptr)->howto->name); rptr++; } } #endif - } - if ((section->flags & SEC_HAS_CONTENTS) - && (! bfd_is_com_section (section))) - { - /* Virtual addr in section. */ - bfd_vma vaddr; - - sptr = _bfd_get_vms_section (abfd, section->index); - if (sptr == NULL) + new_pass: + for (irel = 0; irel < section->reloc_count; irel++) { - bfd_set_error (bfd_error_no_contents); - return -1; - } + struct evax_private_udata_struct *udata; + arelent *rptr = section->orelocation [irel]; + bfd_vma addr = rptr->address; + asymbol *sym = *rptr->sym_ptr_ptr; + asection *sec = sym->section; + int defer = defer_reloc_p (rptr); + unsigned int slen; + char *hash; + + if (pass2_in_progress) + { + /* Non-deferred relocs have already been output. */ + if (!defer) + continue; + } + else + { + /* Deferred relocs must be output at the very end. */ + if (defer) + { + pass2_needed = 1; + continue; + } - vaddr = (bfd_vma) (sptr->offset); + /* Regular relocs are intertwined with binary data. */ + if (curr_addr > addr) + (*_bfd_error_handler) (_("Size error in section %s"), + section->name); + size = addr - curr_addr; + sto_imm (abfd, size, curr_data, curr_addr, + section->index, section->name); + curr_data += size; + curr_addr += size; + } - start_etir_record (abfd, section->index, (uquad) sptr->offset, - FALSE); + size = bfd_get_reloc_size (rptr->howto); - while (sptr != NULL) - { - /* One STA_PQ, CTL_SETRB per vms_section. */ - if (section->flags & SEC_RELOC) - { - /* Check for relocs. */ - arelent **rptr = section->orelocation; - int i = section->reloc_count; + switch (rptr->howto->type) + { + case ALPHA_R_IGNORE: + break; - for (;;) + case ALPHA_R_REFLONG: + if (bfd_is_und_section (sym->section)) { - bfd_size_type addr = (*rptr)->address; - bfd_size_type len = bfd_get_reloc_size ((*rptr)->howto); - if (sptr->offset < addr) - { - /* Sptr starts before reloc. */ - bfd_size_type before = addr - sptr->offset; - if (sptr->size <= before) - { - /* Complete before. */ - sto_imm (abfd, sptr, vaddr, section->index); - vaddr += sptr->size; - break; - } - else - { - /* Partly before. */ - int after = sptr->size - before; - - sptr->size = before; - sto_imm (abfd, sptr, vaddr, section->index); - vaddr += sptr->size; - sptr->contents += before; - sptr->offset += before; - sptr->size = after; - } - } - else if (sptr->offset == addr) + bfd_vma addend = rptr->addend; + slen = strlen ((char *) sym->name); + hash = _bfd_vms_length_hash_symbol + (abfd, sym->name, EOBJ_S_C_SYMSIZ); + etir_output_check (abfd, section, curr_addr, slen); + if (addend) { - /* Sptr starts at reloc. */ - asymbol *sym = *(*rptr)->sym_ptr_ptr; - asection *sec = sym->section; - - switch ((*rptr)->howto->type) - { - case ALPHA_R_IGNORE: - break; - - case ALPHA_R_REFLONG: - { - if (bfd_is_und_section (sym->section)) - { - int slen = strlen ((char *) sym->name); - char *hash; - - if (_bfd_vms_output_check (abfd, slen) < 0) - { - end_etir_record (abfd); - start_etir_record (abfd, - section->index, - vaddr, FALSE); - } - _bfd_vms_output_begin (abfd, - ETIR_S_C_STO_GBL_LW, - -1); - hash = (_bfd_vms_length_hash_symbol - (abfd, sym->name, EOBJ_S_C_SYMSIZ)); - _bfd_vms_output_counted (abfd, hash); - _bfd_vms_output_flush (abfd); - } - else if (bfd_is_abs_section (sym->section)) - { - if (_bfd_vms_output_check (abfd, 16) < 0) - { - end_etir_record (abfd); - start_etir_record (abfd, - section->index, - vaddr, FALSE); - } - _bfd_vms_output_begin (abfd, - ETIR_S_C_STA_LW, - -1); - _bfd_vms_output_quad (abfd, - (uquad) sym->value); - _bfd_vms_output_flush (abfd); - _bfd_vms_output_begin (abfd, - ETIR_S_C_STO_LW, - -1); - _bfd_vms_output_flush (abfd); - } - else - { - if (_bfd_vms_output_check (abfd, 32) < 0) - { - end_etir_record (abfd); - start_etir_record (abfd, - section->index, - vaddr, FALSE); - } - _bfd_vms_output_begin (abfd, - ETIR_S_C_STA_PQ, - -1); - _bfd_vms_output_long (abfd, - (unsigned long) (sec->index)); - _bfd_vms_output_quad (abfd, - ((uquad) (*rptr)->addend - + (uquad) sym->value)); - _bfd_vms_output_flush (abfd); - _bfd_vms_output_begin (abfd, - ETIR_S_C_STO_LW, - -1); - _bfd_vms_output_flush (abfd); - } - } - break; - - case ALPHA_R_REFQUAD: - { - if (bfd_is_und_section (sym->section)) - { - int slen = strlen ((char *) sym->name); - char *hash; - - if (_bfd_vms_output_check (abfd, slen) < 0) - { - end_etir_record (abfd); - start_etir_record (abfd, - section->index, - vaddr, FALSE); - } - _bfd_vms_output_begin (abfd, - ETIR_S_C_STO_GBL, - -1); - hash = (_bfd_vms_length_hash_symbol - (abfd, sym->name, EOBJ_S_C_SYMSIZ)); - _bfd_vms_output_counted (abfd, hash); - _bfd_vms_output_flush (abfd); - } - else if (bfd_is_abs_section (sym->section)) - { - if (_bfd_vms_output_check (abfd, 16) < 0) - { - end_etir_record (abfd); - start_etir_record (abfd, - section->index, - vaddr, FALSE); - } - _bfd_vms_output_begin (abfd, - ETIR_S_C_STA_QW, - -1); - _bfd_vms_output_quad (abfd, - (uquad) sym->value); - _bfd_vms_output_flush (abfd); - _bfd_vms_output_begin (abfd, - ETIR_S_C_STO_QW, - -1); - _bfd_vms_output_flush (abfd); - } - else - { - if (_bfd_vms_output_check (abfd, 32) < 0) - { - end_etir_record (abfd); - start_etir_record (abfd, - section->index, - vaddr, FALSE); - } - _bfd_vms_output_begin (abfd, - ETIR_S_C_STA_PQ, - -1); - _bfd_vms_output_long (abfd, - (unsigned long) (sec->index)); - _bfd_vms_output_quad (abfd, - ((uquad) (*rptr)->addend - + (uquad) sym->value)); - _bfd_vms_output_flush (abfd); - _bfd_vms_output_begin (abfd, - ETIR_S_C_STO_OFF, - -1); - _bfd_vms_output_flush (abfd); - } - } - break; - - case ALPHA_R_HINT: - { - int hint_size; - char *hash ATTRIBUTE_UNUSED; - - hint_size = sptr->size; - sptr->size = len; - sto_imm (abfd, sptr, vaddr, section->index); - sptr->size = hint_size; - } - break; - case ALPHA_R_LINKAGE: - { - char *hash; - - if (_bfd_vms_output_check (abfd, 64) < 0) - { - end_etir_record (abfd); - start_etir_record (abfd, section->index, - vaddr, FALSE); - } - _bfd_vms_output_begin (abfd, - ETIR_S_C_STC_LP_PSB, - -1); - _bfd_vms_output_long (abfd, - (unsigned long) PRIV (vms_linkage_index)); - PRIV (vms_linkage_index) += 2; - hash = (_bfd_vms_length_hash_symbol - (abfd, sym->name, EOBJ_S_C_SYMSIZ)); - _bfd_vms_output_counted (abfd, hash); - _bfd_vms_output_byte (abfd, 0); - _bfd_vms_output_flush (abfd); - } - break; - - case ALPHA_R_CODEADDR: - { - int slen = strlen ((char *) sym->name); - char *hash; - if (_bfd_vms_output_check (abfd, slen) < 0) - { - end_etir_record (abfd); - start_etir_record (abfd, - section->index, - vaddr, FALSE); - } - _bfd_vms_output_begin (abfd, - ETIR_S_C_STO_CA, - -1); - hash = (_bfd_vms_length_hash_symbol - (abfd, sym->name, EOBJ_S_C_SYMSIZ)); - _bfd_vms_output_counted (abfd, hash); - _bfd_vms_output_flush (abfd); - } - break; - - default: - (*_bfd_error_handler) (_("Unhandled relocation %s"), - (*rptr)->howto->name); - break; - } - - vaddr += len; - - if (len == sptr->size) - { - break; - } - else - { - sptr->contents += len; - sptr->offset += len; - sptr->size -= len; - i--; - rptr++; - } + _bfd_vms_output_begin (abfd, ETIR_S_C_STA_GBL, -1); + _bfd_vms_output_counted (abfd, hash); + _bfd_vms_output_flush (abfd); + _bfd_vms_output_begin (abfd, ETIR_S_C_STA_LW, -1); + _bfd_vms_output_long (abfd, (unsigned long) addend); + _bfd_vms_output_flush (abfd); + _bfd_vms_output_begin (abfd, ETIR_S_C_OPR_ADD, -1); + _bfd_vms_output_flush (abfd); + _bfd_vms_output_begin (abfd, ETIR_S_C_STO_LW, -1); + _bfd_vms_output_flush (abfd); } else { - /* Sptr starts after reloc. */ - i--; - /* Check next reloc. */ - rptr++; + _bfd_vms_output_begin (abfd, ETIR_S_C_STO_GBL_LW, -1); + _bfd_vms_output_counted (abfd, hash); + _bfd_vms_output_flush (abfd); } + } + else if (bfd_is_abs_section (sym->section)) + { + etir_output_check (abfd, section, curr_addr, 16); + _bfd_vms_output_begin (abfd, ETIR_S_C_STA_LW, -1); + _bfd_vms_output_long (abfd, (unsigned long) sym->value); + _bfd_vms_output_flush (abfd); + _bfd_vms_output_begin (abfd, ETIR_S_C_STO_LW, -1); + _bfd_vms_output_flush (abfd); + } + else + { + etir_output_check (abfd, section, curr_addr, 32); + _bfd_vms_output_begin (abfd, ETIR_S_C_STA_PQ, -1); + _bfd_vms_output_long (abfd, (unsigned long) sec->index); + _bfd_vms_output_quad (abfd, (uquad) rptr->addend + + (uquad) sym->value); + _bfd_vms_output_flush (abfd); + /* ??? Table B-8 of the OpenVMS Linker Utilily Manual + says that we should have a ETIR_S_C_STO_OFF here. + But the relocation would not be BFD_RELOC_32 then. + This case is very likely unreachable. */ + _bfd_vms_output_begin (abfd, ETIR_S_C_STO_LW, -1); + _bfd_vms_output_flush (abfd); + } + break; - if (i == 0) + case ALPHA_R_REFQUAD: + if (bfd_is_und_section (sym->section)) + { + bfd_vma addend = rptr->addend; + slen = strlen ((char *) sym->name); + hash = _bfd_vms_length_hash_symbol + (abfd, sym->name, EOBJ_S_C_SYMSIZ); + etir_output_check (abfd, section, curr_addr, slen); + if (addend) + { + _bfd_vms_output_begin (abfd, ETIR_S_C_STA_GBL, -1); + _bfd_vms_output_counted (abfd, hash); + _bfd_vms_output_flush (abfd); + _bfd_vms_output_begin (abfd, ETIR_S_C_STA_QW, -1); + _bfd_vms_output_quad (abfd, (uquad) addend); + _bfd_vms_output_flush (abfd); + _bfd_vms_output_begin (abfd, ETIR_S_C_OPR_ADD, -1); + _bfd_vms_output_flush (abfd); + _bfd_vms_output_begin (abfd, ETIR_S_C_STO_QW, -1); + _bfd_vms_output_flush (abfd); + } + else { - /* All reloc checked. */ - if (sptr->size > 0) - { - /* Dump rest. */ - sto_imm (abfd, sptr, vaddr, section->index); - vaddr += sptr->size; - } - break; + _bfd_vms_output_begin (abfd, ETIR_S_C_STO_GBL, -1); + _bfd_vms_output_counted (abfd, hash); + _bfd_vms_output_flush (abfd); } } + else if (bfd_is_abs_section (sym->section)) + { + etir_output_check (abfd, section, curr_addr, 16); + _bfd_vms_output_begin (abfd, ETIR_S_C_STA_QW, -1); + _bfd_vms_output_quad (abfd, (uquad) sym->value); + _bfd_vms_output_flush (abfd); + _bfd_vms_output_begin (abfd, ETIR_S_C_STO_QW, -1); + _bfd_vms_output_flush (abfd); + } + else + { + etir_output_check (abfd, section, curr_addr, 32); + _bfd_vms_output_begin (abfd, ETIR_S_C_STA_PQ, -1); + _bfd_vms_output_long (abfd, (unsigned long) sec->index); + _bfd_vms_output_quad (abfd, (uquad) rptr->addend + + (uquad) sym->value); + _bfd_vms_output_flush (abfd); + _bfd_vms_output_begin (abfd, ETIR_S_C_STO_OFF, -1); + _bfd_vms_output_flush (abfd); + } + break; + + case ALPHA_R_HINT: + sto_imm (abfd, size, curr_data, curr_addr, + section->index, section->name); + break; + + case ALPHA_R_LINKAGE: + etir_output_check (abfd, section, curr_addr, 64); + _bfd_vms_output_begin (abfd, ETIR_S_C_STC_LP_PSB, -1); + _bfd_vms_output_long + (abfd, (unsigned long) PRIV (vms_linkage_index)); + PRIV (vms_linkage_index) += 2; + hash = _bfd_vms_length_hash_symbol + (abfd, sym->name, EOBJ_S_C_SYMSIZ); + _bfd_vms_output_counted (abfd, hash); + _bfd_vms_output_byte (abfd, 0); + _bfd_vms_output_flush (abfd); + break; + + case ALPHA_R_CODEADDR: + slen = strlen ((char *) sym->name); + hash = _bfd_vms_length_hash_symbol + (abfd, sym->name, EOBJ_S_C_SYMSIZ); + etir_output_check (abfd, section, curr_addr, slen); + _bfd_vms_output_begin (abfd, ETIR_S_C_STO_CA, -1); + _bfd_vms_output_counted (abfd, hash); + _bfd_vms_output_flush (abfd); + break; + + case ALPHA_R_NOP: + udata + = (struct evax_private_udata_struct *) rptr->sym_ptr_ptr; + etir_output_check (abfd, section, curr_addr, + 32 + 1 + strlen (udata->origname)); + _bfd_vms_output_begin (abfd, ETIR_S_C_STC_NOP_GBL, -1); + _bfd_vms_output_long (abfd, (unsigned long) udata->lkindex); + _bfd_vms_output_long + (abfd, (unsigned long) udata->enbsym->section->index); + _bfd_vms_output_quad (abfd, (uquad) rptr->address); + _bfd_vms_output_long (abfd, (unsigned long) 0x47ff041f); + _bfd_vms_output_long + (abfd, (unsigned long) udata->enbsym->section->index); + _bfd_vms_output_quad (abfd, (uquad) rptr->addend); + _bfd_vms_output_counted + (abfd, _bfd_vms_length_hash_symbol + (abfd, udata->origname, EOBJ_S_C_SYMSIZ)); + _bfd_vms_output_flush (abfd); + break; + + case ALPHA_R_BSR: + (*_bfd_error_handler) (_("Spurious ALPHA_R_BSR reloc")); + break; + + case ALPHA_R_LDA: + udata + = (struct evax_private_udata_struct *) rptr->sym_ptr_ptr; + etir_output_check (abfd, section, curr_addr, + 32 + 1 + strlen (udata->origname)); + _bfd_vms_output_begin (abfd, ETIR_S_C_STC_LDA_GBL, -1); + _bfd_vms_output_long + (abfd, (unsigned long) udata->lkindex + 1); + _bfd_vms_output_long + (abfd, (unsigned long) udata->enbsym->section->index); + _bfd_vms_output_quad (abfd, (uquad) rptr->address); + _bfd_vms_output_long (abfd, (unsigned long) 0x237B0000); + _bfd_vms_output_long + (abfd, (unsigned long) udata->bsym->section->index); + _bfd_vms_output_quad (abfd, (uquad) rptr->addend); + _bfd_vms_output_counted + (abfd, _bfd_vms_length_hash_symbol + (abfd, udata->origname, EOBJ_S_C_SYMSIZ)); + _bfd_vms_output_flush (abfd); + break; + + case ALPHA_R_BOH: + udata + = (struct evax_private_udata_struct *) rptr->sym_ptr_ptr; + etir_output_check (abfd, section, curr_addr, + 32 + 1 + strlen (udata->origname)); + _bfd_vms_output_begin (abfd, ETIR_S_C_STC_BOH_GBL, -1); + _bfd_vms_output_long (abfd, (unsigned long) udata->lkindex); + _bfd_vms_output_long + (abfd, (unsigned long) udata->enbsym->section->index); + _bfd_vms_output_quad (abfd, (uquad) rptr->address); + _bfd_vms_output_long (abfd, (unsigned long) 0xD3400000); + _bfd_vms_output_long + (abfd, (unsigned long) udata->enbsym->section->index); + _bfd_vms_output_quad (abfd, (uquad) rptr->addend); + _bfd_vms_output_counted + (abfd, _bfd_vms_length_hash_symbol + (abfd, udata->origname, EOBJ_S_C_SYMSIZ)); + _bfd_vms_output_flush (abfd); + break; + + default: + (*_bfd_error_handler) (_("Unhandled relocation %s"), + rptr->howto->name); + break; } - else + + curr_data += size; + curr_addr += size; + } /* End of relocs loop. */ + + if (!pass2_in_progress) + { + /* Output rest of section. */ + if (curr_addr > section->size) + (*_bfd_error_handler) (_("Size error in section %s"), + section->name); + size = section->size - curr_addr; + sto_imm (abfd, size, curr_data, curr_addr, + section->index, section->name); + curr_data += size; + curr_addr += size; + + if (pass2_needed) { - /* No relocs, just dump. */ - sto_imm (abfd, sptr, vaddr, section->index); - vaddr += sptr->size; + pass2_in_progress = 1; + goto new_pass; } - - sptr = sptr->next; } - - end_etir_record (abfd); } + + else /* (section->flags & SEC_RELOC) */ + sto_imm (abfd, section->size, section->contents, 0, + section->index, section->name); - section = section->next; + end_etir_record (abfd); } _bfd_vms_output_alignment (abfd, 2); return 0; } - -/* Write traceback data for bfd abfd. */ - -int -_bfd_vms_write_tbt (bfd * abfd ATTRIBUTE_UNUSED, - int objtype ATTRIBUTE_UNUSED) -{ -#if VMS_DEBUG - _bfd_vms_debug (2, "vms_write_tbt (%p, %d)\n", abfd, objtype); -#endif - - return 0; -} - -/* Write debug info for bfd abfd. */ - -int -_bfd_vms_write_dbg (bfd * abfd ATTRIBUTE_UNUSED, - int objtype ATTRIBUTE_UNUSED) -{ -#if VMS_DEBUG - _bfd_vms_debug (2, "vms_write_dbg (%p, objtype)\n", abfd, objtype); -#endif - - return 0; -} @@ -1,7 +1,9 @@ /* vms.c -- BFD back-end for VAX (openVMS/VAX) and EVAX (openVMS/Alpha) files. Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, - 2006, 2007, 2008 Free Software Foundation, Inc. + 2006, 2007, 2008, 2009 Free Software Foundation, Inc. + + Main file. Written by Klaus K"ampf (kkaempf@rmi.de) @@ -20,6 +22,13 @@ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ +#ifdef VMS +#include <rms.h> +#include <starlet.h> +#define RME$C_SETRFM 0x00000001 +#include <unistd.h> +#endif + #include "sysdep.h" #include "bfd.h" #include "bfdlink.h" @@ -27,6 +36,108 @@ #include "vms.h" +static bfd_boolean vms_initialize (bfd *); +static bfd_boolean fill_section_ptr (struct bfd_hash_entry *, PTR); +static bfd_boolean vms_fixup_sections (bfd *); +static bfd_boolean copy_symbols (struct bfd_hash_entry *, PTR); +static bfd_reloc_status_type reloc_nil (bfd *, arelent *, asymbol *, PTR, + asection *, bfd *, char **); +static int vms_slurp_module (bfd *abfd); +static int vms_slurp_image (bfd *abfd); +static const struct bfd_target *vms_object_p (bfd *abfd); +static const struct bfd_target *vms_archive_p (bfd *abfd); +static bfd_boolean vms_mkobject (bfd *abfd); +static bfd_boolean vms_write_object_contents (bfd *abfd); +static void free_reloc_stream (bfd *abfd, asection *section, void *data); +static bfd_boolean vms_close_and_cleanup (bfd *abfd); +static bfd_boolean vms_bfd_free_cached_info (bfd *abfd); +static bfd_boolean vms_new_section_hook (bfd *abfd, asection *section); +static bfd_boolean vms_get_section_contents + (bfd *abfd, asection *section, PTR x1, file_ptr x2, bfd_size_type x3); +static bfd_boolean vms_get_section_contents_in_window + (bfd *abfd, asection *section, bfd_window *w, file_ptr offset, + bfd_size_type count); +static bfd_boolean vms_bfd_copy_private_bfd_data (bfd *src, bfd *dest); +static bfd_boolean vms_bfd_copy_private_section_data + (bfd *srcbfd, asection *srcsec, bfd *dstbfd, asection *dstsec); +static bfd_boolean vms_bfd_copy_private_symbol_data + (bfd *ibfd, asymbol *isym, bfd *obfd, asymbol *osym); +static bfd_boolean vms_bfd_print_private_bfd_data (bfd *abfd, void *file); +static char *vms_core_file_failing_command (bfd *abfd); +static int vms_core_file_failing_signal (bfd *abfd); +static bfd_boolean vms_core_file_matches_executable_p (bfd *abfd, bfd *bbfd); +static bfd_boolean vms_slurp_armap (bfd *abfd); +static bfd_boolean vms_slurp_extended_name_table (bfd *abfd); +static bfd_boolean vms_construct_extended_name_table + (bfd *abfd, char **tabloc, bfd_size_type *tablen, const char **name); +static void vms_truncate_arname (bfd *abfd, const char *pathname, char *arhdr); +static bfd_boolean vms_write_armap + (bfd *arch, unsigned int elen, struct orl *map, unsigned int cnt, int idx); +static PTR vms_read_ar_hdr (bfd *abfd); +static bfd *vms_get_elt_at_index (bfd *abfd, symindex index); +static bfd *vms_openr_next_archived_file (bfd *arch, bfd *prev); +static bfd_boolean vms_update_armap_timestamp (bfd *abfd); +static int vms_generic_stat_arch_elt (bfd *, struct stat *); +static long vms_get_symtab_upper_bound (bfd *abfd); +static long vms_canonicalize_symtab (bfd *abfd, asymbol **symbols); +static void vms_print_symbol (bfd *abfd, PTR file, asymbol *symbol, + bfd_print_symbol_type how); +static void vms_get_symbol_info (bfd *abfd, asymbol *symbol, symbol_info *ret); +static bfd_boolean vms_bfd_is_local_label_name (bfd *abfd, const char *); +static alent *vms_get_lineno (bfd *abfd, asymbol *symbol); +static bfd_boolean vms_find_nearest_line + (bfd *abfd, asection *section, asymbol **symbols, bfd_vma offset, + const char **file, const char **func, unsigned int *line); +static asymbol *vms_bfd_make_debug_symbol (bfd *abfd, void *ptr, + unsigned long size); +static long vms_read_minisymbols (bfd *abfd, bfd_boolean dynamic, + PTR *minisymsp, unsigned int *sizep); +static asymbol *vms_minisymbol_to_symbol + (bfd *abfd, bfd_boolean dynamic, const PTR minisym, asymbol *sym); +static void alloc_reloc_stream (bfd *abfd, asection *section, + void *alloc_error); +static bfd_boolean vms_slurp_reloc_table (bfd *abfd, asection *section, + asymbol **symbols); +static long vms_get_reloc_upper_bound (bfd *abfd, asection *sect); +static long vms_canonicalize_reloc (bfd *abfd, asection *srcsec, + arelent **location, asymbol **symbols); +static const struct reloc_howto_struct *vms_bfd_reloc_type_lookup + (bfd *abfd, bfd_reloc_code_real_type code); +static bfd_boolean vms_set_arch_mach + (bfd *abfd, enum bfd_architecture arch, unsigned long mach); +static bfd_boolean vms_set_section_contents + (bfd *abfd, asection *section, const PTR location, file_ptr offset, + bfd_size_type count); +static int vms_sizeof_headers (bfd *abfd, + struct bfd_link_info *info ATTRIBUTE_UNUSED); +static bfd_byte *vms_bfd_get_relocated_section_contents + (bfd *abfd, struct bfd_link_info *link_info, + struct bfd_link_order *link_order, bfd_byte *data, + bfd_boolean relocatable, asymbol **symbols); +static bfd_boolean vms_bfd_relax_section + (bfd *abfd, asection *section, struct bfd_link_info *link_info, + bfd_boolean *again); +static bfd_boolean vms_bfd_gc_sections + (bfd *abfd, struct bfd_link_info *link_info); +static bfd_boolean vms_bfd_merge_sections + (bfd *abfd, struct bfd_link_info *link_info); +static struct bfd_link_hash_table *vms_bfd_link_hash_table_create (bfd *abfd); +static void vms_bfd_link_hash_table_free (struct bfd_link_hash_table *hash); +static bfd_boolean vms_bfd_link_add_symbols + (bfd *abfd, struct bfd_link_info *link_info); +static bfd_boolean vms_bfd_final_link (bfd *abfd, + struct bfd_link_info *link_info); +static bfd_boolean vms_bfd_link_split_section (bfd *abfd, asection *section); +static long vms_get_dynamic_symtab_upper_bound (bfd *abfd); +static long vms_canonicalize_dynamic_symtab + (bfd *abfd, asymbol **symbols); +#define vms_get_synthetic_symtab _bfd_nodynamic_get_synthetic_symtab +static long vms_get_dynamic_reloc_upper_bound (bfd *abfd); +static long vms_canonicalize_dynamic_reloc + (bfd *abfd, arelent **arel, asymbol **symbols); +static bfd_boolean vms_bfd_merge_private_bfd_data (bfd *ibfd, bfd *obfd); +static bfd_boolean vms_bfd_set_private_flags (bfd *abfd, flagword flags); + #define vms_bfd_is_target_special_symbol ((bfd_boolean (*) (bfd *, asymbol *)) bfd_false) #define vms_make_empty_symbol _bfd_generic_make_empty_symbol #define vms_bfd_link_just_syms _bfd_generic_link_just_syms @@ -36,42 +147,38 @@ #define vms_bfd_copy_private_header_data _bfd_generic_bfd_copy_private_header_data #define vms_get_synthetic_symtab _bfd_nodynamic_get_synthetic_symtab -static unsigned int priv_section_count; + +#ifdef VMS_DEBUG +/* Cause debug info to be emitted for the structure. */ +struct vms_private_data_struct _vms_private_data_struct_dummy; +struct vms_section_data_struct _vms_section_data_struct_dummy; +#endif + extern const bfd_target vms_vax_vec; extern const bfd_target vms_alpha_vec; - -/* Initialize private data. */ +/* Initialize private data */ static bfd_boolean vms_initialize (bfd * abfd) { - int i; bfd_size_type amt; bfd_set_start_address (abfd, (bfd_vma) -1); amt = sizeof (struct vms_private_data_struct); - abfd->tdata.any = bfd_alloc (abfd, amt); + abfd->tdata.any = bfd_zalloc (abfd, amt); if (abfd->tdata.any == NULL) return FALSE; -#ifdef __ALPHA - PRIV (is_vax) = FALSE; -#else - PRIV (is_vax) = TRUE; -#endif - PRIV (vms_buf) = NULL; - PRIV (buf_size) = 0; - PRIV (rec_length) = 0; + if (bfd_get_flavour (abfd) == bfd_target_ovax_flavour) + PRIV (is_vax) = TRUE; + PRIV (file_format) = FF_UNKNOWN; - PRIV (fixup_done) = FALSE; - PRIV (sections) = NULL; amt = sizeof (struct stack_struct) * STACKSIZE; PRIV (stack) = bfd_alloc (abfd, amt); if (PRIV (stack) == NULL) goto error_ret1; - PRIV (stackptr) = 0; amt = sizeof (struct bfd_hash_table); PRIV (vms_symbol_table) = bfd_alloc (abfd, amt); @@ -82,24 +189,12 @@ vms_initialize (bfd * abfd) sizeof (vms_symbol_entry))) goto error_ret1; - amt = sizeof (struct location_struct) * LOCATION_SAVE_SIZE; - PRIV (location_stack) = bfd_alloc (abfd, amt); - if (PRIV (location_stack) == NULL) - goto error_ret2; - - for (i = 0; i < VMS_SECTION_COUNT; i++) - PRIV (vms_section_table)[i] = NULL; - amt = MAX_OUTREC_SIZE; PRIV (output_buf) = bfd_alloc (abfd, amt); if (PRIV (output_buf) == NULL) goto error_ret2; - PRIV (push_level) = 0; - PRIV (pushed_size) = 0; PRIV (length_pos) = 2; - PRIV (output_size) = 0; - PRIV (output_alignment) = 1; return TRUE; @@ -111,154 +206,127 @@ vms_initialize (bfd * abfd) return FALSE; } -/* Fill symbol->section with section ptr +struct pair +{ + unsigned int section_count; + asection **sections; +}; + +/* Fill symbol->section with section pointer. + symbol->section is filled with the section index for defined symbols - during reading the GSD/EGSD section. But we need the pointer to the + during reading the GSD/EGSD section. But we need the pointer to the bfd section later. - It has the correct value for referenced (undefined section) symbols + It has the correct value for referenced (undefined section) symbols. - called from bfd_hash_traverse in vms_fixup_sections. */ + Called from bfd_hash_traverse in vms_fixup_sections. */ static bfd_boolean -fill_section_ptr (struct bfd_hash_entry * entry, void * sections) +fill_section_ptr (struct bfd_hash_entry *entry, void *sections) { - asection *sec; - asymbol *sym; - - sym = ((vms_symbol_entry *) entry)->symbol; - sec = sym->section; + asymbol *sym = ((vms_symbol_entry *)entry)->symbol; + struct pair *data = (struct pair *)sections; + unsigned long sec = (unsigned long)sym->section; #if VMS_DEBUG vms_debug (6, "fill_section_ptr: sym %p, sec %p\n", sym, 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; + if (sec < data->section_count) + { + sym->section = data->sections[sec]; + if (strcmp (sym->name, sym->section->name) == 0) + sym->flags |= BSF_SECTION_SYM; + } + else if (sec == (unsigned long)-1) + sym->section = &bfd_und_section; + return TRUE; } -/* Fixup sections - set up all pointers and arrays, counters and sizes are fixed now - - we build a private sections vector for easy access since sections - are always referenced by an index number. - - alloc PRIV(sections) according to abfd->section_count - copy abfd->sections to PRIV(sections). */ - +/* Fixup section pointers in symbols. */ static bfd_boolean vms_fixup_sections (bfd * abfd) { + struct pair data; + if (PRIV (fixup_done)) return TRUE; - /* Traverse symbol table and fill in all section pointers. */ - - /* Can't provide section count as argument to fill_section_ptr(). */ - priv_section_count = PRIV (section_count); - bfd_hash_traverse (PRIV (vms_symbol_table), fill_section_ptr, (PRIV (sections))); + data.section_count = PRIV (section_count); + data.sections = PRIV (sections); + bfd_hash_traverse (PRIV (vms_symbol_table), fill_section_ptr, &data); PRIV (fixup_done) = TRUE; - return TRUE; } - -/* Check the format for a file being read. - Return a (bfd_target *) if it's an object file or zero if not. */ -static const struct bfd_target * -vms_object_p (bfd * abfd) +/* Slurp an ordered set of VMS object records. */ +int +_bfd_vms_slurp_object_records (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 VMS_DEBUG - vms_debug (1, "vms_object_p (%p)\n", 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; + int err, new_type, type = -1; do { #if VMS_DEBUG vms_debug (7, "reading at %08lx\n", bfd_tell (abfd)); #endif - if (_bfd_vms_next_record (abfd) < 0) + new_type = _bfd_vms_get_object_record (abfd); + if (new_type < 0) { #if VMS_DEBUG vms_debug (2, "next_record failed\n"); #endif - goto err_wrong_format; + return -1; } - if ((prev_type == EOBJ_S_C_EGSD) - && (PRIV (rec_type) != EOBJ_S_C_EGSD)) + if (type == EOBJ_S_C_EGSD && new_type != EOBJ_S_C_EGSD) { if (! vms_fixup_sections (abfd)) { #if VMS_DEBUG vms_debug (2, "vms_fixup_sections failed\n"); #endif - goto err_wrong_format; + return -1; } } - 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; - } + type = new_type; - switch (prev_type) + switch (type) { case OBJ_S_C_HDR: case EOBJ_S_C_EMH: - err = _bfd_vms_slurp_hdr (abfd, prev_type); + err = _bfd_vms_slurp_hdr (abfd, 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); + err = _bfd_vms_slurp_eom (abfd, type); break; case OBJ_S_C_GSD: case EOBJ_S_C_EGSD: - err = _bfd_vms_slurp_gsd (abfd, prev_type); + err = _bfd_vms_slurp_gsd (abfd, type); break; case OBJ_S_C_TIR: case EOBJ_S_C_ETIR: - err = _bfd_vms_slurp_tir (abfd, prev_type); + err = _bfd_vms_slurp_tir (abfd, type); break; case OBJ_S_C_DBG: case EOBJ_S_C_EDBG: - err = _bfd_vms_slurp_dbg (abfd, prev_type); + err = _bfd_vms_slurp_dbg (abfd, type); + PRIV (dst_ptr_end) = PRIV (image_ptr); break; case OBJ_S_C_TBT: case EOBJ_S_C_ETBT: - err = _bfd_vms_slurp_tbt (abfd, prev_type); + err = _bfd_vms_slurp_tbt (abfd, type); + PRIV (dst_ptr_end) = PRIV (image_ptr); break; case OBJ_S_C_LNK: - err = _bfd_vms_slurp_lnk (abfd, prev_type); + err = _bfd_vms_slurp_lnk (abfd, type); break; default: err = -1; @@ -266,14 +334,105 @@ vms_object_p (bfd * abfd) if (err != 0) { #if VMS_DEBUG - vms_debug (2, "slurp type %d failed with %d\n", prev_type, err); + vms_debug (2, "slurp type %d failed with %d\n", type, err); #endif - goto err_wrong_format; + return err; } } - while ((prev_type != EOBJ_S_C_EEOM) && (prev_type != OBJ_S_C_EOM) && (prev_type != OBJ_S_C_EOMW)); + while (type != EOBJ_S_C_EEOM && type != OBJ_S_C_EOM && type != OBJ_S_C_EOMW); + + return 0; +} + +/* Slurp a VMS module and return an error status. */ + +static int +vms_slurp_module (bfd *abfd) +{ + int type, err; + + if (PRIV (is_vax)) + type = PRIV (vms_rec)[0]; + else + type = bfd_getl16 (PRIV (vms_rec)); + + err = _bfd_vms_slurp_hdr (abfd, type); + if (err != 0) + { + bfd_set_error (bfd_error_wrong_format); + return err; + } + + return _bfd_vms_slurp_object_records (abfd); +} + +/* Slurp a VMS image and return an error status. */ + +static int +vms_slurp_image (bfd *abfd) +{ + unsigned int isd_offset, ihs_offset; + int err; + + err = _bfd_vms_slurp_ihd (abfd, &isd_offset, &ihs_offset); + if (err != 0) + { + bfd_set_error (bfd_error_wrong_format); + return err; + } - if (target_vector == & vms_vax_vec) + err = _bfd_vms_slurp_isd (abfd, isd_offset); + if (err != 0) + { + bfd_set_error (bfd_error_wrong_format); + return err; + } + + return _bfd_vms_slurp_ihs (abfd, ihs_offset); +} + +/* Check the format for a file being read. + Return a (bfd_target *) if it's an object file or zero if not. */ + +static const struct bfd_target * +vms_object_p (bfd *abfd) +{ + const struct bfd_target *target_vector; + const bfd_arch_info_type *arch; + PTR tdata_save = abfd->tdata.any; + bfd_vma saddr_save = bfd_get_start_address (abfd); + int err = 0; + +#if VMS_DEBUG + vms_debug (1, "vms_object_p(%p)\n", abfd); +#endif + + if (!vms_initialize (abfd)) + goto error_ret; + + if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET)) + goto err_wrong_format; + + switch (_bfd_vms_get_first_record (abfd)) + { + case FT_UNKNOWN: + default: + err = -1; + break; + + case FT_MODULE: + err = vms_slurp_module (abfd); + break; + + case FT_IMAGE: + err = vms_slurp_image (abfd); + break; + } + + if (err != 0) + goto err_wrong_format; + + if (PRIV (is_vax)) { if (! vms_fixup_sections (abfd)) { @@ -283,38 +442,29 @@ vms_object_p (bfd * abfd) goto err_wrong_format; } - /* Set arch_info to vax. */ - + target_vector = &vms_vax_vec; arch = bfd_scan_arch ("vax"); - PRIV (is_vax) = TRUE; + #if VMS_DEBUG vms_debug (2, "arch is vax\n"); #endif } - else if (target_vector == & vms_alpha_vec) + else { /* Set arch_info to alpha. */ - + target_vector = &vms_alpha_vec; arch = bfd_scan_arch ("alpha"); - PRIV (is_vax) = FALSE; #if VMS_DEBUG vms_debug (2, "arch is alpha\n"); #endif } - if (arch == NULL) - { -#if 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); @@ -341,6 +491,8 @@ vms_archive_p (bfd * abfd ATTRIBUTE_UNUSED) static bfd_boolean vms_mkobject (bfd * abfd) { + const bfd_arch_info_type *arch; + #if VMS_DEBUG vms_debug (1, "vms_mkobject (%p)\n", abfd); #endif @@ -348,20 +500,18 @@ vms_mkobject (bfd * abfd) if (!vms_initialize (abfd)) return FALSE; - { -#ifdef __VAX - const bfd_arch_info_type *arch = bfd_scan_arch ("vax"); -#else - const bfd_arch_info_type *arch = bfd_scan_arch ("alpha"); -#endif - if (arch == NULL) - { - bfd_set_error (bfd_error_wrong_format); - return FALSE; - } - abfd->arch_info = arch; - } + if (PRIV (is_vax)) + arch = bfd_scan_arch ("vax"); + else + arch = bfd_scan_arch ("alpha"); + + if (arch == 0) + { + bfd_set_error(bfd_error_wrong_format); + return FALSE; + } + abfd->arch_info = arch; return TRUE; } @@ -420,6 +570,62 @@ vms_write_object_contents (bfd * abfd) /* 4.1, generic. */ +/* Free the reloc buffer for the specified section. */ + +static void +free_reloc_stream (bfd *abfd ATTRIBUTE_UNUSED, asection *section, + void *data ATTRIBUTE_UNUSED) +{ + if (vms_section_data (section)->reloc_stream) + free (vms_section_data (section)->reloc_stream); +} + +#ifdef VMS +/* Convert the file to variable record length format. This is done + using undocumented system call sys$modify(). + Pure VMS version. */ + +static void +vms_convert_to_var (char *vms_filename) +{ + struct FAB fab = cc$rms_fab; + + fab.fab$l_fna = vms_filename; + fab.fab$b_fns = strlen (vms_filename); + fab.fab$b_fac = FAB$M_PUT; + fab.fab$l_fop = FAB$M_ESC; + fab.fab$l_ctx = RME$C_SETRFM; + + sys$open (&fab); + + fab.fab$b_rfm = FAB$C_VAR; + + sys$modify (&fab); + sys$close (&fab); +} + +static int +vms_convert_to_var_1 (char *filename, int type) +{ + if (type != DECC$K_FILE) + return FALSE; + vms_convert_to_var (filename); + return TRUE; +} + +/* Convert the file to variable record length format. This is done + using undocumented system call sys$modify(). + Unix filename version. */ + +static int +vms_convert_to_var_unix_filename (const char *unix_filename) +{ + if (decc$to_vms (unix_filename, &vms_convert_to_var_1, 0, 1) != 1) + return FALSE; + return TRUE; +} +#endif /* VMS */ + /* Called when the BFD is being closed to do any necessary cleanup. */ static bfd_boolean @@ -428,8 +634,7 @@ vms_close_and_cleanup (bfd * abfd) #if VMS_DEBUG vms_debug (1, "vms_close_and_cleanup (%p)\n", abfd); #endif - if (abfd == NULL - || abfd->tdata.any == NULL) + if (abfd == NULL || abfd->tdata.any == NULL) return TRUE; if (PRIV (vms_buf) != NULL) @@ -441,9 +646,23 @@ vms_close_and_cleanup (bfd * abfd) if (PRIV (vms_symbol_table)) bfd_hash_table_free (PRIV (vms_symbol_table)); + bfd_map_over_sections (abfd, free_reloc_stream, NULL); + bfd_release (abfd, abfd->tdata.any); abfd->tdata.any = NULL; +#ifdef VMS + if (abfd->direction == write_direction) + { + /* Last step on VMS is to convert the file to variable record length + format. */ + if (bfd_cache_close (abfd) != TRUE) + return FALSE; + if (vms_convert_to_var_unix_filename (abfd->filename) != TRUE) + return FALSE; + } +#endif + return TRUE; } @@ -463,6 +682,8 @@ vms_bfd_free_cached_info (bfd * abfd ATTRIBUTE_UNUSED) static bfd_boolean vms_new_section_hook (bfd * abfd, asection *section) { + bfd_size_type amt; + /* Count hasn't been incremented yet. */ unsigned int section_count = abfd->section_count + 1; @@ -470,7 +691,8 @@ vms_new_section_hook (bfd * abfd, asection *section) vms_debug (1, "vms_new_section_hook (%p, [%d]%s), count %d\n", abfd, section->index, section->name, section_count); #endif - bfd_set_section_alignment (abfd, section, 4); + + bfd_set_section_alignment (abfd, section, 0); if (section_count > PRIV (section_count)) { @@ -481,14 +703,22 @@ vms_new_section_hook (bfd * abfd, asection *section) return FALSE; PRIV (section_count) = section_count; } + #if VMS_DEBUG vms_debug (6, "section_count: %d\n", PRIV (section_count)); #endif + PRIV (sections)[section->index] = section; + #if VMS_DEBUG vms_debug (7, "%d: %s\n", section->index, section->name); #endif + amt = sizeof (struct vms_section_data_struct); + section->used_by_bfd = (PTR) bfd_zalloc (abfd, amt); + if (section->used_by_bfd == NULL) + return FALSE; + return _bfd_generic_new_section_hook (abfd, section); } @@ -503,13 +733,42 @@ vms_get_section_contents (bfd * abfd ATTRIBUTE_UNUSED, file_ptr offset ATTRIBUTE_UNUSED, bfd_size_type buf_size ATTRIBUTE_UNUSED) { + bfd_size_type size = section->size; + #if VMS_DEBUG vms_debug (1, "vms_get_section_contents (%p, %s, %p, off %ld, size %d)\n", abfd, section->name, buf, offset, (int)buf_size); #endif - /* Shouldn't be called, since all sections are IN_MEMORY. */ - return FALSE; + if (section->contents) + abort (); + + section->contents = (unsigned char *) bfd_malloc (size); + + if (section->contents == NULL) + { + bfd_set_error (bfd_error_no_memory); + return FALSE; + } + + if (bfd_seek (abfd, section->filepos, SEEK_SET)) + { + bfd_set_error (bfd_error_file_truncated); + return FALSE; + } + + if (bfd_bread (section->contents, size, abfd) != size) + { + bfd_set_error (bfd_error_file_truncated); + return FALSE; + } + + section->flags |= SEC_IN_MEMORY; + + if (buf) + memcpy (buf, section->contents + offset, (size_t) buf_size); + + return TRUE; } /* Read the contents of a section. @@ -703,7 +962,6 @@ vms_truncate_arname (bfd * abfd ATTRIBUTE_UNUSED, #if VMS_DEBUG vms_debug (1, "vms_truncate_arname (%p, %s, %s)\n", abfd, pathname, arhdr); #endif - return; } /* ??? write archive map. */ @@ -906,7 +1164,9 @@ vms_get_symbol_info (bfd * abfd ATTRIBUTE_UNUSED, if (ret == NULL) return; - if (bfd_is_com_section (sec)) + if (sec == 0) + ret->type = 'U'; + else if (bfd_is_com_section (sec)) ret->type = 'C'; else if (bfd_is_abs_section (sec)) ret->type = 'A'; @@ -972,7 +1232,7 @@ vms_find_nearest_line (bfd * abfd ATTRIBUTE_UNUSED, vms_debug (1, "vms_find_nearest_line (%p, %s, %p, %ld, <ret>, <ret>, <ret>)\n", abfd, section->name, symbols, (long int)offset); #endif - return FALSE; + return _bfd_vms_find_nearest_dst_line (abfd, section, symbols, offset, file, func, line); } static bfd_boolean @@ -1037,36 +1297,160 @@ vms_minisymbol_to_symbol (bfd * abfd, /* Part 4.6, relocations. */ -/* Return the number of bytes required to store the relocation information - associated with section sect attached to bfd abfd. - If an error occurs, return -1. */ +/* Allocate the reloc buffer for the specified section. */ -static long -vms_get_reloc_upper_bound (bfd * abfd ATTRIBUTE_UNUSED, - asection *section ATTRIBUTE_UNUSED) +static void +alloc_reloc_stream (bfd *abfd ATTRIBUTE_UNUSED, asection *section, + void *alloc_error) { + unsigned char *ptr; + + /* If there were no relocations, there is nothing to do. */ + if (section->reloc_count == 0) + return; + + ptr = bfd_malloc (vms_section_data (section)->reloc_size); + if (ptr == NULL) + { + *(bfd_boolean *)alloc_error = TRUE; + return; + } + + vms_section_data (section)->reloc_stream = ptr; +} + +/* Read in the relocs for the specified section and internalize them. + + The implementation is loosely based on the SOM code and made up + of 3 distinct phases: + + 1. When the VMS object is opened and parsed, the number and the size + of the relocations are computed for all sections. This makes it + possible to know upfront both which sections have no relocs and + the size of the reloc buffers for the other sections, at virtually + no cost for consumers that don't care about relocs at all. + + 2. When vms_slurp_reloc_table is invoked for the first time on a section + with relocs, the object is traversed and all the reloc information + is saved in per-section reloc buffers. It would be very inefficient + to scan the whole file on each invocation, so we slurp for all the + sections at once. + + 3. On subsequent invocations of vms_slurp_reloc_table, the relocs for the + specified section are fetched from the buffer, decoded and internalized. + The buffer is then freed since the internalized relocs are attached to + the section, turning additional invocations of vms_slurp_reloc_table + on the same section into no-ops. + + Since VMS objects have very few sections, it could be profitable to merge + phase #2 and phase #3, i.e. to decode and internalize the relocs for all + the sections at once. The current implementation is more elegant. */ + +static bfd_boolean +vms_slurp_reloc_table (bfd *abfd, asection *section, asymbol **symbols) +{ + arelent *internal_relocs; + bfd_size_type amt; + int err; + + /* If there were no relocations, there is nothing to do. */ + if (section->reloc_count == 0) + return TRUE; + + /* Return saved information about the relocations if it is available. */ + if (section->relocation != NULL) + return TRUE; + + /* If the relocation stream has not been slurped, do it now. */ + if (vms_section_data (section)->reloc_stream == NULL) + { + bfd_boolean alloc_error = FALSE; + int type; + + /* Size the reloc buffer for each section. */ + bfd_map_over_sections (abfd, alloc_reloc_stream, &alloc_error); + if (alloc_error) + return FALSE; + + if (bfd_seek (abfd, 0, SEEK_SET) != 0) + return FALSE; + + /* Reset section pointer. */ + PRIV (image_section) = NULL; + + do + { + type = _bfd_vms_get_object_record (abfd); + if (type != EOBJ_S_C_ETIR + && type != EOBJ_S_C_EDBG + && type != EOBJ_S_C_ETBT) + continue; + err = _bfd_vms_slurp_relocs (abfd); + if (err != 0) + { +#if VMS_DEBUG + vms_debug (2, "slurp relocs failed with %d\n", err); +#endif + return FALSE; + } + } + while (type != EOBJ_S_C_EEOM); + } + + amt = section->reloc_count * sizeof (arelent); + internal_relocs = (arelent *) bfd_zalloc (abfd, amt); + if (internal_relocs == NULL) + return FALSE; + + /* Decode and internalize the relocations. */ + err = _bfd_vms_decode_relocs (abfd, internal_relocs, section, symbols); + if (err != 0) + { #if VMS_DEBUG - vms_debug (1, "vms_get_reloc_upper_bound (%p, %s)\n", abfd, section->name); + vms_debug (2, "decode relocs failed with %d\n", err); #endif - return -1L; + return FALSE; + } + + /* We're done with the external relocations. Free them. */ + free (vms_section_data (section)->reloc_stream); + vms_section_data (section)->reloc_stream = NULL; + + /* Save our results and return success. */ + section->relocation = internal_relocs; + return TRUE; } -/* Call the back end associated with the open BFD abfd and translate the - external form of the relocation information attached to sec into the - internal canonical form. Place the table into memory at loc, which has - been preallocated, usually by a call to bfd_get_reloc_upper_bound. - Returns the number of relocs, or -1 on error. */ +/* Return the number of bytes required to store the relocation + information associated with the given section. */ static long -vms_canonicalize_reloc (bfd * abfd ATTRIBUTE_UNUSED, - asection *section ATTRIBUTE_UNUSED, - arelent **location ATTRIBUTE_UNUSED, - asymbol **symbols ATTRIBUTE_UNUSED) +vms_get_reloc_upper_bound (bfd *abfd ATTRIBUTE_UNUSED, asection *section) { -#if VMS_DEBUG - vms_debug (1, "vms_canonicalize_reloc (%p, %s, <ret>, <ret>)\n", abfd, section->name); -#endif - return FALSE; + return (section->reloc_count + 1) * sizeof (arelent *); +} + +/* Convert relocations from VMS (external) form into BFD internal + form. Return the number of relocations. */ + +static long +vms_canonicalize_reloc (bfd *abfd, asection *section, arelent **relptr, + asymbol **symbols) +{ + arelent *tblptr; + int count; + + if (! vms_slurp_reloc_table (abfd, section, symbols)) + return -1; + + count = section->reloc_count; + tblptr = section->relocation; + + while (count--) + *relptr++ = tblptr++; + + *relptr = (arelent *) NULL; + return section->reloc_count; } /* This is just copied from ecoff-alpha, needs to be fixed probably. */ @@ -1317,6 +1701,64 @@ static reloc_howto_type alpha_howto_table[] = 0xffffffff, /* Dest mask. */ FALSE), /* PC rel offset. */ + HOWTO (ALPHA_R_NOP, /* Type. */ + 0, /* Rightshift. */ + 3, /* Size (0 = byte, 1 = short, 2 = long). */ + 0, /* Bitsize. */ + /* The following value must match that of ALPHA_R_BSR/ALPHA_R_BOH + because the calculations for the 3 relocations are the same. + See B.4.5.2 of the OpenVMS Linker Utility Manual. */ + TRUE, /* PC relative. */ + 0, /* Bitpos. */ + complain_overflow_dont,/* Complain_on_overflow. */ + reloc_nil, /* Special_function. */ + "NOP", /* Name. */ + FALSE, /* Partial_inplace. */ + 0xffffffff, /* Source mask. */ + 0xffffffff, /* Dest mask. */ + FALSE), /* PC rel offset. */ + + HOWTO (ALPHA_R_BSR, /* Type. */ + 0, /* Rightshift. */ + 3, /* Size (0 = byte, 1 = short, 2 = long). */ + 0, /* Bitsize. */ + TRUE, /* PC relative. */ + 0, /* Bitpos. */ + complain_overflow_dont,/* Complain_on_overflow. */ + reloc_nil, /* Special_function. */ + "BSR", /* Name. */ + FALSE, /* Partial_inplace. */ + 0xffffffff, /* Source mask. */ + 0xffffffff, /* Dest mask. */ + FALSE), /* PC rel offset. */ + + HOWTO (ALPHA_R_LDA, /* Type. */ + 0, /* Rightshift. */ + 3, /* Size (0 = byte, 1 = short, 2 = long). */ + 0, /* Bitsize. */ + FALSE, /* PC relative. */ + 0, /* Bitpos. */ + complain_overflow_dont,/* Complain_on_overflow. */ + reloc_nil, /* Special_function. */ + "LDA", /* Name. */ + FALSE, /* Partial_inplace. */ + 0xffffffff, /* Source mask. */ + 0xffffffff, /* Dest mask. */ + FALSE), /* PC rel offset. */ + + HOWTO (ALPHA_R_BOH, /* Type. */ + 0, /* Rightshift. */ + 3, /* Size (0 = byte, 1 = short, 2 = long, 3 = nil). */ + 0, /* Bitsize. */ + TRUE, /* PC relative. */ + 0, /* Bitpos. */ + complain_overflow_dont,/* Complain_on_overflow. */ + reloc_nil, /* Special_function. */ + "BOH", /* Name. */ + FALSE, /* Partial_inplace. */ + 0xffffffff, /* Source mask. */ + 0xffffffff, /* Dest mask. */ + FALSE), /* PC rel offset. */ }; /* Return a pointer to a howto structure which, when invoked, will perform @@ -1345,6 +1787,10 @@ vms_bfd_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED, case BFD_RELOC_64_PCREL: alpha_type = ALPHA_R_SREL64; break; case BFD_RELOC_ALPHA_LINKAGE: alpha_type = ALPHA_R_LINKAGE; break; case BFD_RELOC_ALPHA_CODEADDR: alpha_type = ALPHA_R_CODEADDR; break; + case BFD_RELOC_ALPHA_NOP: alpha_type = ALPHA_R_NOP; break; + case BFD_RELOC_ALPHA_BSR: alpha_type = ALPHA_R_BSR; break; + case BFD_RELOC_ALPHA_LDA: alpha_type = ALPHA_R_LDA; break; + case BFD_RELOC_ALPHA_BOH: alpha_type = ALPHA_R_BOH; break; default: (*_bfd_error_handler) ("reloc (%d) is *UNKNOWN*", code); return NULL; @@ -1385,14 +1831,18 @@ vms_set_arch_mach (bfd * abfd, #if VMS_DEBUG vms_debug (1, "vms_set_arch_mach (%p, %d, %ld)\n", abfd, arch, mach); #endif - abfd->arch_info = bfd_scan_arch ("alpha"); - return TRUE; + if (arch != bfd_arch_alpha + && arch != bfd_arch_vax + && arch != bfd_arch_unknown) + return FALSE; + + return bfd_default_set_arch_mach (abfd, arch, mach); } /* Sets the contents of the section section in BFD abfd to the data starting - in memory at data. The data is written to the output section starting at - offset offset for count bytes. + in memory at LOCATION. The data is written to the output section starting + at offset offset for count bytes. Normally TRUE is returned, else FALSE. Possible error returns are: o bfd_error_no_contents - The output section does not have the @@ -1411,7 +1861,16 @@ vms_set_section_contents (bfd * abfd, abfd, section->name, location, (long int)offset, (int)count); vms_debug (2, "size %d\n", (int) section->size); #endif - return _bfd_save_vms_section (abfd, section, location, offset, count); + if (count == (bfd_size_type)0) + return TRUE; + + if (section->contents == NULL) + section->contents = bfd_alloc (abfd, section->size); + if (section->contents == NULL) + return FALSE; + + memcpy (section->contents + offset, location, (size_t) count); + return TRUE; } /* Part 4.8, linker. */ @@ -1550,7 +2009,7 @@ vms_get_dynamic_symtab_upper_bound (bfd * abfd ATTRIBUTE_UNUSED) #if VMS_DEBUG vms_debug (1, "vms_get_dynamic_symtab_upper_bound (%p)\n", abfd); #endif - return 0; + return 0L; } static bfd_boolean @@ -1606,14 +2065,14 @@ const bfd_target vms_alpha_vec = BFD_ENDIAN_LITTLE, /* Data byte order is little. */ BFD_ENDIAN_LITTLE, /* Header byte order is little. */ - (HAS_RELOC | HAS_SYMS + (HAS_RELOC | EXEC_P | HAS_LINENO | HAS_DEBUG | HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED), /* Object flags. */ (SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_READONLY | SEC_CODE | SEC_DATA | SEC_HAS_CONTENTS | SEC_IN_MEMORY), /* Sect flags. */ - 0, /* Symbol_leading_char. */ - ' ', /* AR_pad_char. */ - 15, /* AR_max_namelen. */ + 0, /* symbol_leading_char. */ + ' ', /* ar_pad_char. */ + 15, /* ar_max_namelen. */ bfd_getl64, bfd_getl_signed_64, bfd_putl64, bfd_getl32, bfd_getl_signed_32, bfd_putl32, bfd_getl16, bfd_getl_signed_16, bfd_putl16, @@ -1640,7 +2099,7 @@ const bfd_target vms_alpha_vec = NULL, - NULL + (PTR) 0 }; const bfd_target vms_vax_vec = @@ -1657,15 +2116,15 @@ const bfd_target vms_vax_vec = (SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_READONLY | SEC_CODE | SEC_DATA | SEC_HAS_CONTENTS | SEC_IN_MEMORY), /* Sect flags. */ - 0, /* Symbol_leading_char. */ - ' ', /* AR_pad_char. */ - 15, /* AR_max_namelen. */ + 0, /* symbol_leading_char */ + ' ', /* ar_pad_char */ + 15, /* ar_max_namelen */ bfd_getl64, bfd_getl_signed_64, bfd_putl64, bfd_getl32, bfd_getl_signed_32, bfd_putl32, bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* Data. */ bfd_getl64, bfd_getl_signed_64, bfd_putl64, bfd_getl32, bfd_getl_signed_32, bfd_putl32, - bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* Headers. */ + bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* Hdrs. */ {_bfd_dummy_target, vms_object_p, /* bfd_check_format. */ vms_archive_p, _bfd_dummy_target}, @@ -1686,5 +2145,5 @@ const bfd_target vms_vax_vec = NULL, - NULL + (PTR) 0 }; @@ -1,6 +1,8 @@ /* vms.h -- Header file for VMS (Alpha and Vax) support. - Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2005, 2007 - Free Software Foundation, Inc. + Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2005, 2007, + 2008, 2009 Free Software Foundation, Inc. + + Main header file. Written by Klaus K"ampf (kkaempf@rmi.de) @@ -25,9 +27,12 @@ #ifndef VMS_H #define VMS_H -/* Constants starting with 'Exxx_' are for openVMS/Alpha (EVAX object language) */ +/* Constants starting with 'Exxx_' are for openVMS/Alpha (EVAX object + language). */ + +#define VMS_BLOCK_SIZE 512 -/* VMS Text, information and relocation record (TIR/ETIR) definitions. */ +/* VMS Text Information and Relocation Records (TIR/ETIR). */ #define TIR_S_C_STA_GBL 0 #define TIR_S_C_STA_SB 1 @@ -107,7 +112,7 @@ #define ETIR_S_C_STA_GBL 0 /* Stack global symbol value. */ #define ETIR_S_C_STA_LW 1 /* Stack longword. */ #define ETIR_S_C_STA_QW 2 /* Stack quadword. */ -#define ETIR_S_C_STA_PQ 3 /* Stack psect base plus quadword offset. */ +#define ETIR_S_C_STA_PQ 3 /* Stack psect base + quadword off. */ #define ETIR_S_C_STA_LI 4 /* Stack literal. */ #define ETIR_S_C_STA_MOD 5 /* Stack module. */ #define ETIR_S_C_STA_CKARG 6 /* Check Arguments. */ @@ -173,7 +178,9 @@ #define ETIR_S_C_STC_NBH_PS 214 /* Store-conditional NOP,BSR or HINT at psect + offset. */ #define ETIR_S_C_MAXSTCCOD 214 /* Maximum store-conditional code. */ -/* VMS Global symbol definition record (GSD/EGSD). */ +#define ETIR_S_C_HEADER_SIZE 4 /* Size of the header of a command */ + +/* VMS Global Symbol Directory Records (GSD/EGSD). */ #define GSD_S_K_ENTRIES 1 #define GSD_S_C_ENTRIES 1 @@ -206,6 +213,7 @@ #define EGSD_S_C_SYMG 8 /* EGST - gst version of SYM. */ #define EGSD_S_C_MAXRECTYP 8 /* Maximum entry type defined. */ +/* Program Section Definition. */ #define GPS_S_M_PIC 1 #define GPS_S_M_LIB 2 #define GPS_S_M_OVR 4 @@ -219,31 +227,41 @@ #define GPS_S_K_NAME 9 #define GPS_S_C_NAME 9 -#define EGPS_S_V_PIC 0x0001 -#define EGPS_S_V_LIB 0x0002 -#define EGPS_S_V_OVR 0x0004 -#define EGPS_S_V_REL 0x0008 -#define EGPS_S_V_GBL 0x0010 -#define EGPS_S_V_SHR 0x0020 -#define EGPS_S_V_EXE 0x0040 -#define EGPS_S_V_RD 0x0080 -#define EGPS_S_V_WRT 0x0100 -#define EGPS_S_V_VEC 0x0200 -#define EGPS_S_V_NOMOD 0x0400 -#define EGPS_S_V_COM 0x0800 - +#define EGPS_S_B_ALIGN 4 +#define EGPS_S_W_FLAGS 6 +#define EGPS_S_L_ALLOC 8 +#define EGPS_S_B_NAMLNG 12 + +#define EGPS_S_V_PIC 0x0001 +#define EGPS_S_V_LIB 0x0002 +#define EGPS_S_V_OVR 0x0004 +#define EGPS_S_V_REL 0x0008 +#define EGPS_S_V_GBL 0x0010 +#define EGPS_S_V_SHR 0x0020 +#define EGPS_S_V_EXE 0x0040 +#define EGPS_S_V_RD 0x0080 +#define EGPS_S_V_WRT 0x0100 +#define EGPS_S_V_VEC 0x0200 +#define EGPS_S_V_NOMOD 0x0400 +#define EGPS_S_V_COM 0x0800 +#define EGPS_S_V_ALLOC_64BIT 0x1000 + +/* Symbol Defintion or Reference. */ #define GSY_S_M_WEAK 1 #define GSY_S_M_DEF 2 #define GSY_S_M_UNI 4 #define GSY_S_M_REL 8 -#define EGSY_S_V_WEAK 0x0001 -#define EGSY_S_V_DEF 0x0002 -#define EGSY_S_V_UNI 0x0004 -#define EGSY_S_V_REL 0x0008 -#define EGSY_S_V_COMM 0x0010 -#define EGSY_S_V_VECEP 0x0020 -#define EGSY_S_V_NORM 0x0040 +#define EGSY_S_W_FLAGS 6 + +#define EGSY_S_V_WEAK 0x0001 +#define EGSY_S_V_DEF 0x0002 +#define EGSY_S_V_UNI 0x0004 +#define EGSY_S_V_REL 0x0008 +#define EGSY_S_V_COMM 0x0010 +#define EGSY_S_V_VECEP 0x0020 +#define EGSY_S_V_NORM 0x0040 +#define EGSY_S_V_QUAD_VAL 0x0080 #define LSY_S_M_DEF 2 #define LSY_S_M_REL 8 @@ -251,10 +269,26 @@ #define ENV_S_M_DEF 1 #define ENV_S_M_NESTED 2 +/* Symbol Definition. */ +#define ESDF_S_L_VALUE 8 +#define ESDF_S_L_PSINDX 28 +#define ESDF_S_B_NAMLNG 32 + +/* Universal Symbol Definition. */ +#define EGST_S_W_FLAGS 6 +#define EGST_S_Q_LP_1 16 +#define EGST_S_Q_LP_2 24 +#define EGST_S_L_PSINDX 32 +#define EGST_S_B_NAMLNG 36 + +/* Symbol Reference. */ +#define ESRF_S_B_NAMLNG 8 + /* Debugger symbol definitions: These are done by hand, as no machine-readable version seems to be available. */ #define DST_S_C_C 7 /* Language == "C". */ #define DST_S_C_CXX 15 /* Language == "C++". */ +#define DST_S_C_EPILOG 127 #define DST_S_C_VERSION 153 #define DST_S_C_SOURCE 155 /* Source file. */ #define DST_S_C_PROLOG 162 @@ -269,15 +303,19 @@ #define DST_S_C_MODEND 189 /* End of module. */ #define DST_S_C_RTNBEG 190 /* Beginning of routine.*/ #define DST_S_C_RTNEND 191 /* End of routine. */ -#define DST_S_C_DELTA_PC_W 1 /* Incr PC. */ -#define DST_S_C_INCR_LINUM 2 /* Incr Line #. */ -#define DST_S_C_INCR_LINUM_W 3 /* Incr Line #. */ -#define DST_S_C_SET_LINUM_INCR 4 + +/* These are used with DST_S_C_LINE_NUM. */ +#define DST_S_C_LINE_NUM_HEADER_SIZE 4 + +#define DST_S_C_DELTA_PC_W 1 /* Incr PC. */ +#define DST_S_C_INCR_LINUM 2 /* Incr Line #. */ +#define DST_S_C_INCR_LINUM_W 3 /* Incr Line #. */ +#define DST_S_C_SET_LINUM_INCR 4 #define DST_S_C_SET_LINUM_INCR_W 5 #define DST_S_C_RESET_LINUM_INCR 6 -#define DST_S_C_BEG_STMT_MODE 7 -#define DST_S_C_END_STMT_MODE 8 -#define DST_S_C_SET_LINE_NUM 9 /* Set Line #. */ +#define DST_S_C_BEG_STMT_MODE 7 +#define DST_S_C_END_STMT_MODE 8 +#define DST_S_C_SET_LINE_NUM 9 /* Set Line #. */ #define DST_S_C_SET_PC 10 #define DST_S_C_SET_PC_W 11 #define DST_S_C_SET_PC_L 12 @@ -295,9 +333,32 @@ #define DST_S_C_SRC_SETFILE 2 /* Set source file. */ #define DST_S_C_SRC_SETREC_L 3 /* Set record, longword value. */ #define DST_S_C_SRC_SETREC_W 4 /* Set record, word value. */ +#define DST_S_C_SRC_SETLNUM_L 5 /* Set line, longword value. */ +#define DST_S_C_SRC_SETLNUM_W 6 /* Set line, word value. */ +#define DST_S_C_SRC_INCRLNUM_B 7 /* Increment line. */ #define DST_S_C_SRC_DEFLINES_W 10 /* # of line, word counter. */ #define DST_S_C_SRC_DEFLINES_B 11 /* # of line, byte counter. */ #define DST_S_C_SRC_FORMFEED 16 /* ^L counts as a record. */ + +#define DST_S_B_PCLINE_UNSBYTE 1 +#define DST_S_W_PCLINE_UNSWORD 1 +#define DST_S_L_PCLINE_UNSLONG 1 + +#define DST_S_B_MODBEG_NAME 14 +#define DST_S_L_RTNBEG_ADDRESS 5 +#define DST_S_B_RTNBEG_NAME 13 +#define DST_S_L_RTNEND_SIZE 5 + +/* These are used with DST_S_C_SOURCE. */ +#define DST_S_C_SOURCE_HEADER_SIZE 4 + +#define DST_S_B_SRC_DF_LENGTH 1 +#define DST_S_W_SRC_DF_FILEID 3 +#define DST_S_B_SRC_DF_FILENAME 20 +#define DST_S_B_SRC_UNSBYTE 1 +#define DST_S_W_SRC_UNSWORD 1 +#define DST_S_L_SRC_UNSLONG 1 + /* The following are the codes for the various data types. Anything not on the list is included under 'advanced_type'. */ #define DBG_S_C_UCHAR 0x02 @@ -328,6 +389,7 @@ #define DSC_K_CLASS_D 0x02 /* Dynamic string (not via malloc!). */ #define DSC_K_CLASS_A 0x04 /* Array. */ #define DSC_K_CLASS_UBS 0x0d /* Unaligned bit string. */ + /* These are the codes that are used to generate the definitions of struct union and enum records. */ #define DBG_S_C_ENUM_ITEM 0xa4 @@ -336,7 +398,7 @@ #define DBG_S_C_STRUCT_ITEM DST_K_VFLAGS_BITOFFS /* 0xff */ #define DBG_S_C_STRUCT_START 0xab #define DBG_S_C_STRUCT_END 0xac -#define DST_K_TYPSPEC 0xaf /* Type specification. */ +#define DST_K_TYPSPEC 0xaf /* Type specification. */ /* These codes are used in the generation of the symbol definition records. */ #define DST_K_VFLAGS_NOVAL 0x80 /* Struct definition only. */ #define DST_K_VFLAGS_DSC 0xfa /* Descriptor used. */ @@ -379,7 +441,7 @@ #define DBG_S_C_VOID DST_K_TS_PTR #define DBG_S_C_COMPLEX_ARRAY DST_K_TS_ARRAY -/* VMS Module header record (EMH) definitions. */ +/* VMS Module Header Records (MHD/EMH). */ #define MHD_S_C_MHD 0 #define MHD_S_C_LNM 1 @@ -402,48 +464,68 @@ /* vms.c. */ extern asymbol *_bfd_vms_make_empty_symbol (bfd *); +extern int _bfd_vms_slurp_object_records (bfd *abfd); /* vms-gsd.c. */ -extern int _bfd_vms_slurp_gsd (bfd *, int); -extern int _bfd_vms_write_gsd (bfd *, int); +extern int _bfd_vms_slurp_gsd (bfd *abfd, int objtype); +extern int _bfd_vms_write_gsd (bfd *abfd, int objtype); +extern int _bfd_vms_slurp_dbg (bfd *abfd, int objtype); +extern int _bfd_vms_write_dbg (bfd *abfd, int objtype); +extern int _bfd_vms_slurp_tbt (bfd *abfd, int objtype); +extern int _bfd_vms_write_tbt (bfd *abfd, int objtype); -/* vms-mhd.c. */ +/* vms-misc.c. */ -extern int _bfd_vms_slurp_hdr (bfd *, int); -extern int _bfd_vms_write_hdr (bfd *, int); -extern int _bfd_vms_slurp_eom (bfd *, int); -extern int _bfd_vms_write_eom (bfd *, int); +extern int _bfd_vms_get_object_record (bfd *abfd); +extern int _bfd_vms_get_first_record (bfd *abfd); + +/* vms-hdr.c. */ + +extern int _bfd_vms_slurp_hdr (bfd *abfd, int objtype); +extern int _bfd_vms_write_hdr (bfd *abfd, int objtype); +extern int _bfd_vms_slurp_eom (bfd *abfd, int objtype); +extern int _bfd_vms_write_eom (bfd *abfd, int objtype); +extern bfd_boolean _bfd_vms_find_nearest_dst_line + (bfd *abfd, asection *section, asymbol **symbols, bfd_vma offset, + const char **file, const char **func, unsigned int *line); +extern int _bfd_vms_slurp_ihd + (bfd *abfd, unsigned int *isd_offset, unsigned int *ihs_offset); +extern int _bfd_vms_slurp_isd (bfd *abfd, unsigned int offset); +extern int _bfd_vms_slurp_ihs (bfd *abfd, unsigned int offset); /* vms-tir.c. */ -extern int _bfd_vms_slurp_tir (bfd *, int); -extern int _bfd_vms_slurp_dbg (bfd *, int); -extern int _bfd_vms_slurp_tbt (bfd *, int); -extern int _bfd_vms_slurp_lnk (bfd *, int); - -extern int _bfd_vms_write_tir (bfd *, int); -extern int _bfd_vms_write_tbt (bfd *, int); -extern int _bfd_vms_write_dbg (bfd *, int); - -/* The r_type field in a reloc is one of he following values. */ -#define ALPHA_R_IGNORE 0 -#define ALPHA_R_REFQUAD 1 -#define ALPHA_R_BRADDR 2 -#define ALPHA_R_HINT 3 -#define ALPHA_R_SREL16 4 -#define ALPHA_R_SREL32 5 -#define ALPHA_R_SREL64 6 -#define ALPHA_R_OP_PUSH 7 -#define ALPHA_R_OP_STORE 8 -#define ALPHA_R_OP_PSUB 9 -#define ALPHA_R_OP_PRSHIFT 10 -#define ALPHA_R_LINKAGE 11 -#define ALPHA_R_REFLONG 12 -#define ALPHA_R_CODEADDR 13 - -/* Object language definitions. */ - +extern int _bfd_vms_slurp_tir (bfd *abfd, int objtype); +extern int _bfd_vms_write_tir (bfd *abfd, int objtype); +extern int _bfd_vms_slurp_lnk (bfd *abfd, int objtype); + +extern int _bfd_vms_slurp_relocs (bfd *abfd); +extern int _bfd_vms_decode_relocs + (bfd *abfd, arelent *relocs, asection *section, asymbol **symbols); + +/* The r_type field in a reloc is one of the following values. */ +#define ALPHA_R_IGNORE 0 +#define ALPHA_R_REFQUAD 1 +#define ALPHA_R_BRADDR 2 +#define ALPHA_R_HINT 3 +#define ALPHA_R_SREL16 4 +#define ALPHA_R_SREL32 5 +#define ALPHA_R_SREL64 6 +#define ALPHA_R_OP_PUSH 7 +#define ALPHA_R_OP_STORE 8 +#define ALPHA_R_OP_PSUB 9 +#define ALPHA_R_OP_PRSHIFT 10 +#define ALPHA_R_LINKAGE 11 +#define ALPHA_R_REFLONG 12 +#define ALPHA_R_CODEADDR 13 +#define ALPHA_R_NOP 14 +#define ALPHA_R_BSR 15 +#define ALPHA_R_LDA 16 +#define ALPHA_R_BOH 17 + +/* VMS Object Language (OBJ/EOBJ). */ + #define OBJ_S_C_HDR 0 /* VAX moule header record. */ #define OBJ_S_C_GSD 1 /* VAX glbal symbol definition record. */ #define OBJ_S_C_TIR 2 /* VAX tet information record. */ @@ -453,13 +535,15 @@ extern int _bfd_vms_write_dbg (bfd *, int); #define OBJ_S_C_LNK 6 /* VAX liker options record. */ #define OBJ_S_C_EOMW 7 /* VAX en of module word-psect record. */ #define OBJ_S_C_MAXRECTYP 7 /* VAX Lat assigned record type. */ + #define EOBJ_S_C_EMH 8 /* EVAX mdule header record. */ #define EOBJ_S_C_EEOM 9 /* EVAX ed of module record. */ -#define EOBJ_S_C_EGSD 10 /* EVAX gobal symbol definition record.*/ -#define EOBJ_S_C_ETIR 11 /* EVAX txt information record. */ +#define EOBJ_S_C_EGSD 10 /* EVAX gobal symbol definition record. */ +#define EOBJ_S_C_ETIR 11 /* EVAX txt information record. */ #define EOBJ_S_C_EDBG 12 /* EVAX Dbugger information record. */ #define EOBJ_S_C_ETBT 13 /* EVAX Taceback information record. */ #define EOBJ_S_C_MAXRECTYP 13 /* EVAX Lst assigned record type. */ + #define OBJ_S_K_SUBTYP 1 #define OBJ_S_C_SUBTYP 1 #define EOBJ_S_K_SUBTYP 4 @@ -475,8 +559,9 @@ extern int _bfd_vms_write_dbg (bfd *, int); #define EOBJ_S_C_STOREPLIM -1 /* Maximu repeat count on store commands. */ #define OBJ_S_C_PSCALILIM 9 /* Maximu p-sect alignment. */ #define EOBJ_S_C_PSCALILIM 16 /* Maximu p-sect alignment. */ - + #define EVAX_OFFSET 256 /* Type ofset for EVAX codes in switch. */ + /* Miscellaneous definitions. */ #if __GNUC__ @@ -484,140 +569,286 @@ typedef unsigned long long uquad; #else typedef unsigned long uquad; #endif - -#define MAX_OUTREC_SIZE 4096 -#define MIN_OUTREC_LUFT 64 - -typedef struct _vms_section -{ - unsigned char *contents; - bfd_vma offset; - bfd_size_type size; - struct _vms_section *next; -} vms_section; - -extern vms_section * _bfd_get_vms_section (bfd *, int); - -typedef struct _vms_reloc -{ - struct _vms_reloc *next; - arelent *reloc; - asection *section; -} vms_reloc; - + +#define MAX_OUTREC_SIZE 4096 +#define MIN_OUTREC_LUFT 64 + /* VMS module header. */ - -struct hdr_struc -{ - int hdr_b_strlvl; - long hdr_l_arch1; - long hdr_l_arch2; - long hdr_l_recsiz; - char * hdr_t_name; - char * hdr_t_version; - char * hdr_t_date; - char * hdr_c_lnm; - char * hdr_c_src; - char * hdr_c_ttl; -}; - -/* VMS end of module. */ - -struct eom_struc -{ - long eom_l_total_lps; - unsigned char eom_b_comcod; - bfd_boolean eom_has_transfer; - unsigned char eom_b_tfrflg; - long eom_l_psindx; - long eom_l_tfradr; -}; - -enum file_format_enum { FF_UNKNOWN, FF_FOREIGN, FF_NATIVE, FF_VAX }; - -typedef struct vms_symbol_struct -{ - struct bfd_hash_entry bfd_hash; - asymbol *symbol; -} vms_symbol_entry; - + +struct hdr_struct +{ + char hdr_b_strlvl; + int hdr_l_arch1; + int hdr_l_arch2; + int hdr_l_recsiz; + char *hdr_t_name; + char *hdr_t_version; + char *hdr_t_date; + char *hdr_c_lnm; + char *hdr_c_src; + char *hdr_c_ttl; + char *hdr_c_cpr; +}; + +#define EMH_S_W_HDRTYP 4 +#define EMH_S_B_STRLVL 6 +#define EMH_S_L_ARCH1 8 +#define EMH_S_L_ARCH2 12 +#define EH_S_L_RECSIZ 16 +#define EMH_S_B_NAMLNG 20 + +#define EMH_DATE_LENGTH 17 + +/* VMS End-Of-Module records (EOM/EEOM). */ + +struct eom_struct +{ + int eom_l_total_lps; + short eom_w_comcod; + bfd_boolean eom_has_transfer; + char eom_b_tfrflg; + int eom_l_psindx; + int eom_l_tfradr; +}; + +#define EEOM_S_L_TOTAL_LPS 4 +#define EEOM_S_W_COMCOD 8 +#define EEOM_S_B_TFRFLG 10 +#define EEOM_S_L_PSINDX 12 +#define EEOM_S_L_TFRADR 16 + +/* VMS Image Header Records (IHD/EIHD). */ + +#define EIHD_S_K_MAJORID 3 /* Major id constant */ +#define EIHD_S_K_MINORID 0 /* Minor id constant */ +#define EIHD_S_K_EXE 1 /* Executable image */ + +#define EIHD_S_L_SIZE 8 +#define EIHD_S_L_ISDOFF 12 +#define EIHD_S_L_SYMDBGOFF 20 +#define EIHD_S_Q_SYMVVA 40 +#define EIHD_S_L_IMGTYPE 52 + +/* VMS Image Section Description Records (ISD/EISD). */ + +#define EISD_S_L_EISDSIZE 8 +#define EISD_S_L_SECSIZE 12 +#define EISD_S_Q_VIR_ADDR 16 +#define EISD_S_L_FLAGS 24 +#define EISD_S_L_VBN 28 +#define EISD_S_R_CONTROL 32 +#define EISD_S_L_IDENT 36 +#define EISD_S_T_GBLNAM 40 + +#define EISD_S_M_GBL 0x0001 +#define EISD_S_M_CRF 0x0002 +#define EISD_S_M_DZRO 0x0004 +#define EISD_S_M_WRT 0x0008 +#define EISD_S_M_INITALCODE 0x0010 +#define EISD_S_M_BASED 0x0020 +#define EISD_S_M_FIXUPVEC 0x0040 +#define EISD_S_M_RESIDENT 0x0080 +#define EISD_S_M_VECTOR 0x0100 +#define EISD_S_M_PROTECT 0x0200 +#define EISD_S_M_LASTCLU 0x0400 +#define EISD_S_M_EXE 0x0800 +#define EISD_S_M_NONSHRADR 0x1000 +#define EISD_S_M_QUAD_LENGTH 0x2000 +#define EISD_S_M_ALLOC_64BIT 0x4000 + +/* VMS Image Header Symbol Records (IHS/EIHS). */ + +#define EIHS_S_L_DSTVBN 8 +#define EIHS_S_L_DSTSIZE 12 +#define EIHS_S_L_GSTVBN 16 +#define EIHS_S_L_GSTSIZE 20 +#define EIHS_S_L_DMTVBN 24 +#define EIHS_S_L_DMTBYTES 28 + +/* Debugger symbol definitions. */ + +#define DBG_S_L_DMT_MODBEG 0 +#define DBG_S_L_DST_SIZE 4 +#define DBG_S_W_DMT_PSECT_COUNT 8 +#define DBG_S_C_DMT_HEADER_SIZE 12 + +#define DBG_S_L_DMT_PSECT_START 0 +#define DBG_S_L_DMT_PSECT_LENGTH 4 +#define DBG_S_C_DMT_PSECT_SIZE 8 + + +enum file_format_enum { FF_UNKNOWN, FF_FOREIGN, FF_NATIVE }; +enum file_type_enum { FT_UNKNOWN, FT_MODULE, FT_IMAGE }; + +typedef struct vms_symbol_struct +{ + struct bfd_hash_entry bfd_hash; + asymbol *symbol; +} vms_symbol_entry; + /* Stack value for push/pop commands. */ - -struct stack_struct -{ - uquad value; - int psect; -}; -#define STACKSIZE 8192 - -/* location stack definitions for CTL_DFLC, CTL_STLOC, and CTL_STKDL */ - -struct location_struct -{ - unsigned long value; - int psect; -}; -#define LOCATION_SAVE_SIZE 32 - -#define VMS_SECTION_COUNT 1024 - -struct vms_private_data_struct -{ - bfd_boolean is_vax; + +struct stack_struct +{ + uquad value; + int psect; +}; + +#define STACKSIZE 8192 + +/* A minimal decoding of DST compilation units. We only decode + what's needed to get to the line number information. */ + +struct fileinfo +{ + char *name; + unsigned int srec; +}; + +struct srecinfo +{ + struct srecinfo *next; + unsigned int line; + unsigned int sfile; + unsigned int srec; +}; + +struct lineinfo +{ + struct lineinfo *next; + bfd_vma address; + unsigned int line; +}; + +struct funcinfo +{ + struct funcinfo *next; + char *name; + bfd_vma low; + bfd_vma high; +}; + +struct module +{ + /* Chain the previously read compilation unit. */ + struct module *next; + + /* The module name. */ + char *name; + + /* The start offset and size of debug info in the DST section. */ + unsigned int modbeg; + unsigned int size; + + /* The lowest and highest addresses contained in this compilation + unit as specified in the compilation unit header. */ + bfd_vma low; + bfd_vma high; + + /* The listing line table. */ + struct lineinfo *line_table; + + /* The source record table. */ + struct srecinfo *srec_table; + + /* A list of the functions found in this module. */ + struct funcinfo *func_table; + + /* Current allocation of file_table. */ + unsigned int file_table_count; + + /* An array of the files making up this module. */ + struct fileinfo *file_table; +}; + +struct vms_private_data_struct +{ + bfd_boolean is_vax; bfd_boolean fixup_done; /* Flag to indicate if all section pointers and PRIV(sections) are set up correctly. */ - unsigned char *vms_buf; /* Buffer to record. */ - int buf_size; /* Max size of buffer. */ - unsigned char *vms_rec; /* Actual record ptr. */ - int rec_length; /* Remaining record length. */ - int rec_size; /* Actual record size. */ - int rec_type; /* Actual record type. */ - enum file_format_enum file_format; - - struct hdr_struc hdr_data; /* Data from HDR/EMH record. */ - struct eom_struc eom_data; /* Data from EOM/EEOM record. */ - unsigned int section_count; /* # of sections in following array. */ - asection **sections; /* Array of GSD/EGSD sections. */ - int gsd_sym_count; /* # of GSD/EGSD symbols. */ - asymbol **symbols; /* Vector of GSD/EGSD symbols. */ - struct proc_value *procedure; - - struct stack_struct *stack; - int stackptr; - - vms_section *vms_section_table[VMS_SECTION_COUNT]; - + unsigned char *vms_buf; /* record buffer */ + unsigned int buf_size; /* size of record buffer */ + unsigned char *vms_rec; /* record pointer in record buffer */ + unsigned int rec_size; /* record size */ + enum file_format_enum file_format; + + struct hdr_struct hdr_data; /* data from HDR/EMH record */ + struct eom_struct eom_data; /* data from EOM/EEOM record */ + unsigned int section_count; /* # of sections in following array */ + asection **sections; /* array of GSD/EGSD sections */ + unsigned int gsd_sym_count; /* # of GSD/EGSD symbols */ + asymbol **symbols; /* vector of GSD/EGSD symbols */ + struct proc_value *procedure; + + struct stack_struct *stack; + int stackptr; + struct bfd_hash_table *vms_symbol_table; - struct bfd_symbol **symcache; - int symnum; - - struct location_struct *location_stack; - - asection *image_section; /* Section for image_ptr. */ - unsigned char *image_ptr; /* A pointer to section->contents. */ - - unsigned char pdsc[8]; /* Procedure descriptor. */ - - /* Output routine storage. */ - unsigned char *output_buf; /* Output data. */ - int push_level; - int pushed_size; - int length_pos; - int output_size; - int output_alignment; - - /* Linkage index counter - used by conditional store commands (TIR_S_C_STC_). */ - int vms_linkage_index; - - /* see tc-alpha.c of gas for a descripton. */ - int flag_hash_long_names; /* -+, hash instead of truncate. */ - int flag_show_after_trunc; /* -H, shw hashing/truncation. */ -}; - -#define PRIV(name) ((struct vms_private_data_struct *) abfd->tdata.any)->name - + struct bfd_symbol **symcache; + int symnum; + + asection *image_section; /* section for image_ptr */ + unsigned char *image_ptr; /* a pointer to section->contents */ + + unsigned char pdsc[8]; /* procedure descriptor */ + + struct module *modules; /* list of all compilation units */ + + struct dst_info *dst_info; + asection *dst_section; + unsigned char *dst_ptr_end; + unsigned int dst_ptr_offsets_count; /* # of offsets in following array */ + unsigned int *dst_ptr_offsets; /* array of saved image_ptr offsets */ + + /* Shared library support */ + bfd_vma symvva; /* relative virtual address of symbol vector */ + + /* Output routine storage */ + unsigned char *output_buf; /* output data */ + int push_level; + int pushed_size; + int length_pos; + int output_size; + int output_alignment; + + /* linkage index counter used by conditional store commands */ + int vms_linkage_index; + + /* see tc-alpha.c of gas for a description. */ + int flag_hash_long_names; /* -+, hash instead of truncate */ + int flag_show_after_trunc; /* -H, show hashing/truncation */ +}; + +#define PRIV(name) ((struct vms_private_data_struct *)abfd->tdata.any)->name + +/* Used to keep extra VMS specific information for a given section. + + reloc_size holds the size of the relocation stream, note this + is very different from the number of relocations as VMS relocations + are variable length. + + reloc_stream is the actual stream of relocation entries. */ + +struct vms_section_data_struct +{ + bfd_size_type reloc_size; + unsigned char *reloc_stream; + bfd_size_type reloc_offset; + flagword vflags; +}; + +#define vms_section_data(sec) \ + ((struct vms_section_data_struct *)sec->used_by_bfd) + +struct evax_private_udata_struct +{ + asymbol *bsym; + asymbol *enbsym; + char *origname; + int lkindex; +}; + #define SECTION_NAME_TEMPLATE "__SEC__%d" #if VMS_DEBUG @@ -635,7 +866,6 @@ extern char * _bfd_vms_save_sized_string (unsigned char *, int); extern char * _bfd_vms_save_counted_string (unsigned char *); extern void _bfd_vms_push (bfd *, uquad, int); extern uquad _bfd_vms_pop (bfd *, int *); -extern bfd_boolean _bfd_save_vms_section (bfd *, asection *, const void *, file_ptr, bfd_size_type); extern void _bfd_vms_output_begin (bfd *, int, int); extern void _bfd_vms_output_alignment (bfd *, int); extern void _bfd_vms_output_push (bfd *); @@ -653,4 +883,7 @@ extern void _bfd_vms_output_fill (bfd *, int, int); extern char * _bfd_vms_length_hash_symbol (bfd *, const char *, int); extern vms_symbol_entry * _bfd_vms_enter_symbol (bfd *, char *); +#define EGPS_S_V_NO_SHIFT 16 + +extern void bfd_vms_set_section_flags (bfd *, asection *, flagword); #endif /* VMS_H */ |